blob: e6c5ef2d91ab2eafbe7d5ad1359894d0082d6f8f [file] [log] [blame]
function shouldNotThrow(func) {
let error;
try {
func();
} catch (e) {
error = e;
}
if (error)
throw new Error(`bad error: ${String(error)}`);
}
function shouldThrow(func, errorMessage) {
let errorThrown = false;
let error;
try {
func();
} catch (e) {
errorThrown = true;
error = e;
}
if (!errorThrown)
throw new Error('not thrown');
if (String(error) !== errorMessage)
throw new Error(`bad error: ${String(error)}`);
}
function checkClassicNoSyntaxError(source) {
shouldNotThrow(() => eval(source));
}
function checkClassicSyntaxError(source, errorMessage) {
shouldThrow(() => eval(source), errorMessage);
}
function checkStrictSyntaxError(source, errorMessage) {
shouldThrow(() => checkModuleSyntax(source), errorMessage);
}
function checkNoSyntaxErrorCases(source) {
checkClassicNoSyntaxError(source);
// A nested function within a generator is allowed to use the "yield" name again
// within its body because they have FunctionBody[~Yield]. Same with method bodies.
checkClassicNoSyntaxError(`function *gen() { function f() { ${source} } }`);
checkClassicNoSyntaxError(`function *gen() { async function f() { ${source} } }`);
checkClassicNoSyntaxError(`function *gen() { let f = () => { ${source} } }`);
checkClassicNoSyntaxError(`function *gen() { let f = async () => { ${source} } }`);
checkClassicNoSyntaxError(`function *gen() { var o = { f() { ${source} } } }`);
checkClassicNoSyntaxError(`function *gen() { var o = { async f() { ${source} } } }`);
checkClassicNoSyntaxError(`function *gen() { var o = { get f() { ${source} } } }`);
checkClassicNoSyntaxError(`function *gen() { var o = { set f(x) { ${source} } } }`);
}
checkNoSyntaxErrorCases(`var yield`);
checkNoSyntaxErrorCases(`let yield`);
checkNoSyntaxErrorCases(`const yield = 1`);
checkNoSyntaxErrorCases(`var {yield} = {}`);
checkNoSyntaxErrorCases(`yield: 1`);
checkNoSyntaxErrorCases(`function yield(){}`);
checkNoSyntaxErrorCases(`function foo(yield){}`);
checkNoSyntaxErrorCases(`(class { *yield(){} })`); // GeneratorMethod allows "yield" due to PropertyName[?Yield].
checkNoSyntaxErrorCases(`function *yield(){}`); // GeneratorDeclaration allows "yield" name due to BindingIdentifier[?Yield].
checkNoSyntaxErrorCases(`var o = { yield(yield){ var yield } }`); // PropertyName[?Yield] ( UniqueFormalParameters[~Yield] ) { FunctionBody[~Yield] }
checkNoSyntaxErrorCases(`var o = { *yield(){} }`); // GeneratorMethod[?Yield]
checkNoSyntaxErrorCases(`var o = { async yield(){} }`); // AsyncMethod[?Yield]
checkNoSyntaxErrorCases(`var o = { get x(){ var yield } }`); // get PropertyName[?Yield] () { FunctionBody[~Yield] }
checkNoSyntaxErrorCases(`var o = { set x(yield){} }`); // set PropertyName[?Yield] ( PropertySetParameterList) { FunctionBody[~Yield] }
checkNoSyntaxErrorCases(`var o = { set x(yield){} }`); // PropertySetParameterList : FormalParameter[~Yield]
// Disallowed inside a generator.
checkClassicSyntaxError(`
function* foo() { yield: 1; }
`, `SyntaxError: Cannot use 'yield' as a label in a generator function.`);
checkClassicSyntaxError(`
function* foo() { var yield; }
`, `SyntaxError: Cannot use 'yield' as a variable name in a generator function.`);
checkClassicSyntaxError(`
function* foo() { let yield; }
`, `SyntaxError: Cannot use 'yield' as a lexical variable name in a generator function.`);
checkClassicSyntaxError(`
function* foo() { var {yield} = {}; }
`, `SyntaxError: Cannot use abbreviated destructuring syntax for keyword 'yield'.`);
checkClassicSyntaxError(`
function* foo(yield){}
`, `SyntaxError: Cannot use 'yield' as a parameter name in a generator function.`);
// GeneratorExpression BindingIdentifier[+Yield] on the name.
checkClassicSyntaxError(`
(function* yield() { })
`, `SyntaxError: Cannot declare generator function named 'yield'.`);
// GeneratorDeclaration BindingIdentifier[?Yield] on the name.
checkClassicSyntaxError(`
function* foo() { function* yield(){} }
`, `SyntaxError: Cannot use 'yield' as a generator function name in a generator function.`);
// class BindingIdentifier[?Yield] on the name.
checkClassicSyntaxError(`
function* gen() { (class yield {}) }
`, `SyntaxError: Unexpected keyword 'yield'. Expected opening '{' at the start of a class body.`);
// Disallowed in strict code.
checkStrictSyntaxError(`
function* foo() { yield: 1; }
`, `SyntaxError: Cannot use 'yield' as a label in strict mode.:2`);
checkStrictSyntaxError(`
var yield;
`, `SyntaxError: Cannot use 'yield' as a variable name in strict mode.:2`);
checkStrictSyntaxError(`
let yield;
`, `SyntaxError: Cannot use 'yield' as a lexical variable name in strict mode.:2`);
checkStrictSyntaxError(`
var {yield} = {};
`, `SyntaxError: Cannot use abbreviated destructuring syntax for keyword 'yield'.:2`);
checkStrictSyntaxError(`
yield: 1
`, `SyntaxError: Cannot use 'yield' as a label in strict mode.:2`);
checkStrictSyntaxError(`
import {yield} from 'foo'
`, `SyntaxError: Cannot use keyword as imported binding name.:2`);
checkStrictSyntaxError(`
function* foo(yield){}
`, `SyntaxError: Cannot use 'yield' as a parameter name in strict mode.:2`);
checkStrictSyntaxError(`
function* yield(){}
`, `SyntaxError: Cannot use 'yield' as a generator function name in strict mode.:2`);
checkStrictSyntaxError(`
(function* yield(){})
`, `SyntaxError: Cannot use 'yield' as a generator function name in strict mode.:2`);
checkStrictSyntaxError(`
function* gen() { (class yield {}) }
`, `SyntaxError: Unexpected keyword 'yield'. Expected opening '{' at the start of a class body.:2`);
checkClassicSyntaxError(`
function *get() { var o = { yield }; }
`, `SyntaxError: Cannot use 'yield' as a shorthand property name in a generator function.`);
// Edge cases where ~Yield re-enables use of yield in non-strict code.
// FunctionDeclaration[Yield]:
// function BindingIdentifier[?Yield] ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
checkClassicSyntaxError(`function *gen() { function yield() {} }`, `SyntaxError: Unexpected keyword 'yield'`);
checkClassicNoSyntaxError(`function *gen() { function f(yield) {} }`);
// FunctionExpression:
// function BindingIdentifier[~Yield]opt ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
checkClassicNoSyntaxError(`function *gen() { (function yield() {}) }`);
checkClassicNoSyntaxError(`function *gen() { (function f(yield) {}) }`)
checkClassicNoSyntaxError(`function *gen() { (function yield(yield) {}) }`)
checkClassicNoSyntaxError(`function *gen() { (function(yield) {}) }`);
// AsyncFunctionDeclaration[Yield]:
// async function BindingIdentifier[?Yield] ( FormalParameters[~Yield]) { AsyncFunctionBody }
checkClassicSyntaxError(`function *gen() { async function yield() {} }`, `SyntaxError: Unexpected keyword 'yield'`);
checkClassicNoSyntaxError(`function *gen() { async function f(yield) {} }`);
// AsyncFunctionExpression:
// async function BindingIdentifier[~Yield]opt ( FormalParameters[~Yield] ) { AsyncFunctionBody }
checkClassicNoSyntaxError(`function *gen() { (async function yield() {}) }`);
checkClassicNoSyntaxError(`function *gen() { (async function f(yield) {}) }`)
checkClassicNoSyntaxError(`function *gen() { (async function yield(yield) {}) }`);
checkClassicNoSyntaxError(`function *gen() { (async function(yield) {}) }`);
// ArrowFunction[Yield]:
// ArrowParameters[?Yield] => ConciseBody
checkClassicSyntaxError(`function *gen() { let f = (yield) => {} }`, `SyntaxError: Cannot use 'yield' as a parameter name in a generator function.`);
// ArrowFunction[Yield]:
// ArrowParameters[?Yield] => ConciseBody
checkClassicSyntaxError(`function *gen() { let f = (yield) => {} }`, `SyntaxError: Cannot use 'yield' as a parameter name in a generator function.`);
// AsyncArrowFunction[Yield]:
// async AsyncArrowBindingIdentifier[?Yield] => AsyncConciseBody
checkClassicSyntaxError(`function *gen() { let f = async (yield) => {} }`, `SyntaxError: Cannot use 'yield' as a parameter name in a generator function.`);