GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/node.cc Lines: 1228 1538 79.8 %
Date: 2016-12-18 Branches: 565 947 59.7 %

Line Branch Exec Source
1
#include "node.h"
2
#include "node_buffer.h"
3
#include "node_constants.h"
4
#include "node_file.h"
5
#include "node_http_parser.h"
6
#include "node_javascript.h"
7
#include "node_version.h"
8
#include "node_internals.h"
9
#include "node_revert.h"
10
#include "node_debug_options.h"
11
12
#if defined HAVE_PERFCTR
13
#include "node_counters.h"
14
#endif
15
16
#if HAVE_OPENSSL
17
#include "node_crypto.h"
18
#endif
19
20
#if defined(NODE_HAVE_I18N_SUPPORT)
21
#include "node_i18n.h"
22
#endif
23
24
#if defined HAVE_DTRACE || defined HAVE_ETW
25
#include "node_dtrace.h"
26
#endif
27
28
#if defined HAVE_LTTNG
29
#include "node_lttng.h"
30
#endif
31
32
#include "ares.h"
33
#include "async-wrap.h"
34
#include "async-wrap-inl.h"
35
#include "env.h"
36
#include "env-inl.h"
37
#include "handle_wrap.h"
38
#include "req-wrap.h"
39
#include "req-wrap-inl.h"
40
#include "string_bytes.h"
41
#include "util.h"
42
#include "uv.h"
43
#if NODE_USE_V8_PLATFORM
44
#include "libplatform/libplatform.h"
45
#endif  // NODE_USE_V8_PLATFORM
46
#include "v8-debug.h"
47
#include "v8-profiler.h"
48
#include "zlib.h"
49
50
#ifdef NODE_ENABLE_VTUNE_PROFILING
51
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
52
#endif
53
54
#include <errno.h>
55
#include <limits.h>  // PATH_MAX
56
#include <locale.h>
57
#include <signal.h>
58
#include <stdio.h>
59
#include <stdlib.h>
60
#include <string.h>
61
#include <sys/types.h>
62
63
#include <string>
64
#include <vector>
65
66
#if defined(NODE_HAVE_I18N_SUPPORT)
67
#include <unicode/uvernum.h>
68
#endif
69
70
#if defined(LEAK_SANITIZER)
71
#include <sanitizer/lsan_interface.h>
72
#endif
73
74
#if defined(_MSC_VER)
75
#include <direct.h>
76
#include <io.h>
77
#define getpid GetCurrentProcessId
78
#define umask _umask
79
typedef int mode_t;
80
#else
81
#include <pthread.h>
82
#include <sys/resource.h>  // getrlimit, setrlimit
83
#include <unistd.h>  // setuid, getuid
84
#endif
85
86
#if defined(__POSIX__) && !defined(__ANDROID__)
87
#include <pwd.h>  // getpwnam()
88
#include <grp.h>  // getgrnam()
89
#endif
90
91
#ifdef __APPLE__
92
#include <crt_externs.h>
93
#define environ (*_NSGetEnviron())
94
#elif !defined(_MSC_VER)
95
extern char **environ;
96
#endif
97
98
namespace node {
99
100
using v8::Array;
101
using v8::ArrayBuffer;
102
using v8::Boolean;
103
using v8::Context;
104
using v8::EscapableHandleScope;
105
using v8::Exception;
106
using v8::Float64Array;
107
using v8::Function;
108
using v8::FunctionCallbackInfo;
109
using v8::HandleScope;
110
using v8::HeapStatistics;
111
using v8::Integer;
112
using v8::Isolate;
113
using v8::Local;
114
using v8::Locker;
115
using v8::MaybeLocal;
116
using v8::Message;
117
using v8::Name;
118
using v8::NamedPropertyHandlerConfiguration;
119
using v8::Null;
120
using v8::Number;
121
using v8::Object;
122
using v8::ObjectTemplate;
123
using v8::Promise;
124
using v8::PromiseRejectMessage;
125
using v8::PropertyCallbackInfo;
126
using v8::ScriptOrigin;
127
using v8::SealHandleScope;
128
using v8::String;
129
using v8::TryCatch;
130
using v8::Uint32Array;
131
using v8::V8;
132
using v8::Value;
133
134
static bool print_eval = false;
135
static bool force_repl = false;
136
static bool syntax_check_only = false;
137
static bool trace_deprecation = false;
138
static bool throw_deprecation = false;
139
static bool trace_sync_io = false;
140
static bool track_heap_objects = false;
141
static const char* eval_string = nullptr;
142
static unsigned int preload_module_count = 0;
143
static const char** preload_modules = nullptr;
144
static const int v8_default_thread_pool_size = 4;
145
static int v8_thread_pool_size = v8_default_thread_pool_size;
146
static bool prof_process = false;
147
static bool v8_is_profiling = false;
148
static bool node_is_initialized = false;
149
static node_module* modpending;
150
static node_module* modlist_builtin;
151
static node_module* modlist_linked;
152
static node_module* modlist_addon;
153
154
#if defined(NODE_HAVE_I18N_SUPPORT)
155
// Path to ICU data (for i18n / Intl)
156
static const char* icu_data_dir = nullptr;
157
#endif
158
159
// used by C++ modules as well
160
bool no_deprecation = false;
161
162
#if HAVE_OPENSSL
163
# if NODE_FIPS_MODE
164
// used by crypto module
165
bool enable_fips_crypto = false;
166
bool force_fips_crypto = false;
167
# endif  // NODE_FIPS_MODE
168
const char* openssl_config = nullptr;
169
#endif  // HAVE_OPENSSL
170
171
// true if process warnings should be suppressed
172
bool no_process_warnings = false;
173
bool trace_warnings = false;
174
175
// Set in node.cc by ParseArgs when --preserve-symlinks is used.
176
// Used in node_config.cc to set a constant on process.binding('config')
177
// that is used by lib/module.js
178
bool config_preserve_symlinks = false;
179
180
bool v8_initialized = false;
181
182
// process-relative uptime base, initialized at start-up
183
static double prog_start_time;
184
static bool debugger_running;
185
static uv_async_t dispatch_debug_messages_async;
186
187
1734
static Mutex node_isolate_mutex;
188
static v8::Isolate* node_isolate;
189
190
1734
static node::DebugOptions debug_options;
191
192
static struct {
193
#if NODE_USE_V8_PLATFORM
194
  void Initialize(int thread_pool_size) {
195
1721
    platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
196
1721
    V8::InitializePlatform(platform_);
197
  }
198
199
  void PumpMessageLoop(Isolate* isolate) {
200
24353
    v8::platform::PumpMessageLoop(platform_, isolate);
201
  }
202
203
  void Dispose() {
204
1520
    delete platform_;
205
1520
    platform_ = nullptr;
206
  }
207
208
#if HAVE_INSPECTOR
209
  bool StartInspector(Environment *env, const char* script_path,
210
                      const node::DebugOptions& options) {
211
14
    return env->inspector_agent()->Start(platform_, script_path, options);
212
  }
213
#endif  // HAVE_INSPECTOR
214
215
  v8::Platform* platform_;
216
#else  // !NODE_USE_V8_PLATFORM
217
  void Initialize(int thread_pool_size) {}
218
  void PumpMessageLoop(Isolate* isolate) {}
219
  void Dispose() {}
220
  bool StartInspector(Environment *env, const char* script_path,
221
                      int port, bool wait) {
222
    env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
223
    return false;  // make compiler happy
224
  }
225
#endif  // !NODE_USE_V8_PLATFORM
226
} v8_platform;
227
228
#ifdef __POSIX__
229
static uv_sem_t debug_semaphore;
230
static const unsigned kMaxSignal = 32;
231
#endif
232
233
76
static void PrintErrorString(const char* format, ...) {
234
  va_list ap;
235
76
  va_start(ap, format);
236
#ifdef _WIN32
237
  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
238
239
  // Check if stderr is something other than a tty/console
240
  if (stderr_handle == INVALID_HANDLE_VALUE ||
241
      stderr_handle == nullptr ||
242
      uv_guess_handle(_fileno(stderr)) != UV_TTY) {
243
    vfprintf(stderr, format, ap);
244
    va_end(ap);
245
    return;
246
  }
247
248
  // Fill in any placeholders
249
  int n = _vscprintf(format, ap);
250
  std::vector<char> out(n + 1);
251
  vsprintf(out.data(), format, ap);
252
253
  // Get required wide buffer size
254
  n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
255
256
  std::vector<wchar_t> wbuf(n);
257
  MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
258
259
  // Don't include the null character in the output
260
  CHECK_GT(n, 0);
261
  WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
262
#else
263
152
  vfprintf(stderr, format, ap);
264
#endif
265
76
  va_end(ap);
266
76
}
267
268
269
3117
static void CheckImmediate(uv_check_t* handle) {
270
3117
  Environment* env = Environment::from_immediate_check_handle(handle);
271
6218
  HandleScope scope(env->isolate());
272
9335
  Context::Scope context_scope(env->context());
273
6234
  MakeCallback(env, env->process_object(), env->immediate_callback_string());
274
3101
}
275
276
277
2051
static void IdleImmediateDummy(uv_idle_t* handle) {
278
  // Do nothing. Only for maintaining event loop.
279
  // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
280
2051
}
281
282
283
static inline const char *errno_string(int errorno) {
284
#define ERRNO_CASE(e)  case e: return #e;
285
1
  switch (errorno) {
286
#ifdef EACCES
287
  ERRNO_CASE(EACCES);
288
#endif
289
290
#ifdef EADDRINUSE
291
  ERRNO_CASE(EADDRINUSE);
292
#endif
293
294
#ifdef EADDRNOTAVAIL
295
  ERRNO_CASE(EADDRNOTAVAIL);
296
#endif
297
298
#ifdef EAFNOSUPPORT
299
  ERRNO_CASE(EAFNOSUPPORT);
300
#endif
301
302
#ifdef EAGAIN
303
  ERRNO_CASE(EAGAIN);
304
#endif
305
306
#ifdef EWOULDBLOCK
307
# if EAGAIN != EWOULDBLOCK
308
  ERRNO_CASE(EWOULDBLOCK);
309
# endif
310
#endif
311
312
#ifdef EALREADY
313
  ERRNO_CASE(EALREADY);
314
#endif
315
316
#ifdef EBADF
317
  ERRNO_CASE(EBADF);
318
#endif
319
320
#ifdef EBADMSG
321
  ERRNO_CASE(EBADMSG);
322
#endif
323
324
#ifdef EBUSY
325
  ERRNO_CASE(EBUSY);
326
#endif
327
328
#ifdef ECANCELED
329
  ERRNO_CASE(ECANCELED);
330
#endif
331
332
#ifdef ECHILD
333
  ERRNO_CASE(ECHILD);
334
#endif
335
336
#ifdef ECONNABORTED
337
  ERRNO_CASE(ECONNABORTED);
338
#endif
339
340
#ifdef ECONNREFUSED
341
  ERRNO_CASE(ECONNREFUSED);
342
#endif
343
344
#ifdef ECONNRESET
345
  ERRNO_CASE(ECONNRESET);
346
#endif
347
348
#ifdef EDEADLK
349
  ERRNO_CASE(EDEADLK);
350
#endif
351
352
#ifdef EDESTADDRREQ
353
  ERRNO_CASE(EDESTADDRREQ);
354
#endif
355
356
#ifdef EDOM
357
  ERRNO_CASE(EDOM);
358
#endif
359
360
#ifdef EDQUOT
361
  ERRNO_CASE(EDQUOT);
362
#endif
363
364
#ifdef EEXIST
365
  ERRNO_CASE(EEXIST);
366
#endif
367
368
#ifdef EFAULT
369
  ERRNO_CASE(EFAULT);
370
#endif
371
372
#ifdef EFBIG
373
  ERRNO_CASE(EFBIG);
374
#endif
375
376
#ifdef EHOSTUNREACH
377
  ERRNO_CASE(EHOSTUNREACH);
378
#endif
379
380
#ifdef EIDRM
381
  ERRNO_CASE(EIDRM);
382
#endif
383
384
#ifdef EILSEQ
385
  ERRNO_CASE(EILSEQ);
386
#endif
387
388
#ifdef EINPROGRESS
389
  ERRNO_CASE(EINPROGRESS);
390
#endif
391
392
#ifdef EINTR
393
  ERRNO_CASE(EINTR);
394
#endif
395
396
#ifdef EINVAL
397
  ERRNO_CASE(EINVAL);
398
#endif
399
400
#ifdef EIO
401
  ERRNO_CASE(EIO);
402
#endif
403
404
#ifdef EISCONN
405
  ERRNO_CASE(EISCONN);
406
#endif
407
408
#ifdef EISDIR
409
  ERRNO_CASE(EISDIR);
410
#endif
411
412
#ifdef ELOOP
413
  ERRNO_CASE(ELOOP);
414
#endif
415
416
#ifdef EMFILE
417
  ERRNO_CASE(EMFILE);
418
#endif
419
420
#ifdef EMLINK
421
  ERRNO_CASE(EMLINK);
422
#endif
423
424
#ifdef EMSGSIZE
425
  ERRNO_CASE(EMSGSIZE);
426
#endif
427
428
#ifdef EMULTIHOP
429
  ERRNO_CASE(EMULTIHOP);
430
#endif
431
432
#ifdef ENAMETOOLONG
433
  ERRNO_CASE(ENAMETOOLONG);
434
#endif
435
436
#ifdef ENETDOWN
437
  ERRNO_CASE(ENETDOWN);
438
#endif
439
440
#ifdef ENETRESET
441
  ERRNO_CASE(ENETRESET);
442
#endif
443
444
#ifdef ENETUNREACH
445
  ERRNO_CASE(ENETUNREACH);
446
#endif
447
448
#ifdef ENFILE
449
  ERRNO_CASE(ENFILE);
450
#endif
451
452
#ifdef ENOBUFS
453
  ERRNO_CASE(ENOBUFS);
454
#endif
455
456
#ifdef ENODATA
457
  ERRNO_CASE(ENODATA);
458
#endif
459
460
#ifdef ENODEV
461
  ERRNO_CASE(ENODEV);
462
#endif
463
464
#ifdef ENOENT
465
  ERRNO_CASE(ENOENT);
466
#endif
467
468
#ifdef ENOEXEC
469
  ERRNO_CASE(ENOEXEC);
470
#endif
471
472
#ifdef ENOLINK
473
  ERRNO_CASE(ENOLINK);
474
#endif
475
476
#ifdef ENOLCK
477
# if ENOLINK != ENOLCK
478
  ERRNO_CASE(ENOLCK);
479
# endif
480
#endif
481
482
#ifdef ENOMEM
483
  ERRNO_CASE(ENOMEM);
484
#endif
485
486
#ifdef ENOMSG
487
  ERRNO_CASE(ENOMSG);
488
#endif
489
490
#ifdef ENOPROTOOPT
491
  ERRNO_CASE(ENOPROTOOPT);
492
#endif
493
494
#ifdef ENOSPC
495
  ERRNO_CASE(ENOSPC);
496
#endif
497
498
#ifdef ENOSR
499
  ERRNO_CASE(ENOSR);
500
#endif
501
502
#ifdef ENOSTR
503
  ERRNO_CASE(ENOSTR);
504
#endif
505
506
#ifdef ENOSYS
507
  ERRNO_CASE(ENOSYS);
508
#endif
509
510
#ifdef ENOTCONN
511
  ERRNO_CASE(ENOTCONN);
512
#endif
513
514
#ifdef ENOTDIR
515
  ERRNO_CASE(ENOTDIR);
516
#endif
517
518
#ifdef ENOTEMPTY
519
# if ENOTEMPTY != EEXIST
520
  ERRNO_CASE(ENOTEMPTY);
521
# endif
522
#endif
523
524
#ifdef ENOTSOCK
525
  ERRNO_CASE(ENOTSOCK);
526
#endif
527
528
#ifdef ENOTSUP
529
  ERRNO_CASE(ENOTSUP);
530
#else
531
# ifdef EOPNOTSUPP
532
  ERRNO_CASE(EOPNOTSUPP);
533
# endif
534
#endif
535
536
#ifdef ENOTTY
537
  ERRNO_CASE(ENOTTY);
538
#endif
539
540
#ifdef ENXIO
541
  ERRNO_CASE(ENXIO);
542
#endif
543
544
545
#ifdef EOVERFLOW
546
  ERRNO_CASE(EOVERFLOW);
547
#endif
548
549
#ifdef EPERM
550
  ERRNO_CASE(EPERM);
551
#endif
552
553
#ifdef EPIPE
554
  ERRNO_CASE(EPIPE);
555
#endif
556
557
#ifdef EPROTO
558
  ERRNO_CASE(EPROTO);
559
#endif
560
561
#ifdef EPROTONOSUPPORT
562
  ERRNO_CASE(EPROTONOSUPPORT);
563
#endif
564
565
#ifdef EPROTOTYPE
566
  ERRNO_CASE(EPROTOTYPE);
567
#endif
568
569
#ifdef ERANGE
570
  ERRNO_CASE(ERANGE);
571
#endif
572
573
#ifdef EROFS
574
  ERRNO_CASE(EROFS);
575
#endif
576
577
#ifdef ESPIPE
578
  ERRNO_CASE(ESPIPE);
579
#endif
580
581
#ifdef ESRCH
582
  ERRNO_CASE(ESRCH);
583
#endif
584
585
#ifdef ESTALE
586
  ERRNO_CASE(ESTALE);
587
#endif
588
589
#ifdef ETIME
590
  ERRNO_CASE(ETIME);
591
#endif
592
593
#ifdef ETIMEDOUT
594
  ERRNO_CASE(ETIMEDOUT);
595
#endif
596
597
#ifdef ETXTBSY
598
  ERRNO_CASE(ETXTBSY);
599
#endif
600
601
#ifdef EXDEV
602
  ERRNO_CASE(EXDEV);
603
#endif
604
605
  default: return "";
606
  }
607
}
608
609
680
const char *signo_string(int signo) {
610
#define SIGNO_CASE(e)  case e: return #e;
611
680
  switch (signo) {
612
#ifdef SIGHUP
613
  SIGNO_CASE(SIGHUP);
614
#endif
615
616
#ifdef SIGINT
617
  SIGNO_CASE(SIGINT);
618
#endif
619
620
#ifdef SIGQUIT
621
  SIGNO_CASE(SIGQUIT);
622
#endif
623
624
#ifdef SIGILL
625
  SIGNO_CASE(SIGILL);
626
#endif
627
628
#ifdef SIGTRAP
629
  SIGNO_CASE(SIGTRAP);
630
#endif
631
632
#ifdef SIGABRT
633
  SIGNO_CASE(SIGABRT);
634
#endif
635
636
#ifdef SIGIOT
637
# if SIGABRT != SIGIOT
638
  SIGNO_CASE(SIGIOT);
639
# endif
640
#endif
641
642
#ifdef SIGBUS
643
  SIGNO_CASE(SIGBUS);
644
#endif
645
646
#ifdef SIGFPE
647
  SIGNO_CASE(SIGFPE);
648
#endif
649
650
#ifdef SIGKILL
651
  SIGNO_CASE(SIGKILL);
652
#endif
653
654
#ifdef SIGUSR1
655
  SIGNO_CASE(SIGUSR1);
656
#endif
657
658
#ifdef SIGSEGV
659
  SIGNO_CASE(SIGSEGV);
660
#endif
661
662
#ifdef SIGUSR2
663
  SIGNO_CASE(SIGUSR2);
664
#endif
665
666
#ifdef SIGPIPE
667
  SIGNO_CASE(SIGPIPE);
668
#endif
669
670
#ifdef SIGALRM
671
  SIGNO_CASE(SIGALRM);
672
#endif
673
674
  SIGNO_CASE(SIGTERM);
675
676
#ifdef SIGCHLD
677
  SIGNO_CASE(SIGCHLD);
678
#endif
679
680
#ifdef SIGSTKFLT
681
  SIGNO_CASE(SIGSTKFLT);
682
#endif
683
684
685
#ifdef SIGCONT
686
  SIGNO_CASE(SIGCONT);
687
#endif
688
689
#ifdef SIGSTOP
690
  SIGNO_CASE(SIGSTOP);
691
#endif
692
693
#ifdef SIGTSTP
694
  SIGNO_CASE(SIGTSTP);
695
#endif
696
697
#ifdef SIGBREAK
698
  SIGNO_CASE(SIGBREAK);
699
#endif
700
701
#ifdef SIGTTIN
702
  SIGNO_CASE(SIGTTIN);
703
#endif
704
705
#ifdef SIGTTOU
706
  SIGNO_CASE(SIGTTOU);
707
#endif
708
709
#ifdef SIGURG
710
  SIGNO_CASE(SIGURG);
711
#endif
712
713
#ifdef SIGXCPU
714
  SIGNO_CASE(SIGXCPU);
715
#endif
716
717
#ifdef SIGXFSZ
718
  SIGNO_CASE(SIGXFSZ);
719
#endif
720
721
#ifdef SIGVTALRM
722
  SIGNO_CASE(SIGVTALRM);
723
#endif
724
725
#ifdef SIGPROF
726
  SIGNO_CASE(SIGPROF);
727
#endif
728
729
#ifdef SIGWINCH
730
  SIGNO_CASE(SIGWINCH);
731
#endif
732
733
#ifdef SIGIO
734
  SIGNO_CASE(SIGIO);
735
#endif
736
737
#ifdef SIGPOLL
738
# if SIGPOLL != SIGIO
739
  SIGNO_CASE(SIGPOLL);
740
# endif
741
#endif
742
743
#ifdef SIGLOST
744
# if SIGLOST != SIGABRT
745
  SIGNO_CASE(SIGLOST);
746
# endif
747
#endif
748
749
#ifdef SIGPWR
750
# if SIGPWR != SIGLOST
751
  SIGNO_CASE(SIGPWR);
752
# endif
753
#endif
754
755
#ifdef SIGINFO
756
# if !defined(SIGPWR) || SIGINFO != SIGPWR
757
  SIGNO_CASE(SIGINFO);
758
# endif
759
#endif
760
761
#ifdef SIGSYS
762
  SIGNO_CASE(SIGSYS);
763
#endif
764
765
  default: return "";
766
  }
767
}
768
769
770
1
Local<Value> ErrnoException(Isolate* isolate,
771
                            int errorno,
772
                            const char *syscall,
773
                            const char *msg,
774
                            const char *path) {
775
1
  Environment* env = Environment::GetCurrent(isolate);
776
777
1
  Local<Value> e;
778
1
  Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
779

1
  if (msg == nullptr || msg[0] == '\0') {
780
1
    msg = strerror(errorno);
781
  }
782
1
  Local<String> message = OneByteString(env->isolate(), msg);
783
784
  Local<String> cons =
785
1
      String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
786
1
  cons = String::Concat(cons, message);
787
788
1
  Local<String> path_string;
789
1
  if (path != nullptr) {
790
    // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
791
    path_string = String::NewFromUtf8(env->isolate(), path);
792
  }
793
794
1
  if (path_string.IsEmpty() == false) {
795
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
796
    cons = String::Concat(cons, path_string);
797
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
798
  }
799
1
  e = Exception::Error(cons);
800
801
1
  Local<Object> obj = e->ToObject(env->isolate());
802
4
  obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
803
3
  obj->Set(env->code_string(), estring);
804
805
1
  if (path_string.IsEmpty() == false) {
806
    obj->Set(env->path_string(), path_string);
807
  }
808
809
1
  if (syscall != nullptr) {
810
4
    obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
811
  }
812
813
1
  return e;
814
}
815
816
817
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
818
#ifdef _WIN32
819
  if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
820
    return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
821
                          String::NewFromUtf8(isolate, path + 8));
822
  } else if (strncmp(path, "\\\\?\\", 4) == 0) {
823
    return String::NewFromUtf8(isolate, path + 4);
824
  }
825
#endif
826
827
2465
  return String::NewFromUtf8(isolate, path);
828
}
829
830
831
Local<Value> UVException(Isolate* isolate,
832
                         int errorno,
833
                         const char* syscall,
834
                         const char* msg,
835
                         const char* path) {
836
  return UVException(isolate, errorno, syscall, msg, path, nullptr);
837
}
838
839
840
2475
Local<Value> UVException(Isolate* isolate,
841
                         int errorno,
842
                         const char* syscall,
843
                         const char* msg,
844
                         const char* path,
845
                         const char* dest) {
846
2475
  Environment* env = Environment::GetCurrent(isolate);
847
848

2475
  if (!msg || !msg[0])
849
2475
    msg = uv_strerror(errorno);
850
851
2475
  Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
852
2475
  Local<String> js_syscall = OneByteString(isolate, syscall);
853
2475
  Local<String> js_path;
854
2475
  Local<String> js_dest;
855
856
2475
  Local<String> js_msg = js_code;
857
2475
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
858
2475
  js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
859
2475
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
860
2475
  js_msg = String::Concat(js_msg, js_syscall);
861
862
2475
  if (path != nullptr) {
863
2455
    js_path = StringFromPath(isolate, path);
864
865
2455
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
866
2455
    js_msg = String::Concat(js_msg, js_path);
867
2455
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
868
  }
869
870
2475
  if (dest != nullptr) {
871
10
    js_dest = StringFromPath(isolate, dest);
872
873
10
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
874
10
    js_msg = String::Concat(js_msg, js_dest);
875
10
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
876
  }
877
878
4950
  Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
879
880
  // TODO(piscisaureus) errno should probably go; the user has no way of
881
  // knowing which uv errno value maps to which error.
882
9900
  e->Set(env->errno_string(), Integer::New(isolate, errorno));
883
7425
  e->Set(env->code_string(), js_code);
884
7425
  e->Set(env->syscall_string(), js_syscall);
885
2475
  if (!js_path.IsEmpty())
886
7365
    e->Set(env->path_string(), js_path);
887
2475
  if (!js_dest.IsEmpty())
888
30
    e->Set(env->dest_string(), js_dest);
889
890
2475
  return e;
891
}
892
893
894
// Look up environment variable unless running as setuid root.
895
5186
inline const char* secure_getenv(const char* key) {
896
#ifndef _WIN32
897

5186
  if (getuid() != geteuid() || getgid() != getegid())
898
    return nullptr;
899
#endif
900
5186
  return getenv(key);
901
}
902
903
904
#ifdef _WIN32
905
// Does about the same as strerror(),
906
// but supports all windows error messages
907
static const char *winapi_strerror(const int errorno, bool* must_free) {
908
  char *errmsg = nullptr;
909
910
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
911
      FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
912
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
913
914
  if (errmsg) {
915
    *must_free = true;
916
917
    // Remove trailing newlines
918
    for (int i = strlen(errmsg) - 1;
919
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
920
      errmsg[i] = '\0';
921
    }
922
923
    return errmsg;
924
  } else {
925
    // FormatMessage failed
926
    *must_free = false;
927
    return "Unknown error";
928
  }
929
}
930
931
932
Local<Value> WinapiErrnoException(Isolate* isolate,
933
                                  int errorno,
934
                                  const char* syscall,
935
                                  const char* msg,
936
                                  const char* path) {
937
  Environment* env = Environment::GetCurrent(isolate);
938
  Local<Value> e;
939
  bool must_free = false;
940
  if (!msg || !msg[0]) {
941
    msg = winapi_strerror(errorno, &must_free);
942
  }
943
  Local<String> message = OneByteString(env->isolate(), msg);
944
945
  if (path) {
946
    Local<String> cons1 =
947
        String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
948
    Local<String> cons2 =
949
        String::Concat(cons1, String::NewFromUtf8(isolate, path));
950
    Local<String> cons3 =
951
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
952
    e = Exception::Error(cons3);
953
  } else {
954
    e = Exception::Error(message);
955
  }
956
957
  Local<Object> obj = e->ToObject(env->isolate());
958
  obj->Set(env->errno_string(), Integer::New(isolate, errorno));
959
960
  if (path != nullptr) {
961
    obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
962
  }
963
964
  if (syscall != nullptr) {
965
    obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
966
  }
967
968
  if (must_free)
969
    LocalFree((HLOCAL)msg);
970
971
  return e;
972
}
973
#endif
974
975
976
13752
void* ArrayBufferAllocator::Allocate(size_t size) {
977

13752
  if (zero_fill_field_ || zero_fill_all_buffers)
978
5486
    return node::UncheckedCalloc(size);
979
  else
980
8266
    return node::UncheckedMalloc(size);
981
}
982
983
28
static bool DomainHasErrorHandler(const Environment* env,
984
                                  const Local<Object>& domain) {
985
56
  HandleScope scope(env->isolate());
986
987
84
  Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
988
28
  if (!domain_event_listeners_v->IsObject())
989
    return false;
990
991
  Local<Object> domain_event_listeners_o =
992
28
      domain_event_listeners_v.As<Object>();
993
994
  Local<Value> domain_error_listeners_v =
995
56
      domain_event_listeners_o->Get(env->error_string());
996
997

57
  if (domain_error_listeners_v->IsFunction() ||
998
1
      (domain_error_listeners_v->IsArray() &&
999
      domain_error_listeners_v.As<Array>()->Length() > 0))
1000
    return true;
1001
1002
1
  return false;
1003
}
1004
1005
27
static bool DomainsStackHasErrorHandler(const Environment* env) {
1006
54
  HandleScope scope(env->isolate());
1007
1008
27
  if (!env->using_domains())
1009
    return false;
1010
1011
54
  Local<Array> domains_stack_array = env->domains_stack_array().As<Array>();
1012
27
  if (domains_stack_array->Length() == 0)
1013
    return false;
1014
1015
27
  uint32_t domains_stack_length = domains_stack_array->Length();
1016
28
  for (uint32_t i = domains_stack_length; i > 0; --i) {
1017
28
    Local<Value> domain_v = domains_stack_array->Get(i - 1);
1018
28
    if (!domain_v->IsObject())
1019
27
      return false;
1020
1021
28
    Local<Object> domain = domain_v.As<Object>();
1022
28
    if (DomainHasErrorHandler(env, domain))
1023
      return true;
1024
  }
1025
1026
  return false;
1027
}
1028
1029
1030
27
static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
1031
54
  HandleScope scope(isolate);
1032
1033
27
  Environment* env = Environment::GetCurrent(isolate);
1034
27
  Local<Object> process_object = env->process_object();
1035
  Local<String> emitting_top_level_domain_error_key =
1036
27
    env->emitting_top_level_domain_error_string();
1037
  bool isEmittingTopLevelDomainError =
1038
54
      process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
1039
1040

54
  return isEmittingTopLevelDomainError || !DomainsStackHasErrorHandler(env);
1041
}
1042
1043
1044
128
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
1045
128
  Environment* env = Environment::GetCurrent(args);
1046
1047
128
  if (env->using_domains())
1048
    return;
1049
128
  env->set_using_domains(true);
1050
1051
256
  HandleScope scope(env->isolate());
1052
128
  Local<Object> process_object = env->process_object();
1053
1054
128
  Local<String> tick_callback_function_key = env->tick_domain_cb_string();
1055
  Local<Function> tick_callback_function =
1056
256
      process_object->Get(tick_callback_function_key).As<Function>();
1057
1058
128
  if (!tick_callback_function->IsFunction()) {
1059
    fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
1060
    ABORT();
1061
  }
1062
1063
384
  process_object->Set(env->tick_callback_string(), tick_callback_function);
1064
128
  env->set_tick_callback_function(tick_callback_function);
1065
1066
128
  CHECK(args[0]->IsArray());
1067
256
  env->set_domain_array(args[0].As<Array>());
1068
1069
128
  CHECK(args[1]->IsArray());
1070
256
  env->set_domains_stack_array(args[1].As<Array>());
1071
1072
  // Do a little housekeeping.
