[Next] Async iteration - Implement Async Generator - parser
authorgskachkov@gmail.com <gskachkov@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 6 Aug 2017 13:04:32 +0000 (13:04 +0000)
committergskachkov@gmail.com <gskachkov@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 6 Aug 2017 13:04:32 +0000 (13:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175210

Reviewed by Yusuke Suzuki.

JSTests:

* 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:

Source/JavaScriptCore:

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):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220323 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/async-await-syntax.js
JSTests/stress/async-iteration-syntax.js [new file with mode: 0644]
JSTests/stress/generator-class-methods-syntax.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h

index ae6a9040430b3b5bebd1d5b0ade9a7bcad87546b..3ed359ed3b6304dfdbca0d4029b8f80dd9537083 100644 (file)
@@ -1,3 +1,22 @@
+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
index 83de41f1ff9de2f898fbb936cf0648d6261c065d..1b3dba41c531d14164261031afa0e14211ee2532 100644 (file)
@@ -32,10 +32,12 @@ function testSyntaxError(script, message) {
 }
 
 (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; } };`);
@@ -65,10 +67,12 @@ function testSyntaxError(script, message) {
 })();
 
 (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; } };`);
@@ -155,6 +159,9 @@ function testSyntaxError(script, message) {
 
 
 (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'; };`);
@@ -186,10 +193,10 @@ function testSyntaxError(script, message) {
 
     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; }`);
@@ -241,6 +248,9 @@ function testSyntaxError(script, message) {
 })();
 
 (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'; };`);
@@ -257,10 +267,7 @@ function testSyntaxError(script, message) {
 
     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() {} };`);
diff --git a/JSTests/stress/async-iteration-syntax.js b/JSTests/stress/async-iteration-syntax.js
new file mode 100644 (file)
index 0000000..310e72e
--- /dev/null
@@ -0,0 +1,123 @@
+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 })");
+})();
index 2465ceb1f436c02e36d8b0ac5ba7de325557700c..2a8a0ce9c71d67a734dea968a842df18964c8c7c 100644 (file)
@@ -27,7 +27,7 @@ class Cocoa {
     {
     }
 }
-`, `SyntaxError: Cannot declare a generator named 'constructor'.`);
+`, `SyntaxError: Cannot declare a generator function named 'constructor'.`);
 
 testSyntax(`
 class Cocoa {
index a5e26c090e5bc883ccb10f942b51caccea3bbbe5..2ca8acef7f89f429893397fd6414bc05d815a37a 100644 (file)
@@ -1,3 +1,48 @@
+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
index 280c727d2505056896d7abe7f8057061073166a0..0e77e3a5d704e31b1095b46159aded5654948f33 100644 (file)
@@ -437,11 +437,23 @@ public:
         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)
index ca6d820f0bb693cf85bbd4ea3ae35b355f46daa2..74d1e45489fd4469d49d31176c3777f593607e0e 100644 (file)
@@ -90,6 +90,17 @@ using namespace std;
 
 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)
 {
@@ -228,6 +239,8 @@ String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMo
             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);
     }
@@ -249,7 +262,7 @@ String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMo
     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();
     }
@@ -502,7 +515,7 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGenerato
 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();
@@ -517,9 +530,9 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFun
     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);
@@ -550,6 +563,55 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFun
     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)
 {
@@ -2006,6 +2068,37 @@ template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBo
     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) {
@@ -2032,6 +2125,11 @@ static const char* stringForFunctionMode(SourceParseMode 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:
@@ -2303,9 +2401,9 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
                 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();
@@ -2387,11 +2485,9 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
     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);
@@ -2416,7 +2512,7 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
     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");
     }
@@ -2542,6 +2638,9 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunction
     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.
@@ -2703,11 +2802,9 @@ template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(T
         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) {
@@ -2718,21 +2815,26 @@ parseMethod:
             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:
@@ -2763,18 +2865,12 @@ parseMethod:
         } 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");
 
@@ -3761,19 +3857,34 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpres
 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:
@@ -3782,16 +3893,16 @@ parseProperty:
         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");
@@ -3801,11 +3912,11 @@ namedProperty:
         }
 
         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");
 
@@ -3828,11 +3939,7 @@ namedProperty:
             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);
     }
@@ -3843,11 +3950,11 @@ namedProperty:
 
         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);
@@ -3862,11 +3969,11 @@ namedProperty:
         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);
@@ -3895,13 +4002,13 @@ namedProperty:
 }
 
 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);
 }
@@ -4203,10 +4310,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseAsyncFunctio
     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);
 }
 
index 07feb39c47115e967cbb93dd9ff67a8c314c3ee0..77cf0cec19f5b228b692e3ab9c810e985869918d 100644 (file)
@@ -225,6 +225,10 @@ public:
     void setSourceParseMode(SourceParseMode mode)
     {
         switch (mode) {
+        case SourceParseMode::AsyncGeneratorBodyMode:
+            setIsAsyncFunctionBody();
+            setIsGenerator();
+            break;
         case SourceParseMode::AsyncArrowFunctionBodyMode:
             setIsAsyncArrowFunctionBody();
             break;
@@ -242,6 +246,12 @@ public:
             setIsGeneratorFunction();
             break;
 
+        case SourceParseMode::AsyncGeneratorWrapperMethodMode:
+        case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
+            setIsAsyncFunction();
+            setIsGeneratorFunction();
+            break;
+    
         case SourceParseMode::NormalFunctionMode:
         case SourceParseMode::GetterMode:
         case SourceParseMode::SetterMode:
@@ -1495,6 +1505,7 @@ private:
     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 };
@@ -1541,7 +1552,7 @@ private:
     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&);
index 9a96f5d17bde7040119650e8164f38de13d40034..82229ad058176a4ca0bce038f084796f1f58ae01 100644 (file)
@@ -42,23 +42,26 @@ enum DebuggerMode { DebuggerOff, DebuggerOn };
 
 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 { 
@@ -104,12 +107,18 @@ ALWAYS_INLINE bool isFunctionParseMode(SourceParseMode parseMode)
         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, 
@@ -120,24 +129,58 @@ ALWAYS_INLINE bool isAsyncFunctionParseMode(SourceParseMode parseMode)
 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)
 {
@@ -146,7 +189,8 @@ 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)
@@ -154,6 +198,7 @@ ALWAYS_INLINE bool isGeneratorOrAsyncFunctionBodyParseMode(SourceParseMode parse
     return SourceParseModeSet(
         SourceParseMode::GeneratorBodyMode,
         SourceParseMode::AsyncFunctionBodyMode,
+        SourceParseMode::AsyncGeneratorBodyMode,
         SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
 }
 
@@ -164,7 +209,9 @@ ALWAYS_INLINE bool isGeneratorOrAsyncFunctionWrapperParseMode(SourceParseMode pa
         SourceParseMode::GeneratorWrapperMethodMode,
         SourceParseMode::AsyncFunctionMode,
         SourceParseMode::AsyncArrowFunctionMode,
-        SourceParseMode::AsyncMethodMode).contains(parseMode);
+        SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+        SourceParseMode::AsyncMethodMode,
+        SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
 }
 
 ALWAYS_INLINE bool isGeneratorParseMode(SourceParseMode parseMode)