Make sure that the API does not change templates pass in from the
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 11 Dec 2008 11:09:51 +0000 (11:09 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 11 Dec 2008 11:09:51 +0000 (11:09 +0000)
user.  The API should never change templates behind the back of the
user.
Review URL: http://codereview.chromium.org/13741

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@963 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/api.cc
test/cctest/test-api.cc

index d76edf3e7c029d11190f6b0e658061b48d04b5f3..cc878dbee6e0aec7cde51b6675926a9c579bf1ab 100644 (file)
@@ -2227,39 +2227,52 @@ Persistent<Context> v8::Context::New(
   LOG_API("Context::New");
   ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
 
-  // Make sure that the global_template has a constructor.
-  if (!global_template.IsEmpty()) {
-    i::Handle<i::FunctionTemplateInfo> constructor =
-        EnsureConstructor(Utils::OpenHandle(*global_template));
+  v8::Handle<ObjectTemplate> proxy_template = global_template;
+  i::Handle<i::FunctionTemplateInfo> proxy_constructor;
+  i::Handle<i::FunctionTemplateInfo> global_constructor;
 
-    // Create a fresh template for global proxy object.
-    Local<ObjectTemplate> proxy_template = ObjectTemplate::New();
+  if (!global_template.IsEmpty()) {
+    // Make sure that the global_template has a constructor.
+    global_constructor = EnsureConstructor(Utils::OpenHandle(*global_template));
 
-    i::Handle<i::FunctionTemplateInfo> proxy_constructor =
-      EnsureConstructor(Utils::OpenHandle(*proxy_template));
+    // Create a fresh template for the global proxy object.
+    proxy_template = ObjectTemplate::New();
+    proxy_constructor = EnsureConstructor(Utils::OpenHandle(*proxy_template));
 
-    // Set the global template to be the prototype template
-    // of global proxy template.
+    // Set the global template to be the prototype template of global
+    // proxy template.
     proxy_constructor->set_prototype_template(
         *Utils::OpenHandle(*global_template));
 
-    // Migrate security handlers from global_template to proxy_template.
-    if (!constructor->access_check_info()->IsUndefined()) {
-       proxy_constructor->set_access_check_info(
-           constructor->access_check_info());
-       proxy_constructor->set_needs_access_check(true);
-
-       // Remove access check info from global_template.
-       constructor->set_needs_access_check(false);
-       constructor->set_access_check_info(i::Heap::undefined_value());
+    // Migrate security handlers from global_template to
+    // proxy_template.  Temporarily removing access check information
+    // from the global template.
+    if (!global_constructor->access_check_info()->IsUndefined()) {
+      proxy_constructor->set_access_check_info(
+          global_constructor->access_check_info());
+      proxy_constructor->set_needs_access_check(
+          global_constructor->needs_access_check());
+      global_constructor->set_needs_access_check(false);
+      global_constructor->set_access_check_info(i::Heap::undefined_value());
     }
-
-    global_template = proxy_template;
   }
 
+  // Create the environment.
   i::Handle<i::Context> env = i::Bootstrapper::CreateEnvironment(
       Utils::OpenHandle(*global_object),
-      global_template, extensions);
+      proxy_template,
+      extensions);
+
+  // Restore the access check info on the global template.
+  if (!global_template.IsEmpty()) {
+    ASSERT(!global_constructor.is_null());
+    ASSERT(!proxy_constructor.is_null());
+    global_constructor->set_access_check_info(
+        proxy_constructor->access_check_info());
+    global_constructor->set_needs_access_check(
+        proxy_constructor->needs_access_check());
+  }
+
   if (!ApiCheck(!env.is_null(),
                 "v8::Context::New()",
                 "Could not initialize environment"))
index 5c355de82979ad55bd6b9021384bb3427a01c6be..0f6ceab5bbbaed3f42233e66303e3c1439d6ff5f 100644 (file)
@@ -5447,6 +5447,24 @@ THREADED_TEST(DisableAccessChecksWhileConfiguring) {
 }
 
 
+// This tests that access check information remains on the global
+// object template when creating contexts.
+THREADED_TEST(AccessControlRepeatedContextCreation) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                           IndexedSetAccessBlocker);
+  i::Handle<i::ObjectTemplateInfo> internal_template =
+      v8::Utils::OpenHandle(*global_template);
+  CHECK(!internal_template->constructor()->IsUndefined());
+  i::Handle<i::FunctionTemplateInfo> constructor(
+      i::FunctionTemplateInfo::cast(internal_template->constructor()));
+  CHECK(!constructor->access_check_info()->IsUndefined());
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  CHECK(!constructor->access_check_info()->IsUndefined());
+}
+
+
 static String::ExternalStringResource* SymbolCallback(const char* chars,
                                                       size_t length) {
   uint16_t* buffer = i::NewArray<uint16_t>(length + 1);