⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 181724 in webkit


Ignore:
Timestamp:
Mar 18, 2015, 8:27:00 PM (11 years ago)
Author:
Joseph Pecoraro
Message:

ES6 Classes: Extends should accept an expression without parenthesis
https://bugs.webkit.org/show_bug.cgi?id=142840

Reviewed by Ryosuke Niwa.

Source/JavaScriptCore:

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseClass):
"extends" allows a LeftHandExpression (new expression / call expression,
which includes a member expression), not a primary expression. Our
parseMemberExpression does all of these.

LayoutTests:

  • js/class-syntax-extends-expected.txt:
  • js/script-tests/class-syntax-extends.js:

Extend the test to test cases of extends with different types of expressions.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r181720 r181724  
     12015-03-18  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        ES6 Classes: Extends should accept an expression without parenthesis
     4        https://bugs.webkit.org/show_bug.cgi?id=142840
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * js/class-syntax-extends-expected.txt:
     9        * js/script-tests/class-syntax-extends.js:
     10        Extend the test to test cases of extends with different types of expressions.
     11
    1122015-03-18  Said Abou-Hallawa  <sabouhallawa@apple.com>
    213
  • trunk/LayoutTests/js/class-syntax-extends-expected.txt

    r181618 r181724  
    2626PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
    2727PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } } did not throw exception.
     28PASS x = 1; c = class extends ++x { constructor() { } }; threw exception SyntaxError: Unexpected token '++'.
     29PASS x = 1; c = class extends x++ { constructor() { } }; threw exception SyntaxError: Unexpected token '++'. Expected opening '{' at the start of a class body..
     30PASS x = 1; c = class extends (++x) { constructor() { } }; threw exception TypeError: The superclass is not an object..
     31PASS x = 1; c = class extends (x++) { constructor() { } }; threw exception TypeError: The superclass is not an object..
     32PASS x = 1; try { c = class extends (++x) { constructor() { } } } catch (e) { }; x is 2
     33PASS x = 1; try { c = class extends (x++) { constructor() { } } } catch (e) { }; x is 2
     34PASS namespace = {}; namespace.A = class { }; namespace.B = class extends namespace.A { } did not throw exception.
     35PASS namespace = {}; namespace.A = class A { }; namespace.B = class B extends namespace.A { } did not throw exception.
     36PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends namespace.A { constructor() { } } did not throw exception.
     37PASS namespace = {}; namespace.A = class A { constructor() { } }; namespace.B = class B extends namespace.A { constructor() { } } did not throw exception.
     38PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A) { constructor() { } } did not throw exception.
     39PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends namespace["A"] { constructor() { } } did not throw exception.
     40PASS namespace = {}; namespace.A = class { constructor() { } }; function getClassA() { return namespace.A }; namespace.B = class extends getClassA() { constructor() { } } did not throw exception.
     41PASS namespace = {}; namespace.A = class { constructor() { } }; function getClass(prop) { return namespace[prop] }; namespace.B = class extends getClass("A") { constructor() { } } did not throw exception.
     42PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (false||null||namespace.A) { constructor() { } } did not throw exception.
     43PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends false||null||namespace.A { constructor() { } } threw exception SyntaxError: Unexpected token '||'. Expected opening '{' at the start of a class body..
     44PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } }; did not throw exception.
     45PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } }; threw exception TypeError: The superclass is not an object..
     46PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
     47PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
     48PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x is 2
     49PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
    2850PASS successfullyParsed is true
    2951
  • trunk/LayoutTests/js/script-tests/class-syntax-extends.js

    r181618 r181724  
    4040shouldNotThrow('baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } }');
    4141
     42shouldThrow('x = 1; c = class extends ++x { constructor() { } };');
     43shouldThrow('x = 1; c = class extends x++ { constructor() { } };');
     44shouldThrow('x = 1; c = class extends (++x) { constructor() { } };');
     45shouldThrow('x = 1; c = class extends (x++) { constructor() { } };');
     46shouldBe('x = 1; try { c = class extends (++x) { constructor() { } } } catch (e) { }; x', '2');
     47shouldBe('x = 1; try { c = class extends (x++) { constructor() { } } } catch (e) { }; x', '2');
     48
     49shouldNotThrow('namespace = {}; namespace.A = class { }; namespace.B = class extends namespace.A { }');
     50shouldNotThrow('namespace = {}; namespace.A = class A { }; namespace.B = class B extends namespace.A { }');
     51shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends namespace.A { constructor() { } }');
     52shouldNotThrow('namespace = {}; namespace.A = class A { constructor() { } }; namespace.B = class B extends namespace.A { constructor() { } }');
     53shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A) { constructor() { } }');
     54shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends namespace["A"] { constructor() { } }');
     55shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; function getClassA() { return namespace.A }; namespace.B = class extends getClassA() { constructor() { } }');
     56shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; function getClass(prop) { return namespace[prop] }; namespace.B = class extends getClass("A") { constructor() { } }');
     57shouldNotThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (false||null||namespace.A) { constructor() { } }');
     58shouldThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends false||null||namespace.A { constructor() { } }');
     59shouldNotThrow('x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } };');
     60shouldThrow('x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } };');
     61shouldThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } }');
     62shouldThrow('namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } }');
     63shouldBe('x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x', '2');
     64shouldBe('x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x', '2');
     65
    4266var successfullyParsed = true;
  • trunk/Source/JavaScriptCore/ChangeLog

    r181722 r181724  
     12015-03-18  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        ES6 Classes: Extends should accept an expression without parenthesis
     4        https://bugs.webkit.org/show_bug.cgi?id=142840
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * parser/Parser.cpp:
     9        (JSC::Parser<LexerType>::parseClass):
     10        "extends" allows a LeftHandExpression (new expression / call expression,
     11        which includes a member expression), not a primary expression. Our
     12        parseMemberExpression does all of these.
     13
    1142015-03-18  Joseph Pecoraro  <pecoraro@apple.com>
    215
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r181664 r181724  
    14861486    TreeExpression parentClass = 0;
    14871487    if (consume(EXTENDS)) {
    1488         parentClass = parsePrimaryExpression(context);
     1488        parentClass = parseMemberExpression(context);
    14891489        failIfFalse(parentClass, "Cannot parse the parent class name");
    14901490    }
Note: See TracChangeset for help on using the changeset viewer.