GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/node.cc Lines: 1232 1575 78.2 %
Date: 2016-07-23 Branches: 557 953 58.4 %

Line 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
11
#if defined HAVE_PERFCTR
12
#include "node_counters.h"
13
#endif
14
15
#if HAVE_OPENSSL
16
#include "node_crypto.h"
17
#endif
18
19
#if defined(NODE_HAVE_I18N_SUPPORT)
20
#include "node_i18n.h"
21
#endif
22
23
#if defined HAVE_DTRACE || defined HAVE_ETW
24
#include "node_dtrace.h"
25
#endif
26
27
#if defined HAVE_LTTNG
28
#include "node_lttng.h"
29
#endif
30
31
#include "ares.h"
32
#include "async-wrap.h"
33
#include "async-wrap-inl.h"
34
#include "env.h"
35
#include "env-inl.h"
36
#include "handle_wrap.h"
37
#include "req-wrap.h"
38
#include "req-wrap-inl.h"
39
#include "string_bytes.h"
40
#include "util.h"
41
#include "uv.h"
42
#if NODE_USE_V8_PLATFORM
43
#include "libplatform/libplatform.h"
44
#endif  // NODE_USE_V8_PLATFORM
45
#include "v8-debug.h"
46
#include "v8-profiler.h"
47
#include "zlib.h"
48
49
#ifdef NODE_ENABLE_VTUNE_PROFILING
50
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
51
#endif
52
53
#include <errno.h>
54
#include <limits.h>  // PATH_MAX
55
#include <locale.h>
56
#include <signal.h>
57
#include <stdio.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#include <sys/types.h>
61
62
#include <string>
63
#include <vector>
64
65
#if defined(NODE_HAVE_I18N_SUPPORT)
66
#include <unicode/uvernum.h>
67
#endif
68
69
#if defined(LEAK_SANITIZER)
70
#include <sanitizer/lsan_interface.h>
71
#endif
72
73
#if defined(_MSC_VER)
74
#include <direct.h>
75
#include <io.h>
76
#define getpid GetCurrentProcessId
77
#define umask _umask
78
typedef int mode_t;
79
#else
80
#include <pthread.h>
81
#include <sys/resource.h>  // getrlimit, setrlimit
82
#include <unistd.h>  // setuid, getuid
83
#endif
84
85
#if defined(__POSIX__) && !defined(__ANDROID__)
86
#include <pwd.h>  // getpwnam()
87
#include <grp.h>  // getgrnam()
88
#endif
89
90
#ifdef __APPLE__
91
#include <crt_externs.h>
92
#define environ (*_NSGetEnviron())
93
#elif !defined(_MSC_VER)
94
extern char **environ;
95
#endif
96
97
namespace node {
98
99
using v8::Array;
100
using v8::ArrayBuffer;
101
using v8::Boolean;
102
using v8::Context;
103
using v8::EscapableHandleScope;
104
using v8::Exception;
105
using v8::Float64Array;
106
using v8::Function;
107
using v8::FunctionCallbackInfo;
108
using v8::HandleScope;
109
using v8::HeapStatistics;
110
using v8::Integer;
111
using v8::Isolate;
112
using v8::Local;
113
using v8::Locker;
114
using v8::MaybeLocal;
115
using v8::Message;
116
using v8::Name;
117
using v8::Null;
118
using v8::Number;
119
using v8::Object;
120
using v8::ObjectTemplate;
121
using v8::Promise;
122
using v8::PromiseRejectMessage;
123
using v8::PropertyCallbackInfo;
124
using v8::ScriptOrigin;
125
using v8::SealHandleScope;
126
using v8::String;
127
using v8::TryCatch;
128
using v8::Uint32;
129
using v8::Uint32Array;
130
using v8::V8;
131
using v8::Value;
132
133
static bool print_eval = false;
134
static bool force_repl = false;
135
static bool syntax_check_only = false;
136
static bool trace_deprecation = false;
137
static bool throw_deprecation = false;
138
static bool trace_sync_io = false;
139
static bool track_heap_objects = false;
140
static const char* eval_string = nullptr;
141
static unsigned int preload_module_count = 0;
142
static const char** preload_modules = nullptr;
143
#if HAVE_INSPECTOR
144
static bool use_inspector = false;
145
#else
146
static const bool use_inspector = false;
147
#endif
148
static bool use_debug_agent = false;
149
static bool debug_wait_connect = false;
150
1568
static std::string debug_host;  // NOLINT(runtime/string)
151
static int debug_port = 5858;
152
1568
static std::string inspector_host;  // NOLINT(runtime/string)
153
static int inspector_port = 9229;
154
static const int v8_default_thread_pool_size = 4;
155
static int v8_thread_pool_size = v8_default_thread_pool_size;
156
static bool prof_process = false;
157
static bool v8_is_profiling = false;
158
static bool node_is_initialized = false;
159
static node_module* modpending;
160
static node_module* modlist_builtin;
161
static node_module* modlist_linked;
162
static node_module* modlist_addon;
163
164
#if defined(NODE_HAVE_I18N_SUPPORT)
165
// Path to ICU data (for i18n / Intl)
166
static const char* icu_data_dir = nullptr;
167
#endif
168
169
// used by C++ modules as well
170
bool no_deprecation = false;
171
172
#if HAVE_OPENSSL && NODE_FIPS_MODE
173
// used by crypto module
174
bool enable_fips_crypto = false;
175
bool force_fips_crypto = false;
176
#endif
177
178
// true if process warnings should be suppressed
179
bool no_process_warnings = false;
180
bool trace_warnings = false;
181
182
// Set in node.cc by ParseArgs when --preserve-symlinks is used.
183
// Used in node_config.cc to set a constant on process.binding('config')
184
// that is used by lib/module.js
185
bool config_preserve_symlinks = false;
186
187
// process-relative uptime base, initialized at start-up
188
static double prog_start_time;
189
static bool debugger_running;
190
static uv_async_t dispatch_debug_messages_async;
191
192
1568
static Mutex node_isolate_mutex;
193
static v8::Isolate* node_isolate;
194
195
static struct {
196
#if NODE_USE_V8_PLATFORM
197
  void Initialize(int thread_pool_size) {
198
1557
    platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
199
1557
    V8::InitializePlatform(platform_);
200
  }
201
202
  void PumpMessageLoop(Isolate* isolate) {
203
24096
    v8::platform::PumpMessageLoop(platform_, isolate);
204
  }
205
206
  void Dispose() {
207
1368
    delete platform_;
208
1368
    platform_ = nullptr;
209
  }
210
211
  void StartInspector(Environment *env, int port, bool wait) {
212
#if HAVE_INSPECTOR
213
    env->inspector_agent()->Start(platform_, port, wait);
214
#endif  // HAVE_INSPECTOR
215
  }
216
217
  v8::Platform* platform_;
218
#else  // !NODE_USE_V8_PLATFORM
219
  void Initialize(int thread_pool_size) {}
220
  void PumpMessageLoop(Isolate* isolate) {}
221
  void Dispose() {}
222
  void StartInspector(Environment *env, int port, bool wait) {
223
    env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
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
70
static void PrintErrorString(const char* format, ...) {
234
  va_list ap;
235
70
  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
  WriteConsoleW(stderr_handle, wbuf.data(), n, nullptr, nullptr);
259
#else
260
140
  vfprintf(stderr, format, ap);
261
#endif
262
70
  va_end(ap);
263
70
}
264
265
266
5081
static void CheckImmediate(uv_check_t* handle) {
267
5081
  Environment* env = Environment::from_immediate_check_handle(handle);
268
10158
  HandleScope scope(env->isolate());
269
15239
  Context::Scope context_scope(env->context());
270
10162
  MakeCallback(env, env->process_object(), env->immediate_callback_string());
271
5077
}
272
273
274
4018
static void IdleImmediateDummy(uv_idle_t* handle) {
275
  // Do nothing. Only for maintaining event loop.
276
  // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
277
4018
}
278
279
280
static inline const char *errno_string(int errorno) {
281
#define ERRNO_CASE(e)  case e: return #e;
282
1
  switch (errorno) {
283
#ifdef EACCES
284
  ERRNO_CASE(EACCES);
285
#endif
286
287
#ifdef EADDRINUSE
288
  ERRNO_CASE(EADDRINUSE);
289
#endif
290
291
#ifdef EADDRNOTAVAIL
292
  ERRNO_CASE(EADDRNOTAVAIL);
293
#endif
294
295
#ifdef EAFNOSUPPORT
296
  ERRNO_CASE(EAFNOSUPPORT);
297
#endif
298
299
#ifdef EAGAIN
300
  ERRNO_CASE(EAGAIN);
301
#endif
302
303
#ifdef EWOULDBLOCK
304
# if EAGAIN != EWOULDBLOCK
305
  ERRNO_CASE(EWOULDBLOCK);
306
# endif
307
#endif
308
309
#ifdef EALREADY
310
  ERRNO_CASE(EALREADY);
311
#endif
312
313
#ifdef EBADF
314
  ERRNO_CASE(EBADF);
315
#endif
316
317
#ifdef EBADMSG
318
  ERRNO_CASE(EBADMSG);
319
#endif
320
321
#ifdef EBUSY
322
  ERRNO_CASE(EBUSY);
323
#endif
324
325
#ifdef ECANCELED
326
  ERRNO_CASE(ECANCELED);
327
#endif
328
329
#ifdef ECHILD
330
  ERRNO_CASE(ECHILD);
331
#endif
332
333
#ifdef ECONNABORTED
334
  ERRNO_CASE(ECONNABORTED);
335
#endif
336
337
#ifdef ECONNREFUSED
338
  ERRNO_CASE(ECONNREFUSED);
339
#endif
340
341
#ifdef ECONNRESET
342
  ERRNO_CASE(ECONNRESET);
343
#endif
344
345
#ifdef EDEADLK
346
  ERRNO_CASE(EDEADLK);
347
#endif
348
349
#ifdef EDESTADDRREQ
350
  ERRNO_CASE(EDESTADDRREQ);
351
#endif
352
353
#ifdef EDOM
354
  ERRNO_CASE(EDOM);
355
#endif
356
357
#ifdef EDQUOT
358
  ERRNO_CASE(EDQUOT);
359
#endif
360
361
#ifdef EEXIST
362
  ERRNO_CASE(EEXIST);
363
#endif
364
365
#ifdef EFAULT
366
  ERRNO_CASE(EFAULT);
367
#endif
368
369
#ifdef EFBIG
370
  ERRNO_CASE(EFBIG);
371
#endif
372
373
#ifdef EHOSTUNREACH
374
  ERRNO_CASE(EHOSTUNREACH);
375
#endif
376
377
#ifdef EIDRM
378
  ERRNO_CASE(EIDRM);
379
#endif
380
381
#ifdef EILSEQ
382
  ERRNO_CASE(EILSEQ);
383
#endif
384
385
#ifdef EINPROGRESS
386
  ERRNO_CASE(EINPROGRESS);
387
#endif
388
389
#ifdef EINTR
390
  ERRNO_CASE(EINTR);
391
#endif
392
393
#ifdef EINVAL
394
  ERRNO_CASE(EINVAL);
395
#endif
396
397
#ifdef EIO
398
  ERRNO_CASE(EIO);
399
#endif
400
401
#ifdef EISCONN
402
  ERRNO_CASE(EISCONN);
403
#endif
404
405
#ifdef EISDIR
406
  ERRNO_CASE(EISDIR);
407
#endif
408
409
#ifdef ELOOP
410
  ERRNO_CASE(ELOOP);
411
#endif
412
413
#ifdef EMFILE
414
  ERRNO_CASE(EMFILE);
415
#endif
416
417
#ifdef EMLINK
418
  ERRNO_CASE(EMLINK);
419
#endif
420
421
#ifdef EMSGSIZE
422
  ERRNO_CASE(EMSGSIZE);
423
#endif
424
425
#ifdef EMULTIHOP
426
  ERRNO_CASE(EMULTIHOP);
427
#endif
428
429
#ifdef ENAMETOOLONG
430
  ERRNO_CASE(ENAMETOOLONG);
431
#endif
432
433
#ifdef ENETDOWN
434
  ERRNO_CASE(ENETDOWN);
435
#endif
436
437
#ifdef ENETRESET
438
  ERRNO_CASE(ENETRESET);
439
#endif
440
441
#ifdef ENETUNREACH
442
  ERRNO_CASE(ENETUNREACH);
443
#endif
444
445
#ifdef ENFILE
446
  ERRNO_CASE(ENFILE);
447
#endif
448
449
#ifdef ENOBUFS
450
  ERRNO_CASE(ENOBUFS);
451
#endif
452
453
#ifdef ENODATA
454
  ERRNO_CASE(ENODATA);
455
#endif
456
457
#ifdef ENODEV
458
  ERRNO_CASE(ENODEV);
459
#endif
460
461
#ifdef ENOENT
462
  ERRNO_CASE(ENOENT);
463
#endif
464
465
#ifdef ENOEXEC
466
  ERRNO_CASE(ENOEXEC);
467
#endif
468
469
#ifdef ENOLINK
470
  ERRNO_CASE(ENOLINK);
471
#endif
472
473
#ifdef ENOLCK
474
# if ENOLINK != ENOLCK
475
  ERRNO_CASE(ENOLCK);
476
# endif
477
#endif
478
479
#ifdef ENOMEM
480
  ERRNO_CASE(ENOMEM);
481
#endif
482
483
#ifdef ENOMSG
484
  ERRNO_CASE(ENOMSG);
485
#endif
486
487
#ifdef ENOPROTOOPT
488
  ERRNO_CASE(ENOPROTOOPT);
489
#endif
490
491
#ifdef ENOSPC
492
  ERRNO_CASE(ENOSPC);
493
#endif
494
495
#ifdef ENOSR
496
  ERRNO_CASE(ENOSR);
497
#endif
498
499
#ifdef ENOSTR
500
  ERRNO_CASE(ENOSTR);
501
#endif
502
503
#ifdef ENOSYS
504
  ERRNO_CASE(ENOSYS);
505
#endif
506
507
#ifdef ENOTCONN
508
  ERRNO_CASE(ENOTCONN);
509
#endif
510
511
#ifdef ENOTDIR
512
  ERRNO_CASE(ENOTDIR);
513
#endif
514
515
#ifdef ENOTEMPTY
516
# if ENOTEMPTY != EEXIST
517
  ERRNO_CASE(ENOTEMPTY);
518
# endif
519
#endif
520
521
#ifdef ENOTSOCK
522
  ERRNO_CASE(ENOTSOCK);
523
#endif
524
525
#ifdef ENOTSUP
526
  ERRNO_CASE(ENOTSUP);
527
#else
528
# ifdef EOPNOTSUPP
529
  ERRNO_CASE(EOPNOTSUPP);
530
# endif
531
#endif
532
533
#ifdef ENOTTY
534
  ERRNO_CASE(ENOTTY);
535
#endif
536
537
#ifdef ENXIO
538
  ERRNO_CASE(ENXIO);
539
#endif
540
541
542
#ifdef EOVERFLOW
543
  ERRNO_CASE(EOVERFLOW);
544
#endif
545
546
#ifdef EPERM
547
  ERRNO_CASE(EPERM);
548
#endif
549
550
#ifdef EPIPE
551
  ERRNO_CASE(EPIPE);
552
#endif
553
554
#ifdef EPROTO
555
  ERRNO_CASE(EPROTO);
556
#endif
557
558
#ifdef EPROTONOSUPPORT
559
  ERRNO_CASE(EPROTONOSUPPORT);
560
#endif
561
562
#ifdef EPROTOTYPE
563
  ERRNO_CASE(EPROTOTYPE);
564
#endif
565
566
#ifdef ERANGE
567
  ERRNO_CASE(ERANGE);
568
#endif
569
570
#ifdef EROFS
571
  ERRNO_CASE(EROFS);
572
#endif
573
574
#ifdef ESPIPE
575
  ERRNO_CASE(ESPIPE);
576
#endif
577
578
#ifdef ESRCH
579
  ERRNO_CASE(ESRCH);
580
#endif
581
582
#ifdef ESTALE
583
  ERRNO_CASE(ESTALE);
584
#endif
585
586
#ifdef ETIME
587
  ERRNO_CASE(ETIME);
588
#endif
589
590
#ifdef ETIMEDOUT
591
  ERRNO_CASE(ETIMEDOUT);
592
#endif
593
594
#ifdef ETXTBSY
595
  ERRNO_CASE(ETXTBSY);
596
#endif
597
598
#ifdef EXDEV
599
  ERRNO_CASE(EXDEV);
600
#endif
601
602
  default: return "";
603
  }
604
}
605
606
493
const char *signo_string(int signo) {
607
#define SIGNO_CASE(e)  case e: return #e;
608
493
  switch (signo) {
609
#ifdef SIGHUP
610
  SIGNO_CASE(SIGHUP);
611
#endif
612
613
#ifdef SIGINT
614
  SIGNO_CASE(SIGINT);
615
#endif
616
617
#ifdef SIGQUIT
618
  SIGNO_CASE(SIGQUIT);
619
#endif
620
621
#ifdef SIGILL
622
  SIGNO_CASE(SIGILL);
623
#endif
624
625
#ifdef SIGTRAP
626
  SIGNO_CASE(SIGTRAP);
627
#endif
628
629
#ifdef SIGABRT
630
  SIGNO_CASE(SIGABRT);
631
#endif
632
633
#ifdef SIGIOT
634
# if SIGABRT != SIGIOT
635
  SIGNO_CASE(SIGIOT);
636
# endif
637
#endif
638
639
#ifdef SIGBUS
640
  SIGNO_CASE(SIGBUS);
641
#endif
642
643
#ifdef SIGFPE
644
  SIGNO_CASE(SIGFPE);
645
#endif
646
647
#ifdef SIGKILL
648
  SIGNO_CASE(SIGKILL);
649
#endif
650
651
#ifdef SIGUSR1
652
  SIGNO_CASE(SIGUSR1);
653
#endif
654
655
#ifdef SIGSEGV
656
  SIGNO_CASE(SIGSEGV);
657
#endif
658
659
#ifdef SIGUSR2
660
  SIGNO_CASE(SIGUSR2);
661
#endif
662
663
#ifdef SIGPIPE
664
  SIGNO_CASE(SIGPIPE);
665
#endif
666
667
#ifdef SIGALRM
668
  SIGNO_CASE(SIGALRM);
669
#endif
670
671
  SIGNO_CASE(SIGTERM);
672
673
#ifdef SIGCHLD
674
  SIGNO_CASE(SIGCHLD);
675
#endif
676
677
#ifdef SIGSTKFLT
678
  SIGNO_CASE(SIGSTKFLT);
679
#endif
680
681
682
#ifdef SIGCONT
683
  SIGNO_CASE(SIGCONT);
684
#endif
685
686
#ifdef SIGSTOP
687
  SIGNO_CASE(SIGSTOP);
688
#endif
689
690
#ifdef SIGTSTP
691
  SIGNO_CASE(SIGTSTP);
692
#endif
693
694
#ifdef SIGBREAK
695
  SIGNO_CASE(SIGBREAK);
696
#endif
697
698
#ifdef SIGTTIN
699
  SIGNO_CASE(SIGTTIN);
700
#endif
701
702
#ifdef SIGTTOU
703
  SIGNO_CASE(SIGTTOU);
704
#endif
705
706
#ifdef SIGURG
707
  SIGNO_CASE(SIGURG);
708
#endif
709
710
#ifdef SIGXCPU
711
  SIGNO_CASE(SIGXCPU);
712
#endif
713
714
#ifdef SIGXFSZ
715
  SIGNO_CASE(SIGXFSZ);
716
#endif
717
718
#ifdef SIGVTALRM
719
  SIGNO_CASE(SIGVTALRM);
720
#endif
721
722
#ifdef SIGPROF
723
  SIGNO_CASE(SIGPROF);
724
#endif
725
726
#ifdef SIGWINCH
727
  SIGNO_CASE(SIGWINCH);
728
#endif
729
730
#ifdef SIGIO
731
  SIGNO_CASE(SIGIO);
732
#endif
733
734
#ifdef SIGPOLL
735
# if SIGPOLL != SIGIO
736
  SIGNO_CASE(SIGPOLL);
737
# endif
738
#endif
739
740
#ifdef SIGLOST
741
# if SIGLOST != SIGABRT
742
  SIGNO_CASE(SIGLOST);
743
# endif
744
#endif
745
746
#ifdef SIGPWR
747
# if SIGPWR != SIGLOST
748
  SIGNO_CASE(SIGPWR);
749
# endif
750
#endif
751
752
#ifdef SIGINFO
753
# if !defined(SIGPWR) || SIGINFO != SIGPWR
754
  SIGNO_CASE(SIGINFO);
755
# endif
756
#endif
757
758
#ifdef SIGSYS
759
  SIGNO_CASE(SIGSYS);
760
#endif
761
762
  default: return "";
763
  }
764
}
765
766
767
1
Local<Value> ErrnoException(Isolate* isolate,
768
                            int errorno,
769
                            const char *syscall,
770
                            const char *msg,
771
                            const char *path) {
772
1
  Environment* env = Environment::GetCurrent(isolate);
773
774
1
  Local<Value> e;
775
1
  Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
776
1
  if (msg == nullptr || msg[0] == '\0') {
777
1
    msg = strerror(errorno);
778
  }
779
1
  Local<String> message = OneByteString(env->isolate(), msg);
780
781
  Local<String> cons =
782
1
      String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
783
1
  cons = String::Concat(cons, message);
784
785
1
  Local<String> path_string;
786
1
  if (path != nullptr) {
787
    // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
788
    path_string = String::NewFromUtf8(env->isolate(), path);
789
  }
790
791
1
  if (path_string.IsEmpty() == false) {
792
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
793
    cons = String::Concat(cons, path_string);
794
    cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
795
  }
796
1
  e = Exception::Error(cons);
797
798
1
  Local<Object> obj = e->ToObject(env->isolate());
799
4
  obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
800
3
  obj->Set(env->code_string(), estring);
801
802
1
  if (path_string.IsEmpty() == false) {
803
    obj->Set(env->path_string(), path_string);
804
  }
805
806
1
  if (syscall != nullptr) {
807
4
    obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
808
  }
809
810
1
  return e;
811
}
812
813
814
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
815
#ifdef _WIN32
816
  if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
817
    return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
818
                          String::NewFromUtf8(isolate, path + 8));
819
  } else if (strncmp(path, "\\\\?\\", 4) == 0) {
820
    return String::NewFromUtf8(isolate, path + 4);
821
  }
822
#endif
823
824
1973
  return String::NewFromUtf8(isolate, path);
825
}
826
827
828
Local<Value> UVException(Isolate* isolate,
829
                         int errorno,
830
                         const char* syscall,
831
                         const char* msg,
832
                         const char* path) {
833
  return UVException(isolate, errorno, syscall, msg, path, nullptr);
834
}
835
836
837
1969
Local<Value> UVException(Isolate* isolate,
838
                         int errorno,
839
                         const char* syscall,
840
                         const char* msg,
841
                         const char* path,
842
                         const char* dest) {
843
1969
  Environment* env = Environment::GetCurrent(isolate);
844
845
1969
  if (!msg || !msg[0])
846
1969
    msg = uv_strerror(errorno);
847
848
1969
  Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
849
1969
  Local<String> js_syscall = OneByteString(isolate, syscall);
850
1969
  Local<String> js_path;
851
1969
  Local<String> js_dest;
852
853
1969
  Local<String> js_msg = js_code;
854
1969
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
855
1969
  js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
856
1969
  js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
857
1969
  js_msg = String::Concat(js_msg, js_syscall);
858
859
1969
  if (path != nullptr) {
860
1963
    js_path = StringFromPath(isolate, path);
861
862
1963
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
863
1963
    js_msg = String::Concat(js_msg, js_path);
864
1963
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
865
  }
866
867
1969
  if (dest != nullptr) {
868
10
    js_dest = StringFromPath(isolate, dest);
869
870
10
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
871
10
    js_msg = String::Concat(js_msg, js_dest);
872
10
    js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
873
  }
874
875
3938
  Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
876
877
  // TODO(piscisaureus) errno should probably go; the user has no way of
878
  // knowing which uv errno value maps to which error.
879
7876
  e->Set(env->errno_string(), Integer::New(isolate, errorno));
880
5907
  e->Set(env->code_string(), js_code);
881
5907
  e->Set(env->syscall_string(), js_syscall);
882
1969
  if (!js_path.IsEmpty())
883
5889
    e->Set(env->path_string(), js_path);
884
1969
  if (!js_dest.IsEmpty())
885
30
    e->Set(env->dest_string(), js_dest);
886
887
1969
  return e;
888
}
889
890
891
// Look up environment variable unless running as setuid root.
892
1565
inline const char* secure_getenv(const char* key) {
893
#ifndef _WIN32
894
1565
  if (getuid() != geteuid() || getgid() != getegid())
895
    return nullptr;
896
#endif
897
1565
  return getenv(key);
898
}
899
900
901
#ifdef _WIN32
902
// Does about the same as strerror(),
903
// but supports all windows error messages
904
static const char *winapi_strerror(const int errorno, bool* must_free) {
905
  char *errmsg = nullptr;
906
907
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
908
      FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
909
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
910
911
  if (errmsg) {
912
    *must_free = true;
913
914
    // Remove trailing newlines
915
    for (int i = strlen(errmsg) - 1;
916
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
917
      errmsg[i] = '\0';
918
    }
919
920
    return errmsg;
921
  } else {
922
    // FormatMessage failed
923
    *must_free = false;
924
    return "Unknown error";
925
  }
926
}
927
928
929
Local<Value> WinapiErrnoException(Isolate* isolate,
930
                                  int errorno,
931
                                  const char* syscall,
932
                                  const char* msg,
933
                                  const char* path) {
934
  Environment* env = Environment::GetCurrent(isolate);
935
  Local<Value> e;
936
  bool must_free = false;
937
  if (!msg || !msg[0]) {
938
    msg = winapi_strerror(errorno, &must_free);
939
  }
940
  Local<String> message = OneByteString(env->isolate(), msg);
941
942
  if (path) {
943
    Local<String> cons1 =
944
        String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
945
    Local<String> cons2 =
946
        String::Concat(cons1, String::NewFromUtf8(isolate, path));
947
    Local<String> cons3 =
948
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
949
    e = Exception::Error(cons3);
950
  } else {
951
    e = Exception::Error(message);
952
  }
953
954
  Local<Object> obj = e->ToObject(env->isolate());
955
  obj->Set(env->errno_string(), Integer::New(isolate, errorno));
956
957
  if (path != nullptr) {
958
    obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
959
  }
960
961
  if (syscall != nullptr) {
962
    obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
963
  }
964
965
  if (must_free)
966
    LocalFree((HLOCAL)msg);
967
968
  return e;
969
}
970
#endif
971
972
973
12153
void* ArrayBufferAllocator::Allocate(size_t size) {
974
12153
  if (zero_fill_field_ || zero_fill_all_buffers)
975
5512
    return calloc(size, 1);
976
  else
977
6641
    return malloc(size);
978
}
979
980
28
static bool DomainHasErrorHandler(const Environment* env,
981
                                  const Local<Object>& domain) {
982
56
  HandleScope scope(env->isolate());
983
984
84
  Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
985
28
  if (!domain_event_listeners_v->IsObject())
986
    return false;
987
988
  Local<Object> domain_event_listeners_o =
989
28
      domain_event_listeners_v.As<Object>();
990
991
  Local<Value> domain_error_listeners_v =
992
56
      domain_event_listeners_o->Get(env->error_string());
993
994
57
  if (domain_error_listeners_v->IsFunction() ||
995
1
      (domain_error_listeners_v->IsArray() &&
996
      domain_error_listeners_v.As<Array>()->Length() > 0))
997
    return true;
998
999
1
  return false;
1000
}
1001
1002
27
static bool DomainsStackHasErrorHandler(const Environment* env) {
1003
54
  HandleScope scope(env->isolate());
1004
1005
27
  if (!env->using_domains())
1006
    return false;
1007
1008
54
  Local<Array> domains_stack_array = env->domains_stack_array().As<Array>();
1009
27
  if (domains_stack_array->Length() == 0)
1010
    return false;
1011
1012
27
  uint32_t domains_stack_length = domains_stack_array->Length();
1013
28
  for (uint32_t i = domains_stack_length; i > 0; --i) {
1014
28
    Local<Value> domain_v = domains_stack_array->Get(i - 1);
1015
28
    if (!domain_v->IsObject())
1016
27
      return false;
1017
1018
28
    Local<Object> domain = domain_v.As<Object>();
1019
28
    if (DomainHasErrorHandler(env, domain))
1020
      return true;
1021
  }
1022
1023
  return false;
1024
}
1025
1026
1027
27
static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
1028
54
  HandleScope scope(isolate);
