ES6: Implement object literal property shorthand
authorarv@chromium.org <arv@chromium.org>
Mon, 29 Sep 2014 14:15:48 +0000 (14:15 +0000)
committerarv@chromium.org <arv@chromium.org>
Mon, 29 Sep 2014 14:15:48 +0000 (14:15 +0000)
This allows the following:

var x = 1;
var o = {x};

This is under the --harmony-object-literals flag.

BUG=v8:3584
LOG=y
R=marja@chromium.org, rossberg@chromium.org

Review URL: https://codereview.chromium.org/584993002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24291 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/preparser.h
src/token.h
test/cctest/test-parsing.cc
test/mjsunit/harmony/object-literals-property-shorthand.js [new file with mode: 0644]

index 78f6a26..b34b04e 100644 (file)
@@ -2027,6 +2027,12 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
     return factory()->NewObjectLiteralProperty(is_get, value, next_pos,
                                                is_static);
+
+  } else if (!in_class && allow_harmony_object_literals_ &&
+             Token::IsIdentifier(name_token, strict_mode(),
+                                 this->is_generator())) {
+    value = this->ExpressionFromIdentifier(name, next_pos, scope_, factory());
+
   } else {
     Token::Value next = Next();
     ReportUnexpectedToken(next);
index 9c719b8..bab925a 100644 (file)
@@ -6,6 +6,7 @@
 #define V8_TOKEN_H_
 
 #include "src/base/logging.h"
+#include "src/globals.h"
 
 namespace v8 {
 namespace internal {
@@ -187,6 +188,24 @@ class Token {
     return token_type[tok] == 'K';
   }
 
+  static bool IsIdentifier(Value tok, StrictMode strict_mode,
+                           bool is_generator) {
+    switch (tok) {
+      case IDENTIFIER:
+        return true;
+      case FUTURE_STRICT_RESERVED_WORD:
+      case LET:
+      case STATIC:
+        return strict_mode == SLOPPY;
+      case YIELD:
+        return !is_generator && strict_mode == SLOPPY;
+      default:
+        return false;
+    }
+    UNREACHABLE();
+    return false;
+  }
+
   static bool IsAssignmentOp(Value tok) {
     return INIT_VAR <= tok && tok <= ASSIGN_MOD;
   }
index 72f2298..3556c64 100644 (file)
@@ -3969,3 +3969,121 @@ TEST(ClassesAreStrictErrors) {
   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
                     always_flags, arraysize(always_flags));
 }
+
+
+TEST(ObjectLiteralPropertyShorthandKeywordsError) {
+  const char* context_data[][2] = {{"({", "});"},
+                                   {"'use strict'; ({", "});"},
+                                   {NULL, NULL}};
+
+  const char* name_data[] = {
+    "break",
+    "case",
+    "catch",
+    "class",
+    "const",
+    "continue",
+    "debugger",
+    "default",
+    "delete",
+    "do",
+    "else",
+    "enum",
+    "export",
+    "extends",
+    "false",
+    "finally",
+    "for",
+    "function",
+    "if",
+    "import",
+    "in",
+    "instanceof",
+    "new",
+    "null",
+    "return",
+    "super",
+    "switch",
+    "this",
+    "throw",
+    "true",
+    "try",
+    "typeof",
+    "var",
+    "void",
+    "while",
+    "with",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, name_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
+  const char* context_data[][2] = {{"({", "});"},
+                                   {NULL, NULL}};
+
+  const char* name_data[] = {
+    "implements",
+    "interface",
+    "let",
+    "package",
+    "private",
+    "protected",
+    "public",
+    "static",
+    "yield",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+
+  const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
+                                          {NULL, NULL}};
+  RunParserSyncTest(context_strict_data, name_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(ObjectLiteralPropertyShorthandError) {
+  const char* context_data[][2] = {{"({", "});"},
+                                   {"'use strict'; ({", "});"},
+                                   {NULL, NULL}};
+
+  const char* name_data[] = {
+    "1",
+    "1.2",
+    "0",
+    "0.1",
+    "1.0",
+    "1e1",
+    "0x1",
+    "\"s\"",
+    "'s'",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, name_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+
+TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
+  const char* context_data[][2] = {{"", ""},
+                                   {NULL, NULL}};
+
+  const char* name_data[] = {
+    "function* g() { ({yield}); }",
+    NULL
+  };
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
+  RunParserSyncTest(context_data, name_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
diff --git a/test/mjsunit/harmony/object-literals-property-shorthand.js b/test/mjsunit/harmony/object-literals-property-shorthand.js
new file mode 100644 (file)
index 0000000..2921495
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-object-literals
+
+
+(function TestBasics() {
+  var x = 1;
+  var object = {x};
+  assertEquals(1, object.x);
+})();
+
+
+(function TestDescriptor() {
+  var x = 1;
+  var object = {x};
+  var descr = Object.getOwnPropertyDescriptor(object, 'x');
+  assertEquals(1, descr.value);
+  assertTrue(descr.enumerable);
+  assertTrue(descr.writable);
+  assertTrue(descr.configurable);
+})();
+
+
+(function TestNotDefined() {
+  'use strict';
+  assertThrows(function() {
+    return {notDefined};
+  }, ReferenceError);
+})();
+
+
+(function TestLet() {
+  var let = 1;
+  var object = {let};
+  assertEquals(1, object.let);
+})();
+
+
+(function TestYieldInFunction() {
+  var yield = 1;
+  var object = {yield};
+  assertEquals(1, object.yield);
+})();
+
+
+(function TestToString() {
+  function f(x) { return {x}; }
+  assertEquals('function f(x) { return {x}; }', f.toString());
+})();