v8/test/mjsunit/harmony/async-generators-basic.js
tzik 07011cc4f0 Replace %RunMicrotasks with %PerformMicrotaskCheckpoint
This replaces Runtime_RunMicrotasks with Runtime_PerformMicrotaskCheckpoint.

RunMicrotasks forcibly runs Microtasks even when the microtasks are suppressed,
and may causes nested Microtasks in a problematic way. E.g. that confuses
v8::MicrotasksScope::IsRunningMicrotasks() and GetEnteredOrMicrotaskContext().

OTOH, PerformMicrotaskCheckpoint() doesn't run cause the failure as it
respects the microtask suppressions.

As all existing tests don't call RunMicrotasks() in the suppressed situation
(like Promise.resolve().then(()=>{%RunMicrotasks();})), this change should
not affect to these tests.

Change-Id: Ib043a0cc8e482e022d375084d65ea98a6f54ef3d
Reviewed-on: https://chromium-review.googlesource.com/c/1360095
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58068}
2018-12-06 11:10:18 +00:00

1754 lines
56 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: --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());