// Copyright (C) 2016 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. function shouldBe(expected, actual, msg = "") { if (msg) msg = " for " + msg; if (actual !== expected) throw new Error("bad value" + msg + ": " + actual + ". Expected " + expected); } function testSyntax(script) { try { eval(script); } catch (error) { if (error instanceof SyntaxError) throw new Error("Bad error: " + String(error) + "\n evaluating `" + script + "`"); } } function testSyntaxError(script, message) { var error = null; try { eval(script); } catch (e) { error = e; } if (!error) throw new Error("Expected syntax error not thrown\n evaluating `" + script + "`"); if (typeof message === "string" && String(error) !== message) throw new Error("Bad error: " + String(error) + "\n evaluating `" + script + "`"); } (function testTopLevelAsyncAwaitSyntaxSloppyMode() { testSyntax(`({async: 1})`); testSyntax(`var asyncFn = async function() { await 1; };`); testSyntax(`var asyncFn = async function() { var t = !await 1; };`); testSyntax(`var asyncFn = async function() { var t = ~await 1; };`); testSyntax(`var asyncFn = async function() { var t = typeof await 1; };`); testSyntax(`var asyncFn = async function() { var t = void await 1; };`); testSyntax(`var asyncFn = async function() { var t = !(await 1); };`); testSyntax(`var asyncFn = async function() { var t = ~(await 1); };`); testSyntax(`var asyncFn = async function() { var t = typeof (await 1); };`); testSyntax(`var asyncFn = async function() { var t = void (await 1); };`); testSyntax(`var asyncFn = async function() { var t = !!await 1; };`); testSyntax(`var asyncFn = async function() { var t = ~~await 1; };`); testSyntax(`var asyncFn = async function() { var t = typeof typeof await 1; };`); testSyntax(`var asyncFn = async function() { var t = void void await 1; };`); testSyntax(`var asyncFn = async function withName() { await 1; };`); testSyntax(`var asyncFn = async () => await 'test';`); testSyntax(`var asyncFn = async () => !await 'test';`); testSyntax(`var asyncFn = async () => ~await 'test';`); testSyntax(`var asyncFn = async () => typeof await 'test';`); testSyntax(`var asyncFn = async () => void await 'test';`); testSyntax(`var asyncFn = async () => - await 'test';`); testSyntax(`var asyncFn = async () => + await 'test';`); testSyntax(`var asyncFn = async () => delete await 'test';`); testSyntax(`var asyncFn = async () => !!await 'test';`); testSyntax(`var asyncFn = async () => ~~await 'test';`); testSyntax(`var asyncFn = async () => typeof typeof await 'test';`); testSyntax(`var asyncFn = async () => void void await 'test';`); testSyntax(`var asyncFn = async x => await x + 'test';`); testSyntax(`function foo(fn) { fn({ async: true }); }`); testSyntax(`async function asyncFn() { await 1; }`); testSyntax(`var O = { async method() { await 1; } };`); testSyntax(`var O = { async ['meth' + 'od']() { await 1; } };`); testSyntax(`var O = { async 'method'() { await 1; } };`); testSyntax(`var O = { async 0() { await 1; } };`); testSyntax(`var O = { async function() {} };`); testSyntax(`class C { async method() { await 1; } };`); testSyntax(`class C { async ['meth' + 'od']() { await 1; } };`); testSyntax(`class C { async 'method'() { await 1; } };`); testSyntax(`class C { async 0() { await 1; } };`); testSyntax(`var asyncFn = async({ foo = 1 }) => foo;`); testSyntax(`var asyncFn = async({ foo = 1 } = {}) => foo;`); testSyntax(`function* g() { var f = async(yield); }`); testSyntax(`function* g() { var f = async(x = yield); }`); testSyntax(`class C { async ['function']() {} }`); testSyntax(`class C {}; class C2 extends C { async ['function']() {} }`); testSyntax(`class C { static async ['function']() {} }`); testSyntax(`class C {}; class C2 extends C { static async ['function']() {} }`); testSyntax(`class C { async function() {} }`); testSyntax(`class C {}; class C2 extends C { async function() {} }`); testSyntax(`class C { static async function() {} }`); testSyntax(`class C {}; class C2 extends C { static async function() {} }`); testSyntax(`class C { async 'function'() {} }`); testSyntax(`class C {}; class C2 extends C { async 'function'() {} }`); testSyntax(`class C { static async 'function'() {} }`); testSyntax(`class C {}; class C2 extends C { static async 'function'() {} }`); })(); (function testTopLevelAsyncAwaitSyntaxStrictMode() { testSyntax(`"use strict"; ({async: 1})`); testSyntax(`"use strict"; var asyncFn = async function() { await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = ~await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = +await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = -await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = typeof await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = void await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !(await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = ~(await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = -(await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = +(await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = typeof (await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = void (await 1); };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !!await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = ~~await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = typeof typeof await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = void void await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !!await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !~await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !typeof typeof await 1; };`); testSyntax(`"use strict"; var asyncFn = async function() { var t = !void void await 1; };`); testSyntax(`"use strict"; var asyncFn = async function withName() { await 1; };`); testSyntax(`"use strict"; var asyncFn = async () => await 'test';`); testSyntax(`"use strict"; var asyncFn = async x => await x + 'test';`); testSyntax(`"use strict"; function foo(fn) { fn({ async: true }); }`); testSyntax(`"use strict"; async function asyncFn() { await 1; }`); testSyntax(`"use strict"; var O = { async method() { await 1; } };`); testSyntax(`"use strict"; var O = { async ['meth' + 'od']() { await 1; } };`); testSyntax(`"use strict"; var O = { async 'method'() { await 1; } };`); testSyntax(`"use strict"; var O = { async 0() { await 1; } };`); testSyntax(`"use strict"; class C { async method() { await 1; } };`); testSyntax(`"use strict"; class C { async ['meth' + 'od']() { await 1; } };`); testSyntax(`"use strict"; class C { async 'method'() { await 1; } };`); testSyntax(`"use strict"; class C { async 0() { await 1; } };`); testSyntax(`"use strict"; var asyncFn = async({ foo = 1 }) => foo;`); testSyntax(`"use strict"; var asyncFn = async({ foo = 1 } = {}) => foo;`); testSyntax(`"use strict"; function* g() { var f = async(yield); }`); testSyntax(`"use strict"; function* g() { var f = async(x = yield); }`); testSyntax(`"use strict"; class C { async ['function']() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { async ['function']() {} }`); testSyntax(`"use strict"; class C { static async ['function']() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { static async ['function']() {} }`); testSyntax(`"use strict"; class C { async function() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { async function() {} }`); testSyntax(`"use strict"; class C { async function() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { async function() {} }`); testSyntax(`"use strict"; class C { static async function() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { static async function() {} }`); testSyntax(`"use strict"; class C { async 'function'() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { async 'function'() {} }`); testSyntax(`"use strict"; class C { static async 'function'() {} }`); testSyntax(`"use strict"; class C {}; class C2 extends C { static async 'function'() {} }`); })(); (function testNestedAsyncAwaitSyntax() { var contextData = [ { prefix: "function outerFunction() { ", suffix: " }" }, { prefix: "function* outerGenerator() { ", suffix: " }" }, { prefix: "var outerFuncExpr = function() { ", suffix: " };" }, { prefix: "var outerGenExpr = function*() { ", suffix: " };" }, { prefix: "var outerObject = { outerMethod() { ", suffix: " } };" }, { prefix: "var outerObject = { *outerGenMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { outerMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { *outerGenMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { static outerStaticMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { static *outerStaticGenMethod() { ", suffix: " } };" }, { prefix: "class outerClass { outerMethod() { ", suffix: " } };" }, { prefix: "class outerClass { *outerGenMethod() { ", suffix: " } };" }, { prefix: "class outerClass { static outerStaticMethod() { ", suffix: " } };" }, { prefix: "class outerClass { static *outerStaticGenMethod() { ", suffix: " } };" }, { prefix: "var outerArrow = () => { ", suffix: " };" }, { prefix: "async function outerAsyncFunction() { ", suffix: " }" }, { prefix: "var outerAsyncFuncExpr = async function() { ", suffix: " };" }, { prefix: "var outerAsyncArrowFunc = async () => { ", suffix: " };" }, { prefix: "var outerObject = { async outerAsyncMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { async outerAsyncMethod() { ", suffix: " } };" }, { prefix: "var outerClassExpr = class C { static async outerStaticAsyncMethod() { ", suffix: " } };" }, { prefix: "class outerClass { async outerAsyncMethod() { ", suffix: " } };" }, { prefix: "class outerClass { static async outerStaticAsyncMethod() { ", suffix: " } };" }, ]; var testData = [ `var async = 1; return async;`, `let async = 1; return async;`, `const async = 1; return async;`, `function async() {} return async();`, `var async = async => async; return async();`, `function foo() { var await = 1; return await; }`, `function foo(await) { return await; }`, `function* foo() { var await = 1; return await; }`, `function* foo(await) { return await; }`, `var f = () => { var await = 1; return await; }`, `var O = { method() { var await = 1; return await; } };`, `var O = { method(await) { return await; } };`, `var O = { *method() { var await = 1; return await; } };`, `var O = { *method(await) { return await; } };`, `(function await() {})`, ]; for (let context of contextData) { for (let test of testData) { let script = context.prefix + test + context.suffix; testSyntax(script); testSyntax(`"use strict"; ${script}`); } } })(); (function testTopLevelAsyncAwaitSyntaxSloppyMode() { testSyntaxError(`({ async foo() {} })`); testSyntaxError(`({async = 1})`); testSyntaxError(`var asyncFn = async function await() {}`); testSyntaxError(`var asyncFn = async () => var await = 'test';`); testSyntaxError(`var asyncFn = async () => { var await = 'test'; };`); testSyntaxError(`var asyncFn = async await => await + 'test'`); testSyntaxError(`var asyncFn = async function(await) {}`); testSyntaxError(`var asyncFn = async function withName(await) {}`); testSyntaxError(`var asyncFn = async (await) => 'test';`); testSyntaxError(`async function asyncFunctionDeclaration(await) {}`); testSyntaxError(`var outerObject = { async method(a, a) {} }`); testSyntaxError(`var outerObject = { async ['meth' + 'od'](a, a) {} }`); testSyntaxError(`var outerObject = { async 'method'(a, a) {} }`); testSyntaxError(`var outerObject = { async 0(a, a) {} }`); testSyntaxError(`var outerObject = { async method(a, {a}) {} }`); testSyntaxError(`var outerObject = { async method({a}, a) {} }`); testSyntaxError(`var outerObject = { async method({a}, {a}) {} }`); testSyntaxError(`var outerObject = { async method(a, ...a) {} }`); testSyntaxError(`var outerObject = { async method({a}, ...a) {} }`); testSyntaxError(`var outerObject = { async method(a, ...a) {} }`); testSyntaxError(`var outerObject = { async method({a, ...a}) {} }`); testSyntaxError(`var outerObject = { func: async function(a, {a}) {} }`); testSyntaxError(`var outerObject = { func: async function({a}, a) {} }`); testSyntaxError(`var outerObject = { func: async function({a}, {a}) {} }`); testSyntaxError(`var outerObject = { func: async function(a, ...a) {} }`); testSyntaxError(`var outerObject = { func: async function({a}, ...a) {} }`); testSyntaxError(`var outerObject = { func: async function(a, ...a) {} }`); testSyntaxError(`var outerObject = { func: async function({a, ...a}) {} }`); testSyntaxError(`var asyncArrowFn = async() => await;`); testSyntaxError(`var O = { *async asyncGeneratorMethod() {} };`); testSyntaxError(`var O = { async asyncGeneratorMethod*() {} };`); testSyntaxError(`var asyncFn = async function(x = await 1) { return x; }`); testSyntaxError(`async function f(x = await 1) { return x; }`); testSyntaxError(`var f = async(x = await 1) => x;`); testSyntaxError(`var O = { async method(x = await 1) { return x; } };`); testSyntaxError(`function* outerGenerator() { var asyncArrowFn = async yield => 1; }`); testSyntaxError(`function* outerGenerator() { var asyncArrowFn = async(yield) => 1; }`); testSyntaxError(`function* outerGenerator() { var asyncArrowFn = async(x = yield) => 1; }`); testSyntaxError(`function* outerGenerator() { var asyncArrowFn = async({x = yield}) => 1; }`); testSyntaxError(`class C { async constructor() {} }`); testSyntaxError(`class C {}; class C2 extends C { async constructor() {} }`); testSyntaxError(`class C { static async prototype() {} }`); testSyntaxError(`class C {}; class C2 extends C { static async prototype() {} }`); testSyntaxError(`var f = async() => ((async(x = await 1) => x)();`); // Henrique Ferreiro's bug (tm) testSyntaxError(`(async function foo1() { } foo2 => 1)`); testSyntaxError(`(async function foo3() { } () => 1)`); testSyntaxError(`(async function foo4() { } => 1)`); testSyntaxError(`(async function() { } foo5 => 1)`); testSyntaxError(`(async function() { } () => 1)`); testSyntaxError(`(async function() { } => 1)`); testSyntaxError(`(async.foo6 => 1)`); testSyntaxError(`(async.foo7 foo8 => 1)`); testSyntaxError(`(async.foo9 () => 1)`); testSyntaxError(`(async().foo10 => 1)`); testSyntaxError(`(async().foo11 foo12 => 1)`); testSyntaxError(`(async().foo13 () => 1)`); testSyntaxError(`(async['foo14'] => 1)`); testSyntaxError(`(async['foo15'] foo16 => 1)`); testSyntaxError(`(async['foo17'] () => 1)`); testSyntaxError(`(async()['foo18'] => 1)`); testSyntaxError(`(async()['foo19'] foo20 => 1)`); testSyntaxError(`(async()['foo21'] () => 1`); testSyntaxError("(async`foo22` => 1)"); testSyntaxError("(async`foo23` foo24 => 1)"); testSyntaxError("(async`foo25` () => 1)"); testSyntaxError("(async`foo26`.bar27 => 1)"); testSyntaxError("(async`foo28`.bar29 foo30 => 1)"); testSyntaxError("(async`foo31`.bar32 () => 1)"); // assert that errors are still thrown for calls that may have been async functions testSyntaxError(`function async() {} async({ foo33 = 1 })`); })(); (function testTopLevelAsyncAwaitSyntaxStrictMode() { testSyntaxError(`"use strict"; ({ async foo() {} })`); testSyntaxError(`"use strict"; ({async = 1})`); testSyntaxError(`"use strict"; var asyncFn = async function await() {}`); testSyntaxError(`"use strict"; var asyncFn = async () => var await = 'test';`); testSyntaxError(`"use strict"; var asyncFn = async () => { var await = 'test'; };`); testSyntaxError(`"use strict"; var asyncFn = async await => await + 'test'`); testSyntaxError(`"use strict"; var asyncFn = async function(await) {}`); testSyntaxError(`"use strict"; var asyncFn = async function withName(await) {}`); testSyntaxError(`"use strict"; var asyncFn = async (await) => 'test';`); testSyntaxError(`"use strict"; async function asyncFunctionDeclaration(await) {}`); testSyntaxError(`"use strict"; var outerObject = { async method(a, a) {} }`); testSyntaxError(`"use strict"; var outerObject = { async ['meth' + 'od'](a, a) {} }`); testSyntaxError(`"use strict"; var outerObject = { async 'method'(a, a) {} }`); testSyntaxError(`"use strict"; var outerObject = { async 0(a, a) {} }`); testSyntaxError(`"use strict"; var asyncArrowFn = async() => await;`); testSyntaxError(`"use strict"; var O = { *async asyncGeneratorMethod() {} };`); testSyntaxError(`"use strict"; var O = { async asyncGeneratorMethod*() {} };`); testSyntax(`"use strict"; var O = { async function() {} };`); testSyntaxError(`"use strict"; var asyncFn = async function(x = await 1) { return x; }`); testSyntaxError(`"use strict"; async function f(x = await 1) { return x; }`); testSyntaxError(`"use strict"; var f = async(x = await 1) => x;`); testSyntaxError(`"use strict"; var O = { async method(x = await 1) { return x; } };`); testSyntaxError(`"use strict"; function* outerGenerator() { var asyncArrowFn = async yield => 1; }`); testSyntaxError(`"use strict"; function* outerGenerator() { var asyncArrowFn = async(yield) => 1; }`); testSyntaxError(`"use strict"; function* outerGenerator() { var asyncArrowFn = async(x = yield) => 1; }`); testSyntaxError(`"use strict"; function* outerGenerator() { var asyncArrowFn = async({x = yield}) => 1; }`); testSyntaxError(`"use strict"; class C { async constructor() {} }`); testSyntaxError(`"use strict"; class C {}; class C2 extends C { async constructor() {} }`); testSyntaxError(`"use strict"; class C { static async prototype() {} }`); testSyntaxError(`"use strict"; class C {}; class C2 extends C { static async prototype() {} }`); testSyntaxError(`"use strict"; var f = async() => ((async(x = await 1) => x)();`); // Henrique Ferreiro's bug (tm) testSyntaxError(`"use strict"; (async function foo1() { } foo2 => 1)`); testSyntaxError(`"use strict"; (async function foo3() { } () => 1)`); testSyntaxError(`"use strict"; (async function foo4() { } => 1)`); testSyntaxError(`"use strict"; (async function() { } foo5 => 1)`); testSyntaxError(`"use strict"; (async function() { } () => 1)`); testSyntaxError(`"use strict"; (async function() { } => 1)`); testSyntaxError(`"use strict"; (async.foo6 => 1)`); testSyntaxError(`"use strict"; (async.foo7 foo8 => 1)`); testSyntaxError(`"use strict"; (async.foo9 () => 1)`); testSyntaxError(`"use strict"; (async().foo10 => 1)`); testSyntaxError(`"use strict"; (async().foo11 foo12 => 1)`); testSyntaxError(`"use strict"; (async().foo13 () => 1)`); testSyntaxError(`"use strict"; (async['foo14'] => 1)`); testSyntaxError(`"use strict"; (async['foo15'] foo16 => 1)`); testSyntaxError(`"use strict"; (async['foo17'] () => 1)`); testSyntaxError(`"use strict"; (async()['foo18'] => 1)`); testSyntaxError(`"use strict"; (async()['foo19'] foo20 => 1)`); testSyntaxError(`"use strict"; (async()['foo21'] () => 1)`); testSyntaxError('"use strict"; (async`foo22` => 1)'); testSyntaxError('"use strict"; (async`foo23` foo24 => 1)'); testSyntaxError('"use strict"; (async`foo25` () => 1)'); testSyntaxError('"use strict"; (async`foo26`.bar27 => 1)'); testSyntaxError('"use strict"; (async`foo28`.bar29 foo30 => 1)'); testSyntaxError('"use strict"; (async`foo31`.bar32 () => 1)'); // assert that errors are still thrown for calls that may have been async functions testSyntaxError(`"use strict"; function async() {} async({ foo33 = 1 })`); testSyntaxError(`"use strict"; var O = { async method(eval) {} }`); testSyntaxError(`"use strict"; var O = { async ['meth' + 'od'](eval) {} }`); testSyntaxError(`"use strict"; var O = { async 'method'(eval) {} }`); testSyntaxError(`"use strict"; var O = { async 0(eval) {} }`); testSyntaxError(`"use strict"; var O = { async method(arguments) {} }`); testSyntaxError(`"use strict"; var O = { async ['meth' + 'od'](arguments) {} }`); testSyntaxError(`"use strict"; var O = { async 'method'(arguments) {} }`); testSyntaxError(`"use strict"; var O = { async 0(arguments) {} }`); testSyntaxError(`"use strict"; var O = { async method(dupe, dupe) {} }`); })(); (function testAwaitInFormalParameters() { var testData = [ `async function f(await) {}`, `async function f(...await) {}`, `async function f(await = 1) {}`, `async function f([await]) {}`, `async function f([await = 1]) {}`, `async function f({ await }) {}`, `async function f({ await = 1 }) {}`, `async function f({ } = await) {}`, `(async function(await) {})`, `(async function(...await) {})`, `(async function(await = 1) {})`, `(async function([await]) {})`, `(async function([await = 1]) {})`, `(async function({ await }) {})`, `(async function({ await = 1 }) {})`, `(async function({ } = await) {})`, `var asyncArrow = async(await) => 1;`, `var asyncArrow = async(await) => {};`, `var asyncArrow = async(...await) => 1;`, `var asyncArrow = async(...await) => {};`, `var asyncArrow = async(await = 1) => 1;`, `var asyncArrow = async(await = 1) => {};`, `var asyncArrow = async([await]) => 1;`, `var asyncArrow = async([await]) => {};`, `var asyncArrow = async([await = 1]) => 1;`, `var asyncArrow = async([await = 1]) => {};`, `var asyncArrow = async([] = await) => 1;`, `var asyncArrow = async([] = await) => {};`, `var asyncArrow = async({ await }) => 1;`, `var asyncArrow = async({ await } ) => {};`, `var asyncArrow = async({ await = 1}) => 1;`, `var asyncArrow = async({ await = 1}) => {};`, `var asyncArrow = async({ } = await) => 1;`, `var asyncArrow = async({ } = await) => {};`, `({ async method(await) {} })`, `({ async method(...await) {} })`, `({ async method(await = 1) {} })`, `({ async method([await]) {} })`, `({ async method([await = 1]) {} })`, `({ async method({ await }) {} })`, `({ async method({ await = 1 }) {} })`, `({ async method({ } = await) {} })`, `(class { async method(await) {} })`, `(class { async method(...await) {} })`, `(class { async method(await = 1) {} })`, `(class { async method([await]) {} })`, `(class { async method([await = 1]) {} })`, `(class { async method({ await }) {} })`, `(class { async method({ await = 1 }) {} })`, `(class { async method({ } = await) {} })`, `(class { static async method(await) {} })`, `(class { static async method(...await) {} })`, `(class { static async method(await = 1) {} })`, `(class { static async method([await]) {} })`, `(class { static async method([await = 1]) {} })`, `(class { static async method({ await }) {} })`, `(class { static async method({ await = 1 }) {} })`, `(class { static async method({ } = await) {} })`, ]; for (let script of testData) { testSyntaxError(script); testSyntaxError(`"use strict"; ${script}`); var nested = `var await; var f = (async function() { ${script} });`; testSyntaxError(nested); testSyntaxError(`"use strict"; ${nested}`); } })(); testSyntaxError(` async function fn(arguments) { "use strict"; } `, `SyntaxError: Invalid parameters or function name in strict mode.`); testSyntaxError(` async function fn(eval) { "use strict"; } `, `SyntaxError: Invalid parameters or function name in strict mode.`); testSyntaxError(` async function arguments() { "use strict"; } `, `SyntaxError: 'arguments' is not a valid function name in strict mode.`); testSyntaxError(` async function eval() { "use strict"; } `, `SyntaxError: 'eval' is not a valid function name in strict mode.`); testSyntaxError(` async function fn(a) { let a = 1; } `, `SyntaxError: Cannot declare a let variable twice: 'a'.`); testSyntaxError(` async function fn(b) { const b = 1; } `, `SyntaxError: Cannot declare a const variable twice: 'b'.`); (function testMethodDefinition() { testSyntax("({ async [foo]() {} })"); testSyntax("({ async [Symbol.asyncIterator]() {} })"); testSyntax("({ async 0() {} })"); testSyntax("({ async 'string'() {} })"); testSyntax("({ async ident() {} })"); testSyntax("(class { async [foo]() {} })"); testSyntax("(class { async [Symbol.asyncIterator]() {} })"); testSyntax("(class { async 0() {} })"); testSyntax("(class { async 'string'() {} })"); testSyntax("(class { async ident() {} })"); testSyntax("(class { static async [foo]() {} })"); testSyntax("(class { static async [Symbol.asyncIterator]() {} })"); testSyntax("(class { static async 0() {} })"); testSyntax("(class { static async 'string'() {} })"); testSyntax("(class { static async ident() {} })"); })(); (function testLineTerminator() { let testLineFeedErrors = (prefix, suffix) => { testSyntaxError(`${prefix}// comment ${suffix}`); testSyntaxError(`${prefix}/* comment */ ${suffix}`); testSyntaxError(`${prefix} ${suffix}`); testSyntaxError(`"use strict";${prefix}// comment ${suffix}`); testSyntaxError(`"use strict";${prefix}/* comment */ ${suffix}`); testSyntaxError(`"use strict";${prefix} ${suffix}`); }; let testLineFeeds = (prefix, suffix) => { testSyntax(`${prefix}// comment ${suffix}`); testSyntax(`${prefix}/* comment */${suffix}`); testSyntax(`${prefix} ${suffix}`); testSyntax(`"use strict";${prefix}// comment ${suffix}`); testSyntax(`"use strict";${prefix}/* comment */${suffix}`); testSyntax(`"use strict";${prefix} ${suffix}`); }; let tests = [ // ObjectLiteral AsyncMethodDefinition { prefix: "({ async", suffix: "method() {} }).method" }, // ClassLiteral AsyncMethodDefinition { prefix: "(class { async", suffix: "method() {} }).prototype.method" }, // AsyncArrowFunctions { prefix: "(async", suffix: "param => 1)" }, { prefix: "(async", suffix: "(param) => 1)" }, { prefix: "(async", suffix: "param => {})" }, { prefix: "(async", suffix: "(param) => {})" }, ]; for (let { prefix, suffix } of tests) { testSyntax(`${prefix} ${suffix}`); testSyntax(`"use strict";${prefix} ${suffix}`); shouldBe("function", typeof eval(`${prefix} ${suffix}`)); shouldBe("function", typeof eval(`"use strict";${prefix} ${suffix}`)); testLineFeedErrors(prefix, suffix); } // AsyncFunctionDeclaration testSyntax("async function foo() {}"); testLineFeeds("async", "function foo() {}"); // AsyncFunctionExpression testSyntax("var x = async function foo() {}"); testSyntax("'use strict';var x = async function foo() {}"); testLineFeeds("var x = async", "function foo() {}"); testLineFeedErrors("var x = async", "function() {}"); })();