Add EscapableHandleScope to api to fix problems with HandleScope::Close
R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/24245005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16965 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a57300fb9e
commit
47e32d0339
40
include/v8.h
40
include/v8.h
@ -135,6 +135,7 @@ class DeclaredAccessorDescriptor;
|
|||||||
class ObjectOperationDescriptor;
|
class ObjectOperationDescriptor;
|
||||||
class RawOperationDescriptor;
|
class RawOperationDescriptor;
|
||||||
class CallHandlerHelper;
|
class CallHandlerHelper;
|
||||||
|
class EscapableHandleScope;
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
class Arguments;
|
class Arguments;
|
||||||
@ -401,6 +402,7 @@ template <class T> class Local : public Handle<T> {
|
|||||||
friend class Context;
|
friend class Context;
|
||||||
template<class F> friend class internal::CustomArguments;
|
template<class F> friend class internal::CustomArguments;
|
||||||
friend class HandleScope;
|
friend class HandleScope;
|
||||||
|
friend class EscapableHandleScope;
|
||||||
|
|
||||||
V8_INLINE static Local<T> New(Isolate* isolate, T* that);
|
V8_INLINE static Local<T> New(Isolate* isolate, T* that);
|
||||||
};
|
};
|
||||||
@ -773,10 +775,7 @@ class V8_EXPORT HandleScope {
|
|||||||
|
|
||||||
~HandleScope();
|
~HandleScope();
|
||||||
|
|
||||||
/**
|
// TODO(dcarney): deprecated - use EscapableHandleScope::Escape.
|
||||||
* Closes the handle scope and returns the value as a handle in the
|
|
||||||
* previous scope, which is the new current scope after the call.
|
|
||||||
*/
|
|
||||||
template <class T> Local<T> Close(Handle<T> value);
|
template <class T> Local<T> Close(Handle<T> value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -794,6 +793,9 @@ class V8_EXPORT HandleScope {
|
|||||||
static internal::Object** CreateHandle(internal::HeapObject* value);
|
static internal::Object** CreateHandle(internal::HeapObject* value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
V8_INLINE HandleScope() {}
|
||||||
|
void Initialize(Isolate* isolate);
|
||||||
|
|
||||||
// Make it hard to create heap-allocated or illegal handle scopes by
|
// Make it hard to create heap-allocated or illegal handle scopes by
|
||||||
// disallowing certain operations.
|
// disallowing certain operations.
|
||||||
HandleScope(const HandleScope&);
|
HandleScope(const HandleScope&);
|
||||||
@ -814,19 +816,47 @@ class V8_EXPORT HandleScope {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Initialize(Isolate* isolate);
|
|
||||||
void Leave();
|
void Leave();
|
||||||
|
|
||||||
internal::Isolate* isolate_;
|
internal::Isolate* isolate_;
|
||||||
internal::Object** prev_next_;
|
internal::Object** prev_next_;
|
||||||
internal::Object** prev_limit_;
|
internal::Object** prev_limit_;
|
||||||
|
|
||||||
|
// TODO(dcarney): remove this field
|
||||||
// Allow for the active closing of HandleScopes which allows to pass a handle
|
// Allow for the active closing of HandleScopes which allows to pass a handle
|
||||||
// from the HandleScope being closed to the next top most HandleScope.
|
// from the HandleScope being closed to the next top most HandleScope.
|
||||||
bool is_closed_;
|
bool is_closed_;
|
||||||
internal::Object** RawClose(internal::Object** value);
|
internal::Object** RawClose(internal::Object** value);
|
||||||
|
|
||||||
friend class ImplementationUtilities;
|
friend class ImplementationUtilities;
|
||||||
|
friend class EscapableHandleScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HandleScope which first allocates a handle in the current scope
|
||||||
|
* which will be later filled with the escape value.
|
||||||
|
*/
|
||||||
|
class V8_EXPORT EscapableHandleScope : public HandleScope {
|
||||||
|
public:
|
||||||
|
EscapableHandleScope(Isolate* isolate);
|
||||||
|
V8_INLINE ~EscapableHandleScope() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the value into the previous scope and returns a handle to it.
|
||||||
|
* Cannot be called twice.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
V8_INLINE Local<T> Escape(Local<T> value) {
|
||||||
|
internal::Object** slot =
|
||||||
|
Escape(reinterpret_cast<internal::Object**>(*value));
|
||||||
|
return Local<T>(reinterpret_cast<T*>(slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
internal::Object** Escape(internal::Object** escape_value);
|
||||||
|
|
||||||
|
internal::Object** escape_slot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
20
src/api.cc
20
src/api.cc
@ -701,6 +701,26 @@ i::Object** HandleScope::CreateHandle(i::HeapObject* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
|
||||||
|
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||||
|
escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
|
||||||
|
Initialize(v8_isolate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
|
||||||
|
ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
|
||||||
|
"EscapeableHandleScope::Escape",
|
||||||
|
"Escape value set twice");
|
||||||
|
if (escape_value == NULL) {
|
||||||
|
*escape_slot_ = isolate_->heap()->undefined_value();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*escape_slot_ = *escape_value;
|
||||||
|
return escape_slot_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Context::Enter() {
|
void Context::Enter() {
|
||||||
i::Handle<i::Context> env = Utils::OpenHandle(this);
|
i::Handle<i::Context> env = Utils::OpenHandle(this);
|
||||||
i::Isolate* isolate = env->GetIsolate();
|
i::Isolate* isolate = env->GetIsolate();
|
||||||
|
@ -20593,3 +20593,24 @@ THREADED_TEST(FunctionNew) {
|
|||||||
CHECK_EQ(v8::Integer::New(17, isolate), result2);
|
CHECK_EQ(v8::Integer::New(17, isolate), result2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(EscapeableHandleScope) {
|
||||||
|
HandleScope outer_scope(CcTest::isolate());
|
||||||
|
LocalContext context;
|
||||||
|
const int runs = 10;
|
||||||
|
Local<String> values[runs];
|
||||||
|
for (int i = 0; i < runs; i++) {
|
||||||
|
v8::EscapableHandleScope inner_scope(CcTest::isolate());
|
||||||
|
Local<String> value;
|
||||||
|
if (i != 0) value = v8_str("escape value");
|
||||||
|
values[i] = inner_scope.Escape(value);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < runs; i++) {
|
||||||
|
Local<String> expected;
|
||||||
|
if (i != 0) {
|
||||||
|
CHECK_EQ(v8_str("escape value"), values[i]);
|
||||||
|
} else {
|
||||||
|
CHECK(values[i].IsEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user