Title: [181183] trunk
Revision
181183
Author
commit-qu...@webkit.org
Date
2015-03-06 14:31:28 -0800 (Fri, 06 Mar 2015)

Log Message

ES6: Object Literal Extensions - Methods
https://bugs.webkit.org/show_bug.cgi?id=142390

Patch by Joseph Pecoraro <pecor...@apple.com> on 2015-03-06
Reviewed by Geoffrey Garen.

Source/_javascript_Core:

Support method syntax in object literals.

* parser/Parser.h:
* parser/Parser.cpp:
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseProperty):
Methods are allowed for identifier, string, and numeric names,
and computed property names.

(JSC::Parser<LexerType>::parsePropertyMethod):
Helper for parsing a property method.

LayoutTests:

* js/object-literal-computed-methods-expected.txt: Added.
* js/object-literal-computed-methods.html: Added.
* js/object-literal-methods-expected.txt: Added.
* js/object-literal-methods.html: Added.
* js/script-tests/object-literal-computed-methods.js: Added.
* js/script-tests/object-literal-methods.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (181182 => 181183)


--- trunk/LayoutTests/ChangeLog	2015-03-06 22:29:10 UTC (rev 181182)
+++ trunk/LayoutTests/ChangeLog	2015-03-06 22:31:28 UTC (rev 181183)
@@ -1,5 +1,19 @@
 2015-03-06  Joseph Pecoraro  <pecor...@apple.com>
 
+        ES6: Object Literal Extensions - Methods
+        https://bugs.webkit.org/show_bug.cgi?id=142390
+
+        Reviewed by Geoffrey Garen.
+
+        * js/object-literal-computed-methods-expected.txt: Added.
+        * js/object-literal-computed-methods.html: Added.
+        * js/object-literal-methods-expected.txt: Added.
+        * js/object-literal-methods.html: Added.
+        * js/script-tests/object-literal-computed-methods.js: Added.
+        * js/script-tests/object-literal-methods.js: Added.
+
+2015-03-06  Joseph Pecoraro  <pecor...@apple.com>
+
         __proto__ shorthand property should not modify prototype in Object Literal construction
         https://bugs.webkit.org/show_bug.cgi?id=142382
 

Added: trunk/LayoutTests/js/object-literal-computed-methods-expected.txt (0 => 181183)


