Update harmony ObjectProtoToString() to 2/2/2015 spec
authorcaitpotter88 <caitpotter88@gmail.com>
Tue, 3 Feb 2015 21:05:04 +0000 (13:05 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 3 Feb 2015 21:05:25 +0000 (21:05 +0000)
Applies to API implementation of O.p.toString

- Removes special handling of non-string @@toStringTag values (use builtinTag)
- Removes special handling of @@toStringTags which match [[Class]] names (remove ~ prefix)
- Add tests for non-string @@toStringTag values in test-api.cc

BUG=v8:3502
R=arv@chromium.org
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#26415}

src/api.cc
test/cctest/cctest.h
test/cctest/test-api.cc
test/mjsunit/es6/object-tostring.js

index 6caa82a..d5168cd 100644 (file)
@@ -3290,37 +3290,6 @@ Local<Array> v8::Object::GetOwnPropertyNames() {
 }
 
 
-static bool GetPredefinedToString(i::Handle<i::String> tag,
-                                  Local<String>* result) {
-  i::Isolate* i_isolate = tag->GetIsolate();
-  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
-  i::Factory* factory = i_isolate->factory();
-
-  if (i::String::Equals(tag, factory->Arguments_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Arguments]");
-  } else if (i::String::Equals(tag, factory->Array_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Array]");
-  } else if (i::String::Equals(tag, factory->Boolean_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Boolean]");
-  } else if (i::String::Equals(tag, factory->Date_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Date]");
-  } else if (i::String::Equals(tag, factory->Error_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Error]");
-  } else if (i::String::Equals(tag, factory->Function_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Function]");
-  } else if (i::String::Equals(tag, factory->Number_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~Number]");
-  } else if (i::String::Equals(tag, factory->RegExp_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~RegExp]");
-  } else if (i::String::Equals(tag, factory->String_string())) {
-    *result = v8::String::NewFromUtf8(isolate, "[object ~String]");
-  } else {
-    return false;
-  }
-  return true;
-}
-
-
 Local<String> v8::Object::ObjectProtoToString() {
   i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
@@ -3354,16 +3323,8 @@ Local<String> v8::Object::ObjectProtoToString() {
                  .ToHandle(&tag);
         EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::String>());
 
-        if (!tag->IsUndefined()) {
-          if (!tag->IsString())
-            return v8::String::NewFromUtf8(isolate, "[object ???]");
-          i::Handle<i::String> tag_name = i::Handle<i::String>::cast(tag);
-          if (!i::String::Equals(class_name, tag_name)) {
-            Local<String> result;
-            if (GetPredefinedToString(tag_name, &result)) return result;
-
-            class_name = tag_name;
-          }
+        if (tag->IsString()) {
+          class_name = i::Handle<i::String>::cast(tag);
         }
       }
       const char* prefix = "[object ";
index 2f33d13..1d70c0e 100644 (file)
@@ -347,6 +347,11 @@ static inline v8::Local<v8::String> v8_str(const char* x) {
 }
 
 
+static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
+  return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
+}
+
+
 static inline v8::Local<v8::Script> v8_compile(const char* x) {
   return v8::Script::Compile(v8_str(x));
 }
index 0009253..b8cf20d 100644 (file)
@@ -14002,19 +14002,58 @@ TEST(ObjectProtoToStringES6) {
   } while (0)
 
   TEST_TOSTRINGTAG(Array, Object, Object);
-  TEST_TOSTRINGTAG(Object, Arguments, ~Arguments);
-  TEST_TOSTRINGTAG(Object, Array, ~Array);
-  TEST_TOSTRINGTAG(Object, Boolean, ~Boolean);
-  TEST_TOSTRINGTAG(Object, Date, ~Date);
-  TEST_TOSTRINGTAG(Object, Error, ~Error);
-  TEST_TOSTRINGTAG(Object, Function, ~Function);
-  TEST_TOSTRINGTAG(Object, Number, ~Number);
-  TEST_TOSTRINGTAG(Object, RegExp, ~RegExp);
-  TEST_TOSTRINGTAG(Object, String, ~String);
+  TEST_TOSTRINGTAG(Object, Arguments, Arguments);
+  TEST_TOSTRINGTAG(Object, Array, Array);
+  TEST_TOSTRINGTAG(Object, Boolean, Boolean);
+  TEST_TOSTRINGTAG(Object, Date, Date);
+  TEST_TOSTRINGTAG(Object, Error, Error);
+  TEST_TOSTRINGTAG(Object, Function, Function);
+  TEST_TOSTRINGTAG(Object, Number, Number);
+  TEST_TOSTRINGTAG(Object, RegExp, RegExp);
+  TEST_TOSTRINGTAG(Object, String, String);
   TEST_TOSTRINGTAG(Object, Foo, Foo);
 
 #undef TEST_TOSTRINGTAG
 
+  Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
+                                                  v8::RegExp::kNone);
+  Local<Value> valueNumber = v8_num(123);
+  Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
+  Local<v8::Function> valueFunction =
+      CompileRun("function fn() {}").As<v8::Function>();
+  Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
+  Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
+  Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
+
+#define TEST_TOSTRINGTAG(type, tagValue, expected)          \
+  do {                                                      \
+    object = CompileRun("new " #type "()");                 \
+    object.As<v8::Object>()->Set(toStringTag, tagValue);    \
+    value = object.As<v8::Object>()->ObjectProtoToString(); \
+    CHECK(value->IsString() &&                              \
+          value->Equals(v8_str("[object " #expected "]"))); \
+  } while (0)
+
+#define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
+  TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
+  TEST_TOSTRINGTAG(Object, tagValue, Object);               \
+  TEST_TOSTRINGTAG(Function, tagValue, Function);           \
+  TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
+  TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
+  TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
+
+  // Test non-String-valued @@toStringTag
+  TEST_TOSTRINGTAG_TYPES(valueRegExp);
+  TEST_TOSTRINGTAG_TYPES(valueNumber);
+  TEST_TOSTRINGTAG_TYPES(valueSymbol);
+  TEST_TOSTRINGTAG_TYPES(valueFunction);
+  TEST_TOSTRINGTAG_TYPES(valueObject);
+  TEST_TOSTRINGTAG_TYPES(valueNull);
+  TEST_TOSTRINGTAG_TYPES(valueUndef);
+
+#undef TEST_TOSTRINGTAG
+#undef TEST_TOSTRINGTAG_TYPES
+
   // @@toStringTag getter throws
   Local<Value> obj = v8::Object::New(isolate);
   obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
index 064f2af..c73a768 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-tostring --allow-natives-syntax
+// Flags: --harmony-tostring
 
 var global = this;