1029
1030
27
  Environment* env = Environment::GetCurrent(isolate);
1031
27
  Local<Object> process_object = env->process_object();
1032
  Local<String> emitting_top_level_domain_error_key =
1033
27
    env->emitting_top_level_domain_error_string();
1034
  bool isEmittingTopLevelDomainError =
1035
54
      process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
1036
1037
54
  return isEmittingTopLevelDomainError || !DomainsStackHasErrorHandler(env);
1038
}
1039
1040
1041
119
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
1042
119
  Environment* env = Environment::GetCurrent(args);
1043
1044
119
  if (env->using_domains())
1045
    return;
1046
119
  env->set_using_domains(true);
1047
1048
238
  HandleScope scope(env->isolate());
1049
119
  Local<Object> process_object = env->process_object();
1050
1051
119
  Local<String> tick_callback_function_key = env->tick_domain_cb_string();
1052
  Local<Function> tick_callback_function =
1053
238
      process_object->Get(tick_callback_function_key).As<Function>();
1054
1055
119
  if (!tick_callback_function->IsFunction()) {
1056
    fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
1057
    ABORT();
1058
  }
1059
1060
357
  process_object->Set(env->tick_callback_string(), tick_callback_function);
1061
119
  env->set_tick_callback_function(tick_callback_function);
1062
1063
119
  CHECK(args[0]->IsArray());
1064
238
  env->set_domain_array(args[0].As<Array>());
1065
1066
119
  CHECK(args[1]->IsArray());
1067
238
  env->set_domains_stack_array(args[1].As<Array>());
1068
1069
  // Do a little housekeeping.
1070
357
  env->process_object()->Delete(
1071
      env->context(),
1072
833
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
1073
1074
238
  uint32_t* const fields = env->domain_flag()->fields();
1075
119
  uint32_t const fields_count = env->domain_flag()->fields_count();
1076
1077
  Local<ArrayBuffer> array_buffer =
1078
119
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1079
1080
357
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1081
}
1082
1083
33195
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
1084
33195
  args.GetIsolate()->RunMicrotasks();
1085
33195
}
1086
1087
1088
1563
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
1089
1563
  Environment* env = Environment::GetCurrent(args);
1090
1091
1563
  CHECK(args[0]->IsFunction());
1092
1093
3126
  env->set_push_values_to_array_function(args[0].As<Function>());
1094
4689
  env->process_object()->Delete(
1095
      env->context(),
1096
9378
      FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
1097
1563
}
1098
1099
1100
1563
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
1101
1563
  Environment* env = Environment::GetCurrent(args);
1102
1103
1563
  CHECK(args[0]->IsFunction());
1104
1563
  CHECK(args[1]->IsObject());
1105
1106
3126
  env->set_tick_callback_function(args[0].As<Function>());
1107
1108
3126
  env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
1109
1110
  // Do a little housekeeping.
1111
4689
  env->process_object()->Delete(
1112
      env->context(),
1113
10941
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust();
1114
1115
  // Values use to cross communicate with processNextTick.
1116
3126
  uint32_t* const fields = env->tick_info()->fields();
1117
1563
  uint32_t const fields_count = env->tick_info()->fields_count();
1118
1119
  Local<ArrayBuffer> array_buffer =
1120
1563
      ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1121
1122
4689
  args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1123
1563
}
1124
1125
61
void PromiseRejectCallback(PromiseRejectMessage message) {
1126
61
  Local<Promise> promise = message.GetPromise();
1127
61
  Isolate* isolate = promise->GetIsolate();
1128
61
  Local<Value> value = message.GetValue();
1129
61
  Local<Integer> event = Integer::New(isolate, message.GetEvent());
1130
1131
61
  Environment* env = Environment::GetCurrent(isolate);
1132
61
  Local<Function> callback = env->promise_reject_function();
1133
1134
61
  if (value.IsEmpty())
1135
46
    value = Undefined(isolate);
1136
1137
183
  Local<Value> args[] = { event, promise, value };
1138
61
  Local<Object> process = env->process_object();
1139
1140
122
  callback->Call(process, arraysize(args), args);
1141
61
}
1142
1143
1563
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
1144
1563
  Environment* env = Environment::GetCurrent(args);
1145
1563
  Isolate* isolate = env->isolate();
1146
1147
1563
  CHECK(args[0]->IsFunction());
1148
1149
1563
  isolate->SetPromiseRejectCallback(PromiseRejectCallback);
1150
3126
  env->set_promise_reject_function(args[0].As<Function>());
1151
1152
4689
  env->process_object()->Delete(
1153
      env->context(),
1154
10941
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupPromises")).FromJust();
1155
1563
}
1156
1157
1158
7890
Local<Value> MakeCallback(Environment* env,
1159
                          Local<Value> recv,
1160
                          const Local<Function> callback,
1161
                          int argc,
1162
                          Local<Value> argv[]) {
1163
  // If you hit this assertion, you forgot to enter the v8::Context first.
1164
23670
  CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1165
1166
7890
  Local<Function> pre_fn = env->async_hooks_pre_function();
1167
7890
  Local<Function> post_fn = env->async_hooks_post_function();
1168
15780
  Local<Object> object, domain;
1169
7890
  bool ran_init_callback = false;
1170
7890
  bool has_domain = false;
1171
1172
15765
  Environment::AsyncCallbackScope callback_scope(env);
1173
1174
  // TODO(trevnorris): Adding "_asyncQueue" to the "this" in the init callback
1175
  // is a horrible way to detect usage. Rethink how detection should happen.
1176
7890
  if (recv->IsObject()) {
1177
7890
    object = recv.As<Object>();
1178
15780
    Local<Value> async_queue_v = object->Get(env->async_queue_string());
1179
7890
    if (async_queue_v->IsObject())
1180
      ran_init_callback = true;
1181
  }
1182
1183
7890
  if (env->using_domains()) {
1184
1384
    CHECK(recv->IsObject());
1185
2768
    Local<Value> domain_v = object->Get(env->domain_string());
1186
1384
    has_domain = domain_v->IsObject();
1187
1384
    if (has_domain) {
1188
13
      domain = domain_v.As<Object>();
1189
39
      if (domain->Get(env->disposed_string())->IsTrue())
1190
        return Undefined(env->isolate());
1191
    }
1192
  }
1193
1194
7890
  if (has_domain) {
1195
26
    Local<Value> enter_v = domain->Get(env->enter_string());
1196
13
    if (enter_v->IsFunction()) {
1197
39
      if (enter_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1198
        FatalError("node::MakeCallback",
1199
                   "domain enter callback threw, please report this");
1200
      }
1201
    }
1202
  }
1203
1204
7890
  if (ran_init_callback && !pre_fn.IsEmpty()) {
1205
    TryCatch try_catch(env->isolate());
1206
    MaybeLocal<Value> ar = pre_fn->Call(env->context(), object, 0, nullptr);
1207
    if (ar.IsEmpty()) {
1208
      ClearFatalExceptionHandlers(env);
1209
      FatalException(env->isolate(), try_catch);
1210
      return Local<Value>();
1211
    }
1212
  }
1213
1214
7890
  Local<Value> ret = callback->Call(recv, argc, argv);
1215
1216
7884
  if (ran_init_callback && !post_fn.IsEmpty()) {
1217
    Local<Value> did_throw = Boolean::New(env->isolate(), ret.IsEmpty());
1218
    // Currently there's no way to retrieve an uid from node::MakeCallback().
1219
    // This needs to be fixed.
1220
    Local<Value> vals[] =
1221
        { Undefined(env->isolate()).As<Value>(), did_throw };
1222
    TryCatch try_catch(env->isolate());
1223
    MaybeLocal<Value> ar =
1224
        post_fn->Call(env->context(), object, arraysize(vals), vals);
1225
    if (ar.IsEmpty()) {
1226
      ClearFatalExceptionHandlers(env);
1227
      FatalException(env->isolate(), try_catch);
1228
      return Local<Value>();
1229
    }
1230
  }
1231
1232
7884
  if (ret.IsEmpty()) {
1233
    // NOTE: For backwards compatibility with public API we return Undefined()
1234
    // if the top level call threw.
1235
1023
    return callback_scope.in_makecallback() ?
1236
2042
        ret : Undefined(env->isolate()).As<Value>();
1237
  }
1238
1239
6861
  if (has_domain) {
1240
20
    Local<Value> exit_v = domain->Get(env->exit_string());
1241
10
    if (exit_v->IsFunction()) {
1242
30
      if (exit_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1243
        FatalError("node::MakeCallback",
1244
                   "domain exit callback threw, please report this");
1245
      }
1246
    }
1247
  }
1248
1249
6861
  if (callback_scope.in_makecallback()) {
1250
22
    return ret;
1251
  }
1252
1253
6839
  Environment::TickInfo* tick_info = env->tick_info();
1254
1255
6839
  if (tick_info->length() == 0) {
1256
6384
    env->isolate()->RunMicrotasks();
1257
  }
1258
1259
6839
  Local<Object> process = env->process_object();
1260
1261
6839
  if (tick_info->length() == 0) {
1262
    tick_info->set_index(0);
1263
  }
1264
1265
20508
  if (env->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1266
3
    return Undefined(env->isolate());
1267
  }
1268
1269
6829
  return ret;
1270
}
1271
1272
1273
7868
Local<Value> MakeCallback(Environment* env,
1274
                           Local<Object> recv,
1275
                           Local<String> symbol,
1276
                           int argc,
1277
                           Local<Value> argv[]) {
1278
7868
  Local<Value> cb_v = recv->Get(symbol);
1279
7868
  CHECK(cb_v->IsFunction());
1280
15736
  return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
1281
}
1282
1283
1284
2780
Local<Value> MakeCallback(Environment* env,
1285
                           Local<Object> recv,
1286
                           const char* method,
1287
                           int argc,
1288
                           Local<Value> argv[]) {
1289
2780
  Local<String> method_string = OneByteString(env->isolate(), method);
1290
2780
  return MakeCallback(env, recv, method_string, argc, argv);
1291
}
1292
1293
1294
5
Local<Value> MakeCallback(Isolate* isolate,
1295
                           Local<Object> recv,
1296
                           const char* method,
1297
                           int argc,
1298
                           Local<Value> argv[]) {
1299
10
  EscapableHandleScope handle_scope(isolate);
1300
5
  Local<Context> context = recv->CreationContext();
1301
5
  Environment* env = Environment::GetCurrent(context);
1302
10
  Context::Scope context_scope(context);
1303
  return handle_scope.Escape(
1304
20
      Local<Value>::New(isolate, MakeCallback(env, recv, method, argc, argv)));
1305
}
1306
1307
1308
4
Local<Value> MakeCallback(Isolate* isolate,
1309
                           Local<Object> recv,
1310
                           Local<String> symbol,
1311
                           int argc,
1312
                           Local<Value> argv[]) {
1313
8
  EscapableHandleScope handle_scope(isolate);
1314
4
  Local<Context> context = recv->CreationContext();
1315
4
  Environment* env = Environment::GetCurrent(context);
1316
8
  Context::Scope context_scope(context);
1317
  return handle_scope.Escape(
1318
16
      Local<Value>::New(isolate, MakeCallback(env, recv, symbol, argc, argv)));
1319
}
1320
1321
1322
22
Local<Value> MakeCallback(Isolate* isolate,
1323
                           Local<Object> recv,
1324
                           Local<Function> callback,
1325
                           int argc,
1326
                           Local<Value> argv[]) {
1327
44
  EscapableHandleScope handle_scope(isolate);
1328
22
  Local<Context> context = recv->CreationContext();
1329
22
  Environment* env = Environment::GetCurrent(context);
1330
44
  Context::Scope context_scope(context);
1331
  return handle_scope.Escape(Local<Value>::New(
1332
        isolate,
1333
88
        MakeCallback(env, recv.As<Value>(), callback, argc, argv)));
1334
}
1335
1336
1337
54090
enum encoding ParseEncoding(const char* encoding,
1338
                            enum encoding default_encoding) {
1339
54090
  switch (encoding[0]) {
1340
    case 'u':
1341
      // utf8, utf16le
1342
4476
      if (encoding[1] == 't' && encoding[2] == 'f') {
1343
        // Skip `-`
1344
4287
        encoding += encoding[3] == '-' ? 4 : 3;
1345
4287
        if (encoding[0] == '8' && encoding[1] == '\0')
1346
          return UTF8;
1347
        if (strncmp(encoding, "16le", 4) == 0)
1348
          return UCS2;
1349
1350
      // ucs2
1351
189
      } else if (encoding[1] == 'c' && encoding[2] == 's') {
1352
189
        encoding += encoding[3] == '-' ? 4 : 3;
1353
189
        if (encoding[0] == '2' && encoding[1] == '\0')
1354
          return UCS2;
1355
      }
1356
      break;
1357
    case 'l':
1358
      // latin1
1359
46775
      if (encoding[1] == 'a') {
1360
46773
        if (strncmp(encoding + 2, "tin1", 4) == 0)
1361
          return LATIN1;
1362
      }
1363
      break;
1364
    case 'b':
1365
      // binary
1366
417
      if (encoding[1] == 'i') {
1367
30
        if (strncmp(encoding + 2, "nary", 4) == 0)
1368
          return LATIN1;
1369
1370
      // buffer
1371
387
      } else if (encoding[1] == 'u') {
1372
366
        if (strncmp(encoding + 2, "ffer", 4) == 0)
1373
          return BUFFER;
1374
      }
1375
      break;
1376
    case '\0':
1377
      return default_encoding;
1378
    default:
1379
      break;
1380
  }
1381
1382
2444
  if (StringEqualNoCase(encoding, "utf8")) {
1383
    return UTF8;
1384
2444
  } else if (StringEqualNoCase(encoding, "utf-8")) {
1385
    return UTF8;
1386
2443
  } else if (StringEqualNoCase(encoding, "ascii")) {
1387
    return ASCII;
1388
2432
  } else if (StringEqualNoCase(encoding, "base64")) {
1389
    return BASE64;
1390
2411
  } else if (StringEqualNoCase(encoding, "ucs2")) {
1391
    return UCS2;
1392
2411
  } else if (StringEqualNoCase(encoding, "ucs-2")) {
1393
    return UCS2;
1394
2411
  } else if (StringEqualNoCase(encoding, "utf16le")) {
1395
    return UCS2;
1396
2411
  } else if (StringEqualNoCase(encoding, "utf-16le")) {
1397
    return UCS2;
1398
2411
  } else if (StringEqualNoCase(encoding, "latin1")) {
1399
    return LATIN1;
1400
2411
  } else if (StringEqualNoCase(encoding, "binary")) {
1401
    return LATIN1;  // BINARY is a deprecated alias of LATIN1.
1402
2411
  } else if (StringEqualNoCase(encoding, "buffer")) {
1403
    return BUFFER;
1404
2411
  } else if (StringEqualNoCase(encoding, "hex")) {
1405
    return HEX;
1406
  } else {
1407
2
    return default_encoding;
1408
  }
1409
}
1410
1411
1412
59486
enum encoding ParseEncoding(Isolate* isolate,
1413
                            Local<Value> encoding_v,
1414
                            enum encoding default_encoding) {
1415
118972
  if (!encoding_v->IsString())
1416
    return default_encoding;
1417
1418
54090
  node::Utf8Value encoding(isolate, encoding_v);
1419
1420
54090
  return ParseEncoding(*encoding, default_encoding);
1421
}
1422
1423
191
Local<Value> Encode(Isolate* isolate,
1424
                    const char* buf,
1425
                    size_t len,
1426
                    enum encoding encoding) {
1427
191
  CHECK_NE(encoding, UCS2);
1428
191
  return StringBytes::Encode(isolate, buf, len, encoding);
1429
}
1430
1431
Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1432
  return StringBytes::Encode(isolate, buf, len);
