Title: [183383] trunk
Revision
183383
Author
[email protected]
Date
2015-04-26 21:20:32 -0700 (Sun, 26 Apr 2015)

Log Message

Class body ending with a semicolon throws a SyntaxError
https://bugs.webkit.org/show_bug.cgi?id=144244

Reviewed by Darin Adler.

Source/_javascript_Core:

The bug was caused by parseClass's inner loop for method definitions not moving onto the next iteration
it encounters a semicolon. As a result, we always expected a method to appear after a semicolon. Fixed
it by continue'ing when it encounters a semicolon.

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

LayoutTests:

Added a regression test for having a semicolon inside the class definition.

* js/class-syntax-semicolon-expected.txt: Added.
* js/class-syntax-semicolon.html: Added.
* js/script-tests/class-syntax-semicolon.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (183382 => 183383)


--- trunk/LayoutTests/ChangeLog	2015-04-27 04:18:18 UTC (rev 183382)
+++ trunk/LayoutTests/ChangeLog	2015-04-27 04:20:32 UTC (rev 183383)
@@ -1,5 +1,18 @@
 2015-04-26  Ryosuke Niwa  <[email protected]>
 
+        Class body ending with a semicolon throws a SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=144244
+
+        Reviewed by Darin Adler.
+
+        Added a regression test for having a semicolon inside the class definition.
+
+        * js/class-syntax-semicolon-expected.txt: Added.
+        * js/class-syntax-semicolon.html: Added.
+        * js/script-tests/class-syntax-semicolon.js: Added.
+
+2015-04-26  Ryosuke Niwa  <[email protected]>
+
         Getter or setter method named "prototype" or "constrcutor" should throw SyntaxError
         https://bugs.webkit.org/show_bug.cgi?id=144243
 

Added: trunk/LayoutTests/js/class-syntax-semicolon-expected.txt (0 => 183383)


