20
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
22
22
#include " env-inl.h"
23
+ #include " node_errors.h"
23
24
#include " node_external_reference.h"
24
25
#include " permission/permission.h"
25
26
#include " stream_base-inl.h"
@@ -40,7 +41,11 @@ using v8::HandleScope;
40
41
using v8::Int32;
41
42
using v8::Integer;
42
43
using v8::Isolate;
44
+ using v8::Just;
45
+ using v8::JustVoid;
43
46
using v8::Local;
47
+ using v8::Maybe;
48
+ using v8::Nothing;
44
49
using v8::Number;
45
50
using v8::Object;
46
51
using v8::String;
@@ -96,58 +101,84 @@ class ProcessWrap : public HandleWrap {
96
101
MarkAsUninitialized ();
97
102
}
98
103
99
- static uv_stream_t * StreamForWrap (Environment* env, Local<Object> stdio) {
104
+ static Maybe<uv_stream_t *> StreamForWrap (Environment* env,
105
+ Local<Object> stdio) {
100
106
Local<String> handle_key = env->handle_string ();
101
107
// This property has always been set by JS land if we are in this code path.
102
- Local<Object> handle =
103
- stdio->Get (env->context (), handle_key).ToLocalChecked ().As <Object>();
108
+ Local<Value> val;
109
+ if (!stdio->Get (env->context (), handle_key).ToLocal (&val)) {
110
+ return Nothing<uv_stream_t *>();
111
+ }
112
+ Local<Object> handle = val.As <Object>();
104
113
105
114
uv_stream_t * stream = LibuvStreamWrap::From (env, handle)->stream ();
106
115
CHECK_NOT_NULL (stream);
107
- return stream;
116
+ return Just ( stream) ;
108
117
}
109
118
110
- static void ParseStdioOptions (Environment* env,
111
- Local<Object> js_options,
112
- uv_process_options_t * options) {
119
+ static Maybe< void > ParseStdioOptions (Environment* env,
120
+ Local<Object> js_options,
121
+ uv_process_options_t * options) {
113
122
Local<Context> context = env->context ();
114
123
Local<String> stdio_key = env->stdio_string ();
115
- Local<Array> stdios =
116
- js_options->Get (context, stdio_key).ToLocalChecked ().As <Array>();
124
+ Local<Value> stdios_val;
125
+ if (!js_options->Get (context, stdio_key).ToLocal (&stdios_val)) {
126
+ return Nothing<void >();
127
+ }
128
+ if (!stdios_val->IsArray ()) {
129
+ THROW_ERR_INVALID_ARG_TYPE (env, " options.stdio must be an array" );
130
+ return Nothing<void >();
131
+ }
132
+ Local<Array> stdios = stdios_val.As <Array>();
117
133
118
134
uint32_t len = stdios->Length ();
119
135
options->stdio = new uv_stdio_container_t [len];
120
136
options->stdio_count = len;
121
137
122
138
for (uint32_t i = 0 ; i < len; i++) {
123
- Local<Object> stdio =
124
- stdios->Get (context, i).ToLocalChecked ().As <Object>();
125
- Local<Value> type =
126
- stdio->Get (context, env->type_string ()).ToLocalChecked ();
139
+ Local<Value> val;
140
+ if (!stdios->Get (context, i).ToLocal (&val)) {
141
+ return Nothing<void >();
142
+ }
143
+ Local<Object> stdio = val.As <Object>();
144
+ Local<Value> type;
145
+ if (!stdio->Get (context, env->type_string ()).ToLocal (&type)) {
146
+ return Nothing<void >();
147
+ }
127
148
128
149
if (type->StrictEquals (env->ignore_string ())) {
129
150
options->stdio [i].flags = UV_IGNORE;
130
151
} else if (type->StrictEquals (env->pipe_string ())) {
131
152
options->stdio [i].flags = static_cast <uv_stdio_flags>(
132
153
UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE);
133
- options->stdio [i].data .stream = StreamForWrap (env, stdio);
154
+ if (!StreamForWrap (env, stdio).To (&options->stdio [i].data .stream )) {
155
+ return Nothing<void >();
156
+ }
134
157
} else if (type->StrictEquals (env->overlapped_string ())) {
135
158
options->stdio [i].flags = static_cast <uv_stdio_flags>(
136
159
UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE |
137
160
UV_OVERLAPPED_PIPE);
138
- options->stdio [i].data .stream = StreamForWrap (env, stdio);
161
+ if (!StreamForWrap (env, stdio).To (&options->stdio [i].data .stream )) {
162
+ return Nothing<void >();
163
+ }
139
164
} else if (type->StrictEquals (env->wrap_string ())) {
140
165
options->stdio [i].flags = UV_INHERIT_STREAM;
141
- options->stdio [i].data .stream = StreamForWrap (env, stdio);
166
+ if (!StreamForWrap (env, stdio).To (&options->stdio [i].data .stream )) {
167
+ return Nothing<void >();
168
+ }
142
169
} else {
143
170
Local<String> fd_key = env->fd_string ();
144
- Local<Value> fd_value = stdio->Get (context, fd_key).ToLocalChecked ();
171
+ Local<Value> fd_value;
172
+ if (!stdio->Get (context, fd_key).ToLocal (&fd_value)) {
173
+ return Nothing<void >();
174
+ }
145
175
CHECK (fd_value->IsNumber ());
146
176
int fd = static_cast <int >(fd_value.As <Integer>()->Value ());
147
177
options->stdio [i].flags = UV_INHERIT_FD;
148
178
options->stdio [i].data .fd = fd;
149
179
}
150
180
}
181
+ return JustVoid ();
151
182
}
152
183
153
184
static void Spawn (const FunctionCallbackInfo<Value>& args) {
@@ -159,17 +190,22 @@ class ProcessWrap : public HandleWrap {
159
190
env, permission::PermissionScope::kChildProcess , " " );
160
191
int err = 0 ;
161
192
162
- Local<Object> js_options =
163
- args[0 ]->ToObject (env->context ()).ToLocalChecked ();
193
+ if (!args[0 ]->IsObject ()) {
194
+ return THROW_ERR_INVALID_ARG_TYPE (env, " options must be an object" );
195
+ }
196
+
197
+ Local<Object> js_options = args[0 ].As <Object>();
164
198
165
199
uv_process_options_t options;
166
200
memset (&options, 0 , sizeof (uv_process_options_t ));
167
201
168
202
options.exit_cb = OnExit;
169
203
170
204
// options.uid
171
- Local<Value> uid_v =
172
- js_options->Get (context, env->uid_string ()).ToLocalChecked ();
205
+ Local<Value> uid_v;
206
+ if (!js_options->Get (context, env->uid_string ()).ToLocal (&uid_v)) {
207
+ return ;
208
+ }
173
209
if (!uid_v->IsUndefined () && !uid_v->IsNull ()) {
174
210
CHECK (uid_v->IsInt32 ());
175
211
const int32_t uid = uid_v.As <Int32>()->Value ();
@@ -178,8 +214,10 @@ class ProcessWrap : public HandleWrap {
178
214
}
179
215
180
216
// options.gid
181
- Local<Value> gid_v =
182
- js_options->Get (context, env->gid_string ()).ToLocalChecked ();
217
+ Local<Value> gid_v;
218
+ if (!js_options->Get (context, env->gid_string ()).ToLocal (&gid_v)) {
219
+ return ;
220
+ }
183
221
if (!gid_v->IsUndefined () && !gid_v->IsNull ()) {
184
222
CHECK (gid_v->IsInt32 ());
185
223
const int32_t gid = gid_v.As <Int32>()->Value ();
@@ -190,8 +228,10 @@ class ProcessWrap : public HandleWrap {
190
228
// TODO(bnoordhuis) is this possible to do without mallocing ?
191
229
192
230
// options.file
193
- Local<Value> file_v =
194
- js_options->Get (context, env->file_string ()).ToLocalChecked ();
231
+ Local<Value> file_v;
232
+ if (!js_options->Get (context, env->file_string ()).ToLocal (&file_v)) {
233
+ return ;
234
+ }
195
235
CHECK (file_v->IsString ());
196
236
node::Utf8Value file (env->isolate (), file_v);
197
237
options.file = *file;
@@ -206,8 +246,10 @@ class ProcessWrap : public HandleWrap {
206
246
#endif
207
247
208
248
// options.args
209
- Local<Value> argv_v =
210
- js_options->Get (context, env->args_string ()).ToLocalChecked ();
249
+ Local<Value> argv_v;
250
+ if (!js_options->Get (context, env->args_string ()).ToLocal (&argv_v)) {
251
+ return ;
252
+ }
211
253
if (!argv_v.IsEmpty () && argv_v->IsArray ()) {
212
254
Local<Array> js_argv = argv_v.As <Array>();
213
255
int argc = js_argv->Length ();
@@ -216,46 +258,61 @@ class ProcessWrap : public HandleWrap {
216
258
// Heap allocate to detect errors. +1 is for nullptr.
217
259
options.args = new char *[argc + 1 ];
218
260
for (int i = 0 ; i < argc; i++) {
219
- node::Utf8Value arg (env->isolate (),
220
- js_argv->Get (context, i).ToLocalChecked ());
261
+ Local<Value> val;
262
+ if (!js_argv->Get (context, i).ToLocal (&val)) {
263
+ return ;
264
+ }
265
+ node::Utf8Value arg (env->isolate (), val);
221
266
options.args [i] = strdup (*arg);
222
267
CHECK_NOT_NULL (options.args [i]);
223
268
}
224
269
options.args [argc] = nullptr ;
225
270
}
226
271
227
272
// options.cwd
228
- Local<Value> cwd_v =
229
- js_options->Get (context, env->cwd_string ()).ToLocalChecked ();
273
+ Local<Value> cwd_v;
274
+ if (!js_options->Get (context, env->cwd_string ()).ToLocal (&cwd_v)) {
275
+ return ;
276
+ }
230
277
node::Utf8Value cwd (env->isolate (),
231
278
cwd_v->IsString () ? cwd_v : Local<Value>());
232
279
if (cwd.length () > 0 ) {
233
280
options.cwd = *cwd;
234
281
}
235
282
236
283
// options.env
237
- Local<Value> env_v =
238
- js_options->Get (context, env->env_pairs_string ()).ToLocalChecked ();
284
+ Local<Value> env_v;
285
+ if (!js_options->Get (context, env->env_pairs_string ()).ToLocal (&env_v)) {
286
+ return ;
287
+ }
239
288
if (!env_v.IsEmpty () && env_v->IsArray ()) {
240
289
Local<Array> env_opt = env_v.As <Array>();
241
290
int envc = env_opt->Length ();
242
291
CHECK_LT (envc, INT_MAX); // Check for overflow.
243
292
options.env = new char *[envc + 1 ]; // Heap allocated to detect errors.
244
293
for (int i = 0 ; i < envc; i++) {
245
- node::Utf8Value pair (env->isolate (),
246
- env_opt->Get (context, i).ToLocalChecked ());
294
+ Local<Value> val;
295
+ if (!env_opt->Get (context, i).ToLocal (&val)) {
296
+ return ;
297
+ }
298
+ node::Utf8Value pair (env->isolate (), val);
247
299
options.env [i] = strdup (*pair);
248
300
CHECK_NOT_NULL (options.env [i]);
249
301
}
250
302
options.env [envc] = nullptr ;
251
303
}
252
304
253
305
// options.stdio
254
- ParseStdioOptions (env, js_options, &options);
306
+ if (ParseStdioOptions (env, js_options, &options).IsNothing ()) {
307
+ return ;
308
+ }
255
309
256
310
// options.windowsHide
257
- Local<Value> hide_v =
258
- js_options->Get (context, env->windows_hide_string ()).ToLocalChecked ();
311
+ Local<Value> hide_v;
312
+ if (!js_options->Get (context, env->windows_hide_string ())
313
+ .ToLocal (&hide_v)) {
314
+ return ;
315
+ }
259
316
260
317
if (hide_v->IsTrue ()) {
261
318
options.flags |= UV_PROCESS_WINDOWS_HIDE;
@@ -266,17 +323,22 @@ class ProcessWrap : public HandleWrap {
266
323
}
267
324
268
325
// options.windows_verbatim_arguments
269
- Local<Value> wva_v =
270
- js_options->Get (context, env->windows_verbatim_arguments_string ())
271
- .ToLocalChecked ();
326
+ Local<Value> wva_v;
327
+ if (!js_options->Get (context, env->windows_verbatim_arguments_string ())
328
+ .ToLocal (&wva_v)) {
329
+ return ;
330
+ }
272
331
273
332
if (wva_v->IsTrue ()) {
274
333
options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
275
334
}
276
335
277
336
// options.detached
278
- Local<Value> detached_v =
279
- js_options->Get (context, env->detached_string ()).ToLocalChecked ();
337
+ Local<Value> detached_v;
338
+ if (!js_options->Get (context, env->detached_string ())
339
+ .ToLocal (&detached_v)) {
340
+ return ;
341
+ }
280
342
281
343
if (detached_v->IsTrue ()) {
282
344
options.flags |= UV_PROCESS_DETACHED;
@@ -289,9 +351,13 @@ class ProcessWrap : public HandleWrap {
289
351
290
352
if (err == 0 ) {
291
353
CHECK_EQ (wrap->process_ .data , wrap);
292
- wrap->object ()->Set (context, env->pid_string (),
293
- Integer::New (env->isolate (),
294
- wrap->process_ .pid )).Check ();
354
+ if (wrap->object ()
355
+ ->Set (context,
356
+ env->pid_string (),
357
+ Integer::New (env->isolate (), wrap->process_ .pid ))
358
+ .IsNothing ()) {
359
+ return ;
360
+ }
295
361
}
296
362
297
363
if (options.args ) {
0 commit comments