GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node.cc Lines: 1533 1808 84.8 %
Date: 2017-12-18 Branches: 832 1199 69.4 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "node_buffer.h"
23
#include "node_constants.h"
24
#include "node_javascript.h"
25
#include "node_platform.h"
26
#include "node_version.h"
27
#include "node_internals.h"
28
#include "node_revert.h"
29
#include "node_debug_options.h"
30
#include "node_perf.h"
31
32
#if defined HAVE_PERFCTR
33
#include "node_counters.h"
34
#endif
35
36
#if HAVE_OPENSSL
37
#include "node_crypto.h"
38
#endif
39
40
#if defined(NODE_HAVE_I18N_SUPPORT)
41
#include "node_i18n.h"
42
#endif
43
44
#if HAVE_INSPECTOR
45
#include "inspector_io.h"
46
#endif
47
48
#if defined HAVE_DTRACE || defined HAVE_ETW
49
#include "node_dtrace.h"
50
#endif
51
52
#if defined HAVE_LTTNG
53
#include "node_lttng.h"
54
#endif
55
56
#include "ares.h"
57
#include "async_wrap-inl.h"
58
#include "env-inl.h"
59
#include "handle_wrap.h"
60
#include "http_parser.h"
61
#include "nghttp2/nghttp2ver.h"
62
#include "req_wrap-inl.h"
63
#include "string_bytes.h"
64
#include "tracing/agent.h"
65
#include "util.h"
66
#include "uv.h"
67
#if NODE_USE_V8_PLATFORM
68
#include "libplatform/libplatform.h"
69
#endif  // NODE_USE_V8_PLATFORM
70
#include "v8-profiler.h"
71
#include "zlib.h"
72
73
#ifdef NODE_ENABLE_VTUNE_PROFILING
74
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
75
#endif
76
77
#include <errno.h>
78
#include <fcntl.h>  // _O_RDWR
79
#include <limits.h>  // PATH_MAX
80
#include <locale.h>
81
#include <signal.h>
82
#include <stdio.h>
83
#include <stdlib.h>
84
#include <string.h>
85
#include <sys/types.h>
86
87
#include <string>
88
#include <vector>
89
90
#if defined(NODE_HAVE_I18N_SUPPORT)
91
#include <unicode/uvernum.h>
92
#endif
93
94
#if defined(LEAK_SANITIZER)
95
#include <sanitizer/lsan_interface.h>
96
#endif
97
98
#if defined(_MSC_VER)
99
#include <direct.h>
100
#include <io.h>
101
#define umask _umask
102
typedef int mode_t;
103
#else
104
#include <pthread.h>
105
#include <sys/resource.h>  // getrlimit, setrlimit
106
#include <unistd.h>  // setuid, getuid
107
#endif
108
109
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
110
#include <pwd.h>  // getpwnam()
111
#include <grp.h>  // getgrnam()
112
#endif
113
114
#if defined(__POSIX__)
115
#include <dlfcn.h>
116
#endif
117
118
#ifdef __APPLE__
119
#include <crt_externs.h>
120
#define environ (*_NSGetEnviron())
121
#elif !defined(_MSC_VER)
122
extern char **environ;
123
#endif
124
125
// This is used to load built-in modules. Instead of using
126
// __attribute__((constructor)), we call the _register_<modname>
127
// function for each built-in modules explicitly in
128
// node::RegisterBuiltinModules(). This is only forward declaration.
129
// The definitions are in each module's implementation when calling
130
// the NODE_BUILTIN_MODULE_CONTEXT_AWARE.
131
#define V(modname) void _register_##modname();
132
  NODE_BUILTIN_MODULES(V)
133
#undef V
134
135
namespace node {
136
137
using v8::Array;
138
using v8::ArrayBuffer;
139
using v8::Boolean;
140
using v8::Context;
141
using v8::EscapableHandleScope;
142
using v8::Exception;
143
using v8::Float64Array;
144
using v8::Function;
145
using v8::FunctionCallbackInfo;
146
using v8::HandleScope;
147
using v8::HeapStatistics;
148
using v8::Integer;
149
using v8::Isolate;
150
using v8::Just;
151
using v8::Local;
152
using v8::Locker;
153
using v8::Maybe;
154
using v8::MaybeLocal;
155
using v8::Message;
156
using v8::Name;
157
using v8::NamedPropertyHandlerConfiguration;
158
using v8::Nothing;
159
using v8::Null;
160
using v8::Number;
161
using v8::Object;
162
using v8::ObjectTemplate;
163
using v8::Promise;
164
using v8::PromiseRejectMessage;
165
using v8::PropertyCallbackInfo;
166
using v8::ScriptOrigin;
167
using v8::SealHandleScope;
168
using v8::String;
169
using v8::TryCatch;
170
using v8::Uint32Array;
171
using v8::Undefined;
172
using v8::V8;
173
using v8::Value;
174
175
using AsyncHooks = node::Environment::AsyncHooks;
176
177
static bool print_eval = false;
178
static bool force_repl = false;
179
static bool syntax_check_only = false;
180
static bool trace_deprecation = false;
181
static bool throw_deprecation = false;
182
static bool trace_sync_io = false;
183
static bool no_force_async_hooks_checks = false;
184
static bool track_heap_objects = false;
185
static const char* eval_string = nullptr;
186
3392
static std::vector<std::string> preload_modules;
187
static const int v8_default_thread_pool_size = 4;
188
static int v8_thread_pool_size = v8_default_thread_pool_size;
189
static bool prof_process = false;
190
static bool v8_is_profiling = false;
191
static bool node_is_initialized = false;
192
static node_module* modpending;
193
static node_module* modlist_builtin;
194
static node_module* modlist_internal;
195
static node_module* modlist_linked;
196
static node_module* modlist_addon;
197
static bool trace_enabled = false;
198
3392
static std::string trace_enabled_categories;  // NOLINT(runtime/string)
199
static bool abort_on_uncaught_exception = false;
200
201
// Bit flag used to track security reverts (see node_revert.h)
202
unsigned int reverted = 0;
203
204
#if defined(NODE_HAVE_I18N_SUPPORT)
205
// Path to ICU data (for i18n / Intl)
206
3392
std::string icu_data_dir;  // NOLINT(runtime/string)
207
#endif
208
209
// used by C++ modules as well
210
bool no_deprecation = false;
211
212
#if HAVE_OPENSSL
213
// use OpenSSL's cert store instead of bundled certs
214
bool ssl_openssl_cert_store =
215
#if defined(NODE_OPENSSL_CERT_STORE)
216
        true;
217
#else
218
        false;
219
#endif
220
221
# if NODE_FIPS_MODE
222
// used by crypto module
223
bool enable_fips_crypto = false;
224
bool force_fips_crypto = false;
225
# endif  // NODE_FIPS_MODE
226
3392
std::string openssl_config;  // NOLINT(runtime/string)
227
#endif  // HAVE_OPENSSL
228
229
// true if process warnings should be suppressed
230
bool no_process_warnings = false;
231
bool trace_warnings = false;
232
233
// Set in node.cc by ParseArgs when --preserve-symlinks is used.
234
// Used in node_config.cc to set a constant on process.binding('config')
235
// that is used by lib/module.js
236
bool config_preserve_symlinks = false;
237
238
// Set in node.cc by ParseArgs when --experimental-modules is used.
239
// Used in node_config.cc to set a constant on process.binding('config')
240
// that is used by lib/module.js
241
bool config_experimental_modules = false;
242
243
// Set in node.cc by ParseArgs when --loader is used.
244
// Used in node_config.cc to set a constant on process.binding('config')
245
// that is used by lib/internal/bootstrap_node.js
246
3392
std::string config_userland_loader;  // NOLINT(runtime/string)
247
248
// Set by ParseArgs when --pending-deprecation or NODE_PENDING_DEPRECATION
249
// is used.
250
bool config_pending_deprecation = false;
251
252
// Set in node.cc by ParseArgs when --redirect-warnings= is used.
253
3392
std::string config_warning_file;  // NOLINT(runtime/string)
254
255
// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
256
// used.
257
// Used in node_config.cc to set a constant on process.binding('config')
258
// that is used by lib/internal/bootstrap_node.js
259
bool config_expose_internals = false;
260
261
bool v8_initialized = false;
262
263
bool linux_at_secure = false;
264
265
// process-relative uptime base, initialized at start-up
266
static double prog_start_time;
267
268
3392
static Mutex node_isolate_mutex;
269
static v8::Isolate* node_isolate;
270
271
3392
node::DebugOptions debug_options;
272
273
6784
static struct {
274
#if NODE_USE_V8_PLATFORM
275
3348
  void Initialize(int thread_pool_size) {
276
3348
    if (trace_enabled) {
277
8
      tracing_agent_.reset(new tracing::Agent());
278
      platform_ = new NodePlatform(thread_pool_size,
279
8
        tracing_agent_->GetTracingController());
280
8
      V8::InitializePlatform(platform_);
281
      tracing::TraceEventHelper::SetTracingController(
282
8
        tracing_agent_->GetTracingController());
283
    } else {
284
3340
      tracing_agent_.reset(nullptr);
285
3340
      platform_ = new NodePlatform(thread_pool_size, nullptr);
286
3340
      V8::InitializePlatform(platform_);
287
      tracing::TraceEventHelper::SetTracingController(
288
3340
        new v8::TracingController());
289
    }
290
3348
  }
291
292
3003
  void Dispose() {
293
3003
    platform_->Shutdown();
294
3003
    delete platform_;
295
3003
    platform_ = nullptr;
296
3003
    tracing_agent_.reset(nullptr);
297
3003
  }
298
299
6061
  void DrainVMTasks(Isolate* isolate) {
300
6061
    platform_->DrainBackgroundTasks(isolate);
301
6061
  }
302
303
3003
  void CancelVMTasks(Isolate* isolate) {
304
3003
    platform_->CancelPendingDelayedTasks(isolate);
305
3003
  }
306
307
#if HAVE_INSPECTOR
308
3348
  bool StartInspector(Environment *env, const char* script_path,
309
                      const node::DebugOptions& options) {
310
    // Inspector agent can't fail to start, but if it was configured to listen
311
    // right away on the websocket port and fails to bind/etc, this will return
312
    // false.
313
3348
    return env->inspector_agent()->Start(platform_, script_path, options);
314
  }
315
316
59
  bool InspectorStarted(Environment *env) {
317
59
    return env->inspector_agent()->IsStarted();
318
  }
319
#endif  // HAVE_INSPECTOR
320
321
8
  void StartTracingAgent() {
322
8
    tracing_agent_->Start(trace_enabled_categories);
323
8
  }
324
325
8
  void StopTracingAgent() {
326
8
    tracing_agent_->Stop();
327
8
  }
328
329
3348
  NodePlatform* Platform() {
330
3348
    return platform_;
331
  }
332
333
  std::unique_ptr<tracing::Agent> tracing_agent_;
334
  NodePlatform* platform_;
335
#else  // !NODE_USE_V8_PLATFORM
336
  void Initialize(int thread_pool_size) {}
337
  void Dispose() {}
338
  void DrainVMTasks(Isolate* isolate) {}
339
  void CancelVMTasks(Isolate* isolate) {}
340
  bool StartInspector(Environment *env, const char* script_path,
341
                      const node::DebugOptions& options) {
342
    env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
343
    return true;
344
  }
345
346
  void StartTracingAgent() {
347
    fprintf(stderr, "Node compiled with NODE_USE_V8_PLATFORM=0, "
348
                    "so event tracing is not available.\n");
349
  }
350
  void StopTracingAgent() {}
351
352
  NodePlatform* Platform() {
353
    return nullptr;
354
  }
355
#endif  // !NODE_USE_V8_PLATFORM
356
357
#if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
358
  bool InspectorStarted(Environment *env) {
359
    return false;
360
  }
361
#endif  //  !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
362
3392
} v8_platform;
363
364
#ifdef __POSIX__
365
static const unsigned kMaxSignal = 32;
366
#endif
367
368
143
static void PrintErrorString(const char* format, ...) {
369
  va_list ap;
370
143
  va_start(ap, format);
371
#ifdef _WIN32
372
  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
373
374
  // Check if stderr is something other than a tty/console
375
  if (stderr_handle == INVALID_HANDLE_VALUE ||
376
      stderr_handle == nullptr ||
377
      uv_guess_handle(_fileno(stderr)) != UV_TTY) {
378
    vfprintf(stderr, format, ap);
379
    va_end(ap);
380
    return;
381
  }
382
383
  // Fill in any placeholders
384
  int n = _vscprintf(format, ap);
385
  std::vector<char> out(n + 1);
386
  vsprintf(out.data(), format, ap);
387
388
  // Get required wide buffer size
389
  n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
390
391
  std::vector<wchar_t> wbuf(n);
392
  MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
393
394
  // Don't include the null character in the output
395
  CHECK_GT(n, 0);
396
  WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
397
#else
398
143
  vfprintf(stderr, format, ap);
399
#endif
400
143
  va_end(ap);
401
143
}
402
403
1421
const char *signo_string(int signo) {
404
#define SIGNO_CASE(e)  case e: return #e;
405








1421
  switch (signo) {
406
#ifdef SIGHUP
407
  SIGNO_CASE(SIGHUP);
408
#endif
409
410
#ifdef SIGINT
411
4
  SIGNO_CASE(SIGINT);
412
#endif
413
414
#ifdef SIGQUIT
415
  SIGNO_CASE(SIGQUIT);
416
#endif
417
418
#ifdef SIGILL
419
2
  SIGNO_CASE(SIGILL);
420
#endif
421
422
#ifdef SIGTRAP
423
  SIGNO_CASE(SIGTRAP);
424
#endif
425
426
#ifdef SIGABRT
427
8
  SIGNO_CASE(SIGABRT);
428
#endif
429
430
#ifdef SIGIOT
431
# if SIGABRT != SIGIOT
432
  SIGNO_CASE(SIGIOT);
433
# endif
434
#endif
435
436
#ifdef SIGBUS
437
  SIGNO_CASE(SIGBUS);
438
#endif
439
440
#ifdef SIGFPE
441
  SIGNO_CASE(SIGFPE);
442
#endif
443
444
#ifdef SIGKILL
445
5
  SIGNO_CASE(SIGKILL);
446
#endif
447
448
#ifdef SIGUSR1
449
  SIGNO_CASE(SIGUSR1);
450
#endif
451
452
#ifdef SIGSEGV
453
  SIGNO_CASE(SIGSEGV);
454
#endif
455
456
#ifdef SIGUSR2
457
  SIGNO_CASE(SIGUSR2);
458
#endif
459
460
#ifdef SIGPIPE
461
  SIGNO_CASE(SIGPIPE);
462
#endif
463
464
#ifdef SIGALRM
465
  SIGNO_CASE(SIGALRM);
466
#endif
467
468
151
  SIGNO_CASE(SIGTERM);
469
470
#ifdef SIGCHLD
471
  SIGNO_CASE(SIGCHLD);
472
#endif
473
474
#ifdef SIGSTKFLT
475
  SIGNO_CASE(SIGSTKFLT);
476
#endif
477
478
479
#ifdef SIGCONT
480
  SIGNO_CASE(SIGCONT);
481
#endif
482
483
#ifdef SIGSTOP
484
  SIGNO_CASE(SIGSTOP);
485
#endif
486
487
#ifdef SIGTSTP
488
  SIGNO_CASE(SIGTSTP);
489
#endif
490
491
#ifdef SIGBREAK
492
  SIGNO_CASE(SIGBREAK);
493
#endif
494
495
#ifdef SIGTTIN
496
  SIGNO_CASE(SIGTTIN);
497
#endif
498
499
#ifdef SIGTTOU
500
  SIGNO_CASE(SIGTTOU);
501
#endif
502
503
#ifdef SIGURG
504
  SIGNO_CASE(SIGURG);
505
#endif
506
507
#ifdef SIGXCPU
508
  SIGNO_CASE(SIGXCPU);
509
#endif
510
511
#ifdef SIGXFSZ
512
  SIGNO_CASE(SIGXFSZ);
513
#endif
514
515
#ifdef SIGVTALRM
516
  SIGNO_CASE(SIGVTALRM);
517
#endif
518
519
#ifdef SIGPROF
520
  SIGNO_CASE(SIGPROF);
521
#endif
522
523
#ifdef SIGWINCH
524
  SIGNO_CASE(SIGWINCH);
525
#endif
526
527
#ifdef SIGIO
528
  SIGNO_CASE(SIGIO);
529
#endif
530
531
#ifdef SIGPOLL
532
# if SIGPOLL != SIGIO
533
  SIGNO_CASE(SIGPOLL);
534
# endif
535
#endif
536
537
#ifdef SIGLOST
538
# if SIGLOST != SIGABRT
539
  SIGNO_CASE(SIGLOST);
540
# endif
541
#endif
542
543
#ifdef SIGPWR
544
# if SIGPWR != SIGLOST
545
  SIGNO_CASE(SIGPWR);
546
# endif
547
#endif
548
549
#ifdef SIGINFO
550
# if !defined(SIGPWR) || SIGINFO != SIGPWR
551
  SIGNO_CASE(SIGINFO);
552
# endif
553
#endif
554
555
#ifdef SIGSYS
556
  SIGNO_CASE(SIGSYS);
557
#endif
558
559
1251
  default: return "";
560
  }
561
}
562
563
564
4
Local<Value> ErrnoException(Isolate* isolate,
565
                            int errorno,
566
                            const char *syscall,
567
                            const char *msg,
568
                            const char *path) {
569
4
  Environment* env = Environment::GetCurrent(isolate);
570
571
  Local<Value> e;
572
4
  Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
573

4
  if (msg == nullptr || msg[0] == '\0') {
574
3
    msg = strerror(errorno);
575
  }
576
4
  Local<String> message = OneByteString(env->isolate(), msg);
577
578
  Local<String> cons =
579
4
      String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
580
4
  cons = String::Concat(cons, message);
581
582
  Local<String> path_string;
583
4
  if (path != nullptr) {
584
    // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
585
1
    path_string = String::NewFromUtf8(env->isolate(), path);
586
  }
587
588
4
  if (path_string.IsEmpty() == false) {
589
1
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
590
1
    cons = String::Concat(cons, path_string);
591
1
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
592
  }
593
4
  e = Exception::Error(cons);
594
595
4
  Local<Object> obj = e.As<Object>();
596
12
  obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
597
8
  obj->Set(env->code_string(), estring);
598
599
4
  if (path_string.IsEmpty() == false) {
600
2
    obj->Set(env->path_string(), path_string);
601
  }
602
603
4
  if (syscall != nullptr) {
604
12
    obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
605
  }
606
607
4
  return e;
608
}
609
610
611
19581
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
612
#ifdef _WIN32
613
  if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
614
    return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
615
                          String::NewFromUtf8(isolate, path + 8));
