From a92d237948fa8a696b549efae88d5dd5c4da8208 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Wed, 26 Jun 2013 08:00:05 +0000 Subject: [PATCH] Allow users of the V8 API to distinguish between unset and undefined HiddenValues BUG=v8:2746 R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/17781002 Patch from Adam Klein . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15329 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 2 +- src/objects.cc | 7 +++---- src/objects.h | 2 +- src/runtime.cc | 1 + test/cctest/test-api.cc | 12 ++++++++++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/api.cc b/src/api.cc index 8ca858d..014d82e 100644 --- a/src/api.cc +++ b/src/api.cc @@ -3935,7 +3935,7 @@ v8::Local v8::Object::GetHiddenValue(v8::Handle key) { i::Handle key_string = isolate->factory()->InternalizeString(key_obj); i::Handle result(self->GetHiddenProperty(*key_string), isolate); - if (result->IsUndefined()) return v8::Local(); + if (result->IsTheHole()) return v8::Local(); return Utils::ToLocal(result); } diff --git a/src/objects.cc b/src/objects.cc index 8633012..5265901 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -4734,7 +4734,7 @@ Object* JSObject::GetHiddenProperty(Name* key) { // For a proxy, use the prototype as target object. Object* proxy_parent = GetPrototype(); // If the proxy is detached, return undefined. - if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); + if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); ASSERT(proxy_parent->IsJSGlobalObject()); return JSObject::cast(proxy_parent)->GetHiddenProperty(key); } @@ -4748,15 +4748,14 @@ Object* JSObject::GetHiddenProperty(Name* key) { if (key == GetHeap()->identity_hash_string()) { return inline_value; } else { - return GetHeap()->undefined_value(); + return GetHeap()->the_hole_value(); } } - if (inline_value->IsUndefined()) return GetHeap()->undefined_value(); + if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); Object* entry = hashtable->Lookup(key); - if (entry->IsTheHole()) return GetHeap()->undefined_value(); return entry; } diff --git a/src/objects.h b/src/objects.h index 2e2a018..d3abed1 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1996,7 +1996,7 @@ class JSObject: public JSReceiver { Handle value); // Returns a failure if a GC is required. MUST_USE_RESULT MaybeObject* SetHiddenProperty(Name* key, Object* value); - // Gets the value of a hidden property with the given key. Returns undefined + // Gets the value of a hidden property with the given key. Returns the hole // if the property doesn't exist (or if called on a detached proxy), // otherwise returns the value set for the key. Object* GetHiddenProperty(Name* key); diff --git a/src/runtime.cc b/src/runtime.cc index 8917c58..86f7f0f 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -13380,6 +13380,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedStackTrace) { CONVERT_ARG_CHECKED(JSObject, error_object, 0); String* key = isolate->heap()->hidden_stack_trace_string(); Object* result = error_object->GetHiddenProperty(key); + if (result->IsTheHole()) result = isolate->heap()->undefined_value(); RUNTIME_ASSERT(result->IsJSArray() || result->IsString() || result->IsUndefined()); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index c39b429..b95f292 100755 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -19280,6 +19280,18 @@ THREADED_TEST(Regress2535) { } +THREADED_TEST(Regress2746) { + LocalContext context; + v8::HandleScope scope(context->GetIsolate()); + Local obj = Object::New(); + Local key = String::New("key"); + obj->SetHiddenValue(key, v8::Undefined()); + Local value = obj->GetHiddenValue(key); + CHECK(!value.IsEmpty()); + CHECK(value->IsUndefined()); +} + + #ifndef WIN32 class ThreadInterruptTest { public: -- 2.7.4