ES6 symbols: fix corner cases of equality operators
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Apr 2013 17:06:22 +0000 (17:06 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Apr 2013 17:06:22 +0000 (17:06 +0000)
R=mstarzinger@chromium.org
BUG=

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

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

src/objects-inl.h
src/objects.cc
src/runtime.js
test/mjsunit/harmony/symbols.js

index 8d6f307..ec03405 100644 (file)
@@ -2508,7 +2508,10 @@ void Name::set_hash_field(uint32_t value) {
 
 bool Name::Equals(Name* other) {
   if (other == this) return true;
-  if (this->IsUniqueName() && other->IsUniqueName()) return false;
+  if (this->IsSymbol() || other->IsSymbol() ||
+      (this->IsInternalizedString() && other->IsInternalizedString())) {
+    return false;
+  }
   return String::cast(this)->SlowEquals(String::cast(other));
 }
 
index f3e7471..0662ba5 100644 (file)
@@ -98,6 +98,10 @@ MaybeObject* Object::ToObject() {
     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     Context* native_context = isolate->context()->native_context();
     return CreateJSValue(native_context->string_function(), this);
+  } else if (IsSymbol()) {
+    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+    Context* native_context = isolate->context()->native_context();
+    return CreateJSValue(native_context->symbol_function(), this);
   }
 
   // Throw a type error.
index 8f4388a..22f888d 100644 (file)
@@ -69,16 +69,24 @@ function EQUALS(y) {
     } else if (IS_STRING(x)) {
       while (true) {
         if (IS_STRING(y)) return %StringEquals(x, y);
+        if (IS_SYMBOL(y)) return 1;  // not equal
         if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
         if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
         y = %ToPrimitive(y, NO_HINT);
       }
+    } else if (IS_SYMBOL(x)) {
+      while (true) {
+        if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
+        if (!IS_SPEC_OBJECT(y)) return 1;  // not equal
+        y = %ToPrimitive(y, NO_HINT);
+      }
     } else if (IS_BOOLEAN(x)) {
       if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
       if (IS_NULL_OR_UNDEFINED(y)) return 1;
       if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
       if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
+      if (IS_SYMBOL(y)) return 1;  // not equal
       // y is object.
       x = %ToNumber(x);
       y = %ToPrimitive(y, NO_HINT);
@@ -508,6 +516,7 @@ function ToPrimitive(x, hint) {
   if (IS_STRING(x)) return x;
   // Normal behavior.
   if (!IS_SPEC_OBJECT(x)) return x;
+  if (IS_SYMBOL_WRAPPER(x)) return %_ValueOf(x);
   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
   return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
 }
index 93b6fbd..a3f6e57 100644 (file)
@@ -131,13 +131,17 @@ TestToNumber()
 
 
 function TestEquality() {
-  // Every symbol should equal itself.
+  // Every symbol should equal itself, and non-strictly equal its wrapper.
   for (var i in symbols) {
     assertSame(symbols[i], symbols[i])
     assertEquals(symbols[i], symbols[i])
     assertTrue(Object.is(symbols[i], symbols[i]))
     assertTrue(symbols[i] === symbols[i])
     assertTrue(symbols[i] == symbols[i])
+    assertFalse(symbols[i] === new Symbol(symbols[i]))
+    assertFalse(new Symbol(symbols[i]) === symbols[i])
+    assertTrue(symbols[i] == new Symbol(symbols[i]))
+    assertTrue(new Symbol(symbols[i]) == symbols[i])
   }
 
   // All symbols should be distinct.
@@ -148,6 +152,17 @@ function TestEquality() {
       assertFalse(symbols[i] == symbols[j])
     }
   }
+
+  // Symbols should not be equal to any other value (and the test terminates).
+  var values = [347, 1.275, NaN, "string", null, undefined, {}, function() {}]
+  for (var i in symbols) {
+    for (var j in values) {
+      assertFalse(symbols[i] === values[j])
+      assertFalse(values[j] === symbols[i])
+      assertFalse(symbols[i] == values[j])
+      assertFalse(values[j] == symbols[i])
+    }
+  }
 }
 TestEquality()