1433
}
1434
1435
// Returns -1 if the handle was not valid for decoding
1436
ssize_t DecodeBytes(Isolate* isolate,
1437
                    Local<Value> val,
1438
                    enum encoding encoding) {
1439
  HandleScope scope(isolate);
1440
1441
  return StringBytes::Size(isolate, val, encoding);
1442
}
1443
1444
// Returns number of bytes written.
1445
ssize_t DecodeWrite(Isolate* isolate,
1446
                    char* buf,
1447
                    size_t buflen,
1448
                    Local<Value> val,
1449
                    enum encoding encoding) {
1450
  return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1451
}
1452
1453
239
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
1454
239
  if (!er.IsEmpty() && er->IsObject()) {
1455
239
    Local<Object> err_obj = er.As<Object>();
1456
    auto maybe_value =
1457
478
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
1458
239
    Local<Value> decorated;
1459
239
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
1460
  }
1461
  return false;
1462
}
1463
1464
239
void AppendExceptionLine(Environment* env,
1465
                         Local<Value> er,
1466
                         Local<Message> message,
1467
                         enum ErrorHandlingMode mode) {
1468
239
  if (message.IsEmpty())
1469
26
    return;
1470
1471
452
  HandleScope scope(env->isolate());
1472
239
  Local<Object> err_obj;
1473
239
  if (!er.IsEmpty() && er->IsObject()) {
1474
239
    err_obj = er.As<Object>();
1475
1476
239
    auto context = env->context();
1477
239
    auto processed_private_symbol = env->processed_private_symbol();
1478
    // Do it only once per message
1479
478
    if (err_obj->HasPrivate(context, processed_private_symbol).FromJust())
1480
15
      return;
1481
    err_obj->SetPrivate(
1482
        context,
1483
        processed_private_symbol,
1484
672
        True(env->isolate()));
1485
  }
1486
1487
  // Print (filename):(line number): (message).
1488
437
  node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1489
224
  const char* filename_string = *filename;
1490
224
  int linenum = message->GetLineNumber();
1491
  // Print line of source code.
1492
661
  node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1493
224
  const char* sourceline_string = *sourceline;
1494
1495
  // Because of how node modules work, all scripts are wrapped with a
1496
  // "function (module, exports, __filename, ...) {"
1497
  // to provide script local variables.
1498
  //
1499
  // When reporting errors on the first line of a script, this wrapper
1500
  // function is leaked to the user. There used to be a hack here to
1501
  // truncate off the first 62 characters, but it caused numerous other
1502
  // problems when vm.runIn*Context() methods were used for non-module
1503
  // code.
1504
  //
1505
  // If we ever decide to re-instate such a hack, the following steps
1506
  // must be taken:
1507
  //
1508
  // 1. Pass a flag around to say "this code was wrapped"
1509
  // 2. Update the stack frame output so that it is also correct.
1510
  //
1511
  // It would probably be simpler to add a line rather than add some
1512
  // number of characters to the first line, since V8 truncates the
1513
  // sourceline to 78 characters, and we end up not providing very much
1514
  // useful debugging info to the user if we remove 62 characters.
1515
1516
672
  int start = message->GetStartColumn(env->context()).FromMaybe(0);
1517
672
  int end = message->GetEndColumn(env->context()).FromMaybe(0);
1518
1519
  char arrow[1024];
1520
224
  int max_off = sizeof(arrow) - 2;
1521
1522
  int off = snprintf(arrow,
1523
                     sizeof(arrow),
1524
                     "%s:%i\n%s\n",
1525
                     filename_string,
1526
                     linenum,
1527
224
                     sourceline_string);
1528
224
  CHECK_GE(off, 0);
1529
224
  if (off > max_off) {
1530
20
    off = max_off;
1531
  }
1532
1533
  // Print wavy underline (GetUnderline is deprecated).
1534
2648
  for (int i = 0; i < start; i++) {
1535
1232
    if (sourceline_string[i] == '\0' || off >= max_off) {
1536
      break;
1537
    }
1538
1212
    CHECK_LT(off, max_off);
1539
1212
    arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1540
  }
1541
942
  for (int i = start; i < end; i++) {
1542
382
    if (sourceline_string[i] == '\0' || off >= max_off) {
1543
      break;
1544
    }
1545
359
    CHECK_LT(off, max_off);
1546
359
    arrow[off++] = '^';
1547
  }
1548
224
  CHECK_LE(off, max_off);
1549
224
  arrow[off] = '\n';
1550
224
  arrow[off + 1] = '\0';
1551
1552
224
  Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1553
1554
224
  const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
1555
  // If allocating arrow_str failed, print it out. There's not much else to do.
1556
  // If it's not an error, but something needs to be printed out because
1557
  // it's a fatal exception, also print it out from here.
1558
  // Otherwise, the arrow property will be attached to the object and handled
1559
  // by the caller.
1560
224
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
1561
11
    if (env->printed_error())
1562
11
      return;
1563
11
    env->set_printed_error(true);
1564
1565
11
    uv_tty_reset_mode();
1566
11
    PrintErrorString("\n%s", arrow);
1567
11
    return;
1568
  }
1569
1570
1065
  CHECK(err_obj->SetPrivate(
1571
            env->context(),
1572
            env->arrow_message_private_symbol(),
1573
            arrow_str).FromMaybe(false));
1574
}
1575
1576
1577
52
static void ReportException(Environment* env,
1578
                            Local<Value> er,
1579
                            Local<Message> message) {
1580
104
  HandleScope scope(env->isolate());
1581
1582
52
  AppendExceptionLine(env, er, message, FATAL_ERROR);
1583
1584
52
  Local<Value> trace_value;
1585
52
  Local<Value> arrow;
1586
52
  const bool decorated = IsExceptionDecorated(env, er);
1587
1588
156
  if (er->IsUndefined() || er->IsNull()) {
1589
    trace_value = Undefined(env->isolate());
1590
  } else {
1591
52
    Local<Object> err_obj = er->ToObject(env->isolate());
1592
1593
104
    trace_value = err_obj->Get(env->stack_string());
1594
    arrow =
1595
52
        err_obj->GetPrivate(
1596
            env->context(),
1597
104
            env->arrow_message_private_symbol()).ToLocalChecked();
1598
  }
1599
1600
104
  node::Utf8Value trace(env->isolate(), trace_value);
1601
1602
  // range errors have a trace member set to undefined
1603
104
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1604
102
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1605
25
      PrintErrorString("%s\n", *trace);
1606
    } else {
1607
52
      node::Utf8Value arrow_string(env->isolate(), arrow);
1608
26
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1609
    }
1610
  } else {
1611
    // this really only happens for RangeErrors, since they're the only
1612
    // kind that won't have all this info in the trace, or when non-Error
1613
    // objects are thrown manually.
1614
1
    Local<Value> message;
1615
1
    Local<Value> name;
1616
1617
1
    if (er->IsObject()) {
1618
1
      Local<Object> err_obj = er.As<Object>();
1619
2
      message = err_obj->Get(env->message_string());
1620
2
      name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1621
    }
1622
1623
3
    if (message.IsEmpty() ||
1624
2
        message->IsUndefined() ||
1625
1
        name.IsEmpty() ||
1626
        name->IsUndefined()) {
1627
      // Not an error object. Just print as-is.
1628
2
      String::Utf8Value message(er);
1629
1630
1
      PrintErrorString("%s\n", *message ? *message :
1631
1
                                          "<toString() threw exception>");
1632
    } else {
1633
      node::Utf8Value name_string(env->isolate(), name);
1634
      node::Utf8Value message_string(env->isolate(), message);
1635
1636
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1637
        PrintErrorString("%s: %s\n", *name_string, *message_string);
1638
      } else {
1639
        node::Utf8Value arrow_string(env->isolate(), arrow);
1640
        PrintErrorString("%s\n%s: %s\n",
1641
                         *arrow_string,
1642
                         *name_string,
1643
                         *message_string);
1644
      }
1645
    }
1646
  }
1647
1648
52
  fflush(stderr);
1649
52
}
1650
1651
1652
2
static void ReportException(Environment* env, const TryCatch& try_catch) {
1653
2
  ReportException(env, try_catch.Exception(), try_catch.Message());
1654
2
}
1655
1656
1657
// Executes a str within the current v8 context.
1658
1563
static Local<Value> ExecuteString(Environment* env,
1659
                                  Local<String> source,
1660
                                  Local<String> filename) {
1661
3126
  EscapableHandleScope scope(env->isolate());
1662
3126
  TryCatch try_catch(env->isolate());
1663
1664
  // try_catch must be nonverbose to disable FatalException() handler,
1665
  // we will handle exceptions ourself.
1666
1563
  try_catch.SetVerbose(false);
1667
1668
4689
  ScriptOrigin origin(filename);
1669
  MaybeLocal<v8::Script> script =
1670
1563
      v8::Script::Compile(env->context(), source, &origin);
1671
1563
  if (script.IsEmpty()) {
1672
    ReportException(env, try_catch);
1673
    exit(3);
1674
  }
1675
1676
1563
  Local<Value> result = script.ToLocalChecked()->Run();
1677
1563
  if (result.IsEmpty()) {
1678
    ReportException(env, try_catch);
1679
    exit(4);
1680
  }
1681
1682
3126
  return scope.Escape(result);
1683
}
1684
1685
1686
1
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1687
1
  Environment* env = Environment::GetCurrent(args);
1688
1689
1
  Local<Array> ary = Array::New(args.GetIsolate());
1690
1
  Local<Context> ctx = env->context();
1691
1
  Local<Function> fn = env->push_values_to_array_function();
1692
17
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1693
1
  size_t idx = 0;
1694
1695
15
  for (auto w : *env->req_wrap_queue()) {
1696
24
    if (w->persistent().IsEmpty())
1697
      continue;
1698
36
    argv[idx] = w->object();
1699
12
    if (++idx >= arraysize(argv)) {
1700
3
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1701
1
      idx = 0;
1702
    }
1703
  }
1704
1705
1
  if (idx > 0) {
1706
3
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1707
  }
1708
1709
2
  args.GetReturnValue().Set(ary);
1710
1
}
1711
1712
1713
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1714
// implemented here for consistency with GetActiveRequests().
1715
1
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1716
1
  Environment* env = Environment::GetCurrent(args);
1717
1718
1
  Local<Array> ary = Array::New(env->isolate());
1719
1
  Local<Context> ctx = env->context();
1720
1
  Local<Function> fn = env->push_values_to_array_function();
1721
17
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1722
1
  size_t idx = 0;
1723
1724
1
  Local<String> owner_sym = env->owner_string();
1725
1726
20
  for (auto w : *env->handle_wrap_queue()) {
1727
34
    if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
1728
      continue;
1729
34
    Local<Object> object = w->object();
1730
17
    Local<Value> owner = object->Get(owner_sym);
1731
34
    if (owner->IsUndefined())
1732
      owner = object;
1733
17
    argv[idx] = owner;
1734
17
    if (++idx >= arraysize(argv)) {
1735
6
      fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1736
2
      idx = 0;
1737
    }
1738
  }
1739
1
  if (idx > 0) {
1740
3
    fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1741
  }
1742
1743
2
  args.GetReturnValue().Set(ary);
1744
1
}
1745
1746
1747
NO_RETURN void Abort() {
1748
  DumpBacktrace(stderr);
1749
  fflush(stderr);
1750
  ABORT_NO_BACKTRACE();
1751
}
1752
1753
1754
NO_RETURN void Assert(const char* const (*args)[4]) {
1755
  auto filename = (*args)[0];
1756
  auto linenum = (*args)[1];
1757
  auto message = (*args)[2];
1758
  auto function = (*args)[3];
1759
1760
  char exepath[256];
1761
  size_t exepath_size = sizeof(exepath);
1762
  if (uv_exepath(exepath, &exepath_size))
1763
    snprintf(exepath, sizeof(exepath), "node");
1764
1765
  char pid[12] = {0};
1766
#ifndef _WIN32
1767
  snprintf(pid, sizeof(pid), "[%u]", getpid());
1768
#endif
1769
1770
  fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
1771
          exepath, pid, filename, linenum,
1772
          function, *function ? ":" : "", message);
1773
  fflush(stderr);
1774
1775
  Abort();
1776
}
1777
1778
1779
static void Abort(const FunctionCallbackInfo<Value>& args) {
1780
  Abort();
1781
}
1782
1783
1784
20
static void Chdir(const FunctionCallbackInfo<Value>& args) {
1785
20
  Environment* env = Environment::GetCurrent(args);
1786
1787
76
  if (args.Length() != 1 || !args[0]->IsString()) {
1788
3
    return env->ThrowTypeError("Bad argument.");
1789
  }
1790
1791
51
  node::Utf8Value path(args.GetIsolate(), args[0]);
1792
17
  int err = uv_chdir(*path);
1793
17
  if (err) {
1794
    return env->ThrowUVException(err, "uv_chdir");
1795
  }
1796
}
1797
1798
1799
1882
static void Cwd(const FunctionCallbackInfo<Value>& args) {
1800
1882
  Environment* env = Environment::GetCurrent(args);
1801
#ifdef _WIN32
1802
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1803
  char buf[MAX_PATH * 4];
1804
#else
1805
  char buf[PATH_MAX];
1806
#endif
1807
1808
1882
  size_t cwd_len = sizeof(buf);
1809
1882
  int err = uv_cwd(buf, &cwd_len);
1810
1882
  if (err) {
1811
4
    return env->ThrowUVException(err, "uv_cwd");
1812
  }
1813
1814
  Local<String> cwd = String::NewFromUtf8(env->isolate(),
1815
                                          buf,
1816
                                          String::kNormalString,
1817
1878
                                          cwd_len);
1818
3756
  args.GetReturnValue().Set(cwd);
1819
}
1820
1821
1822
102
static void Umask(const FunctionCallbackInfo<Value>& args) {
1823
102
  Environment* env = Environment::GetCurrent(args);
1824
  uint32_t old;
1825
1826
210
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1827
99
    old = umask(0);
1828
99
    umask(static_cast<mode_t>(old));
1829
8
  } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1830
    return env->ThrowTypeError("argument must be an integer or octal string.");
1831
  } else {
1832
    int oct;
1833
3
    if (args[0]->IsInt32()) {
1834
2
      oct = args[0]->Uint32Value();
1835
    } else {
1836
1
      oct = 0;
1837
2
      node::Utf8Value str(env->isolate(), args[0]);
1838
1839
      // Parse the octal string.
1840
5
      for (size_t i = 0; i < str.length(); i++) {
1841
4
        char c = (*str)[i];
1842
4
        if (c > '7' || c < '0') {
1843
          return env->ThrowTypeError("invalid octal string");
1844
        }
1845
4
        oct *= 8;
1846
4
        oct += c - '0';
1847
      }
1848
    }
1849
3
    old = umask(static_cast<mode_t>(oct));
1850
  }
