@@ -116,9 +116,10 @@ class ProcessWrap : public HandleWrap {
116116 return Just (stream);
117117 }
118118
119- static Maybe<void > ParseStdioOptions (Environment* env,
120- Local<Object> js_options,
121- uv_process_options_t * options) {
119+ static Maybe<void > ParseStdioOptions (
120+ Environment* env,
121+ Local<Object> js_options,
122+ std::vector<uv_stdio_container_t >* options_stdio) {
122123 Local<Context> context = env->context ();
123124 Local<String> stdio_key = env->stdio_string ();
124125 Local<Value> stdios_val;
@@ -132,8 +133,7 @@ class ProcessWrap : public HandleWrap {
132133 Local<Array> stdios = stdios_val.As <Array>();
133134
134135 uint32_t len = stdios->Length ();
135- options->stdio = new uv_stdio_container_t [len];
136- options->stdio_count = len;
136+ options_stdio->resize (len);
137137
138138 for (uint32_t i = 0 ; i < len; i++) {
139139 Local<Value> val;
@@ -147,23 +147,23 @@ class ProcessWrap : public HandleWrap {
147147 }
148148
149149 if (type->StrictEquals (env->ignore_string ())) {
150- options-> stdio [i].flags = UV_IGNORE;
150+ (*options_stdio) [i].flags = UV_IGNORE;
151151 } else if (type->StrictEquals (env->pipe_string ())) {
152- options-> stdio [i].flags = static_cast <uv_stdio_flags>(
152+ (*options_stdio) [i].flags = static_cast <uv_stdio_flags>(
153153 UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE);
154- if (!StreamForWrap (env, stdio).To (&options-> stdio [i].data .stream )) {
154+ if (!StreamForWrap (env, stdio).To (&(*options_stdio) [i].data .stream )) {
155155 return Nothing<void >();
156156 }
157157 } else if (type->StrictEquals (env->overlapped_string ())) {
158- options-> stdio [i].flags = static_cast <uv_stdio_flags>(
159- UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE |
160- UV_OVERLAPPED_PIPE);
161- if (!StreamForWrap (env, stdio).To (&options-> stdio [i].data .stream )) {
158+ (*options_stdio) [i].flags =
159+ static_cast <uv_stdio_flags>( UV_CREATE_PIPE | UV_READABLE_PIPE |
160+ UV_WRITABLE_PIPE | UV_OVERLAPPED_PIPE);
161+ if (!StreamForWrap (env, stdio).To (&(*options_stdio) [i].data .stream )) {
162162 return Nothing<void >();
163163 }
164164 } else if (type->StrictEquals (env->wrap_string ())) {
165- options-> stdio [i].flags = UV_INHERIT_STREAM;
166- if (!StreamForWrap (env, stdio).To (&options-> stdio [i].data .stream )) {
165+ (*options_stdio) [i].flags = UV_INHERIT_STREAM;
166+ if (!StreamForWrap (env, stdio).To (&(*options_stdio) [i].data .stream )) {
167167 return Nothing<void >();
168168 }
169169 } else {
@@ -174,8 +174,8 @@ class ProcessWrap : public HandleWrap {
174174 }
175175 CHECK (fd_value->IsNumber ());
176176 int fd = FromV8Value<int >(fd_value);
177- options-> stdio [i].flags = UV_INHERIT_FD;
178- options-> stdio [i].data .fd = fd;
177+ (*options_stdio) [i].flags = UV_INHERIT_FD;
178+ (*options_stdio) [i].data .fd = fd;
179179 }
180180 }
181181 return JustVoid ();
@@ -199,8 +199,6 @@ class ProcessWrap : public HandleWrap {
199199
200200 options.exit_cb = OnExit;
201201
202- // TODO(bnoordhuis) is this possible to do without mallocing ?
203-
204202 // options.file
205203 Local<Value> file_v;
206204 if (!js_options->Get (context, env->file_string ()).ToLocal (&file_v)) {
@@ -251,23 +249,26 @@ class ProcessWrap : public HandleWrap {
251249 if (!js_options->Get (context, env->args_string ()).ToLocal (&argv_v)) {
252250 return ;
253251 }
254- if (!argv_v.IsEmpty () && argv_v->IsArray ()) {
252+ std::vector<char *> options_args;
253+ std::vector<std::string> args_vals;
254+ if (argv_v->IsArray ()) {
255255 Local<Array> js_argv = argv_v.As <Array>();
256256 int argc = js_argv->Length ();
257257 CHECK_LT (argc, INT_MAX); // Check for overflow.
258-
259- // Heap allocate to detect errors. +1 is for nullptr.
260- options.args = new char *[argc + 1 ];
258+ args_vals.reserve (argc);
259+ options_args.resize (argc + 1 );
261260 for (int i = 0 ; i < argc; i++) {
262261 Local<Value> val;
263262 if (!js_argv->Get (context, i).ToLocal (&val)) {
264263 return ;
265264 }
266265 node::Utf8Value arg (env->isolate (), val);
267- options.args [i] = strdup (*arg);
268- CHECK_NOT_NULL (options.args [i]);
266+ args_vals.emplace_back (arg.ToString ());
267+ options_args[i] = const_cast <char *>(args_vals.back ().c_str ());
268+ CHECK_NOT_NULL (options_args[i]);
269269 }
270- options.args [argc] = nullptr ;
270+ options_args[argc] = nullptr ;
271+ options.args = options_args.data ();
271272 }
272273
273274 // options.cwd
@@ -286,27 +287,35 @@ class ProcessWrap : public HandleWrap {
286287 if (!js_options->Get (context, env->env_pairs_string ()).ToLocal (&env_v)) {
287288 return ;
288289 }
289- if (!env_v.IsEmpty () && env_v->IsArray ()) {
290+ std::vector<char *> options_env;
291+ std::vector<std::string> env_vals;
292+ if (env_v->IsArray ()) {
290293 Local<Array> env_opt = env_v.As <Array>();
291294 int envc = env_opt->Length ();
292295 CHECK_LT (envc, INT_MAX); // Check for overflow.
293- options.env = new char *[envc + 1 ]; // Heap allocated to detect errors.
296+ env_vals.reserve (envc);
297+ options_env.resize (envc + 1 );
294298 for (int i = 0 ; i < envc; i++) {
295299 Local<Value> val;
296300 if (!env_opt->Get (context, i).ToLocal (&val)) {
297301 return ;
298302 }
299303 node::Utf8Value pair (env->isolate (), val);
300- options.env [i] = strdup (*pair);
301- CHECK_NOT_NULL (options.env [i]);
304+ env_vals.emplace_back (pair.ToString ());
305+ options_env[i] = const_cast <char *>(env_vals.back ().c_str ());
306+ CHECK_NOT_NULL (options_env[i]);
302307 }
303- options.env [envc] = nullptr ;
308+ options_env[envc] = nullptr ;
309+ options.env = options_env.data ();
304310 }
305311
306312 // options.stdio
307- if (ParseStdioOptions (env, js_options, &options).IsNothing ()) {
313+ std::vector<uv_stdio_container_t > options_stdio;
314+ if (ParseStdioOptions (env, js_options, &options_stdio).IsNothing ()) {
308315 return ;
309316 }
317+ options.stdio = options_stdio.data ();
318+ options.stdio_count = options_stdio.size ();
310319
311320 // options.windowsHide
312321 Local<Value> hide_v;
@@ -361,18 +370,6 @@ class ProcessWrap : public HandleWrap {
361370 }
362371 }
363372
364- if (options.args ) {
365- for (int i = 0 ; options.args [i]; i++) free (options.args [i]);
366- delete [] options.args ;
367- }
368-
369- if (options.env ) {
370- for (int i = 0 ; options.env [i]; i++) free (options.env [i]);
371- delete [] options.env ;
372- }
373-
374- delete[] options.stdio ;
375-
376373 args.GetReturnValue ().Set (err);
377374 }
378375
0 commit comments