Enable passing of script data via script creation methods.

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
This commit is contained in:
mikhail.naganov@gmail.com 2010-02-16 15:15:31 +00:00
parent a9e174f8ea
commit dcef87af66
6 changed files with 117 additions and 53 deletions

View 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 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 (context-independent).
*
* 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 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> Compile(Handle<String> source,
ScriptOrigin* origin = NULL,
ScriptData* pre_data = NULL);
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 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.
* \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).
*
* \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,
Handle<Value> file_name);
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.
*
* \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<String> script_data = Handle<String>());
/**
* Runs the script returning the resulting value. If the script is

View 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;
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);
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);
}

View File

@ -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,

View 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,

View File

@ -65,7 +65,6 @@ class NumberInfo : public AllStatic {
UNREACHABLE();
return "Unreachable code";
}
};
} } // namespace v8::internal

View 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);
}