Implement support for reattaching a global object to a context. This
can be used to use the same global object for different contexts at different points in time. Review URL: http://codereview.chromium.org/1207003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4253 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
82ae9cbe96
commit
652335b995
12
include/v8.h
12
include/v8.h
@ -2735,6 +2735,18 @@ class V8EXPORT Context {
|
|||||||
*/
|
*/
|
||||||
void DetachGlobal();
|
void DetachGlobal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reattaches a global object to a context. This can be used to
|
||||||
|
* restore the connection between a global object and a context
|
||||||
|
* after DetachGlobal has been called.
|
||||||
|
*
|
||||||
|
* \param global_object The global object to reattach to the
|
||||||
|
* context. For this to work, the global object must be the global
|
||||||
|
* object that was associated with this context before a call to
|
||||||
|
* DetachGlobal.
|
||||||
|
*/
|
||||||
|
void ReattachGlobal(Handle<Object> global_object);
|
||||||
|
|
||||||
/** Creates a new context. */
|
/** Creates a new context. */
|
||||||
static Persistent<Context> New(
|
static Persistent<Context> New(
|
||||||
ExtensionConfiguration* extensions = NULL,
|
ExtensionConfiguration* extensions = NULL,
|
||||||
|
10
src/api.cc
10
src/api.cc
@ -3078,6 +3078,16 @@ void Context::DetachGlobal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Context::ReattachGlobal(Handle<Object> global_object) {
|
||||||
|
if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
|
||||||
|
ENTER_V8;
|
||||||
|
i::Object** ctx = reinterpret_cast<i::Object**>(this);
|
||||||
|
i::Handle<i::Context> context =
|
||||||
|
i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
|
||||||
|
i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Local<v8::Object> ObjectTemplate::NewInstance() {
|
Local<v8::Object> ObjectTemplate::NewInstance() {
|
||||||
ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
|
ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
|
||||||
LOG_API("ObjectTemplate::NewInstance");
|
LOG_API("ObjectTemplate::NewInstance");
|
||||||
|
@ -309,6 +309,17 @@ void Bootstrapper::DetachGlobal(Handle<Context> env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Bootstrapper::ReattachGlobal(Handle<Context> env,
|
||||||
|
Handle<Object> global_object) {
|
||||||
|
ASSERT(global_object->IsJSGlobalProxy());
|
||||||
|
Handle<JSGlobalProxy> global = Handle<JSGlobalProxy>::cast(global_object);
|
||||||
|
env->global()->set_global_receiver(*global);
|
||||||
|
env->set_global_proxy(*global);
|
||||||
|
SetObjectPrototype(global, Handle<JSObject>(env->global()));
|
||||||
|
global->set_context(*env);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||||
const char* name,
|
const char* name,
|
||||||
InstanceType type,
|
InstanceType type,
|
||||||
|
@ -68,6 +68,9 @@ class Bootstrapper : public AllStatic {
|
|||||||
// Detach the environment from its outer global object.
|
// Detach the environment from its outer global object.
|
||||||
static void DetachGlobal(Handle<Context> env);
|
static void DetachGlobal(Handle<Context> env);
|
||||||
|
|
||||||
|
// Reattach an outer global object to an environment.
|
||||||
|
static void ReattachGlobal(Handle<Context> env, Handle<Object> global_object);
|
||||||
|
|
||||||
// Traverses the pointers for memory management.
|
// Traverses the pointers for memory management.
|
||||||
static void Iterate(ObjectVisitor* v);
|
static void Iterate(ObjectVisitor* v);
|
||||||
|
|
||||||
|
@ -4465,7 +4465,7 @@ TEST(ContextDetachGlobal) {
|
|||||||
// Enter env2
|
// Enter env2
|
||||||
env2->Enter();
|
env2->Enter();
|
||||||
|
|
||||||
// Create a function in env1
|
// Create a function in env2 and add a reference to it in env1.
|
||||||
Local<v8::Object> global2 = env2->Global();
|
Local<v8::Object> global2 = env2->Global();
|
||||||
global2->Set(v8_str("prop"), v8::Integer::New(1));
|
global2->Set(v8_str("prop"), v8::Integer::New(1));
|
||||||
CompileRun("function getProp() {return prop;}");
|
CompileRun("function getProp() {return prop;}");
|
||||||
@ -4473,7 +4473,7 @@ TEST(ContextDetachGlobal) {
|
|||||||
env1->Global()->Set(v8_str("getProp"),
|
env1->Global()->Set(v8_str("getProp"),
|
||||||
global2->Get(v8_str("getProp")));
|
global2->Get(v8_str("getProp")));
|
||||||
|
|
||||||
// Detach env1's global, and reuse the global object of env1
|
// Detach env2's global, and reuse the global object of env2
|
||||||
env2->Exit();
|
env2->Exit();
|
||||||
env2->DetachGlobal();
|
env2->DetachGlobal();
|
||||||
// env2 has a new global object.
|
// env2 has a new global object.
|
||||||
@ -4513,6 +4513,85 @@ TEST(ContextDetachGlobal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(DetachAndReattachGlobal) {
|
||||||
|
v8::HandleScope scope;
|
||||||
|
LocalContext env1;
|
||||||
|
|
||||||
|
// Create second environment.
|
||||||
|
v8::Persistent<Context> env2 = Context::New();
|
||||||
|
|
||||||
|
Local<Value> foo = v8_str("foo");
|
||||||
|
|
||||||
|
// Set same security token for env1 and env2.
|
||||||
|
env1->SetSecurityToken(foo);
|
||||||
|
env2->SetSecurityToken(foo);
|
||||||
|
|
||||||
|
// Create a property on the global object in env2.
|
||||||
|
{
|
||||||
|
v8::Context::Scope scope(env2);
|
||||||
|
env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a reference to env2 global from env1 global.
|
||||||
|
env1->Global()->Set(v8_str("other"), env2->Global());
|
||||||
|
|
||||||
|
// Check that we have access to other.p in env2 from env1.
|
||||||
|
Local<Value> result = CompileRun("other.p");
|
||||||
|
CHECK(result->IsInt32());
|
||||||
|
CHECK_EQ(42, result->Int32Value());
|
||||||
|
|
||||||
|
// Hold on to global from env2 and detach global from env2.
|
||||||
|
Local<v8::Object> global2 = env2->Global();
|
||||||
|
env2->DetachGlobal();
|
||||||
|
|
||||||
|
// Check that the global has been detached. No other.p property can
|
||||||
|
// be found.
|
||||||
|
result = CompileRun("other.p");
|
||||||
|
CHECK(result->IsUndefined());
|
||||||
|
|
||||||
|
// Reuse global2 for env3.
|
||||||
|
v8::Persistent<Context> env3 =
|
||||||
|
Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
|
||||||
|
CHECK_EQ(global2, env3->Global());
|
||||||
|
|
||||||
|
// Start by using the same security token for env3 as for env1 and env2.
|
||||||
|
env3->SetSecurityToken(foo);
|
||||||
|
|
||||||
|
// Create a property on the global object in env3.
|
||||||
|
{
|
||||||
|
v8::Context::Scope scope(env3);
|
||||||
|
env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that other.p is now the property in env3 and that we have access.
|
||||||
|
result = CompileRun("other.p");
|
||||||
|
CHECK(result->IsInt32());
|
||||||
|
CHECK_EQ(24, result->Int32Value());
|
||||||
|
|
||||||
|
// Change security token for env3 to something different from env1 and env2.
|
||||||
|
env3->SetSecurityToken(v8_str("bar"));
|
||||||
|
|
||||||
|
// Check that we do not have access to other.p in env1. |other| is now
|
||||||
|
// the global object for env3 which has a different security token,
|
||||||
|
// so access should be blocked.
|
||||||
|
result = CompileRun("other.p");
|
||||||
|
CHECK(result->IsUndefined());
|
||||||
|
|
||||||
|
// Detach the global for env3 and reattach it to env2.
|
||||||
|
env3->DetachGlobal();
|
||||||
|
env2->ReattachGlobal(global2);
|
||||||
|
|
||||||
|
// Check that we have access to other.p again in env1. |other| is now
|
||||||
|
// the global object for env2 which has the same security token as env1.
|
||||||
|
result = CompileRun("other.p");
|
||||||
|
CHECK(result->IsInt32());
|
||||||
|
CHECK_EQ(42, result->Int32Value());
|
||||||
|
|
||||||
|
env2.Dispose();
|
||||||
|
env3.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool NamedAccessBlocker(Local<v8::Object> global,
|
static bool NamedAccessBlocker(Local<v8::Object> global,
|
||||||
Local<Value> name,
|
Local<Value> name,
|
||||||
v8::AccessType type,
|
v8::AccessType type,
|
||||||
|
Loading…
Reference in New Issue
Block a user