1073
384
  env->process_object()->Delete(
1074
      env->context(),
1075
896
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
1076
1077
256
  uint32_t* const fields = env->domain_flag()->fields();
1078
128
  uint32_t const fields_count = env->domain_flag()->fields_count();
1079
1080
  Local<ArrayBuffer> array_buffer =
1081
128
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1082
1083
384
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1084
}
1085
1086
36228
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
1087
36228
  args.GetIsolate()->RunMicrotasks();
1088
36228
}
1089
1090
1091
1727
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
1092
1727
  Environment* env = Environment::GetCurrent(args);
1093
1094
1727
  CHECK(args[0]->IsFunction());
1095
1096
3454
  env->set_push_values_to_array_function(args[0].As<Function>());
1097
5181
  env->process_object()->Delete(
1098
      env->context(),
1099
10362
      FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
1100
1727
}
1101
1102
1103
1727
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
1104
1727
  Environment* env = Environment::GetCurrent(args);
1105
1106
1727
  CHECK(args[0]->IsFunction());
1107
1727
  CHECK(args[1]->IsObject());
1108
1109
3454
  env->set_tick_callback_function(args[0].As<Function>());
1110
1111
3454
  env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
1112
1113
  // Do a little housekeeping.
1114
5181
  env->process_object()->Delete(
1115
      env->context(),
1116
12089
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust();
1117
1118
  // Values use to cross communicate with processNextTick.
1119
3454
  uint32_t* const fields = env->tick_info()->fields();
1120
1727
  uint32_t const fields_count = env->tick_info()->fields_count();
1121
1122
  Local<ArrayBuffer> array_buffer =
1123
1727
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1124
1125
5181
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1126
1727
}
1127
1128
64
void PromiseRejectCallback(PromiseRejectMessage message) {
1129
64
  Local<Promise> promise = message.GetPromise();
1130
64
  Isolate* isolate = promise->GetIsolate();
1131
64
  Local<Value> value = message.GetValue();
1132
64
  Local<Integer> event = Integer::New(isolate, message.GetEvent());
1133
1134
64
  Environment* env = Environment::GetCurrent(isolate);
1135
64
  Local<Function> callback = env->promise_reject_function();
1136
1137
64
  if (value.IsEmpty())
1138
50
    value = Undefined(isolate);
1139
1140
192
  Local<Value> args[] = { event, promise, value };
1141
64
  Local<Object> process = env->process_object();
1142
1143
128
  callback->Call(process, arraysize(args), args);
1144
64
}
1145
1146
1727
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
1147
1727
  Environment* env = Environment::GetCurrent(args);
1148
1727
  Isolate* isolate = env->isolate();
1149
1150
1727
  CHECK(args[0]->IsFunction());
1151
1152
1727
  isolate->SetPromiseRejectCallback(PromiseRejectCallback);
1153
3454
  env->set_promise_reject_function(args[0].As<Function>());
1154
1155
5181
  env->process_object()->Delete(
1156
      env->context(),
1157
12089
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupPromises")).FromJust();
1158
1727
}
1159
1160
1161
6217
Local<Value> MakeCallback(Environment* env,
1162
                          Local<Value> recv,
1163
                          const Local<Function> callback,
1164
                          int argc,
1165
                          Local<Value> argv[]) {
1166
  // If you hit this assertion, you forgot to enter the v8::Context first.
1167
18651
  CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1168
1169
6217
  Local<Function> pre_fn = env->async_hooks_pre_function();
1170
6217
  Local<Function> post_fn = env->async_hooks_post_function();
1171
12434
  Local<Object> object, domain;
1172
6217
  bool ran_init_callback = false;
1173
6217
  bool has_domain = false;
1174
1175
12416
  Environment::AsyncCallbackScope callback_scope(env);
1176
1177
  // TODO(trevnorris): Adding "_asyncQueue" to the "this" in the init callback
1178
  // is a horrible way to detect usage. Rethink how detection should happen.
1179
6217
  if (recv->IsObject()) {
1180
6217
    object = recv.As<Object>();
1181
12434
    Local<Value> async_queue_v = object->Get(env->async_queue_string());
1182
6217
    if (async_queue_v->IsObject())
1183
      ran_init_callback = true;
1184
  }
1185
1186
6217
  if (env->using_domains()) {
1187
1397
    CHECK(recv->IsObject());
1188
2794
    Local<Value> domain_v = object->Get(env->domain_string());
1189
1397
    has_domain = domain_v->IsObject();
1190
1397
    if (has_domain) {
1191
13
      domain = domain_v.As<Object>();
1192
39
      if (domain->Get(env->disposed_string())->IsTrue())
1193
        return Undefined(env->isolate());
1194
    }
1195
  }
1196
1197
6217
  if (has_domain) {
1198
26
    Local<Value> enter_v = domain->Get(env->enter_string());
1199
13
    if (enter_v->IsFunction()) {
1200
39
      if (enter_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1201
        FatalError("node::MakeCallback",
1202
                   "domain enter callback threw, please report this");
1203
      }
1204
    }
1205
  }
1206
1207

6217
  if (ran_init_callback && !pre_fn.IsEmpty()) {
1208
    TryCatch try_catch(env->isolate());
1209
    MaybeLocal<Value> ar = pre_fn->Call(env->context(), object, 0, nullptr);
1210
    if (ar.IsEmpty()) {
1211
      ClearFatalExceptionHandlers(env);
1212
      FatalException(env->isolate(), try_catch);
1213
      return Local<Value>();
1214
    }
1215
  }
1216
1217
6217
  Local<Value> ret = callback->Call(recv, argc, argv);
1218
1219

6199
  if (ran_init_callback && !post_fn.IsEmpty()) {
1220
    Local<Value> did_throw = Boolean::New(env->isolate(), ret.IsEmpty());
1221
    // Currently there's no way to retrieve an uid from node::MakeCallback().
1222
    // This needs to be fixed.
1223
    Local<Value> vals[] =
1224
        { Undefined(env->isolate()).As<Value>(), did_throw };
1225
    TryCatch try_catch(env->isolate());
1226
    MaybeLocal<Value> ar =
1227
        post_fn->Call(env->context(), object, arraysize(vals), vals);
1228
    if (ar.IsEmpty()) {
1229
      ClearFatalExceptionHandlers(env);
1230
      FatalException(env->isolate(), try_catch);
1231
      return Local<Value>();
1232
    }
1233
  }
1234
1235
6199
  if (ret.IsEmpty()) {
1236
    // NOTE: For backwards compatibility with public API we return Undefined()
1237
    // if the top level call threw.
1238
1023
    return callback_scope.in_makecallback() ?
1239
2042
        ret : Undefined(env->isolate()).As<Value>();
1240
  }
1241
1242
5176
  if (has_domain) {
1243
20
    Local<Value> exit_v = domain->Get(env->exit_string());
1244
10
    if (exit_v->IsFunction()) {
1245
30
      if (exit_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1246
        FatalError("node::MakeCallback",
1247
                   "domain exit callback threw, please report this");
1248
      }
1249
    }
1250
  }
1251
1252
5176
  if (callback_scope.in_makecallback()) {
1253
23
    return ret;
1254
  }
1255
1256
5153
  Environment::TickInfo* tick_info = env->tick_info();
1257
1258
5153
  if (tick_info->length() == 0) {
1259
3661
    env->isolate()->RunMicrotasks();
1260
  }
1261
1262
5153
  Local<Object> process = env->process_object();
1263
1264
5153
  if (tick_info->length() == 0) {
1265
    tick_info->set_index(0);
1266
  }
1267
1268
15459
  if (env->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1269
3
    return Undefined(env->isolate());
1270
  }
1271
1272
5152
  return ret;
1273
}
1274
1275
1276
6185
Local<Value> MakeCallback(Environment* env,
1277
                           Local<Object> recv,
1278
                           Local<String> symbol,
1279
                           int argc,
1280
                           Local<Value> argv[]) {
1281
6185
  Local<Value> cb_v = recv->Get(symbol);
1282
6185
  CHECK(cb_v->IsFunction());
1283
12370
  return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
1284
}
1285
1286
1287
3065
Local<Value> MakeCallback(Environment* env,
1288
                           Local<Object> recv,
1289
                           const char* method,
1290
                           int argc,
1291
                           Local<Value> argv[]) {
1292
3065
  Local<String> method_string = OneByteString(env->isolate(), method);
1293
3065
  return MakeCallback(env, recv, method_string, argc, argv);
1294
}
1295
1296
1297
5
Local<Value> MakeCallback(Isolate* isolate,
1298
                          Local<Object> recv,
1299
                          const char* method,
1300
                          int argc,
1301
                          Local<Value> argv[]) {
1302
10
  EscapableHandleScope handle_scope(isolate);
1303
5
  Local<String> method_string = OneByteString(isolate, method);
1304
  return handle_scope.Escape(
1305
15
      MakeCallback(isolate, recv, method_string, argc, argv));
1306
}
1307
1308
1309
10
Local<Value> MakeCallback(Isolate* isolate,
1310
                          Local<Object> recv,
1311
                          Local<String> symbol,
1312
                          int argc,
1313
                          Local<Value> argv[]) {
1314
20
  EscapableHandleScope handle_scope(isolate);
1315
20
  Local<Value> callback_v = recv->Get(symbol);
1316
10
  if (callback_v.IsEmpty()) return Local<Value>();
1317
10
  if (!callback_v->IsFunction()) return Local<Value>();
1318
10
  Local<Function> callback = callback_v.As<Function>();
1319
10
  return handle_scope.Escape(MakeCallback(isolate, recv, callback, argc, argv));
1320
}
1321
1322
1323
32
Local<Value> MakeCallback(Isolate* isolate,
1324
                          Local<Object> recv,
1325
                          Local<Function> callback,
1326
                          int argc,
1327
                          Local<Value> argv[]) {
1328
  // Observe the following two subtleties:
1329
  //
1330
  // 1. The environment is retrieved from the callback function's context.
1331
  // 2. The context to enter is retrieved from the environment.
1332
  //
1333
  // Because of the AssignToContext() call in src/node_contextify.cc,
1334
  // the two contexts need not be the same.
1335
64
  EscapableHandleScope handle_scope(isolate);
1336
64
  Environment* env = Environment::GetCurrent(callback->CreationContext());
1337
96
  Context::Scope context_scope(env->context());
1338
  return handle_scope.Escape(
1339
96
      MakeCallback(env, recv.As<Value>(), callback, argc, argv));
1340
}
1341
1342
1343
54972
enum encoding ParseEncoding(const char* encoding,
1344
                            enum encoding default_encoding) {
1345

54972
  switch (encoding[0]) {
1346
    case 'u':
1347
      // utf8, utf16le
1348

4603
      if (encoding[1] == 't' && encoding[2] == 'f') {
1349
        // Skip `-`
1350
4412
        encoding += encoding[3] == '-' ? 4 : 3;
1351

4412
        if (encoding[0] == '8' && encoding[1] == '\0')
1352
          return UTF8;
1353
14
        if (strncmp(encoding, "16le", 4) == 0)
1354
          return UCS2;
1355
1356
      // ucs2
1357

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

190
        if (encoding[0] == '2' && encoding[1] == '\0')
1360
          return UCS2;
1361
      }
1362
      break;
1363
    case 'l':
1364
      // latin1
1365
47398
      if (encoding[1] == 'a') {
1366
47396
        if (strncmp(encoding + 2, "tin1", 4) == 0)
1367
          return LATIN1;
1368
      }
1369
      break;
1370
    case 'b':
1371
      // binary
1372
446
      if (encoding[1] == 'i') {
1373
30
        if (strncmp(encoding + 2, "nary", 4) == 0)
1374
          return LATIN1;
1375
1376
      // buffer
1377
416
      } else if (encoding[1] == 'u') {
1378
391
        if (strncmp(encoding + 2, "ffer", 4) == 0)
1379
          return BUFFER;
1380
      }
1381
      break;
1382
    case '\0':
1383
      return default_encoding;
1384
    default:
1385
      break;
1386
  }
1387
1388
2552
  if (StringEqualNoCase(encoding, "utf8")) {
1389
    return UTF8;
1390
2552
  } else if (StringEqualNoCase(encoding, "utf-8")) {
1391
    return UTF8;
1392
2551
  } else if (StringEqualNoCase(encoding, "ascii")) {
1393
    return ASCII;
1394
2504
  } else if (StringEqualNoCase(encoding, "base64")) {
1395
    return BASE64;
1396
2481
  } else if (StringEqualNoCase(encoding, "ucs2")) {
1397
    return UCS2;
1398
2481
  } else if (StringEqualNoCase(encoding, "ucs-2")) {
1399
    return UCS2;
1400
2481
  } else if (StringEqualNoCase(encoding, "utf16le")) {
1401
    return UCS2;
1402
2481
  } else if (StringEqualNoCase(encoding, "utf-16le")) {
1403
    return UCS2;
1404
2481
  } else if (StringEqualNoCase(encoding, "latin1")) {
1405
    return LATIN1;
1406
2481
  } else if (StringEqualNoCase(encoding, "binary")) {
1407
    return LATIN1;  // BINARY is a deprecated alias of LATIN1.
1408
2481
  } else if (StringEqualNoCase(encoding, "buffer")) {
1409
    return BUFFER;
1410
2481
  } else if (StringEqualNoCase(encoding, "hex")) {
1411
    return HEX;
1412
  } else {
1413
5
    return default_encoding;
1414
  }
1415
}
1416
1417
1418
56903
enum encoding ParseEncoding(Isolate* isolate,
1419
                            Local<Value> encoding_v,
1420
                            enum encoding default_encoding) {
1421
113806
  if (!encoding_v->IsString())
1422
    return default_encoding;
1423
1424
54972
  node::Utf8Value encoding(isolate, encoding_v);
1425
1426
54972
  return ParseEncoding(*encoding, default_encoding);
1427
}
1428
1429
193
Local<Value> Encode(Isolate* isolate,
1430
                    const char* buf,
1431
                    size_t len,
1432
                    enum encoding encoding) {
1433
193
  CHECK_NE(encoding, UCS2);
1434
193
  return StringBytes::Encode(isolate, buf, len, encoding);
1435
}
1436
1437
Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1438
  return StringBytes::Encode(isolate, buf, len);
1439
}
1440
1441
// Returns -1 if the handle was not valid for decoding
1442
ssize_t DecodeBytes(Isolate* isolate,
1443
                    Local<Value> val,
1444
                    enum encoding encoding) {
1445
  HandleScope scope(isolate);
1446
1447
  return StringBytes::Size(isolate, val, encoding);
1448
}
1449
1450
// Returns number of bytes written.
1451
ssize_t DecodeWrite(Isolate* isolate,
1452
                    char* buf,
1453
                    size_t buflen,
1454
                    Local<Value> val,
1455
                    enum encoding encoding) {
1456
  return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1457
}
1458
1459
359
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
1460

359
  if (!er.IsEmpty() && er->IsObject()) {
1461
359
    Local<Object> err_obj = er.As<Object>();
1462
    auto maybe_value =
1463
718
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
1464
359
    Local<Value> decorated;
1465

359
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
1466
  }
1467
  return false;
