diff --git a/src/objects-inl.h b/src/objects-inl.h index 8d6f307131..ec03405fdd 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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)); } diff --git a/src/objects.cc b/src/objects.cc index f3e7471c07..0662ba540c 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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. diff --git a/src/runtime.js b/src/runtime.js index 8f4388a453..22f888d814 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -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); } diff --git a/test/mjsunit/harmony/symbols.js b/test/mjsunit/harmony/symbols.js index 93b6fbda4e..a3f6e57208 100644 --- a/test/mjsunit/harmony/symbols.js +++ b/test/mjsunit/harmony/symbols.js @@ -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()