commit 93b53376966526c2ce560d98052ce3ab292e9093
parent a2644e7e4a7e2f1566cf42a06d14c31c6829b878
Author: Tooru Fujisawa <arai_a@mac.com>
Date: Mon, 10 Nov 2025 11:00:21 +0000
Bug 1998179 - Part 1: Add a dummy loop in AsyncGeneratorResume as a preparation . r=mgaudet
Differential Revision: https://phabricator.services.mozilla.com/D271351
Diffstat:
1 file changed, 50 insertions(+), 48 deletions(-)
diff --git a/js/src/vm/AsyncIteration.cpp b/js/src/vm/AsyncIteration.cpp
@@ -1212,59 +1212,61 @@ bool js::AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp) {
[[nodiscard]] static bool AsyncGeneratorResume(
JSContext* cx, Handle<AsyncGeneratorObject*> generator,
CompletionKind completionKind, HandleValue argument) {
- MOZ_ASSERT(!generator->isClosed(),
- "closed generator when resuming async generator");
- MOZ_ASSERT(generator->isSuspended(),
- "non-suspended generator when resuming async generator");
+ while (true) {
+ MOZ_ASSERT(!generator->isClosed(),
+ "closed generator when resuming async generator");
+ MOZ_ASSERT(generator->isSuspended(),
+ "non-suspended generator when resuming async generator");
+
+ // Step 1. Assert: generator.[[AsyncGeneratorState]] is either
+ // suspended-start or suspended-yield.
+ //
+ // NOTE: We're using suspend/resume also for await. and the state can be
+ // anything.
- // Step 1. Assert: generator.[[AsyncGeneratorState]] is either
- // suspended-start or suspended-yield.
- //
- // NOTE: We're using suspend/resume also for await. and the state can be
- // anything.
-
- // Step 2. Let genContext be generator.[[AsyncGeneratorContext]].
- // Step 3. Let callerContext be the running execution context.
- // Step 4. Suspend callerContext.
- // (handled in generator)
-
- // Step 5. Set generator.[[AsyncGeneratorState]] to executing.
- generator->setExecuting();
-
- // Step 6. Push genContext onto the execution context stack; genContext is
- // now the running execution context.
- // Step 7. Resume the suspended evaluation of genContext using completion as
- // the result of the operation that suspended it. Let result be the
- // Completion Record returned by the resumed computation.
- // Step 8. Assert: result is never an abrupt completion.
- // Step 9. Assert: When we return here, genContext has already been removed
- // from the execution context stack and callerContext is the currently
- // running execution context.
- // Step 10. Return unused.
- Handle<PropertyName*> funName = completionKind == CompletionKind::Normal
- ? cx->names().AsyncGeneratorNext
- : completionKind == CompletionKind::Throw
- ? cx->names().AsyncGeneratorThrow
- : cx->names().AsyncGeneratorReturn;
- FixedInvokeArgs<1> args(cx);
- args[0].set(argument);
- RootedValue thisOrRval(cx, ObjectValue(*generator));
- if (!CallSelfHostedFunction(cx, funName, thisOrRval, args, &thisOrRval)) {
- if (!generator->isClosed()) {
- generator->setClosed(cx);
+ // Step 2. Let genContext be generator.[[AsyncGeneratorContext]].
+ // Step 3. Let callerContext be the running execution context.
+ // Step 4. Suspend callerContext.
+ // (handled in generator)
+
+ // Step 5. Set generator.[[AsyncGeneratorState]] to executing.
+ generator->setExecuting();
+
+ // Step 6. Push genContext onto the execution context stack; genContext is
+ // now the running execution context.
+ // Step 7. Resume the suspended evaluation of genContext using completion as
+ // the result of the operation that suspended it. Let result be the
+ // Completion Record returned by the resumed computation.
+ // Step 8. Assert: result is never an abrupt completion.
+ // Step 9. Assert: When we return here, genContext has already been removed
+ // from the execution context stack and callerContext is the
+ // currently running execution context.
+ // Step 10. Return unused.
+ Handle<PropertyName*> funName = completionKind == CompletionKind::Normal
+ ? cx->names().AsyncGeneratorNext
+ : completionKind == CompletionKind::Throw
+ ? cx->names().AsyncGeneratorThrow
+ : cx->names().AsyncGeneratorReturn;
+ FixedInvokeArgs<1> args(cx);
+ args[0].set(argument);
+ RootedValue thisOrRval(cx, ObjectValue(*generator));
+ if (!CallSelfHostedFunction(cx, funName, thisOrRval, args, &thisOrRval)) {
+ if (!generator->isClosed()) {
+ generator->setClosed(cx);
+ }
+ return AsyncGeneratorThrown(cx, generator);
}
- return AsyncGeneratorThrown(cx, generator);
- }
- if (generator->isAfterAwait()) {
- return AsyncGeneratorAwait(cx, generator, thisOrRval);
- }
+ if (generator->isAfterAwait()) {
+ return AsyncGeneratorAwait(cx, generator, thisOrRval);
+ }
- if (generator->isAfterYield()) {
- return AsyncGeneratorYield(cx, generator, thisOrRval);
- }
+ if (generator->isAfterYield()) {
+ return AsyncGeneratorYield(cx, generator, thisOrRval);
+ }
- return AsyncGeneratorReturned(cx, generator, thisOrRval);
+ return AsyncGeneratorReturned(cx, generator, thisOrRval);
+ }
}
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT