LOG_API("CloseHandleScope");
// Read the result before popping the handle block.
- i::Object* result = *value;
+ i::Object* result = NULL;
+ if (value != NULL) {
+ result = *value;
+ }
is_closed_ = true;
i::HandleScope::Leave(&previous_);
+ if (value == NULL) {
+ return NULL;
+ }
+
// Allocate a new handle on the previous handle block.
i::Handle<i::Object> handle(result);
return handle.location();
template <class T>
v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
v8::HandleScope* scope) {
- return Utils::OpenHandle(*scope->Close(Utils::ToLocal(*this)));
+ v8::internal::Handle<T> handle;
+ if (!is_null()) {
+ handle = *this;
+ }
+ return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)));
}
#define MAKE_TO_LOCAL(Name, From, To) \
Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
- ASSERT(!obj->IsTheHole()); \
+ ASSERT(obj.is_null() || !obj->IsTheHole()); \
return Local<To>(reinterpret_cast<To*>(obj.location())); \
}
CHECK(Heap::new_space()->Contains(addr));
CHECK(!Heap::lo_space()->Contains(addr));
}
+
+
+TEST(EmptyHandleEscapeFrom) {
+ InitializeVM();
+
+ v8::HandleScope scope;
+ Handle<JSObject> runaway;
+
+ {
+ v8::HandleScope nested;
+ Handle<JSObject> empty;
+ runaway = empty.EscapeFrom(&nested);
+ }
+
+ CHECK(runaway.is_null());
+}