v8/test/mjsunit/harmony/async-generators-basic.js
Caitlin Potter fa0066d170 [async-iteration] implement spec update for yield* in async generators
e3246ad69c
removed some redundancies in yield and yield*.

In particular:
- AsyncGeneratorRawYield becomes unnecessary, and is deleted in this CL
- Parser::RewriteYieldStar() is updated to perform the IteratorValue() algorithm as appropriate

BUG=v8:6187, v8:5855
R=rmcilroy@chromium.org, adamk@chromium.org, littledan@chromium.org, vogelheim@chromium.org

Change-Id: I05e8429b9cbd4531c330ee53a05656b90162064c
Reviewed-on: https://chromium-review.googlesource.com/471806
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Daniel Vogelheim <vogelheim@chromium.org>
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#44649}
2017-04-13 14:32:30 +00:00

1731 lines
55 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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: --harmony-async-iteration --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);
%RunMicrotasks();
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);
%RunMicrotasks();
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 AsyncGeneratorFunction = (async function*() {}).constructor;
// ----------------------------------------------------------------------------
// The AsyncGeneratorFunction Constructor is the %AsyncGeneratorFunction%
// intrinsic object and is a subclass of Function.
// (proposal-async-iteration/#sec-asyncgeneratorfunction-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}",
AsyncGeneratorFunction().toString());
assertEquals("async function* anonymous() {\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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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);
%RunMicrotasks();
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());