--- trunk/LayoutTests/js/object-literal-computed-methods-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/object-literal-computed-methods-expected.txt	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,65 @@
+basic tests for object literal computed methods
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS o = { ['f'+'oo']() { return 10; } }; did not throw exception.
+PASS o.foo() is 10
+PASS typeof o.foo is 'function'
+PASS o.foo.length is 0
+PASS o.foo.name is ''
+PASS o.foo.toString() is 'function () { return 10; }'
+PASS Object.getOwnPropertyDescriptor(o, 'foo').value is o.foo
+PASS Object.getOwnPropertyDescriptor(o, 'foo').enumerable is true
+PASS Object.getOwnPropertyDescriptor(o, 'foo').configurable is true
+PASS Object.getOwnPropertyDescriptor(o, 'foo').writable is true
+PASS methodName = 'add'; o = { [methodName](x, y) { return x + y; } }; did not throw exception.
+PASS o.add(42, -10) is 32
+PASS typeof o.add is 'function'
+PASS o.add.length is 2
+PASS o.add.name is ''
+PASS o.add.toString() is 'function (x, y) { return x + y; }'
+PASS o = { [ (function() { return 'method'; })() ](x, y) { return x + y; } }; did not throw exception.
+PASS o.method(142, -10) is 132
+PASS o = { [10*10]() { return 100; } }; did not throw exception.
+PASS o[100]() is 100
+PASS o['100']() is 100
+PASS o = { [100 + 0.100]() { return 100.100; } }; did not throw exception.
+PASS o[100.1]() is 100.1
+PASS o['100.1']() is 100.1
+PASS o = { ['a' + 'dd']([x, y]) { return x + y; } }; did not throw exception.
+PASS o.add([142, -100]) is 42
+PASS o = { [Array]([x, y]) { return x + y; } }; did not throw exception.
+PASS o[Array.toString()]([142, -100]) is 42
+PASS o = { foo() { return 10; }, }; did not throw exception.
+PASS o = { foo (  ) { return 10; } }; did not throw exception.
+PASS o = {[true](){return true;}}; did not throw exception.
+PASS o = {[NaN](){return NaN;}}; did not throw exception.
+PASS o = {[eval](){return eval;}}; did not throw exception.
+PASS o = { a:1, [foo]() { return 10; }, [bar]() { return 20; }, b: 2 }; did not throw exception.
+PASS o = { a:1, [foo]() { return 10; }, [bar]() { return 20; }, b }; did not throw exception.
+PASS o = { a:1, [foo]() { return 10; }, b: b, [bar]() { return 20; }, c: 2 }; did not throw exception.
+PASS o = { a:1, [foo]() { return 10; }, b, [bar]() { return 20; }, c }; did not throw exception.
+PASS o = {[foo]:{[bar](){ return 100; }}}; did not throw exception.
+PASS o.foo.bar() is 100
+PASS o = { [foo]() { return 10; }, [foo]() { return 20; } }; did not throw exception.
+PASS o.foo() is 20
+PASS o = { ['get'](x, y) { return x + y; } }; did not throw exception.
+PASS o.get('hello', 'world') is 'helloworld'
+PASS o = { ['set'](x, y) { return x + y; } }; did not throw exception.
+PASS o.set('hello', 'world') is 'helloworld'
+PASS ({ [](,,,){} }) threw exception SyntaxError: Unexpected token ']'.
+PASS ({ [1+](){} }) threw exception SyntaxError: Unexpected token ']'.
+PASS ({ [1,](){} }) threw exception SyntaxError: Unexpected token ']'.
+PASS ({ [[1](){} }) threw exception SyntaxError: Unexpected token '{'. Expected ']' to end a computed property name..
+PASS ({ [foo](,,,){} }) threw exception SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list..
+PASS ({ [foo](a{}, bar(){} }) threw exception SyntaxError: Unexpected token '{'. Expected a ')' or a ',' after a parameter declaration..
+PASS ({ [foo](a, b), bar(){} }) threw exception SyntaxError: Unexpected token ','. Expected an opening '{' at the start of a method body..
+PASS ({ [foo](a, b) { if }, bar(){} }) threw exception SyntaxError: Unexpected token '}'. Expected '(' to start a 'if' condition..
+PASS ({__proto__: function(){}}) instanceof Function is true
+PASS ({['__proto__'](){}}) instanceof Function is false
+PASS ({['__proto__'](){}}).__proto__ instanceof Function is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/object-literal-computed-methods.html (0 => 181183)


--- trunk/LayoutTests/js/object-literal-computed-methods.html	                        (rev 0)
+++ trunk/LayoutTests/js/object-literal-computed-methods.html	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/object-literal-methods-expected.txt (0 => 181183)


--- trunk/LayoutTests/js/object-literal-methods-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/object-literal-methods-expected.txt	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,74 @@
+basic tests for object literal methods
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS o = { foo() { return 10; } }; did not throw exception.
+PASS o.foo() is 10
+PASS typeof o.foo is 'function'
+PASS o.foo.length is 0
+PASS o.foo.name is 'foo'
+PASS o.foo.toString() is 'function foo() { return 10; }'
+PASS Object.getOwnPropertyDescriptor(o, 'foo').value is o.foo
+PASS Object.getOwnPropertyDescriptor(o, 'foo').enumerable is true
+PASS Object.getOwnPropertyDescriptor(o, 'foo').configurable is true
+PASS Object.getOwnPropertyDescriptor(o, 'foo').writable is true
+PASS o = { add(x, y) { return x + y; } }; did not throw exception.
+PASS o.add(42, -10) is 32
+PASS typeof o.add is 'function'
+PASS o.add.length is 2
+PASS o.add.name is 'add'
+PASS o.add.toString() is 'function add(x, y) { return x + y; }'
+PASS o = { 'add'(a, b, c) { return a + b + c; } }; did not throw exception.
+PASS o.add(1, 2, 3) is 6
+PASS o = { 'a(d)d'(a, b, c) { return a + b + c; } }; did not throw exception.
+PASS o['a(d)d'](1, 2, 3) is 6
+PASS o = { 100() { return 100; } }; did not throw exception.
+PASS o[100]() is 100
+PASS o['100']() is 100
+PASS o = { 100.100() { return 100.100; } }; did not throw exception.
+PASS o[100.1]() is 100.1
+PASS o['100.1']() is 100.1
+PASS o = { 1e3() { return 1e3; } }; did not throw exception.
+PASS o[1e3]() is 1000
+PASS o['1000']() is 1000
+PASS o = { 0x11() { return 0x11; } }; did not throw exception.
+PASS o[0x11]() is 17
+PASS o['17']() is 17
+PASS o = { add([x, y]) { return x + y; } }; did not throw exception.
+PASS o.add([142, -100]) is 42
+PASS o = { foo() { return 10; }, }; did not throw exception.
+PASS o = { foo (  ) { return 10; } }; did not throw exception.
+PASS o = {true(){return true;}}; did not throw exception.
+PASS o = {NaN(){return NaN;}}; did not throw exception.
+PASS o = {eval(){return eval;}}; did not throw exception.
+PASS o = { a:1, foo() { return 10; }, bar() { return 20; }, b: 2 }; did not throw exception.
+PASS o = { a:1, foo() { return 10; }, bar() { return 20; }, b }; did not throw exception.
+PASS o = { a:1, foo() { return 10; }, b: b, bar() { return 20; }, c: 2 }; did not throw exception.
+PASS o = { a:1, foo() { return 10; }, b, bar() { return 20; }, c }; did not throw exception.
+PASS o = {inner:{method(){ return 100; }}}; did not throw exception.
+PASS o.inner.method() is 100
+PASS o = { foo() { return 10; }, foo() { return 20; } }; did not throw exception.
+PASS o.foo() is 20
+PASS o = { get(x, y) { return x + y; } }; did not throw exception.
+PASS o.get('hello', 'world') is 'helloworld'
+PASS o = { set(x, y) { return x + y; } }; did not throw exception.
+PASS o.set('hello', 'world') is 'helloworld'
+PASS ({get x(){ return true; }}).x is true
+PASS ({get 'x'(){ return true; }}).x is true
+PASS ({get 42(){ return true; }})['42'] is true
+PASS !!Object.getOwnPropertyDescriptor({set x(value){}}, 'x').set is true
+PASS !!Object.getOwnPropertyDescriptor({set 'x'(value){}}, 'x').set is true
+PASS !!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set is true
+PASS ({ (){} }) threw exception SyntaxError: Unexpected token '('. Expected a property name..
+PASS ({ foo(,,,){} }) threw exception SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list..
+PASS ({ foo(a{}, bar(){} }) threw exception SyntaxError: Unexpected token '{'. Expected a ')' or a ',' after a parameter declaration..
+PASS ({ foo(a, b), bar(){} }) threw exception SyntaxError: Unexpected token ','. Expected an opening '{' at the start of a method body..
+PASS ({ foo(a, b) { if }, bar(){} }) threw exception SyntaxError: Unexpected token '}'. Expected '(' to start a 'if' condition..
+PASS ({__proto__: function(){}}) instanceof Function is true
+PASS ({__proto__(){}}) instanceof Function is false
+PASS ({__proto__(){}}).__proto__ instanceof Function is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/object-literal-methods.html (0 => 181183)


--- trunk/LayoutTests/js/object-literal-methods.html	                        (rev 0)
+++ trunk/LayoutTests/js/object-literal-methods.html	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js (0 => 181183)


--- trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,74 @@
+description("basic tests for object literal computed methods");
+
+shouldNotThrow("o = { ['f'+'oo']() { return 10; } };");
+shouldBe("o.foo()", "10");
+shouldBe("typeof o.foo", "'function'");
+shouldBe("o.foo.length", "0");
+shouldBe("o.foo.name", "''");
+shouldBe("o.foo.toString()", "'function () { return 10; }'");
+shouldBe("Object.getOwnPropertyDescriptor(o, 'foo').value", "o.foo");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').enumerable");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').configurable");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').writable");
+
+shouldNotThrow("methodName = 'add'; o = { [methodName](x, y) { return x + y; } };");
+shouldBe("o.add(42, -10)", "32");
+shouldBe("typeof o.add", "'function'");
+shouldBe("o.add.length", "2");
+shouldBe("o.add.name", "''");
+shouldBe("o.add.toString()", "'function (x, y) { return x + y; }'");
+
+shouldNotThrow("o = { [ (function() { return 'method'; })() ](x, y) { return x + y; } };");
+shouldBe("o.method(142, -10)", "132");
+
+shouldNotThrow("o = { [10*10]() { return 100; } };");
+shouldBe("o[100]()", "100");
+shouldBe("o['100']()", "100");
+shouldNotThrow("o = { [100 + 0.100]() { return 100.100; } };");
+shouldBe("o[100.1]()", "100.1");
+shouldBe("o['100.1']()", "100.1");
+
+shouldNotThrow("o = { ['a' + 'dd']([x, y]) { return x + y; } };");
+shouldBe("o.add([142, -100])", "42");
+
+shouldNotThrow("o = { [Array]([x, y]) { return x + y; } };");
+shouldBe("o[Array.toString()]([142, -100])", "42");
+
+a = 1; b = 2; c = 3; foo = "foo"; bar = "bar";
+shouldNotThrow("o = { foo() { return 10; }, };");
+shouldNotThrow("o = { foo (  ) { return 10; } };");
+shouldNotThrow("o = {[true](){return true;}};");
+shouldNotThrow("o = {[NaN](){return NaN;}};");
+shouldNotThrow("o = {[eval](){return eval;}};");
+shouldNotThrow("o = { a:1, [foo]() { return 10; }, [bar]() { return 20; }, b: 2 };");
+shouldNotThrow("o = { a:1, [foo]() { return 10; }, [bar]() { return 20; }, b };");
+shouldNotThrow("o = { a:1, [foo]() { return 10; }, b: b, [bar]() { return 20; }, c: 2 };");
+shouldNotThrow("o = { a:1, [foo]() { return 10; }, b, [bar]() { return 20; }, c };");
+
+shouldNotThrow("o = {[foo]:{[bar](){ return 100; }}};");
+shouldBe("o.foo.bar()", "100");
+
+// Duplicate methods are okay.
+shouldNotThrow("o = { [foo]() { return 10; }, [foo]() { return 20; } };");
+shouldBe("o.foo()", "20");
+
+// Method named "get" or "set".
+shouldNotThrow("o = { ['get'](x, y) { return x + y; } };");
+shouldBe("o.get('hello', 'world')", "'helloworld'");
+shouldNotThrow("o = { ['set'](x, y) { return x + y; } };");
+shouldBe("o.set('hello', 'world')", "'helloworld'");
+
+// Function parse errors.
+shouldThrow("({ [](,,,){} })");
+shouldThrow("({ [1+](){} })");
+shouldThrow("({ [1,](){} })");
+shouldThrow("({ [[1](){} })");
+shouldThrow("({ [foo](,,,){} })");
+shouldThrow("({ [foo](a{}, bar(){} })");
+shouldThrow("({ [foo](a, b), bar(){} })");
+shouldThrow("({ [foo](a, b) { if }, bar(){} })");
+
+// __proto__ method should be not modify the prototype.
+shouldBeTrue("({__proto__: function(){}}) instanceof Function");
+shouldBeFalse("({['__proto__'](){}}) instanceof Function");
+shouldBeTrue("({['__proto__'](){}}).__proto__ instanceof Function");

Added: trunk/LayoutTests/js/script-tests/object-literal-methods.js (0 => 181183)


--- trunk/LayoutTests/js/script-tests/object-literal-methods.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/object-literal-methods.js	2015-03-06 22:31:28 UTC (rev 181183)
@@ -0,0 +1,84 @@
+description("basic tests for object literal methods");
+
+shouldNotThrow("o = { foo() { return 10; } };");
+shouldBe("o.foo()", "10");
+shouldBe("typeof o.foo", "'function'");
+shouldBe("o.foo.length", "0");
+shouldBe("o.foo.name", "'foo'");
+shouldBe("o.foo.toString()", "'function foo() { return 10; }'");
+shouldBe("Object.getOwnPropertyDescriptor(o, 'foo').value", "o.foo");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').enumerable");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').configurable");
+shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').writable");
+
+shouldNotThrow("o = { add(x, y) { return x + y; } };");
+shouldBe("o.add(42, -10)", "32");
+shouldBe("typeof o.add", "'function'");
+shouldBe("o.add.length", "2");
+shouldBe("o.add.name", "'add'");
+shouldBe("o.add.toString()", "'function add(x, y) { return x + y; }'");
+
+shouldNotThrow("o = { 'add'(a, b, c) { return a + b + c; } };");
+shouldBe("o.add(1, 2, 3)", "6");
+shouldNotThrow("o = { 'a(d)d'(a, b, c) { return a + b + c; } };");
+shouldBe("o['a(d)d'](1, 2, 3)", "6");
+
+shouldNotThrow("o = { 100() { return 100; } };");
+shouldBe("o[100]()", "100");
+shouldBe("o['100']()", "100");
+shouldNotThrow("o = { 100.100() { return 100.100; } };");
+shouldBe("o[100.1]()", "100.1");
+shouldBe("o['100.1']()", "100.1");
+shouldNotThrow("o = { 1e3() { return 1e3; } };");
+shouldBe("o[1e3]()", "1000");
+shouldBe("o['1000']()", "1000");
+shouldNotThrow("o = { 0x11() { return 0x11; } };");
+shouldBe("o[0x11]()", "17");
+shouldBe("o['17']()", "17");
+
+shouldNotThrow("o = { add([x, y]) { return x + y; } };");
+shouldBe("o.add([142, -100])", "42");
+
+a = 1; b = 2; c = 3;
+shouldNotThrow("o = { foo() { return 10; }, };");
+shouldNotThrow("o = { foo (  ) { return 10; } };");
+shouldNotThrow("o = {true(){return true;}};");
+shouldNotThrow("o = {NaN(){return NaN;}};");
+shouldNotThrow("o = {eval(){return eval;}};");
+shouldNotThrow("o = { a:1, foo() { return 10; }, bar() { return 20; }, b: 2 };");
+shouldNotThrow("o = { a:1, foo() { return 10; }, bar() { return 20; }, b };");
+shouldNotThrow("o = { a:1, foo() { return 10; }, b: b, bar() { return 20; }, c: 2 };");
+shouldNotThrow("o = { a:1, foo() { return 10; }, b, bar() { return 20; }, c };");
+
+shouldNotThrow("o = {inner:{method(){ return 100; }}};");
+shouldBe("o.inner.method()", "100");
+
+// Duplicate methods are okay.
+shouldNotThrow("o = { foo() { return 10; }, foo() { return 20; } };");
+shouldBe("o.foo()", "20");
+
+// Method named "get" or "set".
+shouldNotThrow("o = { get(x, y) { return x + y; } };");
+shouldBe("o.get('hello', 'world')", "'helloworld'");
+shouldNotThrow("o = { set(x, y) { return x + y; } };");
+shouldBe("o.set('hello', 'world')", "'helloworld'");
+
+// Getter/Setter syntax still works.
+shouldBeTrue("({get x(){ return true; }}).x");
+shouldBeTrue("({get 'x'(){ return true; }}).x");
+shouldBeTrue("({get 42(){ return true; }})['42']");
+shouldBeTrue("!!Object.getOwnPropertyDescriptor({set x(value){}}, 'x').set");
+shouldBeTrue("!!Object.getOwnPropertyDescriptor({set 'x'(value){}}, 'x').set");
+shouldBeTrue("!!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set");
+
+// Function parse errors.
+shouldThrow("({ (){} })");
+shouldThrow("({ foo(,,,){} })");
+shouldThrow("({ foo(a{}, bar(){} })");
+shouldThrow("({ foo(a, b), bar(){} })");
+shouldThrow("({ foo(a, b) { if }, bar(){} })");
+
+// __proto__ method should be not modify the prototype.
+shouldBeTrue("({__proto__: function(){}}) instanceof Function");
+shouldBeFalse("({__proto__(){}}) instanceof Function");
+shouldBeTrue("({__proto__(){}}).__proto__ instanceof Function");

