blob: ba0350fc83c5f3e71de609543ef1208d3c148397 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// 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
9function 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
43function 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
70assertEquals(undefined, this.AsyncFunction);
71let AsyncFunction = (async function() {}).constructor;
72
73// Let functionPrototype be the intrinsic object %AsyncFunctionPrototype%.
74async function asyncFunctionForProto() {}
75assertEquals(AsyncFunction.prototype,
76 Object.getPrototypeOf(asyncFunctionForProto));
77assertEquals(AsyncFunction.prototype,
78 Object.getPrototypeOf(async function() {}));
79assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(async () => {}));
80assertEquals(AsyncFunction.prototype,
81 Object.getPrototypeOf({ async method() {} }.method));
82assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(AsyncFunction()));
83assertEquals(AsyncFunction.prototype,
84 Object.getPrototypeOf(new AsyncFunction()));
85
86// AsyncFunctionCreate does not produce an object with a Prototype
87assertEquals(undefined, asyncFunctionForProto.prototype);
88assertEquals(false, asyncFunctionForProto.hasOwnProperty("prototype"));
89assertEquals(undefined, (async function() {}).prototype);
90assertEquals(false, (async function() {}).hasOwnProperty("prototype"));
91assertEquals(undefined, (async() => {}).prototype);
92assertEquals(false, (async() => {}).hasOwnProperty("prototype"));
93assertEquals(undefined, ({ async method() {} }).method.prototype);
94assertEquals(false, ({ async method() {} }).method.hasOwnProperty("prototype"));
95assertEquals(undefined, AsyncFunction().prototype);
96assertEquals(false, AsyncFunction().hasOwnProperty("prototype"));
97assertEquals(undefined, (new AsyncFunction()).prototype);
98assertEquals(false, (new AsyncFunction()).hasOwnProperty("prototype"));
99
100assertEquals(1, async function(a) { await 1; }.length);
101assertEquals(2, async function(a, b) { await 1; }.length);
102assertEquals(1, async function(a, b = 2) { await 1; }.length);
103assertEquals(2, async function(a, b, ...c) { await 1; }.length);
104
105assertEquals(1, (async(a) => await 1).length);
106assertEquals(2, (async(a, b) => await 1).length);
107assertEquals(1, (async(a, b = 2) => await 1).length);
108assertEquals(2, (async(a, b, ...c) => await 1).length);
109
110assertEquals(1, ({ async f(a) { await 1; } }).f.length);
111assertEquals(2, ({ async f(a, b) { await 1; } }).f.length);
112assertEquals(1, ({ async f(a, b = 2) { await 1; } }).f.length);
113assertEquals(2, ({ async f(a, b, ...c) { await 1; } }).f.length);
114
115assertEquals(1, AsyncFunction("a", "await 1").length);
116assertEquals(2, AsyncFunction("a", "b", "await 1").length);
117assertEquals(1, AsyncFunction("a", "b = 2", "await 1").length);
118assertEquals(2, AsyncFunction("a", "b", "...c", "await 1").length);
119
120assertEquals(1, (new AsyncFunction("a", "await 1")).length);
121assertEquals(2, (new AsyncFunction("a", "b", "await 1")).length);
122assertEquals(1, (new AsyncFunction("a", "b = 2", "await 1")).length);
123assertEquals(2, (new AsyncFunction("a", "b", "...c", "await 1")).length);
124
125// AsyncFunction.prototype[ @@toStringTag ]
126var descriptor =
127 Object.getOwnPropertyDescriptor(AsyncFunction.prototype,
128 Symbol.toStringTag);
129assertEquals("AsyncFunction", descriptor.value);
130assertEquals(false, descriptor.enumerable);
131assertEquals(false, descriptor.writable);
132assertEquals(true, descriptor.configurable);
133
134assertEquals(1, AsyncFunction.length);
135
136// Let F be ! FunctionAllocate(functionPrototype, Strict, "non-constructor")
137async function asyncNonConstructorDecl() {}
138assertThrows(
139 () => new asyncNonConstructorDecl(), TypeError);
140assertThrows(
141 () => new (async function() {}), TypeError);
142assertThrows(
143 () => new ({ async nonConstructor() {} }).nonConstructor(), TypeError);
144assertThrows(
145 () => new (() => "not a constructor!"), TypeError);
146assertThrows(
147 () => new (AsyncFunction()), TypeError);
148assertThrows(
149 () => new (new AsyncFunction()), TypeError);
150
151// Normal completion
152async function asyncDecl() { return "test"; }
153assertEqualsAsync("test", asyncDecl);
154assertEqualsAsync("test2", async function() { return "test2"; });
155assertEqualsAsync("test3", async () => "test3");
156assertEqualsAsync("test4", () => ({ async f() { return "test4"; } }).f());
157assertEqualsAsync("test5", () => AsyncFunction("no", "return 'test' + no;")(5));
158assertEqualsAsync("test6",
159 () => (new AsyncFunction("no", "return 'test' + no;"))(6));
160
161class MyError extends Error {};
162
163// Throw completion
164async function asyncDeclThrower(e) { throw new MyError(e); }
165assertThrowsAsync(() => asyncDeclThrower("boom!"), MyError, "boom!");
166assertThrowsAsync(
167 () => (async function(e) { throw new MyError(e); })("boom!!!"),
168 MyError, "boom!!!");
169assertThrowsAsync(
170 () => (async e => { throw new MyError(e) })("boom!!"), MyError, "boom!!");
171assertThrowsAsync(
172 () => ({ async thrower(e) { throw new MyError(e); } }).thrower("boom!1!"),
173 MyError, "boom!1!");
174assertThrowsAsync(
175 () => AsyncFunction("msg", "throw new MyError(msg)")("boom!2!!"),
176 MyError, "boom!2!!");
177assertThrowsAsync(
178 () => (new AsyncFunction("msg", "throw new MyError(msg)"))("boom!2!!!"),
179 MyError, "boom!2!!!");
180
181function resolveLater(value) { return Promise.resolve(value); }
182function rejectLater(error) { return Promise.reject(error); }
183
184// Resume after Normal completion
185var log = [];
186async function resumeAfterNormal(value) {
187 log.push("start:" + value);
188 value = await resolveLater(value + 1);
189 log.push("resume:" + value);
190 value = await resolveLater(value + 1);
191 log.push("resume:" + value);
192 return value + 1;
193}
194
195assertEqualsAsync(4, () => resumeAfterNormal(1));
196assertEquals("start:1 resume:2 resume:3", log.join(" "));
197
198var O = {
199 async resumeAfterNormal(value) {
200 log.push("start:" + value);
201 value = await resolveLater(value + 1);
202 log.push("resume:" + value);
203 value = await resolveLater(value + 1);
204 log.push("resume:" + value);
205 return value + 1;
206 }
207};
208log = [];
209assertEqualsAsync(5, () => O.resumeAfterNormal(2));
210assertEquals("start:2 resume:3 resume:4", log.join(" "));
211
212var resumeAfterNormalArrow = async (value) => {
213 log.push("start:" + value);
214 value = await resolveLater(value + 1);
215 log.push("resume:" + value);
216 value = await resolveLater(value + 1);
217 log.push("resume:" + value);
218 return value + 1;
219};
220log = [];
221assertEqualsAsync(6, () => resumeAfterNormalArrow(3));
222assertEquals("start:3 resume:4 resume:5", log.join(" "));
223
224var resumeAfterNormalEval = AsyncFunction("value", `
225 log.push("start:" + value);
226 value = await resolveLater(value + 1);
227 log.push("resume:" + value);
228 value = await resolveLater(value + 1);
229 log.push("resume:" + value);
230 return value + 1;`);
231log = [];
232assertEqualsAsync(7, () => resumeAfterNormalEval(4));
233assertEquals("start:4 resume:5 resume:6", log.join(" "));
234
235var resumeAfterNormalNewEval = new AsyncFunction("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;`);
242log = [];
243assertEqualsAsync(8, () => resumeAfterNormalNewEval(5));
244assertEquals("start:5 resume:6 resume:7", log.join(" "));
245
246// Resume after Throw completion
247async function resumeAfterThrow(value) {
248 log.push("start:" + value);
249 try {
250 value = await rejectLater("throw1");
251 } catch (e) {
252 log.push("resume:" + e);
253 }
254 try {
255 value = await rejectLater("throw2");
256 } catch (e) {
257 log.push("resume:" + e);
258 }
259 return value + 1;
260}
261
262log = [];
263assertEqualsAsync(2, () => resumeAfterThrow(1));
264assertEquals("start:1 resume:throw1 resume:throw2", log.join(" "));
265
266var O = {
267 async resumeAfterThrow(value) {
268 log.push("start:" + value);
269 try {
270 value = await rejectLater("throw1");
271 } catch (e) {
272 log.push("resume:" + e);
273 }
274 try {
275 value = await rejectLater("throw2");
276 } catch (e) {
277 log.push("resume:" + e);
278 }
279 return value + 1;
280 }
281}
282log = [];
283assertEqualsAsync(3, () => O.resumeAfterThrow(2));
284assertEquals("start:2 resume:throw1 resume:throw2", log.join(" "));
285
286var resumeAfterThrowArrow = async (value) => {
287 log.push("start:" + value);
288 try {
289 value = await rejectLater("throw1");
290 } catch (e) {
291 log.push("resume:" + e);
292 }
293 try {
294 value = await rejectLater("throw2");
295 } catch (e) {
296 log.push("resume:" + e);
297 }
298 return value + 1;
299};
300
301log = [];
302
303assertEqualsAsync(4, () => resumeAfterThrowArrow(3));
304assertEquals("start:3 resume:throw1 resume:throw2", log.join(" "));
305
306var resumeAfterThrowEval = AsyncFunction("value", `
307 log.push("start:" + value);
308 try {
309 value = await rejectLater("throw1");
310 } catch (e) {
311 log.push("resume:" + e);
312 }
313 try {
314 value = await rejectLater("throw2");
315 } catch (e) {
316 log.push("resume:" + e);
317 }
318 return value + 1;`);
319log = [];
320assertEqualsAsync(5, () => resumeAfterThrowEval(4));
321assertEquals("start:4 resume:throw1 resume:throw2", log.join(" "));
322
323var resumeAfterThrowNewEval = new AsyncFunction("value", `
324 log.push("start:" + value);
325 try {
326 value = await rejectLater("throw1");
327 } catch (e) {
328 log.push("resume:" + e);
329 }
330 try {
331 value = await rejectLater("throw2");
332 } catch (e) {
333 log.push("resume:" + e);
334 }
335 return value + 1;`);
336log = [];
337assertEqualsAsync(6, () => resumeAfterThrowNewEval(5));
338assertEquals("start:5 resume:throw1 resume:throw2", log.join(" "));
339
340async function foo() {}
341assertEquals("async function foo() {}", foo.toString());
342assertEquals("async function () {}", async function() {}.toString());
343assertEquals("async x => x", (async x => x).toString());
344assertEquals("async x => { return x }", (async x => { return x }).toString());
345class AsyncMethod { async foo() { } }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100346assertEquals("async foo() { }",
347 Function.prototype.toString.call(AsyncMethod.prototype.foo));
348assertEquals("async foo() { }",
349 Function.prototype.toString.call({async foo() { }}.foo));
350
351// Async functions are not constructible
352assertThrows(() => class extends (async function() {}) {}, TypeError);
353
354// Regress v8:5148
355assertEqualsAsync("1", () => (async({ a = NaN }) => a)({ a: "1" }));
356assertEqualsAsync(
357 "10", () => (async(foo, { a = NaN }) => foo + a)("1", { a: "0" }));
358assertEqualsAsync("2", () => (async({ a = "2" }) => a)({ a: undefined }));
359assertEqualsAsync(
360 "20", () => (async(foo, { a = "0" }) => foo + a)("2", { a: undefined }));
361assertThrows(() => eval("async({ foo = 1 })"), SyntaxError);
362assertThrows(() => eval("async(a, { foo = 1 })"), SyntaxError);
363
364// https://bugs.chromium.org/p/chromium/issues/detail?id=638019
365async function gaga() {
366 let i = 1;
367 while (i-- > 0) { await 42 }
368}
369assertDoesNotThrow(gaga);