36 using v8::FunctionCallbackInfo;
37 using v8::FunctionTemplate;
38 using v8::HandleScope;
48 class ProcessWrap :
public HandleWrap {
52 Local<Context> context) {
53 Environment* env = Environment::GetCurrent(context);
54 Local<FunctionTemplate> constructor = env->NewFunctionTemplate(
New);
55 constructor->InstanceTemplate()->SetInternalFieldCount(1);
56 Local<String> processString =
57 FIXED_ONE_BYTE_STRING(env->isolate(),
"Process");
58 constructor->SetClassName(processString);
60 AsyncWrap::AddWrapMethods(env, constructor);
62 env->SetProtoMethod(constructor,
"close", HandleWrap::Close);
64 env->SetProtoMethod(constructor,
"spawn", Spawn);
65 env->SetProtoMethod(constructor,
"kill", Kill);
67 env->SetProtoMethod(constructor,
"ref", HandleWrap::Ref);
68 env->SetProtoMethod(constructor,
"unref", HandleWrap::Unref);
69 env->SetProtoMethod(constructor,
"hasRef", HandleWrap::HasRef);
71 target->Set(processString, constructor->GetFunction());
74 size_t self_size()
const override {
return sizeof(*this); }
77 static void New(
const FunctionCallbackInfo<Value>& args) {
81 CHECK(args.IsConstructCall());
82 Environment* env = Environment::GetCurrent(args);
83 new ProcessWrap(env, args.This());
86 ProcessWrap(Environment* env, Local<Object>
object)
89 reinterpret_cast<uv_handle_t*>(&process_),
90 AsyncWrap::PROVIDER_PROCESSWRAP) {
93 static void ParseStdioOptions(Environment* env,
94 Local<Object> js_options,
95 uv_process_options_t* options) {
96 Local<String> stdio_key = env->stdio_string();
97 Local<Array> stdios = js_options->Get(stdio_key).As<Array>();
99 uint32_t
len = stdios->Length();
100 options->stdio =
new uv_stdio_container_t[
len];
101 options->stdio_count =
len;
103 for (uint32_t i = 0; i <
len; i++) {
104 Local<Object> stdio = stdios->Get(i).As<Object>();
105 Local<Value> type = stdio->Get(env->type_string());
107 if (type->Equals(env->ignore_string())) {
108 options->stdio[i].flags = UV_IGNORE;
109 }
else if (type->Equals(env->pipe_string())) {
110 options->stdio[i].flags =
static_cast<uv_stdio_flags
>(
111 UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE);
112 Local<String> handle_key = env->handle_string();
113 Local<Object> handle = stdio->Get(handle_key).As<Object>();
114 CHECK(!handle.IsEmpty());
115 options->stdio[i].data.stream =
116 reinterpret_cast<uv_stream_t*
>(
117 Unwrap<PipeWrap>(handle)->UVHandle());
118 }
else if (type->Equals(env->wrap_string())) {
119 Local<String> handle_key = env->handle_string();
120 Local<Object> handle = stdio->Get(handle_key).As<Object>();
121 uv_stream_t* stream = HandleToStream(env, handle);
122 CHECK_NE(stream,
nullptr);
124 options->stdio[i].flags = UV_INHERIT_STREAM;
125 options->stdio[i].data.stream = stream;
127 Local<String> fd_key = env->fd_string();
128 int fd =
static_cast<int>(stdio->Get(fd_key)->IntegerValue());
129 options->stdio[i].flags = UV_INHERIT_FD;
130 options->stdio[i].data.fd = fd;
135 static void Spawn(
const FunctionCallbackInfo<Value>& args) {
136 Environment* env = Environment::GetCurrent(args);
139 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
141 Local<Object> js_options = args[0]->ToObject(env->isolate());
143 uv_process_options_t options;
144 memset(&options, 0,
sizeof(uv_process_options_t));
146 options.exit_cb = OnExit;
149 Local<Value> uid_v = js_options->Get(env->uid_string());
150 if (!uid_v->IsUndefined() && !uid_v->IsNull()) {
151 CHECK(uid_v->IsInt32());
152 const int32_t uid = uid_v->Int32Value(env->context()).FromJust();
153 options.flags |= UV_PROCESS_SETUID;
154 options.uid =
static_cast<uv_uid_t
>(uid);
158 Local<Value> gid_v = js_options->Get(env->gid_string());
159 if (!gid_v->IsUndefined() && !gid_v->IsNull()) {
160 CHECK(gid_v->IsInt32());
161 const int32_t gid = gid_v->Int32Value(env->context()).FromJust();
162 options.flags |= UV_PROCESS_SETGID;
163 options.gid =
static_cast<uv_gid_t
>(gid);
169 Local<Value> file_v = js_options->Get(env->file_string());
170 CHECK(file_v->IsString());
171 node::Utf8Value
file(env->isolate(), file_v);
172 options.file = *
file;
175 Local<Value> argv_v = js_options->Get(env->args_string());
176 if (!argv_v.IsEmpty() && argv_v->IsArray()) {
177 Local<Array> js_argv = Local<Array>::Cast(argv_v);
178 int argc = js_argv->Length();
180 options.args =
new char*[argc + 1];
181 for (
int i = 0; i < argc; i++) {
182 node::Utf8Value arg(env->isolate(), js_argv->Get(i));
183 options.args[i] = strdup(*arg);
184 CHECK_NE(options.args[i],
nullptr);
186 options.args[argc] =
nullptr;
190 Local<Value> cwd_v = js_options->Get(env->cwd_string());
191 node::Utf8Value cwd(env->isolate(),
192 cwd_v->IsString() ? cwd_v : Local<Value>());
193 if (cwd.length() > 0) {
198 Local<Value> env_v = js_options->Get(env->env_pairs_string());
199 if (!env_v.IsEmpty() && env_v->IsArray()) {
200 Local<Array> env_opt = Local<Array>::Cast(env_v);
201 int envc = env_opt->Length();
202 options.env =
new char*[envc + 1];
203 for (
int i = 0; i < envc; i++) {
204 node::Utf8Value pair(env->isolate(), env_opt->Get(i));
205 options.env[i] = strdup(*pair);
206 CHECK_NE(options.env[i],
nullptr);
208 options.env[envc] =
nullptr;
212 ParseStdioOptions(env, js_options, &options);
215 Local<String> windows_verbatim_arguments_key =
216 env->windows_verbatim_arguments_string();
217 if (js_options->Get(windows_verbatim_arguments_key)->IsTrue()) {
218 options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
222 Local<String> detached_key = env->detached_string();
223 if (js_options->Get(detached_key)->IsTrue()) {
224 options.flags |= UV_PROCESS_DETACHED;
227 int err = uv_spawn(env->event_loop(), &wrap->process_, &options);
230 CHECK_EQ(wrap->process_.data, wrap);
231 wrap->object()->Set(env->pid_string(),
236 for (
int i = 0; options.args[i]; i++) free(options.args[i]);
237 delete [] options.args;
241 for (
int i = 0; options.env[i]; i++) free(options.env[i]);
242 delete [] options.env;
245 delete[] options.stdio;
247 args.GetReturnValue().Set(err);
250 static void Kill(
const FunctionCallbackInfo<Value>& args) {
252 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
253 int signal = args[0]->Int32Value();
254 int err = uv_process_kill(&wrap->process_, signal);
255 args.GetReturnValue().Set(err);
258 static void OnExit(uv_process_t* handle,
261 ProcessWrap* wrap =
static_cast<ProcessWrap*
>(handle->data);
262 CHECK_NE(wrap,
nullptr);
263 CHECK_EQ(&wrap->process_, handle);
265 Environment* env = wrap->env();
266 HandleScope handle_scope(env->isolate());
267 Context::Scope context_scope(env->context());
269 Local<Value> argv[] = {
270 Number::New(env->isolate(),
static_cast<double>(exit_status)),
271 OneByteString(env->isolate(),
signo_string(term_signal))
274 wrap->MakeCallback(env->onexit_string(), arraysize(argv), argv);
277 uv_process_t process_;
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
const char * signo_string(int signo)
void Initialize(Local< Object > target, Local< Value > unused, Local< Context > context, void *priv)
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)