Skip to content

Commit cdfb411

Browse files
authored
Fix generator loop closure resumes (#644)
* Fix generator loop closure resumes * Fix PR review generator callback edge cases - Preserve active match scopes across yielded for-of bodies.\n- Route var destructuring through the iteration context.\n- Isolate reduce and sort array callbacks from parent generator replay state. * Preserve for-await generator loop scopes - Restore saved iteration and match scopes when async generator for-await bodies resume.\n- Skip match-scope release while unwinding body yields.\n- Cover async iterator and sync fallback for-await paths.
1 parent c93a49c commit cdfb411

10 files changed

Lines changed: 541 additions & 179 deletions

source/units/Goccia.AST.Statements.pas

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ implementation
483483
Goccia.Evaluator,
484484
Goccia.GarbageCollector,
485485
Goccia.Modules,
486+
Goccia.Runtime.GeneratorContinuation,
486487
Goccia.Scope,
487488
Goccia.Scope.BindingMap,
488489
Goccia.Token,
@@ -859,14 +860,35 @@ function CreateModuleNamespaceObject(const AModule: TGocciaModule): TGocciaValue
859860
Value: TGocciaValue;
860861
HasRealStrictInit: Boolean;
861862
AnnotationType, TypeHint: TGocciaLocalType;
863+
Continuation: TGocciaGeneratorContinuation;
862864
begin
863865
Result := TGocciaControlFlow.Normal(TGocciaUndefinedLiteralValue.UndefinedValue);
864866
// Function declarations are no-ops at runtime — already hoisted with their value
865867
if IsFunctionDeclaration then
866868
Exit;
867-
for I := 0 to Length(Variables) - 1 do
869+
Continuation := CurrentGeneratorContinuation;
870+
if Assigned(Continuation) then
871+
I := Continuation.GetStatementIndex(Self)
872+
else
873+
I := 0;
874+
while I < Length(Variables) do
868875
begin
869-
Value := EvaluateExpression(Variables[I].Initializer, AContext);
876+
try
877+
Value := EvaluateExpression(Variables[I].Initializer, AContext);
878+
except
879+
on E: EGocciaGeneratorYield do
880+
begin
881+
if Assigned(Continuation) then
882+
Continuation.SaveStatementIndex(Self, I);
883+
raise;
884+
end;
885+
else
886+
begin
887+
if Assigned(Continuation) then
888+
Continuation.ClearStatementIndex(Self);
889+
raise;
890+
end;
891+
end;
870892
if (Value is TGocciaFunctionValue) and (TGocciaFunctionValue(Value).Name = '') then
871893
TGocciaFunctionValue(Value).Name := Variables[I].Name
872894
else if Value is TGocciaClassValue then
@@ -919,7 +941,12 @@ function CreateModuleNamespaceObject(const AModule: TGocciaModule): TGocciaValue
919941
else
920942
AContext.Scope.SetOwnBindingTypeHint(Variables[I].Name, TypeHint);
921943
end;
944+
if Assigned(Continuation) then
945+
Continuation.SaveStatementIndex(Self, I + 1);
946+
Inc(I);
922947
end;
948+
if Assigned(Continuation) then
949+
Continuation.ClearStatementIndex(Self);
923950
end;
924951

925952
function TGocciaDestructuringDeclaration.Execute(const AContext: TGocciaEvaluationContext): TGocciaControlFlow;

0 commit comments

Comments
 (0)