Source/JavaScriptCore:
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Mar 2015 01:16:25 +0000 (01:16 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Mar 2015 01:16:25 +0000 (01:16 +0000)
ES6: Object Literal Extensions - Shorthand Properties (Identifiers)
https://bugs.webkit.org/show_bug.cgi?id=142353

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

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseProperty):
Parsing an identifier property followed by a comma or end brace treat
as a shorthand property and create a property that has the same
property name as the identifier name and value of a variable with that
identifier. Otherwise, fall through to getter/setter parsing.

LayoutTests:
Web Inspector: Follow-up fixes to ObjectTreeBaseTreeElement
https://bugs.webkit.org/show_bug.cgi?id=142367

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

* js/object-literal-shorthand-construction-expected.txt: Added.
* js/object-literal-shorthand-construction.html: Added.
* js/script-tests/object-literal-shorthand-construction.js: Added.
(equivalent):
(testShorthandConstructionEquivalent):
(testShorthandConstructionNotEquivalent):
Tests specifically for new literal construction with shorthands.

* sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T1-expected.txt:
* sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T2-expected.txt:
* sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.4_The_for_in_Statement/S12.6.4_A15-expected.txt:
These tests use object literal shorthand construction syntax and expected
failures. The tests now fail differently, so just rebase their results.

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

LayoutTests/ChangeLog
LayoutTests/js/object-literal-shorthand-construction-expected.txt [new file with mode: 0644]
LayoutTests/js/object-literal-shorthand-construction.html [new file with mode: 0644]
LayoutTests/js/script-tests/object-literal-shorthand-construction.js [new file with mode: 0644]
LayoutTests/sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T1-expected.txt
LayoutTests/sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T2-expected.txt
LayoutTests/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.4_The_for_in_Statement/S12.6.4_A15-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/Parser.cpp

index 0e92ddc..055d139 100644 (file)
@@ -1,3 +1,24 @@
+2015-03-05  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Follow-up fixes to ObjectTreeBaseTreeElement
+        https://bugs.webkit.org/show_bug.cgi?id=142367
+
+        Reviewed by Geoffrey Garen.
+
+        * js/object-literal-shorthand-construction-expected.txt: Added.
+        * js/object-literal-shorthand-construction.html: Added.
+        * js/script-tests/object-literal-shorthand-construction.js: Added.
+        (equivalent):
+        (testShorthandConstructionEquivalent):
+        (testShorthandConstructionNotEquivalent):
+        Tests specifically for new literal construction with shorthands.
+
+        * sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T1-expected.txt:
+        * sputnik/Conformance/12_Statement/12.1_Block/S12.1_A4_T2-expected.txt:
+        * sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.4_The_for_in_Statement/S12.6.4_A15-expected.txt:
+        These tests use object literal shorthand construction syntax and expected
+        failures. The tests now fail differently, so just rebase their results.
+
 2015-03-05  Timothy Horton  <timothy_horton@apple.com>
 
         <attachment> should allow the title property to override its title
