Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/vm/AsyncIteration.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * vim: set ts=8 sts=4 et sw=4 tw=99:
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "vm/AsyncIteration.h"
8
9
#include "builtin/Array.h"
10
11
#include "builtin/Promise.h"
12
#include "vm/GeneratorObject.h"
13
#include "vm/GlobalObject.h"
14
#include "vm/Interpreter.h"
15
#include "vm/Realm.h"
16
#include "vm/SelfHosting.h"
17
18
#include "vm/JSContext-inl.h"
19
#include "vm/JSObject-inl.h"
20
#include "vm/List-inl.h"
21
#include "vm/NativeObject-inl.h"
22
23
using namespace js;
24
25
0
#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
26
0
#define WRAPPED_ASYNC_UNWRAPPED_SLOT 0
27
28
// Async Iteration proposal 8.3.10 Runtime Semantics: EvaluateBody.
29
static bool
30
WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp)
31
0
{
32
0
    CallArgs args = CallArgsFromVp(argc, vp);
33
0
34
0
    RootedFunction wrapped(cx, &args.callee().as<JSFunction>());
35
0
    RootedValue unwrappedVal(cx, wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT));
36
0
37
0
    // Step 1.
38
0
    InvokeArgs args2(cx);
39
0
    if (!FillArgumentsFromArraylike(cx, args2, args)) {
40
0
        return false;
41
0
    }
42
0
43
0
    RootedValue generatorVal(cx);
44
0
    if (!Call(cx, unwrappedVal, args.thisv(), args2, &generatorVal)) {
45
0
        return false;
46
0
    }
47
0
48
0
    // Step 2.
49
0
    AsyncGeneratorObject* asyncGenObj = AsyncGeneratorObject::create(cx, wrapped, generatorVal);
50
0
    if (!asyncGenObj) {
51
0
        return false;
52
0
    }
53
0
54
0
    // Step 3 (skipped).
55
0
    // Done in AsyncGeneratorObject::create and generator.
56
0
57
0
    // Step 4.
58
0
    args.rval().setObject(*asyncGenObj);
59
0
    return true;
60
0
}
61
62
JSObject*
63
js::WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto)
64
0
{
65
0
    MOZ_ASSERT(unwrapped->isAsync());
66
0
    MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default"
67
0
                      "%FunctionPrototype% fallback in NewFunctionWithProto().");
68
0
69
0
    // Create a new function with AsyncGeneratorPrototype, reusing the name and
70
0
    // the length of `unwrapped`.
71
0
72
0
    RootedAtom funName(cx, unwrapped->explicitName());
73
0
    uint16_t length;
74
0
    if (!JSFunction::getLength(cx, unwrapped, &length)) {
75
0
        return nullptr;
76
0
    }
77
0
78
0
    JSFunction* wrapped = NewFunctionWithProto(cx, WrappedAsyncGenerator, length,
79
0
                                               JSFunction::NATIVE_FUN, nullptr, funName, proto,
80
0
                                               gc::AllocKind::FUNCTION_EXTENDED);
81
0
    if (!wrapped) {
82
0
        return nullptr;
83
0
    }
84
0
85
0
    if (unwrapped->hasInferredName()) {
86
0
        wrapped->setInferredName(unwrapped->inferredName());
87
0
    }
88
0
89
0
    // Link them to each other to make GetWrappedAsyncGenerator and
90
0
    // GetUnwrappedAsyncGenerator work.
91
0
    unwrapped->setExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped));
92
0
    wrapped->setExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT, ObjectValue(*unwrapped));
93
0
94
0
    return wrapped;
95
0
}
96
97
JSObject*
98
js::WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped)
99
0
{
100
0
    RootedObject proto(cx, GlobalObject::getOrCreateAsyncGenerator(cx, cx->global()));
101
0
    if (!proto) {
102
0
        return nullptr;
103
0
    }
104
0
105
0
    return WrapAsyncGeneratorWithProto(cx, unwrapped, proto);
106
0
}
107
108
bool
109
js::IsWrappedAsyncGenerator(JSFunction* fun)
110
36
{
111
36
    return fun->maybeNative() == WrappedAsyncGenerator;
112
36
}
113
114
JSFunction*
115
js::GetWrappedAsyncGenerator(JSFunction* unwrapped)
116
0
{
117
0
    MOZ_ASSERT(unwrapped->isAsync());
118
0
    return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT).toObject().as<JSFunction>();
