Context-independent script compilation.
authorchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Aug 2009 11:41:00 +0000 (11:41 +0000)
committerchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Aug 2009 11:41:00 +0000 (11:41 +0000)
Added Script::New calls that create a new context-independent
(boilerplate) script which can be executed in any context, unlike the
current scripts which bind the context in which they're compiled.

Review URL: http://codereview.chromium.org/172043

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

include/v8.h
src/api.cc
test/cctest/test-api.cc

index d8de00c..77223a0 100644 (file)
@@ -513,10 +513,36 @@ class V8EXPORT ScriptOrigin {
 class V8EXPORT Script {
  public:
 
+   /**
+    * Compiles the specified script. The ScriptOrigin* and ScriptData*
+    * parameters are owned by the caller of Script::Compile. No
+    * references to these objects are kept after compilation finishes.
+    *
+    * The script object returned is context independent; when run it
+    * will use the currently entered context.
+    */
+   static Local<Script> New(Handle<String> source,
+                            ScriptOrigin* origin = NULL,
+                            ScriptData* pre_data = NULL);
+
+   /**
+    * Compiles the specified script using the specified file name
+    * object (typically a string) as the script's origin.
+    *
+    * The script object returned is context independent; when run it
+    * will use the currently entered context.
+    */
+   static Local<Script> New(Handle<String> source,
+                            Handle<Value> file_name);
+
   /**
    * Compiles the specified script. The ScriptOrigin* and ScriptData*
    * parameters are owned by the caller of Script::Compile. No
    * references to these objects are kept after compilation finishes.
+   *
+   * The script object returned is bound to the context that was active
+   * when this function was called.  When run it will always use this
+   * context.
    */
   static Local<Script> Compile(Handle<String> source,
                                ScriptOrigin* origin = NULL,
@@ -525,12 +551,20 @@ class V8EXPORT Script {
   /**
    * Compiles the specified script using the specified file name
    * object (typically a string) as the script's origin.
+   *
+   * The script object returned is bound to the context that was active
+   * when this function was called.  When run it will always use this
+   * context.
    */
   static Local<Script> Compile(Handle<String> source,
                                Handle<Value> file_name);
 
   /**
-   * Runs the script returning the resulting value.
+   * Runs the script returning the resulting value.  If the script is
+   * context independent (created using ::New) it will be run in the
+   * currently entered context.  If it is context specific (created
+   * using ::Compile) it will be run in the context in which it was
+   * compiled.
    */
   Local<Value> Run();
 
index a267381..2f7de08 100644 (file)
@@ -1058,11 +1058,11 @@ ScriptData* ScriptData::New(unsigned* data, int length) {
 // --- S c r i p t ---
 
 
-Local<Script> Script::Compile(v8::Handle<String> source,
-                              v8::ScriptOrigin* origin,
-                              v8::ScriptData* script_data) {
-  ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
-  LOG_API("Script::Compile");
+Local<Script> Script::New(v8::Handle<String> source,
+                          v8::ScriptOrigin* origin,
+                          v8::ScriptData* script_data) {
+  ON_BAILOUT("v8::Script::New()", return Local<Script>());
+  LOG_API("Script::New");
   ENTER_V8;
   i::Handle<i::String> str = Utils::OpenHandle(*source);
   i::Handle<i::Object> name_obj;
@@ -1096,6 +1096,27 @@ Local<Script> Script::Compile(v8::Handle<String> source,
                                                               pre_data);
   has_pending_exception = boilerplate.is_null();
   EXCEPTION_BAILOUT_CHECK(Local<Script>());
+  return Local<Script>(ToApi<Script>(boilerplate));
+}
+
+
+Local<Script> Script::New(v8::Handle<String> source,
+                          v8::Handle<Value> file_name) {
+  ScriptOrigin origin(file_name);
+  return New(source, &origin);
+}
+
+
+Local<Script> Script::Compile(v8::Handle<String> source,
+                              v8::ScriptOrigin* origin,
+                              v8::ScriptData* script_data) {
+  ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
+  LOG_API("Script::Compile");
+  ENTER_V8;
+  Local<Script> generic = New(source, origin, script_data);
+  if (generic.IsEmpty())
+    return generic;
+  i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
   i::Handle<i::JSFunction> result =
       i::Factory::NewFunctionFromBoilerplate(boilerplate,
                                              i::Top::global_context());
@@ -1118,6 +1139,10 @@ Local<Value> Script::Run() {
   {
     HandleScope scope;
     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+    if (fun->IsBoilerplate()) {
+      fun = i::Factory::NewFunctionFromBoilerplate(fun,
+                                                   i::Top::global_context());
+    }
     EXCEPTION_PREAMBLE();
     i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
     i::Handle<i::Object> result =
index 35ac031..e0c9f3e 100644 (file)
@@ -7738,3 +7738,18 @@ THREADED_TEST(PixelArray) {
 
   free(pixel_data);
 }
+
+THREADED_TEST(ScriptContextDependence) {
+  v8::HandleScope scope;
+  LocalContext c1;
+  const char *source = "foo";
+  v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
+  v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
+  c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->Run()->Int32Value(), 100);
+  LocalContext c2;
+  c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
+  CHECK_EQ(dep->Run()->Int32Value(), 100);
+  CHECK_EQ(indep->Run()->Int32Value(), 101);
+}