mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-27 01:33:59 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1754 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1754 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // 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());
 |