Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/builtins/builtins-async-gen.h"
6 : #include "src/builtins/builtins-utils-gen.h"
7 : #include "src/builtins/builtins.h"
8 : #include "src/code-factory.h"
9 : #include "src/code-stub-assembler.h"
10 : #include "src/frames-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : using compiler::Node;
16 :
17 : namespace {
18 :
19 : // Describe fields of Context associated with AsyncGeneratorAwait resume
20 : // closures.
21 : class AwaitContext {
22 : public:
23 : enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength };
24 : };
25 :
26 : class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler {
27 : public:
28 : explicit AsyncGeneratorBuiltinsAssembler(CodeAssemblerState* state)
29 : : AsyncBuiltinsAssembler(state) {}
30 :
31 : inline Node* LoadGeneratorState(Node* const generator) {
32 258 : return LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
33 : }
34 :
35 86 : inline Node* IsGeneratorStateClosed(Node* const state) {
36 86 : return SmiEqual(state, SmiConstant(JSGeneratorObject::kGeneratorClosed));
37 : }
38 : inline Node* IsGeneratorClosed(Node* const generator) {
39 : return IsGeneratorStateClosed(LoadGeneratorState(generator));
40 : }
41 :
42 : inline Node* IsGeneratorStateSuspended(Node* const state) {
43 : return SmiGreaterThanOrEqual(state, SmiConstant(0));
44 : }
45 :
46 : inline Node* IsGeneratorSuspended(Node* const generator) {
47 : return IsGeneratorStateSuspended(LoadGeneratorState(generator));
48 : }
49 :
50 43 : inline Node* IsGeneratorStateSuspendedAtStart(Node* const state) {
51 43 : return SmiEqual(state, SmiConstant(0));
52 : }
53 :
54 : inline Node* IsGeneratorStateNotExecuting(Node* const state) {
55 : return SmiNotEqual(state,
56 : SmiConstant(JSGeneratorObject::kGeneratorExecuting));
57 : }
58 : inline Node* IsGeneratorNotExecuting(Node* const generator) {
59 : return IsGeneratorStateNotExecuting(LoadGeneratorState(generator));
60 : }
61 :
62 : inline Node* LoadGeneratorAwaitedPromise(Node* const generator) {
63 : return LoadObjectField(generator,
64 43 : JSAsyncGeneratorObject::kAwaitedPromiseOffset);
65 : }
66 :
67 : inline Node* IsGeneratorNotSuspendedForAwait(Node* const generator) {
68 : return IsUndefined(LoadGeneratorAwaitedPromise(generator));
69 : }
70 :
71 43 : inline Node* IsGeneratorSuspendedForAwait(Node* const generator) {
72 : return HasInstanceType(LoadGeneratorAwaitedPromise(generator),
73 43 : JS_PROMISE_TYPE);
74 : }
75 :
76 : inline void ClearAwaitedPromise(Node* const generator) {
77 : StoreObjectFieldRoot(generator,
78 : JSAsyncGeneratorObject::kAwaitedPromiseOffset,
79 86 : Heap::kUndefinedValueRootIndex);
80 : }
81 :
82 43 : inline void CloseGenerator(Node* const generator) {
83 : StoreObjectFieldNoWriteBarrier(
84 : generator, JSGeneratorObject::kContinuationOffset,
85 43 : SmiConstant(JSGeneratorObject::kGeneratorClosed));
86 43 : }
87 :
88 : inline Node* IsFastJSIterResult(Node* const value, Node* const context) {
89 : CSA_ASSERT(this, TaggedIsNotSmi(value));
90 : Node* const native_context = LoadNativeContext(context);
91 : return WordEqual(
92 : LoadMap(value),
93 : LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX));
94 : }
95 :
96 : inline Node* LoadFirstAsyncGeneratorRequestFromQueue(Node* const generator) {
97 301 : return LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
98 : }
99 :
100 : inline Node* LoadResumeTypeFromAsyncGeneratorRequest(Node* const request) {
101 43 : return LoadObjectField(request, AsyncGeneratorRequest::kResumeModeOffset);
102 : }
103 :
104 : inline Node* LoadPromiseFromAsyncGeneratorRequest(Node* const request) {
105 86 : return LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
106 : }
107 :
108 : inline Node* LoadValueFromAsyncGeneratorRequest(Node* const request) {
109 129 : return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset);
110 : }
111 :
112 43 : inline Node* IsAbruptResumeType(Node* const resume_type) {
113 43 : return SmiNotEqual(resume_type, SmiConstant(JSGeneratorObject::kNext));
114 : }
115 :
116 : void AsyncGeneratorEnqueue(Node* context, Node* generator, Node* value,
117 : JSAsyncGeneratorObject::ResumeMode resume_mode,
118 : const char* method_name);
119 :
120 : Node* TakeFirstAsyncGeneratorRequestFromQueue(Node* generator);
121 : Node* TakeFirstAsyncGeneratorRequestFromQueueIfPresent(Node* generator,
122 : Label* if_not_present);
123 : void AddAsyncGeneratorRequestToQueue(Node* generator, Node* request);
124 :
125 : Node* AllocateAsyncGeneratorRequest(
126 : JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
127 : Node* promise);
128 :
129 : // Shared implementation of the catchable and uncatchable variations of Await
130 : // for AsyncGenerators.
131 : template <typename Descriptor>
132 : void AsyncGeneratorAwait(bool is_catchable);
133 : void AsyncGeneratorAwaitResumeClosure(
134 : Node* context, Node* value,
135 : JSAsyncGeneratorObject::ResumeMode resume_mode);
136 : };
137 :
138 : // Shared implementation for the 3 Async Iterator protocol methods of Async
139 : // Generators.
140 129 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
141 : Node* context, Node* generator, Node* value,
142 : JSAsyncGeneratorObject::ResumeMode resume_mode, const char* method_name) {
143 : // AsyncGeneratorEnqueue produces a new Promise, and appends it to the list
144 : // of async generator requests to be executed. If the generator is not
145 : // presently executing, then this method will loop through, processing each
146 : // request from front to back.
147 : // This loop resides in AsyncGeneratorResumeNext.
148 129 : Node* promise = AllocateAndInitJSPromise(context);
149 :
150 258 : Label enqueue(this), if_receiverisincompatible(this, Label::kDeferred);
151 :
152 129 : GotoIf(TaggedIsSmi(generator), &if_receiverisincompatible);
153 : Branch(HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE), &enqueue,
154 129 : &if_receiverisincompatible);
155 :
156 129 : BIND(&enqueue);
157 : {
158 : Label done(this);
159 : Node* const req =
160 129 : AllocateAsyncGeneratorRequest(resume_mode, value, promise);
161 :
162 129 : AddAsyncGeneratorRequestToQueue(generator, req);
163 :
164 : // Let state be generator.[[AsyncGeneratorState]]
165 : // If state is not "executing", then
166 : // Perform AsyncGeneratorResumeNext(Generator)
167 : // Check if the {receiver} is running or already closed.
168 : Node* continuation = LoadGeneratorState(generator);
169 :
170 : GotoIf(SmiEqual(continuation,
171 : SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)),
172 129 : &done);
173 :
174 129 : CallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
175 :
176 129 : Goto(&done);
177 129 : BIND(&done);
178 129 : Return(promise);
179 : }
180 :
181 129 : BIND(&if_receiverisincompatible);
182 : {
183 : Node* const error =
184 : MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context,
185 129 : CStringConstant(method_name), generator);
186 :
187 : CallBuiltin(Builtins::kRejectNativePromise, context, promise, error,
188 129 : TrueConstant());
189 129 : Return(promise);
190 129 : }
191 129 : }
192 :
193 129 : Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
194 : JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
195 : Node* promise) {
196 : CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
197 129 : Node* request = Allocate(AsyncGeneratorRequest::kSize);
198 129 : StoreMapNoWriteBarrier(request, Heap::kAsyncGeneratorRequestMapRootIndex);
199 : StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset,
200 129 : UndefinedConstant());
201 : StoreObjectFieldNoWriteBarrier(request,
202 : AsyncGeneratorRequest::kResumeModeOffset,
203 129 : SmiConstant(resume_mode));
204 : StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset,
205 129 : resume_value);
206 : StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset,
207 129 : promise);
208 : StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset,
209 129 : Heap::kUndefinedValueRootIndex);
210 129 : return request;
211 : }
212 :
213 86 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
214 : Node* context, Node* value,
215 : JSAsyncGeneratorObject::ResumeMode resume_mode) {
216 : Node* const generator =
217 86 : LoadContextElement(context, AwaitContext::kGeneratorSlot);
218 : CSA_SLOW_ASSERT(this,
219 : HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
220 :
221 : #if defined(DEBUG) && defined(ENABLE_SLOW_DCHECKS)
222 : Node* const awaited_promise = LoadGeneratorAwaitedPromise(generator);
223 : CSA_SLOW_ASSERT(this, HasInstanceType(awaited_promise, JS_PROMISE_TYPE));
224 : CSA_SLOW_ASSERT(this, SmiNotEqual(LoadObjectField(awaited_promise,
225 : JSPromise::kStatusOffset),
226 : SmiConstant(v8::Promise::kPending)));
227 : #endif
228 :
229 : ClearAwaitedPromise(generator);
230 :
231 : CSA_SLOW_ASSERT(this, IsGeneratorSuspended(generator));
232 :
233 : CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, generator,
234 : SmiConstant(resume_mode),
235 172 : SmiConstant(static_cast<int>(SuspendFlags::kAsyncGeneratorAwait)));
236 :
237 : TailCallStub(CodeFactory::AsyncGeneratorResumeNext(isolate()), context,
238 86 : generator);
239 86 : }
240 :
241 : template <typename Descriptor>
242 86 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) {
243 86 : Node* generator = Parameter(1);
244 86 : Node* value = Parameter(2);
245 86 : Node* context = Parameter(5);
246 :
247 : CSA_SLOW_ASSERT(this,
248 : HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
249 :
250 86 : Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
251 : CSA_ASSERT(this, WordNotEqual(request, UndefinedConstant()));
252 :
253 86 : NodeGenerator1 closure_context = [&](Node* native_context) -> Node* {
254 : Node* const context =
255 86 : CreatePromiseContext(native_context, AwaitContext::kLength);
256 86 : StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
257 86 : generator);
258 86 : return context;
259 : };
260 :
261 : Node* outer_promise =
262 86 : LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
263 :
264 : const int resolve_index = Context::ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN;
265 : const int reject_index = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;
266 :
267 : Node* promise =
268 : Await(context, generator, value, outer_promise, closure_context,
269 86 : resolve_index, reject_index, is_catchable);
270 :
271 : CSA_SLOW_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
272 86 : StoreObjectField(generator, JSAsyncGeneratorObject::kAwaitedPromiseOffset,
273 : promise);
274 86 : Return(UndefinedConstant());
275 86 : }
276 :
277 129 : void AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue(
278 : Node* generator, Node* request) {
279 129 : VARIABLE(var_current, MachineRepresentation::kTagged);
280 129 : Label empty(this), loop(this, &var_current), done(this);
281 :
282 : var_current.Bind(
283 129 : LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset));
284 129 : Branch(IsUndefined(var_current.value()), &empty, &loop);
285 :
286 129 : BIND(&empty);
287 : {
288 129 : StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request);
289 129 : Goto(&done);
290 : }
291 :
292 129 : BIND(&loop);
293 : {
294 129 : Label loop_next(this), next_empty(this);
295 129 : Node* current = var_current.value();
296 129 : Node* next = LoadObjectField(current, AsyncGeneratorRequest::kNextOffset);
297 :
298 129 : Branch(IsUndefined(next), &next_empty, &loop_next);
299 129 : BIND(&next_empty);
300 : {
301 129 : StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request);
302 129 : Goto(&done);
303 : }
304 :
305 129 : BIND(&loop_next);
306 : {
307 129 : var_current.Bind(next);
308 129 : Goto(&loop);
309 129 : }
310 : }
311 258 : BIND(&done);
312 129 : }
313 :
314 86 : Node* AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue(
315 : Node* generator) {
316 : // Removes and returns the first AsyncGeneratorRequest from a
317 : // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty.
318 : CSA_ASSERT(this, HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
319 : Node* request =
320 86 : LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
321 : CSA_ASSERT(this, WordNotEqual(request, UndefinedConstant()));
322 :
323 86 : Node* next = LoadObjectField(request, AsyncGeneratorRequest::kNextOffset);
324 :
325 86 : StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next);
326 86 : return request;
327 : }
328 : } // namespace
329 :
330 : // https://tc39.github.io/proposal-async-iteration/
331 : // Section #sec-asyncgenerator-prototype-next
332 172 : TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) {
333 : Node* const generator = Parameter(Descriptor::kReceiver);
334 : Node* const value = Parameter(Descriptor::kValue);
335 : Node* const context = Parameter(Descriptor::kContext);
336 : AsyncGeneratorEnqueue(context, generator, value,
337 : JSAsyncGeneratorObject::kNext,
338 43 : "[AsyncGenerator].prototype.next");
339 43 : }
340 :
341 : // https://tc39.github.io/proposal-async-iteration/
342 : // Section #sec-asyncgenerator-prototype-return
343 172 : TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) {
344 : Node* generator = Parameter(Descriptor::kReceiver);
345 : Node* value = Parameter(Descriptor::kValue);
346 : Node* context = Parameter(Descriptor::kContext);
347 : AsyncGeneratorEnqueue(context, generator, value,
348 : JSAsyncGeneratorObject::kReturn,
349 43 : "[AsyncGenerator].prototype.return");
350 43 : }
351 :
352 : // https://tc39.github.io/proposal-async-iteration/
353 : // Section #sec-asyncgenerator-prototype-throw
354 172 : TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
355 : Node* generator = Parameter(Descriptor::kReceiver);
356 : Node* value = Parameter(Descriptor::kValue);
357 : Node* context = Parameter(Descriptor::kContext);
358 : AsyncGeneratorEnqueue(context, generator, value,
359 : JSAsyncGeneratorObject::kThrow,
360 43 : "[AsyncGenerator].prototype.throw");
361 43 : }
362 :
363 172 : TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
364 : Node* value = Parameter(Descriptor::kValue);
365 : Node* context = Parameter(Descriptor::kContext);
366 : AsyncGeneratorAwaitResumeClosure(context, value,
367 43 : JSAsyncGeneratorObject::kNext);
368 43 : }
369 :
370 172 : TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
371 : Node* value = Parameter(Descriptor::kValue);
372 : Node* context = Parameter(Descriptor::kContext);
373 : AsyncGeneratorAwaitResumeClosure(context, value,
374 43 : JSAsyncGeneratorObject::kThrow);
375 43 : }
376 :
377 129 : TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {
378 : const bool kIsCatchable = false;
379 43 : AsyncGeneratorAwait<Descriptor>(kIsCatchable);
380 0 : }
381 :
382 129 : TF_BUILTIN(AsyncGeneratorAwaitCaught, AsyncGeneratorBuiltinsAssembler) {
383 : const bool kIsCatchable = true;
384 43 : AsyncGeneratorAwait<Descriptor>(kIsCatchable);
385 0 : }
386 :
387 172 : TF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) {
388 : typedef AsyncGeneratorResumeNextDescriptor Descriptor;
389 : Node* const generator = Parameter(Descriptor::kGenerator);
390 : Node* const context = Parameter(Descriptor::kContext);
391 :
392 : // The penultimate step of proposal-async-iteration/#sec-asyncgeneratorresolve
393 : // and proposal-async-iteration/#sec-asyncgeneratorreject both recursively
394 : // invoke AsyncGeneratorResumeNext() again.
395 : //
396 : // This implementation does not implement this recursively, but instead
397 : // performs a loop in AsyncGeneratorResumeNext, which continues as long as
398 : // there is an AsyncGeneratorRequest in the queue, and as long as the
399 : // generator is not suspended due to an AwaitExpression.
400 43 : VARIABLE(var_state, MachineRepresentation::kTaggedSigned,
401 : LoadGeneratorState(generator));
402 86 : VARIABLE(var_next, MachineRepresentation::kTagged,
403 : LoadFirstAsyncGeneratorRequestFromQueue(generator));
404 43 : Variable* labels[] = {&var_state, &var_next};
405 86 : Label start(this, 2, labels);
406 43 : Goto(&start);
407 43 : BIND(&start);
408 :
409 : CSA_ASSERT(this, IsGeneratorNotExecuting(generator));
410 :
411 : // Stop resuming if suspended for Await.
412 43 : ReturnIf(IsGeneratorSuspendedForAwait(generator), UndefinedConstant());
413 :
414 : // Stop resuming if request queue is empty.
415 43 : ReturnIf(IsUndefined(var_next.value()), UndefinedConstant());
416 :
417 43 : Node* const next = var_next.value();
418 : Node* const resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next);
419 :
420 43 : Label if_abrupt(this), if_normal(this), resume_generator(this);
421 43 : Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal);
422 43 : BIND(&if_abrupt);
423 : {
424 43 : Label settle_promise(this), fulfill_promise(this), reject_promise(this);
425 : GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()),
426 43 : &settle_promise);
427 43 : CloseGenerator(generator);
428 43 : var_state.Bind(SmiConstant(JSGeneratorObject::kGeneratorClosed));
429 :
430 43 : Goto(&settle_promise);
431 43 : BIND(&settle_promise);
432 :
433 43 : GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
434 :
435 : Branch(SmiEqual(resume_type, SmiConstant(JSGeneratorObject::kReturn)),
436 43 : &fulfill_promise, &reject_promise);
437 :
438 43 : BIND(&fulfill_promise);
439 : CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator,
440 86 : LoadValueFromAsyncGeneratorRequest(next), TrueConstant());
441 43 : var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
442 43 : Goto(&start);
443 :
444 43 : BIND(&reject_promise);
445 : CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator,
446 43 : LoadValueFromAsyncGeneratorRequest(next));
447 43 : var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
448 86 : Goto(&start);
449 : }
450 :
451 43 : BIND(&if_normal);
452 : {
453 43 : GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
454 : CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator,
455 43 : UndefinedConstant(), TrueConstant());
456 43 : var_state.Bind(LoadGeneratorState(generator));
457 43 : var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
458 43 : Goto(&start);
459 : }
460 :
461 43 : BIND(&resume_generator);
462 : {
463 : CallStub(CodeFactory::ResumeGenerator(isolate()), context,
464 : LoadValueFromAsyncGeneratorRequest(next), generator, resume_type,
465 129 : SmiConstant(static_cast<int>(SuspendFlags::kAsyncGeneratorYield)));
466 43 : var_state.Bind(LoadGeneratorState(generator));
467 43 : var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
468 43 : Goto(&start);
469 43 : }
470 43 : }
471 :
472 172 : TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
473 : Node* const generator = Parameter(Descriptor::kGenerator);
474 : Node* const value = Parameter(Descriptor::kValue);
475 : Node* const done = Parameter(Descriptor::kDone);
476 : Node* const context = Parameter(Descriptor::kContext);
477 :
478 : CSA_SLOW_ASSERT(this,
479 : HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
480 : CSA_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
481 :
482 43 : Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
483 : Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);
484 :
485 43 : Node* const wrapper = AllocateAndInitJSPromise(context);
486 43 : CallBuiltin(Builtins::kResolveNativePromise, context, wrapper, value);
487 :
488 : Node* const on_fulfilled =
489 43 : CreateUnwrapClosure(LoadNativeContext(context), done);
490 :
491 : // Per spec, AsyncGeneratorResolve() returns undefined. However, for the
492 : // benefit of %TraceExit(), return the Promise.
493 : Return(CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapper,
494 43 : on_fulfilled, UndefinedConstant(), promise));
495 43 : }
496 :
497 172 : TF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) {
498 : typedef AsyncGeneratorRejectDescriptor Descriptor;
499 : Node* const generator = Parameter(Descriptor::kGenerator);
500 : Node* const value = Parameter(Descriptor::kValue);
501 : Node* const context = Parameter(Descriptor::kContext);
502 :
503 43 : Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
504 : Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);
505 :
506 : Return(CallBuiltin(Builtins::kRejectNativePromise, context, promise, value,
507 43 : TrueConstant()));
508 43 : }
509 :
510 : } // namespace internal
511 : } // namespace v8
|