--- trunk/LayoutTests/js/class-syntax-semicolon-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/class-syntax-semicolon-expected.txt	2015-04-27 04:20:32 UTC (rev 183383)
@@ -0,0 +1,66 @@
+Tests for ES6 class syntax containing semicolon in the class body
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS class A { foo;() { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '(' before a method's parameter list..
+PASS class A { foo() ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a method body..
+PASS class A { get ; foo() { } } threw exception SyntaxError: Unexpected token ';'.
+PASS class A { get foo;() { } } threw exception SyntaxError: Unexpected token ';'. Expected a parameter list for getter definition..
+PASS class A { get foo() ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a getter body..
+PASS class A { set ; foo(x) { } } threw exception SyntaxError: Unexpected token ';'.
+PASS class A { set foo;(x) { } } threw exception SyntaxError: Unexpected token ';'. Expected a parameter list for setter definition..
+PASS class A { set foo(x) ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a setter body..
+PASS class A { ; } did not throw exception.
+PASS class A { foo() { } ; } did not throw exception.
+PASS class A { get foo() { } ; } did not throw exception.
+PASS class A { set foo(x) { } ; } did not throw exception.
+PASS class A { static foo() { } ; } did not throw exception.
+PASS class A { static get foo() { } ; } did not throw exception.
+PASS class A { static set foo(x) { } ; } did not throw exception.
+PASS class A { ; foo() { } } did not throw exception.
+PASS class A { ; get foo() { } } did not throw exception.
+PASS class A { ; set foo(x) { } } did not throw exception.
+PASS class A { ; static foo() { } } did not throw exception.
+PASS class A { ; static get foo() { } } did not throw exception.
+PASS class A { ; static set foo(x) { } } did not throw exception.
+PASS class A { foo() { } ; foo() {} } did not throw exception.
+PASS class A { foo() { } ; get foo() {} } did not throw exception.
+PASS class A { foo() { } ; set foo(x) {} } did not throw exception.
+PASS class A { foo() { } ; static foo() {} } did not throw exception.
+PASS class A { foo() { } ; static get foo() {} } did not throw exception.
+PASS class A { foo() { } ; static set foo(x) {} } did not throw exception.
+PASS class A { get foo() { } ; foo() {} } did not throw exception.
+PASS class A { get foo() { } ; get foo() {} } did not throw exception.
+PASS class A { get foo() { } ; set foo(x) {} } did not throw exception.
+PASS class A { get foo() { } ; static foo() {} } did not throw exception.
+PASS class A { get foo() { } ; static get foo() {} } did not throw exception.
+PASS class A { get foo() { } ; static set foo(x) {} } did not throw exception.
+PASS class A { set foo(x) { } ; foo() {} } did not throw exception.
+PASS class A { set foo(x) { } ; get foo() {} } did not throw exception.
+PASS class A { set foo(x) { } ; set foo(x) {} } did not throw exception.
+PASS class A { set foo(x) { } ; static foo() {} } did not throw exception.
+PASS class A { set foo(x) { } ; static get foo() {} } did not throw exception.
+PASS class A { set foo(x) { } ; static set foo(x) {} } did not throw exception.
+PASS class A { static foo() { } ; foo() {} } did not throw exception.
+PASS class A { static foo() { } ; get foo() {} } did not throw exception.
+PASS class A { static foo() { } ; set foo(x) {} } did not throw exception.
+PASS class A { static foo() { } ; static foo() {} } did not throw exception.
+PASS class A { static foo() { } ; static get foo() {} } did not throw exception.
+PASS class A { static foo() { } ; static set foo(x) {} } did not throw exception.
+PASS class A { static get foo() { } ; foo() {} } did not throw exception.
+PASS class A { static get foo() { } ; get foo() {} } did not throw exception.
+PASS class A { static get foo() { } ; set foo(x) {} } did not throw exception.
+PASS class A { static get foo() { } ; static foo() {} } did not throw exception.
+PASS class A { static get foo() { } ; static get foo() {} } did not throw exception.
+PASS class A { static get foo() { } ; static set foo(x) {} } did not throw exception.
+PASS class A { static set foo(x) { } ; foo() {} } did not throw exception.
+PASS class A { static set foo(x) { } ; get foo() {} } did not throw exception.
+PASS class A { static set foo(x) { } ; set foo(x) {} } did not throw exception.
+PASS class A { static set foo(x) { } ; static foo() {} } did not throw exception.
+PASS class A { static set foo(x) { } ; static get foo() {} } did not throw exception.
+PASS class A { static set foo(x) { } ; static set foo(x) {} } did not throw exception.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/class-syntax-semicolon.html (0 => 183383)


--- trunk/LayoutTests/js/class-syntax-semicolon.html	                        (rev 0)
+++ trunk/LayoutTests/js/class-syntax-semicolon.html	2015-04-27 04:20:32 UTC (rev 183383)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/class-syntax-semicolon.js (0 => 183383)


--- trunk/LayoutTests/js/script-tests/class-syntax-semicolon.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-semicolon.js	2015-04-27 04:20:32 UTC (rev 183383)
@@ -0,0 +1,70 @@
+
+description('Tests for ES6 class syntax containing semicolon in the class body');
+
+shouldThrow("class A { foo;() { } }", "'SyntaxError: Unexpected token \\';\\'. Expected an opening \\'(\\' before a method\\'s parameter list.'");
+shouldThrow("class A { foo() ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a method body.'");
+shouldThrow("class A { get ; foo() { } }", "'SyntaxError: Unexpected token \\';\\''");
+shouldThrow("class A { get foo;() { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected a parameter list for getter definition.'");
+shouldThrow("class A { get foo() ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a getter body.'");
+shouldThrow("class A { set ; foo(x) { } }", "'SyntaxError: Unexpected token \\';\\''");
+shouldThrow("class A { set foo;(x) { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected a parameter list for setter definition.'");
+shouldThrow("class A { set foo(x) ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a setter body.'");
+
+shouldNotThrow("class A { ; }");
+shouldNotThrow("class A { foo() { } ; }");
+shouldNotThrow("class A { get foo() { } ; }");
+shouldNotThrow("class A { set foo(x) { } ; }");
+shouldNotThrow("class A { static foo() { } ; }");
+shouldNotThrow("class A { static get foo() { } ; }");
+shouldNotThrow("class A { static set foo(x) { } ; }");
+
+shouldNotThrow("class A { ; foo() { } }");
+shouldNotThrow("class A { ; get foo() { } }");
+shouldNotThrow("class A { ; set foo(x) { } }");
+shouldNotThrow("class A { ; static foo() { } }");
+shouldNotThrow("class A { ; static get foo() { } }");
+shouldNotThrow("class A { ; static set foo(x) { } }");
+
+shouldNotThrow("class A { foo() { } ; foo() {} }");
+shouldNotThrow("class A { foo() { } ; get foo() {} }");
+shouldNotThrow("class A { foo() { } ; set foo(x) {} }");
+shouldNotThrow("class A { foo() { } ; static foo() {} }");
+shouldNotThrow("class A { foo() { } ; static get foo() {} }");
+shouldNotThrow("class A { foo() { } ; static set foo(x) {} }");
+
+shouldNotThrow("class A { get foo() { } ; foo() {} }");
+shouldNotThrow("class A { get foo() { } ; get foo() {} }");
+shouldNotThrow("class A { get foo() { } ; set foo(x) {} }");
+shouldNotThrow("class A { get foo() { } ; static foo() {} }");
+shouldNotThrow("class A { get foo() { } ; static get foo() {} }");
+shouldNotThrow("class A { get foo() { } ; static set foo(x) {} }");
+
+shouldNotThrow("class A { set foo(x) { } ; foo() {} }");
+shouldNotThrow("class A { set foo(x) { } ; get foo() {} }");
+shouldNotThrow("class A { set foo(x) { } ; set foo(x) {} }");
+shouldNotThrow("class A { set foo(x) { } ; static foo() {} }");
+shouldNotThrow("class A { set foo(x) { } ; static get foo() {} }");
+shouldNotThrow("class A { set foo(x) { } ; static set foo(x) {} }");
+
+shouldNotThrow("class A { static foo() { } ; foo() {} }");
+shouldNotThrow("class A { static foo() { } ; get foo() {} }");
+shouldNotThrow("class A { static foo() { } ; set foo(x) {} }");
+shouldNotThrow("class A { static foo() { } ; static foo() {} }");
+shouldNotThrow("class A { static foo() { } ; static get foo() {} }");
+shouldNotThrow("class A { static foo() { } ; static set foo(x) {} }");
+
+shouldNotThrow("class A { static get foo() { } ; foo() {} }");
+shouldNotThrow("class A { static get foo() { } ; get foo() {} }");
+shouldNotThrow("class A { static get foo() { } ; set foo(x) {} }");
+shouldNotThrow("class A { static get foo() { } ; static foo() {} }");
+shouldNotThrow("class A { static get foo() { } ; static get foo() {} }");
+shouldNotThrow("class A { static get foo() { } ; static set foo(x) {} }");
+
+shouldNotThrow("class A { static set foo(x) { } ; foo() {} }");
+shouldNotThrow("class A { static set foo(x) { } ; get foo() {} }");
+shouldNotThrow("class A { static set foo(x) { } ; set foo(x) {} }");
+shouldNotThrow("class A { static set foo(x) { } ; static foo() {} }");
+shouldNotThrow("class A { static set foo(x) { } ; static get foo() {} }");
+shouldNotThrow("class A { static set foo(x) { } ; static set foo(x) {} }");
+
+var successfullyParsed = true;

Modified: trunk/Source/_javascript_Core/ChangeLog (183382 => 183383)


--- trunk/Source/_javascript_Core/ChangeLog	2015-04-27 04:18:18 UTC (rev 183382)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-04-27 04:20:32 UTC (rev 183383)
@@ -1,5 +1,19 @@
 2015-04-26  Ryosuke Niwa  <[email protected]>
 
+        Class body ending with a semicolon throws a SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=144244
+
+        Reviewed by Darin Adler.
+
+        The bug was caused by parseClass's inner loop for method definitions not moving onto the next iteration
+        it encounters a semicolon. As a result, we always expected a method to appear after a semicolon. Fixed
+        it by continue'ing when it encounters a semicolon.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseClass):
+
+2015-04-26  Ryosuke Niwa  <[email protected]>
+
         Getter or setter method named "prototype" or "constrcutor" should throw SyntaxError
         https://bugs.webkit.org/show_bug.cgi?id=144243
 

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (183382 => 183383)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2015-04-27 04:18:18 UTC (rev 183382)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2015-04-27 04:20:32 UTC (rev 183383)
@@ -1537,8 +1537,10 @@
     TreePropertyList instanceMethodsTail = 0;
     TreePropertyList staticMethodsTail = 0;
     while (!match(CLOSEBRACE)) {
-        if (match(SEMICOLON))
+        if (match(SEMICOLON)) {
             next();
+            continue;
+        }
 
         JSTokenLocation methodLocation(tokenLocation());
         unsigned methodStart = tokenStart();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to