Title: [206647] trunk
Revision
206647
Author
[email protected]
Date
2016-09-30 11:44:16 -0700 (Fri, 30 Sep 2016)

Log Message

Arrow functions should not allow duplicate parameter names
https://bugs.webkit.org/show_bug.cgi?id=162741

Reviewed by Filip Pizlo.

JSTests:

* test262.yaml:

Source/_javascript_Core:

This patch makes parsing arrow function parameters throw
a syntax error when there are duplicate parameter names.
It also starts to make some syntax errors for arrow functions
better, however, this is trickier than it seems since we need
to choose between two parsing productions when we decide to
throw a syntax error. I'm going to work on this problem
in another patch specifically devoted to making the error
messages better for parsing arrow functions:
https://bugs.webkit.org/show_bug.cgi?id=162794

* parser/Parser.cpp:
(JSC::Parser<LexerType>::isArrowFunctionParameters):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseAssignmentExpression):
* parser/Parser.h:

LayoutTests:

* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (206646 => 206647)


--- trunk/JSTests/ChangeLog	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/JSTests/ChangeLog	2016-09-30 18:44:16 UTC (rev 206647)
@@ -1,5 +1,14 @@
 2016-09-30  Saam Barati  <[email protected]>
 
+        Arrow functions should not allow duplicate parameter names
+        https://bugs.webkit.org/show_bug.cgi?id=162741
+
+        Reviewed by Filip Pizlo.
+
+        * test262.yaml:
+
+2016-09-30  Saam Barati  <[email protected]>
+
         Make some microbenchmarks run for less time.
 
         Rubber stamped by Filip Pizlo.

Modified: trunk/JSTests/test262.yaml (206646 => 206647)


--- trunk/JSTests/test262.yaml	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/JSTests/test262.yaml	2016-09-30 18:44:16 UTC (rev 206647)
@@ -54254,7 +54254,7 @@
 - path: test262/test/language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-rest.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../../../harness/assert.js", "../../../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates.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/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../../../harness/assert.js", "../../../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-eval.js

Modified: trunk/LayoutTests/ChangeLog (206646 => 206647)


--- trunk/LayoutTests/ChangeLog	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/LayoutTests/ChangeLog	2016-09-30 18:44:16 UTC (rev 206647)
@@ -1,3 +1,13 @@
+2016-09-30  Saam Barati  <[email protected]>
+
+        Arrow functions should not allow duplicate parameter names
+        https://bugs.webkit.org/show_bug.cgi?id=162741
+
+        Reviewed by Filip Pizlo.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+
 2016-09-30  Megan Gardner  <[email protected]>
 
         Make it possible to test web-related user-interface features

Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (206646 => 206647)


--- trunk/LayoutTests/js/parser-syntax-check-expected.txt	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt	2016-09-30 18:44:16 UTC (rev 206647)
@@ -1462,6 +1462,36 @@
 PASS Valid:   "function f() { class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { constructor(x = () => super.foo) { super(); this._x_f = x; } x() { return this._x_f(); } } }"
 PASS Valid:   "class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { constructor(x = () => super()) { x(); } x() { return super.foo; } }"
 PASS Valid:   "function f() { class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { constructor(x = () => super()) { x(); } x() { return super.foo; } } }"
