Enable passing of script data via script creation methods.
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Feb 2010 15:15:31 +0000 (15:15 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Feb 2010 15:15:31 +0000 (15:15 +0000)
Patch by Andrey Kosyakov <caseq@chromium.org>
Original issue http://codereview.chromium.org/606053

TBR=sgjesse@chromium.org

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

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

include/v8.h
src/api.cc
src/compiler.cc
src/compiler.h
src/number-info.h
test/cctest/test-debug.cc

index 943c77b..96dc469 100644 (file)
@@ -534,51 +534,76 @@ 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 (context-independent).
+   *
+   * \param source Script source code.
+   * \param origin Script origin, owned by caller, no references are kept 
+   *   when New() returns
+   * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
+   *   using pre_data speeds compilation if it's done multiple times.
+   *   Owned by caller, no references are kept when New() returns.
+   * \param script_data Arbitrary data associated with script. Using
+   *   this has same effect as calling SetData(), but allows data to be 
+   *   available to compile event handlers.
+   * \return Compiled script object (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,
+                           Handle<String> script_data = Handle<String>());
 
-   /**
-    * 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.
+  /**
+   * Compiles the specified script using the specified file name
+   * object (typically a string) as the script's origin.
+   *
+   * \param source Script source code.
+   * \patam file_name file name object (typically a string) to be used 
+   *   as the script's origin.
+   * \return Compiled script object (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 (bound to current context).
    *
-   * 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.
+   * \param source Script source code.
+   * \param origin Script origin, owned by caller, no references are kept 
+   *   when Compile() returns
+   * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
+   *   using pre_data speeds compilation if it's done multiple times.
+   *   Owned by caller, no references are kept when Compile() returns.
+   * \param script_data Arbitrary data associated with script. Using
+   *   this has same effect as calling SetData(), but makes data available
+   *   earlier (i.e. to compile event handlers).
+   * \return Compiled script object, 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,
-                               ScriptData* pre_data = NULL);
+                               ScriptData* pre_data = NULL,
+                               Handle<String> script_data = Handle<String>());
 
   /**
    * 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.
+   * \param source Script source code.
+   * \param file_name File name to use as script's origin
+   * \param script_data Arbitrary data associated with script. Using
+   *   this has same effect as calling SetData(), but makes data available
+   *   earlier (i.e. to compile event handlers).
+   * \return Compiled script object, 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);
+                               Handle<Value> file_name,
+                               Handle<String> script_data = Handle<String>());
 
   /**
    * Runs the script returning the resulting value.  If the script is
index 3c0d594..f2f9956 100644 (file)
@@ -1106,7 +1106,8 @@ ScriptData* ScriptData::New(unsigned* data, int length) {
 
 Local<Script> Script::New(v8::Handle<String> source,
                           v8::ScriptOrigin* origin,
-                          v8::ScriptData* script_data) {
+                          v8::ScriptData* pre_data,
+                          v8::Handle<String> script_data) {
   ON_BAILOUT("v8::Script::New()", return Local<Script>());
   LOG_API("Script::New");
   ENTER_V8;
@@ -1126,20 +1127,17 @@ Local<Script> Script::New(v8::Handle<String> source,
     }
   }
   EXCEPTION_PREAMBLE();
-  i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data);
+  i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
   // We assert that the pre-data is sane, even though we can actually
   // handle it if it turns out not to be in release mode.
-  ASSERT(pre_data == NULL || pre_data->SanityCheck());
+  ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
   // If the pre-data isn't sane we simply ignore it
-  if (pre_data != NULL && !pre_data->SanityCheck()) {
-    pre_data = NULL;
-  }
-  i::Handle<i::JSFunction> boilerplate = i::Compiler::Compile(str,
-                                                              name_obj,
-                                                              line_offset,
-                                                              column_offset,
-                                                              NULL,
-                                                              pre_data);
+  if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
+    pre_data_impl = NULL;
+  }
+  i::Handle<i::JSFunction> boilerplate =
+      i::Compiler::Compile(str, name_obj, line_offset, column_offset, NULL,
+                           pre_data_impl, Utils::OpenHandle(*script_data));
   has_pending_exception = boilerplate.is_null();
   EXCEPTION_BAILOUT_CHECK(Local<Script>());
   return Local<Script>(ToApi<Script>(boilerplate));
@@ -1155,11 +1153,12 @@ Local<Script> Script::New(v8::Handle<String> source,
 
 Local<Script> Script::Compile(v8::Handle<String> source,
                               v8::ScriptOrigin* origin,
-                              v8::ScriptData* script_data) {
+                              v8::ScriptData* pre_data,
+                              v8::Handle<String> script_data) {
   ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
   LOG_API("Script::Compile");
   ENTER_V8;
-  Local<Script> generic = New(source, origin, script_data);
+  Local<Script> generic = New(source, origin, pre_data, script_data);
   if (generic.IsEmpty())
     return generic;
   i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
@@ -1171,9 +1170,10 @@ Local<Script> Script::Compile(v8::Handle<String> source,
 
 
 Local<Script> Script::Compile(v8::Handle<String> source,
-                              v8::Handle<Value> file_name) {
+                              v8::Handle<Value> file_name,
+                              v8::Handle<String> script_data) {
   ScriptOrigin origin(file_name);
-  return Compile(source, &origin);
+  return Compile(source, &origin, 0, script_data);
 }
 
 
index 29a48a0..6202431 100755 (executable)
@@ -237,7 +237,8 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
                                      Handle<Object> script_name,
                                      int line_offset, int column_offset,
                                      v8::Extension* extension,
-                                     ScriptDataImpl* input_pre_data) {
+                                     ScriptDataImpl* input_pre_data,
+                                     Handle<Object> script_data) {
   int source_length = source->length();
   Counters::total_load_size.Increment(source_length);
   Counters::total_compile_size.Increment(source_length);
@@ -271,6 +272,9 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
       script->set_column_offset(Smi::FromInt(column_offset));
     }
 
+    script->set_data(script_data.is_null() ? Heap::undefined_value()
+                                           : *script_data);
+
     // Compile the function and add it to the cache.
     result = MakeFunction(true,
                           false,
index 21affdf..6ee2246 100644 (file)
@@ -185,7 +185,8 @@ class Compiler : public AllStatic {
                                     Handle<Object> script_name,
                                     int line_offset, int column_offset,
                                     v8::Extension* extension,
-                                    ScriptDataImpl* script_Data);
+                                    ScriptDataImpl* pre_data,
+                                    Handle<Object> script_data);
 
   // Compile a String source within a context for Eval.
   static Handle<JSFunction> CompileEval(Handle<String> source,
index 6d212bb..c6f32e4 100644 (file)
@@ -65,7 +65,6 @@ class NumberInfo : public AllStatic {
     UNREACHABLE();
     return "Unreachable code";
   }
-
 };
 
 } }  // namespace v8::internal
index 23d1a57..b7c39b2 100644 (file)
@@ -550,6 +550,15 @@ const char* frame_script_data_source =
 v8::Local<v8::Function> frame_script_data;
 
 
+// Source for The JavaScript function which picks out the script data from
+// AfterCompile event
+const char* compiled_script_data_source =
+    "function compiled_script_data(event_data) {"
+    "  return event_data.script().data();"
+    "}";
+v8::Local<v8::Function> compiled_script_data;
+
+
 // Source for The JavaScript function which returns the number of frames.
 static const char* frame_count_source =
     "function frame_count(exec_state) {"
@@ -647,6 +656,19 @@ static void DebugEventBreakPointHitCount(v8::DebugEvent event,
         script_data->WriteAscii(last_script_data_hit);
       }
     }
+  } else if (event == v8::AfterCompile && !compiled_script_data.IsEmpty()) {
+    const int argc = 1;
+    v8::Handle<v8::Value> argv[argc] = { event_data };
+    v8::Handle<v8::Value> result = compiled_script_data->Call(exec_state,
+                                                              argc, argv);
+    if (result->IsUndefined()) {
+      last_script_data_hit[0] = '\0';
+    } else {
+      result = result->ToString();
+      CHECK(result->IsString());
+      v8::Handle<v8::String> script_data(result->ToString());
+      script_data->WriteAscii(last_script_data_hit);
+    }
   }
 }
 
@@ -5232,6 +5254,9 @@ TEST(ScriptNameAndData) {
   frame_script_data = CompileFunction(&env,
                                       frame_script_data_source,
                                       "frame_script_data");
+  compiled_script_data = CompileFunction(&env,
+                                         compiled_script_data_source,
+                                         "compiled_script_data");
 
   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
                                    v8::Undefined());
@@ -5278,6 +5303,16 @@ TEST(ScriptNameAndData) {
   CHECK_EQ(3, break_point_hit_count);
   CHECK_EQ("new name", last_script_name_hit);
   CHECK_EQ("abc 123", last_script_data_hit);
+
+  v8::Handle<v8::Script> script3 =
+      v8::Script::Compile(script, &origin2, NULL,
+                          v8::String::New("in compile"));
+  CHECK_EQ("in compile", last_script_data_hit);
+  script3->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ("in compile", last_script_data_hit);
 }