AsyncGenerator.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibJS/Runtime/AsyncGenerator.h>
  8. #include <LibJS/Runtime/AsyncGeneratorPrototype.h>
  9. #include <LibJS/Runtime/AsyncGeneratorRequest.h>
  10. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  11. #include <LibJS/Runtime/GlobalObject.h>
  12. #include <LibJS/Runtime/PromiseConstructor.h>
  13. namespace JS {
  14. JS_DEFINE_ALLOCATOR(AsyncGenerator);
  15. ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> AsyncGenerator::create(Realm& realm, Value initial_value, ECMAScriptFunctionObject* generating_function, NonnullOwnPtr<ExecutionContext> execution_context, NonnullOwnPtr<Bytecode::CallFrame> frame)
  16. {
  17. auto& vm = realm.vm();
  18. // This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
  19. auto generating_function_prototype = TRY(generating_function->get(vm.names.prototype));
  20. auto generating_function_prototype_object = TRY(generating_function_prototype.to_object(vm));
  21. auto object = realm.heap().allocate<AsyncGenerator>(realm, realm, generating_function_prototype_object, move(execution_context));
  22. object->m_generating_function = generating_function;
  23. object->m_frame = move(frame);
  24. object->m_previous_value = initial_value;
  25. return object;
  26. }
  27. AsyncGenerator::AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext> context)
  28. : Object(ConstructWithPrototypeTag::Tag, prototype)
  29. , m_async_generator_context(move(context))
  30. {
  31. }
  32. void AsyncGenerator::visit_edges(Cell::Visitor& visitor)
  33. {
  34. Base::visit_edges(visitor);
  35. for (auto const& request : m_async_generator_queue) {
  36. if (request.completion.value().has_value())
  37. visitor.visit(*request.completion.value());
  38. visitor.visit(request.capability);
  39. }
  40. visitor.visit(m_generating_function);
  41. visitor.visit(m_previous_value);
  42. if (m_frame)
  43. m_frame->visit_edges(visitor);
  44. visitor.visit(m_current_promise);
  45. m_async_generator_context->visit_edges(visitor);
  46. }
  47. // 27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability ), https://tc39.es/ecma262/#sec-asyncgeneratorenqueue
  48. void AsyncGenerator::async_generator_enqueue(Completion completion, NonnullGCPtr<PromiseCapability> promise_capability)
  49. {
  50. // 1. Let request be AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }.
  51. auto request = AsyncGeneratorRequest { .completion = move(completion), .capability = promise_capability };
  52. // 2. Append request to generator.[[AsyncGeneratorQueue]].
  53. m_async_generator_queue.append(move(request));
  54. // 3. Return unused.
  55. }
  56. void AsyncGenerator::set_async_generator_state(Badge<AsyncGeneratorPrototype>, AsyncGenerator::State value)
  57. {
  58. m_async_generator_state = value;
  59. }
  60. // 27.7.5.3 Await ( value ), https://tc39.es/ecma262/#await
  61. ThrowCompletionOr<void> AsyncGenerator::await(Value value)
  62. {
  63. auto& vm = this->vm();
  64. auto& realm = *vm.current_realm();
  65. // 1. Let asyncContext be the running execution context.
  66. auto& async_context = vm.running_execution_context();
  67. // 2. Let promise be ? PromiseResolve(%Promise%, value).
  68. auto* promise_object = TRY(promise_resolve(vm, realm.intrinsics().promise_constructor(), value));
  69. // 3. Let fulfilledClosure be a new Abstract Closure with parameters (v) that captures asyncContext and performs the
  70. // following steps when called:
  71. auto fulfilled_closure = [this, &async_context](VM& vm) -> ThrowCompletionOr<Value> {
  72. auto value = vm.argument(0);
  73. // a. Let prevContext be the running execution context.
  74. auto& prev_context = vm.running_execution_context();
  75. // FIXME: b. Suspend prevContext.
  76. // c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  77. TRY(vm.push_execution_context(async_context, {}));
  78. // d. Resume the suspended evaluation of asyncContext using NormalCompletion(v) as the result of the operation that
  79. // suspended it.
  80. execute(vm, normal_completion(value));
  81. // e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and
  82. // prevContext is the currently running execution context.
  83. VERIFY(&vm.running_execution_context() == &prev_context);
  84. // f. Return undefined.
  85. return js_undefined();
  86. };
  87. // 4. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
  88. auto on_fulfilled = NativeFunction::create(realm, move(fulfilled_closure), 1, "");
  89. // 5. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures asyncContext and performs the
  90. // following steps when called:
  91. auto rejected_closure = [this, &async_context](VM& vm) -> ThrowCompletionOr<Value> {
  92. auto reason = vm.argument(0);
  93. // a. Let prevContext be the running execution context.
  94. auto& prev_context = vm.running_execution_context();
  95. // FIXME: b. Suspend prevContext.
  96. // c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  97. TRY(vm.push_execution_context(async_context, {}));
  98. // d. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that
  99. // suspended it.
  100. execute(vm, throw_completion(reason));
  101. // e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and
  102. // prevContext is the currently running execution context.
  103. VERIFY(&vm.running_execution_context() == &prev_context);
  104. // f. Return undefined.
  105. return js_undefined();
  106. };
  107. // 6. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  108. auto on_rejected = NativeFunction::create(realm, move(rejected_closure), 1, "");
  109. // 7. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
  110. m_current_promise = verify_cast<Promise>(promise_object);
  111. m_current_promise->perform_then(on_fulfilled, on_rejected, {});
  112. // 8. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the
  113. // execution context stack as the running execution context.
  114. vm.pop_execution_context();
  115. // NOTE: None of these are necessary. 10-12 are handled by step d of the above lambdas.
  116. // 9. Let callerContext be the running execution context.
  117. // 10. Resume callerContext passing empty. If asyncContext is ever resumed again, let completion be the Completion Record with which it is resumed.
  118. // 11. Assert: If control reaches here, then asyncContext is the running execution context again.
  119. // 12. Return completion.
  120. return {};
  121. }
  122. void AsyncGenerator::execute(VM& vm, Completion completion)
  123. {
  124. while (true) {
  125. // Loosely based on step 4 of https://tc39.es/ecma262/#sec-asyncgeneratorstart
  126. VERIFY(completion.value().has_value());
  127. auto generated_value = [](Value value) -> Value {
  128. if (value.is_object())
  129. return value.as_object().get_without_side_effects("result");
  130. return value.is_empty() ? js_undefined() : value;
  131. };
  132. auto generated_continuation = [&](Value value) -> Bytecode::BasicBlock const* {
  133. if (value.is_object()) {
  134. auto number_value = value.as_object().get_without_side_effects("continuation");
  135. return reinterpret_cast<Bytecode::BasicBlock const*>(static_cast<u64>(number_value.as_double()));
  136. }
  137. return nullptr;
  138. };
  139. auto generated_is_await = [](Value value) -> bool {
  140. if (value.is_object())
  141. return value.as_object().get_without_side_effects("isAwait").as_bool();
  142. return false;
  143. };
  144. auto& realm = *vm.current_realm();
  145. auto completion_object = Object::create(realm, nullptr);
  146. completion_object->define_direct_property(vm.names.type, Value(to_underlying(completion.type())), default_attributes);
  147. completion_object->define_direct_property(vm.names.value, completion.value().value(), default_attributes);
  148. auto& bytecode_interpreter = vm.bytecode_interpreter();
  149. auto const* next_block = generated_continuation(m_previous_value);
  150. // We should never enter `execute` again after the generator is complete.
  151. VERIFY(next_block);
  152. VERIFY(!m_generating_function->bytecode_executable()->basic_blocks.find_if([next_block](auto& block) { return block == next_block; }).is_end());
  153. Bytecode::CallFrame* frame = nullptr;
  154. if (m_frame)
  155. frame = m_frame.ptr();
  156. if (frame)
  157. frame->registers()[0] = completion_object;
  158. else
  159. bytecode_interpreter.accumulator() = completion_object;
  160. auto next_result = bytecode_interpreter.run_and_return_frame(*m_generating_function->bytecode_executable(), next_block, frame);
  161. if (!m_frame)
  162. m_frame = move(next_result.frame);
  163. auto result_value = move(next_result.value);
  164. if (!result_value.is_throw_completion()) {
  165. m_previous_value = result_value.release_value();
  166. auto value = generated_value(m_previous_value);
  167. bool is_await = generated_is_await(m_previous_value);
  168. if (is_await) {
  169. auto await_result = this->await(value);
  170. if (await_result.is_throw_completion()) {
  171. completion = await_result.release_error();
  172. continue;
  173. }
  174. return;
  175. }
  176. }
  177. bool done = result_value.is_throw_completion() || generated_continuation(m_previous_value) == nullptr;
  178. if (!done) {
  179. // 27.6.3.8 AsyncGeneratorYield ( value ), https://tc39.es/ecma262/#sec-asyncgeneratoryield
  180. // 1. Let genContext be the running execution context.
  181. // 2. Assert: genContext is the execution context of a generator.
  182. // 3. Let generator be the value of the Generator component of genContext.
  183. // 4. Assert: GetGeneratorKind() is async.
  184. // NOTE: genContext is `m_async_generator_context`, generator is `this`.
  185. // 5. Let completion be NormalCompletion(value).
  186. auto value = generated_value(m_previous_value);
  187. auto yield_completion = normal_completion(value);
  188. // 6. Assert: The execution context stack has at least two elements.
  189. VERIFY(vm.execution_context_stack().size() >= 2);
  190. // 7. Let previousContext be the second to top element of the execution context stack.
  191. auto& previous_context = vm.execution_context_stack().at(vm.execution_context_stack().size() - 2);
  192. // 8. Let previousRealm be previousContext's Realm.
  193. auto previous_realm = previous_context->realm;
  194. // 9. Perform AsyncGeneratorCompleteStep(generator, completion, false, previousRealm).
  195. complete_step(yield_completion, false, previous_realm.ptr());
  196. // 10. Let queue be generator.[[AsyncGeneratorQueue]].
  197. auto& queue = m_async_generator_queue;
  198. // 11. If queue is not empty, then
  199. if (!queue.is_empty()) {
  200. // a. NOTE: Execution continues without suspending the generator.
  201. // b. Let toYield be the first element of queue.
  202. auto& to_yield = queue.first();
  203. // c. Let resumptionValue be Completion(toYield.[[Completion]]).
  204. completion = Completion(to_yield.completion);
  205. // d. Return ? AsyncGeneratorUnwrapYieldResumption(resumptionValue).
  206. // NOTE: AsyncGeneratorUnwrapYieldResumption is performed inside the continuation block inside the generator,
  207. // so we just need to enter the generator again.
  208. continue;
  209. }
  210. // 12. Else,
  211. else {
  212. // a. Set generator.[[AsyncGeneratorState]] to suspendedYield.
  213. m_async_generator_state = State::SuspendedYield;
  214. // b. Remove genContext from the execution context stack and restore the execution context that is at the top of the
  215. // execution context stack as the running execution context.
  216. vm.pop_execution_context();
  217. // c. Let callerContext be the running execution context.
  218. // d. Resume callerContext passing undefined. If genContext is ever resumed again, let resumptionValue be the Completion Record with which it is resumed.
  219. // e. Assert: If control reaches here, then genContext is the running execution context again.
  220. // f. Return ? AsyncGeneratorUnwrapYieldResumption(resumptionValue).
  221. // NOTE: e-f are performed whenever someone calls `execute` again.
  222. return;
  223. }
  224. }
  225. // 27.6.3.2 AsyncGeneratorStart ( generator, generatorBody ), https://tc39.es/ecma262/#sec-asyncgeneratorstart
  226. // 4.e. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
  227. // 4.f. Remove acGenContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
  228. vm.pop_execution_context();
  229. // 4.g. Set acGenerator.[[AsyncGeneratorState]] to completed.
  230. m_async_generator_state = State::Completed;
  231. // 4.h. If result.[[Type]] is normal, set result to NormalCompletion(undefined).
  232. // 4.i. If result.[[Type]] is return, set result to NormalCompletion(result.[[Value]]).
  233. Completion result;
  234. if (!result_value.is_throw_completion()) {
  235. result = normal_completion(generated_value(m_previous_value));
  236. } else {
  237. result = result_value.release_error();
  238. }
  239. // 4.j. Perform AsyncGeneratorCompleteStep(acGenerator, result, true).
  240. complete_step(result, true);
  241. // 4.k. Perform AsyncGeneratorDrainQueue(acGenerator).
  242. drain_queue();
  243. // 4.l. Return undefined.
  244. return;
  245. }
  246. }
  247. // 27.6.3.6 AsyncGeneratorResume ( generator, completion ), https://tc39.es/ecma262/#sec-asyncgeneratorresume
  248. ThrowCompletionOr<void> AsyncGenerator::resume(VM& vm, Completion completion)
  249. {
  250. // 1. Assert: generator.[[AsyncGeneratorState]] is either suspendedStart or suspendedYield.
  251. VERIFY(m_async_generator_state == State::SuspendedStart || m_async_generator_state == State::SuspendedYield);
  252. // 2. Let genContext be generator.[[AsyncGeneratorContext]].
  253. auto& generator_context = m_async_generator_context;
  254. // 3. Let callerContext be the running execution context.
  255. auto const& caller_context = vm.running_execution_context();
  256. // FIXME: 4. Suspend callerContext.
  257. // 5. Set generator.[[AsyncGeneratorState]] to executing.
  258. m_async_generator_state = State::Executing;
  259. // 6. Push genContext onto the execution context stack; genContext is now the running execution context.
  260. TRY(vm.push_execution_context(*generator_context, {}));
  261. // 7. Resume the suspended evaluation of genContext using completion as the result of the operation that suspended
  262. // it. Let result be the Completion Record returned by the resumed computation.
  263. // 8. Assert: result is never an abrupt completion.
  264. execute(vm, completion);
  265. // 9. Assert: When we return here, genContext has already been removed from the execution context stack and
  266. // callerContext is the currently running execution context.
  267. VERIFY(&vm.running_execution_context() == &caller_context);
  268. // 10. Return unused.
  269. return {};
  270. }
  271. // 27.6.3.9 AsyncGeneratorAwaitReturn ( generator ), https://tc39.es/ecma262/#sec-asyncgeneratorawaitreturn
  272. // With unmerged broken promise fixup from https://github.com/tc39/ecma262/pull/2683
  273. void AsyncGenerator::await_return()
  274. {
  275. auto& vm = this->vm();
  276. auto& realm = *vm.current_realm();
  277. // 1. Let queue be generator.[[AsyncGeneratorQueue]].
  278. auto& queue = m_async_generator_queue;
  279. // 2. Assert: queue is not empty.
  280. VERIFY(!queue.is_empty());
  281. // 3. Let next be the first element of queue.
  282. auto& next = m_async_generator_queue.first();
  283. // 4. Let completion be Completion(next.[[Completion]]).
  284. auto completion = Completion(next.completion);
  285. // 5. Assert: completion.[[Type]] is return.
  286. VERIFY(completion.type() == Completion::Type::Return);
  287. // 6. Let promiseCompletion be Completion(PromiseResolve(%Promise%, _completion_.[[Value]])).
  288. auto promise_completion = promise_resolve(vm, realm.intrinsics().promise_constructor(), completion.value().value());
  289. // 7. If promiseCompletion is an abrupt completion, then
  290. if (promise_completion.is_throw_completion()) {
  291. // a. Set generator.[[AsyncGeneratorState]] to completed.
  292. m_async_generator_state = State::Completed;
  293. // b. Perform AsyncGeneratorCompleteStep(generator, promiseCompletion, true).
  294. complete_step(promise_completion.release_error(), true);
  295. // c. Perform AsyncGeneratorDrainQueue(generator).
  296. drain_queue();
  297. // d. Return unused.
  298. return;
  299. }
  300. // 8. Assert: promiseCompletion.[[Type]] is normal.
  301. VERIFY(!promise_completion.is_throw_completion());
  302. // 9. Let promise be promiseCompletion.[[Value]].
  303. auto* promise = promise_completion.release_value();
  304. // 10. Let fulfilledClosure be a new Abstract Closure with parameters (value) that captures generator and performs
  305. // the following steps when called:
  306. auto fulfilled_closure = [this](VM& vm) -> ThrowCompletionOr<Value> {
  307. // a. Set generator.[[AsyncGeneratorState]] to completed.
  308. m_async_generator_state = State::Completed;
  309. // b. Let result be NormalCompletion(value).
  310. auto result = normal_completion(vm.argument(0));
  311. // c. Perform AsyncGeneratorCompleteStep(generator, result, true).
  312. complete_step(result, true);
  313. // d. Perform AsyncGeneratorDrainQueue(generator).
  314. drain_queue();
  315. // e. Return undefined.
  316. return js_undefined();
  317. };
  318. // 11. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
  319. auto on_fulfilled = NativeFunction::create(realm, move(fulfilled_closure), 1, "");
  320. // 12. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures generator and performs
  321. // the following steps when called:
  322. auto rejected_closure = [this](VM& vm) -> ThrowCompletionOr<Value> {
  323. // a. Set generator.[[AsyncGeneratorState]] to completed.
  324. m_async_generator_state = State::Completed;
  325. // b. Let result be ThrowCompletion(reason).
  326. auto result = throw_completion(vm.argument(0));
  327. // c. Perform AsyncGeneratorCompleteStep(generator, result, true).
  328. complete_step(result, true);
  329. // d. Perform AsyncGeneratorDrainQueue(generator).
  330. drain_queue();
  331. // e. Return undefined.
  332. return js_undefined();
  333. };
  334. // 13. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  335. auto on_rejected = NativeFunction::create(realm, move(rejected_closure), 1, "");
  336. // 14. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
  337. // NOTE: await_return should only be called when the generator is in SuspendedStart or Completed state,
  338. // so an await shouldn't be running currently, so it should be safe to overwrite m_current_promise.
  339. m_current_promise = verify_cast<Promise>(promise);
  340. m_current_promise->perform_then(on_fulfilled, on_rejected, {});
  341. // 15. Return unused.
  342. return;
  343. }
  344. // 27.6.3.5 AsyncGeneratorCompleteStep ( generator, completion, done [ , realm ] ), https://tc39.es/ecma262/#sec-asyncgeneratorcompletestep
  345. void AsyncGenerator::complete_step(Completion completion, bool done, Realm* realm)
  346. {
  347. auto& vm = this->vm();
  348. // 1. Assert: generator.[[AsyncGeneratorQueue]] is not empty.
  349. VERIFY(!m_async_generator_queue.is_empty());
  350. // 2. Let next be the first element of generator.[[AsyncGeneratorQueue]].
  351. // 3. Remove the first element from generator.[[AsyncGeneratorQueue]].
  352. auto next = m_async_generator_queue.take_first();
  353. // 4. Let promiseCapability be next.[[Capability]].
  354. auto promise_capability = next.capability;
  355. // 5. Let value be completion.[[Value]].
  356. auto value = completion.value().value();
  357. // 6. If completion.[[Type]] is throw, then
  358. if (completion.type() == Completion::Type::Throw) {
  359. // a. Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
  360. MUST(call(vm, *promise_capability->reject(), js_undefined(), value));
  361. }
  362. // 7. Else,
  363. else {
  364. // a. Assert: completion.[[Type]] is normal.
  365. VERIFY(completion.type() == Completion::Type::Normal);
  366. GCPtr<Object> iterator_result;
  367. // b. If realm is present, then
  368. if (realm) {
  369. // i. Let oldRealm be the running execution context's Realm.
  370. auto old_realm = vm.running_execution_context().realm;
  371. // ii. Set the running execution context's Realm to realm.
  372. vm.running_execution_context().realm = realm;
  373. // iii. Let iteratorResult be CreateIterResultObject(value, done).
  374. iterator_result = create_iterator_result_object(vm, value, done);
  375. // iv. Set the running execution context's Realm to oldRealm.
  376. vm.running_execution_context().realm = old_realm;
  377. }
  378. // c. Else,
  379. else {
  380. // i. Let iteratorResult be CreateIterResultObject(value, done).
  381. iterator_result = create_iterator_result_object(vm, value, done);
  382. }
  383. VERIFY(iterator_result);
  384. // d. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
  385. MUST(call(vm, *promise_capability->resolve(), js_undefined(), iterator_result));
  386. }
  387. // 8. Return unused.
  388. }
  389. // 27.6.3.10 AsyncGeneratorDrainQueue ( generator ), https://tc39.es/ecma262/#sec-asyncgeneratordrainqueue
  390. void AsyncGenerator::drain_queue()
  391. {
  392. // 1. Assert: generator.[[AsyncGeneratorState]] is completed.
  393. VERIFY(m_async_generator_state == State::Completed);
  394. // 2. Let queue be generator.[[AsyncGeneratorQueue]].
  395. auto& queue = m_async_generator_queue;
  396. // 3. If queue is empty, return unused.
  397. if (queue.is_empty())
  398. return;
  399. // 4. Let done be false.
  400. bool done = false;
  401. // 5. Repeat, while done is false,
  402. while (!done) {
  403. // a. Let next be the first element of queue.
  404. auto& next = m_async_generator_queue.first();
  405. // b. Let completion be Completion(next.[[Completion]]).
  406. auto completion = Completion(next.completion);
  407. // c. If completion.[[Type]] is return, then
  408. if (completion.type() == Completion::Type::Return) {
  409. // i. Set generator.[[AsyncGeneratorState]] to awaiting-return.
  410. m_async_generator_state = State::AwaitingReturn;
  411. // ii. Perform AsyncGeneratorAwaitReturn(generator).
  412. await_return();
  413. // iii. Set done to true.
  414. done = true;
  415. }
  416. // d. Else,
  417. else {
  418. // i. If completion.[[Type]] is normal, then
  419. if (completion.type() == Completion::Type::Normal) {
  420. // 1. Set completion to NormalCompletion(undefined).
  421. completion = normal_completion(js_undefined());
  422. }
  423. // ii. Perform AsyncGeneratorCompleteStep(generator, completion, true).
  424. complete_step(completion, true);
  425. // iii. If queue is empty, set done to true.
  426. if (queue.is_empty())
  427. done = true;
  428. }
  429. }
  430. // 6. Return unused.
  431. }
  432. }