@@ -116,9 +116,10 @@ class ProcessWrap : public HandleWrap {
116
116
return Just (stream);
117
117
}
118
118
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) {
122
123
Local<Context> context = env->context ();
123
124
Local<String> stdio_key = env->stdio_string ();
124
125
Local<Value> stdios_val;
@@ -132,8 +133,7 @@ class ProcessWrap : public HandleWrap {
132
133
Local<Array> stdios = stdios_val.As <Array>();
133
134
134
135
uint32_t len = stdios->Length ();
135
- options->stdio = new uv_stdio_container_t [len];
136
- options->stdio_count = len;
136
+ options_stdio->resize (len);
137
137
138
138
for (uint32_t i = 0 ; i < len; i++) {
139
139
Local<Value> val;
@@ -147,23 +147,23 @@ class ProcessWrap : public HandleWrap {
147
147
}
148
148
149
149
if (type->StrictEquals (env->ignore_string ())) {
150
- options-> stdio [i].flags = UV_IGNORE;
150
+ (*options_stdio) [i].flags = UV_IGNORE;
151
151
} 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>(
153
153
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 )) {
155
155
return Nothing<void >();
156
156
}
157
157
} 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 )) {
162
162
return Nothing<void >();
163
163
}
164
164
} 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 )) {
167
167
return Nothing<void >();
168
168
}
169
169
} else {
@@ -174,8 +174,8 @@ class ProcessWrap : public HandleWrap {
174
174
}
175
175
CHECK (fd_value->IsNumber ());
176
176
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;
179
179
}
180
180
}
181
181
return JustVoid ();
@@ -199,8 +199,6 @@ class ProcessWrap : public HandleWrap {
199
199
200
200
options.exit_cb = OnExit;
201
201
202
- // TODO(bnoordhuis) is this possible to do without mallocing ?
203
-
204
202
// options.file
205
203
Local<Value> file_v;
206
204
if (!js_options->Get (context, env->file_string ()).ToLocal (&file_v)) {
@@ -251,23 +249,26 @@ class ProcessWrap : public HandleWrap {
251
249
if (!js_options->Get (context, env->args_string ()).ToLocal (&argv_v)) {
252
250
return ;
253
251
}
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 ()) {
255
255
Local<Array> js_argv = argv_v.As <Array>();
256
256
int argc = js_argv->Length ();
257
257
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 );
261
260
for (int i = 0 ; i < argc; i++) {
262
261
Local<Value> val;
263
262
if (!js_argv->Get (context, i).ToLocal (&val)) {
264
263
return ;
265
264
}
266
265
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]);
269
269
}
270
- options.args [argc] = nullptr ;
270
+ options_args[argc] = nullptr ;
271
+ options.args = options_args.data ();
271
272
}
272
273
273
274
// options.cwd
@@ -286,27 +287,35 @@ class ProcessWrap : public HandleWrap {
286
287
if (!js_options->Get (context, env->env_pairs_string ()).ToLocal (&env_v)) {
287
288
return ;
288
289
}
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 ()) {
290
293
Local<Array> env_opt = env_v.As <Array>();
291
294
int envc = env_opt->Length ();
292
295
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 );
294
298
for (int i = 0 ; i < envc; i++) {
295
299
Local<Value> val;
296
300
if (!env_opt->Get (context, i).ToLocal (&val)) {
297
301
return ;
298
302
}
299
303
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]);
302
307
}
303
- options.env [envc] = nullptr ;
308
+ options_env[envc] = nullptr ;
309
+ options.env = options_env.data ();
304
310
}
305
311
306
312
// 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 ()) {
308
315
return ;
309
316
}
317
+ options.stdio = options_stdio.data ();
318
+ options.stdio_count = options_stdio.size ();
310
319
311
320
// options.windowsHide
312
321
Local<Value> hide_v;
@@ -361,18 +370,6 @@ class ProcessWrap : public HandleWrap {
361
370
}
362
371
}
363
372
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
-
376
373
args.GetReturnValue ().Set (err);
377
374
}
378
375
0 commit comments