diff options
Diffstat (limited to 'src/node_script.cc')
-rw-r--r-- | src/node_script.cc | 239 |
1 files changed, 104 insertions, 135 deletions
diff --git a/src/node_script.cc b/src/node_script.cc index 4766cd05a69..0e98f067661 100644 --- a/src/node_script.cc +++ b/src/node_script.cc @@ -26,11 +26,11 @@ namespace node { -using v8::Arguments; using v8::Array; using v8::Context; using v8::Exception; using v8::Function; +using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Handle; using v8::HandleScope; @@ -39,7 +39,6 @@ using v8::Object; using v8::Persistent; using v8::Script; using v8::String; -using v8::ThrowException; using v8::TryCatch; using v8::V8; using v8::Value; @@ -48,9 +47,9 @@ using v8::Value; class WrappedContext : ObjectWrap { public: static void Initialize(Handle<Object> target); - static Handle<Value> New(const Arguments& args); + static void New(const FunctionCallbackInfo<Value>& args); - Persistent<Context> GetV8Context(); + Local<Context> GetV8Context(); static Local<Object> NewInstance(); static bool InstanceOf(Handle<Value> value); @@ -81,57 +80,55 @@ class WrappedScript : ObjectWrap { EvalContextFlags context_flag, EvalOutputFlags output_flag, EvalTimeoutFlags timeout_flag> - static Handle<Value> EvalMachine(const Arguments& args); + static void EvalMachine(const FunctionCallbackInfo<Value>& args); protected: - static Persistent<FunctionTemplate> constructor_template; - WrappedScript() : ObjectWrap() {} ~WrappedScript(); - static Handle<Value> New(const Arguments& args); - static Handle<Value> CreateContext(const Arguments& arg); - static Handle<Value> RunInContext(const Arguments& args); - static Handle<Value> RunInThisContext(const Arguments& args); - static Handle<Value> RunInNewContext(const Arguments& args); - static Handle<Value> CompileRunInContext(const Arguments& args); - static Handle<Value> CompileRunInThisContext(const Arguments& args); - static Handle<Value> CompileRunInNewContext(const Arguments& args); + static void New(const FunctionCallbackInfo<Value>& args); + static void CreateContext(const FunctionCallbackInfo<Value>& args); + static void RunInContext(const FunctionCallbackInfo<Value>& args); + static void RunInThisContext(const FunctionCallbackInfo<Value>& args); + static void RunInNewContext(const FunctionCallbackInfo<Value>& args); + static void CompileRunInContext(const FunctionCallbackInfo<Value>& args); + static void CompileRunInThisContext(const FunctionCallbackInfo<Value>& args); + static void CompileRunInNewContext(const FunctionCallbackInfo<Value>& args); Persistent<Script> script_; }; -Persistent<Function> cloneObjectMethod; - void CloneObject(Handle<Object> recv, - Handle<Value> source, Handle<Value> target) { + Handle<Value> source, + Handle<Value> target) { HandleScope scope(node_isolate); - Handle<Value> args[] = {source, target}; - - // Init - if (cloneObjectMethod.IsEmpty()) { - Local<Function> cloneObjectMethod_ = Local<Function>::Cast( - Script::Compile(String::New( - "(function(source, target) {\n\ - Object.getOwnPropertyNames(source).forEach(function(key) {\n\ - try {\n\ - var desc = Object.getOwnPropertyDescriptor(source, key);\n\ - if (desc.value === source) desc.value = target;\n\ - Object.defineProperty(target, key, desc);\n\ - } catch (e) {\n\ - // Catch sealed properties errors\n\ - }\n\ - });\n\ - })" - ), String::New("binding:script"))->Run() - ); - cloneObjectMethod = Persistent<Function>::New(node_isolate, - cloneObjectMethod_); - } - - cloneObjectMethod->Call(recv, 2, args); + const char raw_script_source[] = + "(function(source, target) { \n" + " Object.getOwnPropertyNames(source).forEach(function(key) { \n" + " try { \n" + " var desc = Object.getOwnPropertyDescriptor(source, key); \n" + " if (desc.value === source) desc.value = target; \n" + " Object.defineProperty(target, key, desc); \n" + " } catch (e) { \n" + " // Catch sealed properties errors \n" + " } \n" + " }); \n" + "}); \n"; + + Local<String> script_source = + String::New(raw_script_source, sizeof(raw_script_source) - 1); + Local<Script> script = + Script::Compile(script_source, String::New("binding:script")); + + Local<Function> fun = script->Run().As<Function>(); + assert(fun.IsEmpty() == false); + assert(fun->IsFunction() == true); + + Handle<Value> argv[] = { source, target }; + Handle<Value> rc = fun->Call(recv, ARRAY_SIZE(argv), argv); + assert(rc.IsEmpty() == false); } @@ -139,124 +136,110 @@ void WrappedContext::Initialize(Handle<Object> target) { HandleScope scope(node_isolate); Local<FunctionTemplate> t = FunctionTemplate::New(WrappedContext::New); - constructor_template = Persistent<FunctionTemplate>::New(node_isolate, t); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - constructor_template->SetClassName(String::NewSymbol("Context")); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(String::NewSymbol("Context")); - target->Set(String::NewSymbol("Context"), - constructor_template->GetFunction()); + target->Set(String::NewSymbol("Context"), t->GetFunction()); + constructor_template.Reset(node_isolate, t); } bool WrappedContext::InstanceOf(Handle<Value> value) { - return !value.IsEmpty() && constructor_template->HasInstance(value); + return !value.IsEmpty() && HasInstance(constructor_template, value); } -Handle<Value> WrappedContext::New(const Arguments& args) { +void WrappedContext::New(const FunctionCallbackInfo<Value>& args) { HandleScope scope(node_isolate); - WrappedContext *t = new WrappedContext(); t->Wrap(args.This()); - - return args.This(); } WrappedContext::WrappedContext() : ObjectWrap() { - context_ = Persistent<Context>::New(node_isolate, Context::New(node_isolate)); + context_.Reset(node_isolate, Context::New(node_isolate)); } WrappedContext::~WrappedContext() { - context_.Dispose(node_isolate); + context_.Dispose(); } Local<Object> WrappedContext::NewInstance() { - Local<Object> context = constructor_template->GetFunction()->NewInstance(); - return context; + Local<FunctionTemplate> constructor_template_handle = + Local<FunctionTemplate>::New(node_isolate, constructor_template); + return constructor_template_handle->GetFunction()->NewInstance(); } -Persistent<Context> WrappedContext::GetV8Context() { - return context_; +Local<Context> WrappedContext::GetV8Context() { + return Local<Context>::New(node_isolate, context_); } -Persistent<FunctionTemplate> WrappedScript::constructor_template; - - void WrappedScript::Initialize(Handle<Object> target) { HandleScope scope(node_isolate); Local<FunctionTemplate> t = FunctionTemplate::New(WrappedScript::New); - constructor_template = Persistent<FunctionTemplate>::New(node_isolate, t); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + t->InstanceTemplate()->SetInternalFieldCount(1); // Note: We use 'NodeScript' instead of 'Script' so that we do not // conflict with V8's Script class defined in v8/src/messages.js // See GH-203 https://github.com/joyent/node/issues/203 - constructor_template->SetClassName(String::NewSymbol("NodeScript")); + t->SetClassName(String::NewSymbol("NodeScript")); - NODE_SET_PROTOTYPE_METHOD(constructor_template, + NODE_SET_PROTOTYPE_METHOD(t, "createContext", WrappedScript::CreateContext); - NODE_SET_PROTOTYPE_METHOD(constructor_template, + NODE_SET_PROTOTYPE_METHOD(t, "runInContext", WrappedScript::RunInContext); - NODE_SET_PROTOTYPE_METHOD(constructor_template, + NODE_SET_PROTOTYPE_METHOD(t, "runInThisContext", WrappedScript::RunInThisContext); - NODE_SET_PROTOTYPE_METHOD(constructor_template, + NODE_SET_PROTOTYPE_METHOD(t, "runInNewContext", WrappedScript::RunInNewContext); - NODE_SET_METHOD(constructor_template, + NODE_SET_METHOD(t, "createContext", WrappedScript::CreateContext); - NODE_SET_METHOD(constructor_template, + NODE_SET_METHOD(t, "runInContext", WrappedScript::CompileRunInContext); - NODE_SET_METHOD(constructor_template, + NODE_SET_METHOD(t, "runInThisContext", WrappedScript::CompileRunInThisContext); - NODE_SET_METHOD(constructor_template, + NODE_SET_METHOD(t, "runInNewContext", WrappedScript::CompileRunInNewContext); - target->Set(String::NewSymbol("NodeScript"), - constructor_template->GetFunction()); + target->Set(String::NewSymbol("NodeScript"), t->GetFunction()); } -Handle<Value> WrappedScript::New(const Arguments& args) { - if (!args.IsConstructCall()) { - return FromConstructorTemplate(constructor_template, args); - } - +void WrappedScript::New(const FunctionCallbackInfo<Value>& args) { + assert(args.IsConstructCall() == true); HandleScope scope(node_isolate); - WrappedScript *t = new WrappedScript(); t->Wrap(args.This()); - - return - WrappedScript::EvalMachine< + WrappedScript::EvalMachine< compileCode, thisContext, wrapExternal, noTimeout>(args); } WrappedScript::~WrappedScript() { - script_.Dispose(node_isolate); + script_.Dispose(); } -Handle<Value> WrappedScript::CreateContext(const Arguments& args) { +void WrappedScript::CreateContext(const FunctionCallbackInfo<Value>& args) { HandleScope scope(node_isolate); Local<Object> context = WrappedContext::NewInstance(); @@ -267,54 +250,50 @@ Handle<Value> WrappedScript::CreateContext(const Arguments& args) { CloneObject(args.This(), sandbox, context); } else { - return ThrowException(Exception::TypeError(String::New( - "createContext() accept only object as first argument."))); + return ThrowTypeError( + "createContext() accept only object as first argument."); } } - - return scope.Close(context); + args.GetReturnValue().Set(context); } -Handle<Value> WrappedScript::RunInContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::RunInContext(const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< unwrapExternal, userContext, returnResult, useTimeout>(args); } -Handle<Value> WrappedScript::RunInThisContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::RunInThisContext(const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< unwrapExternal, thisContext, returnResult, useTimeout>(args); } -Handle<Value> WrappedScript::RunInNewContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::RunInNewContext(const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< unwrapExternal, newContext, returnResult, useTimeout>(args); } -Handle<Value> WrappedScript::CompileRunInContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::CompileRunInContext( + const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< compileCode, userContext, returnResult, useTimeout>(args); } -Handle<Value> WrappedScript::CompileRunInThisContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::CompileRunInThisContext( + const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< compileCode, thisContext, returnResult, useTimeout>(args); } -Handle<Value> WrappedScript::CompileRunInNewContext(const Arguments& args) { - return - WrappedScript::EvalMachine< +void WrappedScript::CompileRunInNewContext( + const FunctionCallbackInfo<Value>& args) { + WrappedScript::EvalMachine< compileCode, newContext, returnResult, useTimeout>(args); } @@ -323,23 +302,20 @@ template <WrappedScript::EvalInputFlags input_flag, WrappedScript::EvalContextFlags context_flag, WrappedScript::EvalOutputFlags output_flag, WrappedScript::EvalTimeoutFlags timeout_flag> -Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { +void WrappedScript::EvalMachine(const FunctionCallbackInfo<Value>& args) { HandleScope scope(node_isolate); if (input_flag == compileCode && args.Length() < 1) { - return ThrowException(Exception::TypeError( - String::New("needs at least 'code' argument."))); + return ThrowTypeError("needs at least 'code' argument."); } const int sandbox_index = input_flag == compileCode ? 1 : 0; if (context_flag == userContext && !WrappedContext::InstanceOf(args[sandbox_index])) { - return ThrowException(Exception::TypeError( - String::New("needs a 'context' argument."))); + return ThrowTypeError("needs a 'context' argument."); } - Local<String> code; if (input_flag == compileCode) code = args[0]->ToString(); @@ -361,8 +337,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { const int timeout_index = filename_index + 1; if (timeout_flag == useTimeout && args.Length() > timeout_index) { if (!args[timeout_index]->IsUint32()) { - return ThrowException(Exception::TypeError( - String::New("needs an unsigned integer 'ms' argument."))); + return ThrowTypeError("needs an unsigned integer 'ms' argument."); } timeout = args[timeout_index]->Uint32Value(); } @@ -376,7 +351,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { display_error = true; } - Handle<Context> context = Context::GetCurrent(); + Local<Context> context = Context::GetCurrent(); Local<Array> keys; if (context_flag == newContext) { @@ -406,7 +381,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { try_catch.SetVerbose(false); Handle<Value> result; - Handle<Script> script; + Local<Script> script; if (input_flag == compileCode) { // well, here WrappedScript::New would suffice in all cases, but maybe @@ -418,23 +393,21 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { if (display_error) DisplayExceptionLine(try_catch.Message()); // Hack because I can't get a proper stacktrace on SyntaxError - return try_catch.ReThrow(); + try_catch.ReThrow(); + return; } } else { WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.This()); if (!n_script) { - return ThrowException(Exception::Error( - String::New("Must be called as a method of Script."))); + return ThrowError("Must be called as a method of Script."); } else if (n_script->script_.IsEmpty()) { - return ThrowException(Exception::Error( - String::New("'this' must be a result of previous " - "new Script(code) call."))); + return ThrowError( + "'this' must be a result of previous new Script(code) call."); } - script = n_script->script_; + script = Local<Script>::New(node_isolate, n_script->script_); } - if (output_flag == returnResult) { if (timeout) { Watchdog wd(timeout); @@ -444,20 +417,19 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { } if (try_catch.HasCaught() && try_catch.HasTerminated()) { V8::CancelTerminateExecution(args.GetIsolate()); - return ThrowException(Exception::Error( - String::New("Script execution timed out."))); + return ThrowError("Script execution timed out."); } if (result.IsEmpty()) { if (display_error) DisplayExceptionLine(try_catch.Message()); - return try_catch.ReThrow(); + try_catch.ReThrow(); + return; } } else { WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.This()); if (!n_script) { - return ThrowException(Exception::Error( - String::New("Must be called as a method of Script."))); + return ThrowError("Must be called as a method of Script."); } - n_script->script_ = Persistent<Script>::New(node_isolate, script); + n_script->script_.Reset(node_isolate, script); result = args.This(); } @@ -466,13 +438,12 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) { CloneObject(args.This(), context->Global()->GetPrototype(), sandbox); } - return result == args.This() ? result : scope.Close(result); + args.GetReturnValue().Set(result); } void InitEvals(Handle<Object> target) { HandleScope scope(node_isolate); - WrappedContext::Initialize(target); WrappedScript::Initialize(target); } @@ -480,6 +451,4 @@ void InitEvals(Handle<Object> target) { } // namespace node - NODE_MODULE(node_evals, node::InitEvals) - |