1851
1852
102
  args.GetReturnValue().Set(old);
1853
}
1854
1855
1856
#if defined(__POSIX__) && !defined(__ANDROID__)
1857
1858
static const uid_t uid_not_found = static_cast<uid_t>(-1);
1859
static const gid_t gid_not_found = static_cast<gid_t>(-1);
1860
1861
1862
static uid_t uid_by_name(const char* name) {
1863
  struct passwd pwd;
1864
  struct passwd* pp;
1865
  char buf[8192];
1866
1867
  errno = 0;
1868
  pp = nullptr;
1869
1870
  if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1871
    return pp->pw_uid;
1872
  }
1873
1874
  return uid_not_found;
1875
}
1876
1877
1878
static char* name_by_uid(uid_t uid) {
1879
  struct passwd pwd;
1880
  struct passwd* pp;
1881
  char buf[8192];
1882
  int rc;
1883
1884
  errno = 0;
1885
  pp = nullptr;
1886
1887
  if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1888
      pp != nullptr) {
1889
    return strdup(pp->pw_name);
1890
  }
1891
1892
  if (rc == 0) {
1893
    errno = ENOENT;
1894
  }
1895
1896
  return nullptr;
1897
}
1898
1899
1900
static gid_t gid_by_name(const char* name) {
1901
  struct group pwd;
1902
  struct group* pp;
1903
  char buf[8192];
1904
1905
  errno = 0;
1906
  pp = nullptr;
1907
1908
  if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1909
    return pp->gr_gid;
1910
  }
1911
1912
  return gid_not_found;
1913
}
1914
1915
1916
#if 0  // For future use.
1917
static const char* name_by_gid(gid_t gid) {
1918
  struct group pwd;
1919
  struct group* pp;
1920
  char buf[8192];
1921
  int rc;
1922
1923
  errno = 0;
1924
  pp = nullptr;
1925
1926
  if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1927
      pp != nullptr) {
1928
    return strdup(pp->gr_name);
1929
  }
1930
1931
  if (rc == 0) {
1932
    errno = ENOENT;
1933
  }
1934
1935
  return nullptr;
1936
}
1937
#endif
1938
1939
1940
static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1941
  if (value->IsUint32()) {
1942
    return static_cast<uid_t>(value->Uint32Value());
1943
  } else {
1944
    node::Utf8Value name(isolate, value);
1945
    return uid_by_name(*name);
1946
  }
1947
}
1948
1949
1950
static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1951
  if (value->IsUint32()) {
1952
    return static_cast<gid_t>(value->Uint32Value());
1953
  } else {
1954
    node::Utf8Value name(isolate, value);
1955
    return gid_by_name(*name);
1956
  }
1957
}
1958
1959
16
static void GetUid(const FunctionCallbackInfo<Value>& args) {
1960
  // uid_t is an uint32_t on all supported platforms.
1961
48
  args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1962
16
}
1963
1964
1965
5
static void GetGid(const FunctionCallbackInfo<Value>& args) {
1966
  // gid_t is an uint32_t on all supported platforms.
1967
15
  args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1968
5
}
1969
1970
1971
static void GetEUid(const FunctionCallbackInfo<Value>& args) {
1972
  // uid_t is an uint32_t on all supported platforms.
1973
  args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
1974
}
1975
1976
1977
static void GetEGid(const FunctionCallbackInfo<Value>& args) {
1978
  // gid_t is an uint32_t on all supported platforms.
1979
  args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
1980
}
1981
1982
1983
static void SetGid(const FunctionCallbackInfo<Value>& args) {
1984
  Environment* env = Environment::GetCurrent(args);
1985
1986
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1987
    return env->ThrowTypeError("setgid argument must be a number or a string");
1988
  }
1989
1990
  gid_t gid = gid_by_name(env->isolate(), args[0]);
1991
1992
  if (gid == gid_not_found) {
1993
    return env->ThrowError("setgid group id does not exist");
1994
  }
1995
1996
  if (setgid(gid)) {
1997
    return env->ThrowErrnoException(errno, "setgid");
1998
  }
1999
}
2000
2001
2002
static void SetEGid(const FunctionCallbackInfo<Value>& args) {
2003
  Environment* env = Environment::GetCurrent(args);
2004
2005
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2006
    return env->ThrowTypeError("setegid argument must be a number or string");
2007
  }
2008
2009
  gid_t gid = gid_by_name(env->isolate(), args[0]);
2010
2011
  if (gid == gid_not_found) {
2012
    return env->ThrowError("setegid group id does not exist");
2013
  }
2014
2015
  if (setegid(gid)) {
2016
    return env->ThrowErrnoException(errno, "setegid");
2017
  }
2018
}
2019
2020
2021
static void SetUid(const FunctionCallbackInfo<Value>& args) {
2022
  Environment* env = Environment::GetCurrent(args);
2023
2024
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2025
    return env->ThrowTypeError("setuid argument must be a number or a string");
2026
  }
2027
2028
  uid_t uid = uid_by_name(env->isolate(), args[0]);
2029
2030
  if (uid == uid_not_found) {
2031
    return env->ThrowError("setuid user id does not exist");
2032
  }
2033
2034
  if (setuid(uid)) {
2035
    return env->ThrowErrnoException(errno, "setuid");
2036
  }
2037
}
2038
2039
2040
static void SetEUid(const FunctionCallbackInfo<Value>& args) {
2041
  Environment* env = Environment::GetCurrent(args);
2042
2043
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2044
    return env->ThrowTypeError("seteuid argument must be a number or string");
2045
  }
2046
2047
  uid_t uid = uid_by_name(env->isolate(), args[0]);
2048
2049
  if (uid == uid_not_found) {
2050
    return env->ThrowError("seteuid user id does not exist");
2051
  }
2052
2053
  if (seteuid(uid)) {
2054
    return env->ThrowErrnoException(errno, "seteuid");
2055
  }
2056
}
2057
2058
2059
1
static void GetGroups(const FunctionCallbackInfo<Value>& args) {
2060
1
  Environment* env = Environment::GetCurrent(args);
2061
2062
1
  int ngroups = getgroups(0, nullptr);
2063
2064
1
  if (ngroups == -1) {
2065
    return env->ThrowErrnoException(errno, "getgroups");
2066
  }
2067
2068
1
  gid_t* groups = new gid_t[ngroups];
2069
2070
1
  ngroups = getgroups(ngroups, groups);
2071
2072
1
  if (ngroups == -1) {
2073
    delete[] groups;
2074
    return env->ThrowErrnoException(errno, "getgroups");
2075
  }
2076
2077
1
  Local<Array> groups_list = Array::New(env->isolate(), ngroups);
2078
1
  bool seen_egid = false;
2079
1
  gid_t egid = getegid();
2080
2081
2
  for (int i = 0; i < ngroups; i++) {
2082
2
    groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
2083
1
    if (groups[i] == egid)
2084
1
      seen_egid = true;
2085
  }
2086
2087
1
  delete[] groups;
2088
2089
1
  if (seen_egid == false) {
2090
    groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
2091
  }
2092
2093
1
  args.GetReturnValue().Set(groups_list);
2094
}
2095
2096
2097
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
2098
  Environment* env = Environment::GetCurrent(args);
2099
2100
  if (!args[0]->IsArray()) {
2101
    return env->ThrowTypeError("argument 1 must be an array");
2102
  }
2103
2104
  Local<Array> groups_list = args[0].As<Array>();
2105
  size_t size = groups_list->Length();
2106
  gid_t* groups = new gid_t[size];
2107
2108
  for (size_t i = 0; i < size; i++) {
2109
    gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
2110
2111
    if (gid == gid_not_found) {
2112
      delete[] groups;
2113
      return env->ThrowError("group name not found");
2114
    }
2115
2116
    groups[i] = gid;
2117
  }
2118
2119
  int rc = setgroups(size, groups);
2120
  delete[] groups;
2121
2122
  if (rc == -1) {
2123
    return env->ThrowErrnoException(errno, "setgroups");
2124
  }
2125
}
2126
2127
2128
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
2129
  Environment* env = Environment::GetCurrent(args);
2130
2131
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
2132
    return env->ThrowTypeError("argument 1 must be a number or a string");
2133
  }
2134
2135
  if (!args[1]->IsUint32() && !args[1]->IsString()) {
2136
    return env->ThrowTypeError("argument 2 must be a number or a string");
2137
  }
2138
2139
  node::Utf8Value arg0(env->isolate(), args[0]);
2140
  gid_t extra_group;
2141
  bool must_free;
2142
  char* user;
2143
2144
  if (args[0]->IsUint32()) {
2145
    user = name_by_uid(args[0]->Uint32Value());
2146
    must_free = true;
2147
  } else {
2148
    user = *arg0;
2149
    must_free = false;
2150
  }
2151
2152
  if (user == nullptr) {
2153
    return env->ThrowError("initgroups user not found");
2154
  }
2155
2156
  extra_group = gid_by_name(env->isolate(), args[1]);
2157
2158
  if (extra_group == gid_not_found) {
2159
    if (must_free)
2160
      free(user);
2161
    return env->ThrowError("initgroups extra group not found");
2162
  }
2163
2164
  int rc = initgroups(user, extra_group);
2165
2166
  if (must_free) {
2167
    free(user);
2168
  }
2169
2170
  if (rc) {
2171
    return env->ThrowErrnoException(errno, "initgroups");
2172
  }
2173
}
2174
2175
#endif  // __POSIX__ && !defined(__ANDROID__)
2176
2177
2178
1505
static void WaitForInspectorDisconnect(Environment* env) {
2179
#if HAVE_INSPECTOR
2180
1505
  if (env->inspector_agent()->IsConnected()) {
2181
    // Restore signal dispositions, the app is done and is no longer
2182
    // capable of handling signals.
2183
#ifdef __POSIX__
2184
    struct sigaction act;
2185
    memset(&act, 0, sizeof(act));
2186
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
2187
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
2188
        continue;
2189
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
2190
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
2191
    }
2192
#endif
2193
    env->inspector_agent()->WaitForDisconnect();
2194
  }
2195
#endif
2196
1505
}
2197
2198
2199
137
void Exit(const FunctionCallbackInfo<Value>& args) {
2200
137
  WaitForInspectorDisconnect(Environment::GetCurrent(args));
2201
137
  exit(args[0]->Int32Value());
2202
}
2203
2204
2205
static void Uptime(const FunctionCallbackInfo<Value>& args) {
2206
  Environment* env = Environment::GetCurrent(args);
2207
  double uptime;
2208
2209
  uv_update_time(env->event_loop());
2210
  uptime = uv_now(env->event_loop()) - prog_start_time;
2211
2212
  args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2213
}
2214
2215
2216
2
void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2217
2
  Environment* env = Environment::GetCurrent(args);
2218
2219
  size_t rss;
2220
2
  int err = uv_resident_set_memory(&rss);
2221
2
  if (err) {
2222
    return env->ThrowUVException(err, "uv_resident_set_memory");
2223
  }
2224
2225
  // V8 memory usage
2226
2
  HeapStatistics v8_heap_stats;
2227
2
  env->isolate()->GetHeapStatistics(&v8_heap_stats);
2228
2229
  Local<Number> heap_total =
2230
2
      Number::New(env->isolate(), v8_heap_stats.total_heap_size());
2231
  Local<Number> heap_used =
2232
2
      Number::New(env->isolate(), v8_heap_stats.used_heap_size());
2233
2234
2
  Local<Object> info = Object::New(env->isolate());
2235
8
  info->Set(env->rss_string(), Number::New(env->isolate(), rss));
2236
6
  info->Set(env->heap_total_string(), heap_total);
2237
6
  info->Set(env->heap_used_string(), heap_used);
2238
2239
4
  args.GetReturnValue().Set(info);
2240
}
2241
2242
2243
45
void Kill(const FunctionCallbackInfo<Value>& args) {
2244
45
  Environment* env = Environment::GetCurrent(args);
2245
2246
45
  if (args.Length() != 2) {
2247
    return env->ThrowError("Bad argument.");
2248
  }
2249
2250
45
  int pid = args[0]->Int32Value();
2251
45
  int sig = args[1]->Int32Value();
2252
45
  int err = uv_kill(pid, sig);
2253
90
  args.GetReturnValue().Set(err);
2254
}
2255
2256
// used in Hrtime() below
2257
#define NANOS_PER_SEC 1000000000
2258
2259
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2260
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2261
// so this function instead returns an Array with 2 entries representing seconds
2262
// and nanoseconds, to avoid any integer overflow possibility.
2263
// Pass in an Array from a previous hrtime() call to instead get a time diff.
2264
22
void Hrtime(const FunctionCallbackInfo<Value>& args) {
2265
22
  uint64_t t = uv_hrtime();
2266
2267
44
  Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
2268
22
  uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
2269
2270
  // These three indices will contain the values for the hrtime tuple. The
2271
  // seconds value is broken into the upper/lower 32 bits and stored in two
2272
  // uint32 fields to be converted back in JS.
2273
22
  fields[0] = (t / NANOS_PER_SEC) >> 32;
2274
22
  fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
2275
22
  fields[2] = t % NANOS_PER_SEC;
2276
22
}
2277
2278
// Microseconds in a second, as a float, used in CPUUsage() below
2279
#define MICROS_PER_SEC 1e6
2280
2281
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
2282
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
2283
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
2284
// Returns those values as Float64 microseconds in the elements of the array
2285
// passed to the function.
2286
33
void CPUUsage(const FunctionCallbackInfo<Value>& args) {
2287
  uv_rusage_t rusage;
2288
2289
  // Call libuv to get the values we'll return.
2290
33
  int err = uv_getrusage(&rusage);
2291
33
  if (err) {
2292
    // On error, return the strerror version of the error code.
2293
    Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
2294
    args.GetReturnValue().Set(errmsg);
2295
    return;
2296
  }
2297
2298
  // Get the double array pointer from the Float64Array argument.
2299
33
  CHECK(args[0]->IsFloat64Array());
2300
66
  Local<Float64Array> array = args[0].As<Float64Array>();
2301
33
  CHECK_EQ(array->Length(), 2);
2302
33
  Local<ArrayBuffer> ab = array->Buffer();
2303
33
  double* fields = static_cast<double*>(ab->GetContents().Data());
2304
2305
  // Set the Float64Array elements to be user / system values in microseconds.
2306
33
  fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
2307
33
  fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
2308
}
2309
2310
40797
extern "C" void node_module_register(void* m) {
2311
40797
  struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2312
2313
40797
  if (mp->nm_flags & NM_F_BUILTIN) {
2314
40768
    mp->nm_link = modlist_builtin;
2315
40768
    modlist_builtin = mp;
2316
29
  } else if (!node_is_initialized) {
2317
    // "Linked" modules are included as part of the node project.
2318
    // Like builtins they are registered *before* node::Init runs.
2319
    mp->nm_flags = NM_F_LINKED;
2320
    mp->nm_link = modlist_linked;
2321
    modlist_linked = mp;
2322
  } else {
2323
29
    modpending = mp;
2324
  }
2325
40797
}
2326
2327
31597
struct node_module* get_builtin_module(const char* name) {
2328
  struct node_module* mp;
2329
2330
449575
  for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
2331
446448
    if (strcmp(mp->nm_modname, name) == 0)
2332
      break;
2333
  }
2334
2335
31597
  CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
2336
31597
  return (mp);
2337
}
2338
2339
struct node_module* get_linked_module(const char* name) {
2340
  struct node_module* mp;
2341
2342
  for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
2343
    if (strcmp(mp->nm_modname, name) == 0)
2344
      break;
2345
  }
2346
2347
  CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
2348
  return mp;
2349
}
2350
2351
typedef void (UV_DYNAMIC* extInit)(Local<Object> exports);
2352
2353
// DLOpen is process.dlopen(module, filename).
2354
// Used to load 'module.node' dynamically shared objects.
2355
//
2356
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2357
// when two contexts try to load the same shared object. Maybe have a shadow
2358
// cache that's a plain C list or hash table that's shared across contexts?
2359
32
void DLOpen(const FunctionCallbackInfo<Value>& args) {
2360
32
  Environment* env = Environment::GetCurrent(args);
2361
  uv_lib_t lib;
2362
2363
32
  CHECK_EQ(modpending, nullptr);
2364
2365
32
  if (args.Length() != 2) {
2366
    env->ThrowError("process.dlopen takes exactly 2 arguments.");
2367
3
    return;
2368
  }
2369
2370
64
  Local<Object> module = args[0]->ToObject(env->isolate());  // Cast
2371
61
  node::Utf8Value filename(env->isolate(), args[1]);  // Cast
2372
32
  const bool is_dlopen_error = uv_dlopen(*filename, &lib);
2373
2374
  // Objects containing v14 or later modules will have registered themselves
2375
  // on the pending list.  Activate all of them now.  At present, only one
2376
  // module per object is supported.
2377
32
  node_module* const mp = modpending;
2378
32
  modpending = nullptr;
2379
2380
32
  if (is_dlopen_error) {
2381
3
    Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
2382
3
    uv_dlclose(&lib);
2383
#ifdef _WIN32
2384
    // Windows needs to add the filename into the error message
2385
    errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
2386
#endif  // _WIN32
2387
3
    env->isolate()->ThrowException(Exception::Error(errmsg));
2388
    return;
2389
  }
2390
2391
29
  if (mp == nullptr) {
2392
    uv_dlclose(&lib);
2393
    env->ThrowError("Module did not self-register.");
2394
    return;
2395
  }
2396
29
  if (mp->nm_version != NODE_MODULE_VERSION) {
2397
    char errmsg[1024];
2398
    snprintf(errmsg,
2399
             sizeof(errmsg),
2400
             "Module version mismatch. Expected %d, got %d.",
2401
             NODE_MODULE_VERSION, mp->nm_version);
2402
2403
    // NOTE: `mp` is allocated inside of the shared library's memory, calling
2404
    // `uv_dlclose` will deallocate it
2405
    uv_dlclose(&lib);
2406
    env->ThrowError(errmsg);
2407
    return;
2408
  }
2409
29
  if (mp->nm_flags & NM_F_BUILTIN) {
2410
    uv_dlclose(&lib);
2411
    env->ThrowError("Built-in module self-registered.");
2412
    return;
2413
  }
2414
2415
29
  mp->nm_dso_handle = lib.handle;
2416
29
  mp->nm_link = modlist_addon;
2417
29
  modlist_addon = mp;
2418
2419
29
  Local<String> exports_string = env->exports_string();
2420
116
  Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
2421
2422
29
  if (mp->nm_context_register_func != nullptr) {
2423
3
    mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2424
28
  } else if (mp->nm_register_func != nullptr) {
2425
56
    mp->nm_register_func(exports, module, mp->nm_priv);
2426
  } else {
2427
    uv_dlclose(&lib);
2428
    env->ThrowError("Module has no declared entry point.");
2429
    return;
2430
  }
2431
2432
  // Tell coverity that 'handle' should not be freed when we return.
2433
  // coverity[leaked_storage]
2434
}
2435
2436
2437
static void OnFatalError(const char* location, const char* message) {
2438
  if (location) {
2439
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2440
  } else {
2441
    PrintErrorString("FATAL ERROR: %s\n", message);
2442
  }
2443
  fflush(stderr);
2444
  ABORT();
2445
}
2446
2447
2448
NO_RETURN void FatalError(const char* location, const char* message) {
2449
  OnFatalError(location, message);
2450
  // to suppress compiler warning
2451
  ABORT();
2452
}
2453
2454
2455
1168
void FatalException(Isolate* isolate,
2456
                    Local<Value> error,
2457
                    Local<Message> message) {
2458
2281
  HandleScope scope(isolate);
2459
2460
1168
  Environment* env = Environment::GetCurrent(isolate);
2461
1168
  Local<Object> process_object = env->process_object();
2462
1168
  Local<String> fatal_exception_string = env->fatal_exception_string();
2463
  Local<Function> fatal_exception_function =
2464
2336
      process_object->Get(fatal_exception_string).As<Function>();
2465
2466
1168
  if (!fatal_exception_function->IsFunction()) {
2467
    // failed before the process._fatalException function was added!
2468
    // this is probably pretty bad.  Nothing to do but report and exit.
2469
    ReportException(env, error, message);
2470
    exit(6);
2471
  }
2472
2473
2281
  TryCatch fatal_try_catch(isolate);
2474
2475
  // Do not call FatalException when _fatalException handler throws
2476
1168
  fatal_try_catch.SetVerbose(false);
2477
2478
  // this will return true if the JS layer handled it, false otherwise
2479
  Local<Value> caught =
2480
1168
      fatal_exception_function->Call(process_object, 1, &error);
2481
2482
1165
  if (fatal_try_catch.HasCaught()) {
2483
    // the fatal exception function threw, so we must exit
2484
2
    ReportException(env, fatal_try_catch);
2485
2
    exit(7);
2486
  }
2487
2488
1163
  if (false == caught->BooleanValue()) {
2489
50
    ReportException(env, error, message);
2490
50
    exit(1);
2491
  }
2492
1113
}
2493
2494
2495
4
void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2496
4
  HandleScope scope(isolate);