1468
}
1469
1470
359
void AppendExceptionLine(Environment* env,
1471
                         Local<Value> er,
1472
                         Local<Message> message,
1473
                         enum ErrorHandlingMode mode) {
1474
359
  if (message.IsEmpty())
1475
26
    return;
1476
1477
692
  HandleScope scope(env->isolate());
1478
359
  Local<Object> err_obj;
1479

359
  if (!er.IsEmpty() && er->IsObject()) {
1480
359
    err_obj = er.As<Object>();
1481
1482
359
    auto context = env->context();
1483
359
    auto processed_private_symbol = env->processed_private_symbol();
1484
    // Do it only once per message
1485
718
    if (err_obj->HasPrivate(context, processed_private_symbol).FromJust())
1486
15
      return;
1487
    err_obj->SetPrivate(
1488
        context,
1489
        processed_private_symbol,
1490
1032
        True(env->isolate()));
1491
  }
1492
1493
  // Print (filename):(line number): (message).
1494
677
  node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1495
344
  const char* filename_string = *filename;
1496
344
  int linenum = message->GetLineNumber();
1497
  // Print line of source code.
1498
1021
  node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1499
344
  const char* sourceline_string = *sourceline;
1500
1501
  // Because of how node modules work, all scripts are wrapped with a
1502
  // "function (module, exports, __filename, ...) {"
1503
  // to provide script local variables.
1504
  //
1505
  // When reporting errors on the first line of a script, this wrapper
1506
  // function is leaked to the user. There used to be a hack here to
1507
  // truncate off the first 62 characters, but it caused numerous other
1508
  // problems when vm.runIn*Context() methods were used for non-module
1509
  // code.
1510
  //
1511
  // If we ever decide to re-instate such a hack, the following steps
1512
  // must be taken:
1513
  //
1514
  // 1. Pass a flag around to say "this code was wrapped"
1515
  // 2. Update the stack frame output so that it is also correct.
1516
  //
1517
  // It would probably be simpler to add a line rather than add some
1518
  // number of characters to the first line, since V8 truncates the
1519
  // sourceline to 78 characters, and we end up not providing very much
1520
  // useful debugging info to the user if we remove 62 characters.
1521
1522
1032
  int start = message->GetStartColumn(env->context()).FromMaybe(0);
1523
1032
  int end = message->GetEndColumn(env->context()).FromMaybe(0);
1524
1525
  char arrow[1024];
1526
344
  int max_off = sizeof(arrow) - 2;
1527
1528
  int off = snprintf(arrow,
1529
                     sizeof(arrow),
1530
                     "%s:%i\n%s\n",
1531
                     filename_string,
1532
                     linenum,
1533
344
                     sourceline_string);
1534
344
  CHECK_GE(off, 0);
1535
344
  if (off > max_off) {
1536
138
    off = max_off;
1537
  }
1538
1539
  // Print wavy underline (GetUnderline is deprecated).
1540
12672
  for (int i = 0; i < start; i++) {
1541

6309
    if (sourceline_string[i] == '\0' || off >= max_off) {
1542
      break;
1543
    }
1544
6164
    CHECK_LT(off, max_off);
1545
6164
    arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1546
  }
1547
1600
  for (int i = start; i < end; i++) {
1548

792
    if (sourceline_string[i] == '\0' || off >= max_off) {
1549
      break;
1550
    }
1551
628
    CHECK_LT(off, max_off);
1552
628
    arrow[off++] = '^';
1553
  }
1554
344
  CHECK_LE(off, max_off);
1555
344
  arrow[off] = '\n';
1556
344
  arrow[off + 1] = '\0';
1557
1558
344
  Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1559
1560

344
  const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
1561
  // If allocating arrow_str failed, print it out. There's not much else to do.
1562
  // If it's not an error, but something needs to be printed out because
1563
  // it's a fatal exception, also print it out from here.
1564
  // Otherwise, the arrow property will be attached to the object and handled
1565
  // by the caller.
1566


344
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
1567
11
    if (env->printed_error())
1568
11
      return;
1569
11
    env->set_printed_error(true);
1570
1571
11
    uv_tty_reset_mode();
1572
11
    PrintErrorString("\n%s", arrow);
1573
11
    return;
1574
  }
1575
1576
1665
  CHECK(err_obj->SetPrivate(
1577
            env->context(),
1578
            env->arrow_message_private_symbol(),
1579
            arrow_str).FromMaybe(false));
1580
}
1581
1582
1583
58
static void ReportException(Environment* env,
1584
                            Local<Value> er,
1585
                            Local<Message> message) {
1586
116
  HandleScope scope(env->isolate());
1587
1588
58
  AppendExceptionLine(env, er, message, FATAL_ERROR);
1589
1590
58
  Local<Value> trace_value;
1591
58
  Local<Value> arrow;
1592
58
  const bool decorated = IsExceptionDecorated(env, er);
1593
1594

174
  if (er->IsUndefined() || er->IsNull()) {
1595
    trace_value = Undefined(env->isolate());
1596
  } else {
1597
58
    Local<Object> err_obj = er->ToObject(env->isolate());
1598
1599
116
    trace_value = err_obj->Get(env->stack_string());
1600
    arrow =
1601
58
        err_obj->GetPrivate(
1602
            env->context(),
1603
116
            env->arrow_message_private_symbol()).ToLocalChecked();
1604
  }
1605
1606
116
  node::Utf8Value trace(env->isolate(), trace_value);
1607
1608
  // range errors have a trace member set to undefined
1609

116
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1610


114
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1611
25
      PrintErrorString("%s\n", *trace);
1612
    } else {
1613
64
      node::Utf8Value arrow_string(env->isolate(), arrow);
1614
32
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1615
    }
1616
  } else {
1617
    // this really only happens for RangeErrors, since they're the only
1618
    // kind that won't have all this info in the trace, or when non-Error
1619
    // objects are thrown manually.
1620
1
    Local<Value> message;
1621
1
    Local<Value> name;
1622
1623
1
    if (er->IsObject()) {
1624
1
      Local<Object> err_obj = er.As<Object>();
1625
2
      message = err_obj->Get(env->message_string());
1626
2
      name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1627
    }
1628
1629

3
    if (message.IsEmpty() ||
1630
2
        message->IsUndefined() ||
1631

1
        name.IsEmpty() ||
1632
        name->IsUndefined()) {
1633
      // Not an error object. Just print as-is.
1634
2
      String::Utf8Value message(er);
1635
1636
1
      PrintErrorString("%s\n", *message ? *message :
1637
1
                                          "<toString() threw exception>");
1638
    } else {
1639
      node::Utf8Value name_string(env->isolate(), name);
1640
      node::Utf8Value message_string(env->isolate(), message);
1641
1642
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1643
        PrintErrorString("%s: %s\n", *name_string, *message_string);
1644
      } else {
1645
        node::Utf8Value arrow_string(env->isolate(), arrow);
1646
        PrintErrorString("%s\n%s: %s\n",
1647
                         *arrow_string,
1648
                         *name_string,
1649
                         *message_string);
1650
      }
1651
    }
1652
  }
1653
1654
58
  fflush(stderr);
1655
58
}
1656
1657
1658
2
static void ReportException(Environment* env, const TryCatch& try_catch) {
1659
2
  ReportException(env, try_catch.Exception(), try_catch.Message());
1660
2
}
1661
1662
1663
// Executes a str within the current v8 context.
1664
1727
static Local<Value> ExecuteString(Environment* env,
1665
                                  Local<String> source,
1666
                                  Local<String> filename) {
1667
3454
  EscapableHandleScope scope(env->isolate());
1668
3454
  TryCatch try_catch(env->isolate());
1669
1670
  // try_catch must be nonverbose to disable FatalException() handler,
1671
  // we will handle exceptions ourself.
1672
1727
  try_catch.SetVerbose(false);
1673
1674
5181
  ScriptOrigin origin(filename);
1675
  MaybeLocal<v8::Script> script =
1676
1727
      v8::Script::Compile(env->context(), source, &origin);
1677
1727
  if (script.IsEmpty()) {
1678
    ReportException(env, try_catch);
1679
    exit(3);
1680
  }
1681
1682
1727
  Local<Value> result = script.ToLocalChecked()->Run();
1683
1727
  if (result.IsEmpty()) {
1684
    ReportException(env, try_catch);
1685
    exit(4);
1686
  }
1687
1688
3454
  return scope.Escape(result);
1689
}
1690
1691
1692
1
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1693
1
  Environment* env = Environment::GetCurrent(args);
1694
1695
1
  Local<Array> ary = Array::New(args.GetIsolate());
1696
1
  Local<Context> ctx = env->context();
1697
1
  Local<Function> fn = env->push_values_to_array_function();
1698
17
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1699
1
  size_t idx = 0;
1700
1701
15
  for (auto w : *env->req_wrap_queue()) {
1702
24
    if (w->persistent().IsEmpty())
1703
      continue;
1704
36
    argv[idx] = w->object();
1705
12
    if (++idx >= arraysize(argv)) {
1706
3
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1707
1
      idx = 0;
1708
    }
1709
  }
1710
1711
1
  if (idx > 0) {
1712
3
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1713
  }
1714
1715
2
  args.GetReturnValue().Set(ary);
1716
1
}
1717
1718
1719
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1720
// implemented here for consistency with GetActiveRequests().
1721
3
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1722
3
  Environment* env = Environment::GetCurrent(args);
1723
1724
3
  Local<Array> ary = Array::New(env->isolate());
1725
3
  Local<Context> ctx = env->context();
1726
3
  Local<Function> fn = env->push_values_to_array_function();
1727
51
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1728
3
  size_t idx = 0;
1729
1730
3
  Local<String> owner_sym = env->owner_string();
1731
1732
29
  for (auto w : *env->handle_wrap_queue()) {
1733

40
    if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
1734
      continue;
1735
40
    Local<Object> object = w->object();
1736
20
    Local<Value> owner = object->Get(owner_sym);
1737
40
    if (owner->IsUndefined())
1738
3
      owner = object;
1739
20
    argv[idx] = owner;
1740
20
    if (++idx >= arraysize(argv)) {
1741
6
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1742
2
      idx = 0;
1743
    }
1744
  }
1745
3
  if (idx > 0) {
1746
6
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1747
  }
1748
1749
6
  args.GetReturnValue().Set(ary);
1750
3
}
1751
1752
1753
NO_RETURN void Abort() {
1754
  DumpBacktrace(stderr);
1755
  fflush(stderr);
1756
  ABORT_NO_BACKTRACE();
1757
}
1758
1759
1760
NO_RETURN void Assert(const char* const (*args)[4]) {
1761
  auto filename = (*args)[0];
1762
  auto linenum = (*args)[1];
1763
  auto message = (*args)[2];
1764
  auto function = (*args)[3];
1765
1766
  char exepath[256];
1767
  size_t exepath_size = sizeof(exepath);
1768
  if (uv_exepath(exepath, &exepath_size))
1769
    snprintf(exepath, sizeof(exepath), "node");
1770
1771
  char pid[12] = {0};
1772
#ifndef _WIN32
1773
  snprintf(pid, sizeof(pid), "[%u]", getpid());
1774
#endif
1775
1776
  fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
1777
          exepath, pid, filename, linenum,
1778
          function, *function ? ":" : "", message);
1779
  fflush(stderr);
1780
1781
  Abort();
1782
}
1783
1784
1785
static void Abort(const FunctionCallbackInfo<Value>& args) {
1786
  Abort();
1787
}
1788
1789
1790
44
static void Chdir(const FunctionCallbackInfo<Value>& args) {
1791
44
  Environment* env = Environment::GetCurrent(args);
1792
1793

172
  if (args.Length() != 1 || !args[0]->IsString()) {
1794
3
    return env->ThrowTypeError("Bad argument.");
1795
  }
1796
1797
123
  node::Utf8Value path(args.GetIsolate(), args[0]);
1798
41
  int err = uv_chdir(*path);
1799
41
  if (err) {
1800
    return env->ThrowUVException(err, "uv_chdir");
1801
  }
1802
}
1803
1804
1805
2108
static void Cwd(const FunctionCallbackInfo<Value>& args) {
1806
2108
  Environment* env = Environment::GetCurrent(args);
1807
#ifdef _WIN32
1808
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1809
  char buf[MAX_PATH * 4];
1810
#else
1811
  char buf[PATH_MAX];
1812
#endif
1813
1814
2108
  size_t cwd_len = sizeof(buf);
1815
2108
  int err = uv_cwd(buf, &cwd_len);
1816
2108
  if (err) {
1817
4
    return env->ThrowUVException(err, "uv_cwd");
1818
  }
1819
1820
  Local<String> cwd = String::NewFromUtf8(env->isolate(),
1821
                                          buf,
1822
                                          String::kNormalString,
1823
2104
                                          cwd_len);
1824
4208
  args.GetReturnValue().Set(cwd);
1825
}
1826
1827
1828
138
static void Umask(const FunctionCallbackInfo<Value>& args) {
1829
138
  Environment* env = Environment::GetCurrent(args);
1830
  uint32_t old;
1831
1832

282
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1833
135
    old = umask(0);
1834
135
    umask(static_cast<mode_t>(old));
1835

8
  } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1836
    return env->ThrowTypeError("argument must be an integer or octal string.");
1837
  } else {
1838
    int oct;
1839
3
    if (args[0]->IsInt32()) {
1840
2
      oct = args[0]->Uint32Value();
1841
    } else {
1842
1
      oct = 0;
1843
2
      node::Utf8Value str(env->isolate(), args[0]);
1844
1845
      // Parse the octal string.
1846
5
      for (size_t i = 0; i < str.length(); i++) {
1847
4
        char c = (*str)[i];
1848
4
        if (c > '7' || c < '0') {
1849
          return env->ThrowTypeError("invalid octal string");
1850
        }
1851
4
        oct *= 8;
1852
4
        oct += c - '0';
1853
      }
1854
    }
1855
3
    old = umask(static_cast<mode_t>(oct));
1856
  }
1857
1858
138
  args.GetReturnValue().Set(old);
1859
}
1860
1861
1862
#if defined(__POSIX__) && !defined(__ANDROID__)
1863
1864
static const uid_t uid_not_found = static_cast<uid_t>(-1);
1865
static const gid_t gid_not_found = static_cast<gid_t>(-1);
1866
1867
1868
static uid_t uid_by_name(const char* name) {
1869
  struct passwd pwd;
1870
  struct passwd* pp;
1871
  char buf[8192];
1872
1873
  errno = 0;
1874
  pp = nullptr;
1875
1876
  if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1877
    return pp->pw_uid;
1878
  }
1879
1880
  return uid_not_found;
1881
}
1882
1883
1884
static char* name_by_uid(uid_t uid) {
1885
  struct passwd pwd;
1886
  struct passwd* pp;
1887
  char buf[8192];
1888
  int rc;
1889
1890
  errno = 0;
1891
  pp = nullptr;
1892
1893
  if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1894
      pp != nullptr) {
1895
    return strdup(pp->pw_name);
1896
  }
1897
1898
  if (rc == 0) {
1899
    errno = ENOENT;
1900
  }
1901
1902
  return nullptr;
1903
}
1904
1905
1906
static gid_t gid_by_name(const char* name) {
1907
  struct group pwd;
1908
  struct group* pp;
1909
  char buf[8192];
1910
1911
  errno = 0;
1912
  pp = nullptr;
1913
1914
  if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1915
    return pp->gr_gid;
1916
  }
1917
1918
  return gid_not_found;
1919
}
1920
1921
1922
#if 0  // For future use.
1923
static const char* name_by_gid(gid_t gid) {
1924
  struct group pwd;
1925
  struct group* pp;
1926
  char buf[8192];
1927
  int rc;
1928
1929
  errno = 0;
1930
  pp = nullptr;
1931
1932
  if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1933
      pp != nullptr) {
1934
    return strdup(pp->gr_name);
1935
  }
1936
1937
  if (rc == 0) {
1938
    errno = ENOENT;
1939
  }
1940
1941
  return nullptr;
1942
}
1943
#endif
1944
1945
1946
static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1947
  if (value->IsUint32()) {
1948
    return static_cast<uid_t>(value->Uint32Value());
1949
  } else {
1950
    node::Utf8Value name(isolate, value);
1951
    return uid_by_name(*name);
1952
  }
1953
}
1954
1955
1956
static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1957
  if (value->IsUint32()) {
1958
    return static_cast<gid_t>(value->Uint32Value());
1959
  } else {
1960
    node::Utf8Value name(isolate, value);
1961
    return gid_by_name(*name);
1962
  }
1963
}
1964
1965
16
static void GetUid(const FunctionCallbackInfo<Value>& args) {
1966
  // uid_t is an uint32_t on all supported platforms.
1967
48
  args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1968
16
}
1969
1970
1971
5
static void GetGid(const FunctionCallbackInfo<Value>& args) {
1972
  // gid_t is an uint32_t on all supported platforms.
1973
15
  args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1974
5
}
1975
1976
1977
static void GetEUid(const FunctionCallbackInfo<Value>& args) {
1978
  // uid_t is an uint32_t on all supported platforms.
1979
  args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
1980
}
1981
1982
1983
static void GetEGid(const FunctionCallbackInfo<Value>& args) {
1984
  // gid_t is an uint32_t on all supported platforms.
1985
  args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
1986
}
1987
1988
1989
static void SetGid(const FunctionCallbackInfo<Value>& args) {
1990
  Environment* env = Environment::GetCurrent(args);
1991
1992
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1993
    return env->ThrowTypeError("setgid argument must be a number or a string");
1994
  }
1995
1996
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1997
1998
  if (gid == gid_not_found) {
1999
    return env->ThrowError("setgid group id does not exist");
2000
  }
2001
2002
  if (setgid(gid)) {
2003
    return env->ThrowErrnoException(errno, "setgid");
2004
  }
2005
}
2006
2007
2008
static void SetEGid(const FunctionCallbackInfo<Value>& args) {
2009
  Environment* env = Environment::GetCurrent(args);
2010
2011
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2012
    return env->ThrowTypeError("setegid argument must be a number or string");
2013
  }
2014
2015
  gid_t gid = gid_by_name(env->isolate(), args[0]);
2016
2017
  if (gid == gid_not_found) {
2018
    return env->ThrowError("setegid group id does not exist");
2019
  }
2020
2021
  if (setegid(gid)) {
2022
    return env->ThrowErrnoException(errno, "setegid");
2023
  }
2024
}
2025
2026
2027
static void SetUid(const FunctionCallbackInfo<Value>& args) {
2028
  Environment* env = Environment::GetCurrent(args);
2029
2030
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2031
    return env->ThrowTypeError("setuid argument must be a number or a string");
2032
  }
2033
2034
  uid_t uid = uid_by_name(env->isolate(), args[0]);
2035
2036
  if (uid == uid_not_found) {
2037
    return env->ThrowError("setuid user id does not exist");
2038
  }
2039
2040
  if (setuid(uid)) {
2041
    return env->ThrowErrnoException(errno, "setuid");
2042
  }
2043
}
2044
2045
2046
static void SetEUid(const FunctionCallbackInfo<Value>& args) {
2047
  Environment* env = Environment::GetCurrent(args);
2048
2049
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2050
    return env->ThrowTypeError("seteuid argument must be a number or string");
2051
  }
2052
2053
  uid_t uid = uid_by_name(env->isolate(), args[0]);
2054
2055
  if (uid == uid_not_found) {
2056
    return env->ThrowError("seteuid user id does not exist");
2057
  }
2058
2059
  if (seteuid(uid)) {
2060
    return env->ThrowErrnoException(errno, "seteuid");
2061
  }
2062
}
2063
2064
2065
1
static void GetGroups(const FunctionCallbackInfo<Value>& args) {
2066
1
  Environment* env = Environment::GetCurrent(args);
2067
2068
1
  int ngroups = getgroups(0, nullptr);
2069
2070
1
  if (ngroups == -1) {
2071
    return env->ThrowErrnoException(errno, "getgroups");
2072
  }
2073
2074
1
  gid_t* groups = new gid_t[ngroups];
2075
2076
1
  ngroups = getgroups(ngroups, groups);
2077
2078
1
  if (ngroups == -1) {
2079
    delete[] groups;
2080
    return env->ThrowErrnoException(errno, "getgroups");
2081
  }
2082
2083
1
  Local<Array> groups_list = Array::New(env->isolate(), ngroups);
2084
1
  bool seen_egid = false;
2085
1
  gid_t egid = getegid();
2086
2087
2
  for (int i = 0; i < ngroups; i++) {
2088
2
    groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
2089
1
    if (groups[i] == egid)
2090
1
      seen_egid = true;
2091
  }
2092
2093
1
  delete[] groups;
2094
2095
1
  if (seen_egid == false) {
2096
    groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
2097
  }
2098
2099
1
  args.GetReturnValue().Set(groups_list);
2100
}
2101
2102
2103
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
2104
  Environment* env = Environment::GetCurrent(args);
2105
2106
  if (!args[0]->IsArray()) {
2107
    return env->ThrowTypeError("argument 1 must be an array");
2108
  }
2109
2110
  Local<Array> groups_list = args[0].As<Array>();
2111
  size_t size = groups_list->Length();
2112
  gid_t* groups = new gid_t[size];
2113
2114
  for (size_t i = 0; i < size; i++) {
2115
    gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
2116
2117
    if (gid == gid_not_found) {
2118
      delete[] groups;
2119
      return env->ThrowError("group name not found");
2120
    }
2121
2122
    groups[i] = gid;
2123
  }
2124
2125
  int rc = setgroups(size, groups);
2126
  delete[] groups;
2127
2128
  if (rc == -1) {
2129
    return env->ThrowErrnoException(errno, "setgroups");
2130
  }
2131
}
2132
2133
2134
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
2135
  Environment* env = Environment::GetCurrent(args);
2136
2137
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2138
    return env->ThrowTypeError("argument 1 must be a number or a string");
2139
  }
2140
2141
  if (!args[1]->IsUint32() && !args[1]->IsString()) {
2142
    return env->ThrowTypeError("argument 2 must be a number or a string");
2143
  }
2144
2145
  node::Utf8Value arg0(env->isolate(), args[0]);
2146
  gid_t extra_group;
2147
  bool must_free;
2148
  char* user;
2149
2150
  if (args[0]->IsUint32()) {
2151
    user = name_by_uid(args[0]->Uint32Value());
2152
    must_free = true;
2153
  } else {
2154
    user = *arg0;
2155
    must_free = false;
2156
  }
2157
2158
  if (user == nullptr) {
2159
    return env->ThrowError("initgroups user not found");
2160
  }
2161
2162
  extra_group = gid_by_name(env->isolate(), args[1]);
2163
2164
  if (extra_group == gid_not_found) {
2165
    if (must_free)
2166
      free(user);
2167
    return env->ThrowError("initgroups extra group not found");
2168
  }
2169
2170
  int rc = initgroups(user, extra_group);
2171
2172
  if (must_free) {
2173
    free(user);
2174
  }
2175
2176
  if (rc) {
2177
    return env->ThrowErrnoException(errno, "initgroups");
2178
  }
2179
}
2180
2181
#endif  // __POSIX__ && !defined(__ANDROID__)
2182
2183
2184
1664
static void WaitForInspectorDisconnect(Environment* env) {
2185
#if HAVE_INSPECTOR
2186
1664
  if (env->inspector_agent()->IsConnected()) {
2187
    // Restore signal dispositions, the app is done and is no longer
2188
    // capable of handling signals.
2189
#ifdef __POSIX__
2190
    struct sigaction act;
2191
    memset(&act, 0, sizeof(act));
2192
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
2193
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
2194
        continue;
2195
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
2196
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
2197
    }
2198
#endif
2199
    env->inspector_agent()->WaitForDisconnect();
2200
  }
2201
#endif
2202
1664
}
2203
2204
2205
143
void Exit(const FunctionCallbackInfo<Value>& args) {
2206
143
  WaitForInspectorDisconnect(Environment::GetCurrent(args));
2207
143
  exit(args[0]->Int32Value());
2208
}
2209
2210
2211
static void Uptime(const FunctionCallbackInfo<Value>& args) {
2212
  Environment* env = Environment::GetCurrent(args);
2213
  double uptime;
2214
2215
  uv_update_time(env->event_loop());
2216
  uptime = uv_now(env->event_loop()) - prog_start_time;
2217
2218
  args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2219
}
2220
2221
2222
2
void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2223
2
  Environment* env = Environment::GetCurrent(args);
2224
2225
  size_t rss;
2226
2
  int err = uv_resident_set_memory(&rss);
2227
2
  if (err) {
2228
    return env->ThrowUVException(err, "uv_resident_set_memory");
2229
  }
2230
2231
  // V8 memory usage
2232
2
  HeapStatistics v8_heap_stats;
2233
2
  env->isolate()->GetHeapStatistics(&v8_heap_stats);
2234
2235
  Local<Number> heap_total =
2236
2
      Number::New(env->isolate(), v8_heap_stats.total_heap_size());
2237
  Local<Number> heap_used =
2238
2
      Number::New(env->isolate(), v8_heap_stats.used_heap_size());
2239
  Local<Number> external_mem =
2240
      Number::New(env->isolate(),
2241
4
                  env->isolate()->AdjustAmountOfExternalAllocatedMemory(0));
2242
2243
2
  Local<Object> info = Object::New(env->isolate());
2244
8
  info->Set(env->rss_string(), Number::New(env->isolate(), rss));
2245
6
  info->Set(env->heap_total_string(), heap_total);
2246
6
  info->Set(env->heap_used_string(), heap_used);
2247
6
  info->Set(env->external_string(), external_mem);
2248
2249
4
  args.GetReturnValue().Set(info);
2250
}
2251
2252
2253
43
void Kill(const FunctionCallbackInfo<Value>& args) {
2254
43
  Environment* env = Environment::GetCurrent(args);
2255
2256
43
  if (args.Length() != 2) {
2257
    return env->ThrowError("Bad argument.");
2258
  }
2259
2260
43
  int pid = args[0]->Int32Value();
2261
43
  int sig = args[1]->Int32Value();
2262
43
  int err = uv_kill(pid, sig);
2263
86
  args.GetReturnValue().Set(err);
2264
}
2265
2266
// used in Hrtime() below
2267
#define NANOS_PER_SEC 1000000000
2268
2269
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2270
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2271
// so this function instead returns an Array with 2 entries representing seconds
2272
// and nanoseconds, to avoid any integer overflow possibility.
2273
// Pass in an Array from a previous hrtime() call to instead get a time diff.
2274
20
void Hrtime(const FunctionCallbackInfo<Value>& args) {
2275
20
  uint64_t t = uv_hrtime();
2276
2277
40
  Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
2278
20
  uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
2279
2280
  // These three indices will contain the values for the hrtime tuple. The
2281
  // seconds value is broken into the upper/lower 32 bits and stored in two
2282
  // uint32 fields to be converted back in JS.
2283
20
  fields[0] = (t / NANOS_PER_SEC) >> 32;
2284
20
  fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
2285
20
  fields[2] = t % NANOS_PER_SEC;
2286
20
}
2287
2288
// Microseconds in a second, as a float, used in CPUUsage() below
2289
#define MICROS_PER_SEC 1e6
2290
2291
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
2292
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
2293
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
2294
// Returns those values as Float64 microseconds in the elements of the array
2295
// passed to the function.
2296
33
void CPUUsage(const FunctionCallbackInfo<Value>& args) {
2297
  uv_rusage_t rusage;
2298
2299
  // Call libuv to get the values we'll return.
2300
33
  int err = uv_getrusage(&rusage);
2301
33
  if (err) {
2302
    // On error, return the strerror version of the error code.
2303
    Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
2304
    args.GetReturnValue().Set(errmsg);
2305
    return;
2306
  }
2307
2308
  // Get the double array pointer from the Float64Array argument.
2309
33
  CHECK(args[0]->IsFloat64Array());
2310
66
  Local<Float64Array> array = args[0].As<Float64Array>();
2311
33
  CHECK_EQ(array->Length(), 2);
2312
33
  Local<ArrayBuffer> ab = array->Buffer();
2313
33
  double* fields = static_cast<double*>(ab->GetContents().Data());
2314
2315
  // Set the Float64Array elements to be user / system values in microseconds.
2316
33
  fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
2317
33
  fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
2318
}
2319
2320
46850
extern "C" void node_module_register(void* m) {
2321
46850
  struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2322
2323
46850
  if (mp->nm_flags & NM_F_BUILTIN) {
2324
46818
    mp->nm_link = modlist_builtin;
2325
46818
    modlist_builtin = mp;
2326
32
  } else if (!node_is_initialized) {
2327
    // "Linked" modules are included as part of the node project.
2328
    // Like builtins they are registered *before* node::Init runs.
2329
    mp->nm_flags = NM_F_LINKED;
2330
    mp->nm_link = modlist_linked;
2331
    modlist_linked = mp;
2332
  } else {
2333
32
    modpending = mp;
2334
  }
2335
46850
}
2336
2337
36710
struct node_module* get_builtin_module(const char* name) {
2338
  struct node_module* mp;
2339
2340
537235
  for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
2341
533780
    if (strcmp(mp->nm_modname, name) == 0)
2342
      break;
2343
  }
2344
2345

36710
  CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
2346
36710
  return (mp);
2347
}
2348
2349
struct node_module* get_linked_module(const char* name) {
2350
  struct node_module* mp;
2351
2352
  for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
2353
    if (strcmp(mp->nm_modname, name) == 0)
2354
      break;
2355
  }
2356
2357
  CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
2358
  return mp;
2359
}
2360
2361
typedef void (UV_DYNAMIC* extInit)(Local<Object> exports);
2362
2363
// DLOpen is process.dlopen(module, filename).
2364
// Used to load 'module.node' dynamically shared objects.
2365
//
2366
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2367
// when two contexts try to load the same shared object. Maybe have a shadow
2368
// cache that's a plain C list or hash table that's shared across contexts?
2369
35
void DLOpen(const FunctionCallbackInfo<Value>& args) {
2370
35
  Environment* env = Environment::GetCurrent(args);
2371
  uv_lib_t lib;
2372
2373
35
  CHECK_EQ(modpending, nullptr);
2374
2375
35
  if (args.Length() != 2) {
2376
    env->ThrowError("process.dlopen takes exactly 2 arguments.");
2377
4
    return;
2378
  }
2379
2380
70
  Local<Object> module = args[0]->ToObject(env->isolate());  // Cast
2381
66
  node::Utf8Value filename(env->isolate(), args[1]);  // Cast
2382
35
  const bool is_dlopen_error = uv_dlopen(*filename, &lib);
2383
2384
  // Objects containing v14 or later modules will have registered themselves
2385
  // on the pending list.  Activate all of them now.  At present, only one
2386
  // module per object is supported.
2387
35
  node_module* const mp = modpending;
2388
35
  modpending = nullptr;
2389
2390
35
  if (is_dlopen_error) {
2391
3
    Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
2392
3
    uv_dlclose(&lib);
2393
#ifdef _WIN32
2394
    // Windows needs to add the filename into the error message
2395
    errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
2396
#endif  // _WIN32
2397
3
    env->isolate()->ThrowException(Exception::Error(errmsg));
2398
    return;
2399
  }
2400
2401
32
  if (mp == nullptr) {
2402
    uv_dlclose(&lib);
2403
    env->ThrowError("Module did not self-register.");
2404
    return;
2405
  }
2406
32
  if (mp->nm_version != NODE_MODULE_VERSION) {
2407
    char errmsg[1024];
2408
1
    snprintf(errmsg,
2409
             sizeof(errmsg),
2410
             "The module '%s'"
2411
             "\nwas compiled against a different Node.js version using"
2412
             "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
2413
             "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
2414
             "re-installing\nthe module (for instance, using `npm rebuild` or"
2415
             "`npm install`).",
2416
1
             *filename, mp->nm_version, NODE_MODULE_VERSION);
2417
2418
    // NOTE: `mp` is allocated inside of the shared library's memory, calling
2419
    // `uv_dlclose` will deallocate it
2420
1
    uv_dlclose(&lib);
2421
1
    env->ThrowError(errmsg);
2422
    return;
2423
  }
2424
31
  if (mp->nm_flags & NM_F_BUILTIN) {
2425
    uv_dlclose(&lib);
2426
    env->ThrowError("Built-in module self-registered.");
2427
    return;
2428
  }
2429
2430
31
  mp->nm_dso_handle = lib.handle;
2431
31
  mp->nm_link = modlist_addon;
2432
31
  modlist_addon = mp;
2433
2434
31
  Local<String> exports_string = env->exports_string();
2435
124
  Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
2436
2437
31
  if (mp->nm_context_register_func != nullptr) {
2438
6
    mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2439
29
  } else if (mp->nm_register_func != nullptr) {
2440
58
    mp->nm_register_func(exports, module, mp->nm_priv);
2441
  } else {
2442
    uv_dlclose(&lib);
2443
    env->ThrowError("Module has no declared entry point.");
2444
    return;
2445
  }
2446
2447
  // Tell coverity that 'handle' should not be freed when we return.
2448
  // coverity[leaked_storage]
2449
}
2450
2451
2452
static void OnFatalError(const char* location, const char* message) {
2453
  if (location) {
2454
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2455
  } else {
2456
    PrintErrorString("FATAL ERROR: %s\n", message);
2457
  }
2458
  fflush(stderr);
2459
  ABORT();
2460
}
2461
2462
2463
NO_RETURN void FatalError(const char* location, const char* message) {
2464
  OnFatalError(location, message);
2465
  // to suppress compiler warning
2466
  ABORT();
2467
}
2468
2469
2470
1174
void FatalException(Isolate* isolate,
2471
                    Local<Value> error,
2472
                    Local<Message> message) {
2473
2287
  HandleScope scope(isolate);
2474
2475
1174
  Environment* env = Environment::GetCurrent(isolate);
2476
1174
  Local<Object> process_object = env->process_object();
2477
1174
  Local<String> fatal_exception_string = env->fatal_exception_string();
2478
  Local<Function> fatal_exception_function =
2479
2348
      process_object->Get(fatal_exception_string).As<Function>();
2480
2481
1174
  int exit_code = 0;
2482
1174
  if (!fatal_exception_function->IsFunction()) {
2483
    // failed before the process._fatalException function was added!
2484
    // this is probably pretty bad.  Nothing to do but report and exit.
2485
    ReportException(env, error, message);
2486
    exit_code = 6;
2487
  }
2488
2489
1174
  if (exit_code == 0) {
2490
2345
    TryCatch fatal_try_catch(isolate);
2491
2492
    // Do not call FatalException when _fatalException handler throws
2493
1174
    fatal_try_catch.SetVerbose(false);
2494
2495
    // this will return true if the JS layer handled it, false otherwise
2496
    Local<Value> caught =
2497
1174
        fatal_exception_function->Call(process_object, 1, &error);
2498
2499
1171
    if (fatal_try_catch.HasCaught()) {
2500
      // the fatal exception function threw, so we must exit
2501
2
      ReportException(env, fatal_try_catch);
2502
2
      exit_code = 7;
2503
    }
2504
2505

2340
    if (exit_code == 0 && false == caught->BooleanValue()) {
2506
56
      ReportException(env, error, message);
2507
56
      exit_code = 1;
2508
    }
2509
  }
2510
2511
1171
  if (exit_code) {
2512
#if HAVE_INSPECTOR
2513
58
    if (debug_options.inspector_enabled()) {
2514
      env->inspector_agent()->FatalException(error, message);
2515
    }
2516
#endif
2517
58
    exit(exit_code);
2518
  }
2519
1113
}
2520
2521
2522
4
void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2523
4
  HandleScope scope(isolate);
2524
  // TODO(bajtos) do not call FatalException if try_catch is verbose
2525
  // (requires V8 API to expose getter for try_catch.is_verbose_)
2526
4
  FatalException(isolate, try_catch.Exception(), try_catch.Message());
2527
}
2528
2529
2530
1170
void OnMessage(Local<Message> message, Local<Value> error) {
2531
  // The current version of V8 sends messages for errors only
2532
  // (thus `error` is always set).
2533
1170
  FatalException(Isolate::GetCurrent(), error, message);
2534
1113
}
2535
2536
2537
4
void ClearFatalExceptionHandlers(Environment* env) {
2538
4
  Local<Object> process = env->process_object();
2539
  Local<Value> events =
2540
16
      process->Get(env->context(), env->events_string()).ToLocalChecked();
2541
2542
4
  if (events->IsObject()) {
2543
12
    events.As<Object>()->Set(
2544
        env->context(),
2545
        OneByteString(env->isolate(), "uncaughtException"),
2546
32
        Undefined(env->isolate())).FromJust();
2547
  }
2548
2549
8
  process->Set(
2550
      env->context(),
2551
      env->domain_string(),
2552
32
      Undefined(env->isolate())).FromJust();
2553
4
}
2554
2555
// Call process.emitWarning(str), fmt is a snprintf() format string
2556
1
void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
2557
  char warning[1024];
2558
  va_list ap;
2559
2560
1
  va_start(ap, fmt);
2561
1
  vsnprintf(warning, sizeof(warning), fmt, ap);
2562
1
  va_end(ap);
2563
2564
2
  HandleScope handle_scope(env->isolate());
2565
3
  Context::Scope context_scope(env->context());
2566
2567
1
  Local<Object> process = env->process_object();
2568
  MaybeLocal<Value> emit_warning = process->Get(env->context(),
2569
3
      FIXED_ONE_BYTE_STRING(env->isolate(), "emitWarning"));
2570
2
  Local<Value> arg = node::OneByteString(env->isolate(), warning);
2571
2572
1
  Local<Value> f;
2573
2574
1
  if (!emit_warning.ToLocal(&f)) return;
2575
1
  if (!f->IsFunction()) return;
2576
2577
  // MakeCallback() unneeded, because emitWarning is internal code, it calls
2578
  // process.emit('warning', ..), but does so on the nextTick.
2579
2
  f.As<v8::Function>()->Call(process, 1, &arg);
2580
}
2581
2582
2583
93600
static void Binding(const FunctionCallbackInfo<Value>& args) {
2584
93600
  Environment* env = Environment::GetCurrent(args);
2585
2586
187200
  Local<String> module = args[0]->ToString(env->isolate());
2587
128582
  node::Utf8Value module_v(env->isolate(), module);
2588
2589
93600
  Local<Object> cache = env->binding_cache_object();
2590
93600
  Local<Object> exports;
2591
2592
280800
  if (cache->Has(env->context(), module).FromJust()) {
2593
175851
    exports = cache->Get(module)->ToObject(env->isolate());
2594
58617
    args.GetReturnValue().Set(exports);
2595
58618
    return;
2596
  }
2597
2598
  // Append a string to process.moduleLoadList
2599
  char buf[1024];
2600
69966
  snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2601
2602
34983
  Local<Array> modules = env->module_load_list_array();
2603
34983
  uint32_t l = modules->Length();
2604
69966
  modules->Set(l, OneByteString(env->isolate(), buf));
2605
2606
34983
  node_module* mod = get_builtin_module(*module_v);
2607
34983
  if (mod != nullptr) {
2608
31528
    exports = Object::New(env->isolate());
2609
    // Internal bindings don't have a "module" object, only exports.
2610
31528
    CHECK_EQ(mod->nm_register_func, nullptr);
2611
31528
    CHECK_NE(mod->nm_context_register_func, nullptr);
2612
94584
    Local<Value> unused = Undefined(env->isolate());
2613
63056
    mod->nm_context_register_func(exports, unused,
2614
31528
      env->context(), mod->nm_priv);
2615
63056
    cache->Set(module, exports);
2616
3455
  } else if (!strcmp(*module_v, "constants")) {
2617
1727
    exports = Object::New(env->isolate());
2618
1727
    DefineConstants(env->isolate(), exports);
2619
3454
    cache->Set(module, exports);
2620
1728
  } else if (!strcmp(*module_v, "natives")) {
2621
1727
    exports = Object::New(env->isolate());
2622
1727
    DefineJavaScript(env, exports);
2623
3454
    cache->Set(module, exports);
2624
  } else {
2625
    char errmsg[1024];
2626
1
    snprintf(errmsg,
2627
             sizeof(errmsg),
2628
             "No such module: %s",
2629
1
             *module_v);
2630
1
    return env->ThrowError(errmsg);
2631
  }
2632
2633
69964
  args.GetReturnValue().Set(exports);
2634
}
2635
2636
static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2637
  Environment* env = Environment::GetCurrent(args.GetIsolate());
2638
2639
  Local<String> module_name = args[0]->ToString(env->isolate());
2640
2641
  Local<Object> cache = env->binding_cache_object();
2642
  Local<Value> exports_v = cache->Get(module_name);
2643
2644
  if (exports_v->IsObject())
2645
    return args.GetReturnValue().Set(exports_v.As<Object>());
2646
2647
  node::Utf8Value module_name_v(env->isolate(), module_name);
2648
  node_module* mod = get_linked_module(*module_name_v);
2649
2650
  if (mod == nullptr) {
2651
    char errmsg[1024];
2652
    snprintf(errmsg,
2653
             sizeof(errmsg),
2654
             "No such module was linked: %s",
2655
             *module_name_v);
2656
    return env->ThrowError(errmsg);
2657
  }
2658
2659
  Local<Object> module = Object::New(env->isolate());
2660
  Local<Object> exports = Object::New(env->isolate());
2661
  Local<String> exports_prop = String::NewFromUtf8(env->isolate(), "exports");
2662
  module->Set(exports_prop, exports);
2663
2664
  if (mod->nm_context_register_func != nullptr) {
2665
    mod->nm_context_register_func(exports,
2666
                                  module,
2667
                                  env->context(),
2668
                                  mod->nm_priv);
2669
  } else if (mod->nm_register_func != nullptr) {
2670
    mod->nm_register_func(exports, module, mod->nm_priv);
2671
  } else {
2672
    return env->ThrowError("Linked module has no declared entry point.");
2673
  }
2674
2675
  auto effective_exports = module->Get(exports_prop);
2676
  cache->Set(module_name, effective_exports);
2677
2678
  args.GetReturnValue().Set(effective_exports);
2679
}
2680
2681
4
static void ProcessTitleGetter(Local<Name> property,
2682
                               const PropertyCallbackInfo<Value>& info) {
2683
  char buffer[512];
2684
4
  uv_get_process_title(buffer, sizeof(buffer));
2685
12
  info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer));
2686
4
}
2687
2688
2689
27
static void ProcessTitleSetter(Local<Name> property,
2690
                               Local<Value> value,
2691
                               const PropertyCallbackInfo<void>& info) {
2692
54
  node::Utf8Value title(info.GetIsolate(), value);
2693
  // TODO(piscisaureus): protect with a lock
2694
27
  uv_set_process_title(*title);
2695
27
}
2696
2697
2698
31501
static void EnvGetter(Local<Name> property,
2699
                      const PropertyCallbackInfo<Value>& info) {
2700
31501
  Isolate* isolate = info.GetIsolate();
2701
31501
  if (property->IsSymbol()) {
2702
18716
    return info.GetReturnValue().SetUndefined();
2703
  }
2704
#ifdef __POSIX__
2705
44290
  node::Utf8Value key(isolate, property);
2706
31497
  const char* val = getenv(*key);
2707
31497
  if (val) {
2708
56112
    return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
2709
  }
2710
#else  // _WIN32
2711
  node::TwoByteValue key(isolate, property);
2712
  WCHAR buffer[32767];  // The maximum size allowed for environment variables.
2713
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2714
                                         buffer,
2715
                                         arraysize(buffer));
2716
  // If result >= sizeof buffer the buffer was too small. That should never
2717
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2718
  // not found.
2719
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2720
      result < arraysize(buffer)) {
2721
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2722
    Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
2723
    return info.GetReturnValue().Set(rc);
2724
  }
2725
#endif
2726
}
2727
2728
2729
97
static void EnvSetter(Local<Name> property,
2730
                      Local<Value> value,
2731
                      const PropertyCallbackInfo<Value>& info) {
2732
#ifdef __POSIX__
2733
291
  node::Utf8Value key(info.GetIsolate(), property);
2734
194
  node::Utf8Value val(info.GetIsolate(), value);
2735
97
  setenv(*key, *val, 1);
2736
#else  // _WIN32
2737
  node::TwoByteValue key(info.GetIsolate(), property);
2738
  node::TwoByteValue val(info.GetIsolate(), value);
2739
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2740
  // Environment variables that start with '=' are read-only.
2741
  if (key_ptr[0] != L'=') {
2742
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2743
  }
2744
#endif
2745
  // Whether it worked or not, always return value.
2746
194
  info.GetReturnValue().Set(value);
2747
97
}
2748
2749
2750
10266
static void EnvQuery(Local<Name> property,
2751
                     const PropertyCallbackInfo<Integer>& info) {
2752
10266
  int32_t rc = -1;  // Not found unless proven otherwise.
2753
#ifdef __POSIX__
2754
30798
  node::Utf8Value key(info.GetIsolate(), property);
2755
10266
  if (getenv(*key))
2756
9765
    rc = 0;
2757
#else  // _WIN32
2758
  node::TwoByteValue key(info.GetIsolate(), property);
2759
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2760
  if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
2761
      GetLastError() == ERROR_SUCCESS) {
2762
    rc = 0;
2763
    if (key_ptr[0] == L'=') {
2764
      // Environment variables that start with '=' are hidden and read-only.
2765
      rc = static_cast<int32_t>(v8::ReadOnly) |
2766
           static_cast<int32_t>(v8::DontDelete) |
2767
           static_cast<int32_t>(v8::DontEnum);
2768
    }
2769
  }
2770
#endif
2771
10266
  if (rc != -1)
2772
19530
    info.GetReturnValue().Set(rc);
2773
10266
}
2774
2775
2776
282
static void EnvDeleter(Local<Name> property,
2777
                       const PropertyCallbackInfo<Boolean>& info) {
2778
#ifdef __POSIX__
2779
846
  node::Utf8Value key(info.GetIsolate(), property);
2780
282
  unsetenv(*key);
2781
#else
2782
  node::TwoByteValue key(info.GetIsolate(), property);
2783
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2784
  SetEnvironmentVariableW(key_ptr, nullptr);
2785
#endif
2786
2787
  // process.env never has non-configurable properties, so always
2788
  // return true like the tc39 delete operator.
2789
564
  info.GetReturnValue().Set(true);
2790
282
}
2791
2792
2793
839
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2794
839
  Environment* env = Environment::GetCurrent(info);
2795
839
  Isolate* isolate = env->isolate();
2796
839
  Local<Context> ctx = env->context();
2797
839
  Local<Function> fn = env->push_values_to_array_function();
2798
14263
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
2799
  size_t idx = 0;
2800
2801
#ifdef __POSIX__
2802
  int size = 0;
2803
25015
  while (environ[size])
2804
12088
    size++;
2805
2806
839
  Local<Array> envarr = Array::New(isolate);
2807
2808
12927
  for (int i = 0; i < size; ++i) {
2809
12088
    const char* var = environ[i];
2810
12088
    const char* s = strchr(var, '=');
2811
12088
    const int length = s ? s - var : strlen(var);
2812
    argv[idx] = String::NewFromUtf8(isolate,
2813
                                    var,
2814
                                    String::kNormalString,
2815
24176
                                    length);
2816
12088
    if (++idx >= arraysize(argv)) {
2817
2847
      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2818
949
      idx = 0;
2819
    }
2820
  }
2821
839
  if (idx > 0) {
2822
2337
    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
1678
  info.GetReturnValue().Set(envarr);
2861
839
}
2862
2863
2864
1727
static Local<Object> GetFeatures(Environment* env) {
2865
3454
  EscapableHandleScope scope(env->isolate());
2866
2867
1727
  Local<Object> obj = Object::New(env->isolate());
2868
#if defined(DEBUG) && DEBUG
2869
  Local<Value> debug = True(env->isolate());
2870
#else
2871
5181
  Local<Value> debug = False(env->isolate());
2872
#endif  // defined(DEBUG) && DEBUG
2873
2874
3454
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "debug"), debug);
2875
6908
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "uv"), True(env->isolate()));
2876
  // TODO(bnoordhuis) ping libuv
2877
6908
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "ipv6"), True(env->isolate()));
2878
2879
#ifdef OPENSSL_NPN_NEGOTIATED
2880
3454
  Local<Boolean> tls_npn = True(env->isolate());
2881
#else
2882
  Local<Boolean> tls_npn = False(env->isolate());
2883
#endif
2884
3454
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_npn"), tls_npn);
2885
2886
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2887
3454
  Local<Boolean> tls_alpn = True(env->isolate());
2888
#else
2889
  Local<Boolean> tls_alpn = False(env->isolate());
2890
#endif
2891
3454
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_alpn"), tls_alpn);
2892
2893
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2894
3454
  Local<Boolean> tls_sni = True(env->isolate());
2895
#else
2896
  Local<Boolean> tls_sni = False(env->isolate());
2897
#endif
2898
3454
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_sni"), tls_sni);
2899
2900
#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2901
3454
  Local<Boolean> tls_ocsp = True(env->isolate());
2902
#else
2903
  Local<Boolean> tls_ocsp = False(env->isolate());
2904
#endif  // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2905
3454
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_ocsp"), tls_ocsp);
2906
2907
8635
  obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls"),
2908
           Boolean::New(env->isolate(),
2909
3454
                        get_builtin_module("crypto") != nullptr));
2910
2911
3454
  return scope.Escape(obj);
2912
}
2913
2914
2915
41
static void DebugPortGetter(Local<Name> property,
2916
                            const PropertyCallbackInfo<Value>& info) {
2917
123
  info.GetReturnValue().Set(debug_options.port());
2918
41
}
2919
2920
2921
static void DebugPortSetter(Local<Name> property,
2922
                            Local<Value> value,
2923
                            const PropertyCallbackInfo<void>& info) {
2924
  debug_options.set_port(value->Int32Value());
2925
}
2926
2927
2928
static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2929
static void DebugPause(const FunctionCallbackInfo<Value>& args);
2930
static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2931
2932
2933
5362
void NeedImmediateCallbackGetter(Local<Name> property,
2934
                                 const PropertyCallbackInfo<Value>& info) {
2935
5362
  Environment* env = Environment::GetCurrent(info);
2936
5362
  const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2937
5362
  bool active = uv_is_active(
2938
5362
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2939
16086
  info.GetReturnValue().Set(active);
2940
5362
}
2941
2942
2943
3526
static void NeedImmediateCallbackSetter(
2944
    Local<Name> property,
2945
    Local<Value> value,
2946
    const PropertyCallbackInfo<void>& info) {
2947
3526
  Environment* env = Environment::GetCurrent(info);
2948
2949
3526
  uv_check_t* immediate_check_handle = env->immediate_check_handle();
2950
3526
  bool active = uv_is_active(
2951
3526
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2952
2953
3526
  if (active == value->BooleanValue())
2954
    return;
2955
2956
3503
  uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2957
2958
3503
  if (active) {
2959
1742
    uv_check_stop(immediate_check_handle);
2960
1742
    uv_idle_stop(immediate_idle_handle);
2961
  } else {
2962
1761
    uv_check_start(immediate_check_handle, CheckImmediate);
2963
    // Idle handle is needed only to stop the event loop from blocking in poll.
2964
1761
    uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2965
  }
2966
}
2967
2968
2969
void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2970
  Environment* env = Environment::GetCurrent(args);
2971
  env->StartProfilerIdleNotifier();
2972
}
2973
2974
2975
void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2976
  Environment* env = Environment::GetCurrent(args);
2977
  env->StopProfilerIdleNotifier();
2978
}
2979
2980
2981
#define READONLY_PROPERTY(obj, str, var)                                      \
2982
  do {                                                                        \
2983
    obj->DefineOwnProperty(env->context(),                                    \
2984
                           OneByteString(env->isolate(), str),                \
2985
                           var,                                               \
2986
                           v8::ReadOnly).FromJust();                          \
2987
  } while (0)
2988
2989
#define READONLY_DONT_ENUM_PROPERTY(obj, str, var)                            \
2990
  do {                                                                        \
2991
    obj->DefineOwnProperty(env->context(),                                    \
2992
                           OneByteString(env->isolate(), str),                \
2993
                           var,                                               \
2994
                           static_cast<v8::PropertyAttribute>(v8::ReadOnly |  \
2995
                                                              v8::DontEnum))  \
2996
        .FromJust();                                                          \
2997
  } while (0)
2998
2999
3000
1727
void SetupProcessObject(Environment* env,
3001
                        int argc,
3002
                        const char* const* argv,
3003
                        int exec_argc,
3004
                        const char* const* exec_argv) {
3005
3454
  HandleScope scope(env->isolate());
3006
3007
1727
  Local<Object> process = env->process_object();
3008
3009
1727
  auto title_string = FIXED_ONE_BYTE_STRING(env->isolate(), "title");
3010
8635
  CHECK(process->SetAccessor(env->context(),
3011
                             title_string,
3012
                             ProcessTitleGetter,
3013
                             ProcessTitleSetter,
3014
                             env->as_external()).FromJust());
3015
3016
  // process.version
3017
8635
  READONLY_PROPERTY(process,
3018
                    "version",
3019
                    FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
3020
3021
  // process.moduleLoadList
3022
8635
  READONLY_PROPERTY(process,
3023
                    "moduleLoadList",
3024
                    env->module_load_list_array());
3025
3026
  // process.versions
3027
1727
  Local<Object> versions = Object::New(env->isolate());
3028
6908
  READONLY_PROPERTY(process, "versions", versions);
3029
3030
  const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
3031
                                     "."
3032
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
3033
                                     "."
3034
1727
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
3035
8635
  READONLY_PROPERTY(versions,
3036
                    "http_parser",
3037
                    FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
3038
3039
  // +1 to get rid of the leading 'v'
3040
8635
  READONLY_PROPERTY(versions,
3041
                    "node",
3042
                    OneByteString(env->isolate(), NODE_VERSION + 1));
3043
8635
  READONLY_PROPERTY(versions,
3044
                    "v8",
3045
                    OneByteString(env->isolate(), V8::GetVersion()));
3046
8635
  READONLY_PROPERTY(versions,
3047
                    "uv",
3048
                    OneByteString(env->isolate(), uv_version_string()));
3049
8635
  READONLY_PROPERTY(versions,
3050
                    "zlib",
3051
                    FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
3052
8635
  READONLY_PROPERTY(versions,
3053
                    "ares",
3054
                    FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
3055
3056
#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
3057
  // ICU-related versions are now handled on the js side, see bootstrap_node.js
3058
3059
1727
  if (icu_data_dir != nullptr) {
3060
    // Did the user attempt (via env var or parameter) to set an ICU path?
3061
    READONLY_PROPERTY(process,
3062
                      "icu_data_dir",
3063
                      OneByteString(env->isolate(), icu_data_dir));
3064
  }
3065
#endif
3066
3067
1727
  const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
3068
8635
  READONLY_PROPERTY(
3069
      versions,
3070
      "modules",
3071
      FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
3072
3073
  // process._promiseRejectEvent
3074
1727
  Local<Object> promiseRejectEvent = Object::New(env->isolate());
3075
6908
  READONLY_DONT_ENUM_PROPERTY(process,
3076
                              "_promiseRejectEvent",
3077
                              promiseRejectEvent);
3078
8635
  READONLY_PROPERTY(promiseRejectEvent,
3079
                    "unhandled",
3080
                    Integer::New(env->isolate(),
3081
                                 v8::kPromiseRejectWithNoHandler));
3082
8635
  READONLY_PROPERTY(promiseRejectEvent,
3083
                    "handled",
3084
                    Integer::New(env->isolate(),
3085
                                 v8::kPromiseHandlerAddedAfterReject));
3086
3087
#if HAVE_OPENSSL
3088
  // Stupid code to slice out the version string.
3089
  {  // NOLINT(whitespace/braces)
3090
    size_t i, j, k;
3091
    int c;
3092
15543
    for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
3093
15543
      c = OPENSSL_VERSION_TEXT[i];
3094
15543
      if ('0' <= c && c <= '9') {
3095
10362
        for (j = i + 1; j < k; ++j) {
3096
10362
          c = OPENSSL_VERSION_TEXT[j];
3097
10362
          if (c == ' ')
3098
            break;
3099
        }
3100
        break;
3101
      }
3102
    }
3103
8635
    READONLY_PROPERTY(
3104
        versions,
3105
        "openssl",
3106
        OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
3107
  }
3108
#endif
3109
3110
  // process.arch
3111
8635
  READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
3112
3113
  // process.platform
3114
8635
  READONLY_PROPERTY(process,
3115
                    "platform",
3116
                    OneByteString(env->isolate(), NODE_PLATFORM));
3117
3118
  // process.release
3119
1727
  Local<Object> release = Object::New(env->isolate());
3120
6908
  READONLY_PROPERTY(process, "release", release);
3121
8635
  READONLY_PROPERTY(release, "name", OneByteString(env->isolate(), "node"));
3122
3123
// if this is a release build and no explicit base has been set
3124
// substitute the standard release download URL
3125
#ifndef NODE_RELEASE_URLBASE
3126
# if NODE_VERSION_IS_RELEASE
3127
#  define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
3128
# endif
3129
#endif
3130
3131
#if defined(NODE_RELEASE_URLBASE)
3132
#  define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
3133
#  define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
3134
3135
  READONLY_PROPERTY(release,
3136
                    "sourceUrl",
3137
                    OneByteString(env->isolate(),
3138
                    NODE_RELEASE_URLFPFX ".tar.gz"));
3139
  READONLY_PROPERTY(release,
3140
                    "headersUrl",
3141
                    OneByteString(env->isolate(),
3142
                    NODE_RELEASE_URLFPFX "-headers.tar.gz"));
3143
#  ifdef _WIN32
3144
  READONLY_PROPERTY(release,
3145
                    "libUrl",
3146
                    OneByteString(env->isolate(),
3147
                    strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-"
3148
                                                NODE_ARCH "/node.lib"
3149
                                              : NODE_RELEASE_URLPFX
3150
                                                "win-x86/node.lib"));
3151
#  endif
3152
#endif
3153
3154
  // process.argv
3155
1727
  Local<Array> arguments = Array::New(env->isolate(), argc);
3156
5431
  for (int i = 0; i < argc; ++i) {
3157
11112
    arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
3158
  }
3159
3454
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "argv"), arguments);
3160
3161
  // process.execArgv
3162
1727
  Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
3163
2041
  for (int i = 0; i < exec_argc; ++i) {
3164
942
    exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
3165
  }
3166
5181
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execArgv"),
3167
1727
               exec_arguments);
3168
3169
  // create process.env
3170
  Local<ObjectTemplate> process_env_template =
3171
1727
      ObjectTemplate::New(env->isolate());
3172
6908
  process_env_template->SetHandler(NamedPropertyHandlerConfiguration(
3173
          EnvGetter,
3174
          EnvSetter,
3175
          EnvQuery,
3176
          EnvDeleter,
3177
          EnvEnumerator,
3178
1727
          env->as_external()));
3179
3180
  Local<Object> process_env =
3181
3454
      process_env_template->NewInstance(env->context()).ToLocalChecked();
3182
3454
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "env"), process_env);
3183
3184
8635
  READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
3185
8635
  READONLY_PROPERTY(process, "features", GetFeatures(env));
3186
3187
  auto need_immediate_callback_string =
3188
1727
      FIXED_ONE_BYTE_STRING(env->isolate(), "_needImmediateCallback");
3189
8635
  CHECK(process->SetAccessor(env->context(), need_immediate_callback_string,
3190
                             NeedImmediateCallbackGetter,
3191
                             NeedImmediateCallbackSetter,
3192
                             env->as_external()).FromJust());
3193
3194
  // -e, --eval
3195
1727
  if (eval_string) {
3196
325
    READONLY_PROPERTY(process,
3197
                      "_eval",
3198
                      String::NewFromUtf8(env->isolate(), eval_string));
3199
  }
3200
3201
  // -p, --print
3202
1727
  if (print_eval) {
3203
132
    READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
3204
  }
3205
3206
  // -c, --check
3207
1727
  if (syntax_check_only) {
3208
132
    READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
3209
  }
3210
3211
  // -i, --interactive
3212
1727
  if (force_repl) {
3213
102
    READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
3214
  }
3215
3216
1727
  if (preload_module_count) {
3217
13
    CHECK(preload_modules);
3218
13
    Local<Array> array = Array::New(env->isolate());
3219
30
    for (unsigned int i = 0; i < preload_module_count; ++i) {
3220
      Local<String> module = String::NewFromUtf8(env->isolate(),
3221
17
                                                 preload_modules[i]);
3222
34
      array->Set(i, module);
3223
    }
3224
52
    READONLY_PROPERTY(process,
3225
                      "_preload_modules",
3226
                      array);
3227
3228
13
    delete[] preload_modules;
3229
13
    preload_modules = nullptr;
3230
13
    preload_module_count = 0;
3231
  }
3232
3233
  // --no-deprecation
3234
1727
  if (no_deprecation) {
3235
6
    READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
3236
  }
3237
3238
1727
  if (no_process_warnings) {
3239
42
    READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
3240
  }
3241
3242
1727
  if (trace_warnings) {
3243
6
    READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
3244
  }
3245
3246
  // --throw-deprecation
3247
1727
  if (throw_deprecation) {
3248
    READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
3249
  }
3250
3251
#ifdef NODE_NO_BROWSER_GLOBALS
3252
  // configure --no-browser-globals
3253
  READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
3254
#endif  // NODE_NO_BROWSER_GLOBALS
3255
3256
  // --prof-process
3257
1727
  if (prof_process) {
3258
    READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
3259
  }
3260
3261
  // --trace-deprecation
3262
1727
  if (trace_deprecation) {
3263
6
    READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
3264
  }
3265
3266
  // --debug-brk
3267
1727
  if (debug_options.wait_for_connect()) {
3268
12
    READONLY_PROPERTY(process, "_debugWaitConnect", True(env->isolate()));
3269
  }
3270
3271
  // --security-revert flags
3272
#define V(code, _, __)                                                        \
3273
  do {                                                                        \
3274
    if (IsReverted(REVERT_ ## code)) {                                        \
3275
      READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate()));      \
3276
    }                                                                         \
3277
  } while (0);
3278
  REVERSIONS(V)
3279
#undef V
3280
3281
1727
  size_t exec_path_len = 2 * PATH_MAX;
3282
1727
  char* exec_path = new char[exec_path_len];
3283
1727
  Local<String> exec_path_value;
3284
1727
  if (uv_exepath(exec_path, &exec_path_len) == 0) {
3285
    exec_path_value = String::NewFromUtf8(env->isolate(),
3286
                                          exec_path,
3287
                                          String::kNormalString,
3288
1727
                                          exec_path_len);
3289
  } else {
3290
    exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
3291
  }
3292
5181
  process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
3293
1727
               exec_path_value);
3294
1727
  delete[] exec_path;
3295
3296
1727
  auto debug_port_string = FIXED_ONE_BYTE_STRING(env->isolate(), "debugPort");
3297
8635
  CHECK(process->SetAccessor(env->context(),
3298
                             debug_port_string,
3299
                             DebugPortGetter,
3300
                             DebugPortSetter,
3301
                             env->as_external()).FromJust());
3302
3303
  // define various internal methods
3304
  env->SetMethod(process,
3305
                 "_startProfilerIdleNotifier",
3306
1727
                 StartProfilerIdleNotifier);
3307
  env->SetMethod(process,
3308
                 "_stopProfilerIdleNotifier",
3309
1727
                 StopProfilerIdleNotifier);
3310
1727
  env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
3311
1727
  env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
3312
1727
  env->SetMethod(process, "reallyExit", Exit);
3313
1727
  env->SetMethod(process, "abort", Abort);
3314
1727
  env->SetMethod(process, "chdir", Chdir);
3315
1727
  env->SetMethod(process, "cwd", Cwd);
3316
3317
1727
  env->SetMethod(process, "umask", Umask);
3318
3319
#if defined(__POSIX__) && !defined(__ANDROID__)
3320
1727
  env->SetMethod(process, "getuid", GetUid);
3321
1727
  env->SetMethod(process, "geteuid", GetEUid);
3322
1727
  env->SetMethod(process, "setuid", SetUid);
3323
1727
  env->SetMethod(process, "seteuid", SetEUid);
3324
3325
1727
  env->SetMethod(process, "setgid", SetGid);
3326
1727
  env->SetMethod(process, "setegid", SetEGid);
3327
1727
  env->SetMethod(process, "getgid", GetGid);
3328
1727
  env->SetMethod(process, "getegid", GetEGid);
3329
3330
1727
  env->SetMethod(process, "getgroups", GetGroups);
3331
1727
  env->SetMethod(process, "setgroups", SetGroups);
3332
1727
  env->SetMethod(process, "initgroups", InitGroups);
3333
#endif  // __POSIX__ && !defined(__ANDROID__)
3334
3335
1727
  env->SetMethod(process, "_kill", Kill);
3336
3337
1727
  env->SetMethod(process, "_debugProcess", DebugProcess);
3338
1727
  env->SetMethod(process, "_debugPause", DebugPause);
3339
1727
  env->SetMethod(process, "_debugEnd", DebugEnd);
3340
3341
1727
  env->SetMethod(process, "hrtime", Hrtime);
3342
3343
1727
  env->SetMethod(process, "cpuUsage", CPUUsage);
3344
3345
1727
  env->SetMethod(process, "dlopen", DLOpen);
3346
3347
1727
  env->SetMethod(process, "uptime", Uptime);
3348
1727
  env->SetMethod(process, "memoryUsage", MemoryUsage);
3349
3350
1727
  env->SetMethod(process, "binding", Binding);
3351
1727
  env->SetMethod(process, "_linkedBinding", LinkedBinding);
3352
3353
1727
  env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
3354
1727
  env->SetMethod(process, "_setupNextTick", SetupNextTick);
3355
1727
  env->SetMethod(process, "_setupPromises", SetupPromises);
3356
1727
  env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
3357
3358
  // pre-set _events object for faster emit checks
3359
1727
  Local<Object> events_obj = Object::New(env->isolate());
3360
10362
  CHECK(events_obj->SetPrototype(env->context(),
3361
                                 Null(env->isolate())).FromJust());
3362
5181
  process->Set(env->events_string(), events_obj);
3363
1727
}
3364
3365
3366
#undef READONLY_PROPERTY
3367
3368
3369
void SignalExit(int signo) {
3370
  uv_tty_reset_mode();
3371
#ifdef __FreeBSD__
3372
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
3373
  struct sigaction sa;
3374
  memset(&sa, 0, sizeof(sa));
3375
  sa.sa_handler = SIG_DFL;
3376
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
3377
#endif
3378
  raise(signo);
3379
}
3380
3381
3382
// Most of the time, it's best to use `console.error` to write
3383
// to the process.stderr stream.  However, in some cases, such as
3384
// when debugging the stream.Writable class or the process.nextTick
3385
// function, it is useful to bypass JavaScript entirely.
3386
7
static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3387


28
  CHECK(args.Length() == 1 && args[0]->IsString() &&
3388
        "must be called with a single string");
3389
21
  node::Utf8Value message(args.GetIsolate(), args[0]);
3390
7
  PrintErrorString("%s\n", *message);
3391
7
  fflush(stderr);
3392
7
}
3393
3394
3395
1727
void LoadEnvironment(Environment* env) {
3396
3367
  HandleScope handle_scope(env->isolate());
3397
3398
3367
  TryCatch try_catch(env->isolate());
3399
3400
  // Disable verbose mode to stop FatalException() handler from trying
3401
  // to handle the exception. Errors this early in the start-up phase
3402
  // are not safe to ignore.
3403
1727
  try_catch.SetVerbose(false);
3404
3405
  // Execute the lib/internal/bootstrap_node.js file which was included as a
3406
  // static C string in node_natives.h by node_js2c.
3407
  // 'internal_bootstrap_node_native' is the string containing that source code.
3408
1727
  Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
3409
                                                    "bootstrap_node.js");
3410
1727
  Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3411
1727
  if (try_catch.HasCaught())  {
3412
    ReportException(env, try_catch);
3413
    exit(10);
3414
  }
3415
  // The bootstrap_node.js file returns a function 'f'
3416
1727
  CHECK(f_value->IsFunction());
3417
1727
  Local<Function> f = Local<Function>::Cast(f_value);
3418
3419
  // Add a reference to the global object
3420
1727
  Local<Object> global = env->context()->Global();
3421
3422
#if defined HAVE_DTRACE || defined HAVE_ETW
3423
  InitDTrace(env, global);
3424
#endif
3425
3426
#if defined HAVE_LTTNG
3427
  InitLTTNG(env, global);
3428
#endif
3429
3430
#if defined HAVE_PERFCTR
3431
  InitPerfCounters(env, global);
3432
#endif
3433
3434
  // Enable handling of uncaught exceptions
3435
  // (FatalException(), break on uncaught exception in debugger)
3436
  //
3437
  // This is not strictly necessary since it's almost impossible
3438
  // to attach the debugger fast enought to break on exception
3439
  // thrown during process startup.
3440
1727
  try_catch.SetVerbose(true);
3441
3442
1727
  env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3443
3444
  // Expose the global object as a property on itself
3445
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
3446
3454
  global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
3447
3448
  // Now we call 'f' with the 'process' variable that we've built up with
3449
  // all our bindings. Inside bootstrap_node.js and internal/process we'll
3450
  // take care of assigning things to their places.
3451
3452
  // We start the process this way in order to be more modular. Developers
3453
  // who do not like how bootstrap_node.js sets up the module system but do
3454
  // like Node's I/O bindings may want to replace 'f' with their own function.
3455
3454
  Local<Value> arg = env->process_object();
3456
5181
  f->Call(Null(env->isolate()), 1, &arg);
3457
1640
}
3458
3459
static void PrintHelp() {
3460
  // XXX: If you add an option here, please also add it to doc/node.1 and
3461
  // doc/api/cli.md
3462
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
3463
         "       node debug script.js [arguments] \n"
3464
         "\n"
3465
         "Options:\n"
3466
         "  -v, --version         print Node.js version\n"
3467
         "  -e, --eval script     evaluate script\n"
3468
         "  -p, --print           evaluate script and print result\n"
3469
         "  -c, --check           syntax check script without executing\n"
3470
         "  -i, --interactive     always enter the REPL even if stdin\n"
3471
         "                        does not appear to be a terminal\n"
3472
         "  -r, --require         module to preload (option can be repeated)\n"
3473
         "  --no-deprecation      silence deprecation warnings\n"
3474
         "  --trace-deprecation   show stack traces on deprecations\n"
3475
         "  --throw-deprecation   throw an exception anytime a deprecated "
3476
         "function is used\n"
3477
         "  --no-warnings         silence all process warnings\n"
3478
         "  --trace-warnings      show stack traces on process warnings\n"
3479
         "  --trace-sync-io       show stack trace when use of sync IO\n"
3480
         "                        is detected after the first tick\n"
3481
         "  --track-heap-objects  track heap object allocations for heap "
3482
         "snapshots\n"
3483
         "  --prof-process        process v8 profiler output generated\n"
3484
         "                        using --prof\n"
3485
         "  --zero-fill-buffers   automatically zero-fill all newly allocated\n"
3486
         "                        Buffer and SlowBuffer instances\n"
3487
         "  --v8-options          print v8 command line options\n"
3488
         "  --v8-pool-size=num    set v8's thread pool size\n"
3489
#if HAVE_OPENSSL
3490
         "  --tls-cipher-list=val use an alternative default TLS cipher list\n"
3491
#if NODE_FIPS_MODE
3492
         "  --enable-fips         enable FIPS crypto at startup\n"
3493
         "  --force-fips          force FIPS crypto (cannot be disabled)\n"
3494
#endif  /* NODE_FIPS_MODE */
3495
         "  --openssl-config=path load OpenSSL configuration file from the\n"
3496
         "                        specified path\n"
3497
#endif /* HAVE_OPENSSL */
3498
#if defined(NODE_HAVE_I18N_SUPPORT)
3499
         "  --icu-data-dir=dir    set ICU data load path to dir\n"
3500
         "                        (overrides NODE_ICU_DATA)\n"
3501
#if !defined(NODE_HAVE_SMALL_ICU)
3502
         "                        note: linked-in ICU data is\n"
3503
         "                        present.\n"
3504
#endif
3505
         "  --preserve-symlinks   preserve symbolic links when resolving\n"
3506
         "                        and caching modules.\n"
3507
#endif
3508
         "\n"
3509
         "Environment variables:\n"
3510
#ifdef _WIN32
3511
         "NODE_PATH                ';'-separated list of directories\n"
3512
#else
3513
         "NODE_PATH                ':'-separated list of directories\n"
3514
#endif
3515
         "                         prefixed to the module search path.\n"
3516
         "NODE_DISABLE_COLORS      set to 1 to disable colors in the REPL\n"
3517
#if defined(NODE_HAVE_I18N_SUPPORT)
3518
         "NODE_ICU_DATA            data path for ICU (Intl object) data\n"
3519
#if !defined(NODE_HAVE_SMALL_ICU)
3520
         "                         (will extend linked-in data)\n"
3521
#endif
3522
#endif
3523
         "NODE_REPL_HISTORY        path to the persistent REPL history file\n"
3524
         "\n"
3525
         "Documentation can be found at https://nodejs.org/\n");
3526
}
3527
3528
3529
// Parse command line arguments.
3530
//
3531
// argv is modified in place. exec_argv and v8_argv are out arguments that
3532
// ParseArgs() allocates memory for and stores a pointer to the output
3533
// vector in.  The caller should free them with delete[].
3534
//
3535
// On exit:
3536
//
3537
//  * argv contains the arguments with node and V8 options filtered out.
3538
//  * exec_argv contains both node and V8 options and nothing else.
3539
//  * v8_argv contains argv[0] plus any V8 options
3540
1734
static void ParseArgs(int* argc,
3541
                      const char** argv,
3542
                      int* exec_argc,
3543
                      const char*** exec_argv,
3544
                      int* v8_argc,
3545
                      const char*** v8_argv) {
3546
1734
  const unsigned int nargs = static_cast<unsigned int>(*argc);
3547
1734
  const char** new_exec_argv = new const char*[nargs];
3548
1734
  const char** new_v8_argv = new const char*[nargs];
3549
1734
  const char** new_argv = new const char*[nargs];
3550
1734
  const char** local_preload_modules = new const char*[nargs];
3551
3552
5778
  for (unsigned int i = 0; i < nargs; ++i) {
3553
4044
    new_exec_argv[i] = nullptr;
3554
4044
    new_v8_argv[i] = nullptr;
3555
4044
    new_argv[i] = nullptr;
3556
4044
    local_preload_modules[i] = nullptr;
3557
  }
3558
3559
  // exec_argv starts with the first option, the other two start with argv[0].
3560
1734
  unsigned int new_exec_argc = 0;
3561
1734
  unsigned int new_v8_argc = 1;
3562
1734
  unsigned int new_argc = 1;
3563
1734
  new_v8_argv[0] = argv[0];
3564
1734
  new_argv[0] = argv[0];
3565
3566
1734
  unsigned int index = 1;
3567
1734
  bool short_circuit = false;
3568

2222
  while (index < nargs && argv[index][0] == '-' && !short_circuit) {
3569
247
    const char* const arg = argv[index];
3570
247
    unsigned int args_consumed = 1;
3571
3572
988
    if (debug_options.ParseOption(arg)) {
3573
      // Done, consumed by DebugOptions::ParseOption().
3574

224
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
3575
2
      printf("%s\n", NODE_VERSION);
3576
2
      exit(0);
3577

222
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3578
      PrintHelp();
3579
      exit(0);
3580

440
    } else if (strcmp(arg, "--eval") == 0 ||
3581
384
               strcmp(arg, "-e") == 0 ||
3582
329
               strcmp(arg, "--print") == 0 ||
3583
319
               strcmp(arg, "-pe") == 0 ||
3584
156
               strcmp(arg, "-p") == 0) {
3585
78
      bool is_eval = strchr(arg, 'e') != nullptr;
3586
78
      bool is_print = strchr(arg, 'p') != nullptr;
3587

78
      print_eval = print_eval || is_print;
3588
      // --eval, -e and -pe always require an argument.
3589
78
      if (is_eval == true) {
3590
63
        args_consumed += 1;
3591
63
        eval_string = argv[index + 1];
3592
63
        if (eval_string == nullptr) {
3593
2
          fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3594
1
          exit(9);
3595
        }
3596

30
      } else if ((index + 1 < nargs) &&
3597
30
                 argv[index + 1] != nullptr &&
3598
15
                 argv[index + 1][0] != '-') {
3599
13
        args_consumed += 1;
3600
13
        eval_string = argv[index + 1];
3601
13
        if (strncmp(eval_string, "\\-", 2) == 0) {
3602
          // Starts with "\\-": escaped expression, drop the backslash.
3603
1
          eval_string += 1;
3604
        }
3605
      }
3606

282
    } else if (strcmp(arg, "--require") == 0 ||
3607
138
               strcmp(arg, "-r") == 0) {
3608
17
      const char* module = argv[index + 1];
3609
17
      if (module == nullptr) {
3610
        fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3611
        exit(9);
3612
      }
3613
17
      args_consumed += 1;
3614
17
      local_preload_modules[preload_module_count++] = module;
3615

127
    } else if (strcmp(arg, "--check") == 0 || strcmp(arg, "-c") == 0) {
3616
22
      syntax_check_only = true;
3617

105
    } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3618
15
      force_repl = true;
3619
90
    } else if (strcmp(arg, "--no-deprecation") == 0) {
3620
1
      no_deprecation = true;
3621
89
    } else if (strcmp(arg, "--no-warnings") == 0) {
3622
7
      no_process_warnings = true;
3623
82
    } else if (strcmp(arg, "--trace-warnings") == 0) {
3624
1
      trace_warnings = true;
3625
81
    } else if (strcmp(arg, "--trace-deprecation") == 0) {
3626
1
      trace_deprecation = true;
3627
80
    } else if (strcmp(arg, "--trace-sync-io") == 0) {
3628
1
      trace_sync_io = true;
3629
79
    } else if (strcmp(arg, "--track-heap-objects") == 0) {
3630
      track_heap_objects = true;
3631
79
    } else if (strcmp(arg, "--throw-deprecation") == 0) {
3632
      throw_deprecation = true;
3633
79
    } else if (strncmp(arg, "--security-revert=", 18) == 0) {
3634
      const char* cve = arg + 18;
3635
      Revert(cve);
3636
79
    } else if (strcmp(arg, "--preserve-symlinks") == 0) {
3637
3
      config_preserve_symlinks = true;
3638
76
    } else if (strcmp(arg, "--prof-process") == 0) {
3639
      prof_process = true;
3640
      short_circuit = true;
3641
76
    } else if (strcmp(arg, "--zero-fill-buffers") == 0) {
3642
1
      zero_fill_all_buffers = true;
3643
75
    } else if (strcmp(arg, "--v8-options") == 0) {
3644
      new_v8_argv[new_v8_argc] = "--help";
3645
      new_v8_argc += 1;
3646
75
    } else if (strncmp(arg, "--v8-pool-size=", 15) == 0) {
3647
      v8_thread_pool_size = atoi(arg + 15);
3648
#if HAVE_OPENSSL
3649
75
    } else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
3650
1
      default_cipher_list = arg + 18;
3651
#if NODE_FIPS_MODE
3652
    } else if (strcmp(arg, "--enable-fips") == 0) {
3653
      enable_fips_crypto = true;
3654
    } else if (strcmp(arg, "--force-fips") == 0) {
3655
      force_fips_crypto = true;
3656
#endif /* NODE_FIPS_MODE */
3657
74
    } else if (strncmp(arg, "--openssl-config=", 17) == 0) {
3658
5
      openssl_config = arg + 17;
3659
#endif /* HAVE_OPENSSL */
3660
#if defined(NODE_HAVE_I18N_SUPPORT)
3661
69
    } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3662
      icu_data_dir = arg + 15;
3663
#endif
3664

128
    } else if (strcmp(arg, "--expose-internals") == 0 ||
3665
59
               strcmp(arg, "--expose_internals") == 0) {
3666
      // consumed in js
3667
    } else {
3668
      // V8 option.  Pass through as-is.