test262: test262/test/language/expressions/object/method-definition/early-errors...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Apr 2017 06:52:04 +0000 (06:52 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Apr 2017 06:52:04 +0000 (06:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171190

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2017-04-24
Reviewed by Saam Barati.

JSTests:

* stress/async-await-syntax.js:
* test262.yaml:

Source/JavaScriptCore:

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
(JSC::BytecodeGenerator::emitNewFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
(JSC::Scope::setSourceParseMode):
* parser/ParserModes.h:
(JSC::isFunctionParseMode):
(JSC::isMethodParseMode):
(JSC::isGeneratorOrAsyncFunctionWrapperParseMode):
(JSC::isGeneratorParseMode):
(JSC::isGeneratorWrapperParseMode):
* runtime/FunctionExecutable.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
Add a new GeneratorWrapperMethodMode parse mode. The other function types
(async, arrow) already have a FunctionMode and a MethodMode. Give
generators one as well. This lets isMethodParseMode actually be accurate.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::isArrowFunctionParameters):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parsePropertyMethod):
* parser/Parser.h:
Add a duplicate parameter failure if there are duplicate parameters
in method syntax.

LayoutTests:

* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:
Extend to cover method duplicate parameter cases.

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

14 files changed:
JSTests/ChangeLog
JSTests/stress/async-await-syntax.js
JSTests/test262.yaml
LayoutTests/ChangeLog
LayoutTests/js/parser-syntax-check-expected.txt
LayoutTests/js/script-tests/parser-syntax-check.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h
Source/JavaScriptCore/runtime/FunctionExecutable.h
Source/JavaScriptCore/runtime/JSFunction.cpp

index 7a7c18c..078b146 100644 (file)
@@ -1,3 +1,13 @@
+2017-04-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
+        https://bugs.webkit.org/show_bug.cgi?id=171190
+
+        Reviewed by Saam Barati.
+
+        * stress/async-await-syntax.js:
+        * test262.yaml:
+
 2017-04-24  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] Use JSFixedArray directly when using call_varargs
index 5a7d4f5..47c1f57 100644 (file)
@@ -137,12 +137,25 @@ function testSyntaxError(script, message) {
     testSyntaxError(`var asyncFn = async (await) => 'test';`);
     testSyntaxError(`async function asyncFunctionDeclaration(await) {}`);
 
-    // FIXME: MethodDefinitions do not apply StrictFormalParameters restrictions
-    //        in sloppy mode (https://bugs.webkit.org/show_bug.cgi?id=161408)
-    //testSyntaxError(`var outerObject = { async method(a, a) {} }`);
-    //testSyntaxError(`var outerObject = { async ['meth' + 'od'](a, a) {} }`);
-    //testSyntaxError(`var outerObject = { async 'method'(a, a) {} }`);
-    //testSyntaxError(`var outerObject = { async 0(a, a) {} }`);
+    testSyntaxError(`var outerObject = { async method(a, a) {} }`);
+    testSyntaxError(`var outerObject = { async ['meth' + 'od'](a, a) {} }`);
+    testSyntaxError(`var outerObject = { async 'method'(a, a) {} }`);
+    testSyntaxError(`var outerObject = { async 0(a, a) {} }`);
+
+    testSyntaxError(`var outerObject = { async method(a, {a}) {} }`);
+    testSyntaxError(`var outerObject = { async method({a}, a) {} }`);
+    testSyntaxError(`var outerObject = { async method({a}, {a}) {} }`);
+    testSyntaxError(`var outerObject = { async method(a, ...a) {} }`);
+    testSyntaxError(`var outerObject = { async method({a}, ...a) {} }`);
+    testSyntaxError(`var outerObject = { async method(a, ...a) {} }`);
+    testSyntaxError(`var outerObject = { async method({a, ...a}) {} }`);
+    testSyntaxError(`var outerObject = { func: async function(a, {a}) {} }`);
+    testSyntaxError(`var outerObject = { func: async function({a}, a) {} }`);
+    testSyntaxError(`var outerObject = { func: async function({a}, {a}) {} }`);
+    testSyntaxError(`var outerObject = { func: async function(a, ...a) {} }`);
+    testSyntaxError(`var outerObject = { func: async function({a}, ...a) {} }`);
+    testSyntaxError(`var outerObject = { func: async function(a, ...a) {} }`);
+    testSyntaxError(`var outerObject = { func: async function({a, ...a}) {} }`);
 
     testSyntaxError(`var asyncArrowFn = async() => await;`);
 
index c1578ad..13ec9f8 100644 (file)
 - path: test262/test/language/expressions/object/method-definition/early-errors-object-method-body-contains-super-call.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
-  cmd: runTest262 :fail, "SyntaxError", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "SyntaxError", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], []
 - path: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../../harness/assert.js", "../../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/expressions/object/method-definition/early-errors-object-method-eval-in-formal-parameters.js