2497
  // TODO(bajtos) do not call FatalException if try_catch is verbose
2498
  // (requires V8 API to expose getter for try_catch.is_verbose_)
2499
4
  FatalException(isolate, try_catch.Exception(), try_catch.Message());
2500
}
2501
2502
2503
1164
void OnMessage(Local<Message> message, Local<Value> error) {
2504
  // The current version of V8 sends messages for errors only
2505
  // (thus `error` is always set).
2506
1164
  FatalException(Isolate::GetCurrent(), error, message);
2507
1113
}
2508
2509
2510
4
void ClearFatalExceptionHandlers(Environment* env) {
2511
4
  Local<Object> process = env->process_object();
2512
  Local<Value> events =
2513
16
      process->Get(env->context(), env->events_string()).ToLocalChecked();
2514
2515
4
  if (events->IsObject()) {
2516
12
    events.As<Object>()->Set(
2517
        env->context(),
2518
        OneByteString(env->isolate(), "uncaughtException"),
2519
32
        Undefined(env->isolate())).FromJust();
2520
  }
2521
2522
8
  process->Set(
2523
      env->context(),
2524
      env->domain_string(),
2525
32
      Undefined(env->isolate())).FromJust();
2526
4
}
2527
2528
2529
75512
static void Binding(const FunctionCallbackInfo<Value>& args) {
2530
75512
  Environment* env = Environment::GetCurrent(args);
2531
2532
151024
  Local<String> module = args[0]->ToString(env->isolate());
2533
105545
  node::Utf8Value module_v(env->isolate(), module);
2534
2535
75512
  Local<Object> cache = env->binding_cache_object();
2536
75512
  Local<Object> exports;
2537
2538
226536
  if (cache->Has(env->context(), module).FromJust()) {
2539
136434
    exports = cache->Get(module)->ToObject(env->isolate());
2540
45478
    args.GetReturnValue().Set(exports);
2541
45479
    return;
2542
  }
2543
2544
  // Append a string to process.moduleLoadList
2545
  char buf[1024];
2546
60068
  snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2547
2548
30034
  Local<Array> modules = env->module_load_list_array();
2549
30034
  uint32_t l = modules->Length();
2550
60068
  modules->Set(l, OneByteString(env->isolate(), buf));
2551
2552
30034
  node_module* mod = get_builtin_module(*module_v);
2553
30034
  if (mod != nullptr) {
2554
26907
    exports = Object::New(env->isolate());
2555
    // Internal bindings don't have a "module" object, only exports.
2556
26907
    CHECK_EQ(mod->nm_register_func, nullptr);
2557
26907
    CHECK_NE(mod->nm_context_register_func, nullptr);
2558
80721
    Local<Value> unused = Undefined(env->isolate());
2559
53814
    mod->nm_context_register_func(exports, unused,
2560
26907
      env->context(), mod->nm_priv);
2561
53814
    cache->Set(module, exports);
2562
3127
  } else if (!strcmp(*module_v, "constants")) {
2563
1563
    exports = Object::New(env->isolate());
2564
1563
    DefineConstants(env->isolate(), exports);
2565
3126
    cache->Set(module, exports);
2566
1564
  } else if (!strcmp(*module_v, "natives")) {
2567
1563
    exports = Object::New(env->isolate());
2568
1563
    DefineJavaScript(env, exports);
2569
3126
    cache->Set(module, exports);
2570
  } else {
2571
    char errmsg[1024];
2572
1
    snprintf(errmsg,
2573
             sizeof(errmsg),
2574
             "No such module: %s",
2575
1
             *module_v);
2576
1
    return env->ThrowError(errmsg);
2577
  }
2578
2579
60066
  args.GetReturnValue().Set(exports);
2580
}
2581
2582
static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2583
  Environment* env = Environment::GetCurrent(args.GetIsolate());
2584
2585
  Local<String> module_name = args[0]->ToString(env->isolate());
2586
2587
  Local<Object> cache = env->binding_cache_object();
2588
  Local<Value> exports_v = cache->Get(module_name);
2589
2590
  if (exports_v->IsObject())
2591
    return args.GetReturnValue().Set(exports_v.As<Object>());
2592
2593
  node::Utf8Value module_name_v(env->isolate(), module_name);
2594
  node_module* mod = get_linked_module(*module_name_v);
2595
2596
  if (mod == nullptr) {
2597
    char errmsg[1024];
2598
    snprintf(errmsg,
2599
             sizeof(errmsg),
2600
             "No such module was linked: %s",
2601
             *module_name_v);
2602
    return env->ThrowError(errmsg);
2603
  }
2604
2605
  Local<Object> module = Object::New(env->isolate());
2606
  Local<Object> exports = Object::New(env->isolate());
2607
  Local<String> exports_prop = String::NewFromUtf8(env->isolate(), "exports");
2608
  module->Set(exports_prop, exports);
2609
2610
  if (mod->nm_context_register_func != nullptr) {
2611
    mod->nm_context_register_func(exports,
2612
                                  module,
2613
                                  env->context(),
2614
                                  mod->nm_priv);
2615
  } else if (mod->nm_register_func != nullptr) {
2616
    mod->nm_register_func(exports, module, mod->nm_priv);
2617
  } else {
2618
    return env->ThrowError("Linked module has no declared entry point.");
2619
  }
2620
2621
  auto effective_exports = module->Get(exports_prop);
2622
  cache->Set(module_name, effective_exports);
2623
2624
  args.GetReturnValue().Set(effective_exports);
2625
}
2626
2627
3
static void ProcessTitleGetter(Local<Name> property,
2628
                               const PropertyCallbackInfo<Value>& info) {
2629
  char buffer[512];
2630
3
  uv_get_process_title(buffer, sizeof(buffer));
2631
9
  info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer));
2632
3
}
2633
2634
2635
2
static void ProcessTitleSetter(Local<Name> property,
2636
                               Local<Value> value,
2637
                               const PropertyCallbackInfo<void>& info) {
2638
4
  node::Utf8Value title(info.GetIsolate(), value);
2639
  // TODO(piscisaureus): protect with a lock
2640
2
  uv_set_process_title(*title);
2641
2
}
2642
2643
2644
25078
static void EnvGetter(Local<String> property,
2645
                      const PropertyCallbackInfo<Value>& info) {
2646
25078
  Isolate* isolate = info.GetIsolate();
2647
#ifdef __POSIX__
2648
34680
  node::Utf8Value key(isolate, property);
2649
25078
  const char* val = getenv(*key);
2650
25078
  if (val) {
2651
61904
    return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
2652
  }
2653
#else  // _WIN32
2654
  String::Value key(property);
2655
  WCHAR buffer[32767];  // The maximum size allowed for environment variables.
2656
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2657
                                         buffer,
2658
                                         arraysize(buffer));
2659
  // If result >= sizeof buffer the buffer was too small. That should never
2660
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2661
  // not found.
2662
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2663
      result < arraysize(buffer)) {
2664
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2665
    Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
2666
    return info.GetReturnValue().Set(rc);
2667
  }
2668
#endif
2669
}
2670
2671
2672
41
static void EnvSetter(Local<String> property,
2673
                      Local<Value> value,
2674
                      const PropertyCallbackInfo<Value>& info) {
2675
#ifdef __POSIX__
2676
123
  node::Utf8Value key(info.GetIsolate(), property);
2677
82
  node::Utf8Value val(info.GetIsolate(), value);
2678
41
  setenv(*key, *val, 1);
2679
#else  // _WIN32
2680
  String::Value key(property);
2681
  String::Value val(value);
2682
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2683
  // Environment variables that start with '=' are read-only.
2684
  if (key_ptr[0] != L'=') {
2685
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2686
  }
2687
#endif
2688
  // Whether it worked or not, always return rval.
2689
82
  info.GetReturnValue().Set(value);
2690
41
}
2691
2692
2693
8243
static void EnvQuery(Local<String> property,
2694
                     const PropertyCallbackInfo<Integer>& info) {
2695
8243
  int32_t rc = -1;  // Not found unless proven otherwise.
2696
#ifdef __POSIX__
2697
24729
  node::Utf8Value key(info.GetIsolate(), property);
2698
8243
  if (getenv(*key))
2699
7762
    rc = 0;
2700
#else  // _WIN32
2701
  String::Value key(property);
2702
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2703
  if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
2704
      GetLastError() == ERROR_SUCCESS) {
2705
    rc = 0;
2706
    if (key_ptr[0] == L'=') {
2707
      // Environment variables that start with '=' are hidden and read-only.
2708
      rc = static_cast<int32_t>(v8::ReadOnly) |
2709
           static_cast<int32_t>(v8::DontDelete) |
2710
           static_cast<int32_t>(v8::DontEnum);
2711
    }
2712
  }
2713
#endif
2714
8243
  if (rc != -1)
2715
15524
    info.GetReturnValue().Set(rc);
2716
8243
}
2717
2718
2719
239
static void EnvDeleter(Local<String> property,
2720
                       const PropertyCallbackInfo<Boolean>& info) {
2721
239
  bool rc = true;
2722
#ifdef __POSIX__
2723
717
  node::Utf8Value key(info.GetIsolate(), property);
2724
239
  rc = getenv(*key) != nullptr;
2725
239
  if (rc)
2726
239
    unsetenv(*key);
2727
#else
2728
  String::Value key(property);
2729
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2730
  if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, nullptr)) {
2731
    // Deletion failed. Return true if the key wasn't there in the first place,
2732
    // false if it is still there.
2733
    rc = GetEnvironmentVariableW(key_ptr, nullptr, 0) == 0 &&
2734
         GetLastError() != ERROR_SUCCESS;
2735
  }
2736
#endif
2737
717
  info.GetReturnValue().Set(rc);
2738
239
}
2739
2740
2741
655
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2742
655
  Environment* env = Environment::GetCurrent(info);
2743
655
  Isolate* isolate = env->isolate();
2744
655
  Local<Context> ctx = env->context();
2745
655
  Local<Function> fn = env->push_values_to_array_function();
2746
11135
  Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
2747
  size_t idx = 0;
2748
2749
#ifdef __POSIX__
2750
  int size = 0;
2751
19039
  while (environ[size])
2752
9192
    size++;
2753
2754
655
  Local<Array> envarr = Array::New(isolate);
2755
2756
9847
  for (int i = 0; i < size; ++i) {
2757
9192
    const char* var = environ[i];
2758
9192
    const char* s = strchr(var, '=');
2759
9192
    const int length = s ? s - var : strlen(var);
2760
    argv[idx] = String::NewFromUtf8(isolate,
2761
                                    var,
2762
                                    String::kNormalString,
2763
18384
                                    length);
2764
9192
    if (++idx >= arraysize(argv)) {
2765
1968
      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2766
656
      idx = 0;
2767
    }
2768
  }
2769
655
  if (idx > 0) {
2770
1965
    fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2771
  }
2772
#else  // _WIN32
2773
  WCHAR* environment = GetEnvironmentStringsW();
2774
  if (environment == nullptr)
2775
    return;  // This should not happen.
2776
  Local<Array> envarr = Array::New(isolate);
2777
  WCHAR* p = environment;
2778
  while (*p) {
2779
    WCHAR *s;
2780
    if (*p == L'=') {
2781
      // If the key starts with '=' it is a hidden environment variable.
2782
      p += wcslen(p) + 1;
2783
      continue;
2784
    } else {
2785
      s = wcschr(p, L'=');
2786
    }
2787
    if (!s) {
2788
      s = p + wcslen(p);
2789
    }
2790
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2791
    const size_t two_byte_buffer_len = s - p;
2792
    argv[idx] = String::NewFromTwoByte(isolate,
2793
                                       two_byte_buffer,
2794
                                       String::kNormalString,
2795
                                       two_byte_buffer_len);
2796
    if (++idx >= arraysize(argv)) {
2797
      fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2798
      idx = 0;
2799
    }
2800
    p = s + wcslen(s) + 1;
2801
  }
2802
  if (idx > 0) {
2803
    fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2804
  }
2805
  FreeEnvironmentStringsW(environment);
2806
#endif
2807
2808
1310
  info.GetReturnValue().Set(envarr);
2809
655
}
2810
2811
2812
1563
static Local<Object> GetFeatures(Environment* env) {
2813
3126
  EscapableHandleScope scope(env->isolate());
2814
2815
1563
  Local<Object> obj = Object::New(env->isolate());
2816
#if defined(DEBUG) && DEBUG
2817
  Local<Value> debug = True(env->isolate());
2818
#else
2819
4689
  Local<Value> debug = False(env->isolate());
2820
#endif  // defined(DEBUG) && DEBUG
2821
2822
3126
  obj->Set(env->debug_string(), debug);
2823
2824
7815
  obj->Set(env->uv_string(), True(env->isolate()));
2825
  // TODO(bnoordhuis) ping libuv
2826
7815
  obj->Set(env->ipv6_lc_string(), True(env->isolate()));
2827
2828
#ifdef OPENSSL_NPN_NEGOTIATED
2829
3126
  Local<Boolean> tls_npn = True(env->isolate());
2830
#else
2831
  Local<Boolean> tls_npn = False(env->isolate());
2832
#endif
2833
4689
  obj->Set(env->tls_npn_string(), tls_npn);
2834
2835
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2836
3126
  Local<Boolean> tls_alpn = True(env->isolate());
2837
#else
2838
  Local<Boolean> tls_alpn = False(env->isolate());
2839
#endif
2840
4689
  obj->Set(env->tls_alpn_string(), tls_alpn);
2841
2842
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2843
3126
  Local<Boolean> tls_sni = True(env->isolate());
2844
#else
2845
  Local<Boolean> tls_sni = False(env->isolate());
2846
#endif
2847
4689
  obj->Set(env->tls_sni_string(), tls_sni);
2848
2849
#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2850
3126
  Local<Boolean> tls_ocsp = True(env->isolate());
2851
#else
2852
  Local<Boolean> tls_ocsp = False(env->isolate());
2853
#endif  // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2854
4689
  obj->Set(env->tls_ocsp_string(), tls_ocsp);
2855
2856
9378
  obj->Set(env->tls_string(),
2857
           Boolean::New(env->isolate(),
2858
3126
                        get_builtin_module("crypto") != nullptr));
2859
2860
3126
  return scope.Escape(obj);
2861
}
2862
2863
2864
20
static void DebugPortGetter(Local<Name> property,
2865
                            const PropertyCallbackInfo<Value>& info) {
2866
60
  info.GetReturnValue().Set(debug_port);
2867
20
}
2868
2869
2870
static void DebugPortSetter(Local<Name> property,
2871
                            Local<Value> value,
2872
                            const PropertyCallbackInfo<void>& info) {
2873
  debug_port = value->Int32Value();
2874
}
2875
2876
2877
static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2878
static void DebugPause(const FunctionCallbackInfo<Value>& args);
2879
static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2880
2881
2882
7360
void NeedImmediateCallbackGetter(Local<Name> property,
2883
                                 const PropertyCallbackInfo<Value>& info) {
2884
7360
  Environment* env = Environment::GetCurrent(info);
2885
7360
  const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2886
7360
  bool active = uv_is_active(
2887
7360
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2888
22080
  info.GetReturnValue().Set(active);
2889
7360
}
2890
2891
2892
3356
static void NeedImmediateCallbackSetter(
2893
    Local<Name> property,
2894
    Local<Value> value,
2895
    const PropertyCallbackInfo<void>& info) {
2896
3356
  Environment* env = Environment::GetCurrent(info);
2897
2898
3356
  uv_check_t* immediate_check_handle = env->immediate_check_handle();
2899
3356
  bool active = uv_is_active(
2900
3356
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2901
2902
3356
  if (active == value->BooleanValue())
2903
    return;
2904
2905
3338
  uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2906
2907
3338
  if (active) {
2908
1664
    uv_check_stop(immediate_check_handle);
2909
1664
    uv_idle_stop(immediate_idle_handle);
2910
  } else {
2911
1674
    uv_check_start(immediate_check_handle, CheckImmediate);
2912
    // Idle handle is needed only to stop the event loop from blocking in poll.
2913
1674
    uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2914
  }
2915
}
2916
2917
2918
void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2919
  Environment* env = Environment::GetCurrent(args);
2920
  env->StartProfilerIdleNotifier();
2921
}
2922
2923
2924
void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2925
  Environment* env = Environment::GetCurrent(args);
2926
  env->StopProfilerIdleNotifier();
2927
}
2928
2929
2930
#define READONLY_PROPERTY(obj, str, var)                                      \
2931
  do {                                                                        \
2932
    obj->DefineOwnProperty(env->context(),                                    \
2933
                           OneByteString(env->isolate(), str),                \
2934
                           var,                                               \
2935
                           v8::ReadOnly).FromJust();                          \
2936
  } while (0)
2937
2938
#define READONLY_DONT_ENUM_PROPERTY(obj, str, var)                            \
2939
  do {                                                                        \
2940
    obj->DefineOwnProperty(env->context(),                                    \
2941
                           OneByteString(env->isolate(), str),                \
2942
                           var,                                               \
2943
                           static_cast<v8::PropertyAttribute>(v8::ReadOnly |  \
2944
                                                              v8::DontEnum))  \
2945
        .FromJust();                                                          \
2946
  } while (0)
2947
2948
2949
1563
void SetupProcessObject(Environment* env,
2950
                        int argc,
2951
                        const char* const* argv,
2952
                        int exec_argc,
2953
                        const char* const* exec_argv) {
2954
3126
  HandleScope scope(env->isolate());
2955
2956
1563
  Local<Object> process = env->process_object();
2957
2958
  auto maybe = process->SetAccessor(env->context(),
2959
                                    env->title_string(),
2960
                                    ProcessTitleGetter,
2961
                                    ProcessTitleSetter,
2962
7815
                                    env->as_external());
2963
1563
  CHECK(maybe.FromJust());
2964
2965
  // process.version
2966
7815
  READONLY_PROPERTY(process,
2967
                    "version",
2968
                    FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
2969
2970
  // process.moduleLoadList
2971
7815
  READONLY_PROPERTY(process,
2972
                    "moduleLoadList",
2973
                    env->module_load_list_array());
2974
2975
  // process.versions
2976
1563
  Local<Object> versions = Object::New(env->isolate());
2977
6252
  READONLY_PROPERTY(process, "versions", versions);
2978
2979
  const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2980
                                     "."
2981
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
2982
                                     "."
2983
1563
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
2984
7815
  READONLY_PROPERTY(versions,
2985
                    "http_parser",
2986
                    FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
2987
2988
  // +1 to get rid of the leading 'v'
2989
7815
  READONLY_PROPERTY(versions,
2990
                    "node",
2991
                    OneByteString(env->isolate(), NODE_VERSION + 1));
2992
7815
  READONLY_PROPERTY(versions,
2993
                    "v8",
2994
                    OneByteString(env->isolate(), V8::GetVersion()));
2995
7815
  READONLY_PROPERTY(versions,
2996
                    "uv",
2997
                    OneByteString(env->isolate(), uv_version_string()));
2998
7815
  READONLY_PROPERTY(versions,
2999
                    "zlib",
3000
                    FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
3001
7815
  READONLY_PROPERTY(versions,
3002
                    "ares",
3003
                    FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
3004
3005
#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
3006
7815
  READONLY_PROPERTY(versions,
3007
                    "icu",
3008
                    OneByteString(env->isolate(), U_ICU_VERSION));
3009
3010
1563
  if (icu_data_dir != nullptr) {
3011
    // Did the user attempt (via env var or parameter) to set an ICU path?
3012
    READONLY_PROPERTY(process,
3013
                      "icu_data_dir",
3014
                      OneByteString(env->isolate(), icu_data_dir));
3015
  }
3016
#endif
3017
3018
1563
  const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
3019
7815
  READONLY_PROPERTY(
3020
      versions,
3021
      "modules",
3022
      FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
3023
3024
  // process._promiseRejectEvent
3025
1563
  Local<Object> promiseRejectEvent = Object::New(env->isolate());
3026
6252
  READONLY_DONT_ENUM_PROPERTY(process,
3027
                              "_promiseRejectEvent",
3028
                              promiseRejectEvent);
3029
7815
  READONLY_PROPERTY(promiseRejectEvent,
3030
                    "unhandled",
3031
                    Integer::New(env->isolate(),
3032
                                 v8::kPromiseRejectWithNoHandler));
3033
7815
  READONLY_PROPERTY(promiseRejectEvent,
3034
                    "handled",
3035
                    Integer::New(env->isolate(),
3036
                                 v8::kPromiseHandlerAddedAfterReject));
3037
3038
#if HAVE_OPENSSL
3039
  // Stupid code to slice out the version string.
3040
  {  // NOLINT(whitespace/braces)
3041
    size_t i, j, k;
3042
    int c;
3043
14067
    for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
3044
14067
      c = OPENSSL_VERSION_TEXT[i];
3045
14067
      if ('0' <= c && c <= '9') {
3046
9378
        for (j = i + 1; j < k; ++j) {
3047
9378
          c = OPENSSL_VERSION_TEXT[j];
3048
9378
          if (c == ' ')
3049
            break;
3050
        }
3051
        break;
3052
      }
3053
    }
3054
7815
    READONLY_PROPERTY(
3055
        versions,
3056
        "openssl",
3057
        OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
3058
  }
3059
#endif
3060
3061
  // process.arch
3062
7815
  READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
3063
3064
  // process.platform
3065
7815
  READONLY_PROPERTY(process,
3066
                    "platform",
3067
                    OneByteString(env->isolate(), NODE_PLATFORM));
3068
3069
  // process.release
3070
1563
  Local<Object> release = Object::New(env->isolate());
3071
6252
  READONLY_PROPERTY(process, "release", release);
3072
7815
  READONLY_PROPERTY(release, "name", OneByteString(env->isolate(), "node"));
3073
3074
// if this is a release build and no explicit base has been set
3075
// substitute the standard release download URL
3076
#ifndef NODE_RELEASE_URLBASE
3077
# if NODE_VERSION_IS_RELEASE
3078
#  define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
3079
# endif
3080
#endif
3081
3082
#if defined(NODE_RELEASE_URLBASE)
3083
#  define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
3084
#  define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
3085
3086
  READONLY_PROPERTY(release,
3087
                    "sourceUrl",
3088
                    OneByteString(env->isolate(),
3089
                    NODE_RELEASE_URLFPFX ".tar.gz"));
3090
  READONLY_PROPERTY(release,
3091
                    "headersUrl",
3092
                    OneByteString(env->isolate(),
3093
                    NODE_RELEASE_URLFPFX "-headers.tar.gz"));
3094
#  ifdef _WIN32
3095
  READONLY_PROPERTY(release,
3096
                    "libUrl",
3097
                    OneByteString(env->isolate(),
3098
                    strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-"
3099
                                                NODE_ARCH "/node.lib"
3100
                                              : NODE_RELEASE_URLPFX
3101
                                                "win-x86/node.lib"));
3102
#  endif
3103
#endif
3104
3105
  // process.argv
3106
1563
  Local<Array> arguments = Array::New(env->isolate(), argc);
3107
4804
  for (int i = 0; i < argc; ++i) {
3108
9723
    arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
3109
  }
3110
4689
  process->Set(env->argv_string(), arguments);
3111
3112
  // process.execArgv
3113
1563
  Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
3114
1853
  for (int i = 0; i < exec_argc; ++i) {
3115
870
    exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
3116
  }
3117
4689
  process->Set(env->exec_argv_string(), exec_arguments);
3118
3119
  // create process.env
3120
  Local<ObjectTemplate> process_env_template =
3121
1563
      ObjectTemplate::New(env->isolate());
3122
4689
  process_env_template->SetNamedPropertyHandler(EnvGetter,
3123
                                                EnvSetter,
3124
                                                EnvQuery,
3125
                                                EnvDeleter,
3126
                                                EnvEnumerator,
3127
1563
                                                env->as_external());
3128
  Local<Object> process_env =
3129
3126
      process_env_template->NewInstance(env->context()).ToLocalChecked();
3130
4689
  process->Set(env->env_string(), process_env);
3131
3132
7815
  READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
3133
7815
  READONLY_PROPERTY(process, "features", GetFeatures(env));
3134
  maybe = process->SetAccessor(env->context(),
3135
                               env->need_imm_cb_string(),
3136
                               NeedImmediateCallbackGetter,
3137
                               NeedImmediateCallbackSetter,
3138
7815
                               env->as_external());
3139
1563
  CHECK(maybe.FromJust());
3140
3141
  // -e, --eval
3142
1563
  if (eval_string) {
3143
320
    READONLY_PROPERTY(process,
3144
                      "_eval",
3145
                      String::NewFromUtf8(env->isolate(), eval_string));
3146
  }
3147
3148
  // -p, --print
3149
1563
  if (print_eval) {
3150
144
    READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
3151
  }
3152
3153
  // -c, --check
3154
1563
  if (syntax_check_only) {
3155
132
    READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
3156
  }
3157
3158
  // -i, --interactive
3159
1563
  if (force_repl) {
3160
102
    READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
3161
  }
3162
3163
1563
  if (preload_module_count) {
3164
13
    CHECK(preload_modules);
3165
13
    Local<Array> array = Array::New(env->isolate());
3166
30
    for (unsigned int i = 0; i < preload_module_count; ++i) {
3167
      Local<String> module = String::NewFromUtf8(env->isolate(),
3168
17
                                                 preload_modules[i]);
3169
34
      array->Set(i, module);
3170
    }
3171
52
    READONLY_PROPERTY(process,
3172
                      "_preload_modules",
3173
                      array);
3174
3175
13
    delete[] preload_modules;
3176
13
    preload_modules = nullptr;
3177
13
    preload_module_count = 0;
3178
  }
3179
3180
  // --no-deprecation
3181
1563
  if (no_deprecation) {
3182
6
    READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
3183
  }
3184
3185
1563
  if (no_process_warnings) {
3186
18
    READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
3187
  }
3188
3189
1563
  if (trace_warnings) {
3190
6
    READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
3191
  }
3192
3193
  // --throw-deprecation
3194
1563
  if (throw_deprecation) {
3195
    READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
3196
  }
3197
3198
#ifdef NODE_NO_BROWSER_GLOBALS
3199
  // configure --no-browser-globals
3200
  READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
3201
#endif  // NODE_NO_BROWSER_GLOBALS
3202
3203
  // --prof-process
3204
1563
  if (prof_process) {
3205
12
    READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
3206
  }
3207
3208
  // --trace-deprecation
3209
1563
  if (trace_deprecation) {
3210
6
    READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
3211
  }
3212
3213
  // --debug-brk
3214
1563
  if (debug_wait_connect) {
3215
12
    READONLY_PROPERTY(process, "_debugWaitConnect", True(env->isolate()));
3216
  }
3217
3218
  // --security-revert flags
3219
#define V(code, _, __)                                                        \
3220
  do {                                                                        \
3221
    if (IsReverted(REVERT_ ## code)) {                                        \
3222
      READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate()));      \
3223
    }                                                                         \
3224
  } while (0);
3225
  REVERSIONS(V)
3226
#undef V
3227
3228
1563
  size_t exec_path_len = 2 * PATH_MAX;
3229
1563
  char* exec_path = new char[exec_path_len];
3230
1563
  Local<String> exec_path_value;
3231
1563
  if (uv_exepath(exec_path, &exec_path_len) == 0) {
3232
    exec_path_value = String::NewFromUtf8(env->isolate(),
3233
                                          exec_path,
3234
                                          String::kNormalString,
3235
1563
                                          exec_path_len);
3236
  } else {
3237
    exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
3238
  }
3239
4689
  process->Set(env->exec_path_string(), exec_path_value);
3240
1563
  delete[] exec_path;
3241
3242
  maybe = process->SetAccessor(env->context(),
3243
                               env->debug_port_string(),
3244
                               DebugPortGetter,
3245
                               DebugPortSetter,
3246
7815
                               env->as_external());
3247
1563
  CHECK(maybe.FromJust());
3248
3249
3250
  // define various internal methods
3251
  env->SetMethod(process,
3252
                 "_startProfilerIdleNotifier",
3253
1563
                 StartProfilerIdleNotifier);
3254
  env->SetMethod(process,
3255
                 "_stopProfilerIdleNotifier",
3256
1563
                 StopProfilerIdleNotifier);
3257
1563
  env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
3258
1563
  env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
3259
1563
  env->SetMethod(process, "reallyExit", Exit);
3260
1563
  env->SetMethod(process, "abort", Abort);
3261
1563
  env->SetMethod(process, "chdir", Chdir);
3262
1563
  env->SetMethod(process, "cwd", Cwd);
3263
3264
1563
  env->SetMethod(process, "umask", Umask);
3265
3266
#if defined(__POSIX__) && !defined(__ANDROID__)
3267
1563
  env->SetMethod(process, "getuid", GetUid);
3268
1563
  env->SetMethod(process, "geteuid", GetEUid);
3269
1563
  env->SetMethod(process, "setuid", SetUid);
3270
1563
  env->SetMethod(process, "seteuid", SetEUid);
3271
3272
1563
  env->SetMethod(process, "setgid", SetGid);
3273
1563
  env->SetMethod(process, "setegid", SetEGid);
3274
1563
  env->SetMethod(process, "getgid", GetGid);
3275
1563
  env->SetMethod(process, "getegid", GetEGid);
3276
3277
1563
  env->SetMethod(process, "getgroups", GetGroups);
3278
1563
  env->SetMethod(process, "setgroups", SetGroups);
3279
1563
  env->SetMethod(process, "initgroups", InitGroups);
3280
#endif  // __POSIX__ && !defined(__ANDROID__)
3281
3282
1563
  env->SetMethod(process, "_kill", Kill);
3283
3284
1563
  env->SetMethod(process, "_debugProcess", DebugProcess);
3285
1563
  env->SetMethod(process, "_debugPause", DebugPause);
3286
1563
  env->SetMethod(process, "_debugEnd", DebugEnd);
3287
3288
1563
  env->SetMethod(process, "hrtime", Hrtime);
3289
3290
1563
  env->SetMethod(process, "cpuUsage", CPUUsage);
3291
3292
1563
  env->SetMethod(process, "dlopen", DLOpen);
3293
3294
1563
  env->SetMethod(process, "uptime", Uptime);
3295
1563
  env->SetMethod(process, "memoryUsage", MemoryUsage);
3296
3297
1563
  env->SetMethod(process, "binding", Binding);
3298
1563
  env->SetMethod(process, "_linkedBinding", LinkedBinding);
3299
3300
1563
  env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
3301
1563
  env->SetMethod(process, "_setupNextTick", SetupNextTick);
3302
1563
  env->SetMethod(process, "_setupPromises", SetupPromises);
3303
1563
  env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
3304
3305
  // pre-set _events object for faster emit checks
3306
1563
  Local<Object> events_obj = Object::New(env->isolate());
3307
7815
  maybe = events_obj->SetPrototype(env->context(), Null(env->isolate()));
3308
1563
  CHECK(maybe.FromJust());
3309
4689
  process->Set(env->events_string(), events_obj);
3310
1563
}
3311
3312
3313
#undef READONLY_PROPERTY
3314
3315
3316
1563
static void AtExit() {
3317
1563
  uv_tty_reset_mode();
3318
1563
}
3319
3320
3321
void SignalExit(int signo) {
3322
  uv_tty_reset_mode();
3323
#ifdef __FreeBSD__
3324
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
3325
  struct sigaction sa;
3326
  memset(&sa, 0, sizeof(sa));
3327
  sa.sa_handler = SIG_DFL;
3328
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
3329
#endif
3330
  raise(signo);
3331
}
3332
3333
3334
// Most of the time, it's best to use `console.error` to write
3335
// to the process.stderr stream.  However, in some cases, such as
3336
// when debugging the stream.Writable class or the process.nextTick
3337
// function, it is useful to bypass JavaScript entirely.
3338
7
static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3339
28
  CHECK(args.Length() == 1 && args[0]->IsString() &&
3340
        "must be called with a single string");
3341
21
  node::Utf8Value message(args.GetIsolate(), args[0]);
3342
7
  PrintErrorString("%s\n", *message);
3343
7
  fflush(stderr);
3344
7
}
3345
3346
3347
1563
void LoadEnvironment(Environment* env) {
3348
3050
  HandleScope handle_scope(env->isolate());
3349
3350
1563
  env->isolate()->SetFatalErrorHandler(node::OnFatalError);
3351
1563
  env->isolate()->AddMessageListener(OnMessage);
3352
3353
  // The node.js file returns a function 'f'
3354
1563
  atexit(AtExit);
3355
3356
3050
  TryCatch try_catch(env->isolate());
3357
3358
  // Disable verbose mode to stop FatalException() handler from trying
3359
  // to handle the exception. Errors this early in the start-up phase
3360
  // are not safe to ignore.
3361
1563
  try_catch.SetVerbose(false);
3362
3363
  // Execute the lib/internal/bootstrap_node.js file which was included as a
3364
  // static C string in node_natives.h by node_js2c.
3365
  // 'internal_bootstrap_node_native' is the string containing that source code.
3366
1563
  Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
3367
                                                    "bootstrap_node.js");
3368
1563
  Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3369
1563
  if (try_catch.HasCaught())  {
3370
    ReportException(env, try_catch);
3371
    exit(10);
3372
  }
3373
1563
  CHECK(f_value->IsFunction());
3374
1563
  Local<Function> f = Local<Function>::Cast(f_value);
3375
3376
  // Now we call 'f' with the 'process' variable that we've built up with
3377
  // all our bindings. Inside node.js we'll take care of assigning things to
3378
  // their places.
3379
3380
  // We start the process this way in order to be more modular. Developers
3381
  // who do not like how 'src/node.js' setups the module system but do like
3382
  // Node's I/O bindings may want to replace 'f' with their own function.
3383
3384
  // Add a reference to the global object
3385
1563
  Local<Object> global = env->context()->Global();
3386
3387
#if defined HAVE_DTRACE || defined HAVE_ETW
3388
  InitDTrace(env, global);
3389
#endif
3390
3391
#if defined HAVE_LTTNG
3392
  InitLTTNG(env, global);
3393
#endif
3394
3395
#if defined HAVE_PERFCTR
3396
  InitPerfCounters(env, global);
3397
#endif
3398
3399
  // Enable handling of uncaught exceptions
3400
  // (FatalException(), break on uncaught exception in debugger)
3401
  //
3402
  // This is not strictly necessary since it's almost impossible
3403
  // to attach the debugger fast enought to break on exception
3404
  // thrown during process startup.
3405
1563
  try_catch.SetVerbose(true);
3406
3407
1563
  env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3408
3409
  // Expose the global object as a property on itself
3410
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
3411
3126
  global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
3412
3413
3126
  Local<Value> arg = env->process_object();
3414
4689
  f->Call(Null(env->isolate()), 1, &arg);
3415
1487
}
3416
3417
3418
static void PrintHelp();
3419
3420
218
static bool ParseDebugOpt(const char* arg) {
3421
218
  const char* port = nullptr;
3422
3423
218
  if (!strcmp(arg, "--debug")) {
3424
1
    use_debug_agent = true;
3425
217
  } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
3426
4
    use_debug_agent = true;
3427
4
    port = arg + sizeof("--debug=") - 1;
3428
213
  } else if (!strcmp(arg, "--debug-brk")) {
3429
    use_debug_agent = true;
3430
    debug_wait_connect = true;
3431
213
  } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
3432
1
    use_debug_agent = true;
3433
1
    debug_wait_connect = true;
3434
1
    port = arg + sizeof("--debug-brk=") - 1;
3435
212
  } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
3436
    // XXX(bnoordhuis) Misnomer, configures port and listen address.
3437
7
    port = arg + sizeof("--debug-port=") - 1;
3438
#if HAVE_INSPECTOR
3439
  // Specifying both --inspect and --debug means debugging is on, using Chromium
3440
  // inspector.
3441
205
  } else if (!strcmp(arg, "--inspect")) {
3442
    use_debug_agent = true;
3443
    use_inspector = true;
3444
205
  } else if (!strncmp(arg, "--inspect=", sizeof("--inspect=") - 1)) {
3445
    use_debug_agent = true;
3446
    use_inspector = true;
3447
    port = arg + sizeof("--inspect=") - 1;
3448
#else
3449
  } else if (!strncmp(arg, "--inspect", sizeof("--inspect") - 1)) {
3450
    fprintf(stderr,
3451
            "Inspector support is not available with this Node.js build\n");
3452
    return false;
3453
#endif
3454
  } else {
3455
    return false;
3456
  }
3457
3458
13
  if (port == nullptr) {
3459
    return true;
3460
  }
3461
3462
12
  std::string* const the_host = use_inspector ? &inspector_host : &debug_host;
3463
12
  int* const the_port = use_inspector ? &inspector_port : &debug_port;
3464
3465
  // FIXME(bnoordhuis) Move IPv6 address parsing logic to lib/net.js.
3466
  // It seems reasonable to support [address]:port notation
3467
  // in net.Server#listen() and net.Socket#connect().
3468
12
  const size_t port_len = strlen(port);
3469
12
  if (port[0] == '[' && port[port_len - 1] == ']') {
3470
    the_host->assign(port + 1, port_len - 2);
3471
    return true;
3472
  }
3473
3474
12
  const char* const colon = strrchr(port, ':');
3475
12
  if (colon == nullptr) {
3476
    // Either a port number or a host name.  Assume that
3477
    // if it's not all decimal digits, it's a host name.
3478
115
    for (size_t n = 0; port[n] != '\0'; n += 1) {
3479
52
      if (port[n] < '0' || port[n] > '9') {
3480
        *the_host = port;
3481
        return true;
3482
      }
3483
    }
3484
  } else {
3485
1
    const bool skip = (colon > port && port[0] == '[' && colon[-1] == ']');
3486
1
    the_host->assign(port + skip, colon - skip);
3487
  }
