Reviewers: Mads Ager,

Message:
Mads,

may you have a look?

I am not quite satisfied with this CL: ideally I'd rather have 2-arguments
SAFE_EQUALS JS builtin or function which invokes EQUALS JS builtin (or vice
versa). However I didn't manage to make JS bultins call each other. And if I make SAFE_EQUALS a plain JS function, it might trigger GC when getting lazily compiled (which is no-no thanks to security checks). So I ended up with this
special casing.  Any other ideas are most appreciated.

Description:
Compare JSObjects by identity immediately.

When invoking EQUALS JS builtin, 1st argument is passed as a receiver and
if it's a global object, it gets overwritten with global proxy object and
thus one gets incorrect results.

BUG=v8::1082

Please review this at http://codereview.chromium.org/6287018/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/api.cc
  M test/cctest/test-api.cc


Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index 93037822cf3553ca0b60b62b736430b96770520d..abc48ba1a0c160b76147b824de3a61c107dfb52f 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2200,6 +2200,12 @@ bool Value::Equals(Handle<Value> that) const {
   ENTER_V8;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::Object> other = Utils::OpenHandle(*that);
+  // If both obj and other are JSObjects, we'd better compare by identity
+  // immediately when going into JS builtin.  The reason is Invoke
+  // would overwrite global object receiver with global proxy.
+  if (obj->IsJSObject() && other->IsJSObject()) {
+    return *obj == *other;
+  }
   i::Object** args[1] = { other.location() };
   EXCEPTION_PREAMBLE();
   i::Handle<i::Object> result =
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 9b9f469f60a7a4d434eed5ca7c5003487f0a4fad..3a58929e497d065bbf49dd2f5c0a37749746c342 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -12201,6 +12201,25 @@ TEST(RegExp) {
 }


+THREADED_TEST(EQUALS) {
+  v8::HandleScope handleScope;
+  LocalContext localContext;
+
+  v8::Handle<v8::Object> globalProxy = localContext->Global();
+  v8::Handle<Value> global = globalProxy->GetPrototype();
+
+  CHECK_EQ(1, global->StrictEquals(global));
+  CHECK_EQ(0, global->StrictEquals(globalProxy));
+  CHECK_EQ(0, globalProxy->StrictEquals(global));
+  CHECK_EQ(1, globalProxy->StrictEquals(globalProxy));
+
+  CHECK_EQ(1, global->Equals(global));
+  CHECK_EQ(0, global->Equals(globalProxy));
+  CHECK_EQ(0, globalProxy->Equals(global));
+  CHECK_EQ(1, globalProxy->Equals(globalProxy));
+}
+
+
 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
                                     const v8::AccessorInfo& info ) {
   return v8_str("42!");


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to