diff --git a/LayoutTests/js/object-literal-shorthand-construction-expected.txt b/LayoutTests/js/object-literal-shorthand-construction-expected.txt
new file mode 100644 (file)
index 0000000..28eae7e
--- /dev/null
@@ -0,0 +1,67 @@
+basic tests for object literal shorthand construction
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS !!{a} is true
+PASS ({a}).a === 1 is true
+PASS ({a}).a === a is true
+PASS ({foo})['foo'] === foo is true
+PASS Object.getOwnPropertyDescriptor({a}, 'a').enumerable is true
+PASS Object.getOwnPropertyDescriptor({a}, 'a').configurable is true
+PASS Object.getOwnPropertyDescriptor({a}, 'a').writable is true
+PASS Object.keys({a,b}).join() is "a,b"
+PASS Object.keys({b,a}).join() is "b,a"
+PASS equivalent({a}, {a:a}) is true
+PASS equivalent({a}, {a:a}) is true
+PASS equivalent({a,}, {a:a}) is true
+PASS equivalent({a,a}, {a:a}) is true
+PASS equivalent({a,b}, {a:a, b:b}) is true
+PASS equivalent({ a , b }, {a:a, b:b}) is true
+PASS equivalent({a,b,}, {a:a, b:b}) is true
+PASS equivalent({a,b,a}, {a:a, b:b}) is true
+PASS equivalent({b,a,a}, {b:b, a:a}) is true
+PASS !equivalent({a}, {b:a}) is true
+PASS !equivalent({b}, {a:b}) is true
+PASS !equivalent({a,b}, {a:b, b:a}) is true
+PASS equivalent({foo}, {foo:foo}) is true
+PASS equivalent({foo}, {foo:foo}) is true
+PASS equivalent({foo,}, {foo:foo}) is true
+PASS equivalent({foo,foo}, {foo:foo}) is true
+PASS equivalent({foo,bar}, {foo:foo, bar:bar}) is true
+PASS equivalent({ foo , bar }, {foo:foo, bar:bar}) is true
+PASS equivalent({foo,bar,}, {foo:foo, bar:bar}) is true
+PASS equivalent({foo,bar,foo}, {foo:foo, bar:bar}) is true
+PASS equivalent({bar,foo,foo}, {bar:bar, foo:foo}) is true
+PASS equivalent({foo,bar,foo}, {foo:foo, bar:bar}) is true
+PASS equivalent({bar,foo,foo}, {bar:bar, foo:foo}) is true
+PASS !equivalent({foo}, {bar:foo}) is true
+PASS !equivalent({bar}, {foo:bar}) is true
+PASS !equivalent({foo,bar}, {foo:bar, bar:foo}) is true
+PASS equivalent({a, b:b, c}, {a, b, c}) is true
+PASS equivalent({a:a, b, c:c}, {a, b, c}) is true
+PASS equivalent({a, b, c:c}, {a, b, c}) is true
+PASS equivalent({'a':a, b, c:c}, {a, b, c}) is true
+PASS equivalent({nest:{a}}.nest, {nest: {a:a}}.nest) is true
+PASS equivalent({nest:[{a}]}.nest[0], {nest: [{a:a}]}.nest[0]) is true
+PASS equivalent([{nest:[{a}]}][0].nest[0], [{nest: [{a:a}]}][0].nest[0]) is true
+PASS equivalent({a,b,t,x,f,nul,un,fun,foo,bar}, {a:a, b:b, t:t, x:x, f:f, nul:null, un:un, fun:fun, foo:foo, bar:bar}) is true
+PASS equivalent({eval}, {eval: window.eval}) is true
+PASS ({noSuchIdentifier}) threw exception ReferenceError: Can't find variable: noSuchIdentifier.
+PASS ({a,noSuchIdentifier}) threw exception ReferenceError: Can't find variable: noSuchIdentifier.
+PASS ({noSuchIdentifier,a}) threw exception ReferenceError: Can't find variable: noSuchIdentifier.
+PASS ({a,b,noSuchIdentifier}) threw exception ReferenceError: Can't find variable: noSuchIdentifier.
+PASS ({get}) threw exception ReferenceError: Can't find variable: get.
+PASS ({set}) threw exception ReferenceError: Can't find variable: set.
+PASS equivalent({get}, {get: 1}) is true
+PASS equivalent({set}, {set: 2}) is true
+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 successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/object-literal-shorthand-construction.html b/LayoutTests/js/object-literal-shorthand-construction.html
new file mode 100644 (file)
index 0000000..2b244eb
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/object-literal-shorthand-construction.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/script-tests/object-literal-shorthand-construction.js b/LayoutTests/js/script-tests/object-literal-shorthand-construction.js
new file mode 100644 (file)
index 0000000..d8b439e
--- /dev/null
@@ -0,0 +1,110 @@
+description("basic tests for object literal shorthand construction");
+
+function equivalent(o1, o2) {
+    var keys1 = Object.keys(o1);
+    var keys2 = Object.keys(o2);
+    if (keys1.length !== keys2.length)
+        return false;
+
+    for (var i = 0; i < keys1.length; ++i) {
+        if (keys1[i] !== keys2[i])
+            return false;
+    }
+
+    for (var p in o1) {
+        if (o1[p] !== o2[p])
+            return false;
+    }
+
+    return true;
+}
+
+function testShorthandConstructionEquivalent(expr1, expr2) {
+    shouldBeTrue("equivalent(" + expr1 + ", " + expr2 + ")");
+}
+
+function testShorthandConstructionNotEquivalent(expr1, expr2) {
+    shouldBeTrue("!equivalent(" + expr1 + ", " + expr2 + ")");
+}
+
+a = 1;
+b = 2;
+c = 3;
+t = true;
+x = -0;
+f = 123.456;
+nul = null;
+un = undefined;
+fun = function myFunction() {}
+foo = {property: "value"};
+bar = [1, 2, 3];
+
+shouldBeTrue("!!{a}");
+shouldBeTrue("({a}).a === 1");
+shouldBeTrue("({a}).a === a");
+shouldBeTrue("({foo})['foo'] === foo");
+shouldBeTrue("Object.getOwnPropertyDescriptor({a}, 'a').enumerable");
+shouldBeTrue("Object.getOwnPropertyDescriptor({a}, 'a').configurable");
+shouldBeTrue("Object.getOwnPropertyDescriptor({a}, 'a').writable");
+shouldBe("Object.keys({a,b}).join()", '"a,b"');
+shouldBe("Object.keys({b,a}).join()", '"b,a"');
+
+testShorthandConstructionEquivalent("{a}", "{a:a}");
+testShorthandConstructionEquivalent("{a}", "{a:a}");
+testShorthandConstructionEquivalent("{a,}", "{a:a}");
+testShorthandConstructionEquivalent("{a,a}", "{a:a}");
+testShorthandConstructionEquivalent("{a,b}", "{a:a, b:b}");
+testShorthandConstructionEquivalent("{ a , b }", "{a:a, b:b}");
+testShorthandConstructionEquivalent("{a,b,}", "{a:a, b:b}");
+testShorthandConstructionEquivalent("{a,b,a}", "{a:a, b:b}");
+testShorthandConstructionEquivalent("{b,a,a}", "{b:b, a:a}");
+testShorthandConstructionNotEquivalent("{a}", "{b:a}");
+testShorthandConstructionNotEquivalent("{b}", "{a:b}");
+testShorthandConstructionNotEquivalent("{a,b}", "{a:b, b:a}");
+
+testShorthandConstructionEquivalent("{foo}", "{foo:foo}");
+testShorthandConstructionEquivalent("{foo}", "{foo:foo}");
+testShorthandConstructionEquivalent("{foo,}", "{foo:foo}");
+testShorthandConstructionEquivalent("{foo,foo}", "{foo:foo}");
+testShorthandConstructionEquivalent("{foo,bar}", "{foo:foo, bar:bar}");
+testShorthandConstructionEquivalent("{ foo , bar }", "{foo:foo, bar:bar}");
+testShorthandConstructionEquivalent("{foo,bar,}", "{foo:foo, bar:bar}");
+testShorthandConstructionEquivalent("{foo,bar,foo}", "{foo:foo, bar:bar}");
+testShorthandConstructionEquivalent("{bar,foo,foo}", "{bar:bar, foo:foo}");
+testShorthandConstructionEquivalent("{foo,bar,foo}", "{foo:foo, bar:bar}");
+testShorthandConstructionEquivalent("{bar,foo,foo}", "{bar:bar, foo:foo}");
+testShorthandConstructionNotEquivalent("{foo}", "{bar:foo}");
+testShorthandConstructionNotEquivalent("{bar}", "{foo:bar}");
+testShorthandConstructionNotEquivalent("{foo,bar}", "{foo:bar, bar:foo}");
+
+testShorthandConstructionEquivalent("{a, b:b, c}", "{a, b, c}");
+testShorthandConstructionEquivalent("{a:a, b, c:c}", "{a, b, c}");
+testShorthandConstructionEquivalent("{a, b, c:c}", "{a, b, c}");
+testShorthandConstructionEquivalent("{'a':a, b, c:c}", "{a, b, c}");
+
+testShorthandConstructionEquivalent("{nest:{a}}.nest", "{nest: {a:a}}.nest");
+testShorthandConstructionEquivalent("{nest:[{a}]}.nest[0]", "{nest: [{a:a}]}.nest[0]");
+testShorthandConstructionEquivalent("[{nest:[{a}]}][0].nest[0]", "[{nest: [{a:a}]}][0].nest[0]");
+testShorthandConstructionEquivalent("{a,b,t,x,f,nul,un,fun,foo,bar}", "{a:a, b:b, t:t, x:x, f:f, nul:null, un:un, fun:fun, foo:foo, bar:bar}");
+
+testShorthandConstructionEquivalent("{eval}", "{eval: window.eval}");
+
+shouldThrow("({noSuchIdentifier})");
+shouldThrow("({a,noSuchIdentifier})");
+shouldThrow("({noSuchIdentifier,a})");
+shouldThrow("({a,b,noSuchIdentifier})");
+
+shouldThrow("({get})"); // Shorthand, not a getter, but ReferenceError.
+shouldThrow("({set})"); // Shorthand, not a setter, but ReferenceError.
+get = 1;
+set = 2;
+testShorthandConstructionEquivalent("{get}", "{get: 1}");
+testShorthandConstructionEquivalent("{set}", "{set: 2}");
+
+// 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");
index bfbb21f..f842ddd 100644 (file)
@@ -1,7 +1,6 @@
-CONSOLE MESSAGE: line 80: SyntaxError: Unexpected token '}'. Expected a ':' following the property name '__func'.
 S12.1_A4_T1
 