119
0
}
120
121
JSFunction*
122
js::GetUnwrappedAsyncGenerator(JSFunction* wrapped)
123
0
{
124
0
    MOZ_ASSERT(IsWrappedAsyncGenerator(wrapped));
125
0
    JSFunction* unwrapped = &wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT)
126
0
                            .toObject().as<JSFunction>();
127
0
    MOZ_ASSERT(unwrapped->isAsync());
128
0
    return unwrapped;
129
0
}
130
131
// Async Iteration proposal 4.1.1 Await Fulfilled Functions.
132
MOZ_MUST_USE bool
133
js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
134
                                   HandleValue value)
135
0
{
136
0
    return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Normal, value);
137
0
}
138
139
// Async Iteration proposal 4.1.2 Await Rejected Functions.
140
MOZ_MUST_USE bool
141
js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
142
                                  HandleValue reason)
143
0
{
144
0
    return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
145
0
}
146
147
// Async Iteration proposal 11.4.3.7 step 8.d-e.
148
MOZ_MUST_USE bool
149
js::AsyncGeneratorYieldReturnAwaitedFulfilled(JSContext* cx,
150
                                              Handle<AsyncGeneratorObject*> asyncGenObj,
151
                                              HandleValue value)
152
0
{
153
0
    return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Return, value);
154
0
}
155
156
// Async Iteration proposal 11.4.3.7 step 8.d-e.
157
MOZ_MUST_USE bool
158
js::AsyncGeneratorYieldReturnAwaitedRejected(JSContext* cx,
159
                                             Handle<AsyncGeneratorObject*> asyncGenObj,
160
                                             HandleValue reason)
161
0
{
162
0
    return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
163
0
}
164
165
const Class AsyncFromSyncIteratorObject::class_ = {
166
    "AsyncFromSyncIteratorObject",
167
    JSCLASS_HAS_RESERVED_SLOTS(AsyncFromSyncIteratorObject::Slots)
168
};
169
170
// Async Iteration proposal 11.1.3.1.
171
JSObject*
172
js::CreateAsyncFromSyncIterator(JSContext* cx, HandleObject iter, HandleValue nextMethod)
173
0
{
174
0
    // Step 1 (implicit).
175
0
    // Done in bytecode emitted by emitAsyncIterator.
176
0
177
0
    // Steps 2-4.
178
0
    return AsyncFromSyncIteratorObject::create(cx, iter, nextMethod);
179
0
}
180
181
// Async Iteration proposal 11.1.3.1 steps 2-4.
182
/* static */ JSObject*
183
AsyncFromSyncIteratorObject::create(JSContext* cx, HandleObject iter, HandleValue nextMethod)
184
0
{
185
0
    // Step 2.
186
0
    RootedObject proto(cx, GlobalObject::getOrCreateAsyncFromSyncIteratorPrototype(cx,
187
0
                                                                                   cx->global()));
188
0
    if (!proto) {
189
0
        return nullptr;
190
0
    }
191
0
192
0
    AsyncFromSyncIteratorObject* asyncIter =
193
0
        NewObjectWithGivenProto<AsyncFromSyncIteratorObject>(cx, proto);
194
0
    if (!asyncIter) {
195
0
        return nullptr;
196
0
    }
197
0
198
0
    // Step 3.
199
0
    asyncIter->init(iter, nextMethod);
200
0
201
0
    // Step 4.
202
0
    return asyncIter;
203
0
}
204
205
// Async Iteration proposal 11.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next.
206
static bool
207
AsyncFromSyncIteratorNext(JSContext* cx, unsigned argc, Value* vp)
208
0
{
209
0
    CallArgs args = CallArgsFromVp(argc, vp);
210
0
    return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Normal);
211
0
}
212
213
// Async Iteration proposal 11.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return.
214
static bool
215
AsyncFromSyncIteratorReturn(JSContext* cx, unsigned argc, Value* vp)
216
0
{
217
0
    CallArgs args = CallArgsFromVp(argc, vp);
218
0
    return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Return);
