GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/node.cc Lines: 1240 1568 79.1 %
Date: 2016-09-05 Branches: 572 965 59.3 %

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

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

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

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

13851
  if (zero_fill_field_ || zero_fill_all_buffers)
982
5745
    return calloc(size, 1);
983
  else
984
8106
    return malloc(size);
985
}
986
987
28
static bool DomainHasErrorHandler(const Environment* env,
988
                                  const Local<Object>& domain) {
989
56
  HandleScope scope(env->isolate());
990
991
84
  Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
992
28
  if (!domain_event_listeners_v->IsObject())
993
    return false;
994
995
  Local<Object> domain_event_listeners_o =
996
28
      domain_event_listeners_v.As<Object>();
997
998
  Local<Value> domain_error_listeners_v =
999
56
      domain_event_listeners_o->Get(env->error_string());
1000
1001

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

110
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1611


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

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

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

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

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

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

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

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

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


28
  CHECK(args.Length() == 1 && args[0]->IsString() &&
3355
        "must be called with a single string");
3356
21
  node::Utf8Value message(args.GetIsolate(), args[0]);
3357
7
  PrintErrorString("%s\n", *message);
3358
7
  fflush(stderr);
3359
7
}
3360
3361
3362
1626
void LoadEnvironment(Environment* env) {
3363
3173
  HandleScope handle_scope(env->isolate());
3364
3365
1626
  env->isolate()->SetFatalErrorHandler(node::OnFatalError);
3366
1626
  env->isolate()->AddMessageListener(OnMessage);
3367
3368
1626
  atexit(AtProcessExit);
3369
3370
3173
  TryCatch try_catch(env->isolate());
3371
3372
  // Disable verbose mode to stop FatalException() handler from trying
3373
  // to handle the exception. Errors this early in the start-up phase
3374
  // are not safe to ignore.
3375
1626
  try_catch.SetVerbose(false);
3376
3377
  // Execute the lib/internal/bootstrap_node.js file which was included as a
3378
  // static C string in node_natives.h by node_js2c.
3379
  // 'internal_bootstrap_node_native' is the string containing that source code.
3380
1626
  Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
3381
                                                    "bootstrap_node.js");
3382
1626
  Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3383
1626
  if (try_catch.HasCaught())  {
3384
    ReportException(env, try_catch);
3385
    exit(10);
3386
  }
3387
  // The bootstrap_node.js file returns a function 'f'
3388
1626
  CHECK(f_value->IsFunction());
3389
1626
  Local<Function> f = Local<Function>::Cast(f_value);
3390
3391
  // Now we call 'f' with the 'process' variable that we've built up with
3392
  // all our bindings. Inside bootstrap_node.js we'll take care of
3393
  // assigning things to their places.
3394
3395
  // We start the process this way in order to be more modular. Developers
3396
  // who do not like how bootstrap_node.js setups the module system but do
3397
  // like Node's I/O bindings may want to replace 'f' with their own function.
3398
3399
  // Add a reference to the global object
3400
1626
  Local<Object> global = env->context()->Global();
3401
3402
#if defined HAVE_DTRACE || defined HAVE_ETW
3403
  InitDTrace(env, global);
3404
#endif
3405
3406
#if defined HAVE_LTTNG
3407
  InitLTTNG(env, global);
3408
#endif
3409
3410
#if defined HAVE_PERFCTR
3411
  InitPerfCounters(env, global);
3412
#endif
3413
3414
  // Enable handling of uncaught exceptions
3415
  // (FatalException(), break on uncaught exception in debugger)
3416
  //
3417
  // This is not strictly necessary since it's almost impossible
3418
  // to attach the debugger fast enought to break on exception
3419
  // thrown during process startup.
3420
1626
  try_catch.SetVerbose(true);
3421
3422
1626
  env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3423
3424
  // Expose the global object as a property on itself
3425
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
3426
3252
  global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