3488
3489
  char* endptr;
3490
12
  errno = 0;
3491
12
  const char* const digits = colon != nullptr ? colon + 1 : port;
3492
12
  const long result = strtol(digits, &endptr, 10);  // NOLINT(runtime/int)
3493
12
  if (errno != 0 || *endptr != '\0' || result < 1024 || result > 65535) {
3494
    fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
3495
    PrintHelp();
3496
    exit(12);
3497
  }
3498
3499
12
  *the_port = static_cast<int>(result);
3500
3501
12
  return true;
3502
}
3503
3504
static void PrintHelp() {
3505
  // XXX: If you add an option here, please also add it to doc/node.1 and
3506
  // doc/api/cli.md
3507
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
3508
         "       node debug script.js [arguments] \n"
3509
         "\n"
3510
         "Options:\n"
3511
         "  -v, --version         print Node.js version\n"
3512
         "  -e, --eval script     evaluate script\n"
3513
         "  -p, --print           evaluate script and print result\n"
3514
         "  -c, --check           syntax check script without executing\n"
3515
         "  -i, --interactive     always enter the REPL even if stdin\n"
3516
         "                        does not appear to be a terminal\n"
3517
         "  -r, --require         module to preload (option can be repeated)\n"
3518
         "  --no-deprecation      silence deprecation warnings\n"
3519
         "  --trace-deprecation   show stack traces on deprecations\n"
3520
         "  --throw-deprecation   throw an exception anytime a deprecated "
3521
         "function is used\n"
3522
         "  --no-warnings         silence all process warnings\n"
3523
         "  --trace-warnings      show stack traces on process warnings\n"
3524
         "  --trace-sync-io       show stack trace when use of sync IO\n"
3525
         "                        is detected after the first tick\n"
3526
         "  --track-heap-objects  track heap object allocations for heap "
3527
         "snapshots\n"
3528
         "  --prof-process        process v8 profiler output generated\n"
3529
         "                        using --prof\n"
3530
         "  --zero-fill-buffers   automatically zero-fill all newly allocated\n"
3531
         "                        Buffer and SlowBuffer instances\n"
3532
         "  --v8-options          print v8 command line options\n"
3533
         "  --v8-pool-size=num    set v8's thread pool size\n"
3534
#if HAVE_OPENSSL
3535
         "  --tls-cipher-list=val use an alternative default TLS cipher list\n"
3536
#if NODE_FIPS_MODE
3537
         "  --enable-fips         enable FIPS crypto at startup\n"
3538
         "  --force-fips          force FIPS crypto (cannot be disabled)\n"
3539
#endif  /* NODE_FIPS_MODE */
3540
#endif /* HAVE_OPENSSL */
3541
#if defined(NODE_HAVE_I18N_SUPPORT)
3542
         "  --icu-data-dir=dir    set ICU data load path to dir\n"
3543
         "                        (overrides NODE_ICU_DATA)\n"
3544
#if !defined(NODE_HAVE_SMALL_ICU)
3545
         "                        note: linked-in ICU data is\n"
3546
         "                        present.\n"
3547
#endif
3548
         "  --preserve-symlinks   preserve symbolic links when resolving\n"
3549
         "                        and caching modules.\n"
3550
#endif
3551
         "\n"
3552
         "Environment variables:\n"
3553
#ifdef _WIN32
3554
         "NODE_PATH                ';'-separated list of directories\n"
3555
#else
3556
         "NODE_PATH                ':'-separated list of directories\n"
3557
#endif
3558
         "                         prefixed to the module search path.\n"
3559
         "NODE_DISABLE_COLORS      set to 1 to disable colors in the REPL\n"
3560
#if defined(NODE_HAVE_I18N_SUPPORT)
3561
         "NODE_ICU_DATA            data path for ICU (Intl object) data\n"
3562
#if !defined(NODE_HAVE_SMALL_ICU)
3563
         "                         (will extend linked-in data)\n"
3564
#endif
3565
#endif
3566
         "NODE_REPL_HISTORY        path to the persistent REPL history file\n"
3567
         "\n"
3568
         "Documentation can be found at https://nodejs.org/\n");
3569
}
3570
3571
3572
// Parse command line arguments.
3573
//
3574
// argv is modified in place. exec_argv and v8_argv are out arguments that
3575
// ParseArgs() allocates memory for and stores a pointer to the output
3576
// vector in.  The caller should free them with delete[].
3577
//
3578
// On exit:
3579
//
3580
//  * argv contains the arguments with node and V8 options filtered out.
3581
//  * exec_argv contains both node and V8 options and nothing else.
3582
//  * v8_argv contains argv[0] plus any V8 options
3583
1568
static void ParseArgs(int* argc,
3584
                      const char** argv,
3585
                      int* exec_argc,
3586
                      const char*** exec_argv,
3587
                      int* v8_argc,
3588
                      const char*** v8_argv) {
3589
1568
  const unsigned int nargs = static_cast<unsigned int>(*argc);
3590
1568
  const char** new_exec_argv = new const char*[nargs];
3591
1568
  const char** new_v8_argv = new const char*[nargs];
3592
1568
  const char** new_argv = new const char*[nargs];
3593
1568
  const char** local_preload_modules = new const char*[nargs];
3594
3595
5115
  for (unsigned int i = 0; i < nargs; ++i) {
3596
3547
    new_exec_argv[i] = nullptr;
3597
3547
    new_v8_argv[i] = nullptr;
3598
3547
    new_argv[i] = nullptr;
3599
3547
    local_preload_modules[i] = nullptr;
3600
  }
3601
3602
  // exec_argv starts with the first option, the other two start with argv[0].
3603
1568
  unsigned int new_exec_argc = 0;
3604
1568
  unsigned int new_v8_argc = 1;
3605
1568
  unsigned int new_argc = 1;
3606
1568
  new_v8_argv[0] = argv[0];
3607
1568
  new_argv[0] = argv[0];
3608
3609
1568
  unsigned int index = 1;
3610
1568
  bool short_circuit = false;
3611
1998
  while (index < nargs && argv[index][0] == '-' && !short_circuit) {
3612
218
    const char* const arg = argv[index];
3613
218
    unsigned int args_consumed = 1;
3614
3615
218
    if (ParseDebugOpt(arg)) {
3616
      // Done, consumed by ParseDebugOpt().
3617
205
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
3618
2
      printf("%s\n", NODE_VERSION);
3619
2
      exit(0);
3620
203
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3621
      PrintHelp();
3622
      exit(0);
3623
402
    } else if (strcmp(arg, "--eval") == 0 ||
3624
351
               strcmp(arg, "-e") == 0 ||
3625
301
               strcmp(arg, "--print") == 0 ||
3626
289
               strcmp(arg, "-pe") == 0 ||
3627
140
               strcmp(arg, "-p") == 0) {
3628
75
      bool is_eval = strchr(arg, 'e') != nullptr;
3629
75
      bool is_print = strchr(arg, 'p') != nullptr;
3630
75
      print_eval = print_eval || is_print;
3631
      // --eval, -e and -pe always require an argument.
3632
75
      if (is_eval == true) {
3633
60
        args_consumed += 1;
3634
60
        eval_string = argv[index + 1];
3635
60
        if (eval_string == nullptr) {
3636
2
          fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3637
1
          exit(9);
3638
        }
3639
30
      } else if ((index + 1 < nargs) &&
3640
30
                 argv[index + 1] != nullptr &&
3641
15
                 argv[index + 1][0] != '-') {
3642
13
        args_consumed += 1;
3643
13
        eval_string = argv[index + 1];
3644
13
        if (strncmp(eval_string, "\\-", 2) == 0) {
3645
          // Starts with "\\-": escaped expression, drop the backslash.
3646
1
          eval_string += 1;
3647
        }
3648
      }
3649
250
    } else if (strcmp(arg, "--require") == 0 ||
3650
122
               strcmp(arg, "-r") == 0) {
3651
17
      const char* module = argv[index + 1];
3652
17
      if (module == nullptr) {
3653
        fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3654
        exit(9);
3655
      }
3656
17
      args_consumed += 1;
3657
17
      local_preload_modules[preload_module_count++] = module;
3658
111
    } else if (strcmp(arg, "--check") == 0 || strcmp(arg, "-c") == 0) {
3659
22
      syntax_check_only = true;
3660
89
    } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3661
15
      force_repl = true;
3662
74
    } else if (strcmp(arg, "--no-deprecation") == 0) {
3663
1
      no_deprecation = true;
3664
73
    } else if (strcmp(arg, "--no-warnings") == 0) {
3665
3
      no_process_warnings = true;
3666
70
    } else if (strcmp(arg, "--trace-warnings") == 0) {
3667
1
      trace_warnings = true;
3668
69
    } else if (strcmp(arg, "--trace-deprecation") == 0) {
3669
1
      trace_deprecation = true;
3670
68
    } else if (strcmp(arg, "--trace-sync-io") == 0) {
3671
1
      trace_sync_io = true;
3672
67
    } else if (strcmp(arg, "--track-heap-objects") == 0) {
3673
      track_heap_objects = true;
3674
67
    } else if (strcmp(arg, "--throw-deprecation") == 0) {
3675
      throw_deprecation = true;
3676
67
    } else if (strncmp(arg, "--security-revert=", 18) == 0) {
3677
      const char* cve = arg + 18;
3678
      Revert(cve);
3679
67
    } else if (strcmp(arg, "--preserve-symlinks") == 0) {
3680
3
      config_preserve_symlinks = true;
3681
64
    } else if (strcmp(arg, "--prof-process") == 0) {
3682
2
      prof_process = true;
3683
2
      short_circuit = true;
3684
62
    } else if (strcmp(arg, "--zero-fill-buffers") == 0) {
3685
1
      zero_fill_all_buffers = true;
3686
61
    } else if (strcmp(arg, "--v8-options") == 0) {
3687
      new_v8_argv[new_v8_argc] = "--help";
3688
      new_v8_argc += 1;
3689
61
    } else if (strncmp(arg, "--v8-pool-size=", 15) == 0) {
3690
      v8_thread_pool_size = atoi(arg + 15);
3691
#if HAVE_OPENSSL
3692
61
    } else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
3693
1
      default_cipher_list = arg + 18;
3694
#if NODE_FIPS_MODE
3695
    } else if (strcmp(arg, "--enable-fips") == 0) {
3696
      enable_fips_crypto = true;
3697
    } else if (strcmp(arg, "--force-fips") == 0) {
3698
      force_fips_crypto = true;
3699
#endif /* NODE_FIPS_MODE */
3700
#endif /* HAVE_OPENSSL */
3701
#if defined(NODE_HAVE_I18N_SUPPORT)
3702
60
    } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3703
      icu_data_dir = arg + 15;
3704
#endif
3705
112
    } else if (strcmp(arg, "--expose-internals") == 0 ||
3706
52
               strcmp(arg, "--expose_internals") == 0) {
3707
      // consumed in js
3708
    } else {
3709
      // V8 option.  Pass through as-is.
3710
42
      new_v8_argv[new_v8_argc] = arg;
3711
42
      new_v8_argc += 1;
3712
    }
3713
3714
215
    memcpy(new_exec_argv + new_exec_argc,
3715
           argv + index,
3716
215
           args_consumed * sizeof(*argv));
3717
3718
215
    new_exec_argc += args_consumed;
3719
215
    index += args_consumed;
3720
  }
3721
3722
  // Copy remaining arguments.
3723
1565
  const unsigned int args_left = nargs - index;
3724
3130
  memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3725
1565
  new_argc += args_left;
3726
3727
1565
  *exec_argc = new_exec_argc;
3728
1565
  *exec_argv = new_exec_argv;
3729
1565
  *v8_argc = new_v8_argc;
3730
1565
  *v8_argv = new_v8_argv;
3731
3732
  // Copy new_argv over argv and update argc.
3733
3130
  memcpy(argv, new_argv, new_argc * sizeof(*argv));
3734
1565
  delete[] new_argv;
3735
1565
  *argc = static_cast<int>(new_argc);
3736
3737
  // Copy the preload_modules from the local array to an appropriately sized
3738
  // global array.
3739
1565
  if (preload_module_count > 0) {
3740
13
    CHECK(!preload_modules);
3741
13
    preload_modules = new const char*[preload_module_count];
3742
13
    memcpy(preload_modules, local_preload_modules,
3743
           preload_module_count * sizeof(*preload_modules));
3744
  }
3745
1565
  delete[] local_preload_modules;
3746
1565
}
3747
3748
3749
// Called from V8 Debug Agent TCP thread.
3750
1
static void DispatchMessagesDebugAgentCallback(Environment* env) {
3751
  // TODO(indutny): move async handle to environment
3752
1
  uv_async_send(&dispatch_debug_messages_async);
3753
1
}
3754
3755
3756
6
static void StartDebug(Environment* env, bool wait) {
3757
6
  CHECK(!debugger_running);
3758
6
  if (use_inspector) {
3759
    v8_platform.StartInspector(env, inspector_port, wait);
3760
    debugger_running = true;
3761
  } else {
3762
6
    env->debugger_agent()->set_dispatch_handler(
3763
12
          DispatchMessagesDebugAgentCallback);
3764
    debugger_running =
3765
12
        env->debugger_agent()->Start(debug_host, debug_port, wait);
3766
6
    if (debugger_running == false) {
3767
      fprintf(stderr, "Starting debugger on %s:%d failed\n",
3768
              debug_host.c_str(), debug_port);
3769
      fflush(stderr);
3770
      return;
3771
    }
3772
  }
3773
}
3774
3775
3776
// Called from the main thread.
3777
5
static void EnableDebug(Environment* env) {
3778
5
  CHECK(debugger_running);
3779
3780
5
  if (use_inspector) {
3781
    return;
3782
  }
3783
3784
  // Send message to enable debug in workers
3785
10
  HandleScope handle_scope(env->isolate());
3786
3787
5
  Local<Object> message = Object::New(env->isolate());
3788
25
  message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3789
5
               FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3790
  Local<Value> argv[] = {
3791
    FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
3792
    message
3793
15
  };
3794
10
  MakeCallback(env, env->process_object(), "emit", arraysize(argv), argv);
3795
3796
  // Enabled debugger, possibly making it wait on a semaphore
3797
5
  env->debugger_agent()->Enable();
3798
}
3799
3800
3801
// Called from an arbitrary thread.
3802
static void TryStartDebugger() {
3803
  Mutex::ScopedLock scoped_lock(node_isolate_mutex);
3804
  if (auto isolate = node_isolate) {
3805
    v8::Debug::DebugBreak(isolate);
3806
    uv_async_send(&dispatch_debug_messages_async);
3807
  }
3808
}
3809
3810
3811
// Called from the main thread.
3812
1
static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
3813
2
  Mutex::ScopedLock scoped_lock(node_isolate_mutex);
3814
1
  if (auto isolate = node_isolate) {
3815
1
    if (debugger_running == false) {
3816
      fprintf(stderr, "Starting debugger agent.\n");
3817
3818
      HandleScope scope(isolate);
3819
      Environment* env = Environment::GetCurrent(isolate);
3820
      Context::Scope context_scope(env->context());
3821
3822
      StartDebug(env, false);
3823
      EnableDebug(env);
3824
    }
3825
3826
2
    Isolate::Scope isolate_scope(isolate);
3827
1
    v8::Debug::ProcessDebugMessages(isolate);
3828
  }
3829
1
}
3830
3831
3832
#ifdef __POSIX__
3833
static void EnableDebugSignalHandler(int signo) {
3834
  uv_sem_post(&debug_semaphore);
3835
}
3836
3837
3838
4735
void RegisterSignalHandler(int signal,
3839
                           void (*handler)(int signal),
3840
                           bool reset_handler) {
3841
  struct sigaction sa;
3842
4735
  memset(&sa, 0, sizeof(sa));
3843
4735
  sa.sa_handler = handler;
3844
#ifndef __FreeBSD__
3845
  // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
3846
  // in turn set for a libthr wrapper. This leads to a crash.
3847
  // Work around the issue by manually setting SIG_DFL in the signal handler
3848
4735
  sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
3849
#endif
3850
4735
  sigfillset(&sa.sa_mask);
3851
4735
  CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
3852
4735
}
3853
3854
3855
3
void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3856
3
  Environment* env = Environment::GetCurrent(args);
3857
3858
3
  if (args.Length() != 1) {
3859
    return env->ThrowError("Invalid number of arguments.");
3860
  }
3861
3862
  pid_t pid;
3863
  int r;
3864
3865
3
  pid = args[0]->IntegerValue();
3866
3
  r = kill(pid, SIGUSR1);
3867
3
  if (r != 0) {
3868
1
    return env->ThrowErrnoException(errno, "kill");
3869
  }
3870
}
3871
3872
3873
1551
inline void* DebugSignalThreadMain(void* unused) {
3874
  for (;;) {
3875
1551
    uv_sem_wait(&debug_semaphore);
3876
    TryStartDebugger();
3877
  }
3878
  return nullptr;
3879
}
3880
3881
3882
1551
static int RegisterDebugSignalHandler() {
3883
  // Start a watchdog thread for calling v8::Debug::DebugBreak() because
3884
  // it's not safe to call directly from the signal handler, it can
3885
  // deadlock with the thread it interrupts.
3886
1551
  CHECK_EQ(0, uv_sem_init(&debug_semaphore, 0));
3887
  pthread_attr_t attr;
3888
1551
  CHECK_EQ(0, pthread_attr_init(&attr));
3889
  // Don't shrink the thread's stack on FreeBSD.  Said platform decided to
3890
  // follow the pthreads specification to the letter rather than in spirit:
3891
  // https://lists.freebsd.org/pipermail/freebsd-current/2014-March/048885.html
3892
#ifndef __FreeBSD__
3893
1551
  CHECK_EQ(0, pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN));
3894
#endif  // __FreeBSD__
3895
1551
  CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
3896
  sigset_t sigmask;
3897
1551
  sigfillset(&sigmask);
3898
1551
  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask));
3899
  pthread_t thread;
3900
  const int err =
3901
1551
      pthread_create(&thread, &attr, DebugSignalThreadMain, nullptr);
3902
1551
  CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr));
3903
1551
  CHECK_EQ(0, pthread_attr_destroy(&attr));
3904
1551
  if (err != 0) {
3905
    fprintf(stderr, "node[%d]: pthread_create: %s\n", getpid(), strerror(err));
3906
    fflush(stderr);
3907
    // Leave SIGUSR1 blocked.  We don't install a signal handler,
3908
    // receiving the signal would terminate the process.
3909
    return -err;
3910
  }
3911
1551
  RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
3912
  // Unblock SIGUSR1.  A pending SIGUSR1 signal will now be delivered.
3913
1551
  sigemptyset(&sigmask);
3914
1551
  sigaddset(&sigmask, SIGUSR1);
3915
1551
  CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
3916
  return 0;
3917
}
3918
#endif  // __POSIX__
3919
3920
3921
#ifdef _WIN32
3922
DWORD WINAPI EnableDebugThreadProc(void* arg) {
3923
  TryStartDebugger();
3924
  return 0;
3925
}
3926
3927
3928
static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3929
    size_t buf_len) {
3930
  return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
3931
}
3932
3933
3934
static int RegisterDebugSignalHandler() {
3935
  wchar_t mapping_name[32];
3936
  HANDLE mapping_handle;
3937
  DWORD pid;
3938
  LPTHREAD_START_ROUTINE* handler;
3939
3940
  pid = GetCurrentProcessId();
3941
3942
  if (GetDebugSignalHandlerMappingName(pid,
3943
                                       mapping_name,
3944
                                       arraysize(mapping_name)) < 0) {
3945
    return -1;
3946
  }
3947
3948
  mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
3949
                                      nullptr,
3950
                                      PAGE_READWRITE,
3951
                                      0,
3952
                                      sizeof *handler,
3953
                                      mapping_name);