219
0
}
220
221
// Async Iteration proposal 11.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw.
222
static bool
223
AsyncFromSyncIteratorThrow(JSContext* cx, unsigned argc, Value* vp)
224
0
{
225
0
    CallArgs args = CallArgsFromVp(argc, vp);
226
0
    return AsyncFromSyncIteratorMethod(cx, args, CompletionKind::Throw);
227
0
}
228
229
// Async Iteration proposal 11.4.1.2 AsyncGenerator.prototype.next.
230
static bool
231
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
232
0
{
233
0
    CallArgs args = CallArgsFromVp(argc, vp);
234
0
235
0
    // Steps 1-3.
236
0
    return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Normal, args.get(0),
237
0
                                 args.rval());
238
0
}
239
240
// Async Iteration proposal 11.4.1.3 AsyncGenerator.prototype.return.
241
static bool
242
AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
243
0
{
244
0
    CallArgs args = CallArgsFromVp(argc, vp);
245
0
246
0
    // Steps 1-3.
247
0
    return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Return, args.get(0),
248
0
                                 args.rval());
249
0
}
250
251
// Async Iteration proposal 11.4.1.4 AsyncGenerator.prototype.throw.
252
static bool
253
AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp)
254
0
{
255
0
    CallArgs args = CallArgsFromVp(argc, vp);
256
0
257
0
    // Steps 1-3.
258
0
    return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Throw, args.get(0),
259
0
                                 args.rval());
260
0
}
261
262
const Class AsyncGeneratorObject::class_ = {
263
    "AsyncGenerator",
264
    JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorObject::Slots)
265
};
266
267
// ES 2017 draft 9.1.13.
268
// OrdinaryCreateFromConstructor specialized for AsyncGeneratorObjects.
269
static AsyncGeneratorObject*
270
OrdinaryCreateFromConstructorAsynGen(JSContext* cx, HandleFunction fun)
271
0
{
272
0
    // Step 1 (skipped).
273
0
274
0
    // Step 2.
275
0
    RootedValue protoVal(cx);
276
0
    if (!GetProperty(cx, fun, fun, cx->names().prototype, &protoVal)) {
277
0
        return nullptr;
278
0
    }
279
0
280
0
    RootedObject proto(cx, protoVal.isObject() ? &protoVal.toObject() : nullptr);
281
0
    if (!proto) {
282
0
        proto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, cx->global());
283
0
        if (!proto) {
284
0
            return nullptr;
285
0
        }
286
0
    }
287
0
288
0
    // Step 3.
289
0
    return NewObjectWithGivenProto<AsyncGeneratorObject>(cx, proto);
290
0
}
291
292
/* static */ AsyncGeneratorObject*
293
AsyncGeneratorObject::create(JSContext* cx, HandleFunction asyncGen, HandleValue generatorVal)
294
0
{
295
0
    MOZ_ASSERT(generatorVal.isObject());
296
0
    MOZ_ASSERT(generatorVal.toObject().is<GeneratorObject>());
297
0
298
0
    AsyncGeneratorObject* asyncGenObj = OrdinaryCreateFromConstructorAsynGen(cx, asyncGen);
299
0
    if (!asyncGenObj) {
300
0
        return nullptr;
301
0
    }
302
0
303
0
    // Async Iteration proposal 6.4.3.2 AsyncGeneratorStart.
304
0
    // Step 6.
305
0
    asyncGenObj->setGenerator(generatorVal);
306
0
307
0
    // Step 7.
308
0
    asyncGenObj->setSuspendedStart();
309
0
310
0
    // Step 8.
311
0
    asyncGenObj->clearSingleQueueRequest();
312
0
313
0
    asyncGenObj->clearCachedRequest();
314
0
315
0
    return asyncGenObj;
316
0
}
317
318
/* static */ AsyncGeneratorRequest*
319
AsyncGeneratorObject::createRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
320
                                    CompletionKind completionKind, HandleValue completionValue,
321
                                    Handle<PromiseObject*> promise)
