Skip to content

Commit b90b0e7

Browse files
authored
fix: restore async await lowering on main (#727)
Closes #721
1 parent d211d37 commit b90b0e7

File tree

3 files changed

+298
-18
lines changed

3 files changed

+298
-18
lines changed

src/Asynkron.JsEngine/Execution/GeneratorYieldLowerer.cs

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)