+2017-08-06 Oleksandr Skachkov <gskachkov@gmail.com>
+
+ [ESNext] Async iteration - Implement Async Generator - parser
+ https://bugs.webkit.org/show_bug.cgi?id=175210
+
+ Reviewed by Yusuke Suzuki.
+
+ * stress/async-await-syntax.js:
+ (testTopLevelAsyncAwaitSyntaxSloppyMode.testSyntax):
+ * stress/async-iteration-syntax.js: Added.
+ (assert):
+ (checkSyntax):
+ (checkSyntaxError):
+ (checkSimpleAsyncGeneratorSloppyMode):
+ (checkSimpleAsyncGeneratorStrictMode):
+ (checkNestedAsyncGenerators):
+ (checkSimpleAsyncGeneratorSyntaxErrorInStrictMode):
+ * stress/generator-class-methods-syntax.js:
+
2017-08-03 Carlos Alberto Lopez Perez <clopez@igalia.com>
JSC test wasm/js-api/test_memory_constructor.js should be skipped on memoryLimited
}
(function testTopLevelAsyncAwaitSyntaxSloppyMode() {
+ testSyntax(`({async: 1})`);
testSyntax(`var asyncFn = async function() { await 1; };`);
testSyntax(`var asyncFn = async function withName() { await 1; };`);
testSyntax(`var asyncFn = async () => 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; } };`);
})();
(function testTopLevelAsyncAwaitSyntaxStrictMode() {
+ testSyntax(`"use strict"; ({async: 1})`);
testSyntax(`"use strict"; var asyncFn = async function() { 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; } };`);
(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 asyncArrowFn = async() => await;`);
- testSyntaxError(`var asyncFn = async function*() {}`);
- testSyntaxError(`async function* asyncGenerator() {}`);
+ testSyntax(`var asyncFn = async function*() {}`);
+ testSyntax(`async function* asyncGenerator() {}`);
testSyntaxError(`var O = { *async asyncGeneratorMethod() {} };`);
- testSyntaxError(`var O = { async *asyncGeneratorMethod() {} };`);
+ testSyntax(`var O = { async *asyncGeneratorMethod() {} };`);
testSyntaxError(`var O = { async asyncGeneratorMethod*() {} };`);
testSyntaxError(`var asyncFn = async function(x = await 1) { return x; }`);
})();
(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 asyncArrowFn = async() => await;`);
- testSyntaxError(`"use strict"; var asyncFn = async function*() {}`);
- testSyntaxError(`"use strict"; async function* asyncGenerator() {}`);
testSyntaxError(`"use strict"; var O = { *async asyncGeneratorMethod() {} };`);
- testSyntaxError(`"use strict"; var O = { async *asyncGeneratorMethod() {} };`);
testSyntaxError(`"use strict"; var O = { async asyncGeneratorMethod*() {} };`);
testSyntax(`"use strict"; var O = { async function() {} };`);
--- /dev/null
+var assert = function (result, expected, message = "") {
+ if (result !== expected) {
+ throw new Error('Error in assert. Expected "' + expected + '" but was "' + result + '":' + message );
+ }
+};
+
+
+function checkSyntax(src) {
+ try {
+ eval(src);
+ } catch (error) {
+ if (error instanceof SyntaxError)
+ throw new Error("Syntax Error: " + String(error) + "\n script: `" + src + "`");
+ }
+}
+
+function checkSyntaxError(src, message) {
+ var bError = false;
+ try {
+ eval(src);
+ } catch (error) {
+ bError = error instanceof SyntaxError && (String(error) === message || typeof message === 'undefined');
+ }
+ if (!bError) {
+ throw new Error("Expected syntax Error: " + message + "\n in script: `" + src + "`");
+ }
+}
+
+(function checkSimpleAsyncGeneratorSloppyMode() {
+ checkSyntax('var a1 = async function*asyncGenWithName1(){}');
+ checkSyntax('var a2 = async function *asyncGenWithName2(){ yield 11; }');
+ checkSyntax('var a3 = async function * asyncGenWithName2(){ await p; yield 11; }');
+ checkSyntax('var d1 = async function*(){}');
+ checkSyntax('var d2 = async function* (){ yield 11; }');
+ checkSyntax('var d3 = async function * (){ await p; yield 11; }');
+ checkSyntax('async function* withName1(){ }');
+ checkSyntax('async function *withName2(){ yield 11; }');
+ checkSyntax('async function * withName3(){ await p; yield 11; }');
+ checkSyntax('class A { async * method() { } }');
+ checkSyntax('class B { async * method() {yield 11;} }');
+ checkSyntax('class C { async * method() {yield 11; await p;} }');
+ checkSyntax('class D { async * "method"() {yield 11; await p;} }');
+ checkSyntax('class F { async * 0() {yield 11; await p;} }');
+ checkSyntax('var obj = { async * method() {yield 11; await p;} }');
+ checkSyntax('({ async foo() {} })');
+ checkSyntax('({ async : 1 })');
+})();
+
+(function checkSimpleAsyncGeneratorStrictMode() {
+ checkSyntax('"use strict"; var a1 = async function*asyncGenWithName1(){}');
+ checkSyntax('"use strict"; var a2 = async function *asyncGenWithName2(){ yield 11; }');
+ checkSyntax('"use strict"; var a3 = async function * asyncGenWithName2(){ await p; yield 11; }');
+ checkSyntax('"use strict"; var d1 = async function*(){}');
+ checkSyntax('"use strict"; var d2 = async function* (){ yield 11; }');
+ checkSyntax('"use strict"; var d3 = async function * (){ await p; yield 11; }');
+ checkSyntax('"use strict"; async function* withName1(){ }');
+ checkSyntax('"use strict"; async function *withName2(){ yield 11; }');
+ checkSyntax('"use strict"; async function * withName3(){ await p; yield 11; }');
+ checkSyntax('"use strict"; class A { async * method() { } }');
+ checkSyntax('"use strict"; class B { async * method() {yield 11;} }');
+ checkSyntax('"use strict"; class C { async * method() {yield 11; await p;} }');
+ checkSyntax('"use strict"; class D { async * "method"() {yield 11; await p;} }');
+ checkSyntax('"use strict"; class E { async * ["calc" + "ulate"]() {yield 11; await p;} }');
+ checkSyntax('"use strict"; class F { async * 0() {yield 11; await p;} }');
+ checkSyntax('"use strict"; var obj = { async * method() {yield 11; await p;} }');
+ checkSyntax('"use strict"; ({ async foo() {} })');
+ checkSyntax('"use strict"; ({ async : 1 })');
+})();
+
+
+(function checkNestedAsyncGenerators() {
+ var wrappers = [
+ {start: 'var a1 = async function*asyncGenWithName1(){', finish: '}'},
+ {start: 'async function*asyncGenWithName2(){ ', finish: '}'},
+ {start: 'class A { async * method() { ', finish: ' } }'}
+ ];
+
+ expressions = [
+ 'await 10; yield 11; return 12;',
+ 'var async = 10; yield async;',
+ 'var async = 10; await async;',
+ 'var async = 10; return async;',
+ 'var async = function() {}; return async;',
+ 'var async = function() {}; return async();',
+ ];
+
+ wrappers.forEach(wrapper => {
+ expressions.forEach(exp => {
+ checkSyntax(wrapper.start + exp + wrapper.finish);
+ });
+ })
+})();
+
+
+(function checkSimpleAsyncGeneratorSyntaxErrorInSloppyMode() {
+ checkSyntaxError("var asyncGenFn = async function *await() {}");
+ checkSyntaxError("var asyncGenFn = async function*(await) {}");
+ checkSyntaxError("var asyncGenFn = async function *withName(await) {}");
+ checkSyntaxError("async function *asyncGeneratorFunctionDeclaration(await) {}");
+ checkSyntaxError("var asyncGenFn = *async function () {}");
+ checkSyntaxError("var asyncGenFn = *async function withName() {}");
+ checkSyntaxError("*async function asyncGeneratorFunctionDeclaration(await) {}");
+ checkSyntaxError("var obj = { *async asyncGeneratorMethod() {} };");
+ checkSyntaxError("var obj = { async asyncGeneratorMethod*() {} };");
+ checkSyntaxError("class A { get async* ttt() {} }");
+ checkSyntaxError("class B { get *async ttt() {} }");
+ checkSyntaxError('({ async = 1 })');
+})();
+
+(function checkSimpleAsyncGeneratorSyntaxErrorInStrictMode() {
+ checkSyntaxError("'use strict'; var asyncGenFn = async function *await() {}");
+ checkSyntaxError("'use strict'; var asyncGenFn = async function*(await) {}");
+ checkSyntaxError("'use strict'; var asyncGenFn = async function *withName(await) {}");
+ checkSyntaxError("'use strict'; async function *asyncGeneratorFunctionDeclaration(await) {}");
+ checkSyntaxError("'use strict'; var asyncGenFn = *async function () {}");
+ checkSyntaxError("'use strict'; var asyncGenFn = *async function withName() {}");
+ checkSyntaxError("'use strict'; *async function asyncGeneratorFunctionDeclaration(await) {}");
+ checkSyntaxError("'use strict'; var obj = { *async asyncGeneratorMethod() {} };");
+ checkSyntaxError("'use strict'; var obj = { async asyncGeneratorMethod*() {} };");
+ checkSyntaxError("'use strict'; class A { get async* ttt() {} }");
+ checkSyntaxError("'use strict'; class B { get *async ttt() {} }");
+ checkSyntaxError("'use strict'; ({ async = 1 })");
+})();
{
}
}
-`, `SyntaxError: Cannot declare a generator named 'constructor'.`);
+`, `SyntaxError: Cannot declare a generator function named 'constructor'.`);
testSyntax(`
class Cocoa {
+2017-08-06 Oleksandr Skachkov <gskachkov@gmail.com>
+
+ [ESNext] Async iteration - Implement Async Generator - parser
+ https://bugs.webkit.org/show_bug.cgi?id=175210
+
+ Reviewed by Yusuke Suzuki.
+
+ Current implementation is draft version of Async Iteration.
+ Link to spec https://tc39.github.io/proposal-async-iteration/
+
+ Current patch implement only parser part of the Async generator
+ Runtime part will be in next ptches
+
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createFunctionMetadata):
+ * parser/Parser.cpp:
+ (JSC::getAsynFunctionBodyParseMode):
+ (JSC::Parser<LexerType>::parseInner):
+ (JSC::Parser<LexerType>::parseAsyncFunctionSourceElements):
+ (JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
+ (JSC::stringArticleForFunctionMode):
+ (JSC::stringForFunctionMode):
+ (JSC::Parser<LexerType>::parseFunctionInfo):
+ (JSC::Parser<LexerType>::parseAsyncFunctionDeclaration):
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parseProperty):
+ (JSC::Parser<LexerType>::parsePropertyMethod):
+ (JSC::Parser<LexerType>::parseAsyncFunctionExpression):
+ * parser/Parser.h:
+ (JSC::Scope::setSourceParseMode):
+ * parser/ParserModes.h:
+ (JSC::isFunctionParseMode):
+ (JSC::isAsyncFunctionParseMode):
+ (JSC::isAsyncArrowFunctionParseMode):
+ (JSC::isAsyncGeneratorFunctionParseMode):
+ (JSC::isAsyncFunctionOrAsyncGeneratorWrapperParseMode):
+ (JSC::isAsyncFunctionWrapperParseMode):
+ (JSC::isAsyncFunctionBodyParseMode):
+ (JSC::isGeneratorMethodParseMode):
+ (JSC::isAsyncMethodParseMode):
+ (JSC::isAsyncGeneratorMethodParseMode):
+ (JSC::isMethodParseMode):
+ (JSC::isGeneratorOrAsyncFunctionBodyParseMode):
+ (JSC::isGeneratorOrAsyncFunctionWrapperParseMode):
+
2017-08-05 Filip Pizlo <fpizlo@apple.com>
REGRESSION (r219895-219897): Number of leaks on Open Source went from 9240 to 235983 and is now at 302372
unsigned parameterCount,
SourceParseMode mode, bool isArrowFunctionBodyExpression)
{
+ SourceParseMode bodySourceParseMode = mode;
+ if (mode == SourceParseMode::AsyncGeneratorBodyMode) {
+ ASSERT(Options::useAsyncIterator());
+ bodySourceParseMode = SourceParseMode::AsyncFunctionBodyMode;
+ } else if (mode == SourceParseMode::AsyncGeneratorWrapperFunctionMode) {
+ ASSERT(Options::useAsyncIterator());
+ bodySourceParseMode = SourceParseMode::ArrowFunctionMode;
+ } else if (mode == SourceParseMode::AsyncGeneratorWrapperMethodMode) {
+ ASSERT(Options::useAsyncIterator());
+ bodySourceParseMode = SourceParseMode::AsyncMethodMode;
+ }
+
return new (m_parserArena) FunctionMetadataNode(
m_parserArena, startLocation, endLocation, startColumn, endColumn,
functionKeywordStart, functionNameStart, parametersStart,
inStrictContext, constructorKind, superBinding,
- parameterCount, mode, isArrowFunctionBodyExpression);
+ parameterCount, bodySourceParseMode, isArrowFunctionBodyExpression);
}
ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)
namespace JSC {
+ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
+{
+ if (isAsyncGeneratorFunctionParseMode(parseMode))
+ return SourceParseMode::AsyncGeneratorBodyMode;
+
+ if (parseMode == SourceParseMode::AsyncArrowFunctionMode)
+ return SourceParseMode::AsyncArrowFunctionBodyMode;
+
+ return SourceParseMode::AsyncFunctionBodyMode;
+}
+
template <typename LexerType>
void Parser<LexerType>::logError(bool)
{
sourceElements = parseModuleSourceElements(context, parseMode);
else if (isGeneratorWrapperParseMode(parseMode))
sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
+ else if (isAsyncGeneratorFunctionParseMode(parseMode))
+ sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
else
sourceElements = parseSourceElements(context, CheckForStrictMode);
}
for (auto& entry : capturedVariables)
varDeclarations.markVariableAsCaptured(entry);
- if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
+ if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode)) {
if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
context.propagateArgumentsUse();
}
template <typename LexerType>
template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
{
- ASSERT(isAsyncFunctionWrapperParseMode(parseMode));
+ ASSERT(isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode));
auto sourceElements = context.createSourceElements();
unsigned functionKeywordStart = tokenStart();
createGeneratorParameters(context, info.parameterCount);
info.startOffset = parametersStart;
info.startLine = tokenLine();
- SourceParseMode innerParseMode = parseMode == SourceParseMode::AsyncArrowFunctionMode
- ? SourceParseMode::AsyncArrowFunctionBodyMode
- : SourceParseMode::AsyncFunctionBodyMode;
+
+ SourceParseMode innerParseMode = getAsynFunctionBodyParseMode(parseMode);
+
{
AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
return sourceElements;
}
+template <typename LexerType>
+template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
+{
+ ASSERT_UNUSED(parseMode, isAsyncGeneratorFunctionParseMode(parseMode));
+ auto sourceElements = context.createSourceElements();
+
+ unsigned functionKeywordStart = tokenStart();
+ JSTokenLocation startLocation(tokenLocation());
+ JSTextPosition start = tokenStartPosition();
+ unsigned startColumn = tokenColumn();
+ int functionNameStart = m_token.m_location.startOffset;
+ int parametersStart = m_token.m_location.startOffset;
+
+ ParserFunctionInfo<TreeBuilder> info;
+ info.name = &m_vm->propertyNames->nullIdentifier;
+ createGeneratorParameters(context, info.parameterCount);
+ info.startOffset = parametersStart;
+ info.startLine = tokenLine();
+ SourceParseMode innerParseMode = SourceParseMode::AsyncGeneratorBodyMode;
+ {
+ AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
+ asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
+ SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
+ if (isArrowFunctionBodyExpression) {
+ if (m_debuggerParseData)
+ failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
+ else
+ failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
+ } else {
+ if (m_debuggerParseData)
+ failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
+ else
+ failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
+ }
+ popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
+ }
+ info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
+
+ info.endLine = tokenLine();
+ info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
+ info.parametersStartColumn = startColumn;
+
+ auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
+ auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
+ context.appendStatement(sourceElements, statement);
+
+ return sourceElements;
+}
+
template <typename LexerType>
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
{
return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
}
+static const char* stringArticleForFunctionMode(SourceParseMode mode)
+{
+ switch (mode) {
+ case SourceParseMode::GetterMode:
+ case SourceParseMode::SetterMode:
+ case SourceParseMode::NormalFunctionMode:
+ case SourceParseMode::MethodMode:
+ case SourceParseMode::GeneratorBodyMode:
+ case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode:
+ return "a ";
+ case SourceParseMode::ArrowFunctionMode:
+ case SourceParseMode::AsyncFunctionMode:
+ case SourceParseMode::AsyncFunctionBodyMode:
+ case SourceParseMode::AsyncMethodMode:
+ case SourceParseMode::AsyncArrowFunctionBodyMode:
+ case SourceParseMode::AsyncArrowFunctionMode:
+ case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
+ case SourceParseMode::AsyncGeneratorBodyMode:
+ case SourceParseMode::AsyncGeneratorWrapperMethodMode:
+ return "an ";
+ case SourceParseMode::ProgramMode:
+ case SourceParseMode::ModuleAnalyzeMode:
+ case SourceParseMode::ModuleEvaluateMode:
+ RELEASE_ASSERT_NOT_REACHED();
+ return "";
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
static const char* stringForFunctionMode(SourceParseMode mode)
{
switch (mode) {
case SourceParseMode::AsyncArrowFunctionBodyMode:
case SourceParseMode::AsyncArrowFunctionMode:
return "async arrow function";
+ case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
+ case SourceParseMode::AsyncGeneratorBodyMode:
+ return "async generator function";
+ case SourceParseMode::AsyncGeneratorWrapperMethodMode:
+ return "async generator method";
case SourceParseMode::ProgramMode:
case SourceParseMode::ModuleAnalyzeMode:
case SourceParseMode::ModuleEvaluateMode:
functionInfo.name = m_token.m_data.ident;
m_parserState.lastFunctionName = functionInfo.name;
if (UNLIKELY(isDisallowedAwaitFunctionName))
- semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
- else if (isAsyncFunctionWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
- semanticFail("Cannot declare async function named 'await'");
+ 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'");
next();
if (isGeneratorOrAsyncFunctionWrapperParseMode(mode)) {
AutoPopScopeRef generatorBodyScope(this, pushScope());
SourceParseMode innerParseMode = SourceParseMode::GeneratorBodyMode;
- if (isAsyncFunctionWrapperParseMode(mode)) {
- innerParseMode = mode == SourceParseMode::AsyncArrowFunctionMode
- ? SourceParseMode::AsyncArrowFunctionBodyMode
- : SourceParseMode::AsyncFunctionBodyMode;
- }
+ if (isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode))
+ innerParseMode = getAsynFunctionBodyParseMode(mode);
+
generatorBodyScope->setSourceParseMode(innerParseMode);
generatorBodyScope->setConstructorKind(ConstructorKind::None);
generatorBodyScope->setExpectedSuperBinding(expectedSuperBinding);
context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
ASSERT(functionInfo.name);
- RELEASE_ASSERT(SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::MethodMode, SourceParseMode::ArrowFunctionMode, SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(mode) || isAsyncFunctionWrapperParseMode(mode));
+ RELEASE_ASSERT(SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::MethodMode, SourceParseMode::ArrowFunctionMode, SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(mode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode));
semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
}
next();
ParserFunctionInfo<TreeBuilder> functionInfo;
SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
+ if (Options::useAsyncIterator() && consume(TIMES))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperFunctionMode;
+
FunctionNameRequirements requirements = FunctionNameRequirements::Named;
if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
// Under the "export default" context, function declaration does not require the function name.
TreeExpression computedPropertyName = 0;
bool isGetter = false;
bool isSetter = false;
- bool isGenerator = false;
- bool isAsync = false;
- bool isAsyncMethod = false;
+ SourceParseMode parseMode = SourceParseMode::MethodMode;
if (consume(TIMES))
- isGenerator = true;
+ parseMode = SourceParseMode::GeneratorWrapperMethodMode;
parseMethod:
switch (m_token.m_type) {
next();
break;
case ASYNC:
- isAsync = !isGenerator && !isAsyncMethod;
+ if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode)) {
+ ident = m_token.m_data.ident;
+ next();
+ if (match(OPENPAREN) || match(COLON) || match(EQUAL) || m_lexer->prevTerminator())
+ break;
+ if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
+ else
+ parseMode = SourceParseMode::AsyncMethodMode;
+ goto parseMethod;
+ }
FALLTHROUGH;
case IDENT:
case AWAIT:
ident = m_token.m_data.ident;
ASSERT(ident);
next();
- if (!isGenerator && !isAsyncMethod && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
+ if (parseMode == SourceParseMode::MethodMode && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
isGetter = *ident == propertyNames.get;
isSetter = *ident == propertyNames.set;
-
- if (UNLIKELY(isAsync && !m_lexer->prevTerminator())) {
- isAsyncMethod = true;
- goto parseMethod;
- }
}
break;
case DOUBLE:
} else {
ParserFunctionInfo<TreeBuilder> methodInfo;
bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
- SourceParseMode parseMode = SourceParseMode::MethodMode;
- if (isAsyncMethod) {
+ if (isAsyncMethodParseMode(parseMode) || isAsyncGeneratorMethodParseMode(parseMode) || isGeneratorMethodParseMode(parseMode)) {
isConstructor = false;
- parseMode = SourceParseMode::AsyncMethodMode;
- semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare an async method named 'prototype'");
- semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare an async method named 'constructor'");
- } else if (isGenerator) {
- isConstructor = false;
- parseMode = SourceParseMode::GeneratorWrapperMethodMode;
- semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
- semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
+ semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare ", stringArticleForFunctionMode(parseMode), stringForFunctionMode(parseMode), " named 'prototype'");
+ semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare ", stringArticleForFunctionMode(parseMode), stringForFunctionMode(parseMode), " named 'constructor'");
}
+
methodInfo.name = isConstructor ? info.className : ident;
failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
template <typename LexerType>
template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
{
+ SourceParseMode parseMode = SourceParseMode::MethodMode;
bool wasIdent = false;
- bool isAsync = false;
- bool isGenerator = false;
bool isClassProperty = false;
bool isStaticMethod = false;
- bool isAsyncMethod = false;
+
if (consume(TIMES))
- isGenerator = true;
+ parseMode = SourceParseMode::GeneratorWrapperMethodMode;
parseProperty:
switch (m_token.m_type) {
case ASYNC:
- isAsync = !isGenerator && !isAsyncMethod;
+ if (parseMode == SourceParseMode::MethodMode) {
+ SavePoint savePoint = createSavePoint();
+ next();
+
+ if (match(COLON) || match(OPENPAREN) || match(COMMA) || match(CLOSEBRACE)) {
+ restoreSavePoint(savePoint);
+ wasIdent = true;
+ goto namedProperty;
+ }
+
+ failIfTrue(m_lexer->prevTerminator(), "Expected a property name following keyword 'async'");
+ if (Options::useAsyncIterator() && UNLIKELY(consume(TIMES)))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
+ else
+ parseMode = SourceParseMode::AsyncMethodMode;
+ goto parseProperty;
+ }
FALLTHROUGH;
case IDENT:
case YIELD:
FALLTHROUGH;
case STRING: {
namedProperty:
- JSToken identToken = m_token;
const Identifier* ident = m_token.m_data.ident;
unsigned getterOrSetterStartOffset = tokenStart();
+ JSToken identToken = m_token;
- if (complete || (wasIdent && !isGenerator && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)) || isAsync)
+ if (complete || (wasIdent && !isGeneratorMethodParseMode(parseMode) && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
else
nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
- if (!isGenerator && !isAsyncMethod && match(COLON)) {
+ if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode) && match(COLON)) {
next();
TreeExpression node = parseAssignmentExpressionOrPropagateErrorClass(context);
failIfFalse(node, "Cannot parse expression for property declaration");
}
if (match(OPENPAREN)) {
- auto method = parsePropertyMethod(context, ident, isGenerator, isAsyncMethod);
+ auto method = parsePropertyMethod(context, ident, parseMode);
propagateError();
return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete, SuperBinding::Needed, InferName::Allowed, isClassProperty);
}
- failIfTrue(isGenerator || isAsyncMethod, "Expected a parenthesis for argument list");
+ failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
failIfFalse(wasIdent, "Expected an identifier as property name");
type = PropertyNode::Getter;
else if (*ident == m_vm->propertyNames->set)
type = PropertyNode::Setter;
- else if (UNLIKELY(isAsync && !isAsyncMethod)) {
- isAsyncMethod = true;
- failIfTrue(m_lexer->prevTerminator(), "Expected a property name following keyword 'async'");
- goto parseProperty;
- } else
+ else
failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, isClassProperty, isStaticMethod);
}
if (match(OPENPAREN)) {
const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
- auto method = parsePropertyMethod(context, &ident, isGenerator, isAsyncMethod);
+ auto method = parsePropertyMethod(context, &ident, parseMode);
propagateError();
return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, InferName::Allowed, isClassProperty);
}
- failIfTrue(isGenerator || isAsyncMethod, "Expected a parenthesis for argument list");
+ failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
consumeOrFail(COLON, "Expected ':' after property name");
TreeExpression node = parseAssignmentExpression(context);
handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
if (match(OPENPAREN)) {
- auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, isGenerator, isAsyncMethod);
+ auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, parseMode);
propagateError();
return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete, SuperBinding::Needed, isClassProperty);
}
- failIfTrue(isGenerator || isAsyncMethod, "Expected a parenthesis for argument list");
+ failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
consumeOrFail(COLON, "Expected ':' after property name");
TreeExpression node = parseAssignmentExpression(context);
}
template <typename LexerType>
-template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod)
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode parseMode)
{
+ ASSERT(isMethodParseMode(parseMode));
JSTokenLocation methodLocation(tokenLocation());
unsigned methodStart = tokenStart();
ParserFunctionInfo<TreeBuilder> methodInfo;
methodInfo.name = methodName;
- SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperMethodMode : isAsyncMethod ? SourceParseMode::AsyncMethodMode : SourceParseMode::MethodMode;
failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
return context.createMethodDefinition(methodLocation, methodInfo);
}
JSTokenLocation location(tokenLocation());
unsigned functionKeywordStart = tokenStart();
next();
+ SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
+
+ if (Options::useAsyncIterator() && consume(TIMES))
+ parseMode = SourceParseMode::AsyncGeneratorWrapperFunctionMode;
+
ParserFunctionInfo<TreeBuilder> functionInfo;
functionInfo.name = &m_vm->propertyNames->nullIdentifier;
- SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
- failIfFalse(parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression), "Cannot parse async function expression");
+ failIfFalse(parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression), parseMode == SourceParseMode::AsyncFunctionMode ? "Cannot parse async function expression" : "Cannot parse async generator function expression");
return context.createFunctionExpr(location, functionInfo);
}
void setSourceParseMode(SourceParseMode mode)
{
switch (mode) {
+ case SourceParseMode::AsyncGeneratorBodyMode:
+ setIsAsyncFunctionBody();
+ setIsGenerator();
+ break;
case SourceParseMode::AsyncArrowFunctionBodyMode:
setIsAsyncArrowFunctionBody();
break;
setIsGeneratorFunction();
break;
+ case SourceParseMode::AsyncGeneratorWrapperMethodMode:
+ case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
+ setIsAsyncFunction();
+ setIsGeneratorFunction();
+ break;
+
case SourceParseMode::NormalFunctionMode:
case SourceParseMode::GetterMode:
case SourceParseMode::SetterMode:
template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
template <class TreeBuilder> TreeSourceElements parseGeneratorFunctionSourceElements(TreeBuilder&, const Identifier& name, SourceElementsMode);
template <class TreeBuilder> TreeSourceElements parseAsyncFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
+ template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
enum class ExportType { Exported, NotExported };
template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&);
template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
- template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod);
+ template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode);
template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, bool isClassProperty, bool isStaticMethod);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode);
template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, bool isMethod, unsigned&);
enum class FunctionMode { FunctionExpression, FunctionDeclaration, MethodDefinition };
-enum class SourceParseMode : uint16_t {
- NormalFunctionMode = 0b0000000000000001,
- GeneratorBodyMode = 0b0000000000000010,
- GeneratorWrapperFunctionMode = 0b0000000000000100,
- GeneratorWrapperMethodMode = 0b0000000000001000,
- GetterMode = 0b0000000000010000,
- SetterMode = 0b0000000000100000,
- MethodMode = 0b0000000001000000,
- ArrowFunctionMode = 0b0000000010000000,
- AsyncFunctionBodyMode = 0b0000000100000000,
- AsyncArrowFunctionBodyMode = 0b0000001000000000,
- AsyncFunctionMode = 0b0000010000000000,
- AsyncMethodMode = 0b0000100000000000,
- AsyncArrowFunctionMode = 0b0001000000000000,
- ProgramMode = 0b0010000000000000,
- ModuleAnalyzeMode = 0b0100000000000000,
- ModuleEvaluateMode = 0b1000000000000000,
+enum class SourceParseMode : uint32_t {
+ NormalFunctionMode = 0b00000000000000000000000000000001,
+ GeneratorBodyMode = 0b00000000000000000000000000000010,
+ GeneratorWrapperFunctionMode = 0b00000000000000000000000000000100,
+ GetterMode = 0b00000000000000000000000000001000,
+ SetterMode = 0b00000000000000000000000000010000,
+ MethodMode = 0b00000000000000000000000000100000,
+ ArrowFunctionMode = 0b00000000000000000000000001000000,
+ AsyncFunctionBodyMode = 0b00000000000000000000000010000000,
+ AsyncArrowFunctionBodyMode = 0b00000000000000000000000100000000,
+ AsyncFunctionMode = 0b00000000000000000000001000000000,
+ AsyncMethodMode = 0b00000000000000000000010000000000,
+ AsyncArrowFunctionMode = 0b00000000000000000000100000000000,
+ ProgramMode = 0b00000000000000000001000000000000,
+ ModuleAnalyzeMode = 0b00000000000000000010000000000000,
+ ModuleEvaluateMode = 0b00000000000000000100000000000000,
+ AsyncGeneratorBodyMode = 0b00000000000000001000000000000000,
+ AsyncGeneratorWrapperFunctionMode = 0b00000000000000010000000000000000,
+ AsyncGeneratorWrapperMethodMode = 0b00000000000000100000000000000000,
+ GeneratorWrapperMethodMode = 0b00000000000001000000000000000000,
};
class SourceParseModeSet {
SourceParseMode::AsyncFunctionMode,
SourceParseMode::AsyncMethodMode,
SourceParseMode::AsyncArrowFunctionMode,
- SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
+ SourceParseMode::AsyncArrowFunctionBodyMode,
+ SourceParseMode::AsyncGeneratorBodyMode,
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}
ALWAYS_INLINE bool isAsyncFunctionParseMode(SourceParseMode parseMode)
{
- return SourceParseModeSet(
+ return SourceParseModeSet(
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorBodyMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode,
SourceParseMode::AsyncFunctionBodyMode,
SourceParseMode::AsyncFunctionMode,
SourceParseMode::AsyncMethodMode,
ALWAYS_INLINE bool isAsyncArrowFunctionParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
- SourceParseMode::AsyncArrowFunctionMode,
+ SourceParseMode::AsyncArrowFunctionMode,
SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
}
+ALWAYS_INLINE bool isAsyncGeneratorFunctionParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isAsyncFunctionOrAsyncGeneratorWrapperParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::AsyncArrowFunctionMode,
+ SourceParseMode::AsyncFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode,
+ SourceParseMode::AsyncMethodMode).contains(parseMode);
+ }
+
ALWAYS_INLINE bool isAsyncFunctionWrapperParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
SourceParseMode::AsyncArrowFunctionMode,
- SourceParseMode::AsyncFunctionMode,
+ SourceParseMode::AsyncFunctionMode,
SourceParseMode::AsyncMethodMode).contains(parseMode);
-}
+}
ALWAYS_INLINE bool isAsyncFunctionBodyParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
- SourceParseMode::AsyncFunctionBodyMode,
+ SourceParseMode::AsyncFunctionBodyMode,
+ SourceParseMode::AsyncGeneratorBodyMode,
SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
-}
+}
+
+ALWAYS_INLINE bool isGeneratorMethodParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::GeneratorWrapperMethodMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isAsyncMethodParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(SourceParseMode::AsyncMethodMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isAsyncGeneratorMethodParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(SourceParseMode::AsyncGeneratorWrapperFunctionMode).contains(parseMode);
+}
ALWAYS_INLINE bool isMethodParseMode(SourceParseMode parseMode)
{
SourceParseMode::GetterMode,
SourceParseMode::SetterMode,
SourceParseMode::MethodMode,
- SourceParseMode::AsyncMethodMode).contains(parseMode);
+ SourceParseMode::AsyncMethodMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}
ALWAYS_INLINE bool isGeneratorOrAsyncFunctionBodyParseMode(SourceParseMode parseMode)
return SourceParseModeSet(
SourceParseMode::GeneratorBodyMode,
SourceParseMode::AsyncFunctionBodyMode,
+ SourceParseMode::AsyncGeneratorBodyMode,
SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
}
SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::AsyncFunctionMode,
SourceParseMode::AsyncArrowFunctionMode,
- SourceParseMode::AsyncMethodMode).contains(parseMode);
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncMethodMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}
ALWAYS_INLINE bool isGeneratorParseMode(SourceParseMode parseMode)