3954
  if (mapping_handle == nullptr) {
3955
    return -1;
3956
  }
3957
3958
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3959
      MapViewOfFile(mapping_handle,
3960
                    FILE_MAP_ALL_ACCESS,
3961
                    0,
3962
                    0,
3963
                    sizeof *handler));
3964
  if (handler == nullptr) {
3965
    CloseHandle(mapping_handle);
3966
    return -1;
3967
  }
3968
3969
  *handler = EnableDebugThreadProc;
3970
3971
  UnmapViewOfFile(static_cast<void*>(handler));
3972
3973
  return 0;
3974
}
3975
3976
3977
static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3978
  Environment* env = Environment::GetCurrent(args);
3979
  Isolate* isolate = args.GetIsolate();
3980
  DWORD pid;
3981
  HANDLE process = nullptr;
3982
  HANDLE thread = nullptr;
3983
  HANDLE mapping = nullptr;
3984
  wchar_t mapping_name[32];
3985
  LPTHREAD_START_ROUTINE* handler = nullptr;
3986
3987
  if (args.Length() != 1) {
3988
    env->ThrowError("Invalid number of arguments.");
3989
    goto out;
3990
  }
3991
3992
  pid = (DWORD) args[0]->IntegerValue();
3993
3994
  process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
3995
                            PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3996
                            PROCESS_VM_READ,
3997
                        FALSE,
3998
                        pid);
3999
  if (process == nullptr) {
4000
    isolate->ThrowException(
4001
        WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
4002
    goto out;
4003
  }
4004
4005
  if (GetDebugSignalHandlerMappingName(pid,
4006
                                       mapping_name,
4007
                                       arraysize(mapping_name)) < 0) {
4008
    env->ThrowErrnoException(errno, "sprintf");
4009
    goto out;
4010
  }
4011
4012
  mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
4013
  if (mapping == nullptr) {
4014
    isolate->ThrowException(WinapiErrnoException(isolate,
4015
                                             GetLastError(),
4016
                                             "OpenFileMappingW"));
4017
    goto out;
4018
  }
4019
4020
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
4021
      MapViewOfFile(mapping,
4022
                    FILE_MAP_READ,
4023
                    0,
4024
                    0,
4025
                    sizeof *handler));
4026
  if (handler == nullptr || *handler == nullptr) {
4027
    isolate->ThrowException(
4028
        WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
4029
    goto out;
4030
  }
4031
4032
  thread = CreateRemoteThread(process,
4033
                              nullptr,
4034
                              0,
4035
                              *handler,
4036
                              nullptr,
4037
                              0,
4038
                              nullptr);
4039
  if (thread == nullptr) {
4040
    isolate->ThrowException(WinapiErrnoException(isolate,
4041
                                                 GetLastError(),
4042
                                                 "CreateRemoteThread"));
4043
    goto out;
4044
  }
4045
4046
  // Wait for the thread to terminate
4047
  if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
4048
    isolate->ThrowException(WinapiErrnoException(isolate,
4049
                                                 GetLastError(),
4050
                                                 "WaitForSingleObject"));
4051
    goto out;
4052
  }
4053
4054
 out:
4055
  if (process != nullptr)
4056
    CloseHandle(process);
4057
  if (thread != nullptr)
4058
    CloseHandle(thread);
4059
  if (handler != nullptr)
4060
    UnmapViewOfFile(handler);
4061
  if (mapping != nullptr)
4062
    CloseHandle(mapping);
4063
}
4064
#endif  // _WIN32
4065
4066
4067
static void DebugPause(const FunctionCallbackInfo<Value>& args) {
4068
  v8::Debug::DebugBreak(args.GetIsolate());
4069
}
4070
4071
4072
static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
4073
  if (debugger_running) {
4074
    Environment* env = Environment::GetCurrent(args);
4075
#if HAVE_INSPECTOR
4076
    if (use_inspector) {
4077
      env->inspector_agent()->Stop();
4078
    } else {
4079
#endif
4080
      env->debugger_agent()->Stop();
4081
#if HAVE_INSPECTOR
4082
    }
4083
#endif
4084
    debugger_running = false;
4085
  }
4086
}
4087
4088
4089
1568
inline void PlatformInit() {
4090
#ifdef __POSIX__
4091
  sigset_t sigmask;
4092
1568
  sigemptyset(&sigmask);
4093
1568
  sigaddset(&sigmask, SIGUSR1);
4094
1568
  const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
4095
4096
  // Make sure file descriptors 0-2 are valid before we start logging anything.
4097
6272
  for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
4098
    struct stat ignored;
4099
4704
    if (fstat(fd, &ignored) == 0)
4100
4702
      continue;
4101
    // Anything but EBADF means something is seriously wrong.  We don't
4102
    // have to special-case EINTR, fstat() is not interruptible.
4103
2
    if (errno != EBADF)
4104
      ABORT();
4105
2
    if (fd != open("/dev/null", O_RDWR))
4106
      ABORT();
4107
  }
4108
4109
1568
  CHECK_EQ(err, 0);
4110
4111
  // Restore signal dispositions, the parent process may have changed them.
4112
  struct sigaction act;
4113
1568
  memset(&act, 0, sizeof(act));
4114
4115
  // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
4116
  // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
4117
  // Counting up to SIGRTMIN doesn't work for the same reason.
4118
50176
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
4119
48608
    if (nr == SIGKILL || nr == SIGSTOP)
4120
      continue;
4121
45472
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
4122
45472
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
4123
  }
4124
4125
1568
  RegisterSignalHandler(SIGINT, SignalExit, true);
4126
1568
  RegisterSignalHandler(SIGTERM, SignalExit, true);
4127
4128
  // Raise the open file descriptor limit.
4129
  struct rlimit lim;
4130
1568
  if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
4131
    // Do a binary search for the limit.
4132
1184
    rlim_t min = lim.rlim_cur;
4133
1184
    rlim_t max = 1 << 20;
4134
    // But if there's a defined upper bound, don't search, just set it.
4135
1184
    if (lim.rlim_max != RLIM_INFINITY) {
4136
1184
      min = lim.rlim_max;
4137
1184
      max = lim.rlim_max;
4138
    }
4139
    do {
4140
1184
      lim.rlim_cur = min + (max - min) / 2;
4141
1184
      if (setrlimit(RLIMIT_NOFILE, &lim)) {
4142
        max = lim.rlim_cur;
4143
      } else {
4144
1184
        min = lim.rlim_cur;
4145
      }
4146
1184
    } while (min + 1 < max);
4147
  }
4148
#endif  // __POSIX__
4149
1568
}
4150
4151
4152
1568
void Init(int* argc,
4153
          const char** argv,
4154
          int* exec_argc,
4155
          const char*** exec_argv) {
4156
  // Initialize prog_start_time to get relative uptime.
4157
1568
  prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
4158
4159
  // Make inherited handles noninheritable.
4160
1568
  uv_disable_stdio_inheritance();
4161
4162
  // init async debug messages dispatching
4163
  // Main thread uses uv_default_loop
4164
1568
  CHECK_EQ(0, uv_async_init(uv_default_loop(),
4165
                            &dispatch_debug_messages_async,
4166
                            DispatchDebugMessagesAsyncCallback));
4167
1568
  uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
4168
4169
#if defined(NODE_V8_OPTIONS)
4170
  // Should come before the call to V8::SetFlagsFromCommandLine()
4171
  // so the user can disable a flag --foo at run-time by passing
4172
  // --no_foo from the command line.
4173
  V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
4174
#endif
4175
4176
  // Parse a few arguments which are specific to Node.
4177
  int v8_argc;
4178
  const char** v8_argv;
4179
1568
  ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
4180
4181
  // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
4182
  // manually?  That would give us a little more control over its runtime
4183
  // behavior but it could also interfere with the user's intentions in ways
4184
  // we fail to anticipate.  Dillema.
4185
1610
  for (int i = 1; i < v8_argc; ++i) {
4186
42
    if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
4187
      v8_is_profiling = true;
4188
      break;
4189
    }
4190
  }
4191
4192
#ifdef __POSIX__
4193
  // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc.  Avoids the
4194
  // performance penalty of frequent EINTR wakeups when the profiler is running.
4195
  // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
4196
1565
  if (v8_is_profiling) {
4197
    uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
4198
  }
4199
#endif
4200
4201
#if defined(NODE_HAVE_I18N_SUPPORT)
4202
1565
  if (icu_data_dir == nullptr) {
4203
    // if the parameter isn't given, use the env variable.
4204
1565
    icu_data_dir = secure_getenv("NODE_ICU_DATA");
4205
  }
4206
  // Initialize ICU.
4207
  // If icu_data_dir is nullptr here, it will load the 'minimal' data.
4208
1565
  if (!i18n::InitializeICUDirectory(icu_data_dir)) {
4209
    FatalError(nullptr, "Could not initialize ICU "
4210
                     "(check NODE_ICU_DATA or --icu-data-dir parameters)");
4211
  }
4212
#endif
4213
  // The const_cast doesn't violate conceptual const-ness.  V8 doesn't modify
4214
  // the argv array or the elements it points to.
4215
1565
  if (v8_argc > 1)
4216
40
    V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
4217
4218
  // Anything that's still in v8_argv is not a V8 or a node option.
4219
1585
  for (int i = 1; i < v8_argc; i++) {
4220
20
    fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
4221
  }
4222
1565
  delete[] v8_argv;
4223
1565
  v8_argv = nullptr;
4224
4225
1565
  if (v8_argc > 1) {
4226
8
    exit(9);
4227
  }
4228
4229
  // Unconditionally force typed arrays to allocate outside the v8 heap. This
4230
  // is to prevent memory pointers from being moved around that are returned by
4231
  // Buffer::Data().
4232
1557
  const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
4233
1557
  V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
4234
4235
1557
  if (!use_debug_agent) {
4236
1551
    RegisterDebugSignalHandler();
4237
  }
4238
4239
  // We should set node_is_initialized here instead of in node::Start,
4240
  // otherwise embedders using node::Init to initialize everything will not be
4241
  // able to set it and native modules will not load for them.
4242
1557
  node_is_initialized = true;
4243
1557
}
4244
4245
4246
struct AtExitCallback {
4247
  AtExitCallback* next_;
4248
  void (*cb_)(void* arg);
4249
  void* arg_;
4250
};
4251
4252
static AtExitCallback* at_exit_functions_;
4253
4254
4255
// TODO(bnoordhuis) Turn into per-context event.
4256
1368
void RunAtExit(Environment* env) {
4257
1368
  AtExitCallback* p = at_exit_functions_;
4258
1368
  at_exit_functions_ = nullptr;
4259
4260
1374
  while (p) {
4261
3
    AtExitCallback* q = p->next_;
4262
3
    p->cb_(p->arg_);
4263
3
    delete p;
4264
3
    p = q;
4265
  }
4266
1368
}
4267
4268
4269
3
void AtExit(void (*cb)(void* arg), void* arg) {
4270
3
  AtExitCallback* p = new AtExitCallback;
4271
3
  p->cb_ = cb;
4272
3
  p->arg_ = arg;
4273
3
  p->next_ = at_exit_functions_;
4274
3
  at_exit_functions_ = p;
4275
3
}
4276
4277
4278
1401
void EmitBeforeExit(Environment* env) {
4279
2792
  HandleScope handle_scope(env->isolate());
4280
4193
  Context::Scope context_scope(env->context());
4281
1401
  Local<Object> process_object = env->process_object();
4282
1401
  Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
4283
  Local<Value> args[] = {
4284
    FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
4285
2802
    process_object->Get(exit_code)->ToInteger(env->isolate())
4286
5604
  };
4287
1401
  MakeCallback(env, process_object, "emit", arraysize(args), args);
4288
1391
}
4289
4290
4291
1369
int EmitExit(Environment* env) {
4292
  // process.emit('exit')
4293
2737
  HandleScope handle_scope(env->isolate());
4294
4106
  Context::Scope context_scope(env->context());
4295
1369
  Local<Object> process_object = env->process_object();
4296
6845
  process_object->Set(env->exiting_string(), True(env->isolate()));
4297
4298
1369
  Local<String> exitCode = env->exit_code_string();
4299
2738
  int code = process_object->Get(exitCode)->Int32Value();
4300
4301
  Local<Value> args[] = {
4302
    env->exit_string(),
4303
    Integer::New(env->isolate(), code)
4304
5476
  };
4305
4306
1369
  MakeCallback(env, process_object, "emit", arraysize(args), args);
4307
4308
  // Reload exit code, it may be changed by `emit('exit')`
4309
4104
  return process_object->Get(exitCode)->Int32Value();
4310
}
4311
4312
4313
IsolateData* CreateIsolateData(Isolate* isolate, uv_loop_t* loop) {
4314
  return new IsolateData(isolate, loop);
4315
}
4316
4317
4318
void FreeIsolateData(IsolateData* isolate_data) {
4319
  delete isolate_data;
4320
}
4321
4322
4323
Environment* CreateEnvironment(IsolateData* isolate_data,
4324
                               Local<Context> context,
4325
                               int argc,
4326
                               const char* const* argv,
4327
                               int exec_argc,
4328
                               const char* const* exec_argv) {
4329
  Isolate* isolate = context->GetIsolate();
4330
  HandleScope handle_scope(isolate);
4331
  Context::Scope context_scope(context);
4332
  auto env = new Environment(isolate_data, context);
4333
  env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
4334
  return env;
4335
}
4336
4337
4338
void FreeEnvironment(Environment* env) {
4339
  delete env;
4340
}
4341
4342
4343
// Entry point for new node instances, also called directly for the main
4344
// node instance.
4345
1557
static void StartNodeInstance(void* arg) {
4346
1557
  NodeInstanceData* instance_data = static_cast<NodeInstanceData*>(arg);
4347
1557
  Isolate::CreateParams params;
4348
2925
  ArrayBufferAllocator array_buffer_allocator;
4349
1557
  params.array_buffer_allocator = &array_buffer_allocator;
4350
#ifdef NODE_ENABLE_VTUNE_PROFILING
4351
  params.code_event_handler = vTune::GetVtuneCodeEventHandler();
4352
#endif
4353
1557
  Isolate* isolate = Isolate::New(params);
4354
4355
  {
4356
3114
    Mutex::ScopedLock scoped_lock(node_isolate_mutex);
4357
1557
    if (instance_data->is_main()) {
4358
1557
      CHECK_EQ(node_isolate, nullptr);
4359
1557
      node_isolate = isolate;
4360
    }
4361
  }
4362
4363
1557
  if (track_heap_objects) {
4364
    isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
4365
  }
4366
4367
  {
4368
2925
    Locker locker(isolate);
4369
2925
    Isolate::Scope isolate_scope(isolate);
4370
2925
    HandleScope handle_scope(isolate);
4371
    IsolateData isolate_data(isolate, instance_data->event_loop(),
4372
1557
                             array_buffer_allocator.zero_fill_field());
4373
3114
    Local<Context> context = Context::New(isolate);
4374
2925
    Context::Scope context_scope(context);
4375
2925
    Environment env(&isolate_data, context);
4376
4671
    env.Start(instance_data->argc(),
4377
1557
              instance_data->argv(),
4378
              instance_data->exec_argc(),
4379
1557
              instance_data->exec_argv(),
4380
1557
              v8_is_profiling);
4381
4382
    isolate->SetAbortOnUncaughtExceptionCallback(
4383
1557
        ShouldAbortOnUncaughtException);
4384
4385
    // Start debug agent when argv has --debug
4386
1557
    if (instance_data->use_debug_agent())
4387
6
      StartDebug(&env, debug_wait_connect);
4388
4389
    {
4390
3038
      Environment::AsyncCallbackScope callback_scope(&env);
4391
1557
      LoadEnvironment(&env);
4392
    }
4393
4394
2962
    env.set_trace_sync_io(trace_sync_io);
4395
4396
    // Enable debugger
4397
1481
    if (instance_data->use_debug_agent())
4398
5
      EnableDebug(&env);
4399
4400
    {
4401
2850
      SealHandleScope seal(isolate);
4402
      bool more;
4403
      do {
4404
22695
        v8_platform.PumpMessageLoop(isolate);
4405
22695
        more = uv_run(env.event_loop(), UV_RUN_ONCE);
4406
4407
22600
        if (more == false) {
4408
1401
          v8_platform.PumpMessageLoop(isolate);
4409
1401
          EmitBeforeExit(&env);
4410
4411
          // Emit `beforeExit` if the loop became alive either after emitting
4412
          // event, or after running some callbacks.
4413
1391
          more = uv_loop_alive(env.event_loop());
4414
1391
          if (uv_run(env.event_loop(), UV_RUN_NOWAIT) != 0)
4415
8
            more = true;
4416
        }
4417
22583
      } while (more == true);
4418
    }
4419
4420
1369
    env.set_trace_sync_io(false);
4421
4422
1369
    int exit_code = EmitExit(&env);
4423
1368
    if (instance_data->is_main())
4424
      instance_data->set_exit_code(exit_code);
4425
1368
    RunAtExit(&env);
4426
4427
1368
    WaitForInspectorDisconnect(&env);
4428
#if defined(LEAK_SANITIZER)
4429
    __lsan_do_leak_check();
4430
#endif
4431
  }
4432
4433
  {
4434
2736
    Mutex::ScopedLock scoped_lock(node_isolate_mutex);
4435
1368
    if (node_isolate == isolate)
4436
1368
      node_isolate = nullptr;
4437
  }
4438
4439
1368
  CHECK_NE(isolate, nullptr);
4440
1368
  isolate->Dispose();
4441
1368
  isolate = nullptr;
4442
1368
}
4443
4444
1568
int Start(int argc, char** argv) {
4445
1568
  PlatformInit();
4446
4447
1568
  CHECK_GT(argc, 0);
4448
4449
  // Hack around with the argv pointer. Used for process.title = "blah".
4450
1568
  argv = uv_setup_args(argc, argv);
4451
4452
  // This needs to run *before* V8::Initialize().  The const_cast is not
4453
  // optional, in case you're wondering.
4454
  int exec_argc;
4455
  const char** exec_argv;
4456
1568
  Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
4457
4458
#if HAVE_OPENSSL
4459
#ifdef NODE_FIPS_MODE
4460
  // In the case of FIPS builds we should make sure
4461
  // the random source is properly initialized first.
4462
  OPENSSL_init();
4463
#endif  // NODE_FIPS_MODE
4464
  // V8 on Windows doesn't have a good source of entropy. Seed it from
4465
  // OpenSSL's pool.
4466
1557
  V8::SetEntropySource(crypto::EntropySource);
4467
#endif
4468
4469
3114
  v8_platform.Initialize(v8_thread_pool_size);
4470
1557
  V8::Initialize();
4471
4472
1557
  int exit_code = 1;
4473
  {
4474
    NodeInstanceData instance_data(NodeInstanceType::MAIN,
4475
                                   uv_default_loop(),
4476
                                   argc,
4477
                                   const_cast<const char**>(argv),
4478
                                   exec_argc,
4479
                                   exec_argv,
4480
3114
                                   use_debug_agent);
4481
1557
    StartNodeInstance(&instance_data);
4482
1368
    exit_code = instance_data.exit_code();
4483
  }
4484
1368
  V8::Dispose();
4485
4486
1368
  v8_platform.Dispose();
4487
4488
1368
  delete[] exec_argv;
4489
1368
  exec_argv = nullptr;
4490
4491
1368
  return exit_code;
4492
}
4493
4494
4495
4704
}  // namespace node