Modified: trunk/Source/_javascript_Core/ChangeLog (181182 => 181183)


--- trunk/Source/_javascript_Core/ChangeLog	2015-03-06 22:29:10 UTC (rev 181182)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-03-06 22:31:28 UTC (rev 181183)
@@ -1,3 +1,22 @@
+2015-03-06  Joseph Pecoraro  <pecor...@apple.com>
+
+        ES6: Object Literal Extensions - Methods
+        https://bugs.webkit.org/show_bug.cgi?id=142390
+
+        Reviewed by Geoffrey Garen.
+
+        Support method syntax in object literals.
+
+        * parser/Parser.h:
+        * parser/Parser.cpp:
+        (JSC::stringForFunctionMode):
+        (JSC::Parser<LexerType>::parseProperty):
+        Methods are allowed for identifier, string, and numeric names,
+        and computed property names.
+
+        (JSC::Parser<LexerType>::parsePropertyMethod):
+        Helper for parsing a property method.
+
 2015-03-05  Joseph Pecoraro  <pecor...@apple.com>
 
         __proto__ shorthand property should not modify prototype in Object Literal construction

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (181182 => 181183)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2015-03-06 22:29:10 UTC (rev 181182)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2015-03-06 22:31:28 UTC (rev 181183)
@@ -1282,10 +1282,8 @@
         return "setter";
     case FunctionMode:
         return "function";
