mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-28 10:13:55 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			604 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			604 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2016 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
 | |
| 
 | |
| // Do not install `AsyncFunction` constructor on global object
 | |
| 
 | |
| 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 " + PrettyPrint(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);
 | |
| };
 | |
| 
 | |
| assertEquals(undefined, this.AsyncFunction);
 | |
| let AsyncFunction = (async function() {}).constructor;
 | |
| 
 | |
| // The AsyncFunction Constructor is the %AsyncFunction% intrinsic object and
 | |
| // is a subclass of Function.
 | |
| // (https://tc39.github.io/ecmascript-asyncawait/#async-function-constructor)
 | |
| assertEquals(Object.getPrototypeOf(AsyncFunction), Function);
 | |
| assertEquals(Object.getPrototypeOf(AsyncFunction.prototype),
 | |
|              Function.prototype);
 | |
| assertTrue(async function() {} instanceof Function);
 | |
| 
 | |
| 
 | |
| // Let functionPrototype be the intrinsic object %AsyncFunctionPrototype%.
 | |
| async function asyncFunctionForProto() {}
 | |
| assertEquals(AsyncFunction.prototype,
 | |
|              Object.getPrototypeOf(asyncFunctionForProto));
 | |
| assertEquals(AsyncFunction.prototype,
 | |
|              Object.getPrototypeOf(async function() {}));
 | |
| assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(async () => {}));
 | |
| assertEquals(AsyncFunction.prototype,
 | |
|              Object.getPrototypeOf({ async method() {} }.method));
 | |
| assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(AsyncFunction()));
 | |
| assertEquals(AsyncFunction.prototype,
 | |
|              Object.getPrototypeOf(new AsyncFunction()));
 | |
| 
 | |
| // AsyncFunctionCreate does not produce an object with a Prototype
 | |
| assertEquals(undefined, asyncFunctionForProto.prototype);
 | |
| assertEquals(false, asyncFunctionForProto.hasOwnProperty("prototype"));
 | |
| assertEquals(undefined, (async function() {}).prototype);
 | |
| assertEquals(false, (async function() {}).hasOwnProperty("prototype"));
 | |
| assertEquals(undefined, (async() => {}).prototype);
 | |
| assertEquals(false, (async() => {}).hasOwnProperty("prototype"));
 | |
| assertEquals(undefined, ({ async method() {} }).method.prototype);
 | |
| assertEquals(false, ({ async method() {} }).method.hasOwnProperty("prototype"));
 | |
| assertEquals(undefined, AsyncFunction().prototype);
 | |
| assertEquals(false, AsyncFunction().hasOwnProperty("prototype"));
 | |
| assertEquals(undefined, (new AsyncFunction()).prototype);
 | |
| assertEquals(false, (new AsyncFunction()).hasOwnProperty("prototype"));
 | |
| 
 | |
| 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(a) => await 1).length);
 | |
| assertEquals(2, (async(a, b) => await 1).length);
 | |
| assertEquals(1, (async(a, b = 2) => await 1).length);
 | |
