@@ -236,12 +236,65 @@ private ImmutableArray<StatementNode> RewriteStatements(ImmutableArray<Statement
236236 continue ;
237237 }
238238
239+ if ( _rewriteAwaits && TryRewriteNestedAwaitLoopBody ( statement , out var rewrittenLoopStatement ) )
240+ {
241+ builder . Add ( rewrittenLoopStatement ) ;
242+ changed = true ;
243+ continue ;
244+ }
245+
239246 builder . Add ( statement ) ;
240247 }
241248
242249 return changed ? builder . ToImmutable ( ) : statements ;
243250 }
244251
252+ private bool TryRewriteNestedAwaitLoopBody (
253+ StatementNode statement ,
254+ out StatementNode rewrittenStatement )
255+ {
256+ rewrittenStatement = statement ;
257+
258+ switch ( statement )
259+ {
260+ case ForStatement { Body : BlockStatement forBody } forStatement :
261+ {
262+ var rewrittenBody = RewriteBlock ( forBody ) ;
263+ if ( ReferenceEquals ( rewrittenBody , forBody ) )
264+ {
265+ return false ;
266+ }
267+
268+ rewrittenStatement = forStatement with { Body = rewrittenBody } ;
269+ return true ;
270+ }
271+ case WhileStatement { Body : BlockStatement whileBody } whileStatement :
272+ {
273+ var rewrittenBody = RewriteBlock ( whileBody ) ;
274+ if ( ReferenceEquals ( rewrittenBody , whileBody ) )
275+ {
276+ return false ;
277+ }
278+
279+ rewrittenStatement = whileStatement with { Body = rewrittenBody } ;
280+ return true ;
281+ }
282+ case DoWhileStatement { Body : BlockStatement doWhileBody } doWhileStatement :
283+ {
284+ var rewrittenBody = RewriteBlock ( doWhileBody ) ;
285+ if ( ReferenceEquals ( rewrittenBody , doWhileBody ) )
286+ {
287+ return false ;
288+ }
289+
290+ rewrittenStatement = doWhileStatement with { Body = rewrittenBody } ;
291+ return true ;
292+ }
293+ default :
294+ return false ;
295+ }
296+ }
297+
245298 private bool TryRewriteNestedAwaitStatement (
246299 StatementNode statement ,
247300 bool isStrict ,
@@ -624,6 +677,14 @@ private bool TryRewriteExpressionWithNestedAwait(
624677 return false ;
625678 }
626679
680+ if ( TryRewriteBinaryExpressionWithNestedAwait (
681+ expression ,
682+ out prefixStatements ,
683+ out rewrittenExpression ) )
684+ {
685+ return true ;
686+ }
687+
627688 if ( TryRewriteComputedMemberAwaitProperty (
628689 expression ,
629690 out prefixStatements ,
@@ -632,6 +693,15 @@ private bool TryRewriteExpressionWithNestedAwait(
632693 return true ;
633694 }
634695
696+ if ( expression is BinaryExpression binaryExpression &&
697+ TryRewriteBinaryExpressionWithNestedAwait (
698+ binaryExpression ,
699+ out prefixStatements ,
700+ out rewrittenExpression ) )
701+ {
702+ return true ;
703+ }
704+
635705 var tempBinding = CreateResumeIdentifier ( ) ;
636706 var replacement = new IdentifierExpression ( expression . Source , tempBinding . Name ) ;
637707 if ( ! TryExtractLeadingAwait ( expression , replacement , out var awaitedExpression , out rewrittenExpression ) )
@@ -649,6 +719,145 @@ [new VariableDeclarator(awaitedExpression.Source, tempBinding, awaitedExpression
649719 return true ;
650720 }
651721
722+ private bool TryRewriteBinaryExpressionWithNestedAwait (
723+ BinaryExpression binaryExpression ,
724+ out ImmutableArray < StatementNode > prefixStatements ,
725+ out ExpressionNode rewrittenExpression )
726+ {
727+ prefixStatements = default ;
728+ rewrittenExpression = binaryExpression ;
729+
730+ var leftHasAwait = AstShapeAnalyzer . ContainsAwait ( binaryExpression . Left ) ;
731+ var rightHasAwait = AstShapeAnalyzer . ContainsAwait ( binaryExpression . Right ) ;
732+ if ( ! leftHasAwait && ! rightHasAwait )
733+ {
734+ return false ;
735+ }
736+
737+ var builder = ImmutableArray . CreateBuilder < StatementNode > ( ) ;
738+ var rewrittenLeft = binaryExpression . Left ;
739+ var rewrittenRight = binaryExpression . Right ;
740+ var changed = false ;
741+
742+ if ( leftHasAwait )
743+ {
744+ if ( binaryExpression . Left is AwaitExpression leftAwait )
745+ {
746+ var leftBinding = CreateResumeIdentifier ( ) ;
747+ builder . Add ( CreateTempDeclaration ( leftAwait . Source , leftBinding , leftAwait ) ) ;
748+ rewrittenLeft = new IdentifierExpression ( leftAwait . Source , leftBinding . Name ) ;
749+ changed = true ;
750+ }
751+ else if ( TryRewriteExpressionWithNestedAwait (
752+ binaryExpression . Left ,
753+ out var leftPrefixStatements ,
754+ out var rewrittenLeftExpression ) )
755+ {
756+ builder . AddRange ( leftPrefixStatements ) ;
757+ rewrittenLeft = rewrittenLeftExpression ;
758+ changed = true ;
759+ }
760+ else
761+ {
762+ return false ;
763+ }
764+ }
765+
766+ if ( rightHasAwait )
767+ {
768+ if ( ! leftHasAwait )
769+ {
770+ var leftBinding = CreateResumeIdentifier ( ) ;
771+ builder . Add ( CreateTempDeclaration ( binaryExpression . Left . Source , leftBinding , rewrittenLeft ) ) ;
772+ rewrittenLeft = new IdentifierExpression ( binaryExpression . Left . Source , leftBinding . Name ) ;
773+ changed = true ;
774+ }
775+
776+ if ( binaryExpression . Right is AwaitExpression rightAwait )
777+ {
778+ var rightBinding = CreateResumeIdentifier ( ) ;
779+ builder . Add ( CreateTempDeclaration ( rightAwait . Source , rightBinding , rightAwait ) ) ;
780+ rewrittenRight = new IdentifierExpression ( rightAwait . Source , rightBinding . Name ) ;
781+ changed = true ;
782+ }
783+ else if ( TryRewriteExpressionWithNestedAwait (
784+ binaryExpression . Right ,
785+ out var rightPrefixStatements ,
786+ out var rewrittenRightExpression ) )
787+ {
788+ builder . AddRange ( rightPrefixStatements ) ;
789+ rewrittenRight = rewrittenRightExpression ;
790+ changed = true ;
791+ }
792+ else
793+ {
794+ return false ;
795+ }
796+ }
797+
798+ if ( ! changed )
799+ {
800+ return false ;
801+ }
802+
803+ prefixStatements = builder . ToImmutable ( ) ;
804+ rewrittenExpression = binaryExpression with
805+ {
806+ Left = rewrittenLeft ,
807+ Right = rewrittenRight
808+ } ;
809+ return true ;
810+ }
811+
812+ private bool TryRewriteBinaryExpressionWithNestedAwait (
813+ ExpressionNode expression ,
814+ out ImmutableArray < StatementNode > prefixStatements ,
815+ out ExpressionNode rewrittenExpression )
816+ {
817+ prefixStatements = default ;
818+ rewrittenExpression = expression ;
819+
820+ if ( expression is not BinaryExpression binaryExpression ||
821+ binaryExpression . Operator is BinaryOperator . LogicalAnd or BinaryOperator . LogicalOr or
822+ BinaryOperator . NullishCoalescing )
823+ {
824+ return false ;
825+ }
826+
827+ var builder = ImmutableArray . CreateBuilder < StatementNode > ( ) ;
828+ var changed = false ;
829+ var rewrittenLeft = binaryExpression . Left ;
830+ var rewrittenRight = binaryExpression . Right ;
831+
832+ if ( AstShapeAnalyzer . ContainsAwait ( rewrittenLeft ) )
833+ {
834+ rewrittenLeft = RewriteAwaitExpressionToSyntheticIdentifier ( rewrittenLeft , builder ) ;
835+ changed = true ;
836+ }
837+
838+ if ( AstShapeAnalyzer . ContainsAwait ( rewrittenRight ) )
839+ {
840+ var capturedLeft = CreateResumeIdentifier ( ) ;
841+ builder . Add ( CreateTempDeclaration ( binaryExpression . Left . Source , capturedLeft , rewrittenLeft ) ) ;
842+ rewrittenLeft = new IdentifierExpression ( binaryExpression . Left . Source , capturedLeft . Name ) ;
843+ rewrittenRight = RewriteAwaitExpressionToSyntheticIdentifier ( rewrittenRight , builder ) ;
844+ changed = true ;
845+ }
846+
847+ if ( ! changed )
848+ {
849+ return false ;
850+ }
851+
852+ prefixStatements = builder . ToImmutable ( ) ;
853+ rewrittenExpression = binaryExpression with
854+ {
855+ Left = rewrittenLeft ,
856+ Right = rewrittenRight
857+ } ;
858+ return true ;
859+ }
860+
652861 private bool TryRewriteComputedMemberAwaitProperty (
653862 ExpressionNode expression ,
654863 out ImmutableArray < StatementNode > prefixStatements ,
0 commit comments