616
  } else if (strncmp(path, "\\\\?\\", 4) == 0) {
617
    return String::NewFromUtf8(isolate, path + 4);
618
  }
619
#endif
620
621
19581
  return String::NewFromUtf8(isolate, path);
622
}
623
624
625
Local<Value> UVException(Isolate* isolate,
626
                         int errorno,
627
                         const char* syscall,
628
                         const char* msg,
629
                         const char* path) {
630
  return UVException(isolate, errorno, syscall, msg, path, nullptr);
631
}
632
633
634
19526
Local<Value> UVException(Isolate* isolate,
635
                         int errorno,
636
                         const char* syscall,
637
                         const char* msg,
638
                         const char* path,
639
                         const char* dest) {
640
19526
  Environment* env = Environment::GetCurrent(isolate);
641
642

19526
  if (!msg || !msg[0])
643
19526
    msg = uv_strerror(errorno);
644
645
19526
  Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
646
19526
  Local<String> js_syscall = OneByteString(isolate, syscall);
647
  Local<String> js_path;
648
  Local<String> js_dest;
649
650
19526
  Local<String> js_msg = js_code;
651
19526
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
652
19526
  js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
653
19526
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
654
19526
  js_msg = String::Concat(js_msg, js_syscall);
655
656
19526
  if (path != nullptr) {
657
19505
    js_path = StringFromPath(isolate, path);
658
659
19505
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
660
19505
    js_msg = String::Concat(js_msg, js_path);
661
19505
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
662
  }
663
664
19526
  if (dest != nullptr) {
665
76
    js_dest = StringFromPath(isolate, dest);
666
667
76
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
668
76
    js_msg = String::Concat(js_msg, js_dest);
669
76
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
670
  }
671
672
39052
  Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
673
674
58578
  e->Set(env->errno_string(), Integer::New(isolate, errorno));
675
39052
  e->Set(env->code_string(), js_code);
676
39052
  e->Set(env->syscall_string(), js_syscall);
677
19526
  if (!js_path.IsEmpty())
678
39010
    e->Set(env->path_string(), js_path);
679
19526
  if (!js_dest.IsEmpty())
680
152
    e->Set(env->dest_string(), js_dest);
681
682
19526
  return e;
683
}
684
685
686
// Look up environment variable unless running as setuid root.
687
23652
bool SafeGetenv(const char* key, std::string* text) {
688
#if !defined(__CloudABI__) && !defined(_WIN32)
689


23652
  if (linux_at_secure || getuid() != geteuid() || getgid() != getegid())
690
    goto fail;
691
#endif
692
693
23652
  if (const char* value = getenv(key)) {
694
47
    *text = value;
695
47
    return true;
696
  }
697
698
fail:
699
23605
  text->clear();
700
23605
  return false;
701
}
702
703
704
#ifdef _WIN32
705
// Does about the same as strerror(),
706
// but supports all windows error messages
707
static const char *winapi_strerror(const int errorno, bool* must_free) {
708
  char *errmsg = nullptr;
709
710
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
711
      FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
712
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
713
714
  if (errmsg) {
715
    *must_free = true;
716
717
    // Remove trailing newlines
718
    for (int i = strlen(errmsg) - 1;
719
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
720
      errmsg[i] = '\0';
721
    }
722
723
    return errmsg;
724
  } else {
725
    // FormatMessage failed
726
    *must_free = false;
727
    return "Unknown error";
728
  }
729
}
730
731
732
Local<Value> WinapiErrnoException(Isolate* isolate,
733
                                  int errorno,
734
                                  const char* syscall,
735
                                  const char* msg,
736
                                  const char* path) {
737
  Environment* env = Environment::GetCurrent(isolate);
738
  Local<Value> e;
739
  bool must_free = false;
740
  if (!msg || !msg[0]) {
741
    msg = winapi_strerror(errorno, &must_free);
742
  }
743
  Local<String> message = OneByteString(env->isolate(), msg);
744
745
  if (path) {
746
    Local<String> cons1 =
747
        String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
748
    Local<String> cons2 =
749
        String::Concat(cons1, String::NewFromUtf8(isolate, path));
750
    Local<String> cons3 =
751
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
752
    e = Exception::Error(cons3);
753
  } else {
754
    e = Exception::Error(message);
755
  }
756
757
  Local<Object> obj = e.As<Object>();
758
  obj->Set(env->errno_string(), Integer::New(isolate, errorno));
759
760
  if (path != nullptr) {
761
    obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
762
  }
763
764
  if (syscall != nullptr) {
765
    obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
766
  }
767
768
  if (must_free)
769
    LocalFree((HLOCAL)msg);
770
771
  return e;
772
}
773
#endif
774
775
776
74170
void* ArrayBufferAllocator::Allocate(size_t size) {
777

74170
  if (zero_fill_field_ || zero_fill_all_buffers)
778
19624
    return node::UncheckedCalloc(size);
779
  else
780
54546
    return node::UncheckedMalloc(size);
781
}
782
783
namespace {
784
785
32
bool ShouldAbortOnUncaughtException(Isolate* isolate) {
786
32
  HandleScope scope(isolate);
787
32
  Environment* env = Environment::GetCurrent(isolate);
788

98
  return env->should_abort_on_uncaught_toggle()[0] &&
789
98
         !env->inside_should_not_abort_on_uncaught_scope();
790
}
791
792
793
3181
Local<Value> GetDomainProperty(Environment* env, Local<Object> object) {
794
  Local<Value> domain_v =
795
6362
      object->GetPrivate(env->context(), env->domain_private_symbol())
796
6362
          .ToLocalChecked();
797
3181
  if (domain_v->IsObject()) {
798
    return domain_v;
799
  }
800
12724
  return object->Get(env->context(), env->domain_string()).ToLocalChecked();
801
}
802
803
804
2109
void DomainEnter(Environment* env, Local<Object> object) {
805
2109
  Local<Value> domain_v = GetDomainProperty(env, object);
806
2109
  if (domain_v->IsObject()) {
807
24
    Local<Object> domain = domain_v.As<Object>();
808
48
    Local<Value> enter_v = domain->Get(env->enter_string());
809
24
    if (enter_v->IsFunction()) {
810
72
      if (enter_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
811
        FatalError("node::AsyncWrap::MakeCallback",
812
                   "domain enter callback threw, please report this");
813
      }
814
    }
815
  }
816
2109
}
817
818
819
1072
void DomainExit(Environment* env, v8::Local<v8::Object> object) {
820
1072
  Local<Value> domain_v = GetDomainProperty(env, object);
821
1072
  if (domain_v->IsObject()) {
822
18
    Local<Object> domain = domain_v.As<Object>();
823
36
    Local<Value> exit_v = domain->Get(env->exit_string());
824
18
    if (exit_v->IsFunction()) {
825
54
      if (exit_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
826
        FatalError("node::AsyncWrap::MakeCallback",
827
                  "domain exit callback threw, please report this");
828
      }
829
    }
830
  }
831
1072
}
832
833
144
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
834
144
  Environment* env = Environment::GetCurrent(args);
835
836
144
  if (env->using_domains())
837
144
    return;
838
144
  env->set_using_domains(true);
839
840
144
  HandleScope scope(env->isolate());
841
842
  // Do a little housekeeping.
843
  env->process_object()->Delete(
844
      env->context(),
845
720
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
846
}
847
848
849
78462
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
850
78462
  args.GetIsolate()->RunMicrotasks();
851
78456
}
852
853
854
3348
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
855
3348
  Environment* env = Environment::GetCurrent(args);
856
857
6696
  CHECK(args[0]->IsFunction());
858
859
6696
  env->set_push_values_to_array_function(args[0].As<Function>());
860
  env->process_object()->Delete(
861
      env->context(),
862
13392
      FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
863
3348
}
864
865
866
3348
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
867
3348
  Environment* env = Environment::GetCurrent(args);
868
869
6696
  CHECK(args[0]->IsFunction());
870
6696
  CHECK(args[1]->IsObject());
871
872
6696
  env->set_tick_callback_function(args[0].As<Function>());
873
874
6696
  env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
875
876
  // Do a little housekeeping.
877
  env->process_object()->Delete(
878
      env->context(),
879
16740
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust();
880
881
  // Values use to cross communicate with processNextTick.
882
3348
  uint32_t* const fields = env->tick_info()->fields();
883
3348
  uint32_t const fields_count = env->tick_info()->fields_count();
884
885
  Local<ArrayBuffer> array_buffer =
886
3348
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
887
888
10044
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
889
3348
}
890
891
7608
void PromiseRejectCallback(PromiseRejectMessage message) {
892
7608
  Local<Promise> promise = message.GetPromise();
893
7608
  Isolate* isolate = promise->GetIsolate();
894
7608
  Local<Value> value = message.GetValue();
895
7608
  Local<Integer> event = Integer::New(isolate, message.GetEvent());
896
897
7608
  Environment* env = Environment::GetCurrent(isolate);
898
7608
  Local<Function> callback = env->promise_reject_function();
899
900
7608
  if (value.IsEmpty())
901
106
    value = Undefined(isolate);
902
903
22824
  Local<Value> args[] = { event, promise, value };
904
7608
  Local<Object> process = env->process_object();
905
906
15216
  callback->Call(process, arraysize(args), args);
907
7608
}
908
909
3348
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
910
3348
  Environment* env = Environment::GetCurrent(args);
911
3348
  Isolate* isolate = env->isolate();
912
913
6696
  CHECK(args[0]->IsFunction());
914
915
3348
  isolate->SetPromiseRejectCallback(PromiseRejectCallback);
916
6696
  env->set_promise_reject_function(args[0].As<Function>());
917
918
  env->process_object()->Delete(
919
      env->context(),
920
13392
      FIXED_ONE_BYTE_STRING(isolate, "_setupPromises")).FromJust();
921
3348
}
922
923
}  // anonymous namespace
924
925
926
void AddPromiseHook(v8::Isolate* isolate, promise_hook_func fn, void* arg) {
927
  Environment* env = Environment::GetCurrent(isolate);
928
  env->AddPromiseHook(fn, arg);
929
}
930
931
13
CallbackScope::CallbackScope(Isolate* isolate,
932
                             Local<Object> object,
933
                             async_context asyncContext)
934
  : private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
935
                                       object,
936
13
                                       asyncContext)),
937
26
    try_catch_(isolate) {
938
13
  try_catch_.SetVerbose(true);
939
13
}
940
941
24
CallbackScope::~CallbackScope() {
942
12
  if (try_catch_.HasCaught())
943
1
    private_->MarkAsFailed();
944
12
  delete private_;
945
12
}
946
947
915
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
948
    : InternalCallbackScope(async_wrap->env(),
949
                            async_wrap->object(),
950
915
                            { async_wrap->get_async_id(),
951
915
                              async_wrap->get_trigger_async_id() }) {}
952
953
426310
InternalCallbackScope::InternalCallbackScope(Environment* env,
954
                                             Local<Object> object,
955
                                             const async_context& asyncContext,
956
                                             ResourceExpectation expect)
957
  : env_(env),
958
    async_context_(asyncContext),
959
    object_(object),
960
426310
    callback_scope_(env) {
961
426310
  if (expect == kRequireResource) {
962
425345
    CHECK(!object.IsEmpty());
963
  }
964
965
426310
  HandleScope handle_scope(env->isolate());
966
  // If you hit this assertion, you forgot to enter the v8::Context first.
967
426310
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
968
969


428440
  if (asyncContext.async_id == 0 && env->using_domains() &&
970
4260
      !object_.IsEmpty()) {
971
2109
    DomainEnter(env, object_);
972
  }
973
974
426310
  if (asyncContext.async_id != 0) {
975
    // No need to check a return value because the application will exit if
976
    // an exception occurs.
977
351379
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
978
  }
979
980
  env->async_hooks()->push_async_ids(async_context_.async_id,
981
426310
                               async_context_.trigger_async_id);
982
426310
  pushed_ids_ = true;
983
426310
}
984
985
852368
InternalCallbackScope::~InternalCallbackScope() {
986
426184
  Close();
987
426184
}
988
989
849450
void InternalCallbackScope::Close() {
990
1623796
  if (closed_) return;
991
426253
  closed_ = true;
992
426253
  HandleScope handle_scope(env_->isolate());
993
994
426253
  if (pushed_ids_)
995
426253
    env_->async_hooks()->pop_async_id(async_context_.async_id);
996
997
426253
  if (failed_) return;
998
999
425157
  if (async_context_.async_id != 0) {
1000
351284
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
1001
  }
1002
1003


426250
  if (async_context_.async_id == 0 && env_->using_domains() &&
1004
2186
      !object_.IsEmpty()) {
1005
1072
    DomainExit(env_, object_);
1006
  }
1007
1008
425157
  if (IsInnerMakeCallback()) {
1009
37498
    return;
1010
  }
1011
1012
387659
  Environment::TickInfo* tick_info = env_->tick_info();
1013
1014
387659
  if (tick_info->length() == 0) {
1015
312638
    env_->isolate()->RunMicrotasks();
1016
  }
1017
1018
  // Make sure the stack unwound properly. If there are nested MakeCallback's
1019
  // then it should return early and not reach this code.
1020
387656
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
1021
62565
    CHECK_EQ(env_->execution_async_id(), 0);
1022
62565
    CHECK_EQ(env_->trigger_async_id(), 0);
1023
  }
1024
1025
387656
  Local<Object> process = env_->process_object();
1026
1027
387656
  if (tick_info->length() == 0) {
1028
312555
    tick_info->set_index(0);
1029
312555
    return;
1030
  }
1031
1032
75101
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
1033
604
    CHECK_EQ(env_->execution_async_id(), 0);
1034
604
    CHECK_EQ(env_->trigger_async_id(), 0);
1035
  }
1036
1037
225237
  if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1038
21
    failed_ = true;
1039
75035
  }
1040
}
1041
1042
424417
MaybeLocal<Value> InternalMakeCallback(Environment* env,
1043
                                       Local<Object> recv,
1044
                                       const Local<Function> callback,
1045
                                       int argc,
1046
                                       Local<Value> argv[],
1047
                                       async_context asyncContext) {
1048
424417
  CHECK(!recv.IsEmpty());
1049
424417
  InternalCallbackScope scope(env, recv, asyncContext);
1050
424417
  if (scope.Failed()) {
1051
    return Undefined(env->isolate());
1052
  }
1053
1054
  MaybeLocal<Value> ret;
1055
1056
  {
1057
848834
    ret = callback->Call(env->context(), recv, argc, argv);
1058
1059
424361
    if (ret.IsEmpty()) {
1060
      // NOTE: For backwards compatibility with public API we return Undefined()
1061
      // if the top level call threw.
1062
1095
      scope.MarkAsFailed();
1063
2190
      return scope.IsInnerMakeCallback() ? ret : Undefined(env->isolate());
1064
    }
1065
  }
1066
1067
423266
  scope.Close();
1068
423197
  if (scope.Failed()) {
1069
42
    return Undefined(env->isolate());
1070
  }
1071
1072
423176
  return ret;
1073
}
1074
1075
1076
// Public MakeCallback()s
1077
1078
1079
6066
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1080
                               Local<Object> recv,
1081
                               const char* method,
1082
                               int argc,
1083
                               Local<Value> argv[],
1084
                               async_context asyncContext) {
1085
  Local<String> method_string =
1086
      String::NewFromUtf8(isolate, method, v8::NewStringType::kNormal)
1087
12132
          .ToLocalChecked();
1088
6066
  return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
1089
}
1090
1091
1092
73923
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1093
                               Local<Object> recv,
1094
                               Local<String> symbol,
1095
                               int argc,
1096
                               Local<Value> argv[],
1097
                               async_context asyncContext) {
1098
73923
  Local<Value> callback_v = recv->Get(symbol);
1099
73923
  if (callback_v.IsEmpty()) return Local<Value>();
1100
73923
  if (!callback_v->IsFunction()) return Local<Value>();
1101
73923
  Local<Function> callback = callback_v.As<Function>();
1102
73923
  return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
1103
}
1104
1105
1106
73975
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1107
                               Local<Object> recv,
1108
                               Local<Function> callback,
1109
                               int argc,
1110
                               Local<Value> argv[],
1111
                               async_context asyncContext) {
1112
  // Observe the following two subtleties:
1113
  //
1114
  // 1. The environment is retrieved from the callback function's context.
1115
  // 2. The context to enter is retrieved from the environment.
1116
  //
1117
  // Because of the AssignToContext() call in src/node_contextify.cc,
1118
  // the two contexts need not be the same.
1119
73975
  Environment* env = Environment::GetCurrent(callback->CreationContext());
1120
73975
  Context::Scope context_scope(env->context());
1121
  return InternalMakeCallback(env, recv, callback,
1122
147940
                              argc, argv, asyncContext);
1123
}
1124
1125
1126
// Legacy MakeCallback()s
1127
1128
Local<Value> MakeCallback(Isolate* isolate,
1129
                          Local<Object> recv,
1130
                          const char* method,
1131
                          int argc,
1132
                          Local<Value>* argv) {
1133
  EscapableHandleScope handle_scope(isolate);
1134
  return handle_scope.Escape(
1135
      MakeCallback(isolate, recv, method, argc, argv, {0, 0})
1136
          .FromMaybe(Local<Value>()));
1137
}
1138
1139
1140
5
Local<Value> MakeCallback(Isolate* isolate,
1141
    Local<Object> recv,
1142
    Local<String> symbol,
1143
    int argc,
1144
    Local<Value>* argv) {
1145
5
  EscapableHandleScope handle_scope(isolate);
1146
  return handle_scope.Escape(
1147
5
      MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
1148
15
          .FromMaybe(Local<Value>()));
1149
}
1150
1151
1152
24
Local<Value> MakeCallback(Isolate* isolate,
1153
    Local<Object> recv,
1154
    Local<Function> callback,
1155
    int argc,
1156
    Local<Value>* argv) {
1157
24
  EscapableHandleScope handle_scope(isolate);
1158
  return handle_scope.Escape(
1159
24
      MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
1160
72
          .FromMaybe(Local<Value>()));
1161
}
1162
1163
1164
245140
enum encoding ParseEncoding(const char* encoding,
1165
                            enum encoding default_encoding) {
1166

245140
  switch (encoding[0]) {
1167
    case 'u':
1168
      // utf8, utf16le
1169

109791
      if (encoding[1] == 't' && encoding[2] == 'f') {
1170
        // Skip `-`
1171
109600
        encoding += encoding[3] == '-' ? 4 : 3;
1172

109600
        if (encoding[0] == '8' && encoding[1] == '\0')
1173
109583
          return UTF8;
1174
17
        if (strncmp(encoding, "16le", 4) == 0)
1175
17
          return UCS2;
1176
1177
      // ucs2
1178

191
      } else if (encoding[1] == 'c' && encoding[2] == 's') {
1179
190
        encoding += encoding[3] == '-' ? 4 : 3;
1180

190
        if (encoding[0] == '2' && encoding[1] == '\0')
1181
190
          return UCS2;
1182
      }
1183
1
      break;
1184
    case 'l':
1185
      // latin1
1186
52344
      if (encoding[1] == 'a') {
1187
52342
        if (strncmp(encoding + 2, "tin1", 4) == 0)
1188
52342
          return LATIN1;
1189
      }
1190
2
      break;
1191
    case 'b':
1192
      // binary
1193
40601
      if (encoding[1] == 'i') {
1194
30
        if (strncmp(encoding + 2, "nary", 4) == 0)
1195
30
          return LATIN1;
1196
1197
      // buffer
1198
40571
      } else if (encoding[1] == 'u') {
1199
40292
        if (strncmp(encoding + 2, "ffer", 4) == 0)
1200
40292
          return BUFFER;
1201
      }
1202
279
      break;
1203
    case '\0':
1204
1
      return default_encoding;
1205
    default:
1206
42403
      break;
1207
  }
1208
1209
42685
  if (StringEqualNoCase(encoding, "utf8")) {
1210
    return UTF8;
1211
42685
  } else if (StringEqualNoCase(encoding, "utf-8")) {
1212
3
    return UTF8;
1213
42682
  } else if (StringEqualNoCase(encoding, "ascii")) {
1214
49
    return ASCII;
1215
42633
  } else if (StringEqualNoCase(encoding, "base64")) {
1216
277
    return BASE64;
1217
42356
  } else if (StringEqualNoCase(encoding, "ucs2")) {
1218
    return UCS2;
1219
42356
  } else if (StringEqualNoCase(encoding, "ucs-2")) {
1220
    return UCS2;
1221
42356
  } else if (StringEqualNoCase(encoding, "utf16le")) {
1222
    return UCS2;
1223
42356
  } else if (StringEqualNoCase(encoding, "utf-16le")) {
1224
    return UCS2;
1225
42356
  } else if (StringEqualNoCase(encoding, "latin1")) {
1226
    return LATIN1;
1227
42356
  } else if (StringEqualNoCase(encoding, "binary")) {
1228
    return LATIN1;  // BINARY is a deprecated alias of LATIN1.
1229
42356
  } else if (StringEqualNoCase(encoding, "buffer")) {
1230
    return BUFFER;
1231
42356
  } else if (StringEqualNoCase(encoding, "hex")) {
1232
42351
    return HEX;
1233
  } else {
1234
5
    return default_encoding;
1235
  }
1236
}
1237
1238
1239
249131
enum encoding ParseEncoding(Isolate* isolate,
1240
                            Local<Value> encoding_v,
1241
                            enum encoding default_encoding) {
1242
249131
  CHECK(!encoding_v.IsEmpty());
1243
1244
498262
  if (!encoding_v->IsString())
1245
3991
    return default_encoding;
1246
1247
245140
  node::Utf8Value encoding(isolate, encoding_v);
1248
1249
245140
  return ParseEncoding(*encoding, default_encoding);
1250
}
1251
1252
2
Local<Value> Encode(Isolate* isolate,
1253
                    const char* buf,
1254
                    size_t len,
1255
                    enum encoding encoding) {
1256
2
  CHECK_NE(encoding, UCS2);
1257
  Local<Value> error;
1258
  return StringBytes::Encode(isolate, buf, len, encoding, &error)
1259
4
      .ToLocalChecked();
1260
}
1261
1262
Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1263
  Local<Value> error;
1264
  return StringBytes::Encode(isolate, buf, len, &error)
1265
      .ToLocalChecked();
1266
}
1267
1268
// Returns -1 if the handle was not valid for decoding
1269
ssize_t DecodeBytes(Isolate* isolate,
1270
                    Local<Value> val,
1271
                    enum encoding encoding) {
1272
  HandleScope scope(isolate);
1273
1274
  return StringBytes::Size(isolate, val, encoding);
1275
}
1276
1277
// Returns number of bytes written.
1278
ssize_t DecodeWrite(Isolate* isolate,
1279
                    char* buf,
1280
                    size_t buflen,
1281
                    Local<Value> val,
1282
                    enum encoding encoding) {
1283
  return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1284
}
1285
1286
435
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
1287

870
  if (!er.IsEmpty() && er->IsObject()) {
1288
429
    Local<Object> err_obj = er.As<Object>();
1289
    auto maybe_value =
1290
858
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
1291
    Local<Value> decorated;
1292

858
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
1293
  }
1294
6
  return false;
1295
}
1296
1297
434
void AppendExceptionLine(Environment* env,
1298
                         Local<Value> er,
1299
                         Local<Message> message,
1300
                         enum ErrorHandlingMode mode) {
1301
434
  if (message.IsEmpty())
1302
127
    return;
1303
1304
434
  HandleScope scope(env->isolate());
1305
  Local<Object> err_obj;
1306

868
  if (!er.IsEmpty() && er->IsObject()) {
1307
428
    err_obj = er.As<Object>();
1308
  }
1309
1310
  // Print (filename):(line number): (message).
1311
434
  ScriptOrigin origin = message->GetScriptOrigin();
1312
741
  node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1313
434
  const char* filename_string = *filename;
1314
434
  int linenum = message->GetLineNumber();
1315
  // Print line of source code.
1316
1175
  node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1317
434
  const char* sourceline_string = *sourceline;
1318
434
  if (strstr(sourceline_string, "node-do-not-add-exception-line") != nullptr)
1319
117
    return;
1320
1321
  // Because of how node modules work, all scripts are wrapped with a
1322
  // "function (module, exports, __filename, ...) {"
1323
  // to provide script local variables.
1324
  //
1325
  // When reporting errors on the first line of a script, this wrapper
1326
  // function is leaked to the user. There used to be a hack here to
1327
  // truncate off the first 62 characters, but it caused numerous other
1328
  // problems when vm.runIn*Context() methods were used for non-module
1329
  // code.
1330
  //
1331
  // If we ever decide to re-instate such a hack, the following steps
1332
  // must be taken:
1333
  //
1334
  // 1. Pass a flag around to say "this code was wrapped"
1335
  // 2. Update the stack frame output so that it is also correct.
1336
  //
1337
  // It would probably be simpler to add a line rather than add some
1338
  // number of characters to the first line, since V8 truncates the
1339
  // sourceline to 78 characters, and we end up not providing very much
1340
  // useful debugging info to the user if we remove 62 characters.
1341
1342
  int script_start =
1343
1268
      (linenum - origin.ResourceLineOffset()->Value()) == 1 ?
1344

627
          origin.ResourceColumnOffset()->Value() : 0;
1345
951
  int start = message->GetStartColumn(env->context()).FromMaybe(0);
1346
951
  int end = message->GetEndColumn(env->context()).FromMaybe(0);
1347
317
  if (start >= script_start) {
1348
317
    CHECK_GE(end, start);
1349
317
    start -= script_start;
1350
317
    end -= script_start;
1351
  }
1352
1353
  char arrow[1024];
1354
317
  int max_off = sizeof(arrow) - 2;
1355
1356
  int off = snprintf(arrow,
1357
                     sizeof(arrow),
1358
                     "%s:%i\n%s\n",
1359
                     filename_string,
1360
                     linenum,
1361
317
                     sourceline_string);
1362
317
  CHECK_GE(off, 0);
1363
317
  if (off > max_off) {
1364
33
    off = max_off;
1365
  }
1366
1367
  // Print wavy underline (GetUnderline is deprecated).
1368
9805
  for (int i = 0; i < start; i++) {
1369

9525
    if (sourceline_string[i] == '\0' || off >= max_off) {
1370
      break;
1371
    }
1372
9488
    CHECK_LT(off, max_off);
1373
9488
    arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1374
  }
1375
1043
  for (int i = start; i < end; i++) {
1376

783
    if (sourceline_string[i] == '\0' || off >= max_off) {
1377
      break;
1378
    }
1379
726
    CHECK_LT(off, max_off);
1380
726
    arrow[off++] = '^';
1381
  }
1382
317
  CHECK_LE(off, max_off);
1383
317
  arrow[off] = '\n';
1384
317
  arrow[off + 1] = '\0';
1385
1386
317
  Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1387
1388

634
  const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
1389
  // If allocating arrow_str failed, print it out. There's not much else to do.
1390
  // If it's not an error, but something needs to be printed out because
1391
  // it's a fatal exception, also print it out from here.
1392
  // Otherwise, the arrow property will be attached to the object and handled
1393
  // by the caller.
1394


403
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
1395
10
    if (env->printed_error())
1396
      return;
1397
10
    env->set_printed_error(true);
1398
1399
10
    uv_tty_reset_mode();
1400
10
    PrintErrorString("\n%s", arrow);
1401
10
    return;
1402
  }
1403
1404

1228
  CHECK(err_obj->SetPrivate(
1405
            env->context(),
1406
            env->arrow_message_private_symbol(),
1407
307
            arrow_str).FromMaybe(false));
1408
}
1409
1410
1411
118
static void ReportException(Environment* env,
1412
                            Local<Value> er,
1413
                            Local<Message> message) {
1414
118
  CHECK(!er.IsEmpty());
1415
118
  CHECK(!message.IsEmpty());
1416
118
  HandleScope scope(env->isolate());
1417
1418
118
  AppendExceptionLine(env, er, message, FATAL_ERROR);
1419
1420
  Local<Value> trace_value;
1421
  Local<Value> arrow;
1422
118
  const bool decorated = IsExceptionDecorated(env, er);
1423
1424

470
  if (er->IsUndefined() || er->IsNull()) {
1425
4
    trace_value = Undefined(env->isolate());
1426
  } else {
1427
348
    Local<Object> err_obj = er->ToObject(env->context()).ToLocalChecked();
1428
1429
232
    trace_value = err_obj->Get(env->stack_string());
1430
    arrow =
1431
        err_obj->GetPrivate(
1432
            env->context(),
1433
348
            env->arrow_message_private_symbol()).ToLocalChecked();
1434
  }
1435
1436
236
  node::Utf8Value trace(env->isolate(), trace_value);
1437
1438
  // range errors have a trace member set to undefined
1439

354
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1440


324
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1441
45
      PrintErrorString("%s\n", *trace);
1442
    } else {
1443
63
      node::Utf8Value arrow_string(env->isolate(), arrow);
1444
63
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1445
    }
