| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 4246)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -4465,7 +4465,7 @@
|
| // Enter env2
|
| 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();
|
| global2->Set(v8_str("prop"), v8::Integer::New(1));
|
| CompileRun("function getProp() {return prop;}");
|
| @@ -4473,7 +4473,7 @@
|
| env1->Global()->Set(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->DetachGlobal();
|
| // env2 has a new global object.
|
| @@ -4513,6 +4513,85 @@
|
| }
|
|
|
|
|
| +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,
|
| Local<Value> name,
|
| v8::AccessType type,
|
|
|