322
0
{
323
0
    if (!asyncGenObj->hasCachedRequest()) {
324
0
        return AsyncGeneratorRequest::create(cx, completionKind, completionValue, promise);
325
0
    }
326
0
327
0
    AsyncGeneratorRequest* request = asyncGenObj->takeCachedRequest();
328
0
    request->init(completionKind, completionValue, promise);
329
0
    return request;
330
0
}
331
332
/* static */ MOZ_MUST_USE bool
333
AsyncGeneratorObject::enqueueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
334
                                     Handle<AsyncGeneratorRequest*> request)
335
0
{
336
0
    if (asyncGenObj->isSingleQueue()) {
337
0
        if (asyncGenObj->isSingleQueueEmpty()) {
338
0
            asyncGenObj->setSingleQueueRequest(request);
339
0
            return true;
340
0
        }
341
0
342
0
        RootedNativeObject queue(cx, NewList(cx));
343
0
        if (!queue) {
344
0
            return false;
345
0
        }
346
0
347
0
        RootedValue requestVal(cx, ObjectValue(*asyncGenObj->singleQueueRequest()));
348
0
        if (!AppendToList(cx, queue, requestVal)) {
349
0
            return false;
350
0
        }
351
0
        requestVal = ObjectValue(*request);
352
0
        if (!AppendToList(cx, queue, requestVal)) {
353
0
            return false;
354
0
        }
355
0
356
0
        asyncGenObj->setQueue(queue);
357
0
        return true;
358
0
    }
359
0
360
0
    RootedNativeObject queue(cx, asyncGenObj->queue());
361
0
    RootedValue requestVal(cx, ObjectValue(*request));
362
0
    return AppendToList(cx, queue, requestVal);
363
0
}
364
365
/* static */ AsyncGeneratorRequest*
366
AsyncGeneratorObject::dequeueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
367
0
{
368
0
    if (asyncGenObj->isSingleQueue()) {
369
0
        AsyncGeneratorRequest* request = asyncGenObj->singleQueueRequest();
370
0
        asyncGenObj->clearSingleQueueRequest();
371
0
        return request;
372
0
    }
373
0
374
0
    RootedNativeObject queue(cx, asyncGenObj->queue());
375
0
    return ShiftFromList<AsyncGeneratorRequest>(cx, queue);
376
0
}
377
378
/* static */ AsyncGeneratorRequest*
379
AsyncGeneratorObject::peekRequest(Handle<AsyncGeneratorObject*> asyncGenObj)
380
0
{
381
0
    if (asyncGenObj->isSingleQueue()) {
382
0
        return asyncGenObj->singleQueueRequest();
383
0
    }
384
0
385
0
    return PeekList<AsyncGeneratorRequest>(asyncGenObj->queue());
386
0
}
387
388
const Class AsyncGeneratorRequest::class_ = {
389
    "AsyncGeneratorRequest",
390
    JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots)
391
};
392
393
// Async Iteration proposal 11.4.3.1.
394
/* static */ AsyncGeneratorRequest*
395
AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind,
396
                              HandleValue completionValue, Handle<PromiseObject*> promise)
397
0
{
398
0
    AsyncGeneratorRequest* request = NewObjectWithGivenProto<AsyncGeneratorRequest>(cx, nullptr);
399
0
    if (!request) {
400
0
        return nullptr;
401
0
    }
402
0
403
0
    request->init(completionKind, completionValue, promise);
404
0
    return request;
405
0
}
406
407
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart steps 5.d-g.
408
static MOZ_MUST_USE bool
409
AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
410
                       HandleValue value)