index 90af825..29192d5 100644 (file)
@@ -1,3 +1,14 @@
+2017-04-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
+        https://bugs.webkit.org/show_bug.cgi?id=171190
+
+        Reviewed by Saam Barati.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+        Extend to cover method duplicate parameter cases.
+
 2017-04-24  Jiewen Tan  <jiewen_tan@apple.com>
 
         LayoutTests crypto/subtle/ecdsa-generate-key-sign-verify-p384.html and crypto/subtle/ecdsa-generate-key-sign-verify-p256.html are flaky failures
index 4f17c92..fe71077 100644 (file)
@@ -1514,8 +1514,6 @@ PASS Invalid: "let x = ([a],a)=>{ };". Produced the following syntax error: "Syn
 PASS Invalid: "function f() { let x = ([a],a)=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
 PASS Invalid: "let x = ([a, a])=>{ };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
 PASS Invalid: "function f() { let x = ([a, a])=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
-PASS Invalid: "let x = ([a, a])=>{ };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
-PASS Invalid: "function f() { let x = ([a, a])=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
 PASS Invalid: "let x = (a, ...a)=>{ };". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
 PASS Invalid: "function f() { let x = (a, ...a)=>{ }; }". Produced the following syntax error: "SyntaxError: Unexpected token '...'"
 PASS Invalid: "let x = (b, c, b)=>{ };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in an arrow function."
@@ -1530,6 +1528,68 @@ PASS Invalid: "let x = (a)
 =>a;". Produced the following syntax error: "SyntaxError: Unexpected token '=>'"
 PASS Invalid: "function f() { let x = (a)
 =>a; }". Produced the following syntax error: "SyntaxError: Unexpected token '=>'"
