// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --allow-natives-syntax function assertThrowsAsync(run, errorType, message) { var actual; var hadValue = false; var hadError = false; var promise = run(); if (typeof promise !== "object" || typeof promise.then !== "function") { throw new MjsUnitAssertionError( `Expected ${run.toString()} to return a Promise, but it returned ` + PrettyPrint(promise)); } promise.then(function(value) { hadValue = true; actual = value; }, function(error) { hadError = true; actual = error; }); assertFalse(hadValue || hadError); %PerformMicrotaskCheckpoint(); if (!hadError) { throw new MjsUnitAssertionError( "Expected " + run + "() to throw " + errorType.name + ", but did not throw."); } if (!(actual instanceof errorType)) throw new MjsUnitAssertionError( "Expected " + run + "() to throw " + errorType.name + ", but threw '" + actual + "'"); if (message !== void 0 && actual.message !== message) throw new MjsUnitAssertionError( "Expected " + run + "() to throw '" + message + "', but threw '" + actual.message + "'"); }; function assertEqualsAsync(expected, run, msg) { var actual; var hadValue = false; var hadError = false; var promise = run(); if (typeof promise !== "object" || typeof promise.then !== "function") { throw new MjsUnitAssertionError( `Expected ${run.toString()} to return a Promise, but it returned ` + `${promise}`); } promise.then(function(value) { hadValue = true; actual = value; }, function(error) { hadError = true; actual = error; }); assertFalse(hadValue || hadError); %PerformMicrotaskCheckpoint(); if (hadError) throw actual; assertTrue( hadValue, "Expected '" + run.toString() + "' to produce a value"); assertEquals(expected, actual, msg); }; class MyError extends Error {}; function Thrower(msg) { throw new MyError(msg); } function Rejecter(msg) { return new Promise(function(resolve, reject) { Promise.resolve().then(function() { reject(new MyError(msg)); }); }); } function Resolver(msg) { return new Promise(function(resolve, reject) { Promise.resolve().then(function() { resolve(msg); }); }); } async function ForAwaitOfValues(it) { let array = []; for await (let x of it) array.push(x); return array; } let log = []; function logIterResult(iter_result) { log.push(iter_result); } function logError(error) { log.push(error); } function AbortUnreachable() { %AbortJS("This code should not be reachable."); } // ---------------------------------------------------------------------------- // Do not install `AsyncGeneratorFunction` constructor on global object assertEquals(undefined, this.AsyncGeneratorFunction); // ---------------------------------------------------------------------------- let AsyncGenerator = Object.getPrototypeOf(async function*() {}); let AsyncGeneratorPrototype = AsyncGenerator.prototype; // %AsyncGenerator% and %AsyncGeneratorPrototype% are both ordinary objects assertEquals("object", typeof AsyncGenerator); assertEquals("object", typeof AsyncGeneratorPrototype); // %AsyncGenerator% <---> %AsyncGeneratorPrototype% circular reference assertEquals(AsyncGenerator, AsyncGeneratorPrototype.constructor); assertEquals(AsyncGeneratorPrototype, AsyncGenerator.prototype); let protoDesc = Object.getOwnPropertyDescriptor(AsyncGenerator, 'prototype'); assertFalse(protoDesc.enumerable); assertFalse(protoDesc.writable); assertTrue(protoDesc.configurable); let ctorDesc = Object.getOwnPropertyDescriptor(AsyncGeneratorPrototype, 'constructor'); assertFalse(ctorDesc.enumerable); assertFalse(ctorDesc.writable); assertTrue(ctorDesc.configurable); // ---------------------------------------------------------------------------- // The AsyncGeneratorFunction Constructor is the %AsyncGeneratorFunction% // intrinsic object and is a subclass of Function. // (proposal-async-iteration/#sec-asyncgeneratorfunction-constructor) let AsyncGeneratorFunction = AsyncGenerator.constructor; assertEquals(Object.getPrototypeOf(AsyncGeneratorFunction), Function); assertEquals(Object.getPrototypeOf(AsyncGeneratorFunction.prototype), Function.prototype); assertTrue(async function*() {} instanceof Function); // ---------------------------------------------------------------------------- // Let functionPrototype be the intrinsic object %AsyncGeneratorPrototype%. async function* asyncGeneratorForProto() {} assertEquals(AsyncGeneratorFunction.prototype, Object.getPrototypeOf(asyncGeneratorForProto)); assertEquals(AsyncGeneratorFunction.prototype, Object.getPrototypeOf(async function*() {})); assertEquals(AsyncGeneratorFunction.prototype, Object.getPrototypeOf({ async* method() {} }.method)); assertEquals(AsyncGeneratorFunction.prototype, Object.getPrototypeOf(AsyncGeneratorFunction())); assertEquals(AsyncGeneratorFunction.prototype, Object.getPrototypeOf(new AsyncGeneratorFunction())); // ---------------------------------------------------------------------------- // AsyncGeneratorFunctionCreate produces a function whose prototype property is // derived from %AsyncGeneratorPrototype% assertEquals(AsyncGeneratorFunction.prototype.prototype, Object.getPrototypeOf(asyncGeneratorForProto.prototype)); assertTrue(asyncGeneratorForProto.hasOwnProperty("prototype")); assertEquals(AsyncGeneratorFunction.prototype.prototype, Object.getPrototypeOf((async function*() {}).prototype)); assertTrue((async function*() {}).hasOwnProperty("prototype")); assertEquals(AsyncGeneratorFunction.prototype.prototype, Object.getPrototypeOf(({ async* method() {} }).method.prototype)); assertTrue(({ async* method() {} }).method.hasOwnProperty("prototype")); assertEquals(AsyncGeneratorFunction.prototype.prototype, Object.getPrototypeOf(AsyncGeneratorFunction().prototype)); assertTrue(AsyncGeneratorFunction().hasOwnProperty("prototype")); assertEquals(AsyncGeneratorFunction.prototype.prototype, Object.getPrototypeOf(new AsyncGeneratorFunction().prototype)); assertTrue(new AsyncGeneratorFunction().hasOwnProperty("prototype")); // ---------------------------------------------------------------------------- // Basic Function.prototype.toString() async function* asyncGeneratorForToString() {} assertEquals("async function* asyncGeneratorForToString() {}", asyncGeneratorForToString.toString()); assertEquals("async function*() {}", async function*() {}.toString()); assertEquals("async function* namedAsyncGeneratorForToString() {}", async function* namedAsyncGeneratorForToString() {}.toString()); assertEquals("async *method() { }", ({ async *method() { } }).method.toString()); assertEquals("async *method() { }", (class { static async *method() { } }).method.toString()); assertEquals("async *method() { }", (new (class { async *method() { } })).method.toString()); assertEquals("async function* anonymous(\n) {\n\n}", AsyncGeneratorFunction().toString()); assertEquals("async function* anonymous(\n) {\n\n}", (new AsyncGeneratorFunction()).toString()); // ---------------------------------------------------------------------------- // AsyncGenerator functions syntactically allow AwaitExpressions assertEquals(1, async function*(a) { await 1; }.length); assertEquals(2, async function*(a, b) { await 1; }.length); assertEquals(1, async function*(a, b = 2) { await 1; }.length); assertEquals(2, async function*(a, b, ...c) { await 1; }.length); assertEquals(1, ({ async* f(a) { await 1; } }).f.length); assertEquals(2, ({ async* f(a, b) { await 1; } }).f.length); assertEquals(1, ({ async* f(a, b = 2) { await 1; } }).f.length); assertEquals(2, ({ async* f(a, b, ...c) { await 1; } }).f.length); assertEquals(1, AsyncGeneratorFunction("a", "await 1").length); assertEquals(2, AsyncGeneratorFunction("a", "b", "await 1").length); assertEquals(1, AsyncGeneratorFunction("a", "b = 2", "await 1").length); assertEquals(2, AsyncGeneratorFunction("a", "b", "...c", "await 1").length); assertEquals(1, (new AsyncGeneratorFunction("a", "await 1")).length); assertEquals(2, (new AsyncGeneratorFunction("a", "b", "await 1")).length); assertEquals(1, (new AsyncGeneratorFunction("a", "b = 2", "await 1")).length); assertEquals(2, (new AsyncGeneratorFunction("a", "b", "...c", "await 1")).length); // ---------------------------------------------------------------------------- // AsyncGenerator functions syntactically allow YieldExpressions assertEquals(1, async function*(a) { yield 1; }.length); assertEquals(2, async function*(a, b) { yield 1; }.length); assertEquals(1, async function*(a, b = 2) { yield 1; }.length); assertEquals(2, async function*(a, b, ...c) { yield 1; }.length); assertEquals(1, ({ async* f(a) { yield 1; } }).f.length); assertEquals(2, ({ async* f(a, b) { yield 1; } }).f.length); assertEquals(1, ({ async* f(a, b = 2) { yield 1; } }).f.length); assertEquals(2, ({ async* f(a, b, ...c) { yield 1; } }).f.length); assertEquals(1, AsyncGeneratorFunction("a", "yield 1").length); assertEquals(2, AsyncGeneratorFunction("a", "b", "yield 1").length); assertEquals(1, AsyncGeneratorFunction("a", "b = 2", "yield 1").length); assertEquals(2, AsyncGeneratorFunction("a", "b", "...c", "yield 1").length); assertEquals(1, (new AsyncGeneratorFunction("a", "yield 1")).length); assertEquals(2, (new AsyncGeneratorFunction("a", "b", "yield 1")).length); assertEquals(1, (new AsyncGeneratorFunction("a", "b = 2", "yield 1")).length); assertEquals(2, (new AsyncGeneratorFunction("a", "b", "...c", "yield 1")).length); // ---------------------------------------------------------------------------- // AsyncGeneratorFunction.prototype[ @@toStringTag ] var descriptor = Object.getOwnPropertyDescriptor(AsyncGeneratorFunction.prototype, Symbol.toStringTag); assertEquals("AsyncGeneratorFunction", descriptor.value); assertEquals(false, descriptor.enumerable); assertEquals(false, descriptor.writable); assertEquals(true, descriptor.configurable); assertEquals(1, AsyncGeneratorFunction.length); // ---------------------------------------------------------------------------- // Let F be ! FunctionAllocate(functionPrototype, Strict, "non-constructor") async function* asyncNonConstructorDecl() {} assertThrows(() => new asyncNonConstructorDecl(), TypeError); assertThrows(() => asyncNonConstructorDecl.caller, TypeError); assertThrows(() => asyncNonConstructorDecl.arguments, TypeError); assertThrows(() => new (async function*() {}), TypeError); assertThrows(() => (async function*() {}).caller, TypeError); assertThrows(() => (async function*() {}).arguments, TypeError); assertThrows( () => new ({ async* nonConstructor() {} }).nonConstructor(), TypeError); assertThrows( () => ({ async* nonConstructor() {} }).nonConstructor.caller, TypeError); assertThrows( () => ({ async* nonConstructor() {} }).nonConstructor.arguments, TypeError); assertThrows( () => new (AsyncGeneratorFunction("nonconstructor"))(), TypeError); assertThrows( () => AsyncGeneratorFunction("nonconstructor").caller, TypeError); assertThrows( () => AsyncGeneratorFunction("nonconstructor").arguments, TypeError); assertThrows( () => new (new AsyncGeneratorFunction("nonconstructor"))(), TypeError); assertThrows( () => (new AsyncGeneratorFunction("nonconstructor")).caller, TypeError); assertThrows( () => (new AsyncGeneratorFunction("nonconstructor")).arguments, TypeError); // ---------------------------------------------------------------------------- // Empty functions async function* emptyAsyncGenerator() {} let it = emptyAsyncGenerator(); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function* emptyAsyncGeneratorExpr() { })(); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { } }).method(); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(``)(); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(``))(); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level ReturnStatement async function* asyncGeneratorForReturn() { return "boop1"; throw "(unreachble)"; } it = asyncGeneratorForReturn(); assertEqualsAsync({ value: "boop1", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { return "boop2"; throw "(unreachable)"; })(); assertEqualsAsync({ value: "boop2", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { return "boop3"; throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "boop3", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(` return "boop4"; throw "(unreachable)";`)(); assertEqualsAsync({ value: "boop4", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` return "boop5"; throw "(unreachable)";`))(); assertEqualsAsync({ value: "boop5", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level ReturnStatement after await async function* asyncGeneratorForReturnAfterAwait() { await 1; return "boop6"; throw "(unreachable)"; } it = asyncGeneratorForReturnAfterAwait(); assertEqualsAsync({ value: "boop6", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { await 1; return "boop7"; throw "(unreachable)"; })(); assertEqualsAsync({ value: "boop7", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { await 1; return "boop8"; throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "boop8", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(` await 1; return "boop9"; throw "(unreachable)"`)(); assertEqualsAsync({ value: "boop9", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` await 1; return "boop10"; throw "(unreachable)"`))(); assertEqualsAsync({ value: "boop10", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level Yields async function* asyncGeneratorForYields() { yield 1; yield await Resolver(2); yield Resolver(3); return 4; throw "(unreachable)"; } it = asyncGeneratorForYields(); assertEqualsAsync([1, 2, 3], () => ForAwaitOfValues(it)); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { yield "cow"; yield await Resolver("bird"); yield await "dog"; yield Resolver("donkey"); return "badger"; throw "(unreachable)"; })(); assertEqualsAsync(["cow", "bird", "dog", "donkey"], () => ForAwaitOfValues(it)); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { yield "A"; yield await Resolver("B"); yield await "C"; yield Resolver("CC"); return "D"; throw "(unreachable)"; } }).method(); assertEqualsAsync(["A", "B", "C", "CC"], () => ForAwaitOfValues(it)); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(` yield "alpha"; yield await Resolver("beta"); yield await "gamma"; yield Resolver("delta"); return "epsilon"; throw "(unreachable)"`)(); assertEqualsAsync(["alpha", "beta", "gamma", "delta"], () => ForAwaitOfValues(it)); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` yield "α"; yield await Resolver("β"); yield await "γ"; yield Resolver("δ"); return "ε"; throw "(unreachable)"`))(); assertEqualsAsync(["α", "β", "γ", "δ"], () => ForAwaitOfValues(it)); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Nested Resume via [AsyncGenerator].next() log = []; async function* asyncGeneratorForNestedResumeNext() { it.next().then(logIterResult, logError); it.next().then(logIterResult, logError); yield "rootbeer"; yield await Resolver("float"); } it = asyncGeneratorForNestedResumeNext(); it.next().then(logIterResult, AbortUnreachable); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "rootbeer", done: false }, { value: "float", done: false }, { value: undefined, done: true } ], log); log = []; let asyncGeneratorExprForNestedResumeNext = async function*() { it.next().then(logIterResult, logError); it.next().then(logIterResult, logError); yield "first"; yield await Resolver("second"); }; it = asyncGeneratorExprForNestedResumeNext(); it.next().then(logIterResult, AbortUnreachable); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "first", done: false }, { value: "second", done: false }, { value: undefined, done: true } ], log); log = []; let asyncGeneratorMethodForNestedResumeNext = ({ async* method() { it.next().then(logIterResult, logError); it.next().then(logIterResult, logError); yield "remember"; yield await Resolver("the cant!"); } }).method; it = asyncGeneratorMethodForNestedResumeNext(); it.next().then(logIterResult, AbortUnreachable); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "remember", done: false }, { value: "the cant!", done: false }, { value: undefined, done: true } ], log); log = []; let asyncGeneratorCallEvalForNestedResumeNext = AsyncGeneratorFunction(` it.next().then(logIterResult, logError); it.next().then(logIterResult, logError); yield "reading"; yield await Resolver("rainbow!");`); it = asyncGeneratorCallEvalForNestedResumeNext(); it.next().then(logIterResult, AbortUnreachable); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "reading", done: false }, { value: "rainbow!", done: false }, { value: undefined, done: true } ], log); log = []; let asyncGeneratorNewEvalForNestedResumeNext = new AsyncGeneratorFunction(` it.next().then(logIterResult, logError); it.next().then(logIterResult, logError); yield 731; yield await Resolver("BB!");`); it = asyncGeneratorNewEvalForNestedResumeNext(); it.next().then(logIterResult, AbortUnreachable); %PerformMicrotaskCheckpoint(); assertEquals([ { value: 731, done: false }, { value: "BB!", done: false }, { value: undefined, done: true } ], log); // ---------------------------------------------------------------------------- // Nested Resume via [AsyncGenerator].throw() log = []; async function* asyncGeneratorForNestedResumeThrow() { try { it.throw(await Rejecter("...")).then(logIterResult, logError); } catch (e) { it.throw("throw2").then(logIterResult, logError); it.next().then(logIterResult, logError); throw "throw1"; } AbortUnreachable(); } it = asyncGeneratorForNestedResumeThrow(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ "throw1", "throw2", { value: undefined, done: true } ], log); log = []; let asyncGeneratorExprForNestedResumeThrow = async function*() { try { it.throw(await Rejecter("...")).then(logIterResult, logError); } catch (e) { it.throw("throw4").then(logIterResult, logError); it.next().then(logIterResult, logError); throw "throw3"; } AbortUnreachable(); }; it = asyncGeneratorExprForNestedResumeThrow(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ "throw3", "throw4", { value: undefined, done: true } ], log); log = []; let asyncGeneratorMethodForNestedResumeThrow = ({ async* method() { try { it.throw(await Rejecter("...")).then(logIterResult, logError); } catch (e) { it.throw("throw6").then(logIterResult, logError); it.next().then(logIterResult, logError); throw "throw5"; } AbortUnreachable(); } }).method; it = asyncGeneratorMethodForNestedResumeThrow(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ "throw5", "throw6", { value: undefined, done: true } ], log); log = []; let asyncGeneratorCallEvalForNestedResumeThrow = AsyncGeneratorFunction(` try { it.throw(await Rejecter("...")).then(logIterResult, logError); } catch (e) { it.throw("throw8").then(logIterResult, logError); it.next().then(logIterResult, logError); throw "throw7"; } AbortUnreachable();`); it = asyncGeneratorCallEvalForNestedResumeThrow(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ "throw7", "throw8", { value: undefined, done: true } ], log); log = []; let asyncGeneratorNewEvalForNestedResumeThrow = new AsyncGeneratorFunction(` try { it.throw(await Rejecter("...")).then(logIterResult, logError); } catch (e) { it.throw("throw10").then(logIterResult, logError); it.next().then(logIterResult, logError); throw "throw9"; } AbortUnreachable();`); it = asyncGeneratorNewEvalForNestedResumeThrow(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ "throw9", "throw10", { value: undefined, done: true } ], log); // ---------------------------------------------------------------------------- // Nested Resume via [AsyncGenerator].return() log = []; async function* asyncGeneratorForNestedResumeReturn() { it.return("step2").then(logIterResult, logError); it.next().then(logIterResult, logError); yield "step1"; AbortUnreachable(); } it = asyncGeneratorForNestedResumeReturn(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "step1", done: false }, { value: "step2", done: true }, { value: undefined, done: true }, ], log); log = []; let asyncGeneratorExprForNestedResumeReturn = async function*() { it.return("step4").then(logIterResult, logError); it.next().then(logIterResult, logError); yield "step3"; }; it = asyncGeneratorExprForNestedResumeReturn(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "step3", done: false }, { value: "step4", done: true }, { value: undefined, done: true }, ], log); log = []; let asyncGeneratorMethodForNestedResumeReturn = ({ async* method() { it.return("step6").then(logIterResult, logError); it.next().then(logIterResult, logError); yield "step5"; } }).method; it = asyncGeneratorMethodForNestedResumeReturn(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "step5", done: false }, { value: "step6", done: true }, { value: undefined, done: true }, ], log); log = []; let asyncGeneratorCallEvalForNestedResumeReturn = AsyncGeneratorFunction(` it.return("step8").then(logIterResult, logError); it.next().then(logIterResult, logError); yield "step7";`); it = asyncGeneratorCallEvalForNestedResumeReturn(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "step7", done: false }, { value: "step8", done: true }, { value: undefined, done: true }, ], log); log = []; let asyncGeneratorNewEvalForNestedResumeReturn = new AsyncGeneratorFunction(` it.return("step10").then(logIterResult, logError); it.next().then(logIterResult, logError); yield "step9";`); it = asyncGeneratorNewEvalForNestedResumeReturn(); it.next().then(logIterResult, logError); %PerformMicrotaskCheckpoint(); assertEquals([ { value: "step9", done: false }, { value: "step10", done: true }, { value: undefined, done: true }, ], log); // ---------------------------------------------------------------------------- // Top-level Yield ThrowStatement async function* asyncGeneratorForYieldThrow() { yield await Thrower("OOPS1"); throw "(unreachable)"; } it = asyncGeneratorForYieldThrow(); assertThrowsAsync(() => it.next(), MyError, "OOPS1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { yield Thrower("OOPS2"); throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "OOPS2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { yield Thrower("OOPS3"); throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "OOPS3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(` yield Thrower("OOPS4"); throw "(unreachable)"`)(); assertThrowsAsync(() => it.next(), MyError, "OOPS4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` yield Thrower("OOPS5"); throw "(unreachable)"`))(); assertThrowsAsync(() => it.next(), MyError, "OOPS5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level Yield Awaited Rejection async function* asyncGeneratorForYieldAwaitedRejection() { yield await Rejecter("OOPS1"); throw "(unreachable)"; } it = asyncGeneratorForYieldAwaitedRejection(); assertThrowsAsync(() => it.next(), MyError, "OOPS1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { yield await Rejecter("OOPS2"); throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "OOPS2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { yield await Rejecter("OOPS3"); throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "OOPS3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = AsyncGeneratorFunction(` yield await Rejecter("OOPS4"); throw "(unreachable)"`)(); assertThrowsAsync(() => it.next(), MyError, "OOPS4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` yield await Rejecter("OOPS5"); throw "(unreachable)"`))(); assertThrowsAsync(() => it.next(), MyError, "OOPS5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level ThrowStatement async function* asyncGeneratorForThrow() { throw new MyError("BOOM1"); throw "(unreachable)"; } it = asyncGeneratorForThrow(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { throw new MyError("BOOM2"); throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { throw new MyError("BOOM3"); throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` throw new MyError("BOOM4"); throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` throw new MyError("BOOM5"); throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level ThrowStatement after Await async function* asyncGeneratorForThrowAfterAwait() { await 1; throw new MyError("BOOM6"); throw "(unreachable)"; } it = asyncGeneratorForThrowAfterAwait(); assertThrowsAsync(() => it.next(), MyError, "BOOM6"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { await 1; throw new MyError("BOOM7"); throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM7"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { await 1; throw new MyError("BOOM8"); throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM8"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` await 1; throw new MyError("BOOM9"); throw "(unreachable)";`))(); assertThrowsAsync(() => it.next(), MyError, "BOOM9"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` await 1; throw new MyError("BOOM10"); throw "(unreachable)";`))(); assertThrowsAsync(() => it.next(), MyError, "BOOM10"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Top-level Awaited rejection async function* asyncGeneratorForAwaitedRejection() { await Rejecter("BOOM11"); throw "(unreachable)"; } it = asyncGeneratorForAwaitedRejection(); assertThrowsAsync(() => it.next(), MyError, "BOOM11"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { await Rejecter("BOOM12"); throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM12"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { await Rejecter("BOOM13"); throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM13"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` await Rejecter("BOOM14"); throw "(unreachable)";`))(); assertThrowsAsync(() => it.next(), MyError, "BOOM14"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (new AsyncGeneratorFunction(` await Rejecter("BOOM15"); throw "(unreachable)";`))(); assertThrowsAsync(() => it.next(), MyError, "BOOM15"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Caught ThrowStatement async function* asyncGeneratorForCaughtThrow() { try { throw new MyError("BOOM1"); } catch (e) { return "caught1"; } throw "(unreachable)"; } it = asyncGeneratorForCaughtThrow(); assertEqualsAsync({ value: "caught1", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { throw new MyError("BOOM2"); } catch (e) { return "caught2"; } throw "(unreachable)"; })(); assertEqualsAsync({ value: "caught2", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { throw new MyError("BOOM3"); } catch (e) { return "caught3"; } throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "caught3", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM4"); } catch (e) { return "caught4"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "caught4", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM5"); } catch (e) { return "caught5"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "caught5", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Caught ThrowStatement and rethrow async function* asyncGeneratorForCaughtRethrow() { try { throw new MyError("BOOM1"); } catch (e) { throw new MyError("RETHROW1"); } throw "(unreachable)"; } it = asyncGeneratorForCaughtRethrow(); assertThrowsAsync(() => it.next(), MyError, "RETHROW1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { throw new MyError("BOOM2"); } catch (e) { throw new MyError("RETHROW2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "RETHROW2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { throw new MyError("BOOM3"); } catch (e) { throw new MyError("RETHROW3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "RETHROW3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM4"); } catch (e) { throw new MyError("RETHROW4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "RETHROW4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM5"); } catch (e) { throw new MyError("RETHROW5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "RETHROW5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ReturnStatement in Try, ReturnStatement in Finally async function* asyncGeneratorForReturnInTryReturnInFinally() { try { return "early1" } finally { return "later1"; } throw "(unreachable)"; } it = asyncGeneratorForReturnInTryReturnInFinally(); assertEqualsAsync({ value: "later1", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { return "early2"; } finally { return "later2"; } throw "(unreachable)"; })(); assertEqualsAsync({ value: "later2", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { return "early3"; } finally { return "later3"; } throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "later3", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early4"; } finally { return "later4"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later4", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early5"; } finally { return "later5"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later5", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ThrowStatement in Try, ReturnStatement in Finally async function* asyncGeneratorForThrowInTryReturnInFinally() { try { throw new MyError("BOOM1"); } finally { return "later1"; } throw "(unreachable)"; } it = asyncGeneratorForThrowInTryReturnInFinally(); assertEqualsAsync({ value: "later1", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { throw new MyError("BOOM2"); } finally { return "later2"; } throw "(unreachable)"; })(); assertEqualsAsync({ value: "later2", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { throw new MyError("BOOM3"); } finally { return "later3"; } throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "later3", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM4"); } finally { return "later4"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later4", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("BOOM5"); } finally { return "later5"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later5", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Awaited Rejection in Try, ReturnStatement in Finally async function* asyncGeneratorForAwaitRejectionInTryReturnInFinally() { try { await Rejecter("BOOM1"); } finally { return "later1"; } throw "(unreachable)"; } it = asyncGeneratorForThrowInTryReturnInFinally(); assertEqualsAsync({ value: "later1", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { await Rejecter("BOOM2"); } finally { return "later2"; } throw "(unreachable)"; })(); assertEqualsAsync({ value: "later2", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { await Rejecter("BOOM3"); } finally { return "later3"; } throw "(unreachable)"; } }).method(); assertEqualsAsync({ value: "later3", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("BOOM4"); } finally { return "later4"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later4", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("BOOM5"); } finally { return "later5"; } throw "(unreachable)";`))() assertEqualsAsync({ value: "later5", done: true }, () => it.next()); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ReturnStatement in Try, ThrowStatement in Finally async function* asyncGeneratorForReturnInTryThrowInFinally() { try { return "early1" } finally { throw new MyError("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForReturnInTryThrowInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { return "early2"; } finally { throw new MyError("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { return "early3"; } finally { throw new MyError("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early4"; } finally { throw new MyError("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early5"; } finally { throw new MyError("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ThrowStatement in Try, ThrowStatement in Finally async function* asyncGeneratorForThrowInTryThrowInFinally() { try { throw new MyError("EARLY1"); } finally { throw new MyError("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForThrowInTryThrowInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { throw new MyError("EARLY2"); } finally { throw new MyError("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { throw new MyError("EARLY3"); } finally { throw new MyError("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("EARLY4"); } finally { throw new MyError("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("EARLY5"); } finally { throw new MyError("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Awaited Rejection in Try, ThrowStatement in Finally async function* asyncGeneratorForAwaitedRejectInTryThrowInFinally() { try { await Rejecter("EARLY1"); } finally { throw new MyError("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForAwaitedRejectInTryThrowInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { await Rejecter("EARLY2"); } finally { throw new MyError("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { await Rejecter("EARLY3"); } finally { throw new MyError("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("EARLY4"); } finally { throw new MyError("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("EARLY5"); } finally { throw new MyError("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ReturnStatement in Try, Awaited Rejection in Finally async function* asyncGeneratorForReturnInTryAwaitedRejectionInFinally() { try { return "early1" } finally { await Rejecter("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForReturnInTryAwaitedRejectionInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { return "early2"; } finally { await Rejecter("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { return "early3"; } finally { await Rejecter("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early4"; } finally { await Rejecter("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { return "early5"; } finally { await Rejecter("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // ThrowStatement in Try, Awaited Rejection in Finally async function* asyncGeneratorForThrowInTryAwaitedRejectionInFinally() { try { throw new MyError("EARLY1"); } finally { await Rejecter("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForThrowInTryAwaitedRejectionInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { throw new MyError("EARLY2"); } finally { await Rejecter("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { throw new MyError("EARLY3"); } finally { await Rejecter("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("EARLY4"); } finally { await Rejecter("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { throw new MyError("EARLY5"); } finally { await Rejecter("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Awaited Rejection in Try, Awaited Rejection in Finally async function* asyncGeneratorForAwaitedRejectInTryAwaitedRejectionInFinally() { try { await Rejecter("EARLY1"); } finally { await Rejecter("BOOM1"); } throw "(unreachable)"; } it = asyncGeneratorForAwaitedRejectInTryAwaitedRejectionInFinally(); assertThrowsAsync(() => it.next(), MyError, "BOOM1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (async function*() { try { await Rejecter("EARLY2"); } finally { await Rejecter("BOOM2"); } throw "(unreachable)"; })(); assertThrowsAsync(() => it.next(), MyError, "BOOM2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = ({ async* method() { try { await Rejecter("EARLY3"); } finally { await Rejecter("BOOM3"); } throw "(unreachable)"; } }).method(); assertThrowsAsync(() => it.next(), MyError, "BOOM3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("EARLY4"); } finally { await Rejecter("BOOM4"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); it = (AsyncGeneratorFunction(` try { await Rejecter("EARLY5"); } finally { await Rejecter("BOOM5"); } throw "(unreachable)";`))() assertThrowsAsync(() => it.next(), MyError, "BOOM5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next()); // ---------------------------------------------------------------------------- // Early errors during parameter initialization async function* asyncGeneratorForParameterInitializationErrors( [...a], b = c, d) { AbortUnreachable(); } assertThrows(() => asyncGeneratorForParameterInitializationErrors(null), TypeError); assertThrows(() => asyncGeneratorForParameterInitializationErrors([]), ReferenceError); let asyncGeneratorExprForParameterInitializationErrors = async function*([...a], b = c, d) { AbortUnreachable(); }; assertThrows(() => asyncGeneratorExprForParameterInitializationErrors(null), TypeError); assertThrows(() => asyncGeneratorExprForParameterInitializationErrors([]), ReferenceError); let asyncGeneratorMethodForParameterInitializationErrors = ({ async* method([...a], b = c, d) { AbortUnreachable(); } }).method; assertThrows(() => asyncGeneratorMethodForParameterInitializationErrors(null), TypeError); assertThrows(() => asyncGeneratorMethodForParameterInitializationErrors([]), ReferenceError); let asyncGeneratorCallEvalForParameterInitializationErrors = AsyncGeneratorFunction("[...a], b = c, d", `AbortUnreachable();`); assertThrows(() => asyncGeneratorCallEvalForParameterInitializationErrors(null), TypeError); assertThrows(() => asyncGeneratorCallEvalForParameterInitializationErrors([]), ReferenceError); let asyncGeneratorNewEvalForParameterInitializationErrors = new AsyncGeneratorFunction("[...a], b = c, d", `AbortUnreachable();`); assertThrows(() => asyncGeneratorNewEvalForParameterInitializationErrors(null), TypeError); assertThrows(() => asyncGeneratorNewEvalForParameterInitializationErrors([]), ReferenceError); // ---------------------------------------------------------------------------- // Invoke [AsyncGenerator].return() when generator is in state suspendedStart async function* asyncGeneratorForReturnSuspendedStart() { AbortUnreachable(); } it = asyncGeneratorForReturnSuspendedStart(); assertEqualsAsync({ value: "ret1", done: true }, () => it.return("ret1")); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (async function*() { AbortUnreachable(); })(); assertEqualsAsync({ value: "ret2", done: true }, () => it.return("ret2")); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = ({ async* method() { AbortUnreachable(); } }).method(); assertEqualsAsync({ value: "ret3", done: true }, () => it.return("ret3")); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (AsyncGeneratorFunction(`AbortUnreachable();`))(); assertEqualsAsync({ value: "ret4", done: true }, () => it.return("ret4")); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (AsyncGeneratorFunction(`AbortUnreachable();`))(); assertEqualsAsync({ value: "ret5", done: true }, () => it.return("ret5")); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); // ---------------------------------------------------------------------------- // Invoke [AsyncGenerator].throw() when generator is in state suspendedStart async function* asyncGeneratorForThrowSuspendedStart() { AbortUnreachable(); } it = asyncGeneratorForReturnSuspendedStart(); assertThrowsAsync(() => it.throw(new MyError("throw1")), MyError, "throw1"); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (async function*() { AbortUnreachable(); })(); assertThrowsAsync(() => it.throw(new MyError("throw2")), MyError, "throw2"); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = ({ async* method() { AbortUnreachable(); } }).method(); assertThrowsAsync(() => it.throw(new MyError("throw3")), MyError, "throw3"); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (AsyncGeneratorFunction(`AbortUnreachable()`))(); assertThrowsAsync(() => it.throw(new MyError("throw4")), MyError, "throw4"); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); it = (AsyncGeneratorFunction(`AbortUnreachable();`))(); assertThrowsAsync(() => it.throw(new MyError("throw5")), MyError, "throw5"); assertEqualsAsync({ value: undefined, done: true }, () => it.next("x")); assertEqualsAsync({ value: "nores", done: true }, () => it.return("nores")); assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores"); // ---------------------------------------------------------------------------- // Simple yield*: log = []; async function* asyncGeneratorYieldStar1() { yield* { get [Symbol.asyncIterator]() { log.push({ name: "get @@asyncIterator" }); return (...args) => { log.push({ name: "call @@asyncIterator", args }); return this; }; }, get [Symbol.iterator]() { log.push({ name: "get @@iterator" }); return (...args) => { log.push({ name: "call @@iterator", args }); return this; } }, get next() { log.push({ name: "get next" }); return (...args) => { log.push({ name: "call next", args }); return { get then() { log.push({ name: "get then" }); return null; }, get value() { log.push({ name: "get value" }); throw (exception = new MyError("AbruptValue!")); }, get done() { log.push({ name: "get done" }); return false; } }; } }, get return() { log.push({ name: "get return" }); return (...args) => { log.push({ name: "call return", args }); return { value: args[0], done: true }; } }, get throw() { log.push({ name: "get throw" }); return (...args) => { log.push({ name: "call throw", args }); throw args[0]; }; }, }; } it = asyncGeneratorYieldStar1(); assertThrowsAsync(() => it.next(), MyError); assertEquals([ { name: "get @@asyncIterator" }, { name: "call @@asyncIterator", args: [] }, { name: "get next" }, { name: "call next", args: [undefined] }, { name: "get then" }, { name: "get done" }, { name: "get value" }, ], log); assertEqualsAsync({ value: undefined, done: true }, () => it.next());