Index: test/cctest/test-api.cc |
=================================================================== |
--- test/cctest/test-api.cc (revision 2285) |
+++ test/cctest/test-api.cc (working copy) |
@@ -6040,6 +6040,7 @@ |
CHECK(value->BooleanValue()); |
} |
+ |
static bool NamedGetAccessBlocker(Local<v8::Object> obj, |
Local<Value> name, |
v8::AccessType type, |
@@ -6093,6 +6094,7 @@ |
CHECK(value_2->IsUndefined()); |
} |
+ |
// This tests that access check information remains on the global |
// object template when creating contexts. |
THREADED_TEST(AccessControlRepeatedContextCreation) { |
@@ -6111,6 +6113,71 @@ |
} |
+THREADED_TEST(TurnOnAccessCheck) { |
+ v8::HandleScope handle_scope; |
+ |
+ // Create an environment with access check to the global object disabled by |
+ // default. |
+ v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); |
+ global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker, |
+ IndexedGetAccessBlocker, |
+ v8::Handle<v8::Value>(), |
+ false); |
+ v8::Persistent<Context> context = Context::New(NULL, global_template); |
+ Context::Scope context_scope(context); |
+ |
+ // Set up a property and a number of functions. |
+ context->Global()->Set(v8_str("a"), v8_num(1)); |
+ CompileRun("function f1() {return a;}" |
+ "function f2() {return a;}" |
+ "function g1() {return h();}" |
+ "function g2() {return h();}" |
+ "function h() {return 1;}"); |
+ Local<Function> f1 = |
+ Local<Function>::Cast(context->Global()->Get(v8_str("f1"))); |
+ Local<Function> f2 = |
+ Local<Function>::Cast(context->Global()->Get(v8_str("f2"))); |
+ Local<Function> g1 = |
+ Local<Function>::Cast(context->Global()->Get(v8_str("g1"))); |
+ Local<Function> g2 = |
+ Local<Function>::Cast(context->Global()->Get(v8_str("g2"))); |
+ Local<Function> h = |
+ Local<Function>::Cast(context->Global()->Get(v8_str("h"))); |
+ |
+ // Get the global object. |
+ v8::Handle<v8::Object> global = context->Global(); |
+ |
+ // Call f1 one time and f2 a number of times. This will ensure that f1 still |
+ // uses the runtime system to retreive property a whereas f2 uses global load |
+ // inline cache is used. |
Mads Ager (chromium)
2009/06/30 10:07:34
remove 'is used'
|
+ CHECK(!f1->Call(global, 0, NULL)->IsUndefined()); |
Mads Ager (chromium)
2009/06/30 10:07:34
Maybe check that it is actually '1' in these cases
|
+ for (int i = 0; i < 4; i++) { |
+ CHECK(!f2->Call(global, 0, NULL)->IsUndefined()); |
+ } |
+ |
+ // Same for g1 and g2. |
+ CHECK(!g1->Call(global, 0, NULL)->IsUndefined()); |
+ for (int i = 0; i < 4; i++) { |
+ CHECK(!g2->Call(global, 0, NULL)->IsUndefined()); |
+ } |
+ |
+ // Detach the global and turn on access check. |
+ context->DetachGlobal(); |
+ context->Global()->TurnOnAccessCheck(); |
+ |
+ // Failing access check to property get results in undefined. |
+ CHECK(f1->Call(global, 0, NULL)->IsUndefined()); |
+ CHECK(f2->Call(global, 0, NULL)->IsUndefined()); |
+ |
+ // Failing access check to function call results in exception. |
+ CHECK(g1->Call(global, 0, NULL).IsEmpty()); |
+ CHECK(g2->Call(global, 0, NULL).IsEmpty()); |
+ |
+ // No failing access check when just returning a constant. |
+ CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1))); |
+} |
+ |
+ |
// This test verifies that pre-compilation (aka preparsing) can be called |
// without initializing the whole VM. Thus we cannot run this test in a |
// multi-threaded setup. |