3427
3428
3252
  Local<Value> arg = env->process_object();
3429
4878
  f->Call(Null(env->isolate()), 1, &arg);
3430
1547
}
3431
3432
3433
static void PrintHelp();
3434
3435
221
static bool ParseDebugOpt(const char* arg) {
3436
221
  const char* port = nullptr;
3437
3438
221
  if (!strcmp(arg, "--debug")) {
3439
1
    use_debug_agent = true;
3440
220
  } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
3441
4
    use_debug_agent = true;
3442
4
    port = arg + sizeof("--debug=") - 1;
3443
216
  } else if (!strcmp(arg, "--debug-brk")) {
3444
    use_debug_agent = true;
3445
    debug_wait_connect = true;
3446
216
  } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
3447
1
    use_debug_agent = true;
3448
1
    debug_wait_connect = true;
3449
1
    port = arg + sizeof("--debug-brk=") - 1;
3450
215
  } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
3451
    // XXX(bnoordhuis) Misnomer, configures port and listen address.
3452
7
    port = arg + sizeof("--debug-port=") - 1;
3453
#if HAVE_INSPECTOR
3454
  // Specifying both --inspect and --debug means debugging is on, using Chromium
3455
  // inspector.
3456
208
  } else if (!strcmp(arg, "--inspect")) {
3457
    use_debug_agent = true;
3458
    use_inspector = true;
3459
208
  } else if (!strncmp(arg, "--inspect=", sizeof("--inspect=") - 1)) {
3460
    use_debug_agent = true;
3461
    use_inspector = true;
3462
    port = arg + sizeof("--inspect=") - 1;
3463
#else
3464
  } else if (!strncmp(arg, "--inspect", sizeof("--inspect") - 1)) {
3465
    fprintf(stderr,
3466
            "Inspector support is not available with this Node.js build\n");
3467
    return false;
3468
#endif
3469
  } else {
3470
    return false;
3471
  }
3472
3473
13
  if (port == nullptr) {
3474
    return true;
3475
  }
3476
3477
12
  std::string** const the_host = use_inspector ? &inspector_host : &debug_host;
3478
12
  int* const the_port = use_inspector ? &inspector_port : &debug_port;
3479
3480
  // FIXME(bnoordhuis) Move IPv6 address parsing logic to lib/net.js.
3481
  // It seems reasonable to support [address]:port notation
3482
  // in net.Server#listen() and net.Socket#connect().
3483
12
  const size_t port_len = strlen(port);
3484

12
  if (port[0] == '[' && port[port_len - 1] == ']') {
3485
    *the_host = new std::string(port + 1, port_len - 2);
3486
    return true;
3487
  }
3488
3489
12
  const char* const colon = strrchr(port, ':');
3490
12
  if (colon == nullptr) {
3491
    // Either a port number or a host name.  Assume that
3492
    // if it's not all decimal digits, it's a host name.
3493
115
    for (size_t n = 0; port[n] != '\0'; n += 1) {
3494
52
      if (port[n] < '0' || port[n] > '9') {
3495
        *the_host = new std::string(port);
3496
        return true;
3497
      }
3498
    }
3499
  } else {
3500

1
    const bool skip = (colon > port && port[0] == '[' && colon[-1] == ']');
3501
3
    *the_host = new std::string(port + skip, colon - skip);
3502
  }
3503
3504
  char* endptr;
3505
12
  errno = 0;
3506
12
  const char* const digits = colon != nullptr ? colon + 1 : port;
3507
12
  const long result = strtol(digits, &endptr, 10);  // NOLINT(runtime/int)
3508

12
  if (errno != 0 || *endptr != '\0' || result < 1024 || result > 65535) {
3509
    fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
3510
    PrintHelp();
3511
    exit(12);
3512
  }
3513
3514
12
  *the_port = static_cast<int>(result);
3515
3516
12
  return true;
