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 |