| assertEquals(2, (async(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, AsyncFunction("a", "await 1").length);
 | |
| assertEquals(2, AsyncFunction("a", "b", "await 1").length);
 | |
| assertEquals(1, AsyncFunction("a", "b = 2", "await 1").length);
 | |
| assertEquals(2, AsyncFunction("a", "b", "...c", "await 1").length);
 | |
| 
 | |
| assertEquals(1, (new AsyncFunction("a", "await 1")).length);
 | |
| assertEquals(2, (new AsyncFunction("a", "b", "await 1")).length);
 | |
| assertEquals(1, (new AsyncFunction("a", "b = 2", "await 1")).length);
 | |
| assertEquals(2, (new AsyncFunction("a", "b", "...c", "await 1")).length);
 | |
| 
 | |
| // AsyncFunction.prototype[ @@toStringTag ]
 | |
| var descriptor =
 | |
|     Object.getOwnPropertyDescriptor(AsyncFunction.prototype,
 | |
|                                     Symbol.toStringTag);
 | |
| assertEquals("AsyncFunction", descriptor.value);
 | |
| assertEquals(false, descriptor.enumerable);
 | |
| assertEquals(false, descriptor.writable);
 | |
| assertEquals(true, descriptor.configurable);
 | |
| 
 | |
| assertEquals(1, AsyncFunction.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 (() => "not a constructor!"), TypeError);
 | |
| assertThrows(() => (() => 1).caller, TypeError);
 | |
| assertThrows(() => (() => 1).arguments, TypeError);
 | |
| 
 | |
| assertThrows(() => new (AsyncFunction()), TypeError);
 | |
| assertThrows(() => AsyncFunction().caller, TypeError);
 | |
| assertThrows(() => AsyncFunction().arguments, TypeError);
 | |
| 
 | |
| assertThrows(() => new (new AsyncFunction()), TypeError);
 | |
| assertThrows(() => (new AsyncFunction()).caller, TypeError);
 | |
| assertThrows(() => (new AsyncFunction()).arguments, TypeError);
 | |
| 
 | |
| // Normal completion
 | |
| async function asyncDecl() { return "test"; }
 | |
| assertEqualsAsync("test", asyncDecl);
 | |
| assertEqualsAsync("test2", async function() { return "test2"; });
 | |
| assertEqualsAsync("test3", async () => "test3");
 | |
| assertEqualsAsync("test4", () => ({ async f() { return "test4"; } }).f());
 | |
| assertEqualsAsync("test5", () => AsyncFunction("no", "return 'test' + no;")(5));
 | |
| assertEqualsAsync("test6",
 | |
|                   () => (new AsyncFunction("no", "return 'test' + no;"))(6));
 | |
| 
 | |
| class MyError extends Error {};
 | |
| 
 | |
| // Throw completion
 | |
| async function asyncDeclThrower(e) { throw new MyError(e); }
 | |
| assertThrowsAsync(() => asyncDeclThrower("boom!"), MyError, "boom!");
 | |
| assertThrowsAsync(
 | |
|   () => (async function(e) { throw new MyError(e); })("boom!!!"),
 | |
|   MyError, "boom!!!");
 | |
| assertThrowsAsync(
 | |
|   () => (async e => { throw new MyError(e) })("boom!!"), MyError, "boom!!");
 | |
| assertThrowsAsync(
 | |
|   () => ({ async thrower(e) { throw new MyError(e); } }).thrower("boom!1!"),
 | |
|   MyError, "boom!1!");
 | |
| assertThrowsAsync(
 | |
|   () => AsyncFunction("msg", "throw new MyError(msg)")("boom!2!!"),
 | |
|   MyError, "boom!2!!");
 | |
| assertThrowsAsync(
 | |
|   () => (new AsyncFunction("msg", "throw new MyError(msg)"))("boom!2!!!"),
 | |
|   MyError, "boom!2!!!");
 | |
| 
 | |
| function resolveLater(value) { return Promise.resolve(value); }
 | |
| function rejectLater(error) { return Promise.reject(error); }
 | |
| 
 | |
| // Resume after Normal completion
 | |
| var log = [];
 | |
| async function resumeAfterNormal(value) {
 | |
|   log.push("start:" + value);
 | |
|   value = await resolveLater(value + 1);
 | |
|   log.push("resume:" + value);
 | |
|   value = await resolveLater(value + 1);
 | |
|   log.push("resume:" + value);
 | |
|   return value + 1;
 | |
| }
 | |
| 
 | |
| assertEqualsAsync(4, () => resumeAfterNormal(1));
 | |
| assertEquals("start:1 resume:2 resume:3", log.join(" "));
 | |
| 
 | |
| var O = {
 | |
|   async resumeAfterNormal(value) {
 | |
|     log.push("start:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     return value + 1;
 | |
|   }
 | |
| };
 | |
| log = [];
 | |
| assertEqualsAsync(5, () => O.resumeAfterNormal(2));
 | |
| assertEquals("start:2 resume:3 resume:4", log.join(" "));
 | |
| 
 | |
| var resumeAfterNormalArrow = async (value) => {
 | |
|   log.push("start:" + value);
 | |
|   value = await resolveLater(value + 1);
 | |
|   log.push("resume:" + value);
 | |
|   value = await resolveLater(value + 1);
 | |
|   log.push("resume:" + value);
 | |
|   return value + 1;
 | |
| };
 | |
| log = [];
 | |
| assertEqualsAsync(6, () => resumeAfterNormalArrow(3));
 | |
| assertEquals("start:3 resume:4 resume:5", log.join(" "));
 | |
| 
 | |
| var resumeAfterNormalEval = AsyncFunction("value", `
 | |
|     log.push("start:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     return value + 1;`);
 | |
| log = [];
 | |
| assertEqualsAsync(7, () => resumeAfterNormalEval(4));
 | |
| assertEquals("start:4 resume:5 resume:6", log.join(" "));
 | |
| 
 | |
| var resumeAfterNormalNewEval = new AsyncFunction("value", `
 | |
|     log.push("start:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     value = await resolveLater(value + 1);
 | |
|     log.push("resume:" + value);
 | |
|     return value + 1;`);
 | |
| log = [];
 | |
| assertEqualsAsync(8, () => resumeAfterNormalNewEval(5));
 | |
| assertEquals("start:5 resume:6 resume:7", log.join(" "));
 | |
| 
 | |
| // Resume after Throw completion
 | |
| async function resumeAfterThrow(value) {
 | |
|   log.push("start:" + value);
 | |
|   try {
 | |
|     value = await rejectLater("throw1");
 | |
|   } catch (e) {
 | |
|     log.push("resume:" + e);
 | |
|   }
 | |
|   try {
 | |
|     value = await rejectLater("throw2");
 | |
|   } catch (e) {
 | |
|     log.push("resume:" + e);
 | |
|   }
 | |
|   return value + 1;
 | |
| }
 | |
| 
 | |
| log = [];
 | |
| assertEqualsAsync(2, () => resumeAfterThrow(1));
 | |
| assertEquals("start:1 resume:throw1 resume:throw2", log.join(" "));
 | |
| 
 | |
| var O = {
 | |
|   async resumeAfterThrow(value) {
 | |
|     log.push("start:" + value);
 | |
|     try {
 | |
|       value = await rejectLater("throw1");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     try {
 | |
|       value = await rejectLater("throw2");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     return value + 1;
 | |
|   }
 | |
| }
 | |
| log = [];
 | |
| assertEqualsAsync(3, () => O.resumeAfterThrow(2));
 | |
| assertEquals("start:2 resume:throw1 resume:throw2", log.join(" "));
 | |
| 
 | |
| var resumeAfterThrowArrow = async (value) => {
 | |
|   log.push("start:" + value);
 | |
|   try {
 | |
|     value = await rejectLater("throw1");
 | |
|   } catch (e) {
 | |
|     log.push("resume:" + e);
 | |
|   }
 | |
|   try {
 | |
|     value = await rejectLater("throw2");
 | |
|   } catch (e) {
 | |
|     log.push("resume:" + e);
 | |
|   }
 | |
|  return value + 1;
 | |
| };
 | |
| 
 | |
| log = [];
 | |
| 
 | |
| assertEqualsAsync(4, () => resumeAfterThrowArrow(3));
 | |
| assertEquals("start:3 resume:throw1 resume:throw2", log.join(" "));
 | |
| 
 | |
| var resumeAfterThrowEval = AsyncFunction("value", `
 | |
|     log.push("start:" + value);
 | |
|     try {
 | |
|       value = await rejectLater("throw1");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     try {
 | |
|       value = await rejectLater("throw2");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     return value + 1;`);
 | |
| log = [];
 | |
| assertEqualsAsync(5, () => resumeAfterThrowEval(4));
 | |
| assertEquals("start:4 resume:throw1 resume:throw2", log.join(" "));
 | |
| 
 | |
| var resumeAfterThrowNewEval = new AsyncFunction("value", `
 | |
|     log.push("start:" + value);
 | |
|     try {
 | |
|       value = await rejectLater("throw1");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     try {
 | |
|       value = await rejectLater("throw2");
 | |
|     } catch (e) {
 | |
|       log.push("resume:" + e);
 | |
|     }
 | |
|     return value + 1;`);
 | |
| log = [];
 | |
| assertEqualsAsync(6, () => resumeAfterThrowNewEval(5));
 | |
| assertEquals("start:5 resume:throw1 resume:throw2", log.join(" "));
 | |
| 
 | |
| async function foo() {}
 | |
| assertEquals("async function foo() {}", foo.toString());
 | |
| assertEquals("async function () {}", async function () {}.toString());
 | |
| assertEquals("async x => x", (async x => x).toString());
 | |
| assertEquals("async x => { return x }", (async x => { return x }).toString());
 | |
| class AsyncMethod { async foo() { } }
 | |
| assertEquals("async foo() { }",
 | |
|              Function.prototype.toString.call(AsyncMethod.prototype.foo));
 | |
| assertEquals("async foo() { }",
 | |
|              Function.prototype.toString.call({async foo() { }}.foo));
 | |
| 
 | |
| // Async functions are not constructible
 | |
| assertThrows(() => class extends (async function() {}) {}, TypeError);
 | |
| 
 | |
| // Regress v8:5148
 | |
| assertEqualsAsync("1", () => (async({ a = NaN }) => a)({ a: "1" }));
 | |
| assertEqualsAsync(
 | |
|     "10", () => (async(foo, { a = NaN }) => foo + a)("1", { a: "0" }));
 | |
| assertEqualsAsync("2", () => (async({ a = "2" }) => a)({ a: undefined }));
 | |
| assertEqualsAsync(
 | |
|     "20", () => (async(foo, { a = "0" }) => foo + a)("2", { a: undefined }));
 | |
| assertThrows(() => eval("async({ foo = 1 })"), SyntaxError);
 | |
| assertThrows(() => eval("async(a, { foo = 1 })"), SyntaxError);
 | |
| 
 | |
| // https://bugs.chromium.org/p/chromium/issues/detail?id=638019
 | |
| async function gaga() {
 | |
|   let i = 1;
 | |
|   while (i-- > 0) { await 42 }
 | |
| }
 | |
| assertDoesNotThrow(gaga);
 | |
| 
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "a", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "a", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return await Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["a", "b", "c"], log);
 | |
| }
 | |
| 
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "c", "a"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "a", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return await Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["a", "b", "c"], log);
 | |
| }
 | |
| 
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "a", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "a", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return await Promise.resolve().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["a", "b", "c"], log);
 | |