+PASS Invalid: "let x = (a,a)=>a;". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+PASS Invalid: "function f() { let x = (a,a)=>a; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+PASS Invalid: "let x = ([a],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)=>a; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "let x = ([a, 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])=>a; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "let x = ({a, b:{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, b:{a}})=>a; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "let x = (a,a)=>{ a };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+PASS Invalid: "function f() { let x = (a,a)=>{ a }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+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: 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."
+PASS Invalid: "function f() { let x = (b, c, b)=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'b' not allowed in an arrow function."
+PASS Invalid: "let x = (a, b, c, d, {a})=>{ };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "function f() { let x = (a, b, c, d, {a})=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in function with destructuring parameters."
+PASS Invalid: "let x = (b = (a,a)=>a, b)=>{ };". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+PASS Invalid: "function f() { let x = (b = (a,a)=>a, b)=>{ }; }". Produced the following syntax error: "SyntaxError: Duplicate parameter 'a' not allowed in an arrow function."
+PASS Invalid: "((a,a)=>a);". Produced the following syntax error: "SyntaxError: Unexpected token '('. Expected a parameter pattern or a ')' in parameter list."
+PASS Invalid: "function f() { ((a,a)=>a); }". Produced the following syntax error: "SyntaxError: Unexpected token '('. Expected a parameter pattern or a ')' in parameter list."
+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 '=>'"
 Weird things that used to crash.
 PASS Invalid: "or ([[{break //(elseifo (a=0;a<2;a++)n=
         [[{aFYY sga=

Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (206646 => 206647)


--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2016-09-30 18:44:16 UTC (rev 206647)
@@ -843,6 +843,20 @@
 valid("class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { x(y = (y = () => super.foo) => {return y()}) { return y(); } }");
 valid("class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { constructor(x = () => super.foo) { super(); this._x_f = x; } x() { return this._x_f(); } }");
 valid("class C { constructor() { this._x = 45; } get foo() { return this._x;} } class D extends C { constructor(x = () => super()) { x(); } x() { return super.foo; } }");
+invalid("let x = (a,a)=>a;");
+invalid("let x = ([a],a)=>a;");
+invalid("let x = ([a, a])=>a;");
+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})=>{ };");
+invalid("let x = (b = (a,a)=>a, b)=>{ };");
+invalid("((a,a)=>a);");
+invalid("let x = (a)\n=>a;");
 
 debug("Weird things that used to crash.");
 invalid(`or ([[{break //(elseifo (a=0;a<2;a++)n=

Modified: trunk/Source/_javascript_Core/ChangeLog (206646 => 206647)


--- trunk/Source/_javascript_Core/ChangeLog	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-09-30 18:44:16 UTC (rev 206647)
@@ -1,3 +1,27 @@
+2016-09-30  Saam Barati  <[email protected]>
+
+        Arrow functions should not allow duplicate parameter names
+        https://bugs.webkit.org/show_bug.cgi?id=162741
+
+        Reviewed by Filip Pizlo.
+
+        This patch makes parsing arrow function parameters throw
+        a syntax error when there are duplicate parameter names.
+        It also starts to make some syntax errors for arrow functions
+        better, however, this is trickier than it seems since we need
+        to choose between two parsing productions when we decide to
+        throw a syntax error. I'm going to work on this problem
+        in another patch specifically devoted to making the error
+        messages better for parsing arrow functions:
+        https://bugs.webkit.org/show_bug.cgi?id=162794
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::isArrowFunctionParameters):
+        (JSC::Parser<LexerType>::parseFormalParameters):
+        (JSC::Parser<LexerType>::parseFunctionParameters):
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        * parser/Parser.h:
+
 2016-09-30  Mark Lam  <[email protected]>
 
         Use topVMEntryFrame to determine whether to skip the re-throw of a simulated throw.

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (206646 => 206647)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-09-30 18:44:16 UTC (rev 206647)
@@ -36,7 +36,7 @@
     logError(shouldPrintToken, __VA_ARGS__); \
 } while (0)
 
-#define propagateError() do { if (hasError()) return 0; } while (0)
+#define propagateError() do { if (UNLIKELY(hasError())) return 0; } while (0)
 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
@@ -370,8 +370,9 @@
 
             unsigned parametersCount = 0;
             unsigned functionLength = 0;
-            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), parametersCount, functionLength) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
-                
+            bool isArrowFunctionParameterList = true;
+            isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount, functionLength) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
+            propagateError();
             popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
         }
         restoreSavePoint(saveArrowFunctionPoint);
@@ -1838,7 +1839,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount, unsigned& functionLength)
+template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount, unsigned& functionLength)
 {
 #define failIfDuplicateIfViolation() \
     if (duplicateParameter) {\
@@ -1845,6 +1846,7 @@
         semanticFailIfTrue(hasDefaultParameterValues, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
         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");\
     }
 
     bool hasDefaultParameterValues = false;
@@ -1966,8 +1968,10 @@
                 if (match(CLOSEPAREN)) {
                     functionInfo.parameterCount = 0;
                     functionInfo.functionLength = 0;
-                } else
-                    failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+                } else {
+                    bool isArrowFunction = true;
+                    failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+                }
                 
                 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
             } else {
@@ -2012,8 +2016,10 @@
         if (match(CLOSEPAREN)) {
             functionInfo.parameterCount = 0;
             functionInfo.functionLength = 0;
-        } else
-            failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+        } else {
+            bool isArrowFunction = false;
+            failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+        }
         consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
     }
 
@@ -3410,6 +3416,8 @@
                     currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
                 return parseArrowFunctionExpression(context, isAsyncArrow);
             }
+            if (isArrowFunctionToken)
+                propagateError();
             restoreSavePointWithError(errorRestorationSavePoint);
             if (isArrowFunctionToken)
                 failDueToUnexpectedToken();

Modified: trunk/Source/_javascript_Core/parser/Parser.h (206646 => 206647)


--- trunk/Source/_javascript_Core/parser/Parser.h	2016-09-30 18:39:59 UTC (rev 206646)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2016-09-30 18:44:16 UTC (rev 206647)
@@ -1490,7 +1490,7 @@
     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);
     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, unsigned, SourceParseMode);
-    template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, unsigned&, unsigned&);
+    template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, unsigned&, 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&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to