1446
  } else {
1447
    // this really only happens for RangeErrors, since they're the only
1448
    // kind that won't have all this info in the trace, or when non-Error
1449
    // objects are thrown manually.
1450
    Local<Value> message;
1451
    Local<Value> name;
1452
1453
10
    if (er->IsObject()) {
1454
4
      Local<Object> err_obj = er.As<Object>();
1455
8
      message = err_obj->Get(env->message_string());
1456
8
      name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1457
    }
1458
1459

24
    if (message.IsEmpty() ||
1460
9
        message->IsUndefined() ||
1461

12
        name.IsEmpty() ||
1462
2
        name->IsUndefined()) {
1463
      // Not an error object. Just print as-is.
1464
9
      String::Utf8Value message(er);
1465
1466
9
      PrintErrorString("%s\n", *message ? *message :
1467
9
                                          "<toString() threw exception>");
1468
    } else {
1469
1
      node::Utf8Value name_string(env->isolate(), name);
1470
2
      node::Utf8Value message_string(env->isolate(), message);
1471
1472


3
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1473
1
        PrintErrorString("%s: %s\n", *name_string, *message_string);
1474
      } else {
1475
        node::Utf8Value arrow_string(env->isolate(), arrow);
1476
        PrintErrorString("%s\n%s: %s\n",
1477
                         *arrow_string,
1478
                         *name_string,
1479
                         *message_string);
1480
1
      }
1481
    }
1482
  }
1483
1484
118
  fflush(stderr);
1485
1486
#if HAVE_INSPECTOR
1487
236
  env->inspector_agent()->FatalException(er, message);
1488
#endif
1489
118
}
1490
1491
1492
2
static void ReportException(Environment* env, const TryCatch& try_catch) {
1493
2
  ReportException(env, try_catch.Exception(), try_catch.Message());
1494
2
}
1495
1496
1497
// Executes a str within the current v8 context.
1498
3348
static Local<Value> ExecuteString(Environment* env,
1499
                                  Local<String> source,
1500
                                  Local<String> filename) {
1501
3348
  EscapableHandleScope scope(env->isolate());
1502
6696
  TryCatch try_catch(env->isolate());
1503
1504
  // try_catch must be nonverbose to disable FatalException() handler,
1505
  // we will handle exceptions ourself.
1506
3348
  try_catch.SetVerbose(false);
1507
1508
3348
  ScriptOrigin origin(filename);
1509
  MaybeLocal<v8::Script> script =
1510
3348
      v8::Script::Compile(env->context(), source, &origin);
1511
3348
  if (script.IsEmpty()) {
1512
    ReportException(env, try_catch);
1513
    exit(3);
1514
  }
1515
1516
6696
  Local<Value> result = script.ToLocalChecked()->Run();
1517
3348
  if (result.IsEmpty()) {
1518
    ReportException(env, try_catch);
1519
    exit(4);
1520
  }
1521
1522
3348
  return scope.Escape(result);
1523
}
1524
1525
1526
1
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1527
1
  Environment* env = Environment::GetCurrent(args);
1528
1529
1
  Local<Array> ary = Array::New(args.GetIsolate());
1530
1
  Local<Context> ctx = env->context();
1531
1
  Local<Function> fn = env->push_values_to_array_function();
1532
9
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1533
1
  size_t idx = 0;
1534
1535
13
  for (auto w : *env->req_wrap_queue()) {
1536
24
    if (w->persistent().IsEmpty())
1537
      continue;
1538
24
    argv[idx] = w->object();
1539
12
    if (++idx >= arraysize(argv)) {
1540
3
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1541
1
      idx = 0;
1542
    }
1543
  }
1544
1545
1
  if (idx > 0) {
1546
3
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1547
  }
1548
1549
2
  args.GetReturnValue().Set(ary);
1550
1
}
1551
1552
1553
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1554
// implemented here for consistency with GetActiveRequests().
1555
6
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1556
6
  Environment* env = Environment::GetCurrent(args);
1557
1558
6
  Local<Array> ary = Array::New(env->isolate());
1559
6
  Local<Context> ctx = env->context();
1560
6
  Local<Function> fn = env->push_values_to_array_function();
1561
54
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1562
6
  size_t idx = 0;
1563
1564
6
  Local<String> owner_sym = env->owner_string();
1565
1566
38
  for (auto w : *env->handle_wrap_queue()) {
1567

64
    if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
1568
4
      continue;
1569
28
    Local<Object> object = w->object();
1570
28
    Local<Value> owner = object->Get(owner_sym);
1571
56
    if (owner->IsUndefined())
1572
5
      owner = object;
1573
28
    argv[idx] = owner;
1574
28
    if (++idx >= arraysize(argv)) {
1575
6
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1576
2
      idx = 0;
1577
    }
1578
  }
1579
6
  if (idx > 0) {
1580
15
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1581
  }
1582
1583
12
  args.GetReturnValue().Set(ary);
1584
6
}
1585
1586
1587
NO_RETURN void Abort() {
1588
  DumpBacktrace(stderr);
1589
  fflush(stderr);
1590
  ABORT_NO_BACKTRACE();
1591
}
1592
1593
1594
NO_RETURN void Assert(const char* const (*args)[4]) {
1595
  auto filename = (*args)[0];
1596
  auto linenum = (*args)[1];
1597
  auto message = (*args)[2];
1598
  auto function = (*args)[3];
1599
1600
  char name[1024];
1601
  GetHumanReadableProcessName(&name);
1602
1603
  fprintf(stderr, "%s: %s:%s:%s%s Assertion `%s' failed.\n",
1604
          name, filename, linenum, function, *function ? ":" : "", message);
1605
  fflush(stderr);
1606
1607
  Abort();
1608
}
1609
1610
1611
static void Abort(const FunctionCallbackInfo<Value>& args) {
1612
  Abort();
1613
}
1614
1615
1616
110
static void Chdir(const FunctionCallbackInfo<Value>& args) {
1617
110
  Environment* env = Environment::GetCurrent(args);
1618
1619


544
  if (args.Length() != 1 || !args[0]->IsString()) {
1620
6
    return env->ThrowTypeError("Bad argument.");
1621
  }
1622
1623
107
  node::Utf8Value path(args.GetIsolate(), args[0]);
1624
107
  int err = uv_chdir(*path);
1625
107
  if (err) {
1626
    return env->ThrowUVException(err, "uv_chdir");
1627
107
  }
1628
}
1629
1630
1631
10850
static void Cwd(const FunctionCallbackInfo<Value>& args) {
1632
10850
  Environment* env = Environment::GetCurrent(args);
1633
#ifdef _WIN32
1634
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1635
  char buf[MAX_PATH * 4];
1636
#else
1637
  char buf[PATH_MAX];
1638
#endif
1639
1640
10850
  size_t cwd_len = sizeof(buf);
1641
10850
  int err = uv_cwd(buf, &cwd_len);
1642
10850
  if (err) {
1643
10863
    return env->ThrowUVException(err, "uv_cwd");
1644
  }
1645
1646
  Local<String> cwd = String::NewFromUtf8(env->isolate(),
1647
                                          buf,
1648
                                          String::kNormalString,
1649
10837
                                          cwd_len);
1650
21674
  args.GetReturnValue().Set(cwd);
1651
}
1652
1653
1654
1325
static void Umask(const FunctionCallbackInfo<Value>& args) {
1655
1325
  Environment* env = Environment::GetCurrent(args);
1656
  uint32_t old;
1657
1658


2665
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1659
1320
    old = umask(0);
1660
1320
    umask(static_cast<mode_t>(old));
1661


24
  } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1662
1
    return env->ThrowTypeError("argument must be an integer or octal string.");
1663
  } else {
1664
    int oct;
1665
8
    if (args[0]->IsInt32()) {
1666
4
      oct = args[0]->Uint32Value();
1667
    } else {
1668
2
      oct = 0;
1669
2
      node::Utf8Value str(env->isolate(), args[0]);
1670
1671
      // Parse the octal string.
1672

9
      for (size_t i = 0; i < str.length(); i++) {
1673
8
        char c = (*str)[i];
1674

8
        if (c > '7' || c < '0') {
1675
1
          return env->ThrowTypeError("invalid octal string");
1676
        }
1677
7
        oct *= 8;
1678
7
        oct += c - '0';
1679
1
      }
1680
    }
1681
3
    old = umask(static_cast<mode_t>(oct));
1682
  }
1683
1684
2646
  args.GetReturnValue().Set(old);
1685
}
1686
1687
1688
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
1689
1690
static const uid_t uid_not_found = static_cast<uid_t>(-1);
1691
static const gid_t gid_not_found = static_cast<gid_t>(-1);
1692
1693
1694
4
static uid_t uid_by_name(const char* name) {
1695
  struct passwd pwd;
1696
  struct passwd* pp;
1697
  char buf[8192];
1698
1699
4
  errno = 0;
1700
4
  pp = nullptr;
1701
1702

4
  if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1703
2
    return pp->pw_uid;
1704
  }
1705
1706
2
  return uid_not_found;
1707
}
1708
1709
1710
static char* name_by_uid(uid_t uid) {
1711
  struct passwd pwd;
1712
  struct passwd* pp;
1713
  char buf[8192];
1714
  int rc;
1715
1716
  errno = 0;
1717
  pp = nullptr;
1718
1719
  if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1720
      pp != nullptr) {
1721
    return strdup(pp->pw_name);
1722
  }
1723
1724
  if (rc == 0) {
1725
    errno = ENOENT;
1726
  }
1727
1728
  return nullptr;
1729
}
1730
1731
1732
2
static gid_t gid_by_name(const char* name) {
1733
  struct group pwd;
1734
  struct group* pp;
1735
  char buf[8192];
1736
1737
2
  errno = 0;
1738
2
  pp = nullptr;
1739
1740

2
  if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1741
    return pp->gr_gid;
1742
  }
1743
1744
2
  return gid_not_found;
1745
}
1746
1747
1748
#if 0  // For future use.
1749
static const char* name_by_gid(gid_t gid) {
1750
  struct group pwd;
1751
  struct group* pp;
1752
  char buf[8192];
1753
  int rc;
1754
1755
  errno = 0;
1756
  pp = nullptr;
1757
1758
  if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1759
      pp != nullptr) {
1760
    return strdup(pp->gr_name);
1761
  }
1762
1763
  if (rc == 0) {
1764
    errno = ENOENT;
1765
  }
1766
1767
  return nullptr;
1768
}
1769
#endif
1770
1771
1772
4
static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1773
4
  if (value->IsUint32()) {
1774
    return static_cast<uid_t>(value->Uint32Value());
1775
  } else {
1776
4
    node::Utf8Value name(isolate, value);
1777
4
    return uid_by_name(*name);
1778
  }
1779
}
1780
1781
1782
2
static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1783
2
  if (value->IsUint32()) {
1784
    return static_cast<gid_t>(value->Uint32Value());
1785
  } else {
1786
2
    node::Utf8Value name(isolate, value);
1787
2
    return gid_by_name(*name);
1788
  }
1789
}
1790
1791
366
static void GetUid(const FunctionCallbackInfo<Value>& args) {
1792
  // uid_t is an uint32_t on all supported platforms.
1793
1098
  args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1794
366
}
1795
1796
1797
353
static void GetGid(const FunctionCallbackInfo<Value>& args) {
1798
  // gid_t is an uint32_t on all supported platforms.
1799
1059
  args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1800
353
}
1801
1802
1803
1
static void GetEUid(const FunctionCallbackInfo<Value>& args) {
1804
  // uid_t is an uint32_t on all supported platforms.
1805
3
  args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
1806
1
}
1807
1808
1809
1
static void GetEGid(const FunctionCallbackInfo<Value>& args) {
1810
  // gid_t is an uint32_t on all supported platforms.
1811
3
  args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
1812
1
}
1813
1814
1815
1
static void SetGid(const FunctionCallbackInfo<Value>& args) {
1816
1
  Environment* env = Environment::GetCurrent(args);
1817
1818


6
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1819
    return env->ThrowTypeError("setgid argument must be a number or a string");
1820
  }
1821
1822
1
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1823
1824
1
  if (gid == gid_not_found) {
1825
1
    return env->ThrowError("setgid group id does not exist");
1826
  }
1827
1828
  if (setgid(gid)) {
1829
    return env->ThrowErrnoException(errno, "setgid");
1830
  }
1831
}
1832
1833
1834
1
static void SetEGid(const FunctionCallbackInfo<Value>& args) {
1835
1
  Environment* env = Environment::GetCurrent(args);
1836
1837


6
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1838
    return env->ThrowTypeError("setegid argument must be a number or string");
1839
  }
1840
1841
1
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1842
1843
1
  if (gid == gid_not_found) {
1844
1
    return env->ThrowError("setegid group id does not exist");
1845
  }
1846
1847
  if (setegid(gid)) {
1848
    return env->ThrowErrnoException(errno, "setegid");
1849
  }
1850
}
1851
1852
1853
2
static void SetUid(const FunctionCallbackInfo<Value>& args) {
1854
2
  Environment* env = Environment::GetCurrent(args);
1855
1856


12
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1857
    return env->ThrowTypeError("setuid argument must be a number or a string");
1858
  }
1859
1860
2
  uid_t uid = uid_by_name(env->isolate(), args[0]);
1861
1862
2
  if (uid == uid_not_found) {
1863
1
    return env->ThrowError("setuid user id does not exist");
1864
  }
1865
1866
1
  if (setuid(uid)) {
1867
1
    return env->ThrowErrnoException(errno, "setuid");
1868
  }
1869
}
1870
1871
1872
3
static void SetEUid(const FunctionCallbackInfo<Value>& args) {
1873
3
  Environment* env = Environment::GetCurrent(args);
1874
1875


18
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1876
1
    return env->ThrowTypeError("seteuid argument must be a number or string");
1877
  }
1878
1879
2
  uid_t uid = uid_by_name(env->isolate(), args[0]);
1880
1881
2
  if (uid == uid_not_found) {
1882
1
    return env->ThrowError("seteuid user id does not exist");
1883
  }
1884
1885
1
  if (seteuid(uid)) {
1886
1
    return env->ThrowErrnoException(errno, "seteuid");
1887
  }
1888
}
1889
1890
1891
2
static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1892
2
  Environment* env = Environment::GetCurrent(args);
1893
1894
2
  int ngroups = getgroups(0, nullptr);
1895
1896
2
  if (ngroups == -1) {
1897
    return env->ThrowErrnoException(errno, "getgroups");
1898
  }
1899
1900
2
  gid_t* groups = new gid_t[ngroups];
1901
1902
2
  ngroups = getgroups(ngroups, groups);
1903
1904
2
  if (ngroups == -1) {
1905
    delete[] groups;
1906
    return env->ThrowErrnoException(errno, "getgroups");
1907
  }
1908
1909
2
  Local<Array> groups_list = Array::New(env->isolate(), ngroups);
1910
2
  bool seen_egid = false;
1911
2
  gid_t egid = getegid();
1912
1913
4
  for (int i = 0; i < ngroups; i++) {
1914
6
    groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
1915
2
    if (groups[i] == egid)
1916
2
      seen_egid = true;
1917
  }
1918
1919
2
  delete[] groups;
1920
1921
2
  if (seen_egid == false) {
1922
    groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
1923
  }
1924
1925
4
  args.GetReturnValue().Set(groups_list);
1926
}
1927
1928
1929
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1930
  Environment* env = Environment::GetCurrent(args);
1931
1932
  if (!args[0]->IsArray()) {
1933
    return env->ThrowTypeError("argument 1 must be an array");
1934
  }
1935
1936
  Local<Array> groups_list = args[0].As<Array>();
1937
  size_t size = groups_list->Length();
1938
  gid_t* groups = new gid_t[size];
1939
1940
  for (size_t i = 0; i < size; i++) {
1941
    gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
1942
1943
    if (gid == gid_not_found) {
1944
      delete[] groups;
1945
      return env->ThrowError("group name not found");
1946
    }
1947
1948
    groups[i] = gid;
1949
  }
1950
1951
  int rc = setgroups(size, groups);
1952
  delete[] groups;
1953
1954
  if (rc == -1) {
1955
    return env->ThrowErrnoException(errno, "setgroups");
1956
  }
1957
}
1958
1959
1960
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
1961
  Environment* env = Environment::GetCurrent(args);
1962
1963
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1964
    return env->ThrowTypeError("argument 1 must be a number or a string");
1965
  }
1966
1967
  if (!args[1]->IsUint32() && !args[1]->IsString()) {
1968
    return env->ThrowTypeError("argument 2 must be a number or a string");
1969
  }
1970
1971
  node::Utf8Value arg0(env->isolate(), args[0]);
1972
  gid_t extra_group;
1973
  bool must_free;
1974
  char* user;
1975
1976
  if (args[0]->IsUint32()) {
1977
    user = name_by_uid(args[0]->Uint32Value());
1978
    must_free = true;
1979
  } else {
1980
    user = *arg0;
1981
    must_free = false;
1982
  }
1983
1984
  if (user == nullptr) {
1985
    return env->ThrowError("initgroups user not found");
1986
  }
1987
1988
  extra_group = gid_by_name(env->isolate(), args[1]);
1989
1990
  if (extra_group == gid_not_found) {
1991
    if (must_free)
1992
      free(user);
1993
    return env->ThrowError("initgroups extra group not found");
1994
  }
1995
1996
  int rc = initgroups(user, extra_group);
1997
1998
  if (must_free) {
1999
    free(user);
2000
  }
2001
2002
  if (rc) {
2003
    return env->ThrowErrnoException(errno, "initgroups");
2004
  }
2005
}
2006
2007
#endif  // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
2008
2009
2010
3222
static void WaitForInspectorDisconnect(Environment* env) {
2011
#if HAVE_INSPECTOR
2012
3222
  if (env->inspector_agent()->delegate() != nullptr) {
2013
    // Restore signal dispositions, the app is done and is no longer
2014
    // capable of handling signals.
2015
#if defined(__POSIX__) && !defined(NODE_SHARED_MODE)
2016
    struct sigaction act;
2017
11
    memset(&act, 0, sizeof(act));
2018
352
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
2019

341
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
2020
33
        continue;
2021
308
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
2022
308
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
2023
    }
2024
#endif
2025
11
    env->inspector_agent()->WaitForDisconnect();
2026
  }
2027
#endif
2028
3222
}
2029
2030
2031
219
static void Exit(const FunctionCallbackInfo<Value>& args) {
2032
219
  WaitForInspectorDisconnect(Environment::GetCurrent(args));
2033
438
  exit(args[0]->Int32Value());
2034
}
2035
2036
2037
3
static void Uptime(const FunctionCallbackInfo<Value>& args) {
2038
3
  Environment* env = Environment::GetCurrent(args);
2039
  double uptime;
2040
2041
3
  uv_update_time(env->event_loop());
2042
3
  uptime = uv_now(env->event_loop()) - prog_start_time;
2043
2044
9
  args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2045
3
}
2046
2047
2048
7
static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2049
7
  Environment* env = Environment::GetCurrent(args);
2050
2051
  size_t rss;
2052
7
  int err = uv_resident_set_memory(&rss);
2053
7
  if (err) {
2054
7
    return env->ThrowUVException(err, "uv_resident_set_memory");
2055
  }
2056
2057
7
  Isolate* isolate = env->isolate();
2058
  // V8 memory usage
2059
7
  HeapStatistics v8_heap_stats;
2060
7
  isolate->GetHeapStatistics(&v8_heap_stats);
2061
2062
  // Get the double array pointer from the Float64Array argument.
2063
14
  CHECK(args[0]->IsFloat64Array());
2064
14
  Local<Float64Array> array = args[0].As<Float64Array>();
2065
7
  CHECK_EQ(array->Length(), 4);
2066
7
  Local<ArrayBuffer> ab = array->Buffer();
2067
7
  double* fields = static_cast<double*>(ab->GetContents().Data());
2068
2069
7
  fields[0] = rss;
2070
7
  fields[1] = v8_heap_stats.total_heap_size();
2071
7
  fields[2] = v8_heap_stats.used_heap_size();
2072
14
  fields[3] = isolate->AdjustAmountOfExternalAllocatedMemory(0);
2073
}
2074
2075
2076
45
static void Kill(const FunctionCallbackInfo<Value>& args) {
2077
45
  Environment* env = Environment::GetCurrent(args);
2078
2079
45
  if (args.Length() != 2) {
2080
45
    return env->ThrowError("Bad argument.");
2081
  }
2082
2083
90
  int pid = args[0]->Int32Value();
2084
90
  int sig = args[1]->Int32Value();
2085
45
  int err = uv_kill(pid, sig);
2086
90
  args.GetReturnValue().Set(err);
2087
}
2088
2089
// used in Hrtime() below
2090
#define NANOS_PER_SEC 1000000000
2091
2092
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2093
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2094
// so this function instead fills in an Uint32Array with 3 entries,
2095
// to avoid any integer overflow possibility.
2096
// The first two entries contain the second part of the value
2097
// broken into the upper/lower 32 bits to be converted back in JS,
2098
// because there is no Uint64Array in JS.
2099
// The third entry contains the remaining nanosecond part of the value.
2100
243463
static void Hrtime(const FunctionCallbackInfo<Value>& args) {
2101
243463
  uint64_t t = uv_hrtime();
2102
2103
730389
  Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
2104
243463
  uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
2105
2106
243463
  fields[0] = (t / NANOS_PER_SEC) >> 32;
2107
243463
  fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
2108
243463
  fields[2] = t % NANOS_PER_SEC;
2109
243463
}
2110
2111
// Microseconds in a second, as a float, used in CPUUsage() below
2112
#define MICROS_PER_SEC 1e6
2113
2114
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
2115
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
2116
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
2117
// Returns those values as Float64 microseconds in the elements of the array
2118
// passed to the function.
2119
33
static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
2120
  uv_rusage_t rusage;
2121
2122
  // Call libuv to get the values we'll return.
2123
33
  int err = uv_getrusage(&rusage);
2124
33
  if (err) {
2125
    // On error, return the strerror version of the error code.
2126
    Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
2127
    args.GetReturnValue().Set(errmsg);
2128
33
    return;
2129
  }
2130
2131
  // Get the double array pointer from the Float64Array argument.
2132
66
  CHECK(args[0]->IsFloat64Array());
2133
66
  Local<Float64Array> array = args[0].As<Float64Array>();
2134
33
  CHECK_EQ(array->Length(), 2);
2135
33
  Local<ArrayBuffer> ab = array->Buffer();
2136
33
  double* fields = static_cast<double*>(ab->GetContents().Data());
2137
2138
  // Set the Float64Array elements to be user / system values in microseconds.
2139
33
  fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
2140
33
  fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
2141
}
2142
2143
111993
extern "C" void node_module_register(void* m) {
2144
111993
  struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2145
2146
111993
  if (mp->nm_flags & NM_F_BUILTIN) {
2147
108512
    mp->nm_link = modlist_builtin;
2148
108512
    modlist_builtin = mp;
2149
3481
  } else if (mp->nm_flags & NM_F_INTERNAL) {
2150
3391
    mp->nm_link = modlist_internal;
2151
3391
    modlist_internal = mp;
2152
90
  } else if (!node_is_initialized) {
2153
    // "Linked" modules are included as part of the node project.
2154
    // Like builtins they are registered *before* node::Init runs.
2155
    mp->nm_flags = NM_F_LINKED;
2156
    mp->nm_link = modlist_linked;
2157
    modlist_linked = mp;
2158
  } else {
2159
90
    modpending = mp;
2160
  }
2161
111993
}
2162
2163
93414
inline struct node_module* FindModule(struct node_module* list,
2164
                                      const char* name,
2165
                                      int flag) {
2166
  struct node_module* mp;
2167
2168
1613035
  for (mp = list; mp != nullptr; mp = mp->nm_link) {
2169
1606333
    if (strcmp(mp->nm_modname, name) == 0)
2170
86712
      break;
2171
  }
2172
2173

93414
  CHECK(mp == nullptr || (mp->nm_flags & flag) != 0);
2174
93414
  return mp;
2175
}
2176
2177
90066
node_module* get_builtin_module(const char* name) {
2178
90066
  return FindModule(modlist_builtin, name, NM_F_BUILTIN);
2179
}
2180
3348
node_module* get_internal_module(const char* name) {
2181
3348
  return FindModule(modlist_internal, name, NM_F_INTERNAL);
2182
}
2183
node_module* get_linked_module(const char* name) {
2184
  return FindModule(modlist_linked, name, NM_F_LINKED);
2185
}
2186
2187
190
struct DLib {
2188
  std::string filename_;
2189
  std::string errmsg_;
2190
  void* handle_;
2191
  int flags_;
2192
2193
#ifdef __POSIX__
2194
  static const int kDefaultFlags = RTLD_LAZY;
2195
2196
95
  bool Open() {
2197
95
    handle_ = dlopen(filename_.c_str(), flags_);
2198
95
    if (handle_ != nullptr)
2199
92
      return true;
2200
3
    errmsg_ = dlerror();
2201
3
    return false;
2202
  }
2203
2204
7
  void Close() {
2205
7
    if (handle_ != nullptr)
2206
4
      dlclose(handle_);
2207
7
  }
2208
#else  // !__POSIX__
2209
  static const int kDefaultFlags = 0;
2210
  uv_lib_t lib_;
2211
2212
  bool Open() {
2213
    int ret = uv_dlopen(filename_.c_str(), &lib_);
2214
    if (ret == 0) {
2215
      handle_ = static_cast<void*>(lib_.handle);
2216
      return true;
2217
    }
2218
    errmsg_ = uv_dlerror(&lib_);
2219
    uv_dlclose(&lib_);
2220
    return false;
2221
  }
2222
2223
  void Close() {
2224
    uv_dlclose(&lib_);
2225
  }
2226
#endif  // !__POSIX__
2227
};
2228
2229
// DLOpen is process.dlopen(module, filename, flags).
2230
// Used to load 'module.node' dynamically shared objects.
2231
//
2232
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2233
// when two contexts try to load the same shared object. Maybe have a shadow
2234
// cache that's a plain C list or hash table that's shared across contexts?
2235
95
static void DLOpen(const FunctionCallbackInfo<Value>& args) {
2236
95
  Environment* env = Environment::GetCurrent(args);
2237
2238
95
  CHECK_EQ(modpending, nullptr);
2239
2240
95
  if (args.Length() < 2) {
2241
    env->ThrowError("process.dlopen needs at least 2 arguments.");
2242
    return;
2243
  }
2244
2245
95
  int32_t flags = DLib::kDefaultFlags;
2246


193
  if (args.Length() > 2 && !args[2]->Int32Value(env->context()).To(&flags)) {
2247
    return env->ThrowTypeError("flag argument must be an integer.");
2248
  }
2249
2250
  Local<Object> module =
2251
380
      args[0]->ToObject(env->context()).ToLocalChecked();  // Cast
2252
95
  node::Utf8Value filename(env->isolate(), args[1]);  // Cast
2253
183
  DLib dlib;
2254
95
  dlib.filename_ = *filename;
2255
95
  dlib.flags_ = flags;
2256
95
  bool is_opened = dlib.Open();
2257
2258
  // Objects containing v14 or later modules will have registered themselves
2259
  // on the pending list.  Activate all of them now.  At present, only one
2260
  // module per object is supported.
2261
95
  node_module* const mp = modpending;
2262
95
  modpending = nullptr;
2263
2264
95
  if (!is_opened) {
2265
3
    Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str());
2266
3
    dlib.Close();
2267
#ifdef _WIN32
2268
    // Windows needs to add the filename into the error message
2269
    errmsg = String::Concat(errmsg,
2270
                            args[1]->ToString(env->context()).ToLocalChecked());
2271
#endif  // _WIN32
2272
3
    env->isolate()->ThrowException(Exception::Error(errmsg));
2273
3
    return;
2274
  }
2275
2276
92
  if (mp == nullptr) {
2277
2
    dlib.Close();
2278
2
    env->ThrowError("Module did not self-register.");
2279
2
    return;
2280
  }
2281
90
  if (mp->nm_version == -1) {
2282
45
    if (env->EmitNapiWarning()) {
2283
86
      if (ProcessEmitWarning(env, "N-API is an experimental feature and could "
2284
86
                                  "change at any time.").IsNothing()) {
2285
        dlib.Close();
2286
        return;
2287
      }
2288
    }
2289
45
  } else if (mp->nm_version != NODE_MODULE_VERSION) {
2290
    char errmsg[1024];
2291
    snprintf(errmsg,
2292
             sizeof(errmsg),
2293
             "The module '%s'"
2294
             "\nwas compiled against a different Node.js version using"
2295
             "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
2296
             "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
2297
             "re-installing\nthe module (for instance, using `npm rebuild` "
2298
             "or `npm install`).",
2299
1
             *filename, mp->nm_version, NODE_MODULE_VERSION);
2300
2301
    // NOTE: `mp` is allocated inside of the shared library's memory, calling
2302
    // `dlclose` will deallocate it
2303
1
    dlib.Close();
2304
1
    env->ThrowError(errmsg);
2305
1
    return;
2306
  }
2307
89
  if (mp->nm_flags & NM_F_BUILTIN) {
2308
    dlib.Close();
2309
    env->ThrowError("Built-in module self-registered.");
2310
    return;
2311
  }
2312
2313
89
  mp->nm_dso_handle = dlib.handle_;
2314
89
  mp->nm_link = modlist_addon;
2315
89
  modlist_addon = mp;
2316
2317
89
  Local<String> exports_string = env->exports_string();
2318
  MaybeLocal<Value> maybe_exports =
2319
178
      module->Get(env->context(), exports_string);
2320
2321

445
  if (maybe_exports.IsEmpty() ||
2322

534
      maybe_exports.ToLocalChecked()->ToObject(env->context()).IsEmpty()) {
2323
1
    dlib.Close();
2324
1
    return;
2325
  }
2326
2327
  Local<Object> exports =
2328
352
      maybe_exports.ToLocalChecked()->ToObject(env->context())
2329
264
          .FromMaybe(Local<Object>());
2330
2331
88
  if (mp->nm_context_register_func != nullptr) {
2332
94
    mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2333
41
  } else if (mp->nm_register_func != nullptr) {
2334
82
    mp->nm_register_func(exports, module, mp->nm_priv);
2335
  } else {
2336
    dlib.Close();
2337
    env->ThrowError("Module has no declared entry point.");
2338
    return;
2339
88
  }
2340
2341
  // Tell coverity that 'handle' should not be freed when we return.
2342
  // coverity[leaked_storage]
2343
}
2344
2345
2346
static void OnFatalError(const char* location, const char* message) {
2347
  if (location) {
2348
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2349
  } else {
2350
    PrintErrorString("FATAL ERROR: %s\n", message);
2351
  }
2352
  fflush(stderr);
2353
  ABORT();
2354
}
2355
2356
2357
NO_RETURN void FatalError(const char* location, const char* message) {
2358
  OnFatalError(location, message);
2359
  // to suppress compiler warning
2360
  ABORT();
2361
}
2362
2363
2364
132602
FatalTryCatch::~FatalTryCatch() {
2365
66301
  if (HasCaught()) {
2366
    HandleScope scope(env_->isolate());
2367
    ReportException(env_, *this);
2368
    exit(7);
2369
  }
2370
66301
}
2371
2372
2373
1265
void FatalException(Isolate* isolate,
2374
                    Local<Value> error,
2375
                    Local<Message> message) {
2376
1265
  HandleScope scope(isolate);
2377
2378
1265
  Environment* env = Environment::GetCurrent(isolate);
2379
1265
  Local<Object> process_object = env->process_object();
2380
1265
  Local<String> fatal_exception_string = env->fatal_exception_string();
2381
  Local<Function> fatal_exception_function =
2382
2530
      process_object->Get(fatal_exception_string).As<Function>();
2383
2384
1265
  int exit_code = 0;
2385
1265
  if (!fatal_exception_function->IsFunction()) {
2386
    // failed before the process._fatalException function was added!
2387
    // this is probably pretty bad.  Nothing to do but report and exit.
2388
    ReportException(env, error, message);
2389
    exit_code = 6;
2390
  }
2391
2392
1265
  if (exit_code == 0) {
2393
1265
    TryCatch fatal_try_catch(isolate);
2394
2395
    // Do not call FatalException when _fatalException handler throws
2396
1265
    fatal_try_catch.SetVerbose(false);
2397
2398
    // this will return true if the JS layer handled it, false otherwise
2399
    Local<Value> caught =
2400
1265
        fatal_exception_function->Call(process_object, 1, &error);
2401
2402
1263
    if (fatal_try_catch.HasCaught()) {
2403
      // the fatal exception function threw, so we must exit
2404
2
      ReportException(env, fatal_try_catch);
2405
2
      exit_code = 7;
2406
    }
2407
2408

2524
    if (exit_code == 0 && false == caught->BooleanValue()) {
2409
116
      ReportException(env, error, message);
2410
116
      exit_code = 1;
2411
1263
    }
2412
  }
2413
2414
1263
  if (exit_code) {
2415
118
    exit(exit_code);
2416
1145
  }
2417
1145
}
2418
2419
2420
2
void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2421
2
  HandleScope scope(isolate);
2422
2
  if (!try_catch.IsVerbose()) {
2423
2
    FatalException(isolate, try_catch.Exception(), try_catch.Message());
2424
1
  }
2425
1
}
2426
2427
2428
1263
static void OnMessage(Local<Message> message, Local<Value> error) {
2429
  // The current version of V8 sends messages for errors only
2430
  // (thus `error` is always set).
2431
1263
  FatalException(Isolate::GetCurrent(), error, message);
2432
1144
}
2433
2434
50
static Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
2435
                                             const char* warning,
2436
                                             const char* type = nullptr,
2437
                                             const char* code = nullptr) {
2438
50
  HandleScope handle_scope(env->isolate());
2439
50
  Context::Scope context_scope(env->context());
2440
2441
50
  Local<Object> process = env->process_object();
2442
  Local<Value> emit_warning;
2443
100
  if (!process->Get(env->context(),
2444
250
                    env->emit_warning_string()).ToLocal(&emit_warning)) {
2445
1
    return Nothing<bool>();
2446
  }
2447
2448
49
  if (!emit_warning->IsFunction()) return Just(false);
2449
2450
49
  int argc = 0;
2451
196
  Local<Value> args[3];  // warning, type, code
2452
2453
  // The caller has to be able to handle a failure anyway, so we might as well
2454
  // do proper error checking for string creation.
2455
98
  if (!String::NewFromUtf8(env->isolate(),
2456
                           warning,
2457
147
                           v8::NewStringType::kNormal).ToLocal(&args[argc++])) {
2458
    return Nothing<bool>();
2459
  }
2460
49
  if (type != nullptr) {
2461
    if (!String::NewFromOneByte(env->isolate(),
2462
                                reinterpret_cast<const uint8_t*>(type),
2463
                                v8::NewStringType::kNormal)
2464
                                    .ToLocal(&args[argc++])) {
2465
      return Nothing<bool>();
2466
    }
2467
    if (code != nullptr &&
2468
        !String::NewFromOneByte(env->isolate(),
2469
                                reinterpret_cast<const uint8_t*>(code),
2470
                                v8::NewStringType::kNormal)
2471
                                    .ToLocal(&args[argc++])) {
2472
      return Nothing<bool>();
2473
    }
2474
  }
2475
2476
  // MakeCallback() unneeded because emitWarning is internal code, it calls
2477
  // process.emit('warning', ...), but does so on the nextTick.
2478
98
  if (emit_warning.As<Function>()->Call(env->context(),
2479
                                        process,
2480
                                        argc,
2481
196
                                        args).IsEmpty()) {
2482
1
    return Nothing<bool>();
2483
  }
2484
98
  return Just(true);
2485
}
2486
2487
2488
// Call process.emitWarning(str), fmt is a snprintf() format string
2489
50
Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...) {
2490
  char warning[1024];
2491
  va_list ap;
2492
2493
50
  va_start(ap, fmt);
2494
50
  vsnprintf(warning, sizeof(warning), fmt, ap);
2495
50
  va_end(ap);
2496
2497
50
  return ProcessEmitWarningGeneric(env, warning);
2498
}
2499
2500
2501
Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
2502
                                          const char* warning,
2503
                                          const char* deprecation_code) {
2504
  return ProcessEmitWarningGeneric(env,
2505
                                   warning,
2506
                                   "DeprecationWarning",
2507
                                   deprecation_code);
2508
}
2509
2510
2511
305488
static bool PullFromCache(Environment* env,
2512
                          const FunctionCallbackInfo<Value>& args,
2513
                          Local<String> module,
2514
                          Local<Object> cache) {
2515
305488
  Local<Context> context = env->context();
2516
  Local<Value> exports_v;
2517
  Local<Object> exports;
2518


1832928
  if (cache->Get(context, module).ToLocal(&exports_v) &&
2519

1652804
      exports_v->IsObject() &&
2520
736340
      exports_v->ToObject(context).ToLocal(&exports)) {
2521
430852
    args.GetReturnValue().Set(exports);
2522
215426
    return true;
2523
  }
2524
90062
  return false;
2525
}
2526
2527
83364
static Local<Object> InitModule(Environment* env,
2528
                                 node_module* mod,
2529
                                 Local<String> module) {
2530
83364
  Local<Object> exports = Object::New(env->isolate());
2531
  // Internal bindings don't have a "module" object, only exports.
2532
83364
  CHECK_EQ(mod->nm_register_func, nullptr);
2533
83364
  CHECK_NE(mod->nm_context_register_func, nullptr);
2534
83364
  Local<Value> unused = Undefined(env->isolate());
2535
  mod->nm_context_register_func(exports,
2536
                                unused,
2537
                                env->context(),
2538
83364
                                mod->nm_priv);
2539
83364
  return exports;
2540
}
2541
2542
2
static void ThrowIfNoSuchModule(Environment* env, const char* module_v) {
2543
  char errmsg[1024];
2544
  snprintf(errmsg,
2545
           sizeof(errmsg),
2546
           "No such module: %s",
2547
2
           module_v);
2548
2
  env->ThrowError(errmsg);
2549
2
}
2550
2551
295444
static void Binding(const FunctionCallbackInfo<Value>& args) {
2552
295444
  Environment* env = Environment::GetCurrent(args);
2553
2554
  Local<String> module;
2555
1390508
  if (!args[0]->ToString(env->context()).ToLocal(&module)) return;
2556
2557
295444
  Local<Object> cache = env->binding_cache_object();
2558
2559
295444
  if (PullFromCache(env, args, module, cache))
2560
208730
    return;
2561
2562
  // Append a string to process.moduleLoadList
2563
  char buf[1024];
2564
86714
  node::Utf8Value module_v(env->isolate(), module);
2565
86714
  snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2566
2567
86714
  Local<Array> modules = env->module_load_list_array();
2568
86714
  uint32_t l = modules->Length();
2569
173428
  modules->Set(l, OneByteString(env->isolate(), buf));
2570
2571
86714
  node_module* mod = get_builtin_module(*module_v);
2572
  Local<Object> exports;
2573
86714
  if (mod != nullptr) {
2574
80016
    exports = InitModule(env, mod, module);
2575
6698
  } else if (!strcmp(*module_v, "constants")) {
2576
3348
    exports = Object::New(env->isolate());
2577
13392
    CHECK(exports->SetPrototype(env->context(),
2578
                                Null(env->isolate())).FromJust());
2579
3348
    DefineConstants(env->isolate(), exports);
2580
3350
  } else if (!strcmp(*module_v, "natives")) {
2581
3348
    exports = Object::New(env->isolate());
2582
3348
    DefineJavaScript(env, exports);
2583
  } else {
2584
2
    return ThrowIfNoSuchModule(env, *module_v);
2585
  }
2586
86712
  cache->Set(module, exports);
2587
2588
173424
  args.GetReturnValue().Set(exports);
2589
}
2590
2591
10044
static void InternalBinding(const FunctionCallbackInfo<Value>& args) {
2592
10044
  Environment* env = Environment::GetCurrent(args);
2593
2594
  Local<String> module;
2595
46872
  if (!args[0]->ToString(env->context()).ToLocal(&module)) return;
2596
2597
10044
  Local<Object> cache = env->internal_binding_cache_object();
2598
2599
10044
  if (PullFromCache(env, args, module, cache))
2600
6696
    return;
2601
2602
  // Append a string to process.moduleLoadList
2603
  char buf[1024];
2604
3348
  node::Utf8Value module_v(env->isolate(), module);
2605
3348
  snprintf(buf, sizeof(buf), "Internal Binding %s", *module_v);
2606
2607
3348
  Local<Array> modules = env->module_load_list_array();
2608
3348
  uint32_t l = modules->Length();
2609
6696
  modules->Set(l, OneByteString(env->isolate(), buf));
2610
2611
3348
  node_module* mod = get_internal_module(*module_v);
2612
3348
  if (mod == nullptr) return ThrowIfNoSuchModule(env, *module_v);
2613
3348
  Local<Object> exports = InitModule(env, mod, module);
2614
3348
  cache->Set(module, exports);
2615
2616
6696
  args.GetReturnValue().Set(exports);
2617
}
2618
2619
static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2620
  Environment* env = Environment::GetCurrent(args.GetIsolate());
2621
2622
  Local<String> module_name;
2623
  if (!args[0]->ToString(env->context()).ToLocal(&module_name)) return;
2624
2625
  Local<Object> cache = env->binding_cache_object();
2626
  Local<Value> exports_v = cache->Get(module_name);
2627
2628
  if (exports_v->IsObject())
2629
    return args.GetReturnValue().Set(exports_v.As<Object>());
2630
2631
  node::Utf8Value module_name_v(env->isolate(), module_name);
2632
  node_module* mod = get_linked_module(*module_name_v);
2633
2634
  if (mod == nullptr) {
2635
    char errmsg[1024];
2636
    snprintf(errmsg,
2637
             sizeof(errmsg),
2638
             "No such module was linked: %s",
2639
             *module_name_v);
2640
    return env->ThrowError(errmsg);
2641
  }
2642
2643
  Local<Object> module = Object::New(env->isolate());
2644
  Local<Object> exports = Object::New(env->isolate());
2645
  Local<String> exports_prop = String::NewFromUtf8(env->isolate(), "exports");
2646
  module->Set(exports_prop, exports);
2647
2648
  if (mod->nm_context_register_func != nullptr) {
2649
    mod->nm_context_register_func(exports,
2650
                                  module,
2651
                                  env->context(),
2652
                                  mod->nm_priv);
2653
  } else if (mod->nm_register_func != nullptr) {
2654
    mod->nm_register_func(exports, module, mod->nm_priv);
2655
  } else {
2656
    return env->ThrowError("Linked module has no declared entry point.");
2657
  }
2658
2659
  auto effective_exports = module->Get(exports_prop);
2660
  cache->Set(module_name, effective_exports);
2661
2662
  args.GetReturnValue().Set(effective_exports);
2663
}
2664
2665
11
static void ProcessTitleGetter(Local<Name> property,
2666
                               const PropertyCallbackInfo<Value>& info) {
2667
  char buffer[512];
2668
11
  uv_get_process_title(buffer, sizeof(buffer));
2669
33
  info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer));
2670
11
}
2671
2672
2673
73
static void ProcessTitleSetter(Local<Name> property,
2674
                               Local<Value> value,
2675
                               const PropertyCallbackInfo<void>& info) {
2676
73
  node::Utf8Value title(info.GetIsolate(), value);
2677
  // TODO(piscisaureus): protect with a lock
2678
73
  uv_set_process_title(*title);
2679
73
}
2680
2681
2682
243702
static void EnvGetter(Local<Name> property,
2683
                      const PropertyCallbackInfo<Value>& info) {
2684
243702
  Isolate* isolate = info.GetIsolate();
2685
243702
  if (property->IsSymbol()) {
2686
211307
    return info.GetReturnValue().SetUndefined();
2687
  }
2688
#ifdef __POSIX__
2689
243684
  node::Utf8Value key(isolate, property);
2690
243684
  const char* val = getenv(*key);
2691
243684
  if (val) {
2692
633759
    return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
2693
32431
  }
2694
#else  // _WIN32
2695
  node::TwoByteValue key(isolate, property);
2696
  WCHAR buffer[32767];  // The maximum size allowed for environment variables.
2697
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2698
                                         buffer,
2699
                                         arraysize(buffer));
2700
  // If result >= sizeof buffer the buffer was too small. That should never
2701
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2702
  // not found.
2703
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2704
      result < arraysize(buffer)) {
2705
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2706
    Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
2707
    return info.GetReturnValue().Set(rc);
2708
  }
2709
#endif
2710
}
2711
2712
2713
197
static void EnvSetter(Local<Name> property,
2714
                      Local<Value> value,
2715
                      const PropertyCallbackInfo<Value>& info) {
2716
#ifdef __POSIX__
2717
197
  node::Utf8Value key(info.GetIsolate(), property);
2718
394
  node::Utf8Value val(info.GetIsolate(), value);
2719
197
  setenv(*key, *val, 1);
2720
#else  // _WIN32
2721
  node::TwoByteValue key(info.GetIsolate(), property);
2722
  node::TwoByteValue val(info.GetIsolate(), value);
2723
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2724
  // Environment variables that start with '=' are read-only.
2725
  if (key_ptr[0] != L'=') {
2726
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2727
  }
2728
#endif
2729
  // Whether it worked or not, always return value.
2730
591
  info.GetReturnValue().Set(value);
2731
197
}
2732
2733
2734
324745
static void EnvQuery(Local<Name> property,
2735
                     const PropertyCallbackInfo<Integer>& info) {
2736
324745
  int32_t rc = -1;  // Not found unless proven otherwise.
2737
649490
  if (property->IsString()) {
2738
#ifdef __POSIX__
2739
324736
    node::Utf8Value key(info.GetIsolate(), property);
2740
324736
    if (getenv(*key))
2741
322748
      rc = 0;
2742
#else  // _WIN32
2743
    node::TwoByteValue key(info.GetIsolate(), property);
2744
    WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2745
    if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
2746
        GetLastError() == ERROR_SUCCESS) {
2747
      rc = 0;
2748
      if (key_ptr[0] == L'=') {
2749
        // Environment variables that start with '=' are hidden and read-only.
2750
        rc = static_cast<int32_t>(v8::ReadOnly) |
2751
             static_cast<int32_t>(v8::DontDelete) |
2752
             static_cast<int32_t>(v8::DontEnum);
2753
      }
2754
    }
2755
#endif
2756
  }
2757
324745
  if (rc != -1)
2758
645496
    info.GetReturnValue().Set(rc);
2759
324745
}
2760
2761
2762
717
static void EnvDeleter(Local<Name> property,
2763
                       const PropertyCallbackInfo<Boolean>& info) {
2764
1434
  if (property->IsString()) {
2765
#ifdef __POSIX__
2766
716
    node::Utf8Value key(info.GetIsolate(), property);
2767
716
    unsetenv(*key);
2768
#else
2769
    node::TwoByteValue key(info.GetIsolate(), property);
2770
    WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2771
    SetEnvironmentVariableW(key_ptr, nullptr);
2772
#endif
2773
  }
2774
2775
  // process.env never has non-configurable properties, so always
2776
  // return true like the tc39 delete operator.
2777
1434
  info.GetReturnValue().Set(true);
2778
717
}
2779
2780
2781
2960
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2782
2960
  Environment* env = Environment::GetCurrent(info);
2783
2960
  Isolate* isolate = env->isolate();
2784
2960
  Local<Context> ctx = env->context();
2785
2960
  Local<Function> fn = env->push_values_to_array_function();
2786
26640
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
2787
2960
  size_t idx = 0;
2788
2789
#ifdef __POSIX__
2790
2960
  int size = 0;
2791
187856
  while (environ[size])
2792
181936
    size++;
2793
2794
2960
  Local<Array> envarr = Array::New(isolate);
2795
2796
184896
  for (int i = 0; i < size; ++i) {
2797
181936
    const char* var = environ[i];
2798
181936
    const char* s = strchr(var, '=');
2799
181936
    const int length = s ? s - var : strlen(var);
2800
    argv[idx] = String::NewFromUtf8(isolate,
2801
                                    var,
2802
                                    String::kNormalString,
2803
363872
                                    length);
2804
181936
    if (++idx >= arraysize(argv)) {
2805
62262
      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2806
20754
      idx = 0;
2807
    }
2808
  }
2809
2960
  if (idx > 0) {
2810
8778
    fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2811
  }
2812
#else  // _WIN32
2813
  WCHAR* environment = GetEnvironmentStringsW();
2814
  if (environment == nullptr)
2815
    return;  // This should not happen.
2816
  Local<Array> envarr = Array::New(isolate);
2817
  WCHAR* p = environment;
2818
  while (*p) {
2819
    WCHAR *s;
2820
    if (*p == L'=') {
2821
      // If the key starts with '=' it is a hidden environment variable.
2822
      p += wcslen(p) + 1;
2823
      continue;
2824
    } else {
2825
      s = wcschr(p, L'=');
2826
    }
2827
    if (!s) {
2828
      s = p + wcslen(p);
2829
    }
2830
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2831
    const size_t two_byte_buffer_len = s - p;
2832
    argv[idx] = String::NewFromTwoByte(isolate,
2833
                                       two_byte_buffer,
2834
                                       String::kNormalString,
2835
                                       two_byte_buffer_len);
2836
    if (++idx >= arraysize(argv)) {
2837
      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2838
      idx = 0;
2839
    }
2840
    p = s + wcslen(s) + 1;
2841
  }
2842
  if (idx > 0) {
2843
    fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2844
  }
2845
  FreeEnvironmentStringsW(environment);
2846
#endif
2847
2848
5920
  info.GetReturnValue().Set(envarr);
2849
2960
}
2850
2851
2852
10
static void GetParentProcessId(Local<Name> property,
2853
                               const PropertyCallbackInfo<Value>& info) {
2854
40
  info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid()));
2855
10
}
2856
2857
2858
3352
static Local<Object> GetFeatures(Environment* env) {
2859
3352
  EscapableHandleScope scope(env->isolate());
2860
2861
3352
  Local<Object> obj = Object::New(env->isolate());
2862
#if defined(DEBUG) && DEBUG
2863
  Local<Value> debug = True(env->isolate());
2864
#else
2865
3352
  Local<Value> debug = False(env->isolate());
2866
#endif  // defined(DEBUG) && DEBUG
2867
2868
6704
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "debug"), debug);
2869
10056
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "uv"), True(env->isolate()));
2870
  // TODO(bnoordhuis) ping libuv
2871
10056
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "ipv6"), True(env->isolate()));
2872
2873
#ifndef OPENSSL_NO_NEXTPROTONEG
2874
6704
  Local<Boolean> tls_npn = True(env->isolate());
2875
#else
2876
  Local<Boolean> tls_npn = False(env->isolate());
2877
#endif
2878
6704
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_npn"), tls_npn);
2879
2880
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2881
6704
  Local<Boolean> tls_alpn = True(env->isolate());
2882
#else
2883
  Local<Boolean> tls_alpn = False(env->isolate());
2884
#endif
2885
6704
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_alpn"), tls_alpn);
2886
2887
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2888
6704
  Local<Boolean> tls_sni = True(env->isolate());
2889
#else
2890
  Local<Boolean> tls_sni = False(env->isolate());
2891
#endif
2892
6704
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_sni"), tls_sni);
2893
2894
#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2895
6704
  Local<Boolean> tls_ocsp = True(env->isolate());
2896
#else
2897
  Local<Boolean> tls_ocsp = False(env->isolate());
2898
#endif  // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2899
6704
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_ocsp"), tls_ocsp);
2900
2901
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls"),
2902
           Boolean::New(env->isolate(),
2903
10056
                        get_builtin_module("crypto") != nullptr));
2904
2905
3352
  return scope.Escape(obj);
2906
}
2907
2908
2909
65
static void DebugPortGetter(Local<Name> property,
2910
                            const PropertyCallbackInfo<Value>& info) {
2911
65
  int port = debug_options.port();
2912
#if HAVE_INSPECTOR
2913
65
  if (port == 0) {
2914
10
    Environment* env = Environment::GetCurrent(info);
2915
10
    if (auto io = env->inspector_agent()->io())
2916
7
      port = io->port();
2917
  }
2918
#endif  // HAVE_INSPECTOR
2919
130
  info.GetReturnValue().Set(port);
2920
65
}
2921
2922
2923
static void DebugPortSetter(Local<Name> property,
2924
                            Local<Value> value,
2925
                            const PropertyCallbackInfo<void>& info) {
2926
  debug_options.set_port(value->Int32Value());
2927
}
2928
2929
2930
static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2931
static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2932
2933
namespace {
2934
2935
3641
void ActivateImmediateCheck(const FunctionCallbackInfo<Value>& args) {
2936
3641
  Environment* env = Environment::GetCurrent(args);
2937
3641
  env->ActivateImmediateCheck();
2938
3641
}
2939
2940
2941
void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2942
  Environment* env = Environment::GetCurrent(args);
2943
  env->StartProfilerIdleNotifier();
2944
}
2945
2946
2947
void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2948
  Environment* env = Environment::GetCurrent(args);
2949
  env->StopProfilerIdleNotifier();
2950
}
2951
2952
2953
#define READONLY_PROPERTY(obj, str, var)                                      \
2954
  do {                                                                        \
2955
    obj->DefineOwnProperty(env->context(),                                    \
2956
                           OneByteString(env->isolate(), str),                \
2957
                           var,                                               \
2958
                           v8::ReadOnly).FromJust();                          \
2959
  } while (0)
2960
2961
#define READONLY_DONT_ENUM_PROPERTY(obj, str, var)                            \
2962
  do {                                                                        \
2963
    obj->DefineOwnProperty(env->context(),                                    \
2964
                           OneByteString(env->isolate(), str),                \
2965
                           var,                                               \
2966
                           static_cast<v8::PropertyAttribute>(v8::ReadOnly |  \
2967
                                                              v8::DontEnum))  \
2968
        .FromJust();                                                          \
2969
  } while (0)
2970
2971
}  // anonymous namespace
2972
2973
3352
void SetupProcessObject(Environment* env,
2974
                        int argc,
2975
                        const char* const* argv,
2976
                        int exec_argc,
2977
                        const char* const* exec_argv) {
2978
3352
  HandleScope scope(env->isolate());
2979
2980
3352
  Local<Object> process = env->process_object();
2981
2982
3352
  auto title_string = FIXED_ONE_BYTE_STRING(env->isolate(), "title");
2983
13408
  CHECK(process->SetAccessor(env->context(),
2984
                             title_string,
2985
                             ProcessTitleGetter,
2986
                             ProcessTitleSetter,
2987
                             env->as_external()).FromJust());
2988
2989
  // process.version
2990
16760
  READONLY_PROPERTY(process,
2991
                    "version",
2992
                    FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
2993
2994
  // process.moduleLoadList
2995
16760
  READONLY_PROPERTY(process,
2996
                    "moduleLoadList",
2997
                    env->module_load_list_array());
2998
2999
  // process.versions
3000
3352
  Local<Object> versions = Object::New(env->isolate());
3001
13408
  READONLY_PROPERTY(process, "versions", versions);
3002
3003
  const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
3004
                                     "."
3005
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
3006
                                     "."
3007
3352
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
3008
16760
  READONLY_PROPERTY(versions,
3009
                    "http_parser",
3010
                    FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
3011
3012
  // +1 to get rid of the leading 'v'
3013
16760
  READONLY_PROPERTY(versions,
3014
                    "node",
3015
                    OneByteString(env->isolate(), NODE_VERSION + 1));
3016
16760
  READONLY_PROPERTY(versions,
3017
                    "v8",
3018
                    OneByteString(env->isolate(), V8::GetVersion()));
3019
16760
  READONLY_PROPERTY(versions,
3020
                    "uv",
3021
                    OneByteString(env->isolate(), uv_version_string()));
3022
16760
  READONLY_PROPERTY(versions,
3023
                    "zlib",
3024
                    FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
3025
16760
  READONLY_PROPERTY(versions,
3026
                    "ares",
3027
                    FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
3028
3029
3352
  const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
3030
16760
  READONLY_PROPERTY(
3031
      versions,
3032
      "modules",
3033
      FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
3034
3035
16760
  READONLY_PROPERTY(versions,
3036
                    "nghttp2",
3037
                    FIXED_ONE_BYTE_STRING(env->isolate(), NGHTTP2_VERSION));
3038
3039
  // process._promiseRejectEvent
3040
3352
  Local<Object> promiseRejectEvent = Object::New(env->isolate());
3041
13408
  READONLY_DONT_ENUM_PROPERTY(process,
3042
                              "_promiseRejectEvent",
3043
                              promiseRejectEvent);
3044
16760
  READONLY_PROPERTY(promiseRejectEvent,
3045
                    "unhandled",
3046
                    Integer::New(env->isolate(),
3047
                                 v8::kPromiseRejectWithNoHandler));
3048
16760
  READONLY_PROPERTY(promiseRejectEvent,
3049
                    "handled",
3050
                    Integer::New(env->isolate(),
3051
                                 v8::kPromiseHandlerAddedAfterReject));
3052
3053
#if HAVE_OPENSSL
3054
  // Stupid code to slice out the version string.
3055
  {  // NOLINT(whitespace/braces)
3056
    size_t i, j, k;
3057
    int c;
3058
30168
    for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
3059
30168
      c = OPENSSL_VERSION_TEXT[i];
3060

30168
      if ('0' <= c && c <= '9') {
3061
20112
        for (j = i + 1; j < k; ++j) {
3062
20112
          c = OPENSSL_VERSION_TEXT[j];
3063
20112
          if (c == ' ')
3064
3352
            break;
3065
        }
3066
3352
        break;
3067
      }
3068
    }
3069
16760
    READONLY_PROPERTY(
3070
        versions,
3071
        "openssl",
3072
        OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
3073
  }
3074
#endif
3075
3076
  // process.arch
3077
16760
  READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
3078
3079
  // process.platform
3080
16760
  READONLY_PROPERTY(process,
3081
                    "platform",
3082
                    OneByteString(env->isolate(), NODE_PLATFORM));
3083
3084
  // process.release
3085
3352
  Local<Object> release = Object::New(env->isolate());
3086
13408
  READONLY_PROPERTY(process, "release", release);
3087
16760
  READONLY_PROPERTY(release, "name",
3088
                    OneByteString(env->isolate(), NODE_RELEASE));
3089
3090
#if NODE_VERSION_IS_LTS
3091
  READONLY_PROPERTY(release, "lts",
3092
                    OneByteString(env->isolate(), NODE_VERSION_LTS_CODENAME));
3093
#endif
3094
3095
// if this is a release build and no explicit base has been set
3096
// substitute the standard release download URL
3097
#ifndef NODE_RELEASE_URLBASE
3098
# if NODE_VERSION_IS_RELEASE
3099
#  define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
3100
# endif
3101
#endif
3102
3103
#if defined(NODE_RELEASE_URLBASE)
3104
#  define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
3105
#  define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
3106
3107
  READONLY_PROPERTY(release,
3108
                    "sourceUrl",
3109
                    OneByteString(env->isolate(),
3110
                    NODE_RELEASE_URLFPFX ".tar.gz"));
3111
  READONLY_PROPERTY(release,
3112
                    "headersUrl",
3113
                    OneByteString(env->isolate(),
3114
                    NODE_RELEASE_URLFPFX "-headers.tar.gz"));
3115
#  ifdef _WIN32
3116
  READONLY_PROPERTY(release,
3117
                    "libUrl",
3118
                    OneByteString(env->isolate(),
3119
                    strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-"
3120
                                                NODE_ARCH "/node.lib"
3121
                                              : NODE_RELEASE_URLPFX
3122
                                                "win-x86/node.lib"));
3123
#  endif
3124
#endif
3125
3126
  // process.argv
3127
3352
  Local<Array> arguments = Array::New(env->isolate(), argc);
3128
13547
  for (int i = 0; i < argc; ++i) {
3129
30585
    arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
3130
  }
3131
6704
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "argv"), arguments);
3132
3133
  // process.execArgv
3134
3352
  Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
3135
4152
  for (int i = 0; i < exec_argc; ++i) {
3136
2400
    exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
3137
  }
3138
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execArgv"),
3139
6704
               exec_arguments);
3140
3141
  // create process.env
3142
  Local<ObjectTemplate> process_env_template =
3143
3352
      ObjectTemplate::New(env->isolate());
3144
  process_env_template->SetHandler(NamedPropertyHandlerConfiguration(
3145
          EnvGetter,
3146
          EnvSetter,
3147
          EnvQuery,
3148
          EnvDeleter,
3149
          EnvEnumerator,
3150
10056
          env->as_external()));
3151
3152
  Local<Object> process_env =
3153
10056
      process_env_template->NewInstance(env->context()).ToLocalChecked();
3154
6704
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "env"), process_env);
3155
3156
16760
  READONLY_PROPERTY(process, "pid",
3157
                    Integer::New(env->isolate(), uv_os_getpid()));
3158
16760
  READONLY_PROPERTY(process, "features", GetFeatures(env));
3159
3160
13408
  CHECK(process->SetAccessor(env->context(),
3161
                             FIXED_ONE_BYTE_STRING(env->isolate(), "ppid"),
3162
                             GetParentProcessId).FromJust());
3163
3164
  auto scheduled_immediate_count =
3165
3352
      FIXED_ONE_BYTE_STRING(env->isolate(), "_scheduledImmediateCount");
3166
13408
  CHECK(process->Set(env->context(),
3167
                     scheduled_immediate_count,
3168
                     env->scheduled_immediate_count().GetJSArray()).FromJust());
3169
3170
  auto should_abort_on_uncaught_toggle =
3171
3352
      FIXED_ONE_BYTE_STRING(env->isolate(), "_shouldAbortOnUncaughtToggle");
3172
13408
  CHECK(process->Set(env->context(),
3173
                     should_abort_on_uncaught_toggle,
3174
                     env->should_abort_on_uncaught_toggle().GetJSArray())
3175
                         .FromJust());
3176
3177
  // -e, --eval
3178
3352
  if (eval_string) {
3179
875
    READONLY_PROPERTY(process,
3180
                      "_eval",
3181
                      String::NewFromUtf8(env->isolate(), eval_string));
3182
  }
3183
3184
  // -p, --print
3185
3352
  if (print_eval) {
3186
400
    READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
3187
  }
3188
3189
  // -c, --check
3190
3352
  if (syntax_check_only) {
3191
130
    READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
3192
  }
3193
3194
  // -i, --interactive
3195
3352
  if (force_repl) {
3196
45
    READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
3197
  }
3198
3199
  // -r, --require
3200
3352
  if (!preload_modules.empty()) {
3201
15
    Local<Array> array = Array::New(env->isolate());
3202
34
    for (unsigned int i = 0; i < preload_modules.size(); ++i) {
3203
      Local<String> module = String::NewFromUtf8(env->isolate(),
3204
19
                                                 preload_modules[i].c_str());
3205
19
      array->Set(i, module);
3206
    }
3207
60
    READONLY_PROPERTY(process,
3208
                      "_preload_modules",
3209
                      array);
3210
3211
15
    preload_modules.clear();
3212
  }
3213
3214
  // --no-deprecation
3215
3352
  if (no_deprecation) {
3216
20
    READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
3217
  }
3218
3219
  // --no-warnings
3220
3352
  if (no_process_warnings) {
3221
60
    READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
3222
  }
3223
3224
  // --trace-warnings
3225
3352
  if (trace_warnings) {
3226
15
    READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
3227
  }
3228
3229
  // --throw-deprecation
3230
3352
  if (throw_deprecation) {
3231
5
    READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
3232
  }
3233
3234
#ifdef NODE_NO_BROWSER_GLOBALS
3235
  // configure --no-browser-globals
3236
  READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
3237
#endif  // NODE_NO_BROWSER_GLOBALS
3238
3239
  // --prof-process
3240
3352
  if (prof_process) {
3241
    READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
3242
  }
3243
3244
  // --trace-deprecation
3245
3352
  if (trace_deprecation) {
3246
10
    READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
3247
  }
3248
3249
  // TODO(refack): move the following 3 to `node_config`
3250
  // --inspect-brk
3251
3352
  if (debug_options.wait_for_connect()) {
3252
50
    READONLY_DONT_ENUM_PROPERTY(process,
3253
                                "_breakFirstLine", True(env->isolate()));
3254
  }
3255
3256
  // --inspect --debug-brk
3257
3352
  if (debug_options.deprecated_invocation()) {
3258
5
    READONLY_DONT_ENUM_PROPERTY(process,
3259
                                "_deprecatedDebugBrk", True(env->isolate()));
3260
  }
3261
3262
  // --debug or, --debug-brk without --inspect
3263
3352
  if (debug_options.invalid_invocation()) {
3264
10
    READONLY_DONT_ENUM_PROPERTY(process,
3265
                                "_invalidDebug", True(env->isolate()));
3266
  }
3267
3268
  // --security-revert flags
3269
#define V(code, _, __)                                                        \
3270
  do {                                                                        \
3271
    if (IsReverted(SECURITY_REVERT_ ## code)) {                               \
3272
      READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate()));      \
3273
    }                                                                         \
3274
  } while (0);
3275
  SECURITY_REVERSIONS(V)
3276
#undef V
3277
3278
3352
  size_t exec_path_len = 2 * PATH_MAX;
3279
3352
  char* exec_path = new char[exec_path_len];
3280
  Local<String> exec_path_value;
3281
3352
  if (uv_exepath(exec_path, &exec_path_len) == 0) {
3282
    exec_path_value = String::NewFromUtf8(env->isolate(),
3283
                                          exec_path,
3284
                                          String::kNormalString,
3285
3352
                                          exec_path_len);
3286
  } else {
3287
    exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
3288
  }
3289
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
3290
6704
               exec_path_value);
3291
3352
  delete[] exec_path;
3292
3293
3352
  auto debug_port_string = FIXED_ONE_BYTE_STRING(env->isolate(), "debugPort");
3294
13408
  CHECK(process->SetAccessor(env->context(),
3295
                             debug_port_string,
3296
                             DebugPortGetter,
3297
                             DebugPortSetter,
3298
                             env->as_external()).FromJust());
3299
3300
  // define various internal methods
3301
  env->SetMethod(process,
3302
                 "_activateImmediateCheck",
3303
3352
                 ActivateImmediateCheck);
3304
  env->SetMethod(process,
3305
                 "_startProfilerIdleNotifier",
3306
3352
                 StartProfilerIdleNotifier);
3307
  env->SetMethod(process,
3308
                 "_stopProfilerIdleNotifier",
3309
3352
                 StopProfilerIdleNotifier);
3310
3352
  env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
3311
3352
  env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
3312
3352
  env->SetMethod(process, "reallyExit", Exit);
3313
3352
  env->SetMethod(process, "abort", Abort);
3314
3352
  env->SetMethod(process, "chdir", Chdir);
3315
3352
  env->SetMethod(process, "cwd", Cwd);
3316
3317
3352
  env->SetMethod(process, "umask", Umask);
3318
3319
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
3320
3352
  env->SetMethod(process, "getuid", GetUid);
3321
3352
  env->SetMethod(process, "geteuid", GetEUid);
3322
3352
  env->SetMethod(process, "setuid", SetUid);
3323
3352
  env->SetMethod(process, "seteuid", SetEUid);
3324
3325
3352
  env->SetMethod(process, "setgid", SetGid);
3326
3352
  env->SetMethod(process, "setegid", SetEGid);
3327
3352
  env->SetMethod(process, "getgid", GetGid);
3328
3352
  env->SetMethod(process, "getegid", GetEGid);
3329
3330
3352
  env->SetMethod(process, "getgroups", GetGroups);
3331
3352
  env->SetMethod(process, "setgroups", SetGroups);
3332
3352
  env->SetMethod(process, "initgroups", InitGroups);
3333
#endif  // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
3334
3335
3352
  env->SetMethod(process, "_kill", Kill);
3336
3337
3352
  env->SetMethod(process, "_debugProcess", DebugProcess);
3338
3352
  env->SetMethod(process, "_debugEnd", DebugEnd);
3339
3340
3352
  env->SetMethod(process, "hrtime", Hrtime);
3341
3342
3352
  env->SetMethod(process, "cpuUsage", CPUUsage);
3343
3344
3352
  env->SetMethod(process, "dlopen", DLOpen);
3345
3346
3352
  env->SetMethod(process, "uptime", Uptime);
3347
3352
  env->SetMethod(process, "memoryUsage", MemoryUsage);
3348
3349
3352
  env->SetMethod(process, "binding", Binding);
3350
3352
  env->SetMethod(process, "_linkedBinding", LinkedBinding);
3351
3352
  env->SetMethod(process, "_internalBinding", InternalBinding);
3352
3353
3352
  env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
3354
3352
  env->SetMethod(process, "_setupNextTick", SetupNextTick);
3355
3352
  env->SetMethod(process, "_setupPromises", SetupPromises);
3356
3352
  env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
3357
3352
}
3358
3359
3360
#undef READONLY_PROPERTY
3361
3362
3363
void SignalExit(int signo) {
3364
  uv_tty_reset_mode();
3365
  if (trace_enabled) {
3366
    v8_platform.StopTracingAgent();
3367
  }
3368
#ifdef __FreeBSD__
3369
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
3370
  struct sigaction sa;
3371
  memset(&sa, 0, sizeof(sa));
3372
  sa.sa_handler = SIG_DFL;
3373
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
3374
#endif
3375
  raise(signo);
3376
}
3377
3378
3379
// Most of the time, it's best to use `console.error` to write
3380
// to the process.stderr stream.  However, in some cases, such as
3381
// when debugging the stream.Writable class or the process.nextTick
3382
// function, it is useful to bypass JavaScript entirely.
3383
15
static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3384


75
  CHECK(args.Length() == 1 && args[0]->IsString() &&
3385
        "must be called with a single string");
3386
15
  node::Utf8Value message(args.GetIsolate(), args[0]);
3387
15
  PrintErrorString("%s\n", *message);
3388
15
  fflush(stderr);
3389
15
}
3390
3391
3348
void LoadEnvironment(Environment* env) {
3392
3348
  HandleScope handle_scope(env->isolate());
3393
3394
6478
  TryCatch try_catch(env->isolate());
3395
3396
  // Disable verbose mode to stop FatalException() handler from trying
3397
  // to handle the exception. Errors this early in the start-up phase
3398
  // are not safe to ignore.
3399
3348
  try_catch.SetVerbose(false);
3400
3401
  // Execute the lib/internal/bootstrap_node.js file which was included as a
3402
  // static C string in node_natives.h by node_js2c.
3403
  // 'internal_bootstrap_node_native' is the string containing that source code.
3404
3348
  Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
3405
                                                    "bootstrap_node.js");
3406
3348
  Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3407
3348
  if (try_catch.HasCaught())  {
3408
    ReportException(env, try_catch);
3409
    exit(10);
3410
  }
3411
  // The bootstrap_node.js file returns a function 'f'
3412
3348
  CHECK(f_value->IsFunction());
3413
3414
3348
  Local<Function> f = Local<Function>::Cast(f_value);
3415
3416
  // Add a reference to the global object
3417
6696
  Local<Object> global = env->context()->Global();
3418
3419
#if defined HAVE_DTRACE || defined HAVE_ETW
3420
  InitDTrace(env, global);
3421
#endif
3422
3423
#if defined HAVE_LTTNG
3424
  InitLTTNG(env, global);
3425
#endif
3426
3427
#if defined HAVE_PERFCTR
3428
  InitPerfCounters(env, global);
3429
#endif
3430
3431
  // Enable handling of uncaught exceptions
3432
  // (FatalException(), break on uncaught exception in debugger)
3433
  //
3434
  // This is not strictly necessary since it's almost impossible
3435
  // to attach the debugger fast enough to break on exception
3436
  // thrown during process startup.
3437
3348
  try_catch.SetVerbose(true);
3438
3439
3348
  env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3440
3441
  // Expose the global object as a property on itself
3442
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
3443
6696
  global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
3444
3445
  // Now we call 'f' with the 'process' variable that we've built up with
3446
  // all our bindings. Inside bootstrap_node.js and internal/process we'll
3447
  // take care of assigning things to their places.
3448
3449
  // We start the process this way in order to be more modular. Developers
3450
  // who do not like how bootstrap_node.js sets up the module system but do
3451
  // like Node's I/O bindings may want to replace 'f' with their own function.
3452
3348
  Local<Value> arg = env->process_object();
3453
3454
10044
  auto ret = f->Call(env->context(), Null(env->isolate()), 1, &arg);
3455
  // If there was an error during bootstrap then it was either handled by the
3456
  // FatalException handler or it's unrecoverable (e.g. max call stack
3457
  // exceeded). Either way, clear the stack so that the AsyncCallbackScope
3458
  // destructor doesn't fail on the id check.
3459
  // There are only two ways to have a stack size > 1: 1) the user manually
3460
  // called MakeCallback or 2) user awaited during bootstrap, which triggered
3461
  // _tickCallback().
3462
3130
  if (ret.IsEmpty())
3463
3169
    env->async_hooks()->clear_async_id_stack();
3464
3130
}
3465
3466
static void PrintHelp() {
3467
  // XXX: If you add an option here, please also add it to doc/node.1 and
3468
  // doc/api/cli.md
3469
  printf("Usage: node [options] [ -e script | script.js | - ] [arguments]\n"
3470
         "       node inspect script.js [arguments]\n"
3471
         "\n"
3472
         "Options:\n"
3473
         "  -v, --version              print Node.js version\n"
3474
         "  -e, --eval script          evaluate script\n"
3475
         "  -p, --print                evaluate script and print result\n"
3476
         "  -c, --check                syntax check script without executing\n"
3477
         "  -i, --interactive          always enter the REPL even if stdin\n"
3478
         "                             does not appear to be a terminal\n"
3479
         "  -r, --require              module to preload (option can be "
3480
         "repeated)\n"
3481
         "  -                          script read from stdin (default; "
3482
         "interactive mode if a tty)\n"
3483
#if HAVE_INSPECTOR
3484
         "  --inspect[=[host:]port]    activate inspector on host:port\n"
3485
         "                             (default: 127.0.0.1:9229)\n"
3486
         "  --inspect-brk[=[host:]port]\n"
3487
         "                             activate inspector on host:port\n"
3488
         "                             and break at start of user script\n"
3489
         "  --inspect-port=[host:]port\n"
3490
         "                             set host:port for inspector\n"
3491
#endif
3492
         "  --no-deprecation           silence deprecation warnings\n"
3493
         "  --trace-deprecation        show stack traces on deprecations\n"
3494
         "  --throw-deprecation        throw an exception on deprecations\n"
3495
         "  --pending-deprecation      emit pending deprecation warnings\n"
3496
         "  --no-warnings              silence all process warnings\n"
3497
         "  --napi-modules             load N-API modules (no-op - option\n"
3498
         "                             kept for compatibility)\n"
3499
         "  --abort-on-uncaught-exception\n"
3500
         "                             aborting instead of exiting causes a\n"
3501
         "                             core file to be generated for analysis\n"
3502
         "  --trace-warnings           show stack traces on process warnings\n"
3503
         "  --redirect-warnings=file\n"
3504
         "                             write warnings to file instead of\n"
3505
         "                             stderr\n"
3506
         "  --trace-sync-io            show stack trace when use of sync IO\n"
3507
         "                             is detected after the first tick\n"
3508
         "  --no-force-async-hooks-checks\n"
3509
         "                             disable checks for async_hooks\n"
3510
         "  --trace-events-enabled     track trace events\n"
3511
         "  --trace-event-categories   comma separated list of trace event\n"
3512
         "                             categories to record\n"
3513
         "  --track-heap-objects       track heap object allocations for heap "
3514
         "snapshots\n"
3515
         "  --prof-process             process v8 profiler output generated\n"
3516
         "                             using --prof\n"
3517
         "  --zero-fill-buffers        automatically zero-fill all newly "
3518
         "allocated\n"
3519
         "                             Buffer and SlowBuffer instances\n"
3520
         "  --v8-options               print v8 command line options\n"
3521
         "  --v8-pool-size=num         set v8's thread pool size\n"
3522
#if HAVE_OPENSSL
3523
         "  --tls-cipher-list=val      use an alternative default TLS cipher "
3524
         "list\n"
3525
         "  --use-bundled-ca           use bundled CA store"
3526
#if !defined(NODE_OPENSSL_CERT_STORE)
3527
         " (default)"
3528
#endif
3529
         "\n"
3530
         "  --use-openssl-ca           use OpenSSL's default CA store"
3531
#if defined(NODE_OPENSSL_CERT_STORE)
3532
         " (default)"
3533
#endif
3534
         "\n"
3535
#if NODE_FIPS_MODE
3536
         "  --enable-fips              enable FIPS crypto at startup\n"
3537
         "  --force-fips               force FIPS crypto (cannot be disabled)\n"
3538
#endif  /* NODE_FIPS_MODE */
3539
         "  --openssl-config=file      load OpenSSL configuration from the\n"
3540
         "                             specified file (overrides\n"
3541
         "                             OPENSSL_CONF)\n"
3542
#endif /* HAVE_OPENSSL */
3543
#if defined(NODE_HAVE_I18N_SUPPORT)
3544
         "  --icu-data-dir=dir         set ICU data load path to dir\n"
3545
         "                             (overrides NODE_ICU_DATA)\n"
3546
#if !defined(NODE_HAVE_SMALL_ICU)
3547
         "                             note: linked-in ICU data is present\n"
3548
#endif
3549
         "  --preserve-symlinks        preserve symbolic links when resolving\n"
3550
         "  --experimental-modules     experimental ES Module support\n"
3551
         "                             and caching modules\n"
3552
#endif
3553
         "\n"
3554
         "Environment variables:\n"
3555
         "NODE_DEBUG                   ','-separated list of core modules\n"
3556
         "                             that should print debug information\n"
3557
         "NODE_DISABLE_COLORS          set to 1 to disable colors in the REPL\n"
3558
         "NODE_EXTRA_CA_CERTS          path to additional CA certificates\n"
3559
         "                             file\n"
3560
#if defined(NODE_HAVE_I18N_SUPPORT)
3561
         "NODE_ICU_DATA                data path for ICU (Intl object) data\n"
3562
#if !defined(NODE_HAVE_SMALL_ICU)
3563
         "                             (will extend linked-in data)\n"
3564
#endif
3565
#endif
3566
         "NODE_NO_WARNINGS             set to 1 to silence process warnings\n"
3567
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
3568
         "NODE_OPTIONS                 set CLI options in the environment\n"
3569
         "                             via a space-separated list\n"
3570
#endif
3571
#ifdef _WIN32
3572
         "NODE_PATH                    ';'-separated list of directories\n"
3573
#else
3574
         "NODE_PATH                    ':'-separated list of directories\n"
3575
#endif
3576
         "                             prefixed to the module search path\n"
3577
         "NODE_PENDING_DEPRECATION     set to 1 to emit pending deprecation\n"
3578
         "                             warnings\n"
3579
         "NODE_REPL_HISTORY            path to the persistent REPL history\n"
3580
         "                             file\n"
3581
         "NODE_REDIRECT_WARNINGS       write warnings to path instead of\n"
3582
         "                             stderr\n"
3583
         "OPENSSL_CONF                 load OpenSSL configuration from file\n"
3584
         "\n"
3585
         "Documentation can be found at https://nodejs.org/\n");
3586
}
3587
3588
3589
890
static bool ArgIsAllowed(const char* arg, const char* allowed) {
3590

2829
  for (; *arg && *allowed; arg++, allowed++) {
3591
    // Like normal strcmp(), except that a '_' in `allowed` matches e