| }
 | |
| 
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "c", "a"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["b", "c", "a"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   let log = [];
 | |
|   async function foo() {
 | |
|     try {
 | |
|       return await Promise.resolve().then().then(() => log.push("a"))
 | |
|     } finally {
 | |
|       return log.push("b");
 | |
|     }
 | |
|   }
 | |
|   foo().then(() => log.push("c"));
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals(["a", "b", "c"], log);
 | |
| }
 | |
| 
 | |
| {
 | |
|   function f1() {
 | |
|     var x;
 | |
|     with ({get await() { return [42] }}) {
 | |
|       x = await
 | |
|       [0];
 | |
|     };
 | |
|     return x;
 | |
|   }
 | |
| 
 | |
|   assertEquals(42, f1());
 | |
|   async function f2() {
 | |
|     var x;
 | |
|     with ({get await() { return [42] }}) {
 | |
|       x = await
 | |
|       [0];
 | |
|     };
 | |
|     return x;
 | |
|   }
 | |
| 
 | |
|   var ans;
 | |
|   f2().then(x => ans = x).catch(e => ans = e);
 | |
|   %PerformMicrotaskCheckpoint();
 | |
|   assertEquals([0], ans);
 | |
| }
 | |
| 
 | |
| {
 | |
|   function f1() {
 | |
|     var x, y;
 | |
|     with ({get await() { return [42] }}) {
 | |
|       x = await
 | |
|       y = 1
 | |
|     };
 | |
|     return y;
 | |
|   }
 | |
| 
 | |
|   assertEquals(1, f1());
 | |
| }
 |