Commit b449691d authored by rossberg@chromium.org's avatar rossberg@chromium.org

ES6 symbols: fix corner cases of equality operators

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
parent a172a5e8
...@@ -2508,7 +2508,10 @@ void Name::set_hash_field(uint32_t value) { ...@@ -2508,7 +2508,10 @@ void Name::set_hash_field(uint32_t value) {
bool Name::Equals(Name* other) { bool Name::Equals(Name* other) {
if (other == this) return true; 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)); return String::cast(this)->SlowEquals(String::cast(other));
} }
......
...@@ -98,6 +98,10 @@ MaybeObject* Object::ToObject() { ...@@ -98,6 +98,10 @@ MaybeObject* Object::ToObject() {
Isolate* isolate = HeapObject::cast(this)->GetIsolate(); Isolate* isolate = HeapObject::cast(this)->GetIsolate();
Context* native_context = isolate->context()->native_context(); Context* native_context = isolate->context()->native_context();
return CreateJSValue(native_context->string_function(), this); 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. // Throw a type error.
......
...@@ -69,16 +69,24 @@ function EQUALS(y) { ...@@ -69,16 +69,24 @@ function EQUALS(y) {
} else if (IS_STRING(x)) { } else if (IS_STRING(x)) {
while (true) { while (true) {
if (IS_STRING(y)) return %StringEquals(x, y); 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_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y)); if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal if (IS_NULL_OR_UNDEFINED(y)) return 1; // not equal
y = %ToPrimitive(y, NO_HINT); 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)) { } else if (IS_BOOLEAN(x)) {
if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1; if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
if (IS_NULL_OR_UNDEFINED(y)) return 1; if (IS_NULL_OR_UNDEFINED(y)) return 1;
if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y); if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y)); if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
if (IS_SYMBOL(y)) return 1; // not equal
// y is object. // y is object.
x = %ToNumber(x); x = %ToNumber(x);
y = %ToPrimitive(y, NO_HINT); y = %ToPrimitive(y, NO_HINT);
...@@ -508,6 +516,7 @@ function ToPrimitive(x, hint) { ...@@ -508,6 +516,7 @@ function ToPrimitive(x, hint) {
if (IS_STRING(x)) return x; if (IS_STRING(x)) return x;
// Normal behavior. // Normal behavior.
if (!IS_SPEC_OBJECT(x)) return x; 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; if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x); return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
} }
......
...@@ -131,13 +131,17 @@ TestToNumber() ...@@ -131,13 +131,17 @@ TestToNumber()
function TestEquality() { function TestEquality() {
// Every symbol should equal itself. // Every symbol should equal itself, and non-strictly equal its wrapper.
for (var i in symbols) { for (var i in symbols) {
assertSame(symbols[i], symbols[i]) assertSame(symbols[i], symbols[i])
assertEquals(symbols[i], symbols[i]) assertEquals(symbols[i], symbols[i])
assertTrue(Object.is(symbols[i], symbols[i])) assertTrue(Object.is(symbols[i], symbols[i]))
assertTrue(symbols[i] === symbols[i]) assertTrue(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. // All symbols should be distinct.
...@@ -148,6 +152,17 @@ function TestEquality() { ...@@ -148,6 +152,17 @@ function TestEquality() {
assertFalse(symbols[i] == symbols[j]) 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() TestEquality()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment