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: 1556 1825 85.3 %
Date: 2017-11-19 Branches: 832 1193 69.7 %

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-debug.h"
71
#include "v8-profiler.h"
72
#include "zlib.h"
73
74
#ifdef NODE_ENABLE_VTUNE_PROFILING
75
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
76
#endif
77
78
#include <errno.h>
79
#include <fcntl.h>  // _O_RDWR
80
#include <limits.h>  // PATH_MAX
81
#include <locale.h>
82
#include <signal.h>
83
#include <stdio.h>
84
#include <stdlib.h>
85
#include <string.h>
86
#include <sys/types.h>
87
88
#include <string>
89
#include <vector>
90
91
#if defined(NODE_HAVE_I18N_SUPPORT)
92
#include <unicode/uvernum.h>
93
#endif
94
95
#if defined(LEAK_SANITIZER)
96
#include <sanitizer/lsan_interface.h>
97
#endif
98
99
#if defined(_MSC_VER)
100
#include <direct.h>
101
#include <io.h>
102
#define getpid GetCurrentProcessId
103
#define umask _umask
104
typedef int mode_t;
105
#else
106
#include <pthread.h>
107
#include <sys/resource.h>  // getrlimit, setrlimit
108
#include <unistd.h>  // setuid, getuid
109
#endif
110
111
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
112
#include <pwd.h>  // getpwnam()
113
#include <grp.h>  // getgrnam()
114
#endif
115
116
#if defined(__POSIX__)
117
#include <dlfcn.h>
118
#endif
119
120
#ifdef __APPLE__
121
#include <crt_externs.h>
122
#define environ (*_NSGetEnviron())
123
#elif !defined(_MSC_VER)
124
extern char **environ;
125
#endif
126
127
// This is used to load built-in modules. Instead of using
128
// __attribute__((constructor)), we call the _register_<modname>
129
// function for each built-in modules explicitly in
130
// node::RegisterBuiltinModules(). This is only forward declaration.
131
// The definitions are in each module's implementation when calling
132
// the NODE_BUILTIN_MODULE_CONTEXT_AWARE.
133
#define V(modname) void _register_##modname();
134
  NODE_BUILTIN_MODULES(V)
135
#undef V
136
137
namespace node {
138
139
using v8::Array;
140
using v8::ArrayBuffer;
141
using v8::Boolean;
142
using v8::Context;
143
using v8::EscapableHandleScope;
144
using v8::Exception;
145
using v8::Float64Array;
146
using v8::Function;
147
using v8::FunctionCallbackInfo;
148
using v8::HandleScope;
149
using v8::HeapStatistics;
150
using v8::Integer;
151
using v8::Isolate;
152
using v8::Local;
153
using v8::Locker;
154
using v8::MaybeLocal;
155
using v8::Message;
156
using v8::Name;
157
using v8::NamedPropertyHandlerConfiguration;
158
using v8::Null;
159
using v8::Number;
160
using v8::Object;
161
using v8::ObjectTemplate;
162
using v8::Promise;
163
using v8::PromiseRejectMessage;
164
using v8::PropertyCallbackInfo;
165
using v8::ScriptOrigin;
166
using v8::SealHandleScope;
167
using v8::String;
168
using v8::TryCatch;
169
using v8::Uint32Array;
170
using v8::Undefined;
171
using v8::V8;
172
using v8::Value;
173
174
using AsyncHooks = node::Environment::AsyncHooks;
175
176
static bool print_eval = false;
177
static bool force_repl = false;
178
static bool syntax_check_only = false;
179
static bool trace_deprecation = false;
180
static bool throw_deprecation = false;
181
static bool trace_sync_io = false;
182
static bool no_force_async_hooks_checks = false;
183
static bool track_heap_objects = false;
184
static const char* eval_string = nullptr;
185
3333
static std::vector<std::string> preload_modules;
186
static const int v8_default_thread_pool_size = 4;
187
static int v8_thread_pool_size = v8_default_thread_pool_size;
188
static bool prof_process = false;
189
static bool v8_is_profiling = false;
190
static bool node_is_initialized = false;
191
static node_module* modpending;
192
static node_module* modlist_builtin;
193
static node_module* modlist_internal;
194
static node_module* modlist_linked;
195
static node_module* modlist_addon;
196
static bool trace_enabled = false;
197
3333
static std::string trace_enabled_categories;  // NOLINT(runtime/string)
198
static bool abort_on_uncaught_exception = false;
199
200
// Bit flag used to track security reverts (see node_revert.h)
201
unsigned int reverted = 0;
202
203
#if defined(NODE_HAVE_I18N_SUPPORT)
204
// Path to ICU data (for i18n / Intl)
205
3333
std::string icu_data_dir;  // NOLINT(runtime/string)
206
#endif
207
208
// used by C++ modules as well
209
bool no_deprecation = false;
210
211
#if HAVE_OPENSSL
212
// use OpenSSL's cert store instead of bundled certs
213
bool ssl_openssl_cert_store =
214
#if defined(NODE_OPENSSL_CERT_STORE)
215
        true;
216
#else
217
        false;
218
#endif
219
220
# if NODE_FIPS_MODE
221
// used by crypto module
222
bool enable_fips_crypto = false;
223
bool force_fips_crypto = false;
224
# endif  // NODE_FIPS_MODE
225
3333
std::string openssl_config;  // NOLINT(runtime/string)
226
#endif  // HAVE_OPENSSL
227
228
// true if process warnings should be suppressed
229
bool no_process_warnings = false;
230
bool trace_warnings = false;
231
232
// Set in node.cc by ParseArgs when --preserve-symlinks is used.
233
// Used in node_config.cc to set a constant on process.binding('config')
234
// that is used by lib/module.js
235
bool config_preserve_symlinks = false;
236
237
// Set in node.cc by ParseArgs when --experimental-modules is used.
238
// Used in node_config.cc to set a constant on process.binding('config')
239
// that is used by lib/module.js
240
bool config_experimental_modules = false;
241
242
// Set in node.cc by ParseArgs when --loader is used.
243
// Used in node_config.cc to set a constant on process.binding('config')
244
// that is used by lib/internal/bootstrap_node.js
245
3333
std::string config_userland_loader;  // NOLINT(runtime/string)
246
247
// Set by ParseArgs when --pending-deprecation or NODE_PENDING_DEPRECATION
248
// is used.
249
bool config_pending_deprecation = false;
250
251
// Set in node.cc by ParseArgs when --redirect-warnings= is used.
252
3333
std::string config_warning_file;  // NOLINT(runtime/string)
253
254
// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
255
// used.
256
// Used in node_config.cc to set a constant on process.binding('config')
257
// that is used by lib/internal/bootstrap_node.js
258
bool config_expose_internals = false;
259
260
bool v8_initialized = false;
261
262
bool linux_at_secure = false;
263
264
// process-relative uptime base, initialized at start-up
265
static double prog_start_time;
266
267
3333
static Mutex node_isolate_mutex;
268
static v8::Isolate* node_isolate;
269
270
3333
node::DebugOptions debug_options;
271
272
6666
static struct {
273
#if NODE_USE_V8_PLATFORM
274
3289
  void Initialize(int thread_pool_size) {
275
3289
    if (trace_enabled) {
276
8
      tracing_agent_.reset(new tracing::Agent());
277
      platform_ = new NodePlatform(thread_pool_size,
278
8
        tracing_agent_->GetTracingController());
279
8
      V8::InitializePlatform(platform_);
280
      tracing::TraceEventHelper::SetTracingController(
281
8
        tracing_agent_->GetTracingController());
282
    } else {
283
3281
      tracing_agent_.reset(nullptr);
284
3281
      platform_ = new NodePlatform(thread_pool_size, nullptr);
285
3281
      V8::InitializePlatform(platform_);
286
      tracing::TraceEventHelper::SetTracingController(
287
3281
        new v8::TracingController());
288
    }
289
3289
  }
290
291
2946
  void Dispose() {
292
2946
    platform_->Shutdown();
293
2946
    delete platform_;
294
2946
    platform_ = nullptr;
295
2946
    tracing_agent_.reset(nullptr);
296
2946
  }
297
298
5943
  void DrainVMTasks(Isolate* isolate) {
299
5943
    platform_->DrainBackgroundTasks(isolate);
300
5943
  }
301
302
2944
  void CancelVMTasks(Isolate* isolate) {
303
2944
    platform_->CancelPendingDelayedTasks(isolate);
304
2944
  }
305
306
#if HAVE_INSPECTOR
307
3289
  bool StartInspector(Environment *env, const char* script_path,
308
                      const node::DebugOptions& options) {
309
    // Inspector agent can't fail to start, but if it was configured to listen
310
    // right away on the websocket port and fails to bind/etc, this will return
311
    // false.
312
3289
    return env->inspector_agent()->Start(platform_, script_path, options);
313
  }
314
315
64
  bool InspectorStarted(Environment *env) {
316
64
    return env->inspector_agent()->IsStarted();
317
  }
318
#endif  // HAVE_INSPECTOR
319
320
8
  void StartTracingAgent() {
321
8
    tracing_agent_->Start(trace_enabled_categories);
322
8
  }
323
324
8
  void StopTracingAgent() {
325
8
    tracing_agent_->Stop();
326
8
  }
327
328
3289
  NodePlatform* Platform() {
329
3289
    return platform_;
330
  }
331
332
  std::unique_ptr<tracing::Agent> tracing_agent_;
333
  NodePlatform* platform_;
334
#else  // !NODE_USE_V8_PLATFORM
335
  void Initialize(int thread_pool_size) {}
336
  void Dispose() {}
337
  void DrainVMTasks(Isolate* isolate) {}
338
  void CancelVMTasks(Isolate* isolate) {}
339
  bool StartInspector(Environment *env, const char* script_path,
340
                      const node::DebugOptions& options) {
341
    env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
342
    return true;
343
  }
344
345
  void StartTracingAgent() {
346
    fprintf(stderr, "Node compiled with NODE_USE_V8_PLATFORM=0, "
347
                    "so event tracing is not available.\n");
348
  }
349
  void StopTracingAgent() {}
350
351
  NodePlatform* Platform() {
352
    return nullptr;
353
  }
354
#endif  // !NODE_USE_V8_PLATFORM
355
356
#if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
357
  bool InspectorStarted(Environment *env) {
358
    return false;
359
  }
360
#endif  //  !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
361
3333
} v8_platform;
362
363
#ifdef __POSIX__
364
static const unsigned kMaxSignal = 32;
365
#endif
366
367
144
static void PrintErrorString(const char* format, ...) {
368
  va_list ap;
369
144
  va_start(ap, format);
370
#ifdef _WIN32
371
  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
372
373
  // Check if stderr is something other than a tty/console
374
  if (stderr_handle == INVALID_HANDLE_VALUE ||
375
      stderr_handle == nullptr ||
376
      uv_guess_handle(_fileno(stderr)) != UV_TTY) {
377
    vfprintf(stderr, format, ap);
378
    va_end(ap);
379
    return;
380
  }
381
382
  // Fill in any placeholders
383
  int n = _vscprintf(format, ap);
384
  std::vector<char> out(n + 1);
385
  vsprintf(out.data(), format, ap);
386
387
  // Get required wide buffer size
388
  n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
389
390
  std::vector<wchar_t> wbuf(n);
391
  MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
392
393
  // Don't include the null character in the output
394
  CHECK_GT(n, 0);
395
  WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
396
#else
397
144
  vfprintf(stderr, format, ap);
398
#endif
399
144
  va_end(ap);
400
144
}
401
402
1405
const char *signo_string(int signo) {
403
#define SIGNO_CASE(e)  case e: return #e;
404








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

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

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


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

54670
  if (zero_fill_field_ || zero_fill_all_buffers)
777
3491
    return node::UncheckedCalloc(size);
778
  else
779
51179
    return node::UncheckedMalloc(size);
780
}
781
782
namespace {
783
784
28
bool DomainHasErrorHandler(const Environment* env,
785
                           const Local<Object>& domain) {
786
28
  HandleScope scope(env->isolate());
787
788
56
  Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
789
28
  if (!domain_event_listeners_v->IsObject())
790
    return false;
791
792
  Local<Object> domain_event_listeners_o =
793
28
      domain_event_listeners_v.As<Object>();
794
795
  Local<Value> domain_error_listeners_v =
796
56
      domain_event_listeners_o->Get(env->error_string());
797
798

140
  if (domain_error_listeners_v->IsFunction() ||
799
1
      (domain_error_listeners_v->IsArray() &&
800
28
      domain_error_listeners_v.As<Array>()->Length() > 0))
801
27
    return true;
802
803
1
  return false;
804
}
805
806
27
bool DomainsStackHasErrorHandler(const Environment* env) {
807
27
  HandleScope scope(env->isolate());
808
809
27
  if (!env->using_domains())
810
    return false;
811
812
54
  Local<Array> domains_stack_array = env->domains_stack_array().As<Array>();
813
27
  if (domains_stack_array->Length() == 0)
814
    return false;
815
816
27
  uint32_t domains_stack_length = domains_stack_array->Length();
817
56
  for (uint32_t i = domains_stack_length; i > 0; --i) {
818
56
    Local<Value> domain_v = domains_stack_array->Get(i - 1);
819
28
    if (!domain_v->IsObject())
820
27
      return false;
821
822
28
    Local<Object> domain = domain_v.As<Object>();
823
28
    if (DomainHasErrorHandler(env, domain))
824
27
      return true;
825
  }
826
827
  return false;
828
}
829
830
831
27
bool ShouldAbortOnUncaughtException(Isolate* isolate) {
832
27
  HandleScope scope(isolate);
833
834
27
  Environment* env = Environment::GetCurrent(isolate);
835
27
  Local<Object> process_object = env->process_object();
836
  Local<String> emitting_top_level_domain_error_key =
837
27
    env->emitting_top_level_domain_error_string();
838
  bool isEmittingTopLevelDomainError =
839
54
      process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
840
841

27
  return isEmittingTopLevelDomainError || !DomainsStackHasErrorHandler(env);
842
}
843
844
1923
Local<Value> GetDomainProperty(Environment* env, Local<Object> object) {
845
  Local<Value> domain_v =
846
3846
      object->GetPrivate(env->context(), env->domain_private_symbol())
847
3846
          .ToLocalChecked();
848
1923
  if (domain_v->IsObject()) {
849
    return domain_v;
850
  }
851
7692
  return object->Get(env->context(), env->domain_string()).ToLocalChecked();
852
}
853
854
855
1480
void DomainEnter(Environment* env, Local<Object> object) {
856
1480
  Local<Value> domain_v = GetDomainProperty(env, object);
857
1480
  if (domain_v->IsObject()) {
858
22
    Local<Object> domain = domain_v.As<Object>();
859
44
    Local<Value> enter_v = domain->Get(env->enter_string());
860
22
    if (enter_v->IsFunction()) {
861
66
      if (enter_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
862
        FatalError("node::AsyncWrap::MakeCallback",
863
                   "domain enter callback threw, please report this");
864
      }
865
    }
866
  }
867
1480
}
868
869
870
443
void DomainExit(Environment* env, v8::Local<v8::Object> object) {
871
443
  Local<Value> domain_v = GetDomainProperty(env, object);
872
443
  if (domain_v->IsObject()) {
873
16
    Local<Object> domain = domain_v.As<Object>();
874
32
    Local<Value> exit_v = domain->Get(env->exit_string());
875
16
    if (exit_v->IsFunction()) {
876
48
      if (exit_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
877
        FatalError("node::AsyncWrap::MakeCallback",
878
                  "domain exit callback threw, please report this");
879
      }
880
    }
881
  }
882
443
}
883
884
139
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
885
139
  Environment* env = Environment::GetCurrent(args);
886
887
139
  if (env->using_domains())
888
139
    return;
889
139
  env->set_using_domains(true);
890
891
139
  HandleScope scope(env->isolate());
892
139
  Local<Object> process_object = env->process_object();
893
894
278
  CHECK(args[0]->IsArray());
895
278
  env->set_domains_stack_array(args[0].As<Array>());
896
897
  // Do a little housekeeping.
898
  env->process_object()->Delete(
899
      env->context(),
900
695
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
901
}
902
903
904
64903
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
905
64903
  args.GetIsolate()->RunMicrotasks();
906
64897
}
907
908
909
3287
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
910
3287
  Environment* env = Environment::GetCurrent(args);
911
912
6574
  CHECK(args[0]->IsFunction());
913
914
6574
  env->set_push_values_to_array_function(args[0].As<Function>());
915
  env->process_object()->Delete(
916
      env->context(),
917
13148
      FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
918
3287
}
919
920
921
3287
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
922
3287
  Environment* env = Environment::GetCurrent(args);
923
924
6574
  CHECK(args[0]->IsFunction());
925
6574
  CHECK(args[1]->IsObject());
926
927
6574
  env->set_tick_callback_function(args[0].As<Function>());
928
929
6574
  env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
930
931
  // Do a little housekeeping.
932
  env->process_object()->Delete(
933
      env->context(),
934
16435
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust();
935
936
  // Values use to cross communicate with processNextTick.
937
3287
  uint32_t* const fields = env->tick_info()->fields();
938
3287
  uint32_t const fields_count = env->tick_info()->fields_count();
939
940
  Local<ArrayBuffer> array_buffer =
941
3287
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
942
943
9861
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
944
3287
}
945
946
7166
void PromiseRejectCallback(PromiseRejectMessage message) {
947
7166
  Local<Promise> promise = message.GetPromise();
948
7166
  Isolate* isolate = promise->GetIsolate();
949
7166
  Local<Value> value = message.GetValue();
950
7166
  Local<Integer> event = Integer::New(isolate, message.GetEvent());
951
952
7166
  Environment* env = Environment::GetCurrent(isolate);
953
7166
  Local<Function> callback = env->promise_reject_function();
954
955
7166
  if (value.IsEmpty())
956
91
    value = Undefined(isolate);
957
958
21498
  Local<Value> args[] = { event, promise, value };
959
7166
  Local<Object> process = env->process_object();
960
961
14332
  callback->Call(process, arraysize(args), args);
962
7166
}
963
964
3287
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
965
3287
  Environment* env = Environment::GetCurrent(args);
966
3287
  Isolate* isolate = env->isolate();
967
968
6574
  CHECK(args[0]->IsFunction());
969
970
3287
  isolate->SetPromiseRejectCallback(PromiseRejectCallback);
971
6574
  env->set_promise_reject_function(args[0].As<Function>());
972
973
  env->process_object()->Delete(
974
      env->context(),
975
13148
      FIXED_ONE_BYTE_STRING(isolate, "_setupPromises")).FromJust();
976
3287
}
977
978
}  // anonymous namespace
979
980
981
void AddPromiseHook(v8::Isolate* isolate, promise_hook_func fn, void* arg) {
982
  Environment* env = Environment::GetCurrent(isolate);
983
  env->AddPromiseHook(fn, arg);
984
}
985
986
13
CallbackScope::CallbackScope(Isolate* isolate,
987
                             Local<Object> object,
988
                             async_context asyncContext)
989
  : private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
990
                                       object,
991
13
                                       asyncContext)),
992
26
    try_catch_(isolate) {
993
13
  try_catch_.SetVerbose(true);
994
13
}
995
996
24
CallbackScope::~CallbackScope() {
997
12
  if (try_catch_.HasCaught())
998
1
    private_->MarkAsFailed();
999
12
  delete private_;
1000
12
}
1001
1002
2220
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
1003
    : InternalCallbackScope(async_wrap->env(),
1004
                            async_wrap->object(),
1005
2220
                            { async_wrap->get_async_id(),
1006
2220
                              async_wrap->get_trigger_async_id() }) {}
1007
1008
404086
InternalCallbackScope::InternalCallbackScope(Environment* env,
1009
                                             Local<Object> object,
1010
                                             const async_context& asyncContext,
1011
                                             ResourceExpectation expect)
1012
  : env_(env),
1013
    async_context_(asyncContext),
1014
    object_(object),
1015
404086
    callback_scope_(env) {
1016
404086
  if (expect == kRequireResource) {
1017
403244
    CHECK(!object.IsEmpty());
1018
  }
1019
1020
404086
  HandleScope handle_scope(env->isolate());
1021
  // If you hit this assertion, you forgot to enter the v8::Context first.
1022
404086
  CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
1023
1024


405583
  if (asyncContext.async_id == 0 && env->using_domains() &&
1025
2994
      !object_.IsEmpty()) {
1026
1480
    DomainEnter(env, object_);
1027
  }
1028
1029
404086
  if (asyncContext.async_id != 0) {
1030
    // No need to check a return value because the application will exit if
1031
    // an exception occurs.
1032
330836
    AsyncWrap::EmitBefore(env, asyncContext.async_id);
1033
  }
1034
1035
  env->async_hooks()->push_async_ids(async_context_.async_id,
1036
404086
                               async_context_.trigger_async_id);
1037
404086
  pushed_ids_ = true;
1038
404086
}
1039
1040
807920
InternalCallbackScope::~InternalCallbackScope() {
1041
403960
  Close();
1042
403960
}
1043
1044
803821
void InternalCallbackScope::Close() {
1045
1546033
  if (closed_) return;
1046
404030
  closed_ = true;
1047
404030
  HandleScope handle_scope(env_->isolate());
1048
1049
404030
  if (pushed_ids_)
1050
404030
    env_->async_hooks()->pop_async_id(async_context_.async_id);
1051
1052
404030
  if (failed_) return;
1053
1054
402934
  if (async_context_.async_id != 0) {
1055
330742
    AsyncWrap::EmitAfter(env_, async_context_.async_id);
1056
  }
1057
1058


403394
  if (async_context_.async_id == 0 && env_->using_domains() &&
1059
920
      !object_.IsEmpty()) {
1060
443
    DomainExit(env_, object_);
1061
  }
1062
1063
402934
  if (IsInnerMakeCallback()) {
1064
35211
    return;
1065
  }
1066
1067
367723
  Environment::TickInfo* tick_info = env_->tick_info();
1068
1069
367723
  if (tick_info->length() == 0) {
1070
306194
    env_->isolate()->RunMicrotasks();
1071
  }
1072
1073
  // Make sure the stack unwound properly. If there are nested MakeCallback's
1074
  // then it should return early and not reach this code.
1075
367722
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
1076
61659
    CHECK_EQ(env_->execution_async_id(), 0);
1077
61659
    CHECK_EQ(env_->trigger_async_id(), 0);
1078
  }
1079
1080
367722
  Local<Object> process = env_->process_object();
1081
1082
367722
  if (tick_info->length() == 0) {
1083
306114
    tick_info->set_index(0);
1084
306114
    return;
1085
  }
1086
1087
61608
  if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
1088
586
    CHECK_EQ(env_->execution_async_id(), 0);
1089
586
    CHECK_EQ(env_->trigger_async_id(), 0);
1090
  }
1091
1092
184755
  if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1093
22
    failed_ = true;
1094
61539
  }
1095
}
1096
1097
401011
MaybeLocal<Value> InternalMakeCallback(Environment* env,
1098
                                       Local<Object> recv,
1099
                                       const Local<Function> callback,
1100
                                       int argc,
1101
                                       Local<Value> argv[],
1102
                                       async_context asyncContext) {
1103
401011
  CHECK(!recv.IsEmpty());
1104
401011
  InternalCallbackScope scope(env, recv, asyncContext);
1105
401011
  if (scope.Failed()) {
1106
    return Undefined(env->isolate());
1107
  }
1108
1109
  MaybeLocal<Value> ret;
1110
1111
  {
1112
802022
    ret = callback->Call(env->context(), recv, argc, argv);
1113
1114
400956
    if (ret.IsEmpty()) {
1115
      // NOTE: For backwards compatibility with public API we return Undefined()
1116
      // if the top level call threw.
1117
1095
      scope.MarkAsFailed();
1118
2190
      return scope.IsInnerMakeCallback() ? ret : Undefined(env->isolate());
1119
    }
1120
  }
1121
1122
399861
  scope.Close();
1123
399791
  if (scope.Failed()) {
1124
44
    return Undefined(env->isolate());
1125
  }
1126
1127
399769
  return ret;
1128
}
1129
1130
1131
// Public MakeCallback()s
1132
1133
1134
5948
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1135
                               Local<Object> recv,
1136
                               const char* method,
1137
                               int argc,
1138
                               Local<Value> argv[],
1139
                               async_context asyncContext) {
1140
  Local<String> method_string =
1141
      String::NewFromUtf8(isolate, method, v8::NewStringType::kNormal)
1142
11896
          .ToLocalChecked();
1143
5948
  return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
1144
}
1145
1146
1147
72365
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1148
                               Local<Object> recv,
1149
                               Local<String> symbol,
1150
                               int argc,
1151
                               Local<Value> argv[],
1152
                               async_context asyncContext) {
1153
72365
  Local<Value> callback_v = recv->Get(symbol);
1154
72365
  if (callback_v.IsEmpty()) return Local<Value>();
1155
72365
  if (!callback_v->IsFunction()) return Local<Value>();
1156
72365
  Local<Function> callback = callback_v.As<Function>();
1157
72365
  return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
1158
}
1159
1160
1161
72417
MaybeLocal<Value> MakeCallback(Isolate* isolate,
1162
                               Local<Object> recv,
1163
                               Local<Function> callback,
1164
                               int argc,
1165
                               Local<Value> argv[],
1166
                               async_context asyncContext) {
1167
  // Observe the following two subtleties:
1168
  //
1169
  // 1. The environment is retrieved from the callback function's context.
1170
  // 2. The context to enter is retrieved from the environment.
1171
  //
1172
  // Because of the AssignToContext() call in src/node_contextify.cc,
1173
  // the two contexts need not be the same.
1174
72417
  Environment* env = Environment::GetCurrent(callback->CreationContext());
1175
72417
  Context::Scope context_scope(env->context());
1176
  return InternalMakeCallback(env, recv, callback,
1177
144824
                              argc, argv, asyncContext);
1178
}
1179
1180
1181
// Legacy MakeCallback()s
1182
1183
Local<Value> MakeCallback(Isolate* isolate,
1184
                          Local<Object> recv,
1185
                          const char* method,
1186
                          int argc,
1187
                          Local<Value>* argv) {
1188
  EscapableHandleScope handle_scope(isolate);
1189
  return handle_scope.Escape(
1190
      MakeCallback(isolate, recv, method, argc, argv, {0, 0})
1191
          .FromMaybe(Local<Value>()));
1192
}
1193
1194
1195
5
Local<Value> MakeCallback(Isolate* isolate,
1196
    Local<Object> recv,
1197
    Local<String> symbol,
1198
    int argc,
1199
    Local<Value>* argv) {
1200
5
  EscapableHandleScope handle_scope(isolate);
1201
  return handle_scope.Escape(
1202
5
      MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
1203
15
          .FromMaybe(Local<Value>()));
1204
}
1205
1206
1207
24
Local<Value> MakeCallback(Isolate* isolate,
1208
    Local<Object> recv,
1209
    Local<Function> callback,
1210
    int argc,
1211
    Local<Value>* argv) {
1212
24
  EscapableHandleScope handle_scope(isolate);
1213
  return handle_scope.Escape(
1214
24
      MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
1215
72
          .FromMaybe(Local<Value>()));
1216
}
1217
1218
1219
216534
enum encoding ParseEncoding(const char* encoding,
1220
                            enum encoding default_encoding) {
1221

216534
  switch (encoding[0]) {
1222
    case 'u':
1223
      // utf8, utf16le
1224

109684
      if (encoding[1] == 't' && encoding[2] == 'f') {
1225
        // Skip `-`
1226
109493
        encoding += encoding[3] == '-' ? 4 : 3;
1227

109493
        if (encoding[0] == '8' && encoding[1] == '\0')
1228
109476
          return UTF8;
1229
17
        if (strncmp(encoding, "16le", 4) == 0)
1230
17
          return UCS2;
1231
1232
      // ucs2
1233

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

190
        if (encoding[0] == '2' && encoding[1] == '\0')
1236
190
          return UCS2;
1237
      }
1238
1
      break;
1239
    case 'l':
1240
      // latin1
1241
52402
      if (encoding[1] == 'a') {
1242
52400
        if (strncmp(encoding + 2, "tin1", 4) == 0)
1243
52400
          return LATIN1;
1244
      }
1245
2
      break;
1246
    case 'b':
1247
      // binary
1248
26323
      if (encoding[1] == 'i') {
1249
30
        if (strncmp(encoding + 2, "nary", 4) == 0)
1250
30
          return LATIN1;
1251
1252
      // buffer
1253
26293
      } else if (encoding[1] == 'u') {
1254
26014
        if (strncmp(encoding + 2, "ffer", 4) == 0)
1255
26014
          return BUFFER;
1256
      }
1257
279
      break;
1258
    case '\0':
1259
1
      return default_encoding;
1260
    default:
1261
28124
      break;
1262
  }
1263
1264
28406
  if (StringEqualNoCase(encoding, "utf8")) {
1265
    return UTF8;
1266
28406
  } else if (StringEqualNoCase(encoding, "utf-8")) {
1267
3
    return UTF8;
1268
28403
  } else if (StringEqualNoCase(encoding, "ascii")) {
1269
49
    return ASCII;
1270
28354
  } else if (StringEqualNoCase(encoding, "base64")) {
1271
277
    return BASE64;
1272
28077
  } else if (StringEqualNoCase(encoding, "ucs2")) {
1273
    return UCS2;
1274
28077
  } else if (StringEqualNoCase(encoding, "ucs-2")) {
1275
    return UCS2;
1276
28077
  } else if (StringEqualNoCase(encoding, "utf16le")) {
1277
    return UCS2;
1278
28077
  } else if (StringEqualNoCase(encoding, "utf-16le")) {
1279
    return UCS2;
1280
28077
  } else if (StringEqualNoCase(encoding, "latin1")) {
1281
    return LATIN1;
1282
28077
  } else if (StringEqualNoCase(encoding, "binary")) {
1283
    return LATIN1;  // BINARY is a deprecated alias of LATIN1.
1284
28077
  } else if (StringEqualNoCase(encoding, "buffer")) {
1285
    return BUFFER;
1286
28077
  } else if (StringEqualNoCase(encoding, "hex")) {
1287
28072
    return HEX;
1288
  } else {
1289
5
    return default_encoding;
1290
  }
1291
}
1292
1293
1294
220478
enum encoding ParseEncoding(Isolate* isolate,
1295
                            Local<Value> encoding_v,
1296
                            enum encoding default_encoding) {
1297
220478
  CHECK(!encoding_v.IsEmpty());
1298
1299
440956
  if (!encoding_v->IsString())
1300
3944
    return default_encoding;
1301
1302
216534
  node::Utf8Value encoding(isolate, encoding_v);
1303
1304
216534
  return ParseEncoding(*encoding, default_encoding);
1305
}
1306
1307
2
Local<Value> Encode(Isolate* isolate,
1308
                    const char* buf,
1309
                    size_t len,
1310
                    enum encoding encoding) {
1311
2
  CHECK_NE(encoding, UCS2);
1312
  Local<Value> error;
1313
  return StringBytes::Encode(isolate, buf, len, encoding, &error)
1314
4
      .ToLocalChecked();
1315
}
1316
1317
Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1318
  Local<Value> error;
1319
  return StringBytes::Encode(isolate, buf, len, &error)
1320
      .ToLocalChecked();
1321
}
1322
1323
// Returns -1 if the handle was not valid for decoding
1324
ssize_t DecodeBytes(Isolate* isolate,
1325
                    Local<Value> val,
1326
                    enum encoding encoding) {
1327
  HandleScope scope(isolate);
1328
1329
  return StringBytes::Size(isolate, val, encoding);
1330
}
1331
1332
// Returns number of bytes written.
1333
ssize_t DecodeWrite(Isolate* isolate,
1334
                    char* buf,
1335
                    size_t buflen,
1336
                    Local<Value> val,
1337
                    enum encoding encoding) {
1338
  return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1339
}
1340
1341
432
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
1342

864
  if (!er.IsEmpty() && er->IsObject()) {
1343
426
    Local<Object> err_obj = er.As<Object>();
1344
    auto maybe_value =
1345
852
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
1346
    Local<Value> decorated;
1347

852
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
1348
  }
1349
6
  return false;
1350
}
1351
1352
429
void AppendExceptionLine(Environment* env,
1353
                         Local<Value> er,
1354
                         Local<Message> message,
1355
                         enum ErrorHandlingMode mode) {
1356
429
  if (message.IsEmpty())
1357
53
    return;
1358
1359
429
  HandleScope scope(env->isolate());
1360
  Local<Object> err_obj;
1361

858
  if (!er.IsEmpty() && er->IsObject()) {
1362
423
    err_obj = er.As<Object>();
1363
1364
423
    auto context = env->context();
1365
423
    auto processed_private_symbol = env->processed_private_symbol();
1366
    // Do it only once per message
1367
846
    if (err_obj->HasPrivate(context, processed_private_symbol).FromJust())
1368
43
      return;
1369
    err_obj->SetPrivate(
1370
        context,
1371
        processed_private_symbol,
1372
760
        True(env->isolate()));
1373
  }
1374
1375
  // Print (filename):(line number): (message).
1376
386
  ScriptOrigin origin = message->GetScriptOrigin();
1377
762
  node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1378
386
  const char* filename_string = *filename;
1379
386
  int linenum = message->GetLineNumber();
1380
  // Print line of source code.
1381
1148
  node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1382
386
  const char* sourceline_string = *sourceline;
1383
1384
  // Because of how node modules work, all scripts are wrapped with a
1385
  // "function (module, exports, __filename, ...) {"
1386
  // to provide script local variables.
1387
  //
1388
  // When reporting errors on the first line of a script, this wrapper
1389
  // function is leaked to the user. There used to be a hack here to
1390
  // truncate off the first 62 characters, but it caused numerous other
1391
  // problems when vm.runIn*Context() methods were used for non-module
1392
  // code.
1393
  //
1394
  // If we ever decide to re-instate such a hack, the following steps
1395
  // must be taken:
1396
  //
1397
  // 1. Pass a flag around to say "this code was wrapped"
1398
  // 2. Update the stack frame output so that it is also correct.
1399
  //
1400
  // It would probably be simpler to add a line rather than add some
1401
  // number of characters to the first line, since V8 truncates the
1402
  // sourceline to 78 characters, and we end up not providing very much
1403
  // useful debugging info to the user if we remove 62 characters.
1404
1405
  int script_start =
1406
1544
      (linenum - origin.ResourceLineOffset()->Value()) == 1 ?
1407

670
          origin.ResourceColumnOffset()->Value() : 0;
1408
1158
  int start = message->GetStartColumn(env->context()).FromMaybe(0);
1409
1158
  int end = message->GetEndColumn(env->context()).FromMaybe(0);
1410
386
  if (start >= script_start) {
1411
386
    CHECK_GE(end, start);
1412
386
    start -= script_start;
1413
386
    end -= script_start;
1414
  }
1415
1416
  char arrow[1024];
1417
386
  int max_off = sizeof(arrow) - 2;
1418
1419
  int off = snprintf(arrow,
1420
                     sizeof(arrow),
1421
                     "%s:%i\n%s\n",
1422
                     filename_string,
1423
                     linenum,
1424
386
                     sourceline_string);
1425
386
  CHECK_GE(off, 0);
1426
386
  if (off > max_off) {
1427
120
    off = max_off;
1428
  }
1429
1430
  // Print wavy underline (GetUnderline is deprecated).
1431
9162
  for (int i = 0; i < start; i++) {
1432

8900
    if (sourceline_string[i] == '\0' || off >= max_off) {
1433
      break;
1434
    }
1435
8776
    CHECK_LT(off, max_off);
1436
8776
    arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1437
  }
1438
1086
  for (int i = start; i < end; i++) {
1439

844
    if (sourceline_string[i] == '\0' || off >= max_off) {
1440
      break;
1441
    }
1442
700
    CHECK_LT(off, max_off);
1443
700
    arrow[off++] = '^';
1444
  }
1445
386
  CHECK_LE(off, max_off);
1446
386
  arrow[off] = '\n';
1447
386
  arrow[off + 1] = '\0';
1448
1449
386
  Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1450
1451

772
  const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
1452
  // If allocating arrow_str failed, print it out. There's not much else to do.
1453
  // If it's not an error, but something needs to be printed out because
1454
  // it's a fatal exception, also print it out from here.
1455
  // Otherwise, the arrow property will be attached to the object and handled
1456
  // by the caller.
1457


456
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
1458
10
    if (env->printed_error())
1459
      return;
1460
10
    env->set_printed_error(true);
1461
1462
10
    uv_tty_reset_mode();
1463
10
    PrintErrorString("\n%s", arrow);
1464
10
    return;
1465
  }
1466
1467

1504
  CHECK(err_obj->SetPrivate(
1468
            env->context(),
1469
            env->arrow_message_private_symbol(),
1470
376
            arrow_str).FromMaybe(false));
1471
}
1472
1473
1474
119
static void ReportException(Environment* env,
1475
                            Local<Value> er,
1476
                            Local<Message> message) {
1477
119
  HandleScope scope(env->isolate());
1478
1479
119
  AppendExceptionLine(env, er, message, FATAL_ERROR);
1480
1481
  Local<Value> trace_value;
1482
  Local<Value> arrow;
1483
119
  const bool decorated = IsExceptionDecorated(env, er);
1484
1485

474
  if (er->IsUndefined() || er->IsNull()) {
1486
4
    trace_value = Undefined(env->isolate());
1487
  } else {
1488
234
    Local<Object> err_obj = er->ToObject(env->isolate());
1489
1490
234
    trace_value = err_obj->Get(env->stack_string());
1491
    arrow =
1492
        err_obj->GetPrivate(
1493
            env->context(),
1494
351
            env->arrow_message_private_symbol()).ToLocalChecked();
1495
  }
1496
1497
238
  node::Utf8Value trace(env->isolate(), trace_value);
1498
1499
  // range errors have a trace member set to undefined
1500

357
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1501


327
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1502
43
      PrintErrorString("%s\n", *trace);
1503
    } else {
1504
66
      node::Utf8Value arrow_string(env->isolate(), arrow);
1505
66
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1506
    }
1507
  } else {
1508
    // this really only happens for RangeErrors, since they're the only
1509
    // kind that won't have all this info in the trace, or when non-Error
1510
    // objects are thrown manually.
1511
    Local<Value> message;
1512
    Local<Value> name;
1513
1514
10
    if (er->IsObject()) {
1515
4
      Local<Object> err_obj = er.As<Object>();
1516
8
      message = err_obj->Get(env->message_string());
1517
8
      name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1518
    }
1519
1520

24
    if (message.IsEmpty() ||
1521
9
        message->IsUndefined() ||
1522

12
        name.IsEmpty() ||
1523
2
        name->IsUndefined()) {
1524
      // Not an error object. Just print as-is.
1525
9
      String::Utf8Value message(er);
1526
1527
9
      PrintErrorString("%s\n", *message ? *message :
1528
9
                                          "<toString() threw exception>");
1529
    } else {
1530
1
      node::Utf8Value name_string(env->isolate(), name);
1531
2
      node::Utf8Value message_string(env->isolate(), message);
1532
1533


3
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1534
1
        PrintErrorString("%s: %s\n", *name_string, *message_string);
1535
      } else {
1536
        node::Utf8Value arrow_string(env->isolate(), arrow);
1537
        PrintErrorString("%s\n%s: %s\n",
1538
                         *arrow_string,
1539
                         *name_string,
1540
                         *message_string);
1541
1
      }
1542
    }
1543
  }
1544
1545
238
  fflush(stderr);
1546
119
}
1547
1548
1549
2
static void ReportException(Environment* env, const TryCatch& try_catch) {
1550
2
  ReportException(env, try_catch.Exception(), try_catch.Message());
1551
2
}
1552
1553
1554
// Executes a str within the current v8 context.
1555
3287
static Local<Value> ExecuteString(Environment* env,
1556
                                  Local<String> source,
1557
                                  Local<String> filename) {
1558
3287
  EscapableHandleScope scope(env->isolate());
1559
6574
  TryCatch try_catch(env->isolate());
1560
1561
  // try_catch must be nonverbose to disable FatalException() handler,
1562
  // we will handle exceptions ourself.
1563
3287
  try_catch.SetVerbose(false);
1564
1565
3287
  ScriptOrigin origin(filename);
1566
  MaybeLocal<v8::Script> script =
1567
3287
      v8::Script::Compile(env->context(), source, &origin);
1568
3287
  if (script.IsEmpty()) {
1569
    ReportException(env, try_catch);
1570
    exit(3);
1571
  }
1572
1573
6574
  Local<Value> result = script.ToLocalChecked()->Run();
1574
3287
  if (result.IsEmpty()) {
1575
    ReportException(env, try_catch);
1576
    exit(4);
1577
  }
1578
1579
3287
  return scope.Escape(result);
1580
}
1581
1582
1583
1
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1584
1
  Environment* env = Environment::GetCurrent(args);
1585
1586
1
  Local<Array> ary = Array::New(args.GetIsolate());
1587
1
  Local<Context> ctx = env->context();
1588
1
  Local<Function> fn = env->push_values_to_array_function();
1589
9
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1590
1
  size_t idx = 0;
1591
1592
13
  for (auto w : *env->req_wrap_queue()) {
1593
24
    if (w->persistent().IsEmpty())
1594
      continue;
1595
24
    argv[idx] = w->object();
1596
12
    if (++idx >= arraysize(argv)) {
1597
3
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1598
1
      idx = 0;
1599
    }
1600
  }
1601
1602
1
  if (idx > 0) {
1603
3
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1604
  }
1605
1606
2
  args.GetReturnValue().Set(ary);
1607
1
}
1608
1609
1610
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1611
// implemented here for consistency with GetActiveRequests().
1612
6
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1613
6
  Environment* env = Environment::GetCurrent(args);
1614
1615
6
  Local<Array> ary = Array::New(env->isolate());
1616
6
  Local<Context> ctx = env->context();
1617
6
  Local<Function> fn = env->push_values_to_array_function();
1618
54
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1619
6
  size_t idx = 0;
1620
1621
6
  Local<String> owner_sym = env->owner_string();
1622
1623
38
  for (auto w : *env->handle_wrap_queue()) {
1624

64
    if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
1625
4
      continue;
1626
28
    Local<Object> object = w->object();
1627
28
    Local<Value> owner = object->Get(owner_sym);
1628
56
    if (owner->IsUndefined())
1629
5
      owner = object;
1630
28
    argv[idx] = owner;
1631
28
    if (++idx >= arraysize(argv)) {
1632
6
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1633
2
      idx = 0;
1634
    }
1635
  }
1636
6
  if (idx > 0) {
1637
15
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1638
  }
1639
1640
12
  args.GetReturnValue().Set(ary);
1641
6
}
1642
1643
1644
NO_RETURN void Abort() {
1645
  DumpBacktrace(stderr);
1646
  fflush(stderr);
1647
  ABORT_NO_BACKTRACE();
1648
}
1649
1650
1651
NO_RETURN void Assert(const char* const (*args)[4]) {
1652
  auto filename = (*args)[0];
1653
  auto linenum = (*args)[1];
1654
  auto message = (*args)[2];
1655
  auto function = (*args)[3];
1656
1657
  char exepath[256];
1658
  size_t exepath_size = sizeof(exepath);
1659
  if (uv_exepath(exepath, &exepath_size))
1660
    snprintf(exepath, sizeof(exepath), "node");
1661
1662
  char pid[12] = {0};
1663
#ifndef _WIN32
1664
  snprintf(pid, sizeof(pid), "[%u]", getpid());
1665
#endif
1666
1667
  fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
1668
          exepath, pid, filename, linenum,
1669
          function, *function ? ":" : "", message);
1670
  fflush(stderr);
1671
1672
  Abort();
1673
}
1674
1675
1676
static void Abort(const FunctionCallbackInfo<Value>& args) {
1677
  Abort();
1678
}
1679
1680
1681
109
static void Chdir(const FunctionCallbackInfo<Value>& args) {
1682
109
  Environment* env = Environment::GetCurrent(args);
1683
1684


539
  if (args.Length() != 1 || !args[0]->IsString()) {
1685
6
    return env->ThrowTypeError("Bad argument.");
1686
  }
1687
1688
106
  node::Utf8Value path(args.GetIsolate(), args[0]);
1689
106
  int err = uv_chdir(*path);
1690
106
  if (err) {
1691
    return env->ThrowUVException(err, "uv_chdir");
1692
106
  }
1693
}
1694
1695
1696
10625
static void Cwd(const FunctionCallbackInfo<Value>& args) {
1697
10625
  Environment* env = Environment::GetCurrent(args);
1698
#ifdef _WIN32
1699
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1700
  char buf[MAX_PATH * 4];
1701
#else
1702
  char buf[PATH_MAX];
1703
#endif
1704
1705
10625
  size_t cwd_len = sizeof(buf);
1706
10625
  int err = uv_cwd(buf, &cwd_len);
1707
10625
  if (err) {
1708
10638
    return env->ThrowUVException(err, "uv_cwd");
1709
  }
1710
1711
  Local<String> cwd = String::NewFromUtf8(env->isolate(),
1712
                                          buf,
1713
                                          String::kNormalString,
1714
10612
                                          cwd_len);
1715
21224
  args.GetReturnValue().Set(cwd);
1716
}
1717
1718
1719
1316
static void Umask(const FunctionCallbackInfo<Value>& args) {
1720
1316
  Environment* env = Environment::GetCurrent(args);
1721
  uint32_t old;
1722
1723


2647
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1724
1311
    old = umask(0);
1725
1311
    umask(static_cast<mode_t>(old));
1726


24
  } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1727
1
    return env->ThrowTypeError("argument must be an integer or octal string.");
1728
  } else {
1729
    int oct;
1730
8
    if (args[0]->IsInt32()) {
1731
4
      oct = args[0]->Uint32Value();
1732
    } else {
1733
2
      oct = 0;
1734
2
      node::Utf8Value str(env->isolate(), args[0]);
1735
1736
      // Parse the octal string.
1737

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

8
        if (c > '7' || c < '0') {
1740
1
          return env->ThrowTypeError("invalid octal string");
1741
        }
1742
7
        oct *= 8;
1743
7
        oct += c - '0';
1744
1
      }
1745
    }
1746
3
    old = umask(static_cast<mode_t>(oct));
1747
  }
1748
1749
2628
  args.GetReturnValue().Set(old);
1750
}
1751
1752
1753
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
1754
1755
static const uid_t uid_not_found = static_cast<uid_t>(-1);
1756
static const gid_t gid_not_found = static_cast<gid_t>(-1);
1757
1758
1759
4
static uid_t uid_by_name(const char* name) {
1760
  struct passwd pwd;
1761
  struct passwd* pp;
1762
  char buf[8192];
1763
1764
4
  errno = 0;
1765
4
  pp = nullptr;
1766
1767

4
  if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1768
2
    return pp->pw_uid;
1769
  }
1770
1771
2
  return uid_not_found;
1772
}
1773
1774
1775
static char* name_by_uid(uid_t uid) {
1776
  struct passwd pwd;
1777
  struct passwd* pp;
1778
  char buf[8192];
1779
  int rc;
1780
1781
  errno = 0;
1782
  pp = nullptr;
1783
1784
  if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1785
      pp != nullptr) {
1786
    return strdup(pp->pw_name);
1787
  }
1788
1789
  if (rc == 0) {
1790
    errno = ENOENT;
1791
  }
1792
1793
  return nullptr;
1794
}
1795
1796
1797
2
static gid_t gid_by_name(const char* name) {
1798
  struct group pwd;
1799
  struct group* pp;
1800
  char buf[8192];
1801
1802
2
  errno = 0;
1803
2
  pp = nullptr;
1804
1805

2
  if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1806
    return pp->gr_gid;
1807
  }
1808
1809
2
  return gid_not_found;
1810
}
1811
1812
1813
#if 0  // For future use.
1814
static const char* name_by_gid(gid_t gid) {
1815
  struct group pwd;
1816
  struct group* pp;
1817
  char buf[8192];
1818
  int rc;
1819
1820
  errno = 0;
1821
  pp = nullptr;
1822
1823
  if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1824
      pp != nullptr) {
1825
    return strdup(pp->gr_name);
1826
  }
1827
1828
  if (rc == 0) {
1829
    errno = ENOENT;
1830
  }
1831
1832
  return nullptr;
1833
}
1834
#endif
1835
1836
1837
4
static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1838
4
  if (value->IsUint32()) {
1839
    return static_cast<uid_t>(value->Uint32Value());
1840
  } else {
1841
4
    node::Utf8Value name(isolate, value);
1842
4
    return uid_by_name(*name);
1843
  }
1844
}
1845
1846
1847
2
static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1848
2
  if (value->IsUint32()) {
1849
    return static_cast<gid_t>(value->Uint32Value());
1850
  } else {
1851
2
    node::Utf8Value name(isolate, value);
1852
2
    return gid_by_name(*name);
1853
  }
1854
}
1855
1856
359
static void GetUid(const FunctionCallbackInfo<Value>& args) {
1857
  // uid_t is an uint32_t on all supported platforms.
1858
1077
  args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1859
359
}
1860
1861
1862
347
static void GetGid(const FunctionCallbackInfo<Value>& args) {
1863
  // gid_t is an uint32_t on all supported platforms.
1864
1041
  args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1865
347
}
1866
1867
1868
1
static void GetEUid(const FunctionCallbackInfo<Value>& args) {
1869
  // uid_t is an uint32_t on all supported platforms.
1870
3
  args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
1871
1
}
1872
1873
1874
1
static void GetEGid(const FunctionCallbackInfo<Value>& args) {
1875
  // gid_t is an uint32_t on all supported platforms.
1876
3
  args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
1877
1
}
1878
1879
1880
1
static void SetGid(const FunctionCallbackInfo<Value>& args) {
1881
1
  Environment* env = Environment::GetCurrent(args);
1882
1883


6
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1884
    return env->ThrowTypeError("setgid argument must be a number or a string");
1885
  }
1886
1887
1
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1888
1889
1
  if (gid == gid_not_found) {
1890
1
    return env->ThrowError("setgid group id does not exist");
1891
  }
1892
1893
  if (setgid(gid)) {
1894
    return env->ThrowErrnoException(errno, "setgid");
1895
  }
1896
}
1897
1898
1899
1
static void SetEGid(const FunctionCallbackInfo<Value>& args) {
1900
1
  Environment* env = Environment::GetCurrent(args);
1901
1902


6
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1903
    return env->ThrowTypeError("setegid argument must be a number or string");
1904
  }
1905
1906
1
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1907
1908
1
  if (gid == gid_not_found) {
1909
1
    return env->ThrowError("setegid group id does not exist");
1910
  }
1911
1912
  if (setegid(gid)) {
1913
    return env->ThrowErrnoException(errno, "setegid");
1914
  }
1915
}
1916
1917
1918
2
static void SetUid(const FunctionCallbackInfo<Value>& args) {
1919
2
  Environment* env = Environment::GetCurrent(args);
1920
1921


12
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1922
    return env->ThrowTypeError("setuid argument must be a number or a string");
1923
  }
1924
1925
2
  uid_t uid = uid_by_name(env->isolate(), args[0]);
1926
1927
2
  if (uid == uid_not_found) {
1928
1
    return env->ThrowError("setuid user id does not exist");
1929
  }
1930
1931
1
  if (setuid(uid)) {
1932
1
    return env->ThrowErrnoException(errno, "setuid");
1933
  }
1934
}
1935
1936
1937
3
static void SetEUid(const FunctionCallbackInfo<Value>& args) {
1938
3
  Environment* env = Environment::GetCurrent(args);
1939
1940


18
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1941
1
    return env->ThrowTypeError("seteuid argument must be a number or string");
1942
  }
1943
1944
2
  uid_t uid = uid_by_name(env->isolate(), args[0]);
1945
1946
2
  if (uid == uid_not_found) {
1947
1
    return env->ThrowError("seteuid user id does not exist");
1948
  }
1949
1950
1
  if (seteuid(uid)) {
1951
1
    return env->ThrowErrnoException(errno, "seteuid");
1952
  }
1953
}
1954
1955
1956
2
static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1957
2
  Environment* env = Environment::GetCurrent(args);
1958
1959
2
  int ngroups = getgroups(0, nullptr);
1960
1961
2
  if (ngroups == -1) {
1962
    return env->ThrowErrnoException(errno, "getgroups");
1963
  }
1964
1965
2
  gid_t* groups = new gid_t[ngroups];
1966
1967
2
  ngroups = getgroups(ngroups, groups);
1968
1969
2
  if (ngroups == -1) {
1970
    delete[] groups;
1971
    return env->ThrowErrnoException(errno, "getgroups");
1972
  }
1973
1974
2
  Local<Array> groups_list = Array::New(env->isolate(), ngroups);
1975
2
  bool seen_egid = false;
1976
2
  gid_t egid = getegid();
1977
1978
4
  for (int i = 0; i < ngroups; i++) {
1979
6
    groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
1980
2
    if (groups[i] == egid)
1981
2
      seen_egid = true;
1982
  }
1983
1984
2
  delete[] groups;
1985
1986
2
  if (seen_egid == false) {
1987
    groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
1988
  }
1989
1990
4
  args.GetReturnValue().Set(groups_list);
1991
}
1992
1993
1994
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1995
  Environment* env = Environment::GetCurrent(args);
1996
1997
  if (!args[0]->IsArray()) {
1998
    return env->ThrowTypeError("argument 1 must be an array");
1999
  }
2000
2001
  Local<Array> groups_list = args[0].As<Array>();
2002
  size_t size = groups_list->Length();
2003
  gid_t* groups = new gid_t[size];
2004
2005
  for (size_t i = 0; i < size; i++) {
2006
    gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
2007
2008
    if (gid == gid_not_found) {
2009
      delete[] groups;
2010
      return env->ThrowError("group name not found");
2011
    }
2012
2013
    groups[i] = gid;
2014
  }
2015
2016
  int rc = setgroups(size, groups);
2017
  delete[] groups;
2018
2019
  if (rc == -1) {
2020
    return env->ThrowErrnoException(errno, "setgroups");
2021
  }
2022
}
2023
2024
2025
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
2026
  Environment* env = Environment::GetCurrent(args);
2027
2028
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2029
    return env->ThrowTypeError("argument 1 must be a number or a string");
2030
  }
2031
2032
  if (!args[1]->IsUint32() && !args[1]->IsString()) {
2033
    return env->ThrowTypeError("argument 2 must be a number or a string");
2034
  }
2035
2036
  node::Utf8Value arg0(env->isolate(), args[0]);
2037
  gid_t extra_group;
2038
  bool must_free;
2039
  char* user;
2040
2041
  if (args[0]->IsUint32()) {
2042
    user = name_by_uid(args[0]->Uint32Value());
2043
    must_free = true;
2044
  } else {
2045
    user = *arg0;
2046
    must_free = false;
2047
  }
2048
2049
  if (user == nullptr) {
2050
    return env->ThrowError("initgroups user not found");
2051
  }
2052
2053
  extra_group = gid_by_name(env->isolate(), args[1]);
2054
2055
  if (extra_group == gid_not_found) {
2056
    if (must_free)
2057
      free(user);
2058
    return env->ThrowError("initgroups extra group not found");
2059
  }
2060
2061
  int rc = initgroups(user, extra_group);
2062
2063
  if (must_free) {
2064
    free(user);
2065
  }
2066
2067
  if (rc) {
2068
    return env->ThrowErrnoException(errno, "initgroups");
2069
  }
2070
}
2071
2072
#endif  // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
2073
2074
2075
3160
static void WaitForInspectorDisconnect(Environment* env) {
2076
#if HAVE_INSPECTOR
2077
3160
  if (env->inspector_agent()->IsConnected()) {
2078
    // Restore signal dispositions, the app is done and is no longer
2079
    // capable of handling signals.
2080
#if defined(__POSIX__) && !defined(NODE_SHARED_MODE)
2081
    struct sigaction act;
2082
8
    memset(&act, 0, sizeof(act));
2083
256
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
2084

248
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
2085
24
        continue;
2086
224
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
2087
224
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
2088
    }
2089
#endif
2090
8
    env->inspector_agent()->WaitForDisconnect();
2091
  }
2092
#endif
2093
3160
}
2094
2095
2096
216
static void Exit(const FunctionCallbackInfo<Value>& args) {
2097
216
  WaitForInspectorDisconnect(Environment::GetCurrent(args));
2098
432
  exit(args[0]->Int32Value());
2099
}
2100
2101
2102
3
static void Uptime(const FunctionCallbackInfo<Value>& args) {
2103
3
  Environment* env = Environment::GetCurrent(args);
2104
  double uptime;
2105
2106
3
  uv_update_time(env->event_loop());
2107
3
  uptime = uv_now(env->event_loop()) - prog_start_time;
2108
2109
9
  args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2110
3
}
2111
2112
2113
7
static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2114
7
  Environment* env = Environment::GetCurrent(args);
2115
2116
  size_t rss;
2117
7
  int err = uv_resident_set_memory(&rss);
2118
7
  if (err) {
2119
7
    return env->ThrowUVException(err, "uv_resident_set_memory");
2120
  }
2121
2122
7
  Isolate* isolate = env->isolate();
2123
  // V8 memory usage
2124
7
  HeapStatistics v8_heap_stats;
2125
7
  isolate->GetHeapStatistics(&v8_heap_stats);
2126
2127
  // Get the double array pointer from the Float64Array argument.
2128
14
  CHECK(args[0]->IsFloat64Array());
2129
14
  Local<Float64Array> array = args[0].As<Float64Array>();
2130
7
  CHECK_EQ(array->Length(), 4);
2131
7
  Local<ArrayBuffer> ab = array->Buffer();
2132
7
  double* fields = static_cast<double*>(ab->GetContents().Data());
2133
2134
7
  fields[0] = rss;
2135
7
  fields[1] = v8_heap_stats.total_heap_size();
2136
7
  fields[2] = v8_heap_stats.used_heap_size();
2137
14
  fields[3] = isolate->AdjustAmountOfExternalAllocatedMemory(0);
2138
}
2139
2140
2141
41
static void Kill(const FunctionCallbackInfo<Value>& args) {
2142
41
  Environment* env = Environment::GetCurrent(args);
2143
2144
41
  if (args.Length() != 2) {
2145
41
    return env->ThrowError("Bad argument.");
2146
  }
2147
2148
82
  int pid = args[0]->Int32Value();
2149
82
  int sig = args[1]->Int32Value();
2150
41
  int err = uv_kill(pid, sig);
2151
82
  args.GetReturnValue().Set(err);
2152
}
2153
2154
// used in Hrtime() below
2155
#define NANOS_PER_SEC 1000000000
2156
2157
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2158
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2159
// so this function instead fills in an Uint32Array with 3 entries,
2160
// to avoid any integer overflow possibility.
2161
// The first two entries contain the second part of the value
2162
// broken into the upper/lower 32 bits to be converted back in JS,
2163
// because there is no Uint64Array in JS.
2164
// The third entry contains the remaining nanosecond part of the value.
2165
243445
static void Hrtime(const FunctionCallbackInfo<Value>& args) {
2166
243445
  uint64_t t = uv_hrtime();
2167
2168
730335
  Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
2169
243445
  uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
2170
2171
243445
  fields[0] = (t / NANOS_PER_SEC) >> 32;
2172
243445
  fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
2173
243445
  fields[2] = t % NANOS_PER_SEC;
2174
243445
}
2175
2176
// Microseconds in a second, as a float, used in CPUUsage() below
2177
#define MICROS_PER_SEC 1e6
2178
2179
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
2180
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
2181
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
2182
// Returns those values as Float64 microseconds in the elements of the array
2183
// passed to the function.
2184
33
static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
2185
  uv_rusage_t rusage;
2186
2187
  // Call libuv to get the values we'll return.
2188
33
  int err = uv_getrusage(&rusage);
2189
33
  if (err) {
2190
    // On error, return the strerror version of the error code.
2191
    Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
2192
    args.GetReturnValue().Set(errmsg);
2193
33
    return;
2194
  }
2195
2196
  // Get the double array pointer from the Float64Array argument.
2197
66
  CHECK(args[0]->IsFloat64Array());
2198
66
  Local<Float64Array> array = args[0].As<Float64Array>();
2199
33
  CHECK_EQ(array->Length(), 2);
2200
33
  Local<ArrayBuffer> ab = array->Buffer();
2201
33
  double* fields = static_cast<double*>(ab->GetContents().Data());
2202
2203
  // Set the Float64Array elements to be user / system values in microseconds.
2204
33
  fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
2205
33
  fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
2206
}
2207
2208
110044
extern "C" void node_module_register(void* m) {
2209
110044
  struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2210
2211
110044
  if (mp->nm_flags & NM_F_BUILTIN) {
2212
106624
    mp->nm_link = modlist_builtin;
2213
106624
    modlist_builtin = mp;
2214
3420
  } else if (mp->nm_flags & NM_F_INTERNAL) {
2215
3332
    mp->nm_link = modlist_internal;
2216
3332
    modlist_internal = mp;
2217
88
  } else if (!node_is_initialized) {
2218
    // "Linked" modules are included as part of the node project.
2219
    // Like builtins they are registered *before* node::Init runs.
2220
    mp->nm_flags = NM_F_LINKED;
2221
    mp->nm_link = modlist_linked;
2222
    modlist_linked = mp;
2223
  } else {
2224
88
    modpending = mp;
2225
  }
2226
110044
}
2227
2228
88568
inline struct node_module* FindModule(struct node_module* list,
2229
                                      const char* name,
2230
                                      int flag) {
2231
  struct node_module* mp;
2232
2233
1569608
  for (mp = list; mp != nullptr; mp = mp->nm_link) {
2234
1563028
    if (strcmp(mp->nm_modname, name) == 0)
2235
81988
      break;
2236
  }
2237
2238

88568
  CHECK(mp == nullptr || (mp->nm_flags & flag) != 0);
2239
88568
  return mp;
2240
}
2241
2242
85281
node_module* get_builtin_module(const char* name) {
2243
85281
  return FindModule(modlist_builtin, name, NM_F_BUILTIN);
2244
}
2245
3287
node_module* get_internal_module(const char* name) {
2246
3287
  return FindModule(modlist_internal, name, NM_F_INTERNAL);
2247
}
2248
node_module* get_linked_module(const char* name) {
2249
  return FindModule(modlist_linked, name, NM_F_LINKED);
2250
}
2251
2252
186
struct DLib {
2253
  std::string filename_;
2254
  std::string errmsg_;
2255
  void* handle_;
2256
  int flags_;
2257
2258
#ifdef __POSIX__
2259
  static const int kDefaultFlags = RTLD_LAZY;
2260
2261
93
  bool Open() {
2262
93
    handle_ = dlopen(filename_.c_str(), flags_);
2263
93
    if (handle_ != nullptr)
2264
90
      return true;
2265
3
    errmsg_ = dlerror();
2266
3
    return false;
2267
  }
2268
2269
6
  void Close() {
2270
6
    if (handle_ != nullptr)
2271
3
      dlclose(handle_);
2272
6
  }
2273
#else  // !__POSIX__
2274
  static const int kDefaultFlags = 0;
2275
  uv_lib_t lib_;
2276
2277
  bool Open() {
2278
    int ret = uv_dlopen(filename_.c_str(), &lib_);
2279
    if (ret == 0) {
2280
      handle_ = static_cast<void*>(lib_.handle);
2281
      return true;
2282
    }
2283
    errmsg_ = uv_dlerror(&lib_);
2284
    uv_dlclose(&lib_);
2285
    return false;
2286
  }
2287
2288
  void Close() {
2289
    uv_dlclose(&lib_);
2290
  }
2291
#endif  // !__POSIX__
2292
};
2293
2294
// DLOpen is process.dlopen(module, filename, flags).
2295
// Used to load 'module.node' dynamically shared objects.
2296
//
2297
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2298
// when two contexts try to load the same shared object. Maybe have a shadow
2299
// cache that's a plain C list or hash table that's shared across contexts?
2300
93
static void DLOpen(const FunctionCallbackInfo<Value>& args) {
2301
93
  Environment* env = Environment::GetCurrent(args);
2302
2303
93
  CHECK_EQ(modpending, nullptr);
2304
2305
93
  if (args.Length() < 2) {
2306
    env->ThrowError("process.dlopen needs at least 2 arguments.");
2307
    return;
2308
  }
2309
2310
93
  int32_t flags = DLib::kDefaultFlags;
2311


189
  if (args.Length() > 2 && !args[2]->Int32Value(env->context()).To(&flags)) {
2312
    return env->ThrowTypeError("flag argument must be an integer.");
2313
  }
2314
2315
279
  Local<Object> module = args[0]->ToObject(env->isolate());  // Cast
2316
93
  node::Utf8Value filename(env->isolate(), args[1]);  // Cast
2317
180
  DLib dlib;
2318
93
  dlib.filename_ = *filename;
2319
93
  dlib.flags_ = flags;
2320
93
  bool is_opened = dlib.Open();
2321
2322
  // Objects containing v14 or later modules will have registered themselves
2323
  // on the pending list.  Activate all of them now.  At present, only one
2324
  // module per object is supported.
2325
93
  node_module* const mp = modpending;
2326
93
  modpending = nullptr;
2327
2328
93
  if (!is_opened) {
2329
3
    Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str());
2330
3
    dlib.Close();
2331
#ifdef _WIN32
2332
    // Windows needs to add the filename into the error message
2333
    errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
2334
#endif  // _WIN32
2335
3
    env->isolate()->ThrowException(Exception::Error(errmsg));
2336
3
    return;
2337
  }
2338
2339
90
  if (mp == nullptr) {
2340
2
    dlib.Close();
2341
2
    env->ThrowError("Module did not self-register.");
2342
2
    return;
2343
  }
2344
88
  if (mp->nm_version == -1) {
2345
44
    if (env->EmitNapiWarning()) {
2346
      ProcessEmitWarning(env, "N-API is an experimental feature and could "
2347
42
                         "change at any time.");
2348
    }
2349
44
  } else if (mp->nm_version != NODE_MODULE_VERSION) {
2350
    char errmsg[1024];
2351
    snprintf(errmsg,
2352
             sizeof(errmsg),
2353
             "The module '%s'"
2354
             "\nwas compiled against a different Node.js version using"
2355
             "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
2356
             "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
2357
             "re-installing\nthe module (for instance, using `npm rebuild` "
2358
             "or `npm install`).",
2359
1
             *filename, mp->nm_version, NODE_MODULE_VERSION);
2360
2361
    // NOTE: `mp` is allocated inside of the shared library's memory, calling
2362
    // `dlclose` will deallocate it
2363
1
    dlib.Close();
2364
1
    env->ThrowError(errmsg);
2365
1
    return;
2366
  }
2367
87
  if (mp->nm_flags & NM_F_BUILTIN) {
2368
    dlib.Close();
2369
    env->ThrowError("Built-in module self-registered.");
2370
    return;
2371
  }
2372
2373
87
  mp->nm_dso_handle = dlib.handle_;
2374
87
  mp->nm_link = modlist_addon;
2375
87
  modlist_addon = mp;
2376
2377
87
  Local<String> exports_string = env->exports_string();
2378
261
  Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
2379
2380
87
  if (mp->nm_context_register_func != nullptr) {
2381
92
    mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2382
41
  } else if (mp->nm_register_func != nullptr) {
2383
82
    mp->nm_register_func(exports, module, mp->nm_priv);
2384
  } else {
2385
    dlib.Close();
2386
    env->ThrowError("Module has no declared entry point.");
2387
    return;
2388
87
  }
2389
2390
  // Tell coverity that 'handle' should not be freed when we return.
2391
  // coverity[leaked_storage]
2392
}
2393
2394
2395
static void OnFatalError(const char* location, const char* message) {
2396
  if (location) {
2397
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2398
  } else {
2399
    PrintErrorString("FATAL ERROR: %s\n", message);
2400
  }
2401
  fflush(stderr);
2402
  ABORT();
2403
}
2404
2405
2406
NO_RETURN void FatalError(const char* location, const char* message) {
2407
  OnFatalError(location, message);
2408
  // to suppress compiler warning
2409
  ABORT();
2410
}
2411
2412
2413
1264
void FatalException(Isolate* isolate,
2414
                    Local<Value> error,
2415
                    Local<Message> message) {
2416
1264
  HandleScope scope(isolate);
2417
2418
1264
  Environment* env = Environment::GetCurrent(isolate);
2419
1264
  Local<Object> process_object = env->process_object();
2420
1264
  Local<String> fatal_exception_string = env->fatal_exception_string();
2421
  Local<Function> fatal_exception_function =
2422
2528
      process_object->Get(fatal_exception_string).As<Function>();
2423
2424
1264
  int exit_code = 0;
2425
1264
  if (!fatal_exception_function->IsFunction()) {
2426
    // failed before the process._fatalException function was added!
2427
    // this is probably pretty bad.  Nothing to do but report and exit.
2428
    ReportException(env, error, message);
2429
    exit_code = 6;
2430
  }
2431
2432
1264
  if (exit_code == 0) {
2433
1264
    TryCatch fatal_try_catch(isolate);
2434
2435
    // Do not call FatalException when _fatalException handler throws
2436
1264
    fatal_try_catch.SetVerbose(false);
2437
2438
    // this will return true if the JS layer handled it, false otherwise
2439
    Local<Value> caught =
2440
1264
        fatal_exception_function->Call(process_object, 1, &error);
2441
2442
1261
    if (fatal_try_catch.HasCaught()) {
2443
      // the fatal exception function threw, so we must exit
2444
2
      ReportException(env, fatal_try_catch);
2445
2
      exit_code = 7;
2446
    }
2447
2448

2520
    if (exit_code == 0 && false == caught->BooleanValue()) {
2449
117
      ReportException(env, error, message);
2450
117
      exit_code = 1;
2451
1261
    }
2452
  }
2453
2454
1261
  if (exit_code) {
2455
#if HAVE_INSPECTOR
2456
119
    env->inspector_agent()->FatalException(error, message);
2457
#endif
2458
119
    exit(exit_code);
2459
1142
  }
2460
1142
}
2461
2462
2463
2
void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2464
2
  HandleScope scope(isolate);
2465
2
  if (!try_catch.IsVerbose()) {
2466
2
    FatalException(isolate, try_catch.Exception(), try_catch.Message());
2467
1
  }
2468
1
}
2469
2470
2471
1262
static void OnMessage(Local<Message> message, Local<Value> error) {
2472
  // The current version of V8 sends messages for errors only
2473
  // (thus `error` is always set).
2474
1262
  FatalException(Isolate::GetCurrent(), error, message);
2475
1141
}
2476
2477
2478
void ClearFatalExceptionHandlers(Environment* env) {
2479
  Local<Object> process = env->process_object();
2480
  Local<Value> events =
2481
      process->Get(env->context(), env->events_string()).ToLocalChecked();
2482
2483
  if (events->IsObject()) {
2484
    events.As<Object>()->Set(
2485
        env->context(),
2486
        OneByteString(env->isolate(), "uncaughtException"),
2487
        Undefined(env->isolate())).FromJust();
2488
  }
2489
2490
  process->Set(
2491
      env->context(),
2492
      env->domain_string(),
2493
      Undefined(env->isolate())).FromJust();
2494
}
2495
2496
// Call process.emitWarning(str), fmt is a snprintf() format string
2497
46
void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
2498
  char warning[1024];
2499
  va_list ap;
2500
2501
46
  va_start(ap, fmt);
2502
46
  vsnprintf(warning, sizeof(warning), fmt, ap);
2503
46
  va_end(ap);
2504
2505
46
  HandleScope handle_scope(env->isolate());
2506
92
  Context::Scope context_scope(env->context());
2507
2508
46
  Local<Object> process = env->process_object();
2509
  MaybeLocal<Value> emit_warning = process->Get(env->context(),
2510
138
      FIXED_ONE_BYTE_STRING(env->isolate(), "emitWarning"));
2511
46
  Local<Value> arg = node::OneByteString(env->isolate(), warning);
2512
2513
  Local<Value> f;
2514
2515
46
  if (!emit_warning.ToLocal(&f)) return;
2516
46
  if (!f->IsFunction()) return;
2517
2518
  // MakeCallback() unneeded, because emitWarning is internal code, it calls
2519
  // process.emit('warning', ..), but does so on the nextTick.
2520
138
  f.As<v8::Function>()->Call(process, 1, &arg);
2521
}
2522
2523
293685
static bool PullFromCache(Environment* env,
2524
                          const FunctionCallbackInfo<Value>& args,
2525
                          Local<String> module,
2526
                          Local<Object> cache) {
2527
293685
  Local<Context> context = env->context();
2528
  Local<Value> exports_v;
2529
  Local<Object> exports;
2530


1762110
  if (cache->Get(context, module).ToLocal(&exports_v) &&
2531

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

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


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