blob: 0bdbd1b5bd5af65caec062a9963483bcad236461 [file] [log] [blame]
// 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() {})`,
`(function () { await => {}; })`,
`(function () { (await) => {}; })`,
`(function () { (x = await => {}) => {}; })`,
`(function () { (x = (await) => {}) => {}; })`,
`(function () { (x = await /1/g) => {}; })`,
];
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) => {};`,
`var asyncArrow = async() => { (x = await => {}) => {} };`,
`var asyncArrow = async() => { (x = (await) => {}) => {} };`,
`var asyncArrow = async() => { (x = await /1/g) => {} };`,
`({ 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() {}");
})();