Expose SameValue equality comparison algorithm
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 16:51:43 +0000 (16:51 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 16:51:43 +0000 (16:51 +0000)
Since SameValue algorithm is defined formally in ECMA262 and V8 already
exported Equals and StrictEquals algorithms, SameValue should be exposed.
And in this issue, we fix the issue of Object::SameValue implementation,
SameValue(0.0, -0.0) returnes true.

BUG=v8:2909
TEST=cctest/test-api/Equality
R=mstarzinger@chromium.org

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

Patch from Yusuke Suzuki <yusukesuzuki@chromium.org>.

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

include/v8.h
src/api.cc
src/objects.cc
test/cctest/test-api.cc

index 4206105..62a1cb3 100644 (file)
@@ -1479,6 +1479,7 @@ class V8_EXPORT Value : public Data {
   /** JS == */
   bool Equals(Handle<Value> that) const;
   bool StrictEquals(Handle<Value> that) const;
+  bool SameValue(Handle<Value> that) const;
 
   template <class T> V8_INLINE static Value* Cast(T* value);
 
index 618e444..6eb3789 100644 (file)
@@ -3055,6 +3055,19 @@ bool Value::StrictEquals(Handle<Value> that) const {
 }
 
 
+bool Value::SameValue(Handle<Value> that) const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (EmptyCheck("v8::Value::SameValue()", this) ||
+      EmptyCheck("v8::Value::SameValue()", that)) {
+    return false;
+  }
+  LOG_API(isolate, "SameValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> other = Utils::OpenHandle(*that);
+  return obj->SameValue(*other);
+}
+
+
 uint32_t Value::Uint32Value() const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) {
index 2ed417f..169307f 100644 (file)
@@ -1005,8 +1005,11 @@ bool Object::SameValue(Object* other) {
   if (IsNumber() && other->IsNumber()) {
     double this_value = Number();
     double other_value = other->Number();
-    return (this_value == other_value) ||
-        (std::isnan(this_value) && std::isnan(other_value));
+    bool equal = this_value == other_value;
+    // SameValue(NaN, NaN) is true.
+    if (!equal) return std::isnan(this_value) && std::isnan(other_value);
+    // SameValue(0.0, -0.0) is false.
+    return (this_value != 0) || ((1 / this_value) == (1 / other_value));
   }
   if (IsString() && other->IsString()) {
     return String::cast(this)->Equals(String::cast(other));
index 070c377..cfebeff 100644 (file)
@@ -4973,7 +4973,7 @@ THREADED_TEST(Equality) {
   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
-  CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
+  CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   CHECK(!not_a_number->StrictEquals(not_a_number));
   CHECK(v8::False()->StrictEquals(v8::False()));
@@ -4983,6 +4983,16 @@ THREADED_TEST(Equality) {
   v8::Persistent<v8::Object> alias(isolate, obj);
   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   alias.Dispose();
+
+  CHECK(v8_str("a")->SameValue(v8_str("a")));
+  CHECK(!v8_str("a")->SameValue(v8_str("b")));
+  CHECK(!v8_str("5")->SameValue(v8_num(5)));
+  CHECK(v8_num(1)->SameValue(v8_num(1)));
+  CHECK(!v8_num(1)->SameValue(v8_num(2)));
+  CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
+  CHECK(not_a_number->SameValue(not_a_number));
+  CHECK(v8::False()->SameValue(v8::False()));
+  CHECK(!v8::False()->SameValue(v8::Undefined()));
 }