411
0
{
412
0
    // Step 5.d.
413
0
    asyncGenObj->setCompleted();
414
0
415
0
    // Step 5.e (done in bytecode).
416
0
    // Step 5.f.i (implicit).
417
0
418
0
    // Step 5.g.
419
0
    return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
420
0
}
421
422
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart steps 5.d, f.
423
static MOZ_MUST_USE bool
424
AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
425
0
{
426
0
    // Step 5.d.
427
0
    asyncGenObj->setCompleted();
428
0
429
0
    // Not much we can do about uncatchable exceptions, so just bail.
430
0
    if (!cx->isExceptionPending()) {
431
0
        return false;
432
0
    }
433
0
434
0
    // Step 5.f.i.
435
0
    RootedValue value(cx);
436
0
    if (!GetAndClearException(cx, &value)) {
437
0
        return false;
438
0
    }
439
0
440
0
    // Step 5.f.ii.
441
0
    return AsyncGeneratorReject(cx, asyncGenObj, value);
442
0
}
443
444
// Async Iteration proposal 11.4.3.7 (partially).
445
// Most steps are done in generator.
446
static MOZ_MUST_USE bool
447
AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value)
448
0
{
449
0
    // Step 5 is done in bytecode.
450
0
451
0
    // Step 6.
452
0
    asyncGenObj->setSuspendedYield();
453
0
454
0
    // Step 9.
455
0
    return AsyncGeneratorResolve(cx, asyncGenObj, value, false);
456
0
}
457
458
// Async Iteration proposal 4.1 Await steps 2-9.
459
// Async Iteration proposal 8.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
460
// Async Iteration proposal 11.4.3.2 AsyncGeneratorStart step 5.f-g.
461
// Async Iteration proposal 11.4.3.5 AsyncGeneratorResumeNext
462
//   steps 12-14, 16-20.
463
// Execution context switching is handled in generator.
464
MOZ_MUST_USE bool
465
js::AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
466
                         CompletionKind completionKind, HandleValue argument)
467
0
{
468
0
    RootedValue generatorVal(cx, asyncGenObj->generatorVal());
469
0
470
0
    // 11.4.3.5 steps 12-14, 16-20.
471
0
    HandlePropertyName funName = completionKind == CompletionKind::Normal
472
0
                                 ? cx->names().GeneratorNext
473
0
                                 : completionKind == CompletionKind::Throw
474
0
                                 ? cx->names().GeneratorThrow
475
0
                                 : cx->names().GeneratorReturn;
476
0
    FixedInvokeArgs<1> args(cx);
477
0
    args[0].set(argument);
478
0
    RootedValue result(cx);
479
0
    if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) {
480
0
        // 11.4.3.2 step 5.d, f.
481
0
        return AsyncGeneratorThrown(cx, asyncGenObj);
482
0
    }
483
0
484
0
    // 4.1 steps 2-9.
485
0
    if (asyncGenObj->generatorObj()->isAfterAwait()) {
486
0
        return AsyncGeneratorAwait(cx, asyncGenObj, result);
487
0
    }
488
0
489
0
    // The following code corresponds to the following 3 cases:
490
0
    //   * yield
491
0
    //   * yield*
492
0
    //   * return
493
0
    // For yield and return, property access is done on an internal result
494
0
    // object and it's not observable.
495
0
    // For yield*, it's done on a possibly user-provided result object, and
496
0
    // it's observable.
497
0
    //
498
0
    // Note that IteratorComplete steps in 8.2.1 are done in bytecode.
499
0
500
0
    // 8.2.1 yield* steps 6.a.vii, 6.b.ii.7, 6.c.ix.
501
0
    RootedObject resultObj(cx, &result.toObject());
502
0
    RootedValue value(cx);
503
0
    if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value)) {
504
0
        return false;
505
0
    }
506
0
507
0
    if (asyncGenObj->generatorObj()->isAfterYield()) {
508
0
        return AsyncGeneratorYield(cx, asyncGenObj, value);
509
0
    }
510
0
511
0
    // 11.4.3.2 step 5.d-g.
512
0
    return AsyncGeneratorReturned(cx, asyncGenObj, value);
513
0
}
514
515
static const JSFunctionSpec async_iterator_proto_methods[] = {
516
    JS_SELF_HOSTED_SYM_FN(asyncIterator, "AsyncIteratorIdentity", 0, 0),
517
    JS_FS_END
518
};
519
520
static const JSFunctionSpec async_from_sync_iter_methods[] = {
521
    JS_FN("next", AsyncFromSyncIteratorNext, 1, 0),
522
    JS_FN("throw", AsyncFromSyncIteratorThrow, 1, 0),
523
    JS_FN("return", AsyncFromSyncIteratorReturn, 1, 0),
524
    JS_FS_END
525
};
526
527
static const JSFunctionSpec async_generator_methods[] = {
528
    JS_FN("next", AsyncGeneratorNext, 1, 0),
529
    JS_FN("throw", AsyncGeneratorThrow, 1, 0),
530
    JS_FN("return", AsyncGeneratorReturn, 1, 0),
531
    JS_FS_END
532
};
533
534
/* static */ MOZ_MUST_USE bool
535
GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
536
0
{
537
0
    if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject()) {
538
0
        return true;
539
0
    }
540
0
541
0
    // Async Iteration proposal 11.1.2 %AsyncIteratorPrototype%.
542
0
    RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
543
0
    if (!asyncIterProto) {
544
0
        return false;
545
0
    }
546
0
    if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods)) {
547
0
        return false;
548
0
    }
549
0
550
0
    // Async Iteration proposal 11.1.3.2 %AsyncFromSyncIteratorPrototype%.
551
0
    RootedObject asyncFromSyncIterProto(
552
0
        cx, GlobalObject::createBlankPrototypeInheriting(cx, &PlainObject::class_,
553
0
                                                         asyncIterProto));
554
0
    if (!asyncFromSyncIterProto) {
555
0
        return false;
556
0
    }
557
0
    if (!DefinePropertiesAndFunctions(cx, asyncFromSyncIterProto, nullptr,
558
0
                                      async_from_sync_iter_methods) ||
559
0
        !DefineToStringTag(cx, asyncFromSyncIterProto, cx->names().AsyncFromSyncIterator))
560
0
    {
561
0
        return false;
562
0
    }
563
0
564
0
    // Async Iteration proposal 11.4.1 %AsyncGeneratorPrototype%.
565
0
    RootedObject asyncGenProto(
566
0
        cx, GlobalObject::createBlankPrototypeInheriting(cx, &PlainObject::class_,
567
0
                                                         asyncIterProto));
568
0
    if (!asyncGenProto) {
569
0
        return false;
570
0
    }
571
0
    if (!DefinePropertiesAndFunctions(cx, asyncGenProto, nullptr, async_generator_methods) ||
572
0
        !DefineToStringTag(cx, asyncGenProto, cx->names().AsyncGenerator))
573
0
    {
574
0
        return false;
575
0
    }
576
0
577
0
    // Async Iteration proposal 11.3.3 %AsyncGenerator%.
578
0
    RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
579
0
    if (!asyncGenerator) {
580
0
        return false;
581
0
    }
582
0
    if (!JSObject::setDelegate(cx, asyncGenerator)) {
583
0
        return false;
584
0
    }
585
0
    if (!LinkConstructorAndPrototype(cx, asyncGenerator, asyncGenProto, JSPROP_READONLY,
586
0
                                     JSPROP_READONLY) ||
587
0
        !DefineToStringTag(cx, asyncGenerator, cx->names().AsyncGeneratorFunction))
588
0
    {
589
0
        return false;
590
0
    }
591
0
592
0
    RootedValue function(cx, global->getConstructor(JSProto_Function));
593
0
    if (!function.toObjectOrNull()) {
594
0
        return false;
595
0
    }
596
0
    RootedObject proto(cx, &function.toObject());
597
0
    RootedAtom name(cx, cx->names().AsyncGeneratorFunction);
598
0
599
0
    // Async Iteration proposal 11.3.2 %AsyncGeneratorFunction%.
600
0
    RootedObject asyncGenFunction(
601
0
        cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR,
602
0
                                 nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject));
603
0
    if (!asyncGenFunction) {
604
0
        return false;
605
0
    }
606
0
    if (!LinkConstructorAndPrototype(cx, asyncGenFunction, asyncGenerator,
607
0
                                     JSPROP_PERMANENT | JSPROP_READONLY, JSPROP_READONLY))
608
0
    {
609
0
        return false;
610
0
    }
611
0
612
0
    global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*asyncIterProto));
613
0
    global->setReservedSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO, ObjectValue(*asyncFromSyncIterProto));
614
0
    global->setReservedSlot(ASYNC_GENERATOR, ObjectValue(*asyncGenerator));
615
0
    global->setReservedSlot(ASYNC_GENERATOR_FUNCTION, ObjectValue(*asyncGenFunction));
616
0
    global->setReservedSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*asyncGenProto));
617
0
    return true;
618
0
}