Getter or setter method named "prototype" or "constrcutor" should throw SyntaxError
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2015 04:18:18 +0000 (04:18 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2015 04:18:18 +0000 (04:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144243

Reviewed by Darin Adler.

Source/JavaScriptCore:

Fixed the bug by adding explicit checks in parseGetterSetter when we're parsing class methods.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseGetterSetter):

LayoutTests:

Added tests cases to both tests. Also added test cases missing from expression tests.

* js/class-syntax-declaration-expected.txt:
* js/class-syntax-expression-expected.txt:
* js/script-tests/class-syntax-declaration.js:
* js/script-tests/class-syntax-expression.js:

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

LayoutTests/ChangeLog
LayoutTests/js/class-syntax-declaration-expected.txt
LayoutTests/js/class-syntax-expression-expected.txt
LayoutTests/js/script-tests/class-syntax-declaration.js
LayoutTests/js/script-tests/class-syntax-expression.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/Parser.cpp

index 1b00391fabb04001856ccdf9469c99899a81b639..3d1148f018d56e882ec7c57f49fb9580783745b0 100644 (file)
@@ -1,3 +1,17 @@
+2015-04-26  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Getter or setter method named "prototype" or "constrcutor" should throw SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=144243
+
+        Reviewed by Darin Adler.
+
+        Added tests cases to both tests. Also added test cases missing from expression tests.
+
+        * js/class-syntax-declaration-expected.txt:
+        * js/class-syntax-expression-expected.txt:
+        * js/script-tests/class-syntax-declaration.js:
+        * js/script-tests/class-syntax-expression.js:
+
 2015-04-26  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         SVGFilterBuilder should drive the builtin sourceAlpha from the passed sourceGraphic
index dd000297404d90a389eff73899b1933719dad7b2..ac7f974a6f3f1b06effbac90ad064debbb33fe4c 100644 (file)
@@ -22,9 +22,13 @@ PASS class X { threw exception SyntaxError: Unexpected end of script.
 PASS class X { ( } threw exception SyntaxError: Unexpected token '('. Expected an identifier..
 PASS class X {} did not throw exception.
 PASS class X { constructor() {} constructor() {} } threw exception SyntaxError: Cannot declare multiple constructors in a single class..
+PASS class X { get constructor() {} } threw exception SyntaxError: Cannot declare a getter or setter named 'constructor'..
+PASS class X { set constructor() {} } threw exception SyntaxError: Cannot declare a getter or setter named 'constructor'..
 PASS class X { constructor() {} static constructor() { return staticMethodValue; } } did not throw exception.
 PASS class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor() is staticMethodValue
 PASS class X { constructor() {} static prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
+PASS class X { constructor() {} static get prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
+PASS class X { constructor() {} static set prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
 PASS class X { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
 PASS class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype() is instanceMethodValue
 PASS class X { constructor() {} set foo(a) {} } did not throw exception.
index db302d42f362db2051bb90f16f141a6967888259..81bc8de777f8cf28b193500d936b3c29ca06e237 100644 (file)
@@ -20,11 +20,22 @@ PASS x = class { threw exception SyntaxError: Unexpected end of script.
 PASS x = class { ( } threw exception SyntaxError: Unexpected token '('. Expected an identifier..
 PASS x = class {} did not throw exception.
 PASS x = class { constructor() {} constructor() {} } threw exception SyntaxError: Cannot declare multiple constructors in a single class..
+PASS x = class { get constructor() {} } threw exception SyntaxError: Cannot declare a getter or setter named 'constructor'..
+PASS x = class { set constructor() {} } threw exception SyntaxError: Cannot declare a getter or setter named 'constructor'..
 PASS x = class { constructor() {} static constructor() { return staticMethodValue; } } did not throw exception.
-PASS x.constructor() is staticMethodValue
+PASS x = class { constructor() {} static constructor() { return staticMethodValue; } }; x.constructor() is staticMethodValue
 PASS x = class { constructor() {} static prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
-PASS x = class { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
-PASS (new x).prototype() is instanceMethodValue
+PASS x = class { constructor() {} static get prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
+PASS x = class { constructor() {} static set prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
+PASS x = class  { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
+PASS x = class { constructor() {} prototype() { return instanceMethodValue; } }; (new x).prototype() is instanceMethodValue
+PASS x = class { constructor() {} set foo(a) {} } did not throw exception.
+PASS x = class { constructor() {} set foo({x, y}) {} } did not throw exception.
+PASS x = class { constructor() {} set foo() {} } threw exception SyntaxError: Unexpected token ')'. setter functions must have one parameter..
+PASS x = class { constructor() {} set foo(a, b) {} } threw exception SyntaxError: Unexpected token ','. setter functions must have one parameter..
+PASS x = class { constructor() {} get foo() {} } did not throw exception.
+PASS x = class { constructor() {} get foo(x) {} } threw exception SyntaxError: Unexpected identifier 'x'. getter functions must have no parameters..
+PASS x = class { constructor() {} get foo({x, y}) {} } threw exception SyntaxError: Unexpected token '{'. getter functions must have no parameters..
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 769688c4eea28509a2d5f86ef3e8bad0502b29d4..8c3fa09028e5973df443a777db7bc5f705ef2062 100644 (file)
@@ -35,10 +35,16 @@ shouldThrow("class {", "'SyntaxError: Class statements must have a name.'");
 shouldThrow("class X {", "'SyntaxError: Unexpected end of script'");
 shouldThrow("class X { ( }", "'SyntaxError: Unexpected token \\'(\\'. Expected an identifier.'");
 shouldNotThrow("class X {}");
+
 shouldThrow("class X { constructor() {} constructor() {} }", "'SyntaxError: Cannot declare multiple constructors in a single class.'");
+shouldThrow("class X { get constructor() {} }", "'SyntaxError: Cannot declare a getter or setter named \\'constructor\\'.'");
+shouldThrow("class X { set constructor() {} }", "'SyntaxError: Cannot declare a getter or setter named \\'constructor\\'.'");
 shouldNotThrow("class X { constructor() {} static constructor() { return staticMethodValue; } }");
 shouldBe("class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor()", "staticMethodValue");
+
 shouldThrow("class X { constructor() {} static prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
+shouldThrow("class X { constructor() {} static get prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
+shouldThrow("class X { constructor() {} static set prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
 shouldNotThrow("class X { constructor() {} prototype() { return instanceMethodValue; } }");
 shouldBe("class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype()", "instanceMethodValue");
 
index 16c67c7ec38659c1c6b67107e2db4185b4cdbd10..ddc0a69cb97cabbfc924a33e18320f4dced1a808 100644 (file)
@@ -33,11 +33,25 @@ shouldThrow("x = class", "'SyntaxError: Unexpected end of script'");
 shouldThrow("x = class {", "'SyntaxError: Unexpected end of script'");
 shouldThrow("x = class { ( }", "'SyntaxError: Unexpected token \\'(\\'. Expected an identifier.'");
 shouldNotThrow("x = class {}");
+
 shouldThrow("x = class { constructor() {} constructor() {} }", "'SyntaxError: Cannot declare multiple constructors in a single class.'");
+shouldThrow("x = class { get constructor() {} }", "'SyntaxError: Cannot declare a getter or setter named \\'constructor\\'.'");
+shouldThrow("x = class { set constructor() {} }", "'SyntaxError: Cannot declare a getter or setter named \\'constructor\\'.'");
 shouldNotThrow("x = class { constructor() {} static constructor() { return staticMethodValue; } }");
-shouldBe("x.constructor()", "staticMethodValue");
+shouldBe("x = class { constructor() {} static constructor() { return staticMethodValue; } }; x.constructor()", "staticMethodValue");
+
 shouldThrow("x = class { constructor() {} static prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
-shouldNotThrow("x = class { constructor() {} prototype() { return instanceMethodValue; } }");
-shouldBe("(new x).prototype()", "instanceMethodValue");
+shouldThrow("x = class { constructor() {} static get prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
+shouldThrow("x = class { constructor() {} static set prototype() {} }", "'SyntaxError: Cannot declare a static method named \\'prototype\\'.'");
+shouldNotThrow("x = class  { constructor() {} prototype() { return instanceMethodValue; } }");
+shouldBe("x = class { constructor() {} prototype() { return instanceMethodValue; } }; (new x).prototype()", "instanceMethodValue");
+
+shouldNotThrow("x = class { constructor() {} set foo(a) {} }");
+shouldNotThrow("x = class { constructor() {} set foo({x, y}) {} }");
+shouldThrow("x = class { constructor() {} set foo() {} }");
+shouldThrow("x = class { constructor() {} set foo(a, b) {} }");
+shouldNotThrow("x = class { constructor() {} get foo() {} }");
+shouldThrow("x = class { constructor() {} get foo(x) {} }");
+shouldThrow("x = class { constructor() {} get foo({x, y}) {} }");
 
 var successfullyParsed = true;
index 54f093674ebc05f540dda8078be66365fd823dfc..e6377eb8d139f9ecc2e168db5c0c65f31ace56b4 100644 (file)
@@ -1,3 +1,15 @@
+2015-04-26  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Getter or setter method named "prototype" or "constrcutor" should throw SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=144243
+
+        Reviewed by Darin Adler.
+
+        Fixed the bug by adding explicit checks in parseGetterSetter when we're parsing class methods.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseGetterSetter):
+
 2015-04-26  Jordan Harband  <ljharb@gmail.com>
 
         Map#forEach does not pass "map" argument to callback.
index bd799bf00956b76e400fd3b595a7f4955fb585aa..2163dbd8720c9fef8f290931474845dc2b51b125 100644 (file)
@@ -2077,9 +2077,13 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(T
 {
     const Identifier* stringPropertyName = 0;
     double numericPropertyName = 0;
-    if (m_token.m_type == IDENT || m_token.m_type == STRING)
+    if (m_token.m_type == IDENT || m_token.m_type == STRING) {
         stringPropertyName = m_token.m_data.ident;
-    else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
+        semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
+            "Cannot declare a static method named 'prototype'");
+        semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->constructor,
+            "Cannot declare a getter or setter named 'constructor'");
+    } else if (m_token.m_type == DOUBLE || m_token.m_type == INTEGER)
         numericPropertyName = m_token.m_data.doubleValue;
     else
         failDueToUnexpectedToken();