-PASS Expected parsing failure
+PASS TypeError: Object is not a function (evaluating '{__func}()')
 
 TEST COMPLETE
 
index 7edaad8..122cb4e 100644 (file)
@@ -1,7 +1,6 @@
-CONSOLE MESSAGE: line 80: SyntaxError: Unexpected token '}'. Expected a ':' following the property name 'x'.
 S12.1_A4_T2
 
-PASS Expected parsing failure
+FAIL No error detected
 
 TEST COMPLETE
 
index ef74341..56d0e38 100644 (file)
@@ -1,3 +1,17 @@
+2015-03-05  Joseph Pecoraro  <pecoraro@apple.com>
+
+        ES6: Object Literal Extensions - Shorthand Properties (Identifiers)
+        https://bugs.webkit.org/show_bug.cgi?id=142353
+
+        Reviewed by Geoffrey Garen.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseProperty):
+        Parsing an identifier property followed by a comma or end brace treat
+        as a shorthand property and create a property that has the same
+        property name as the identifier name and value of a variable with that
+        identifier. Otherwise, fall through to getter/setter parsing.
+
 2015-03-05  Brent Fulgham  <bfulgham@apple.com>
 
         [Win] Unreviewed gardening.
index 6318fd6..f491ea6 100644 (file)
@@ -1869,7 +1869,6 @@ int Parser<LexerType>::isBinaryOperator(JSTokenType token)
 template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
 {
-    
     int operandStackDepth = 0;
     int operatorStackDepth = 0;
     typename TreeBuilder::BinaryExprContext binaryExprContext(context);
@@ -1928,7 +1927,7 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeB
             nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
         else
             nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
-        
+
         if (match(COLON)) {
             next();
             TreeExpression node = parseAssignmentExpression(context);
@@ -1936,7 +1935,17 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeB
             context.setEndOffset(node, m_lexer->currentOffset());
             return context.createProperty(ident, node, PropertyNode::Constant, complete);
         }
+
         failIfFalse(wasIdent, "Expected an identifier as property name");
+
+        if (match(COMMA) || match(CLOSEBRACE)) {
+            JSTextPosition start = tokenStartPosition();
+            JSTokenLocation location(tokenLocation());
+            currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
+            TreeExpression node = context.createResolve(location, ident, start);
+            return context.createProperty(ident, node, PropertyNode::Constant, complete);
+        }
+
         PropertyNode::Type type;
         if (*ident == m_vm->propertyNames->get)
             type = PropertyNode::Getter;