+PASS Invalid: "({ foo(a,a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "function f() { ({ foo(a,a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "({ foo(b, c, b){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Invalid: "function f() { ({ foo(b, c, b){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Invalid: "({ *foo(a,a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "function f() { ({ *foo(a,a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "({ *foo(b, c, b){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Invalid: "function f() { ({ *foo(b, c, b){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Invalid: "({ async foo(a,a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "function f() { ({ async foo(a,a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in a method."
+PASS Invalid: "({ async foo(b, c, b){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Invalid: "function f() { ({ async foo(b, c, b){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in a method."
+PASS Valid:   "({ foo: function(a,a){} });"
+PASS Valid:   "function f() { ({ foo: function(a,a){} }); }"
+PASS Valid:   "({ foo: function(b, c, b){} });"
+PASS Valid:   "function f() { ({ foo: function(b, c, b){} }); }"
+PASS Valid:   "({ foo: function*(a,a){} });"
+PASS Valid:   "function f() { ({ foo: function*(a,a){} }); }"
+PASS Valid:   "({ foo: function*(b, c, b){} });"
+PASS Valid:   "function f() { ({ foo: function*(b, c, b){} }); }"
+PASS Valid:   "({ foo: async function(a,a){} });"
+PASS Valid:   "function f() { ({ foo: async function(a,a){} }); }"
+PASS Valid:   "({ foo: async function(b, c, b){} });"
+PASS Valid:   "function f() { ({ foo: async function(b, c, b){} }); }"
+PASS Invalid: "({ foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ foo(a,{a}){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ foo(a,{a}){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ foo(a,...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "function f() { ({ foo(a,...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "({ foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ *foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ *foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ *foo(a,{a}){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ *foo(a,{a}){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ *foo(a,...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "function f() { ({ *foo(a,...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "({ *foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ *foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ *foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ *foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ async foo({a},a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ async foo({a},a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ async foo(a,{a}){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ async foo(a,{a}){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ async foo(a,...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "function f() { ({ async foo(a,...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with a rest parameter."
+PASS Invalid: "({ async foo({a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ async foo({a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "({ async foo({...a},...a){} });". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { ({ async foo({...a},...a){} }); }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Valid:   "({ foo(a, ...b){} });"
+PASS Valid:   "function f() { ({ foo(a, ...b){} }); }"
+PASS Valid:   "({ foo({a}, ...b){} });"
+PASS Valid:   "function f() { ({ foo({a}, ...b){} }); }"
+PASS Valid:   "({ foo({a, ...b}){} });"
+PASS Valid:   "function f() { ({ foo({a, ...b}){} }); }"
+PASS Valid:   "({ foo({b, ...a}, ...c){} });"
+PASS Valid:   "function f() { ({ foo({b, ...a}, ...c){} }); }"
 Weird things that used to crash.
 PASS Invalid: "or ([[{break //(elseifo (a=0;a<2;a++)n=
         [[{aFYY sga=
index 2061390..a71a18d 100644 (file)
@@ -869,7 +869,6 @@ invalid("let x = ({a, b:{a}})=>a;");
 invalid("let x = (a,a)=>{ a };");
 invalid("let x = ([a],a)=>{ };");
 invalid("let x = ([a, a])=>{ };");
-invalid("let x = ([a, a])=>{ };");
 invalid("let x = (a, ...a)=>{ };");
 invalid("let x = (b, c, b)=>{ };");
 invalid("let x = (a, b, c, d, {a})=>{ };");
@@ -877,6 +876,38 @@ invalid("let x = (b = (a,a)=>a, b)=>{ };");
 invalid("((a,a)=>a);");
 invalid("let x = (a)\n=>a;");
 
+invalid("({ foo(a,a){} });");
+invalid("({ foo(b, c, b){} });");
+invalid("({ *foo(a,a){} });");
+invalid("({ *foo(b, c, b){} });");
+invalid("({ async foo(a,a){} });");
+invalid("({ async foo(b, c, b){} });");
+valid("({ foo: function(a,a){} });");
+valid("({ foo: function(b, c, b){} });");
+valid("({ foo: function*(a,a){} });");
+valid("({ foo: function*(b, c, b){} });");
+valid("({ foo: async function(a,a){} });");
+valid("({ foo: async function(b, c, b){} });");
+invalid("({ foo({a},a){} });");
+invalid("({ foo(a,{a}){} });");
+invalid("({ foo(a,...a){} });");
+invalid("({ foo({a},...a){} });");
+invalid("({ foo({...a},...a){} });");
+invalid("({ *foo({a},a){} });");
+invalid("({ *foo(a,{a}){} });");
+invalid("({ *foo(a,...a){} });");
+invalid("({ *foo({a},...a){} });");
+invalid("({ *foo({...a},...a){} });");
+invalid("({ async foo({a},a){} });");
+invalid("({ async foo(a,{a}){} });");
+invalid("({ async foo(a,...a){} });");
+invalid("({ async foo({a},...a){} });");
+invalid("({ async foo({...a},...a){} });");
+valid("({ foo(a, ...b){} });");
+valid("({ foo({a}, ...b){} });");
+valid("({ foo({a, ...b}){} });");
+valid("({ foo({b, ...a}, ...c){} });");
+
 debug("Weird things that used to crash.");
 invalid(`or ([[{break //(elseifo (a=0;a<2;a++)n=
         [[{aFYY sga=
index b675495..602e623 100644 (file)
@@ -1,3 +1,43 @@
+2017-04-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
+        https://bugs.webkit.org/show_bug.cgi?id=171190
+
+        Reviewed by Saam Barati.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
+        (JSC::BytecodeGenerator::emitNewFunction):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::FunctionNode::emitBytecode):
+        (JSC::Scope::setSourceParseMode):
+        * parser/ParserModes.h:
+        (JSC::isFunctionParseMode):
+        (JSC::isMethodParseMode):
+        (JSC::isGeneratorOrAsyncFunctionWrapperParseMode):
+        (JSC::isGeneratorParseMode):
+        (JSC::isGeneratorWrapperParseMode):
+        * runtime/FunctionExecutable.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::getOwnPropertySlot):
+        Add a new GeneratorWrapperMethodMode parse mode. The other function types
+        (async, arrow) already have a FunctionMode and a MethodMode. Give
+        generators one as well. This lets isMethodParseMode actually be accurate.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::isArrowFunctionParameters):
+        (JSC::Parser<LexerType>::parseFormalParameters):
+        (JSC::stringForFunctionMode):
+        (JSC::Parser<LexerType>::parseFunctionParameters):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parsePropertyMethod):
+        * parser/Parser.h:
+        Add a duplicate parameter failure if there are duplicate parameters
+        in method syntax.
+
 2017-04-24  Andy VanWagoner  <thetalecrafter@gmail.com>
 
         Clean up ICU headers
index 048664d..f7724b5 100644 (file)
@@ -534,7 +534,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
 
     m_newTargetRegister = addVar();
     switch (parseMode) {
-    case SourceParseMode::GeneratorWrapperFunctionMode: {
+    case SourceParseMode::GeneratorWrapperFunctionMode:
+    case SourceParseMode::GeneratorWrapperMethodMode: {
         m_generatorRegister = addVar();
 
         // FIXME: Emit to_this only when Generator uses it.
@@ -3229,6 +3230,7 @@ void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, Functio
     OpcodeID opcodeID = op_new_func_exp;
     switch (function->parseMode()) {
     case SourceParseMode::GeneratorWrapperFunctionMode:
+    case SourceParseMode::GeneratorWrapperMethodMode:
         opcodeID = op_new_generator_func_exp;
         break;
     case SourceParseMode::AsyncFunctionMode:
@@ -3286,7 +3288,7 @@ RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, Constr
 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function)
 {
     unsigned index = m_codeBlock->addFunctionDecl(makeFunction(function));
-    if (function->parseMode() == SourceParseMode::GeneratorWrapperFunctionMode)
+    if (isGeneratorWrapperParseMode(function->parseMode()))
         emitOpcode(op_new_generator_func);
     else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
         emitOpcode(op_new_async_func);
index c33c9b8..9b3c943 100644 (file)
@@ -3512,7 +3512,8 @@ void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
     generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
 
     switch (generator.parseMode()) {
-    case SourceParseMode::GeneratorWrapperFunctionMode: {
+    case SourceParseMode::GeneratorWrapperFunctionMode:
+    case SourceParseMode::GeneratorWrapperMethodMode: {
         StatementNode* singleStatement = this->singleStatement();
         ASSERT(singleStatement->isExprStatement());
         ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
index a8918b0..4d6c2e3 100644 (file)
@@ -216,7 +216,7 @@ String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMo
             sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
         else if (isModuleParseMode(parseMode))
             sourceElements = parseModuleSourceElements(context, parseMode);
-        else if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
+        else if (isGeneratorWrapperParseMode(parseMode))
             sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
         else
             sourceElements = parseSourceElements(context, CheckForStrictMode);
@@ -239,7 +239,7 @@ String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMo
     for (auto& entry : capturedVariables)
         varDeclarations.markVariableAsCaptured(entry);
 
-    if (SourceParseModeSet(SourceParseMode::GeneratorWrapperFunctionMode).contains(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
+    if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
         if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
             context.propagateArgumentsUse();
     }
@@ -298,7 +298,8 @@ bool Parser<LexerType>::isArrowFunctionParameters()
 
             unsigned parametersCount = 0;
             bool isArrowFunctionParameterList = true;
-            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
+            bool isMethod = false;
+            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, isMethod, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
             propagateError();
             popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
         }
@@ -1850,7 +1851,7 @@ template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDecl
 }
 
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount)
+template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, bool isMethod, unsigned& parameterCount)
 {
 #define failIfDuplicateIfViolation() \
     if (duplicateParameter) {\
@@ -1858,6 +1859,7 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeB
         semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
         semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
         semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
+        semanticFailIfTrue(isMethod, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in a method");\
     }
 
     bool hasDefaultParameterValues = false;
@@ -1951,6 +1953,7 @@ static const char* stringForFunctionMode(SourceParseMode mode)
     case SourceParseMode::GeneratorBodyMode:
         return "generator";
     case SourceParseMode::GeneratorWrapperFunctionMode:
+    case SourceParseMode::GeneratorWrapperMethodMode:
         return "generator function";
     case SourceParseMode::ArrowFunctionMode:
         return "arrow function";
@@ -1990,7 +1993,8 @@ template <typename LexerType> template <class TreeBuilder, class FunctionInfoTyp
                     functionInfo.parameterCount = 0;
                 } else {
                     bool isArrowFunction = true;
-                    failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+                    bool isMethod = false;
+                    failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
                 }
                 
                 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
@@ -2034,7 +2038,8 @@ template <typename LexerType> template <class TreeBuilder, class FunctionInfoTyp
             functionInfo.parameterCount = 0;
         } else {
             bool isArrowFunction = false;
-            failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+            bool isMethod = isMethodParseMode(mode);
+            failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
         }
         consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
     }
@@ -2234,7 +2239,7 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
                     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'");
-                else if (mode == SourceParseMode::GeneratorWrapperFunctionMode && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
+                else if (isGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
                     semanticFail("Cannot declare generator function named 'yield'");
                 next();
                 if (!nameIsInContainingScope)
@@ -2699,7 +2704,7 @@ parseMethod:
                 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare an async method named 'constructor'");
             } else if (isGenerator) {
                 isConstructor = false;
-                parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
+                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'");
             }
@@ -3823,7 +3828,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMeth
     unsigned methodStart = tokenStart();
     ParserFunctionInfo<TreeBuilder> methodInfo;
     methodInfo.name = methodName;
-    SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : isAsyncMethod ? SourceParseMode::AsyncMethodMode : SourceParseMode::MethodMode;
+    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);
 }
index 94b3902..c35d5a1 100644 (file)
@@ -276,6 +276,7 @@ public:
             break;
 
         case SourceParseMode::GeneratorWrapperFunctionMode:
+        case SourceParseMode::GeneratorWrapperMethodMode:
             setIsGeneratorFunction();
             break;
 
@@ -1581,7 +1582,7 @@ private:
     template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod);
     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, unsigned&);
+    template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, bool isMethod, unsigned&);
     enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
     template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer);
     template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&);
index 5929846..9a96f5d 100644 (file)
@@ -46,18 +46,19 @@ enum class SourceParseMode : uint16_t {
     NormalFunctionMode            = 0b0000000000000001,
     GeneratorBodyMode             = 0b0000000000000010,
     GeneratorWrapperFunctionMode  = 0b0000000000000100,
-    GetterMode                    = 0b0000000000001000,
-    SetterMode                    = 0b0000000000010000,
-    MethodMode                    = 0b0000000000100000,
-    ArrowFunctionMode             = 0b0000000001000000,
-    AsyncFunctionBodyMode         = 0b0000000010000000,
-    AsyncArrowFunctionBodyMode    = 0b0000000100000000,
-    AsyncFunctionMode             = 0b0000001000000000,
-    AsyncMethodMode               = 0b0000010000000000,
-    AsyncArrowFunctionMode        = 0b0000100000000000,
-    ProgramMode                   = 0b0001000000000000,
-    ModuleAnalyzeMode             = 0b0010000000000000,
-    ModuleEvaluateMode            = 0b0100000000000000,
+    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,
 };
 
 class SourceParseModeSet { 
@@ -94,6 +95,7 @@ ALWAYS_INLINE bool isFunctionParseMode(SourceParseMode parseMode)
         SourceParseMode::NormalFunctionMode, 
         SourceParseMode::GeneratorBodyMode, 
         SourceParseMode::GeneratorWrapperFunctionMode, 
+        SourceParseMode::GeneratorWrapperMethodMode,
         SourceParseMode::GetterMode, 
         SourceParseMode::SetterMode, 
         SourceParseMode::MethodMode, 
@@ -140,8 +142,7 @@ ALWAYS_INLINE bool isAsyncFunctionBodyParseMode(SourceParseMode parseMode)
 ALWAYS_INLINE bool isMethodParseMode(SourceParseMode parseMode)
 {
     return SourceParseModeSet(
-        // FIXME: GeneratorWrapperFunctionMode is not guaranteed to be a method.
-        SourceParseMode::GeneratorWrapperFunctionMode,
+        SourceParseMode::GeneratorWrapperMethodMode,
         SourceParseMode::GetterMode,
         SourceParseMode::SetterMode,
         SourceParseMode::MethodMode,
@@ -160,11 +161,27 @@ ALWAYS_INLINE bool isGeneratorOrAsyncFunctionWrapperParseMode(SourceParseMode pa
 {
     return SourceParseModeSet(
         SourceParseMode::GeneratorWrapperFunctionMode,
+        SourceParseMode::GeneratorWrapperMethodMode,
         SourceParseMode::AsyncFunctionMode,
         SourceParseMode::AsyncArrowFunctionMode,
         SourceParseMode::AsyncMethodMode).contains(parseMode);
 }
 
+ALWAYS_INLINE bool isGeneratorParseMode(SourceParseMode parseMode)
+{
+    return SourceParseModeSet(
+        SourceParseMode::GeneratorBodyMode,
+        SourceParseMode::GeneratorWrapperFunctionMode,
+        SourceParseMode::GeneratorWrapperMethodMode).contains(parseMode);    
+}
+
+ALWAYS_INLINE bool isGeneratorWrapperParseMode(SourceParseMode parseMode)
+{
+    return SourceParseModeSet(
+        SourceParseMode::GeneratorWrapperFunctionMode,
+        SourceParseMode::GeneratorWrapperMethodMode).contains(parseMode);
+}
+
 ALWAYS_INLINE bool isArrowFunctionParseMode(SourceParseMode parseMode)
 {
     return SourceParseModeSet(
index cee410d..7c1b088 100644 (file)
@@ -123,7 +123,7 @@ public:
     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
     bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
     bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
-    bool isGenerator() const { return SourceParseModeSet(SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(parseMode()); }
+    bool isGenerator() const { return isGeneratorParseMode(parseMode()); }
     bool isMethod() const { return parseMode() == SourceParseMode::MethodMode; }
     bool hasCallerAndArgumentsProperties() const
     {
@@ -136,7 +136,8 @@ public:
         return SourceParseModeSet(
             SourceParseMode::NormalFunctionMode,
             SourceParseMode::GeneratorBodyMode,
-            SourceParseMode::GeneratorWrapperFunctionMode
+            SourceParseMode::GeneratorWrapperFunctionMode,
+            SourceParseMode::GeneratorWrapperMethodMode
         ).contains(parseMode()) || isClass();
     }
     DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
index 51d4154..42f709c 100644 (file)
@@ -358,7 +358,7 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
         PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
         if (!isValidOffset(offset)) {
             JSObject* prototype = nullptr;
-            if (thisObject->jsExecutable()->parseMode() == SourceParseMode::GeneratorWrapperFunctionMode) {
+            if (isGeneratorWrapperParseMode(thisObject->jsExecutable()->parseMode())) {
                 // Unlike function instances, the object that is the value of the a GeneratorFunction's prototype
                 // property does not have a constructor property whose value is the GeneratorFunction instance.
                 // https://tc39.github.io/ecma262/#sec-generatorfunction-instances-prototype