Skip to content

Commit

Permalink
[JSC] yield is not a valid BindingIdentifier for AsyncGeneratorExpr…
Browse files Browse the repository at this point in the history
…ession

https://bugs.webkit.org/show_bug.cgi?id=263686
<rdar://problem/117497786>

Reviewed by Justin Michaud.

Representation of AsyncGeneratorExpression [1] contains BindingIdentifier production with [Yield]
parameter, which throws an early error if it matches `yield` terminal [2].

This change implements above-mentioned error, with an error message similar to the case of `await`
idenfitier, aligning JSC with V8 and SpiderMonkey.

[1]: https://tc39.es/ecma262/#prod-AsyncGeneratorExpression
[2]: https://tc39.es/ecma262/#sec-identifiers-static-semantics-early-errors

* LayoutTests/js/parser-syntax-check-expected.txt:
* LayoutTests/js/script-tests/parser-syntax-check.js:
* JSTests/test262/expectations.yaml: Mark 1 test as passing.
* Source/JavaScriptCore/parser/Parser.cpp:
(JSC::Parser<LexerType>::parseFunctionInfo):
* Source/JavaScriptCore/parser/ParserModes.h:
(JSC::isGeneratorOrAsyncGeneratorWrapperParseMode): Extract a helper that will most likely be needed elsewhere.

Canonical link: https://commits.webkit.org/269801@main
  • Loading branch information
Alexey Shvayka committed Oct 26, 2023
1 parent fdd2e5c commit d5e6b96
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 4 deletions.
2 changes: 0 additions & 2 deletions JSTests/test262/expectations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1154,8 +1154,6 @@ test/language/expressions/assignmenttargettype/direct-callexpression-arguments.j
default: 'Test262: This statement should not be evaluated.'
test/language/expressions/assignmenttargettype/parenthesized-callexpression-arguments.js:
default: 'Test262: This statement should not be evaluated.'
test/language/expressions/async-generator/early-errors-expression-yield-as-function-binding-identifier.js:
default: 'Test262: This statement should not be evaluated.'
test/language/expressions/async-generator/generator-created-after-decl-inst.js:
default: 'Test262Error: Expected SameValue(«[object AsyncGenerator]», «[object AsyncGenerator]») to be false'
strict mode: 'Test262Error: Expected SameValue(«[object AsyncGenerator]», «[object AsyncGenerator]») to be false'
Expand Down
2 changes: 2 additions & 0 deletions LayoutTests/js/parser-syntax-check-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,8 @@ PASS Invalid: "(function () {'use strict'; ({...arguments} = {}); })()". Produce
PASS Invalid: "function f() { (function () {'use strict'; ({...arguments} = {}); })() }". Produced the following syntax error: "SyntaxError: Cannot modify 'arguments' in strict mode."
PASS Invalid: "async function foo () { let {...await} = {}; }". Produced the following syntax error: "SyntaxError: Cannot use 'await' as a lexical variable name in an async function."
PASS Invalid: "function f() { async function foo () { let {...await} = {}; } }". Produced the following syntax error: "SyntaxError: Cannot use 'await' as a lexical variable name in an async function."
PASS Invalid: "(async function* yield() {})". Produced the following syntax error: "SyntaxError: Cannot declare async generator function named 'yield'."
PASS Invalid: "function f() { (async function* yield() {}) }". Produced the following syntax error: "SyntaxError: Cannot declare async generator function named 'yield'."
PASS Invalid: "let {...let} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
PASS Invalid: "function f() { let {...let} = {a: 1, b: 2}; }". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
PASS Invalid: "const {...let} = {a: 1, b: 2};". Produced the following syntax error: "SyntaxError: Unexpected keyword 'let'. Cannot use 'let' as an identifier name for a LexicalDeclaration."
Expand Down
1 change: 1 addition & 0 deletions LayoutTests/js/script-tests/parser-syntax-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ invalid("(function * (o) { ({ ...{ x: yield } } = o); })()");
invalid("(function () {'use strict'; ({...eval} = {}); })()");
invalid("(function () {'use strict'; ({...arguments} = {}); })()");
invalid("async function foo () { let {...await} = {}; }");
invalid("(async function* yield() {})");
invalid("let {...let} = {a: 1, b: 2};");
invalid("const {...let} = {a: 1, b: 2};");
invalid("try { throw {a:2} } catch({...foo.a}) {}");
Expand Down
4 changes: 2 additions & 2 deletions Source/JavaScriptCore/parser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2572,8 +2572,8 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
else if (isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
semanticFail("Cannot declare ", stringForFunctionMode(mode), " named 'await'");
else if (isGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
semanticFail("Cannot declare generator function named 'yield'");
else if (isGeneratorOrAsyncGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
semanticFail("Cannot declare ", stringForFunctionMode(mode), " named 'yield'");
next();
if (!nameIsInContainingScope)
failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
Expand Down
9 changes: 9 additions & 0 deletions Source/JavaScriptCore/parser/ParserModes.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@ ALWAYS_INLINE bool isGeneratorOrAsyncFunctionWrapperParseMode(SourceParseMode pa
SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}

ALWAYS_INLINE bool isGeneratorOrAsyncGeneratorWrapperParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
SourceParseMode::GeneratorWrapperFunctionMode,
SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::AsyncGeneratorWrapperFunctionMode,
SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}

ALWAYS_INLINE bool isGeneratorParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
Expand Down

0 comments on commit d5e6b96

Please sign in to comment.