3517
}
3518
3519
static void PrintHelp() {
3520
  // XXX: If you add an option here, please also add it to doc/node.1 and
3521
  // doc/api/cli.md
3522
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
3523
         "       node debug script.js [arguments] \n"
3524
         "\n"
3525
         "Options:\n"
3526
         "  -v, --version         print Node.js version\n"
3527
         "  -e, --eval script     evaluate script\n"
3528
         "  -p, --print           evaluate script and print result\n"
3529
         "  -c, --check           syntax check script without executing\n"
3530
         "  -i, --interactive     always enter the REPL even if stdin\n"
3531
         "                        does not appear to be a terminal\n"
3532
         "  -r, --require         module to preload (option can be repeated)\n"
3533
         "  --no-deprecation      silence deprecation warnings\n"
3534
         "  --trace-deprecation   show stack traces on deprecations\n"
3535
         "  --throw-deprecation   throw an exception anytime a deprecated "
3536
         "function is used\n"
3537
         "  --no-warnings         silence all process warnings\n"
3538
         "  --trace-warnings      show stack traces on process warnings\n"
3539
         "  --trace-sync-io       show stack trace when use of sync IO\n"
3540
         "                        is detected after the first tick\n"
3541
         "  --track-heap-objects  track heap object allocations for heap "
3542
         "snapshots\n"
3543
         "  --prof-process        process v8 profiler output generated\n"
3544
         "                        using --prof\n"
3545
         "  --zero-fill-buffers   automatically zero-fill all newly allocated\n"
3546
         "                        Buffer and SlowBuffer instances\n"
3547
         "  --v8-options          print v8 command line options\n"
3548
         "  --v8-pool-size=num    set v8's thread pool size\n"
3549
#if HAVE_OPENSSL
3550
         "  --tls-cipher-list=val use an alternative default TLS cipher list\n"
3551
#if NODE_FIPS_MODE
3552
         "  --enable-fips         enable FIPS crypto at startup\n"
3553
         "  --force-fips          force FIPS crypto (cannot be disabled)\n"
3554
#endif  /* NODE_FIPS_MODE */
3555
#endif /* HAVE_OPENSSL */
3556
#if defined(NODE_HAVE_I18N_SUPPORT)
3557
         "  --icu-data-dir=dir    set ICU data load path to dir\n"
3558
         "                        (overrides NODE_ICU_DATA)\n"
3559
#if !defined(NODE_HAVE_SMALL_ICU)
3560
         "                        note: linked-in ICU data is\n"
3561
         "                        present.\n"
3562
#endif
3563
         "  --preserve-symlinks   preserve symbolic links when resolving\n"
3564
         "                        and caching modules.\n"
3565
#endif
3566
         "\n"
3567
         "Environment variables:\n"
3568
#ifdef _WIN32
3569
         "NODE_PATH                ';'-separated list of directories\n"
3570
#else
3571
         "NODE_PATH                ':'-separated list of directories\n"
3572
#endif
3573
         "                         prefixed to the module search path.\n"
3574
         "NODE_DISABLE_COLORS      set to 1 to disable colors in the REPL\n"
3575
#if defined(NODE_HAVE_I18N_SUPPORT)
3576
         "NODE_ICU_DATA            data path for ICU (Intl object) data\n"
3577
#if !defined(NODE_HAVE_SMALL_ICU)
3578
         "                         (will extend linked-in data)\n"
3579
#endif
3580
#endif
3581
         "NODE_REPL_HISTORY        path to the persistent REPL history file\n"
3582
         "\n"
3583
         "Documentation can be found at https://nodejs.org/\n");