-#if ENABLE(ES6_CLASS_SYNTAX)
     case MethodMode:
         return "method";
-#endif
     }
     RELEASE_ASSERT_NOT_REACHED();
     return nullptr;
@@ -1936,6 +1934,12 @@
             return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete);
         }
 
+        if (match(OPENPAREN)) {
+            auto method = parsePropertyMethod(context, ident);
+            propagateError();
+            return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
+        }
+
         failIfFalse(wasIdent, "Expected an identifier as property name");
 
         if (match(COMMA) || match(CLOSEBRACE)) {
@@ -1959,6 +1963,14 @@
     case INTEGER: {
         double propertyName = m_token.m_data.doubleValue;
         next();
+
+        if (match(OPENPAREN)) {
+            const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
+            auto method = parsePropertyMethod(context, &ident);
+            propagateError();
+            return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
+        }
+
         consumeOrFail(COLON, "Expected ':' after property name");
         TreeExpression node = parseAssignmentExpression(context);
         failIfFalse(node, "Cannot parse _expression_ for property declaration");
@@ -1969,8 +1981,14 @@
         next();
         auto propertyName = parseExpression(context);
         failIfFalse(propertyName, "Cannot parse computed property name");
-        
         handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
+
+        if (match(OPENPAREN)) {
+            auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
+            propagateError();
+            return context.createProperty(propertyName, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
+        }
+
         consumeOrFail(COLON, "Expected ':' after property name");
         TreeExpression node = parseAssignmentExpression(context);
         failIfFalse(node, "Cannot parse _expression_ for property declaration");
@@ -1984,6 +2002,17 @@
 }
 
 template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
+{
+    JSTokenLocation methodLocation(tokenLocation());
+    unsigned methodStart = tokenStart();
+    ParserFunctionInfo<TreeBuilder> methodInfo;
+    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, methodInfo)), "Cannot parse this method");
+    methodInfo.name = methodName;
+    return context.createFunctionExpr(methodLocation, methodInfo, methodStart);
+}
+
+template <typename LexerType>
 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset)
 {
     const Identifier* stringPropertyName = 0;

Modified: trunk/Source/_javascript_Core/parser/Parser.h (181182 => 181183)


--- trunk/Source/_javascript_Core/parser/Parser.h	2015-03-06 22:29:10 UTC (rev 181182)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2015-03-06 22:31:28 UTC (rev 181183)
@@ -85,9 +85,7 @@
     FunctionMode,
     GetterMode,
     SetterMode,
-#if ENABLE(ES6_CLASS_SYNTAX)
-    MethodMode
-#endif
+    MethodMode,
 };
 enum DeconstructionKind {
     DeconstructToVariables,
@@ -739,6 +737,7 @@
     enum SpreadMode { AllowSpread, DontAllowSpread };
     template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode);
     template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
+    template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
     template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset);
     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to