Index: test/cctest/test-access-checks.cc |
diff --git a/test/cctest/test-access-checks.cc b/test/cctest/test-access-checks.cc |
index 34b64c400a8550ae64279ccd3f2657e5802db688..5664d7555426e65bafbd383452c8b3ffbe9a150f 100644 |
--- a/test/cctest/test-access-checks.cc |
+++ b/test/cctest/test-access-checks.cc |
@@ -10,8 +10,11 @@ namespace { |
int32_t g_cross_context_int = 0; |
+bool g_expect_interceptor_call = false; |
+ |
void NamedGetter(v8::Local<v8::Name> property, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (property->Equals(context, v8_str("cross_context_int")).FromJust()) |
@@ -20,6 +23,7 @@ void NamedGetter(v8::Local<v8::Name> property, |
void NamedSetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (!property->Equals(context, v8_str("cross_context_int")).FromJust()) |
@@ -32,6 +36,7 @@ void NamedSetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, |
void NamedQuery(v8::Local<v8::Name> property, |
const v8::PropertyCallbackInfo<v8::Integer>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (!property->Equals(context, v8_str("cross_context_int")).FromJust()) |
@@ -41,6 +46,7 @@ void NamedQuery(v8::Local<v8::Name> property, |
void NamedDeleter(v8::Local<v8::Name> property, |
const v8::PropertyCallbackInfo<v8::Boolean>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (!property->Equals(context, v8_str("cross_context_int")).FromJust()) |
@@ -49,6 +55,7 @@ void NamedDeleter(v8::Local<v8::Name> property, |
} |
void NamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
v8::Local<v8::Array> names = v8::Array::New(isolate, 1); |
@@ -58,11 +65,13 @@ void NamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { |
void IndexedGetter(uint32_t index, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CHECK(g_expect_interceptor_call); |
if (index == 7) info.GetReturnValue().Set(g_cross_context_int); |
} |
void IndexedSetter(uint32_t index, v8::Local<v8::Value> value, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (index != 7) return; |
@@ -74,15 +83,18 @@ void IndexedSetter(uint32_t index, v8::Local<v8::Value> value, |
void IndexedQuery(uint32_t index, |
const v8::PropertyCallbackInfo<v8::Integer>& info) { |
+ CHECK(g_expect_interceptor_call); |
if (index == 7) info.GetReturnValue().Set(v8::DontDelete); |
} |
void IndexedDeleter(uint32_t index, |
const v8::PropertyCallbackInfo<v8::Boolean>& info) { |
+ CHECK(g_expect_interceptor_call); |
if (index == 7) info.GetReturnValue().Set(false); |
} |
void IndexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { |
+ CHECK(g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
v8::Local<v8::Array> names = v8::Array::New(isolate, 1); |
@@ -98,12 +110,14 @@ bool AccessCheck(v8::Local<v8::Context> accessing_context, |
void GetCrossContextInt(v8::Local<v8::String> property, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CHECK(!g_expect_interceptor_call); |
info.GetReturnValue().Set(g_cross_context_int); |
} |
void SetCrossContextInt(v8::Local<v8::String> property, |
v8::Local<v8::Value> value, |
const v8::PropertyCallbackInfo<void>& info) { |
+ CHECK(!g_expect_interceptor_call); |
v8::Isolate* isolate = info.GetIsolate(); |
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
if (value->IsInt32()) { |
@@ -141,6 +155,7 @@ TEST(AccessCheckWithInterceptor) { |
context0->Enter(); |
// Running script in this context should work. |
+ g_expect_interceptor_call = false; |
CompileRunChecked(isolate, "this.foo = 42; this[23] = true;"); |
ExpectInt32("this.all_can_read", 42); |
CompileRunChecked(isolate, "this.cross_context_int = 23"); |
@@ -156,6 +171,62 @@ TEST(AccessCheckWithInterceptor) { |
->Set(context1, v8_str("other"), context0->Global()) |
.FromJust(); |
v8::Context::Scope context_scope(context1); |
+ g_expect_interceptor_call = true; |
+ |
+ { |
+ v8::TryCatch try_catch(isolate); |
+ CHECK(CompileRun(context1, "this.other.foo").IsEmpty()); |
+ } |
+ { |
+ v8::TryCatch try_catch(isolate); |
+ CHECK(CompileRun(context1, "this.other[23]").IsEmpty()); |
+ } |
+ |
+ // AllCanRead properties are also inaccessible. |
+ { |
+ v8::TryCatch try_catch(isolate); |
+ CHECK(CompileRun(context1, "this.other.all_can_read").IsEmpty()); |
+ } |
+ |
+ // Intercepted properties are accessible, however. |
+ ExpectInt32("this.other.cross_context_int", 23); |
+ CompileRunChecked(isolate, "this.other.cross_context_int = 42"); |
+ ExpectInt32("this.other[7]", 42); |
+ ExpectString("JSON.stringify(Object.getOwnPropertyNames(this.other))", |
+ "[\"7\",\"cross_context_int\"]"); |
+ } |
+} |
+ |
+TEST(NewDetachedGlobal) { |
+ v8::Isolate* isolate = CcTest::isolate(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::ObjectTemplate> global_template = |
+ v8::ObjectTemplate::New(isolate); |
+ global_template->SetAccessCheckCallbackAndHandler( |
+ AccessCheck, |
+ v8::NamedPropertyHandlerConfiguration( |
+ NamedGetter, NamedSetter, NamedQuery, NamedDeleter, NamedEnumerator), |
+ v8::IndexedPropertyHandlerConfiguration(IndexedGetter, IndexedSetter, |
+ IndexedQuery, IndexedDeleter, |
+ IndexedEnumerator)); |
+ global_template->SetNativeDataProperty( |
+ v8_str("cross_context_int"), GetCrossContextInt, SetCrossContextInt); |
+ global_template->SetNativeDataProperty( |
+ v8_str("all_can_read"), Return42, nullptr, v8::Local<v8::Value>(), |
+ v8::None, v8::Local<v8::AccessorSignature>(), v8::ALL_CAN_READ); |
+ g_cross_context_int = 23; |
+ |
+ v8::Local<v8::Object> global0 = |
+ v8::Context::NewDetachedGlobal(isolate, global_template); |
+ |
+ // Create a real context. |
+ { |
+ v8::HandleScope other_scope(isolate); |
+ v8::Local<v8::Context> context1 = |
+ v8::Context::New(isolate, nullptr, global_template); |
+ context1->Global()->Set(context1, v8_str("other"), global0).FromJust(); |
+ v8::Context::Scope context_scope(context1); |
+ g_expect_interceptor_call = true; |
{ |
v8::TryCatch try_catch(isolate); |
@@ -179,4 +250,23 @@ TEST(AccessCheckWithInterceptor) { |
ExpectString("JSON.stringify(Object.getOwnPropertyNames(this.other))", |
"[\"7\",\"cross_context_int\"]"); |
} |
+ |
+ // Create a context using the detached global. |
+ { |
+ v8::HandleScope other_scope(isolate); |
+ v8::Local<v8::Context> context2 = |
+ v8::Context::New(isolate, nullptr, global_template, global0); |
+ v8::Context::Scope context_scope(context2); |
+ g_expect_interceptor_call = true; |
+ g_cross_context_int = 0; |
+ context2->Enter(); |
+ |
+ // Running script in this context should work. |
+ g_expect_interceptor_call = false; |
+ CompileRunChecked(isolate, "this.foo = 42; this[23] = true;"); |
+ ExpectInt32("this.all_can_read", 42); |
+ CompileRunChecked(isolate, "this.cross_context_int = 23"); |
+ CHECK_EQ(g_cross_context_int, 23); |
+ ExpectInt32("this.cross_context_int", 23); |
+ } |
} |