| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Flags: --harmony-async-await --allow-natives-syntax | |
| 6 | |
| 7 // Do not install `AsyncFunction` constructor on global object | |
| 8 | |
| 9 function assertThrowsAsync(run, errorType, message) { | |
| 10 var actual; | |
| 11 var hadValue = false; | |
| 12 var hadError = false; | |
| 13 var promise = run(); | |
| 14 | |
| 15 if (typeof promise !== "object" || typeof promise.then !== "function") { | |
| 16 throw new MjsUnitAssertionError( | |
| 17 "Expected " + run.toString() + | |
| 18 " to return a Promise, but it returned " + PrettyPrint(promise)); | |
| 19 } | |
| 20 | |
| 21 promise.then(function(value) { hadValue = true; actual = value; }, | |
| 22 function(error) { hadError = true; actual = error; }); | |
| 23 | |
| 24 assertFalse(hadValue || hadError); | |
| 25 | |
| 26 %RunMicrotasks(); | |
| 27 | |
| 28 if (!hadError) { | |
| 29 throw new MjsUnitAssertionError( | |
| 30 "Expected " + run + "() to throw " + errorType.name + | |
| 31 ", but did not throw."); | |
| 32 } | |
| 33 if (!(actual instanceof errorType)) | |
| 34 throw new MjsUnitAssertionError( | |
| 35 "Expected " + run + "() to throw " + errorType.name + | |
| 36 ", but threw '" + actual + "'"); | |
| 37 if (message !== void 0 && actual.message !== message) | |
| 38 throw new MjsUnitAssertionError( | |
| 39 "Expected " + run + "() to throw '" + message + "', but threw '" + | |
| 40 actual.message + "'"); | |
| 41 }; | |
| 42 | |
| 43 function assertEqualsAsync(expected, run, msg) { | |
| 44 var actual; | |
| 45 var hadValue = false; | |
| 46 var hadError = false; | |
| 47 var promise = run(); | |
| 48 | |
| 49 if (typeof promise !== "object" || typeof promise.then !== "function") { | |
| 50 throw new MjsUnitAssertionError( | |
| 51 "Expected " + run.toString() + | |
| 52 " to return a Promise, but it returned " + PrettyPrint(promise)); | |
| 53 } | |
| 54 | |
| 55 promise.then(function(value) { hadValue = true; actual = value; }, | |
| 56 function(error) { hadError = true; actual = error; }); | |
| 57 | |
| 58 assertFalse(hadValue || hadError); | |
| 59 | |
| 60 %RunMicrotasks(); | |
| 61 | |
| 62 if (hadError) throw actual; | |
| 63 | |
| 64 assertTrue( | |
| 65 hadValue, "Expected '" + run.toString() + "' to produce a value"); | |
| 66 | |
| 67 assertEquals(expected, actual, msg); | |
| 68 }; | |
| 69 | |
| 70 assertEquals(undefined, this.AsyncFunction); | |
| 71 let AsyncFunction = (async function() {}).constructor; | |
| 72 | |
| 73 // The AsyncFunction Constructor is the %AsyncFunction% intrinsic object and | |
| 74 // is a subclass of Function. | |
| 75 // (https://tc39.github.io/ecmascript-asyncawait/#async-function-constructor) | |
| 76 assertEquals(Object.getPrototypeOf(AsyncFunction), Function); | |
| 77 assertEquals(Object.getPrototypeOf(AsyncFunction.prototype), | |
| 78 Function.prototype); | |
| 79 assertTrue(async function() {} instanceof Function); | |
| 80 | |
| 81 | |
| 82 // Let functionPrototype be the intrinsic object %AsyncFunctionPrototype%. | |
| 83 async function asyncFunctionForProto() {} | |
| 84 assertEquals(AsyncFunction.prototype, | |
| 85 Object.getPrototypeOf(asyncFunctionForProto)); | |
| 86 assertEquals(AsyncFunction.prototype, | |
| 87 Object.getPrototypeOf(async function() {})); | |
| 88 assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(async () => {})); | |
| 89 assertEquals(AsyncFunction.prototype, | |
| 90 Object.getPrototypeOf({ async method() {} }.method)); | |
| 91 assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(AsyncFunction())); | |
| 92 assertEquals(AsyncFunction.prototype, | |
| 93 Object.getPrototypeOf(new AsyncFunction())); | |
| 94 | |
| 95 // AsyncFunctionCreate does not produce an object with a Prototype | |
| 96 assertEquals(undefined, asyncFunctionForProto.prototype); | |
| 97 assertEquals(false, asyncFunctionForProto.hasOwnProperty("prototype")); | |
| 98 assertEquals(undefined, (async function() {}).prototype); | |
| 99 assertEquals(false, (async function() {}).hasOwnProperty("prototype")); | |
| 100 assertEquals(undefined, (async() => {}).prototype); | |
| 101 assertEquals(false, (async() => {}).hasOwnProperty("prototype")); | |
| 102 assertEquals(undefined, ({ async method() {} }).method.prototype); | |
| 103 assertEquals(false, ({ async method() {} }).method.hasOwnProperty("prototype")); | |
| 104 assertEquals(undefined, AsyncFunction().prototype); | |
| 105 assertEquals(false, AsyncFunction().hasOwnProperty("prototype")); | |
| 106 assertEquals(undefined, (new AsyncFunction()).prototype); | |
| 107 assertEquals(false, (new AsyncFunction()).hasOwnProperty("prototype")); | |
| 108 | |
| 109 assertEquals(1, async function(a) { await 1; }.length); | |
| 110 assertEquals(2, async function(a, b) { await 1; }.length); | |
| 111 assertEquals(1, async function(a, b = 2) { await 1; }.length); | |
| 112 assertEquals(2, async function(a, b, ...c) { await 1; }.length); | |
| 113 | |
| 114 assertEquals(1, (async(a) => await 1).length); | |
| 115 assertEquals(2, (async(a, b) => await 1).length); | |
| 116 assertEquals(1, (async(a, b = 2) => await 1).length); | |
| 117 assertEquals(2, (async(a, b, ...c) => await 1).length); | |
| 118 | |
| 119 assertEquals(1, ({ async f(a) { await 1; } }).f.length); | |
| 120 assertEquals(2, ({ async f(a, b) { await 1; } }).f.length); | |
| 121 assertEquals(1, ({ async f(a, b = 2) { await 1; } }).f.length); | |
| 122 assertEquals(2, ({ async f(a, b, ...c) { await 1; } }).f.length); | |
| 123 | |
| 124 assertEquals(1, AsyncFunction("a", "await 1").length); | |
| 125 assertEquals(2, AsyncFunction("a", "b", "await 1").length); | |
| 126 assertEquals(1, AsyncFunction("a", "b = 2", "await 1").length); | |
| 127 assertEquals(2, AsyncFunction("a", "b", "...c", "await 1").length); | |
| 128 | |
| 129 assertEquals(1, (new AsyncFunction("a", "await 1")).length); | |
| 130 assertEquals(2, (new AsyncFunction("a", "b", "await 1")).length); | |
| 131 assertEquals(1, (new AsyncFunction("a", "b = 2", "await 1")).length); | |
| 132 assertEquals(2, (new AsyncFunction("a", "b", "...c", "await 1")).length); | |
| 133 | |
| 134 // AsyncFunction.prototype[ @@toStringTag ] | |
| 135 var descriptor = | |
| 136 Object.getOwnPropertyDescriptor(AsyncFunction.prototype, | |
| 137 Symbol.toStringTag); | |
| 138 assertEquals("AsyncFunction", descriptor.value); | |
| 139 assertEquals(false, descriptor.enumerable); | |
| 140 assertEquals(false, descriptor.writable); | |
| 141 assertEquals(true, descriptor.configurable); | |
| 142 | |
| 143 assertEquals(1, AsyncFunction.length); | |
| 144 | |
| 145 // Let F be ! FunctionAllocate(functionPrototype, Strict, "non-constructor") | |
| 146 async function asyncNonConstructorDecl() {} | |
| 147 assertThrows(() => new asyncNonConstructorDecl(), TypeError); | |
| 148 assertThrows(() => asyncNonConstructorDecl.caller, TypeError); | |
| 149 assertThrows(() => asyncNonConstructorDecl.arguments, TypeError); | |
| 150 | |
| 151 assertThrows(() => new (async function() {}), TypeError); | |
| 152 assertThrows(() => (async function() {}).caller, TypeError); | |
| 153 assertThrows(() => (async function() {}).arguments, TypeError); | |
| 154 | |
| 155 assertThrows( | |
| 156 () => new ({ async nonConstructor() {} }).nonConstructor(), TypeError); | |
| 157 assertThrows( | |
| 158 () => ({ async nonConstructor() {} }).nonConstructor.caller, TypeError); | |
| 159 assertThrows( | |
| 160 () => ({ async nonConstructor() {} }).nonConstructor.arguments, TypeError); | |
| 161 | |
| 162 assertThrows(() => new (() => "not a constructor!"), TypeError); | |
| 163 assertThrows(() => (() => 1).caller, TypeError); | |
| 164 assertThrows(() => (() => 1).arguments, TypeError); | |
| 165 | |
| 166 assertThrows(() => new (AsyncFunction()), TypeError); | |
| 167 assertThrows(() => AsyncFunction().caller, TypeError); | |
| 168 assertThrows(() => AsyncFunction().arguments, TypeError); | |
| 169 | |
| 170 assertThrows(() => new (new AsyncFunction()), TypeError); | |
| 171 assertThrows(() => (new AsyncFunction()).caller, TypeError); | |
| 172 assertThrows(() => (new AsyncFunction()).arguments, TypeError); | |
| 173 | |
| 174 // Normal completion | |
| 175 async function asyncDecl() { return "test"; } | |
| 176 assertEqualsAsync("test", asyncDecl); | |
| 177 assertEqualsAsync("test2", async function() { return "test2"; }); | |
| 178 assertEqualsAsync("test3", async () => "test3"); | |
| 179 assertEqualsAsync("test4", () => ({ async f() { return "test4"; } }).f()); | |
| 180 assertEqualsAsync("test5", () => AsyncFunction("no", "return 'test' + no;")(5)); | |
| 181 assertEqualsAsync("test6", | |
| 182 () => (new AsyncFunction("no", "return 'test' + no;"))(6)); | |
| 183 | |
| 184 class MyError extends Error {}; | |
| 185 | |
| 186 // Throw completion | |
| 187 async function asyncDeclThrower(e) { throw new MyError(e); } | |
| 188 assertThrowsAsync(() => asyncDeclThrower("boom!"), MyError, "boom!"); | |
| 189 assertThrowsAsync( | |
| 190 () => (async function(e) { throw new MyError(e); })("boom!!!"), | |
| 191 MyError, "boom!!!"); | |
| 192 assertThrowsAsync( | |
| 193 () => (async e => { throw new MyError(e) })("boom!!"), MyError, "boom!!"); | |
| 194 assertThrowsAsync( | |
| 195 () => ({ async thrower(e) { throw new MyError(e); } }).thrower("boom!1!"), | |
| 196 MyError, "boom!1!"); | |
| 197 assertThrowsAsync( | |
| 198 () => AsyncFunction("msg", "throw new MyError(msg)")("boom!2!!"), | |
| 199 MyError, "boom!2!!"); | |
| 200 assertThrowsAsync( | |
| 201 () => (new AsyncFunction("msg", "throw new MyError(msg)"))("boom!2!!!"), | |
| 202 MyError, "boom!2!!!"); | |
| 203 | |
| 204 function resolveLater(value) { return Promise.resolve(value); } | |
| 205 function rejectLater(error) { return Promise.reject(error); } | |
| 206 | |
| 207 // Resume after Normal completion | |
| 208 var log = []; | |
| 209 async function resumeAfterNormal(value) { | |
| 210 log.push("start:" + value); | |
| 211 value = await resolveLater(value + 1); | |
| 212 log.push("resume:" + value); | |
| 213 value = await resolveLater(value + 1); | |
| 214 log.push("resume:" + value); | |
| 215 return value + 1; | |
| 216 } | |
| 217 | |
| 218 assertEqualsAsync(4, () => resumeAfterNormal(1)); | |
| 219 assertEquals("start:1 resume:2 resume:3", log.join(" ")); | |
| 220 | |
| 221 var O = { | |
| 222 async resumeAfterNormal(value) { | |
| 223 log.push("start:" + value); | |
| 224 value = await resolveLater(value + 1); | |
| 225 log.push("resume:" + value); | |
| 226 value = await resolveLater(value + 1); | |
| 227 log.push("resume:" + value); | |
| 228 return value + 1; | |
| 229 } | |
| 230 }; | |
| 231 log = []; | |
| 232 assertEqualsAsync(5, () => O.resumeAfterNormal(2)); | |
| 233 assertEquals("start:2 resume:3 resume:4", log.join(" ")); | |
| 234 | |
| 235 var resumeAfterNormalArrow = async (value) => { | |
| 236 log.push("start:" + value); | |
| 237 value = await resolveLater(value + 1); | |
| 238 log.push("resume:" + value); | |
| 239 value = await resolveLater(value + 1); | |
| 240 log.push("resume:" + value); | |
| 241 return value + 1; | |
| 242 }; | |
| 243 log = []; | |
| 244 assertEqualsAsync(6, () => resumeAfterNormalArrow(3)); | |
| 245 assertEquals("start:3 resume:4 resume:5", log.join(" ")); | |
| 246 | |
| 247 var resumeAfterNormalEval = AsyncFunction("value", ` | |
| 248 log.push("start:" + value); | |
| 249 value = await resolveLater(value + 1); | |
| 250 log.push("resume:" + value); | |
| 251 value = await resolveLater(value + 1); | |
| 252 log.push("resume:" + value); | |
| 253 return value + 1;`); | |
| 254 log = []; | |
| 255 assertEqualsAsync(7, () => resumeAfterNormalEval(4)); | |
| 256 assertEquals("start:4 resume:5 resume:6", log.join(" ")); | |
| 257 | |
| 258 var resumeAfterNormalNewEval = new AsyncFunction("value", ` | |
| 259 log.push("start:" + value); | |
| 260 value = await resolveLater(value + 1); | |
| 261 log.push("resume:" + value); | |
| 262 value = await resolveLater(value + 1); | |
| 263 log.push("resume:" + value); | |
| 264 return value + 1;`); | |
| 265 log = []; | |
| 266 assertEqualsAsync(8, () => resumeAfterNormalNewEval(5)); | |
| 267 assertEquals("start:5 resume:6 resume:7", log.join(" ")); | |
| 268 | |
| 269 // Resume after Throw completion | |
| 270 async function resumeAfterThrow(value) { | |
| 271 log.push("start:" + value); | |
| 272 try { | |
| 273 value = await rejectLater("throw1"); | |
| 274 } catch (e) { | |
| 275 log.push("resume:" + e); | |
| 276 } | |
| 277 try { | |
| 278 value = await rejectLater("throw2"); | |
| 279 } catch (e) { | |
| 280 log.push("resume:" + e); | |
| 281 } | |
| 282 return value + 1; | |
| 283 } | |
| 284 | |
| 285 log = []; | |
| 286 assertEqualsAsync(2, () => resumeAfterThrow(1)); | |
| 287 assertEquals("start:1 resume:throw1 resume:throw2", log.join(" ")); | |
| 288 | |
| 289 var O = { | |
| 290 async resumeAfterThrow(value) { | |
| 291 log.push("start:" + value); | |
| 292 try { | |
| 293 value = await rejectLater("throw1"); | |
| 294 } catch (e) { | |
| 295 log.push("resume:" + e); | |
| 296 } | |
| 297 try { | |
| 298 value = await rejectLater("throw2"); | |
| 299 } catch (e) { | |
| 300 log.push("resume:" + e); | |
| 301 } | |
| 302 return value + 1; | |
| 303 } | |
| 304 } | |
| 305 log = []; | |
| 306 assertEqualsAsync(3, () => O.resumeAfterThrow(2)); | |
| 307 assertEquals("start:2 resume:throw1 resume:throw2", log.join(" ")); | |
| 308 | |
| 309 var resumeAfterThrowArrow = async (value) => { | |
| 310 log.push("start:" + value); | |
| 311 try { | |
| 312 value = await rejectLater("throw1"); | |
| 313 } catch (e) { | |
| 314 log.push("resume:" + e); | |
| 315 } | |
| 316 try { | |
| 317 value = await rejectLater("throw2"); | |
| 318 } catch (e) { | |
| 319 log.push("resume:" + e); | |
| 320 } | |
| 321 return value + 1; | |
| 322 }; | |
| 323 | |
| 324 log = []; | |
| 325 | |
| 326 assertEqualsAsync(4, () => resumeAfterThrowArrow(3)); | |
| 327 assertEquals("start:3 resume:throw1 resume:throw2", log.join(" ")); | |
| 328 | |
| 329 var resumeAfterThrowEval = AsyncFunction("value", ` | |
| 330 log.push("start:" + value); | |
| 331 try { | |
| 332 value = await rejectLater("throw1"); | |
| 333 } catch (e) { | |
| 334 log.push("resume:" + e); | |
| 335 } | |
| 336 try { | |
| 337 value = await rejectLater("throw2"); | |
| 338 } catch (e) { | |
| 339 log.push("resume:" + e); | |
| 340 } | |
| 341 return value + 1;`); | |
| 342 log = []; | |
| 343 assertEqualsAsync(5, () => resumeAfterThrowEval(4)); | |
| 344 assertEquals("start:4 resume:throw1 resume:throw2", log.join(" ")); | |
| 345 | |
| 346 var resumeAfterThrowNewEval = new AsyncFunction("value", ` | |
| 347 log.push("start:" + value); | |
| 348 try { | |
| 349 value = await rejectLater("throw1"); | |
| 350 } catch (e) { | |
| 351 log.push("resume:" + e); | |
| 352 } | |
| 353 try { | |
| 354 value = await rejectLater("throw2"); | |
| 355 } catch (e) { | |
| 356 log.push("resume:" + e); | |
| 357 } | |
| 358 return value + 1;`); | |
| 359 log = []; | |
| 360 assertEqualsAsync(6, () => resumeAfterThrowNewEval(5)); | |
| 361 assertEquals("start:5 resume:throw1 resume:throw2", log.join(" ")); | |
| 362 | |
| 363 async function foo() {} | |
| 364 assertEquals("async function foo() {}", foo.toString()); | |
| 365 assertEquals("async function () {}", async function () {}.toString()); | |
| 366 assertEquals("async x => x", (async x => x).toString()); | |
| 367 assertEquals("async x => { return x }", (async x => { return x }).toString()); | |
| 368 class AsyncMethod { async foo() { } } | |
| 369 assertEquals("async foo() { }", | |
| 370 Function.prototype.toString.call(AsyncMethod.prototype.foo)); | |
| 371 assertEquals("async foo() { }", | |
| 372 Function.prototype.toString.call({async foo() { }}.foo)); | |
| 373 | |
| 374 // Async functions are not constructible | |
| 375 assertThrows(() => class extends (async function() {}) {}, TypeError); | |
| 376 | |
| 377 // Regress v8:5148 | |
| 378 assertEqualsAsync("1", () => (async({ a = NaN }) => a)({ a: "1" })); | |
| 379 assertEqualsAsync( | |
| 380 "10", () => (async(foo, { a = NaN }) => foo + a)("1", { a: "0" })); | |
| 381 assertEqualsAsync("2", () => (async({ a = "2" }) => a)({ a: undefined })); | |
| 382 assertEqualsAsync( | |
| 383 "20", () => (async(foo, { a = "0" }) => foo + a)("2", { a: undefined })); | |
| 384 assertThrows(() => eval("async({ foo = 1 })"), SyntaxError); | |
| 385 assertThrows(() => eval("async(a, { foo = 1 })"), SyntaxError); | |
| 386 | |
| 387 // https://bugs.chromium.org/p/chromium/issues/detail?id=638019 | |
| 388 async function gaga() { | |
| 389 let i = 1; | |
| 390 while (i-- > 0) { await 42 } | |
| 391 } | |
| 392 assertDoesNotThrow(gaga); | |
| OLD | NEW |