function testSyntax(script) { try { eval(script); } catch (error) { if (error instanceof SyntaxError) throw new Error("Bad error: " + String(error)); } } function testSyntaxError(script, message) { var error = null; try { eval(script); } catch (e) { error = e; } if (!error) throw new Error("Expected syntax error not thrown"); if (String(error) !== message) throw new Error("Bad error: " + String(error)); } testSyntaxError(` class Hello { get *gen() { } } `, `SyntaxError: Unexpected token '*'. Expected an opening '(' before a method's parameter list.`); testSyntaxError(` class Hello { set *gen(value) { } } `, `SyntaxError: Unexpected token '*'. Expected an opening '(' before a method's parameter list.`); testSyntaxError(` function ** gen() { } `, `SyntaxError: Unexpected token '**'`); // "yield" is never a YieldExpression in a ConciseBody (per http://ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions // and https://tc39.github.io/ecma262/#prod-ConciseBody) testSyntax(` var value = () => { yield } `); testSyntax(` var value = (val = yield) => { } `); // Confusingly, FormalParameters[~Yield] does not product a SyntaxError for "yield", even // inside of a generator (https://tc39.github.io/ecma262/#prod-FunctionDeclaration), // but instead resolves "yield" as a BindingIdentifier testSyntax(` function *gen() { function ng(val = yield) { } } `); // Arrow formal parameters within Generators are parameterized with [+Yield], but are // still forbidden from including YieldExpressions in ArrowFormalParameters. // (https://tc39.github.io/ecma262/#prod-ArrowFormalParameters) testSyntaxError(` var yield; function *gen() { var ng = (val = yield) => { } } `, `SyntaxError: Unexpected keyword 'yield'. Cannot use yield expression out of generator.`); (function testYieldBindingIdentifier() { var yield = "hello!"; function* gen() { yield (function(x = yield) { return x; })(); } var result = gen().next(); if (result.value !== "hello!") throw new Error("Expected BindingIdentifier bound to 'hello!', but found " + JSON.stringify(result)); })(); testSyntax(` function* gen() { var ng = (it = function*() { yield 1; }) => { return it().next(); } yield ng(); } `); testSyntaxError(` function* gen() { var ng = (it = function() { yield 1; }) => { return it().next(); } yield ng(); } `, `SyntaxError: Unexpected number '1'`); testSyntax(` function gen(val = yield) { } `); // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors testSyntaxError(` function *gen(val = yield) { } `, `SyntaxError: Unexpected keyword 'yield'. Cannot use yield expression within parameters.`); testSyntaxError(` function *gen(val = yield 20) { } `, `SyntaxError: Unexpected keyword 'yield'. Cannot use yield expression within parameters.`); testSyntaxError(` function *gen(val = yield * g) { } `, `SyntaxError: Unexpected keyword 'yield'. Cannot use yield expression within parameters.`); testSyntax(` function *gen(g = function *() { yield }) { } `); testSyntaxError(` function* gen(arguments) { "use strict"; } `, `SyntaxError: Invalid parameters or function name in strict mode.`); testSyntaxError(` function* gen(eval) { "use strict"; } `, `SyntaxError: Invalid parameters or function name in strict mode.`); testSyntaxError(` function* arguments() { "use strict"; } `, `SyntaxError: 'arguments' is not a valid function name in strict mode.`); testSyntaxError(` function* eval() { "use strict"; } `, `SyntaxError: 'eval' is not a valid function name in strict mode.`); testSyntaxError(` function* gen(a) { let a = 1; } `, `SyntaxError: Cannot declare a let variable twice: 'a'.`); testSyntaxError(` function* gen(b) { const b = 1; } `, `SyntaxError: Cannot declare a const variable twice: 'b'.`);