diff --git a/src/api.cc b/src/api.cc index 8d3018409a..399d091ac7 100644 --- a/src/api.cc +++ b/src/api.cc @@ -2661,26 +2661,38 @@ int v8::Object::GetIdentityHash() { ENTER_V8; HandleScope scope; i::Handle self = Utils::OpenHandle(this); - i::Handle hidden_props(i::GetHiddenProperties(self, true)); - i::Handle hash_symbol = i::Factory::identity_hash_symbol(); - i::Handle hash = i::GetProperty(hidden_props, hash_symbol); - int hash_value; - if (hash->IsSmi()) { - hash_value = i::Smi::cast(*hash)->value(); - } else { - int attempts = 0; - do { - // Generate a random 32-bit hash value but limit range to fit - // within a smi. - hash_value = i::V8::Random() & i::Smi::kMaxValue; - attempts++; - } while (hash_value == 0 && attempts < 30); - hash_value = hash_value != 0 ? hash_value : 1; // never return 0 - i::SetProperty(hidden_props, - hash_symbol, - i::Handle(i::Smi::FromInt(hash_value)), - static_cast(None)); + i::Handle hidden_props_obj(i::GetHiddenProperties(self, true)); + if (!hidden_props_obj->IsJSObject()) { + // We failed to create hidden properties. That's a detached + // global proxy. + ASSERT(hidden_props_obj->IsUndefined()); + return 0; } + i::Handle hidden_props = + i::Handle::cast(hidden_props_obj); + i::Handle hash_symbol = i::Factory::identity_hash_symbol(); + if (hidden_props->HasLocalProperty(*hash_symbol)) { + i::Handle hash = i::GetProperty(hidden_props, hash_symbol); + CHECK(!hash.is_null()); + CHECK(hash->IsSmi()); + return i::Smi::cast(*hash)->value(); + } + + int hash_value; + int attempts = 0; + do { + // Generate a random 32-bit hash value but limit range to fit + // within a smi. + hash_value = i::V8::Random() & i::Smi::kMaxValue; + attempts++; + } while (hash_value == 0 && attempts < 30); + hash_value = hash_value != 0 ? hash_value : 1; // never return 0 + CHECK(!i::SetLocalPropertyIgnoreAttributes( + hidden_props, + hash_symbol, + i::Handle(i::Smi::FromInt(hash_value)), + static_cast(None)).is_null()); + return hash_value; } diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index b68fdffe19..b92185f52a 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -1649,6 +1649,23 @@ THREADED_TEST(IdentityHash) { CHECK_NE(hash, hash3); int hash4 = obj->GetIdentityHash(); CHECK_EQ(hash, hash4); + + // Check identity hashes behaviour in the presence of JS accessors. + // Put a getter for 'v8::IdentityHash' on the Object's prototype: + { + CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n"); + Local o1 = v8::Object::New(); + Local o2 = v8::Object::New(); + CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash()); + } + { + CompileRun( + "function cnst() { return 42; };\n" + "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n"); + Local o1 = v8::Object::New(); + Local o2 = v8::Object::New(); + CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash()); + } }