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