Expose the calling context through the API.
In C++ callbacks, we can now get the context of the javascript code that called the callback. Review URL: http://codereview.chromium.org/113622 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2006 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
897ecefe1e
commit
10b8928e0e
@ -2250,6 +2250,13 @@ class V8EXPORT Context {
|
||||
/** Returns the context that is on the top of the stack. */
|
||||
static Local<Context> GetCurrent();
|
||||
|
||||
/**
|
||||
* Returns the context of the calling JavaScript code. That is the
|
||||
* context of the top-most JavaScript frame. If there are no
|
||||
* JavaScript frames an empty handle is returned.
|
||||
*/
|
||||
static Local<Context> GetCalling();
|
||||
|
||||
/**
|
||||
* Sets the security token for the context. To access an object in
|
||||
* another context, the security tokens must match.
|
||||
|
@ -2612,6 +2612,13 @@ v8::Local<v8::Context> Context::GetCurrent() {
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Context> Context::GetCalling() {
|
||||
if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
|
||||
i::Handle<i::Context> context(i::Top::GetCallingGlobalContext());
|
||||
return Utils::ToLocal(context);
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Object> Context::Global() {
|
||||
if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
|
||||
i::Object** ctx = reinterpret_cast<i::Object**>(this);
|
||||
|
@ -881,6 +881,15 @@ Handle<Context> Top::global_context() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Context> Top::GetCallingGlobalContext() {
|
||||
JavaScriptFrameIterator it;
|
||||
if (it.done()) return Handle<Context>::null();
|
||||
JavaScriptFrame* frame = it.frame();
|
||||
Context* context = Context::cast(frame->context());
|
||||
return Handle<Context>(context->global_context());
|
||||
}
|
||||
|
||||
|
||||
Object* Top::LookupSpecialFunction(JSObject* receiver,
|
||||
JSObject* prototype,
|
||||
JSFunction* function) {
|
||||
|
@ -255,8 +255,13 @@ class Top {
|
||||
return context()->global_proxy();
|
||||
}
|
||||
|
||||
// Returns the current global context.
|
||||
static Handle<Context> global_context();
|
||||
|
||||
// Returns the global context of the calling JavaScript code. That
|
||||
// is, the global context of the top-most JavaScript frame.
|
||||
static Handle<Context> GetCallingGlobalContext();
|
||||
|
||||
static Handle<JSBuiltinsObject> builtins() {
|
||||
return Handle<JSBuiltinsObject>(thread_local_.context_->builtins());
|
||||
}
|
||||
|
@ -6608,3 +6608,67 @@ TEST(ForceSetWithInterceptor) {
|
||||
CHECK_EQ(1, force_set_set_count);
|
||||
CHECK_EQ(6, force_set_get_count);
|
||||
}
|
||||
|
||||
|
||||
v8::Persistent<Context> calling_context0;
|
||||
v8::Persistent<Context> calling_context1;
|
||||
v8::Persistent<Context> calling_context2;
|
||||
|
||||
|
||||
// Check that the call to the callback is initiated in
|
||||
// calling_context2, the directly calling context is calling_context1
|
||||
// and the callback itself is in calling_context0.
|
||||
static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(Context::GetCurrent() == calling_context0);
|
||||
CHECK(Context::GetCalling() == calling_context1);
|
||||
CHECK(Context::GetEntered() == calling_context2);
|
||||
return v8::Integer::New(42);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(GetCallingContext) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
calling_context0 = Context::New();
|
||||
calling_context1 = Context::New();
|
||||
calling_context2 = Context::New();
|
||||
|
||||
// Allow cross-domain access.
|
||||
Local<String> token = v8_str("<security token>");
|
||||
calling_context0->SetSecurityToken(token);
|
||||
calling_context1->SetSecurityToken(token);
|
||||
calling_context2->SetSecurityToken(token);
|
||||
|
||||
// Create an object with a C++ callback in context0.
|
||||
calling_context0->Enter();
|
||||
Local<v8::FunctionTemplate> callback_templ =
|
||||
v8::FunctionTemplate::New(GetCallingContextCallback);
|
||||
calling_context0->Global()->Set(v8_str("callback"),
|
||||
callback_templ->GetFunction());
|
||||
calling_context0->Exit();
|
||||
|
||||
// Expose context0 in context1 and setup a function that calls the
|
||||
// callback function.
|
||||
calling_context1->Enter();
|
||||
calling_context1->Global()->Set(v8_str("context0"),
|
||||
calling_context0->Global());
|
||||
CompileRun("function f() { context0.callback() }");
|
||||
calling_context1->Exit();
|
||||
|
||||
// Expose context1 in context2 and call the callback function in
|
||||
// context0 indirectly through f in context1.
|
||||
calling_context2->Enter();
|
||||
calling_context2->Global()->Set(v8_str("context1"),
|
||||
calling_context1->Global());
|
||||
CompileRun("context1.f()");
|
||||
calling_context2->Exit();
|
||||
|
||||
// Dispose the contexts to allow them to be garbage collected.
|
||||
calling_context0.Dispose();
|
||||
calling_context1.Dispose();
|
||||
calling_context2.Dispose();
|
||||
calling_context0.Clear();
|
||||
calling_context1.Clear();
|
||||
calling_context2.Clear();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user