3584
}
3585
3586
3587
// Parse command line arguments.
3588
//
3589
// argv is modified in place. exec_argv and v8_argv are out arguments that
3590
// ParseArgs() allocates memory for and stores a pointer to the output
3591
// vector in.  The caller should free them with delete[].
3592
//
3593
// On exit:
3594
//
3595
//  * argv contains the arguments with node and V8 options filtered out.
3596
//  * exec_argv contains both node and V8 options and nothing else.
3597
//  * v8_argv contains argv[0] plus any V8 options
3598
1631
static void ParseArgs(int* argc,
3599
                      const char** argv,
3600
                      int* exec_argc,
3601
                      const char*** exec_argv,
3602
                      int* v8_argc,
3603
                      const char*** v8_argv) {
3604
1631
  const unsigned int nargs = static_cast<unsigned int>(*argc);
3605
1631
  const char** new_exec_argv = new const char*[nargs];
3606
1631
  const char** new_v8_argv = new const char*[nargs];
3607
1631
  const char** new_argv = new const char*[nargs];
3608
1631
  const char** local_preload_modules = new const char*[nargs];
3609
3610
5402
  for (unsigned int i = 0; i < nargs; ++i) {
3611
3771
    new_exec_argv[i] = nullptr;
3612
3771
    new_v8_argv[i] = nullptr;
3613
3771
    new_argv[i] = nullptr;
3614
3771
    local_preload_modules[i] = nullptr;
3615
  }
3616
3617
  // exec_argv starts with the first option, the other two start with argv[0].
3618
1631
  unsigned int new_exec_argc = 0;
3619
1631
  unsigned int new_v8_argc = 1;
3620
1631
  unsigned int new_argc = 1;
3621
1631
  new_v8_argv[0] = argv[0];
3622
1631
  new_argv[0] = argv[0];
3623
3624
1631
  unsigned int index = 1;
3625
1631
  bool short_circuit = false;
3626

2067
  while (index < nargs && argv[index][0] == '-' && !short_circuit) {
3627
221
    const char* const arg = argv[index];
3628
221
    unsigned int args_consumed = 1;
3629
3630
221
    if (ParseDebugOpt(arg)) {
3631
      // Done, consumed by ParseDebugOpt().
3632

208
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
3633
2
      printf("%s\n", NODE_VERSION);
3634
2
      exit(0);
3635

206
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3636
      PrintHelp();
3637
      exit(0);
3638

408
    } else if (strcmp(arg, "--eval") == 0 ||
3639
357
               strcmp(arg, "-e") == 0 ||
3640
307
               strcmp(arg, "--print") == 0 ||
3641
295
               strcmp(arg, "-pe") == 0 ||
3642
143
               strcmp(arg, "-p") == 0) {
3643
75
      bool is_eval = strchr(arg, 'e') != nullptr;
3644
75
      bool is_print = strchr(arg, 'p') != nullptr;
3645

75
      print_eval = print_eval || is_print;
3646
      // --eval, -e and -pe always require an argument.
3647
75
      if (is_eval == true) {
3648
60
        args_consumed += 1;
3649
60
        eval_string = argv[index + 1];
3650
60
        if (eval_string == nullptr) {
3651
2
          fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3652
1
          exit(9);
3653
        }
3654

30
      } else if ((index + 1 < nargs) &&
3655
30
                 argv[index + 1] != nullptr &&
3656
15
                 argv[index + 1][0] != '-') {
3657
13
        args_consumed += 1;
3658
13
        eval_string = argv[index + 1];
3659
13
        if (strncmp(eval_string, "\\-", 2) == 0) {
3660
          // Starts with "\\-": escaped expression, drop the backslash.
3661
1
          eval_string += 1;
3662
        }
3663
      }
3664

256
    } else if (strcmp(arg, "--require") == 0 ||
3665
125
               strcmp(arg, "-r") == 0) {
3666
17
      const char* module = argv[index + 1];
3667
17
      if (module == nullptr) {
3668
        fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3669
        exit(9);
3670
      }
3671
17
      args_consumed += 1;
3672
17
      local_preload_modules[preload_module_count++] = module;
3673

114
    } else if (strcmp(arg, "--check") == 0 || strcmp(arg, "-c") == 0) {
3674