2 #include "node_buffer.h"
3 #include "node_constants.h"
5 #include "node_http_parser.h"
6 #include "node_javascript.h"
7 #include "node_version.h"
8 #include "node_internals.h"
9 #include "node_revert.h"
11 #if defined HAVE_PERFCTR
12 #include "node_counters.h"
16 #include "node_crypto.h"
19 #if defined(NODE_HAVE_I18N_SUPPORT)
20 #include "node_i18n.h"
23 #if defined HAVE_DTRACE || defined HAVE_ETW
24 #include "node_dtrace.h"
27 #if defined HAVE_LTTNG
28 #include "node_lttng.h"
32 #include "async-wrap.h"
33 #include "async-wrap-inl.h"
36 #include "handle_wrap.h"
38 #include "req-wrap-inl.h"
39 #include "string_bytes.h"
42 #if NODE_USE_V8_PLATFORM
43 #include "libplatform/libplatform.h"
44 #endif // NODE_USE_V8_PLATFORM
46 #include "v8-profiler.h"
49 #ifdef NODE_ENABLE_VTUNE_PROFILING
50 #include "../deps/v8/src/third_party/vtune/v8-vtune.h"
54 #include <limits.h> // PATH_MAX
60 #include <sys/types.h>
65 #if defined(NODE_HAVE_I18N_SUPPORT)
66 #include <unicode/uvernum.h>
69 #if defined(LEAK_SANITIZER)
70 #include <sanitizer/lsan_interface.h>
76 #define getpid GetCurrentProcessId
81 #include <sys/resource.h> // getrlimit, setrlimit
82 #include <unistd.h> // setuid, getuid
85 #if defined(__POSIX__) && !defined(__ANDROID__)
86 #include <pwd.h> // getpwnam()
87 #include <grp.h> // getgrnam()
91 #include <crt_externs.h>
92 #define environ (*_NSGetEnviron())
93 #elif !defined(_MSC_VER)
94 extern char **environ;
98 #include <dlog/dlog.h>
104 using v8::ArrayBuffer;
107 using v8::EscapableHandleScope;
109 using v8::Float64Array;
111 using v8::FunctionCallbackInfo;
112 using v8::HandleScope;
113 using v8::HeapStatistics;
118 using v8::MaybeLocal;
121 using v8::NamedPropertyHandlerConfiguration;
125 using v8::ObjectTemplate;
127 using v8::PromiseRejectMessage;
128 using v8::PropertyCallbackInfo;
129 using v8::PropertyHandlerFlags;
130 using v8::ScriptOrigin;
131 using v8::SealHandleScope;
134 using v8::Uint32Array;
138 bool g_standalone_mode = true;
139 bool g_upstream_node_mode = true;
141 static bool print_eval = false;
142 static bool force_repl = false;
143 static bool syntax_check_only = false;
144 static bool trace_deprecation = false;
145 static bool throw_deprecation = false;
146 static bool trace_sync_io = false;
147 static bool track_heap_objects = false;
148 static const char* eval_string = nullptr;
149 static unsigned int preload_module_count = 0;
150 static const char** preload_modules = nullptr;
152 static bool use_inspector = false;
154 static const bool use_inspector = false;
156 static bool use_debug_agent = false;
157 static bool debug_wait_connect = false;
158 static std::string* debug_host; // coverity[leaked_storage]
159 static const int default_debugger_port = 5858;
160 static const int default_inspector_port = 9229;
161 static int debug_port = -1;
162 static const int v8_default_thread_pool_size = 4;
163 static int v8_thread_pool_size = v8_default_thread_pool_size;
164 static bool prof_process = false;
165 static bool v8_is_profiling = false;
166 static bool node_is_initialized = false;
167 static node_module* modpending;
168 static node_module* modlist_builtin;
169 static node_module* modlist_linked;
170 static node_module* modlist_addon;
172 #if defined(NODE_HAVE_I18N_SUPPORT)
173 // Path to ICU data (for i18n / Intl)
174 static const char* icu_data_dir = nullptr;
177 // used by C++ modules as well
178 bool no_deprecation = false;
182 // used by crypto module
183 bool enable_fips_crypto = false;
184 bool force_fips_crypto = false;
185 # endif // NODE_FIPS_MODE
186 const char* openssl_config = nullptr;
187 #endif // HAVE_OPENSSL
189 // true if process warnings should be suppressed
190 bool no_process_warnings = false;
191 bool trace_warnings = false;
193 // Set in node.cc by ParseArgs when --preserve-symlinks is used.
194 // Used in node_config.cc to set a constant on process.binding('config')
195 // that is used by lib/module.js
196 bool config_preserve_symlinks = false;
198 bool v8_initialized = false;
200 // process-relative uptime base, initialized at start-up
201 static double prog_start_time;
202 static bool debugger_running;
203 static uv_async_t dispatch_debug_messages_async;
205 static Mutex node_isolate_mutex;
206 static v8::Isolate* node_isolate;
209 #if NODE_USE_V8_PLATFORM
210 void Initialize(int thread_pool_size) {
211 platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
212 V8::InitializePlatform(platform_);
215 void PumpMessageLoop(Isolate* isolate) {
216 v8::platform::PumpMessageLoop(platform_, isolate);
224 bool StartInspector(Environment *env, const char* script_path,
225 int port, bool wait) {
227 return env->inspector_agent()->Start(platform_, script_path, port, wait);
230 #endif // HAVE_INSPECTOR
233 v8::Platform* platform_;
234 #else // !NODE_USE_V8_PLATFORM
235 void Initialize(int thread_pool_size) {}
236 void PumpMessageLoop(Isolate* isolate) {}
238 bool StartInspector(Environment *env, const char* script_path,
239 int port, bool wait) {
240 env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
241 return false; // make compiler happy
243 #endif // !NODE_USE_V8_PLATFORM
247 static uv_sem_t debug_semaphore;
248 static const unsigned kMaxSignal = 32;
251 static void PrintErrorString(const char* format, ...) {
253 va_start(ap, format);
255 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
257 // Check if stderr is something other than a tty/console
258 if (stderr_handle == INVALID_HANDLE_VALUE ||
259 stderr_handle == nullptr ||
260 uv_guess_handle(_fileno(stderr)) != UV_TTY) {
261 vfprintf(stderr, format, ap);
266 // Fill in any placeholders
267 int n = _vscprintf(format, ap);
268 std::vector<char> out(n + 1);
269 vsprintf(out.data(), format, ap);
271 // Get required wide buffer size
272 n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
274 std::vector<wchar_t> wbuf(n);
275 MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
277 // Don't include the null character in the output
279 WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
280 #elif defined(OS_TIZEN)
281 dlog_print(DLOG_ERROR, "WRT", "[Node.js ERROR]");
282 dlog_vprint(DLOG_ERROR, "WRT", format, ap);
284 vfprintf(stderr, format, ap);
290 static void CheckImmediate(uv_check_t* handle) {
291 Environment* env = Environment::from_immediate_check_handle(handle);
292 HandleScope scope(env->isolate());
293 Context::Scope context_scope(env->context());
294 MakeCallback(env, env->process_object(), env->immediate_callback_string());
298 static void IdleImmediateDummy(uv_idle_t* handle) {
299 // Do nothing. Only for maintaining event loop.
300 // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
304 static inline const char *errno_string(int errorno) {
305 #define ERRNO_CASE(e) case e: return #e;
312 ERRNO_CASE(EADDRINUSE);
316 ERRNO_CASE(EADDRNOTAVAIL);
320 ERRNO_CASE(EAFNOSUPPORT);
328 # if EAGAIN != EWOULDBLOCK
329 ERRNO_CASE(EWOULDBLOCK);
334 ERRNO_CASE(EALREADY);
350 ERRNO_CASE(ECANCELED);
358 ERRNO_CASE(ECONNABORTED);
362 ERRNO_CASE(ECONNREFUSED);
366 ERRNO_CASE(ECONNRESET);
374 ERRNO_CASE(EDESTADDRREQ);
398 ERRNO_CASE(EHOSTUNREACH);
410 ERRNO_CASE(EINPROGRESS);
446 ERRNO_CASE(EMSGSIZE);
450 ERRNO_CASE(EMULTIHOP);
454 ERRNO_CASE(ENAMETOOLONG);
458 ERRNO_CASE(ENETDOWN);
462 ERRNO_CASE(ENETRESET);
466 ERRNO_CASE(ENETUNREACH);
498 # if ENOLINK != ENOLCK
512 ERRNO_CASE(ENOPROTOOPT);
532 ERRNO_CASE(ENOTCONN);
540 # if ENOTEMPTY != EEXIST
541 ERRNO_CASE(ENOTEMPTY);
546 ERRNO_CASE(ENOTSOCK);
553 ERRNO_CASE(EOPNOTSUPP);
567 ERRNO_CASE(EOVERFLOW);
582 #ifdef EPROTONOSUPPORT
583 ERRNO_CASE(EPROTONOSUPPORT);
587 ERRNO_CASE(EPROTOTYPE);
615 ERRNO_CASE(ETIMEDOUT);
630 const char *signo_string(int signo) {
631 #define SIGNO_CASE(e) case e: return #e;
658 # if SIGABRT != SIGIOT
702 SIGNO_CASE(SIGSTKFLT);
719 SIGNO_CASE(SIGBREAK);
743 SIGNO_CASE(SIGVTALRM);
751 SIGNO_CASE(SIGWINCH);
759 # if SIGPOLL != SIGIO
765 # if SIGLOST != SIGABRT
771 # if SIGPWR != SIGLOST
777 # if !defined(SIGPWR) || SIGINFO != SIGPWR
791 Local<Value> ErrnoException(Isolate* isolate,
796 Environment* env = Environment::GetCurrent(isolate);
799 Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
800 if (msg == nullptr || msg[0] == '\0') {
801 msg = strerror(errorno);
803 Local<String> message = OneByteString(env->isolate(), msg);
806 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
807 cons = String::Concat(cons, message);
809 Local<String> path_string;
810 if (path != nullptr) {
811 // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
812 path_string = String::NewFromUtf8(env->isolate(), path);
815 if (path_string.IsEmpty() == false) {
816 cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
817 cons = String::Concat(cons, path_string);
818 cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
820 e = Exception::Error(cons);
822 Local<Object> obj = e->ToObject(env->isolate());
823 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
824 obj->Set(env->code_string(), estring);
826 if (path_string.IsEmpty() == false) {
827 obj->Set(env->path_string(), path_string);
830 if (syscall != nullptr) {
831 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
838 static Local<String> StringFromPath(Isolate* isolate, const char* path) {
840 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
841 return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
842 String::NewFromUtf8(isolate, path + 8));
843 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
844 return String::NewFromUtf8(isolate, path + 4);
848 return String::NewFromUtf8(isolate, path);
852 Local<Value> UVException(Isolate* isolate,
857 return UVException(isolate, errorno, syscall, msg, path, nullptr);
861 Local<Value> UVException(Isolate* isolate,
867 Environment* env = Environment::GetCurrent(isolate);
870 msg = uv_strerror(errorno);
872 const char* err_name = uv_err_name(errorno);
873 if (err_name == NULL)
874 err_name = "UnknownSystemError";
876 Local<String> js_code = OneByteString(isolate, err_name);
877 Local<String> js_syscall = OneByteString(isolate, syscall);
878 Local<String> js_path;
879 Local<String> js_dest;
881 Local<String> js_msg = js_code;
882 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
883 js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
884 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
885 js_msg = String::Concat(js_msg, js_syscall);
887 if (path != nullptr) {
888 js_path = StringFromPath(isolate, path);
890 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
891 js_msg = String::Concat(js_msg, js_path);
892 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
895 if (dest != nullptr) {
896 js_dest = StringFromPath(isolate, dest);
898 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
899 js_msg = String::Concat(js_msg, js_dest);
900 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
903 Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
905 // TODO(piscisaureus) errno should probably go; the user has no way of
906 // knowing which uv errno value maps to which error.
907 e->Set(env->errno_string(), Integer::New(isolate, errorno));
908 e->Set(env->code_string(), js_code);
909 e->Set(env->syscall_string(), js_syscall);
910 if (!js_path.IsEmpty())
911 e->Set(env->path_string(), js_path);
912 if (!js_dest.IsEmpty())
913 e->Set(env->dest_string(), js_dest);
919 // Look up environment variable unless running as setuid root.
920 inline const char* secure_getenv(const char* key) {
922 if (getuid() != geteuid() || getgid() != getegid())
930 // Does about the same as strerror(),
931 // but supports all windows error messages
932 static const char *winapi_strerror(const int errorno, bool* must_free) {
933 char *errmsg = nullptr;
935 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
936 FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
937 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
942 // Remove trailing newlines
943 for (int i = strlen(errmsg) - 1;
944 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
950 // FormatMessage failed
952 return "Unknown error";
957 Local<Value> WinapiErrnoException(Isolate* isolate,
962 Environment* env = Environment::GetCurrent(isolate);
964 bool must_free = false;
965 if (!msg || !msg[0]) {
966 msg = winapi_strerror(errorno, &must_free);
968 Local<String> message = OneByteString(env->isolate(), msg);
971 Local<String> cons1 =
972 String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
973 Local<String> cons2 =
974 String::Concat(cons1, String::NewFromUtf8(isolate, path));
975 Local<String> cons3 =
976 String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
977 e = Exception::Error(cons3);
979 e = Exception::Error(message);
982 Local<Object> obj = e->ToObject(env->isolate());
983 obj->Set(env->errno_string(), Integer::New(isolate, errorno));
985 if (path != nullptr) {
986 obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
989 if (syscall != nullptr) {
990 obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
994 LocalFree((HLOCAL)msg);
1001 void* ArrayBufferAllocator::Allocate(size_t size) {
1002 if (zero_fill_field_ || zero_fill_all_buffers)
1003 return node::UncheckedCalloc(size);
1005 return node::UncheckedMalloc(size);
1008 static bool DomainHasErrorHandler(const Environment* env,
1009 const Local<Object>& domain) {
1010 HandleScope scope(env->isolate());
1012 Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
1013 if (!domain_event_listeners_v->IsObject())
1016 Local<Object> domain_event_listeners_o =
1017 domain_event_listeners_v.As<Object>();
1019 Local<Value> domain_error_listeners_v =
1020 domain_event_listeners_o->Get(env->error_string());
1022 if (domain_error_listeners_v->IsFunction() ||
1023 (domain_error_listeners_v->IsArray() &&
1024 domain_error_listeners_v.As<Array>()->Length() > 0))
1030 static bool DomainsStackHasErrorHandler(const Environment* env) {
1031 HandleScope scope(env->isolate());
1033 if (!env->using_domains())
1036 Local<Array> domains_stack_array = env->domains_stack_array().As<Array>();
1037 if (domains_stack_array->Length() == 0)
1040 uint32_t domains_stack_length = domains_stack_array->Length();
1041 for (uint32_t i = domains_stack_length; i > 0; --i) {
1042 Local<Value> domain_v = domains_stack_array->Get(i - 1);
1043 if (!domain_v->IsObject())
1046 Local<Object> domain = domain_v.As<Object>();
1047 if (DomainHasErrorHandler(env, domain))
1055 static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
1056 HandleScope scope(isolate);
1058 Environment* env = Environment::GetCurrent(isolate);
1059 Local<Object> process_object = env->process_object();
1060 Local<String> emitting_top_level_domain_error_key =
1061 env->emitting_top_level_domain_error_string();
1062 bool isEmittingTopLevelDomainError =
1063 process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
1065 return isEmittingTopLevelDomainError || !DomainsStackHasErrorHandler(env);
1069 void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
1070 Environment* env = Environment::GetCurrent(args);
1072 if (env->using_domains())
1074 env->set_using_domains(true);
1076 HandleScope scope(env->isolate());
1077 Local<Object> process_object = env->process_object();
1079 Local<String> tick_callback_function_key = env->tick_domain_cb_string();
1080 Local<Function> tick_callback_function =
1081 process_object->Get(tick_callback_function_key).As<Function>();
1083 if (!tick_callback_function->IsFunction()) {
1084 fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
1088 process_object->Set(env->tick_callback_string(), tick_callback_function);
1089 env->set_tick_callback_function(tick_callback_function);
1091 CHECK(args[0]->IsArray());
1092 env->set_domain_array(args[0].As<Array>());
1094 CHECK(args[1]->IsArray());
1095 env->set_domains_stack_array(args[1].As<Array>());
1097 // Do a little housekeeping.
1098 env->process_object()->Delete(
1100 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
1102 uint32_t* const fields = env->domain_flag()->fields();
1103 uint32_t const fields_count = env->domain_flag()->fields_count();
1105 Local<ArrayBuffer> array_buffer =
1106 ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1108 args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1111 void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
1112 args.GetIsolate()->RunMicrotasks();
1116 void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
1117 Environment* env = Environment::GetCurrent(args);
1119 CHECK(args[0]->IsFunction());
1121 env->set_push_values_to_array_function(args[0].As<Function>());
1122 env->process_object()->Delete(
1124 FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
1128 void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
1129 Environment* env = Environment::GetCurrent(args);
1131 CHECK(args[0]->IsFunction());
1132 CHECK(args[1]->IsObject());
1134 env->set_tick_callback_function(args[0].As<Function>());
1136 env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
1138 // Do a little housekeeping.
1139 env->process_object()->Delete(
1141 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust();
1143 // Values use to cross communicate with processNextTick.
1144 uint32_t* const fields = env->tick_info()->fields();
1145 uint32_t const fields_count = env->tick_info()->fields_count();
1147 Local<ArrayBuffer> array_buffer =
1148 ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1150 args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1153 void PromiseRejectCallback(PromiseRejectMessage message) {
1154 Local<Promise> promise = message.GetPromise();
1155 Isolate* isolate = promise->GetIsolate();
1156 Local<Value> value = message.GetValue();
1157 Local<Integer> event = Integer::New(isolate, message.GetEvent());
1159 Environment* env = Environment::GetCurrent(isolate);
1160 Local<Function> callback = env->promise_reject_function();
1162 if (value.IsEmpty())
1163 value = Undefined(isolate);
1165 Local<Value> args[] = { event, promise, value };
1166 Local<Object> process = env->process_object();
1168 callback->Call(process, arraysize(args), args);
1171 void SetupPromises(const FunctionCallbackInfo<Value>& args) {
1172 Environment* env = Environment::GetCurrent(args);
1173 Isolate* isolate = env->isolate();
1175 CHECK(args[0]->IsFunction());
1177 if (g_standalone_mode) { // No indent to minimize diff.
1178 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
1180 env->set_promise_reject_function(args[0].As<Function>());
1182 env->process_object()->Delete(
1184 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupPromises")).FromJust();
1188 Local<Value> MakeCallback(Environment* env,
1190 const Local<Function> callback,
1192 Local<Value> argv[]) {
1193 // If you hit this assertion, you forgot to enter the v8::Context first.
1194 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1196 Local<Function> pre_fn = env->async_hooks_pre_function();
1197 Local<Function> post_fn = env->async_hooks_post_function();
1198 Local<Object> object, domain;
1199 bool ran_init_callback = false;
1200 bool has_domain = false;
1202 Environment::AsyncCallbackScope callback_scope(env);
1204 // TODO(trevnorris): Adding "_asyncQueue" to the "this" in the init callback
1205 // is a horrible way to detect usage. Rethink how detection should happen.
1206 if (recv->IsObject()) {
1207 object = recv.As<Object>();
1208 Local<Value> async_queue_v = object->Get(env->async_queue_string());
1209 if (async_queue_v->IsObject())
1210 ran_init_callback = true;
1213 if (env->using_domains()) {
1214 CHECK(recv->IsObject());
1215 Local<Value> domain_v = object->Get(env->domain_string());
1216 has_domain = domain_v->IsObject();
1218 domain = domain_v.As<Object>();
1219 if (domain->Get(env->disposed_string())->IsTrue())
1220 return Undefined(env->isolate());
1225 Local<Value> enter_v = domain->Get(env->enter_string());
1226 if (enter_v->IsFunction()) {
1227 if (enter_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1228 FatalError("node::MakeCallback",
1229 "domain enter callback threw, please report this");
1234 if (ran_init_callback && !pre_fn.IsEmpty()) {
1235 TryCatch try_catch(env->isolate());
1236 MaybeLocal<Value> ar = pre_fn->Call(env->context(), object, 0, nullptr);
1238 ClearFatalExceptionHandlers(env);
1239 FatalException(env->isolate(), try_catch);
1240 return Local<Value>();
1244 Local<Value> ret = callback->Call(recv, argc, argv);
1246 if (ran_init_callback && !post_fn.IsEmpty()) {
1247 Local<Value> did_throw = Boolean::New(env->isolate(), ret.IsEmpty());
1248 // Currently there's no way to retrieve an uid from node::MakeCallback().
1249 // This needs to be fixed.
1250 Local<Value> vals[] =
1251 { Undefined(env->isolate()).As<Value>(), did_throw };
1252 TryCatch try_catch(env->isolate());
1253 MaybeLocal<Value> ar =
1254 post_fn->Call(env->context(), object, arraysize(vals), vals);
1256 ClearFatalExceptionHandlers(env);
1257 FatalException(env->isolate(), try_catch);
1258 return Local<Value>();
1262 if (ret.IsEmpty()) {
1263 // NOTE: For backwards compatibility with public API we return Undefined()
1264 // if the top level call threw.
1265 return callback_scope.in_makecallback() ?
1266 ret : Undefined(env->isolate()).As<Value>();
1270 Local<Value> exit_v = domain->Get(env->exit_string());
1271 if (exit_v->IsFunction()) {
1272 if (exit_v.As<Function>()->Call(domain, 0, nullptr).IsEmpty()) {
1273 FatalError("node::MakeCallback",
1274 "domain exit callback threw, please report this");
1279 if (callback_scope.in_makecallback()) {
1283 Environment::TickInfo* tick_info = env->tick_info();
1285 if (tick_info->length() == 0) {
1286 env->isolate()->RunMicrotasks();
1289 Local<Object> process = env->process_object();
1291 if (tick_info->length() == 0) {
1292 tick_info->set_index(0);
1296 if (env->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1297 return Undefined(env->isolate());
1304 Local<Value> MakeCallback(Environment* env,
1306 Local<String> symbol,
1308 Local<Value> argv[]) {
1309 Local<Value> cb_v = recv->Get(symbol);
1310 CHECK(cb_v->IsFunction());
1311 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
1315 Local<Value> MakeCallback(Environment* env,
1319 Local<Value> argv[]) {
1320 Local<String> method_string = OneByteString(env->isolate(), method);
1321 return MakeCallback(env, recv, method_string, argc, argv);
1325 Local<Value> MakeCallback(Isolate* isolate,
1329 Local<Value> argv[]) {
1330 EscapableHandleScope handle_scope(isolate);
1331 Local<String> method_string = OneByteString(isolate, method);
1332 return handle_scope.Escape(
1333 MakeCallback(isolate, recv, method_string, argc, argv));
1337 Local<Value> MakeCallback(Isolate* isolate,
1339 Local<String> symbol,
1341 Local<Value> argv[]) {
1342 EscapableHandleScope handle_scope(isolate);
1343 Local<Value> callback_v = recv->Get(symbol);
1344 if (callback_v.IsEmpty()) return Local<Value>();
1345 if (!callback_v->IsFunction()) return Local<Value>();
1346 Local<Function> callback = callback_v.As<Function>();
1347 return handle_scope.Escape(MakeCallback(isolate, recv, callback, argc, argv));
1351 Local<Value> MakeCallback(Isolate* isolate,
1353 Local<Function> callback,
1355 Local<Value> argv[]) {
1356 // Observe the following two subtleties:
1358 // 1. The environment is retrieved from the callback function's context.
1359 // 2. The context to enter is retrieved from the environment.
1361 // Because of the AssignToContext() call in src/node_contextify.cc,
1362 // the two contexts need not be the same.
1363 EscapableHandleScope handle_scope(isolate);
1364 Environment* env = Environment::GetCurrent(callback->CreationContext());
1365 Context::Scope context_scope(env->context());
1366 return handle_scope.Escape(
1367 MakeCallback(env, recv.As<Value>(), callback, argc, argv));
1371 enum encoding ParseEncoding(const char* encoding,
1372 enum encoding default_encoding) {
1373 switch (encoding[0]) {
1376 if (encoding[1] == 't' && encoding[2] == 'f') {
1378 encoding += encoding[3] == '-' ? 4 : 3;
1379 if (encoding[0] == '8' && encoding[1] == '\0')
1381 if (strncmp(encoding, "16le", 4) == 0)
1385 } else if (encoding[1] == 'c' && encoding[2] == 's') {
1386 encoding += encoding[3] == '-' ? 4 : 3;
1387 if (encoding[0] == '2' && encoding[1] == '\0')
1393 if (encoding[1] == 'a') {
1394 if (strncmp(encoding + 2, "tin1", 4) == 0)
1400 if (encoding[1] == 'i') {
1401 if (strncmp(encoding + 2, "nary", 4) == 0)
1405 } else if (encoding[1] == 'u') {
1406 if (strncmp(encoding + 2, "ffer", 4) == 0)
1411 return default_encoding;
1416 if (StringEqualNoCase(encoding, "utf8")) {
1418 } else if (StringEqualNoCase(encoding, "utf-8")) {
1420 } else if (StringEqualNoCase(encoding, "ascii")) {
1422 } else if (StringEqualNoCase(encoding, "base64")) {
1424 } else if (StringEqualNoCase(encoding, "ucs2")) {
1426 } else if (StringEqualNoCase(encoding, "ucs-2")) {
1428 } else if (StringEqualNoCase(encoding, "utf16le")) {
1430 } else if (StringEqualNoCase(encoding, "utf-16le")) {
1432 } else if (StringEqualNoCase(encoding, "latin1")) {
1434 } else if (StringEqualNoCase(encoding, "binary")) {
1435 return LATIN1; // BINARY is a deprecated alias of LATIN1.
1436 } else if (StringEqualNoCase(encoding, "buffer")) {
1438 } else if (StringEqualNoCase(encoding, "hex")) {
1441 return default_encoding;
1446 enum encoding ParseEncoding(Isolate* isolate,
1447 Local<Value> encoding_v,
1448 enum encoding default_encoding) {
1449 if (!encoding_v->IsString())
1450 return default_encoding;
1452 node::Utf8Value encoding(isolate, encoding_v);
1454 return ParseEncoding(*encoding, default_encoding);
1457 Local<Value> Encode(Isolate* isolate,
1460 enum encoding encoding) {
1461 CHECK_NE(encoding, UCS2);
1462 return StringBytes::Encode(isolate, buf, len, encoding);
1465 Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1466 return StringBytes::Encode(isolate, buf, len);
1469 // Returns -1 if the handle was not valid for decoding
1470 ssize_t DecodeBytes(Isolate* isolate,
1472 enum encoding encoding) {
1473 HandleScope scope(isolate);
1475 return StringBytes::Size(isolate, val, encoding);
1478 // Returns number of bytes written.
1479 ssize_t DecodeWrite(Isolate* isolate,
1483 enum encoding encoding) {
1484 return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1487 bool IsExceptionDecorated(Environment* env, Local<Value> er) {
1488 if (!er.IsEmpty() && er->IsObject()) {
1489 Local<Object> err_obj = er.As<Object>();
1491 err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
1492 Local<Value> decorated;
1493 return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
1498 void AppendExceptionLine(Environment* env,
1500 Local<Message> message,
1501 enum ErrorHandlingMode mode) {
1502 if (message.IsEmpty())
1505 HandleScope scope(env->isolate());
1506 Local<Object> err_obj;
1507 if (!er.IsEmpty() && er->IsObject()) {
1508 err_obj = er.As<Object>();
1510 auto context = env->context();
1511 auto processed_private_symbol = env->processed_private_symbol();
1512 // Do it only once per message
1513 if (err_obj->HasPrivate(context, processed_private_symbol).FromJust())
1515 err_obj->SetPrivate(
1517 processed_private_symbol,
1518 True(env->isolate()));
1521 // Print (filename):(line number): (message).
1522 node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1523 const char* filename_string = *filename;
1524 int linenum = message->GetLineNumber();
1525 // Print line of source code.
1526 node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1527 const char* sourceline_string = *sourceline;
1529 // Because of how node modules work, all scripts are wrapped with a
1530 // "function (module, exports, __filename, ...) {"
1531 // to provide script local variables.
1533 // When reporting errors on the first line of a script, this wrapper
1534 // function is leaked to the user. There used to be a hack here to
1535 // truncate off the first 62 characters, but it caused numerous other
1536 // problems when vm.runIn*Context() methods were used for non-module
1539 // If we ever decide to re-instate such a hack, the following steps
1542 // 1. Pass a flag around to say "this code was wrapped"
1543 // 2. Update the stack frame output so that it is also correct.
1545 // It would probably be simpler to add a line rather than add some
1546 // number of characters to the first line, since V8 truncates the
1547 // sourceline to 78 characters, and we end up not providing very much
1548 // useful debugging info to the user if we remove 62 characters.
1550 int start = message->GetStartColumn(env->context()).FromMaybe(0);
1551 int end = message->GetEndColumn(env->context()).FromMaybe(0);
1554 int max_off = sizeof(arrow) - 2;
1556 int off = snprintf(arrow,
1563 if (off > max_off) {
1567 // Print wavy underline (GetUnderline is deprecated).
1568 for (int i = 0; i < start; i++) {
1569 if (sourceline_string[i] == '\0' || off >= max_off) {
1572 CHECK_LT(off, max_off);
1573 arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1575 for (int i = start; i < end; i++) {
1576 if (sourceline_string[i] == '\0' || off >= max_off) {
1579 CHECK_LT(off, max_off);
1582 CHECK_LE(off, max_off);
1584 arrow[off + 1] = '\0';
1586 Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1588 const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
1589 // If allocating arrow_str failed, print it out. There's not much else to do.
1590 // If it's not an error, but something needs to be printed out because
1591 // it's a fatal exception, also print it out from here.
1592 // Otherwise, the arrow property will be attached to the object and handled
1594 if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
1595 if (env->printed_error())
1597 env->set_printed_error(true);
1599 uv_tty_reset_mode();
1600 PrintErrorString("\n%s", arrow);
1604 CHECK(err_obj->SetPrivate(
1606 env->arrow_message_private_symbol(),
1607 arrow_str).FromMaybe(false));
1611 static void ReportException(Environment* env,
1613 Local<Message> message) {
1614 HandleScope scope(env->isolate());
1616 AppendExceptionLine(env, er, message, FATAL_ERROR);
1618 Local<Value> trace_value;
1620 const bool decorated = IsExceptionDecorated(env, er);
1622 if (er->IsUndefined() || er->IsNull()) {
1623 trace_value = Undefined(env->isolate());
1625 Local<Object> err_obj = er->ToObject(env->isolate());
1627 trace_value = err_obj->Get(env->stack_string());
1629 err_obj->GetPrivate(
1631 env->arrow_message_private_symbol()).ToLocalChecked();
1634 node::Utf8Value trace(env->isolate(), trace_value);
1636 // range errors have a trace member set to undefined
1637 if (trace.length() > 0 && !trace_value->IsUndefined()) {
1638 if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1639 PrintErrorString("%s\n", *trace);
1641 node::Utf8Value arrow_string(env->isolate(), arrow);
1642 PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1645 // this really only happens for RangeErrors, since they're the only
1646 // kind that won't have all this info in the trace, or when non-Error
1647 // objects are thrown manually.
1648 Local<Value> message;
1651 if (er->IsObject()) {
1652 Local<Object> err_obj = er.As<Object>();
1653 message = err_obj->Get(env->message_string());
1654 name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1657 if (message.IsEmpty() ||
1658 message->IsUndefined() ||
1660 name->IsUndefined()) {
1661 // Not an error object. Just print as-is.
1662 String::Utf8Value message(er);
1664 PrintErrorString("%s\n", *message ? *message :
1665 "<toString() threw exception>");
1667 node::Utf8Value name_string(env->isolate(), name);
1668 node::Utf8Value message_string(env->isolate(), message);
1670 if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
1671 PrintErrorString("%s: %s\n", *name_string, *message_string);
1673 node::Utf8Value arrow_string(env->isolate(), arrow);
1674 PrintErrorString("%s\n%s: %s\n",
1686 static void ReportException(Environment* env, const TryCatch& try_catch) {
1687 ReportException(env, try_catch.Exception(), try_catch.Message());
1691 // Executes a str within the current v8 context.
1692 static Local<Value> ExecuteString(Environment* env,
1693 Local<String> source,
1694 Local<String> filename) {
1695 EscapableHandleScope scope(env->isolate());
1696 TryCatch try_catch(env->isolate());
1698 // try_catch must be nonverbose to disable FatalException() handler,
1699 // we will handle exceptions ourself.
1700 try_catch.SetVerbose(false);
1702 ScriptOrigin origin(filename);
1703 MaybeLocal<v8::Script> script =
1704 v8::Script::Compile(env->context(), source, &origin);
1705 if (script.IsEmpty()) {
1706 ReportException(env, try_catch);
1710 Local<Value> result = script.ToLocalChecked()->Run();
1711 if (result.IsEmpty()) {
1712 ReportException(env, try_catch);
1716 return scope.Escape(result);
1720 static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1721 Environment* env = Environment::GetCurrent(args);
1723 Local<Array> ary = Array::New(args.GetIsolate());
1724 Local<Context> ctx = env->context();
1725 Local<Function> fn = env->push_values_to_array_function();
1726 Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1729 for (auto w : *env->req_wrap_queue()) {
1730 if (w->persistent().IsEmpty())
1732 argv[idx] = w->object();
1733 if (++idx >= arraysize(argv)) {
1734 fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1740 fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1743 args.GetReturnValue().Set(ary);
1747 // Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1748 // implemented here for consistency with GetActiveRequests().
1749 void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1750 Environment* env = Environment::GetCurrent(args);
1752 Local<Array> ary = Array::New(env->isolate());
1753 Local<Context> ctx = env->context();
1754 Local<Function> fn = env->push_values_to_array_function();
1755 Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
1758 Local<String> owner_sym = env->owner_string();
1760 for (auto w : *env->handle_wrap_queue()) {
1761 if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
1763 Local<Object> object = w->object();
1764 Local<Value> owner = object->Get(owner_sym);
1765 if (owner->IsUndefined())
1768 if (++idx >= arraysize(argv)) {
1769 fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1774 fn->Call(ctx, ary, idx, argv).ToLocalChecked();
1777 args.GetReturnValue().Set(ary);
1781 NO_RETURN void Abort() {
1782 DumpBacktrace(stderr);
1784 ABORT_NO_BACKTRACE();
1788 NO_RETURN void Assert(const char* const (*args)[4]) {
1789 auto filename = (*args)[0];
1790 auto linenum = (*args)[1];
1791 auto message = (*args)[2];
1792 auto function = (*args)[3];
1795 size_t exepath_size = sizeof(exepath);
1796 if (uv_exepath(exepath, &exepath_size))
1797 snprintf(exepath, sizeof(exepath), "node");
1801 snprintf(pid, sizeof(pid), "[%u]", getpid());
1804 fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
1805 exepath, pid, filename, linenum,
1806 function, *function ? ":" : "", message);
1813 static void Abort(const FunctionCallbackInfo<Value>& args) {
1818 static void Chdir(const FunctionCallbackInfo<Value>& args) {
1819 Environment* env = Environment::GetCurrent(args);
1821 if (args.Length() != 1 || !args[0]->IsString()) {
1822 return env->ThrowTypeError("Bad argument.");
1825 node::Utf8Value path(args.GetIsolate(), args[0]);
1826 int err = uv_chdir(*path);
1828 return env->ThrowUVException(err, "uv_chdir");
1833 static void Cwd(const FunctionCallbackInfo<Value>& args) {
1834 Environment* env = Environment::GetCurrent(args);
1836 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1837 char buf[MAX_PATH * 4];
1842 size_t cwd_len = sizeof(buf);
1843 int err = uv_cwd(buf, &cwd_len);
1845 return env->ThrowUVException(err, "uv_cwd");
1848 Local<String> cwd = String::NewFromUtf8(env->isolate(),
1850 String::kNormalString,
1852 args.GetReturnValue().Set(cwd);
1856 static void Umask(const FunctionCallbackInfo<Value>& args) {
1857 Environment* env = Environment::GetCurrent(args);
1860 if (args.Length() < 1 || args[0]->IsUndefined()) {
1862 umask(static_cast<mode_t>(old));
1863 } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1864 return env->ThrowTypeError("argument must be an integer or octal string.");
1867 if (args[0]->IsInt32()) {
1868 oct = args[0]->Uint32Value();
1871 node::Utf8Value str(env->isolate(), args[0]);
1873 // Parse the octal string.
1874 for (size_t i = 0; i < str.length(); i++) {
1876 if (c > '7' || c < '0') {
1877 return env->ThrowTypeError("invalid octal string");
1883 old = umask(static_cast<mode_t>(oct));
1886 args.GetReturnValue().Set(old);
1890 #if defined(__POSIX__) && !defined(__ANDROID__)
1892 static const uid_t uid_not_found = static_cast<uid_t>(-1);
1893 static const gid_t gid_not_found = static_cast<gid_t>(-1);
1896 static uid_t uid_by_name(const char* name) {
1904 if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1908 return uid_not_found;
1912 static char* name_by_uid(uid_t uid) {
1921 if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1923 return strdup(pp->pw_name);
1934 static gid_t gid_by_name(const char* name) {
1942 if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1946 return gid_not_found;
1950 #if 0 // For future use.
1951 static const char* name_by_gid(gid_t gid) {
1960 if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1962 return strdup(pp->gr_name);
1974 static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1975 if (value->IsUint32()) {
1976 return static_cast<uid_t>(value->Uint32Value());
1978 node::Utf8Value name(isolate, value);
1979 return uid_by_name(*name);
1984 static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1985 if (value->IsUint32()) {
1986 return static_cast<gid_t>(value->Uint32Value());
1988 node::Utf8Value name(isolate, value);
1989 return gid_by_name(*name);
1993 static void GetUid(const FunctionCallbackInfo<Value>& args) {
1994 // uid_t is an uint32_t on all supported platforms.
1995 args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1999 static void GetGid(const FunctionCallbackInfo<Value>& args) {
2000 // gid_t is an uint32_t on all supported platforms.
2001 args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
2005 static void GetEUid(const FunctionCallbackInfo<Value>& args) {
2006 // uid_t is an uint32_t on all supported platforms.
2007 args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
2011 static void GetEGid(const FunctionCallbackInfo<Value>& args) {
2012 // gid_t is an uint32_t on all supported platforms.
2013 args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
2017 static void SetGid(const FunctionCallbackInfo<Value>& args) {
2018 Environment* env = Environment::GetCurrent(args);
2020 if (!args[0]->IsUint32() && !args[0]->IsString()) {
2021 return env->ThrowTypeError("setgid argument must be a number or a string");
2024 gid_t gid = gid_by_name(env->isolate(), args[0]);
2026 if (gid == gid_not_found) {
2027 return env->ThrowError("setgid group id does not exist");
2031 return env->ThrowErrnoException(errno, "setgid");
2036 static void SetEGid(const FunctionCallbackInfo<Value>& args) {
2037 Environment* env = Environment::GetCurrent(args);
2039 if (!args[0]->IsUint32() && !args[0]->IsString()) {
2040 return env->ThrowTypeError("setegid argument must be a number or string");
2043 gid_t gid = gid_by_name(env->isolate(), args[0]);
2045 if (gid == gid_not_found) {
2046 return env->ThrowError("setegid group id does not exist");
2050 return env->ThrowErrnoException(errno, "setegid");
2055 static void SetUid(const FunctionCallbackInfo<Value>& args) {
2056 Environment* env = Environment::GetCurrent(args);
2058 if (!args[0]->IsUint32() && !args[0]->IsString()) {
2059 return env->ThrowTypeError("setuid argument must be a number or a string");
2062 uid_t uid = uid_by_name(env->isolate(), args[0]);
2064 if (uid == uid_not_found) {
2065 return env->ThrowError("setuid user id does not exist");
2069 return env->ThrowErrnoException(errno, "setuid");
2074 static void SetEUid(const FunctionCallbackInfo<Value>& args) {
2075 Environment* env = Environment::GetCurrent(args);
2077 if (!args[0]->IsUint32() && !args[0]->IsString()) {
2078 return env->ThrowTypeError("seteuid argument must be a number or string");
2081 uid_t uid = uid_by_name(env->isolate(), args[0]);
2083 if (uid == uid_not_found) {
2084 return env->ThrowError("seteuid user id does not exist");
2088 return env->ThrowErrnoException(errno, "seteuid");
2093 static void GetGroups(const FunctionCallbackInfo<Value>& args) {
2094 Environment* env = Environment::GetCurrent(args);
2096 int ngroups = getgroups(0, nullptr);
2098 if (ngroups == -1) {
2099 return env->ThrowErrnoException(errno, "getgroups");
2102 gid_t* groups = new gid_t[ngroups];
2104 ngroups = getgroups(ngroups, groups);
2106 if (ngroups == -1) {
2108 return env->ThrowErrnoException(errno, "getgroups");
2111 Local<Array> groups_list = Array::New(env->isolate(), ngroups);
2112 bool seen_egid = false;
2113 gid_t egid = getegid();
2115 for (int i = 0; i < ngroups; i++) {
2116 groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
2117 if (groups[i] == egid)
2123 if (seen_egid == false) {
2124 groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
2127 args.GetReturnValue().Set(groups_list);
2131 static void SetGroups(const FunctionCallbackInfo<Value>& args) {
2132 Environment* env = Environment::GetCurrent(args);
2134 if (!args[0]->IsArray()) {
2135 return env->ThrowTypeError("argument 1 must be an array");
2138 Local<Array> groups_list = args[0].As<Array>();
2139 size_t size = groups_list->Length();
2140 gid_t* groups = new gid_t[size];
2142 for (size_t i = 0; i < size; i++) {
2143 gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
2145 if (gid == gid_not_found) {
2147 return env->ThrowError("group name not found");
2153 int rc = setgroups(size, groups);
2157 return env->ThrowErrnoException(errno, "setgroups");
2162 static void InitGroups(const FunctionCallbackInfo<Value>& args) {
2163 Environment* env = Environment::GetCurrent(args);
2165 if (!args[0]->IsUint32() && !args[0]->IsString()) {
2166 return env->ThrowTypeError("argument 1 must be a number or a string");
2169 if (!args[1]->IsUint32() && !args[1]->IsString()) {
2170 return env->ThrowTypeError("argument 2 must be a number or a string");
2173 node::Utf8Value arg0(env->isolate(), args[0]);
2178 if (args[0]->IsUint32()) {
2179 user = name_by_uid(args[0]->Uint32Value());
2186 if (user == nullptr) {
2187 return env->ThrowError("initgroups user not found");
2190 extra_group = gid_by_name(env->isolate(), args[1]);
2192 if (extra_group == gid_not_found) {
2195 return env->ThrowError("initgroups extra group not found");
2198 int rc = initgroups(user, extra_group);
2205 return env->ThrowErrnoException(errno, "initgroups");
2209 #endif // __POSIX__ && !defined(__ANDROID__)
2212 static void WaitForInspectorDisconnect(Environment* env) {
2214 if (env->inspector_agent()->IsConnected()) {
2215 // Restore signal dispositions, the app is done and is no longer
2216 // capable of handling signals.
2218 struct sigaction act;
2219 memset(&act, 0, sizeof(act));
2220 for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
2221 if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
2223 act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
2224 CHECK_EQ(0, sigaction(nr, &act, nullptr));
2227 env->inspector_agent()->WaitForDisconnect();
2233 void Exit(const FunctionCallbackInfo<Value>& args) {
2234 WaitForInspectorDisconnect(Environment::GetCurrent(args));
2235 exit(args[0]->Int32Value());
2239 static void Uptime(const FunctionCallbackInfo<Value>& args) {
2240 Environment* env = Environment::GetCurrent(args);
2243 uv_update_time(env->event_loop());
2244 uptime = uv_now(env->event_loop()) - prog_start_time;
2246 args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2250 void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2251 Environment* env = Environment::GetCurrent(args);
2254 int err = uv_resident_set_memory(&rss);
2256 return env->ThrowUVException(err, "uv_resident_set_memory");
2260 HeapStatistics v8_heap_stats;
2261 env->isolate()->GetHeapStatistics(&v8_heap_stats);
2263 Local<Number> heap_total =
2264 Number::New(env->isolate(), v8_heap_stats.total_heap_size());
2265 Local<Number> heap_used =
2266 Number::New(env->isolate(), v8_heap_stats.used_heap_size());
2267 Local<Number> external_mem =
2268 Number::New(env->isolate(),
2269 env->isolate()->AdjustAmountOfExternalAllocatedMemory(0));
2271 Local<Object> info = Object::New(env->isolate());
2272 info->Set(env->rss_string(), Number::New(env->isolate(), rss));
2273 info->Set(env->heap_total_string(), heap_total);
2274 info->Set(env->heap_used_string(), heap_used);
2275 info->Set(env->external_string(), external_mem);
2277 args.GetReturnValue().Set(info);
2281 void Kill(const FunctionCallbackInfo<Value>& args) {
2282 Environment* env = Environment::GetCurrent(args);
2284 if (args.Length() != 2) {
2285 return env->ThrowError("Bad argument.");
2288 int pid = args[0]->Int32Value();
2289 int sig = args[1]->Int32Value();
2290 int err = uv_kill(pid, sig);
2291 args.GetReturnValue().Set(err);
2294 // used in Hrtime() below
2295 #define NANOS_PER_SEC 1000000000
2297 // Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2298 // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2299 // so this function instead returns an Array with 2 entries representing seconds
2300 // and nanoseconds, to avoid any integer overflow possibility.
2301 // Pass in an Array from a previous hrtime() call to instead get a time diff.
2302 void Hrtime(const FunctionCallbackInfo<Value>& args) {
2303 uint64_t t = uv_hrtime();
2305 Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
2306 uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
2308 // These three indices will contain the values for the hrtime tuple. The
2309 // seconds value is broken into the upper/lower 32 bits and stored in two
2310 // uint32 fields to be converted back in JS.
2311 fields[0] = (t / NANOS_PER_SEC) >> 32;
2312 fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
2313 fields[2] = t % NANOS_PER_SEC;
2316 // Microseconds in a second, as a float, used in CPUUsage() below
2317 #define MICROS_PER_SEC 1e6
2319 // CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
2320 // to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
2321 // which are uv_timeval_t structs (long tv_sec, long tv_usec).
2322 // Returns those values as Float64 microseconds in the elements of the array
2323 // passed to the function.
2324 void CPUUsage(const FunctionCallbackInfo<Value>& args) {
2327 // Call libuv to get the values we'll return.
2328 int err = uv_getrusage(&rusage);
2330 // On error, return the strerror version of the error code.
2331 Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
2332 args.GetReturnValue().Set(errmsg);
2336 // Get the double array pointer from the Float64Array argument.
2337 CHECK(args[0]->IsFloat64Array());
2338 Local<Float64Array> array = args[0].As<Float64Array>();
2339 CHECK_EQ(array->Length(), 2);
2340 Local<ArrayBuffer> ab = array->Buffer();
2341 double* fields = static_cast<double*>(ab->GetContents().Data());
2343 // Set the Float64Array elements to be user / system values in microseconds.
2344 fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
2345 fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
2348 extern "C" void node_module_register(void* m) {
2349 struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2351 if (mp->nm_flags & NM_F_BUILTIN) {
2352 mp->nm_link = modlist_builtin;
2353 modlist_builtin = mp;
2354 } else if (!node_is_initialized) {
2355 // "Linked" modules are included as part of the node project.
2356 // Like builtins they are registered *before* node::Init runs.
2357 mp->nm_flags = NM_F_LINKED;
2358 mp->nm_link = modlist_linked;
2359 modlist_linked = mp;
2365 struct node_module* get_builtin_module(const char* name) {
2366 struct node_module* mp;
2368 for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
2369 if (strcmp(mp->nm_modname, name) == 0)
2373 CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
2377 struct node_module* get_linked_module(const char* name) {
2378 struct node_module* mp;
2380 for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
2381 if (strcmp(mp->nm_modname, name) == 0)
2385 CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
2389 typedef void (UV_DYNAMIC* extInit)(Local<Object> exports);
2391 // DLOpen is process.dlopen(module, filename).
2392 // Used to load 'module.node' dynamically shared objects.
2394 // FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2395 // when two contexts try to load the same shared object. Maybe have a shadow
2396 // cache that's a plain C list or hash table that's shared across contexts?
2397 void DLOpen(const FunctionCallbackInfo<Value>& args) {
2398 Environment* env = Environment::GetCurrent(args);
2401 CHECK_EQ(modpending, nullptr);
2403 if (args.Length() != 2) {
2404 env->ThrowError("process.dlopen takes exactly 2 arguments.");
2408 Local<Object> module = args[0]->ToObject(env->isolate()); // Cast
2409 node::Utf8Value filename(env->isolate(), args[1]); // Cast
2410 const bool is_dlopen_error = uv_dlopen(*filename, &lib);
2412 // Objects containing v14 or later modules will have registered themselves
2413 // on the pending list. Activate all of them now. At present, only one
2414 // module per object is supported.
2415 node_module* const mp = modpending;
2416 modpending = nullptr;
2418 if (is_dlopen_error) {
2419 Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
2422 // Windows needs to add the filename into the error message
2423 errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
2425 env->isolate()->ThrowException(Exception::Error(errmsg));
2429 if (mp == nullptr) {
2431 env->ThrowError("Module did not self-register.");
2434 if (mp->nm_version != NODE_MODULE_VERSION) {
2439 "\nwas compiled against a different Node.js version using"
2440 "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
2441 "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
2442 "re-installing\nthe module (for instance, using `npm rebuild` or"
2444 *filename, mp->nm_version, NODE_MODULE_VERSION);
2446 // NOTE: `mp` is allocated inside of the shared library's memory, calling
2447 // `uv_dlclose` will deallocate it
2449 env->ThrowError(errmsg);
2452 if (mp->nm_flags & NM_F_BUILTIN) {
2454 env->ThrowError("Built-in module self-registered.");
2458 mp->nm_dso_handle = lib.handle;
2459 mp->nm_link = modlist_addon;
2462 Local<String> exports_string = env->exports_string();
2463 Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
2465 if (mp->nm_context_register_func != nullptr) {
2466 mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2467 } else if (mp->nm_register_func != nullptr) {
2468 mp->nm_register_func(exports, module, mp->nm_priv);
2471 env->ThrowError("Module has no declared entry point.");
2475 // Tell coverity that 'handle' should not be freed when we return.
2476 // coverity[leaked_storage]
2480 static void OnFatalError(const char* location, const char* message) {
2482 PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2484 PrintErrorString("FATAL ERROR: %s\n", message);
2491 NO_RETURN void FatalError(const char* location, const char* message) {
2492 OnFatalError(location, message);
2493 // to suppress compiler warning
2498 void FatalException(Isolate* isolate,
2500 Local<Message> message) {
2501 HandleScope scope(isolate);
2503 Environment* env = Environment::GetCurrent(isolate);
2504 Local<Object> process_object = env->process_object();
2505 Local<String> fatal_exception_string = env->fatal_exception_string();
2506 Local<Function> fatal_exception_function =
2507 process_object->Get(fatal_exception_string).As<Function>();
2510 if (!fatal_exception_function->IsFunction()) {
2511 // failed before the process._fatalException function was added!
2512 // this is probably pretty bad. Nothing to do but report and exit.
2513 ReportException(env, error, message);
2517 if (exit_code == 0) {
2518 TryCatch fatal_try_catch(isolate);
2520 // Do not call FatalException when _fatalException handler throws
2521 fatal_try_catch.SetVerbose(false);
2523 // this will return true if the JS layer handled it, false otherwise
2524 Local<Value> caught =
2525 fatal_exception_function->Call(process_object, 1, &error);
2527 if (fatal_try_catch.HasCaught()) {
2528 // the fatal exception function threw, so we must exit
2529 ReportException(env, fatal_try_catch);
2533 if (exit_code == 0 && false == caught->BooleanValue()) {
2534 ReportException(env, error, message);
2541 if (use_inspector) {
2542 env->inspector_agent()->FatalException(error, message);
2550 void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2551 HandleScope scope(isolate);
2552 // TODO(bajtos) do not call FatalException if try_catch is verbose
2553 // (requires V8 API to expose getter for try_catch.is_verbose_)
2554 FatalException(isolate, try_catch.Exception(), try_catch.Message());
2558 void OnMessage(Local<Message> message, Local<Value> error) {
2559 // The current version of V8 sends messages for errors only
2560 // (thus `error` is always set).
2561 FatalException(Isolate::GetCurrent(), error, message);
2565 void ClearFatalExceptionHandlers(Environment* env) {
2566 Local<Object> process = env->process_object();
2567 Local<Value> events =
2568 process->Get(env->context(), env->events_string()).ToLocalChecked();
2570 if (events->IsObject()) {
2571 events.As<Object>()->Set(
2573 OneByteString(env->isolate(), "uncaughtException"),
2574 Undefined(env->isolate())).FromJust();
2579 env->domain_string(),
2580 Undefined(env->isolate())).FromJust();
2583 // Call process.emitWarning(str), fmt is a snprintf() format string
2584 void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
2589 vsnprintf(warning, sizeof(warning), fmt, ap);
2592 HandleScope handle_scope(env->isolate());
2593 Context::Scope context_scope(env->context());
2595 Local<Object> process = env->process_object();
2596 MaybeLocal<Value> emit_warning = process->Get(env->context(),
2597 FIXED_ONE_BYTE_STRING(env->isolate(), "emitWarning"));
2598 Local<Value> arg = node::OneByteString(env->isolate(), warning);
2602 if (!emit_warning.ToLocal(&f)) return;
2603 if (!f->IsFunction()) return;
2605 // MakeCallback() unneeded, because emitWarning is internal code, it calls
2606 // process.emit('warning', ..), but does so on the nextTick.
2607 f.As<v8::Function>()->Call(process, 1, &arg);
2611 static void Binding(const FunctionCallbackInfo<Value>& args) {
2612 Environment* env = Environment::GetCurrent(args);
2614 Local<String> module = args[0]->ToString(env->isolate());
2615 node::Utf8Value module_v(env->isolate(), module);
2617 Local<Object> cache = env->binding_cache_object();
2618 Local<Object> exports;
2620 if (cache->Has(env->context(), module).FromJust()) {
2621 exports = cache->Get(module)->ToObject(env->isolate());
2622 args.GetReturnValue().Set(exports);
2626 // Append a string to process.moduleLoadList
2628 snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2630 Local<Array> modules = env->module_load_list_array();
2631 uint32_t l = modules->Length();
2632 modules->Set(l, OneByteString(env->isolate(), buf));
2634 node_module* mod = get_builtin_module(*module_v);
2635 if (mod != nullptr) {
2636 exports = Object::New(env->isolate());
2637 // Internal bindings don't have a "module" object, only exports.
2638 CHECK_EQ(mod->nm_register_func, nullptr);
2639 CHECK_NE(mod->nm_context_register_func, nullptr);
2640 Local<Value> unused = Undefined(env->isolate());
2641 mod->nm_context_register_func(exports, unused,
2642 env->context(), mod->nm_priv);
2643 cache->Set(module, exports);
2644 } else if (!strcmp(*module_v, "constants")) {
2645 exports = Object::New(env->isolate());
2646 DefineConstants(env->isolate(), exports);
2647 cache->Set(module, exports);
2648 } else if (!strcmp(*module_v, "natives")) {
2649 exports = Object::New(env->isolate());
2650 DefineJavaScript(env, exports);
2651 cache->Set(module, exports);
2656 "No such module: %s",
2658 return env->ThrowError(errmsg);
2661 args.GetReturnValue().Set(exports);
2664 static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2665 Environment* env = Environment::GetCurrent(args.GetIsolate());
2667 Local<String> module_name = args[0]->ToString(env->isolate());
2669 Local<Object> cache = env->binding_cache_object();
2670 Local<Value> exports_v = cache->Get(module_name);
2672 if (exports_v->IsObject())
2673 return args.GetReturnValue().Set(exports_v.As<Object>());
2675 node::Utf8Value module_name_v(env->isolate(), module_name);
2676 node_module* mod = get_linked_module(*module_name_v);
2678 if (mod == nullptr) {
2682 "No such module was linked: %s",
2684 return env->ThrowError(errmsg);
2687 Local<Object> module = Object::New(env->isolate());
2688 Local<Object> exports = Object::New(env->isolate());
2689 Local<String> exports_prop = String::NewFromUtf8(env->isolate(), "exports");
2690 module->Set(exports_prop, exports);
2692 if (mod->nm_context_register_func != nullptr) {
2693 mod->nm_context_register_func(exports,
2697 } else if (mod->nm_register_func != nullptr) {
2698 mod->nm_register_func(exports, module, mod->nm_priv);
2700 return env->ThrowError("Linked module has no declared entry point.");
2703 auto effective_exports = module->Get(exports_prop);
2704 cache->Set(module_name, effective_exports);
2706 args.GetReturnValue().Set(effective_exports);
2709 static void ProcessTitleGetter(Local<Name> property,
2710 const PropertyCallbackInfo<Value>& info) {
2712 uv_get_process_title(buffer, sizeof(buffer));
2713 info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer));
2717 static void ProcessTitleSetter(Local<Name> property,
2719 const PropertyCallbackInfo<void>& info) {
2720 node::Utf8Value title(info.GetIsolate(), value);
2721 // TODO(piscisaureus): protect with a lock
2722 uv_set_process_title(*title);
2726 static void EnvGetter(Local<Name> property,
2727 const PropertyCallbackInfo<Value>& info) {
2728 Isolate* isolate = info.GetIsolate();
2730 node::Utf8Value key(isolate, property);
2731 const char* val = getenv(*key);
2733 return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
2736 String::Value key(property);
2737 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
2738 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2741 // If result >= sizeof buffer the buffer was too small. That should never
2742 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2744 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2745 result < arraysize(buffer)) {
2746 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2747 Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
2748 return info.GetReturnValue().Set(rc);
2754 static void EnvSetter(Local<Name> property,
2756 const PropertyCallbackInfo<Value>& info) {
2758 node::Utf8Value key(info.GetIsolate(), property);
2759 node::Utf8Value val(info.GetIsolate(), value);
2760 setenv(*key, *val, 1);
2762 String::Value key(property);
2763 String::Value val(value);
2764 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2765 // Environment variables that start with '=' are read-only.
2766 if (key_ptr[0] != L'=') {
2767 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2770 // Whether it worked or not, always return value.
2771 info.GetReturnValue().Set(value);
2775 static void EnvQuery(Local<Name> property,
2776 const PropertyCallbackInfo<Integer>& info) {
2777 int32_t rc = -1; // Not found unless proven otherwise.
2779 node::Utf8Value key(info.GetIsolate(), property);
2783 String::Value key(property);
2784 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2785 if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
2786 GetLastError() == ERROR_SUCCESS) {
2788 if (key_ptr[0] == L'=') {
2789 // Environment variables that start with '=' are hidden and read-only.
2790 rc = static_cast<int32_t>(v8::ReadOnly) |
2791 static_cast<int32_t>(v8::DontDelete) |
2792 static_cast<int32_t>(v8::DontEnum);
2797 info.GetReturnValue().Set(rc);
2801 static void EnvDeleter(Local<Name> property,
2802 const PropertyCallbackInfo<Boolean>& info) {
2804 node::Utf8Value key(info.GetIsolate(), property);
2807 String::Value key(property);
2808 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2809 SetEnvironmentVariableW(key_ptr, nullptr);
2812 // process.env never has non-configurable properties, so always
2813 // return true like the tc39 delete operator.
2814 info.GetReturnValue().Set(true);
2818 static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2819 Environment* env = Environment::GetCurrent(info);
2820 Isolate* isolate = env->isolate();
2821 Local<Context> ctx = env->context();
2822 Local<Function> fn = env->push_values_to_array_function();
2823 Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
2828 while (environ[size])
2831 Local<Array> envarr = Array::New(isolate);
2833 for (int i = 0; i < size; ++i) {
2834 const char* var = environ[i];
2835 const char* s = strchr(var, '=');
2836 const int length = s ? s - var : strlen(var);
2837 argv[idx] = String::NewFromUtf8(isolate,
2839 String::kNormalString,
2841 if (++idx >= arraysize(argv)) {
2842 fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2847 fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2850 WCHAR* environment = GetEnvironmentStringsW();
2851 if (environment == nullptr)
2852 return; // This should not happen.
2853 Local<Array> envarr = Array::New(isolate);
2854 WCHAR* p = environment;
2858 // If the key starts with '=' it is a hidden environment variable.
2862 s = wcschr(p, L'=');
2867 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2868 const size_t two_byte_buffer_len = s - p;
2869 argv[idx] = String::NewFromTwoByte(isolate,
2871 String::kNormalString,
2872 two_byte_buffer_len);
2873 if (++idx >= arraysize(argv)) {
2874 fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2877 p = s + wcslen(s) + 1;
2880 fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
2882 FreeEnvironmentStringsW(environment);
2885 info.GetReturnValue().Set(envarr);
2889 static Local<Object> GetFeatures(Environment* env) {
2890 EscapableHandleScope scope(env->isolate());
2892 Local<Object> obj = Object::New(env->isolate());
2893 #if defined(DEBUG) && DEBUG
2894 Local<Value> debug = True(env->isolate());
2896 Local<Value> debug = False(env->isolate());
2897 #endif // defined(DEBUG) && DEBUG
2899 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "debug"), debug);
2900 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "uv"), True(env->isolate()));
2901 // TODO(bnoordhuis) ping libuv
2902 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "ipv6"), True(env->isolate()));
2904 #ifdef OPENSSL_NPN_NEGOTIATED
2905 Local<Boolean> tls_npn = True(env->isolate());
2907 Local<Boolean> tls_npn = False(env->isolate());
2909 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_npn"), tls_npn);
2911 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2912 Local<Boolean> tls_alpn = True(env->isolate());
2914 Local<Boolean> tls_alpn = False(env->isolate());
2916 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_alpn"), tls_alpn);
2918 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2919 Local<Boolean> tls_sni = True(env->isolate());
2921 Local<Boolean> tls_sni = False(env->isolate());
2923 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_sni"), tls_sni);
2925 #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2926 Local<Boolean> tls_ocsp = True(env->isolate());
2928 Local<Boolean> tls_ocsp = False(env->isolate());
2929 #endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2930 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls_ocsp"), tls_ocsp);
2932 obj->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "tls"),
2933 Boolean::New(env->isolate(),
2934 get_builtin_module("crypto") != nullptr));
2936 return scope.Escape(obj);
2940 static void DebugPortGetter(Local<Name> property,
2941 const PropertyCallbackInfo<Value>& info) {
2942 int port = debug_port;
2944 port = use_inspector ? default_inspector_port : default_debugger_port;
2945 info.GetReturnValue().Set(port);
2949 static void DebugPortSetter(Local<Name> property,
2951 const PropertyCallbackInfo<void>& info) {
2952 debug_port = value->Int32Value();
2956 static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2957 static void DebugPause(const FunctionCallbackInfo<Value>& args);
2958 static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2961 void NeedImmediateCallbackGetter(Local<Name> property,
2962 const PropertyCallbackInfo<Value>& info) {
2963 Environment* env = Environment::GetCurrent(info);
2964 const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2965 bool active = uv_is_active(
2966 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2967 info.GetReturnValue().Set(active);
2971 static void NeedImmediateCallbackSetter(
2972 Local<Name> property,
2974 const PropertyCallbackInfo<void>& info) {
2975 Environment* env = Environment::GetCurrent(info);
2977 uv_check_t* immediate_check_handle = env->immediate_check_handle();
2978 bool active = uv_is_active(
2979 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2981 if (active == value->BooleanValue())
2984 uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2987 uv_check_stop(immediate_check_handle);
2988 uv_idle_stop(immediate_idle_handle);
2990 uv_check_start(immediate_check_handle, CheckImmediate);
2991 // Idle handle is needed only to stop the event loop from blocking in poll.
2992 uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2997 void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2998 Environment* env = Environment::GetCurrent(args);
2999 env->StartProfilerIdleNotifier();
3003 void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
3004 Environment* env = Environment::GetCurrent(args);
3005 env->StopProfilerIdleNotifier();
3009 #define READONLY_PROPERTY(obj, str, var) \
3011 obj->DefineOwnProperty(env->context(), \
3012 OneByteString(env->isolate(), str), \
3014 v8::ReadOnly).FromJust(); \
3017 #define READONLY_DONT_ENUM_PROPERTY(obj, str, var) \
3019 obj->DefineOwnProperty(env->context(), \
3020 OneByteString(env->isolate(), str), \
3022 static_cast<v8::PropertyAttribute>(v8::ReadOnly | \
3028 void SetupProcessObject(Environment* env,
3030 const char* const* argv,
3032 const char* const* exec_argv) {
3033 HandleScope scope(env->isolate());
3035 Local<Object> process = env->process_object();
3037 auto title_string = FIXED_ONE_BYTE_STRING(env->isolate(), "title");
3038 CHECK(process->SetAccessor(env->context(),
3042 env->as_external()).FromJust());
3045 READONLY_PROPERTY(process,
3047 FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
3049 // process.moduleLoadList
3050 READONLY_PROPERTY(process,
3052 env->module_load_list_array());
3055 Local<Object> versions = Object::New(env->isolate());
3056 READONLY_PROPERTY(process, "versions", versions);
3058 const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
3060 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
3062 NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
3063 READONLY_PROPERTY(versions,
3065 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
3067 // +1 to get rid of the leading 'v'
3068 READONLY_PROPERTY(versions,
3070 OneByteString(env->isolate(), NODE_VERSION + 1));
3071 READONLY_PROPERTY(versions,
3073 OneByteString(env->isolate(), V8::GetVersion()));
3074 READONLY_PROPERTY(versions,
3076 OneByteString(env->isolate(), uv_version_string()));
3077 READONLY_PROPERTY(versions,
3079 FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
3080 READONLY_PROPERTY(versions,
3082 FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
3084 #if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
3085 // ICU-related versions are now handled on the js side, see bootstrap_node.js
3087 if (icu_data_dir != nullptr) {
3088 // Did the user attempt (via env var or parameter) to set an ICU path?
3089 READONLY_PROPERTY(process,
3091 OneByteString(env->isolate(), icu_data_dir));
3095 const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
3099 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
3101 // process._promiseRejectEvent
3102 Local<Object> promiseRejectEvent = Object::New(env->isolate());
3103 READONLY_DONT_ENUM_PROPERTY(process,
3104 "_promiseRejectEvent",
3105 promiseRejectEvent);
3106 READONLY_PROPERTY(promiseRejectEvent,
3108 Integer::New(env->isolate(),
3109 v8::kPromiseRejectWithNoHandler));
3110 READONLY_PROPERTY(promiseRejectEvent,
3112 Integer::New(env->isolate(),
3113 v8::kPromiseHandlerAddedAfterReject));
3116 // Stupid code to slice out the version string.
3117 { // NOLINT(whitespace/braces)
3120 for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
3121 c = OPENSSL_VERSION_TEXT[i];
3122 if ('0' <= c && c <= '9') {
3123 for (j = i + 1; j < k; ++j) {
3124 c = OPENSSL_VERSION_TEXT[j];
3134 OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
3139 READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
3142 READONLY_PROPERTY(process,
3144 OneByteString(env->isolate(), NODE_PLATFORM));
3147 Local<Object> release = Object::New(env->isolate());
3148 READONLY_PROPERTY(process, "release", release);
3149 READONLY_PROPERTY(release, "name", OneByteString(env->isolate(), "node"));
3151 // if this is a release build and no explicit base has been set
3152 // substitute the standard release download URL
3153 #ifndef NODE_RELEASE_URLBASE
3154 # if NODE_VERSION_IS_RELEASE
3155 # define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
3159 #if defined(NODE_RELEASE_URLBASE)
3160 # define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
3161 # define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
3163 READONLY_PROPERTY(release,
3165 OneByteString(env->isolate(),
3166 NODE_RELEASE_URLFPFX ".tar.gz"));
3167 READONLY_PROPERTY(release,
3169 OneByteString(env->isolate(),
3170 NODE_RELEASE_URLFPFX "-headers.tar.gz"));
3172 READONLY_PROPERTY(release,
3174 OneByteString(env->isolate(),
3175 strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-"
3176 NODE_ARCH "/node.lib"
3177 : NODE_RELEASE_URLPFX
3178 "win-x86/node.lib"));
3183 Local<Array> arguments = Array::New(env->isolate(), argc);
3184 for (int i = 0; i < argc; ++i) {
3185 arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
3187 process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "argv"), arguments);
3190 Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
3191 for (int i = 0; i < exec_argc; ++i) {
3192 exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
3194 process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execArgv"),
3197 // create process.env
3198 Local<ObjectTemplate> process_env_template =
3199 ObjectTemplate::New(env->isolate());
3200 process_env_template->SetHandler(NamedPropertyHandlerConfiguration(
3207 PropertyHandlerFlags::kOnlyInterceptStrings));
3209 Local<Object> process_env =
3210 process_env_template->NewInstance(env->context()).ToLocalChecked();
3211 process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "env"), process_env);
3213 READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
3214 READONLY_PROPERTY(process, "features", GetFeatures(env));
3216 auto need_immediate_callback_string =
3217 FIXED_ONE_BYTE_STRING(env->isolate(), "_needImmediateCallback");
3218 CHECK(process->SetAccessor(env->context(), need_immediate_callback_string,
3219 NeedImmediateCallbackGetter,
3220 NeedImmediateCallbackSetter,
3221 env->as_external()).FromJust());
3225 READONLY_PROPERTY(process,
3227 String::NewFromUtf8(env->isolate(), eval_string));
3232 READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
3236 if (syntax_check_only) {
3237 READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
3240 // -i, --interactive
3242 READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
3245 if (preload_module_count) {
3246 CHECK(preload_modules);
3247 Local<Array> array = Array::New(env->isolate());
3248 for (unsigned int i = 0; i < preload_module_count; ++i) {
3249 Local<String> module = String::NewFromUtf8(env->isolate(),
3250 preload_modules[i]);
3251 array->Set(i, module);
3253 READONLY_PROPERTY(process,
3257 delete[] preload_modules;
3258 preload_modules = nullptr;
3259 preload_module_count = 0;
3263 if (no_deprecation) {
3264 READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
3267 if (no_process_warnings) {
3268 READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
3271 if (trace_warnings) {
3272 READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
3275 // --throw-deprecation
3276 if (throw_deprecation) {
3277 READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
3280 #ifdef NODE_NO_BROWSER_GLOBALS
3281 // configure --no-browser-globals
3282 READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
3283 #endif // NODE_NO_BROWSER_GLOBALS
3287 READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
3290 // --trace-deprecation
3291 if (trace_deprecation) {
3292 READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
3296 if (debug_wait_connect) {
3297 READONLY_PROPERTY(process, "_debugWaitConnect", True(env->isolate()));
3300 // --security-revert flags
3301 #define V(code, _, __) \
3303 if (IsReverted(REVERT_ ## code)) { \
3304 READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
3310 size_t exec_path_len = 2 * PATH_MAX;
3311 char* exec_path = new char[exec_path_len];
3312 Local<String> exec_path_value;
3313 if (uv_exepath(exec_path, &exec_path_len) == 0) {
3314 exec_path_value = String::NewFromUtf8(env->isolate(),
3316 String::kNormalString,
3319 exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
3321 process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
3325 auto debug_port_string = FIXED_ONE_BYTE_STRING(env->isolate(), "debugPort");
3326 CHECK(process->SetAccessor(env->context(),
3330 env->as_external()).FromJust());
3332 // define various internal methods
3333 env->SetMethod(process,
3334 "_startProfilerIdleNotifier",
3335 StartProfilerIdleNotifier);
3336 env->SetMethod(process,
3337 "_stopProfilerIdleNotifier",
3338 StopProfilerIdleNotifier);
3339 env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
3340 env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
3341 env->SetMethod(process, "reallyExit", Exit);
3342 env->SetMethod(process, "abort", Abort);
3343 env->SetMethod(process, "chdir", Chdir);
3344 env->SetMethod(process, "cwd", Cwd);
3346 env->SetMethod(process, "umask", Umask);
3348 #if defined(__POSIX__) && !defined(__ANDROID__)
3349 env->SetMethod(process, "getuid", GetUid);
3350 env->SetMethod(process, "geteuid", GetEUid);
3351 env->SetMethod(process, "setuid", SetUid);
3352 env->SetMethod(process, "seteuid", SetEUid);
3354 env->SetMethod(process, "setgid", SetGid);
3355 env->SetMethod(process, "setegid", SetEGid);
3356 env->SetMethod(process, "getgid", GetGid);
3357 env->SetMethod(process, "getegid", GetEGid);
3359 env->SetMethod(process, "getgroups", GetGroups);
3360 env->SetMethod(process, "setgroups", SetGroups);
3361 env->SetMethod(process, "initgroups", InitGroups);
3362 #endif // __POSIX__ && !defined(__ANDROID__)
3364 env->SetMethod(process, "_kill", Kill);
3366 env->SetMethod(process, "_debugProcess", DebugProcess);
3367 env->SetMethod(process, "_debugPause", DebugPause);
3368 env->SetMethod(process, "_debugEnd", DebugEnd);
3370 env->SetMethod(process, "hrtime", Hrtime);
3372 env->SetMethod(process, "cpuUsage", CPUUsage);
3374 env->SetMethod(process, "dlopen", DLOpen);
3376 env->SetMethod(process, "uptime", Uptime);
3377 env->SetMethod(process, "memoryUsage", MemoryUsage);
3379 env->SetMethod(process, "binding", Binding);
3380 env->SetMethod(process, "_linkedBinding", LinkedBinding);
3382 env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
3383 env->SetMethod(process, "_setupNextTick", SetupNextTick);
3384 env->SetMethod(process, "_setupPromises", SetupPromises);
3385 env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
3387 // pre-set _events object for faster emit checks
3388 Local<Object> events_obj = Object::New(env->isolate());
3389 CHECK(events_obj->SetPrototype(env->context(),
3390 Null(env->isolate())).FromJust());
3391 process->Set(env->events_string(), events_obj);
3395 #undef READONLY_PROPERTY
3398 void SignalExit(int signo) {
3399 uv_tty_reset_mode();
3401 // FreeBSD has a nasty bug, see RegisterSignalHandler for details
3402 struct sigaction sa;
3403 memset(&sa, 0, sizeof(sa));
3404 sa.sa_handler = SIG_DFL;
3405 CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
3411 // Most of the time, it's best to use `console.error` to write
3412 // to the process.stderr stream. However, in some cases, such as
3413 // when debugging the stream.Writable class or the process.nextTick
3414 // function, it is useful to bypass JavaScript entirely.
3415 static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3416 CHECK(args.Length() == 1 && args[0]->IsString() &&
3417 "must be called with a single string");
3418 node::Utf8Value message(args.GetIsolate(), args[0]);
3419 PrintErrorString("%s\n", *message);
3424 void LoadEnvironment(Environment* env) {
3425 if (g_standalone_mode) {
3426 env->isolate()->AddMessageListener(OnMessage);
3428 if (g_upstream_node_mode) {
3429 env->isolate()->SetFatalErrorHandler(OnFatalError);
3432 HandleScope handle_scope(env->isolate());
3434 TryCatch try_catch(env->isolate());
3436 // Disable verbose mode to stop FatalException() handler from trying
3437 // to handle the exception. Errors this early in the start-up phase
3438 // are not safe to ignore.
3439 try_catch.SetVerbose(false);
3441 // Execute the lib/internal/bootstrap_node.js file which was included as a
3442 // static C string in node_natives.h by node_js2c.
3443 // 'internal_bootstrap_node_native' is the string containing that source code.
3444 Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
3445 "bootstrap_node.js");
3446 Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3447 if (try_catch.HasCaught()) {
3448 ReportException(env, try_catch);
3451 // The bootstrap_node.js file returns a function 'f'
3452 CHECK(f_value->IsFunction());
3453 Local<Function> f = Local<Function>::Cast(f_value);
3455 // Add a reference to the global object
3456 Local<Object> global = env->context()->Global();
3458 #if defined HAVE_DTRACE || defined HAVE_ETW
3459 InitDTrace(env, global);
3462 #if defined HAVE_LTTNG
3463 InitLTTNG(env, global);
3466 #if defined HAVE_PERFCTR
3467 InitPerfCounters(env, global);
3470 // Enable handling of uncaught exceptions
3471 // (FatalException(), break on uncaught exception in debugger)
3473 // This is not strictly necessary since it's almost impossible
3474 // to attach the debugger fast enought to break on exception
3475 // thrown during process startup.
3476 try_catch.SetVerbose(true);
3478 env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3480 // Expose the global object as a property on itself
3481 // (Allows you to set stuff on `global` from anywhere in JavaScript.)
3482 global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global);
3484 // Now we call 'f' with the 'process' variable that we've built up with
3485 // all our bindings. Inside bootstrap_node.js and internal/process we'll
3486 // take care of assigning things to their places.
3488 // We start the process this way in order to be more modular. Developers
3489 // who do not like how bootstrap_node.js sets up the module system but do
3490 // like Node's I/O bindings may want to replace 'f' with their own function.
3491 Local<Value> arg = env->process_object();
3492 f->Call(Null(env->isolate()), 1, &arg);
3496 static void PrintHelp();
3498 static bool ParseDebugOpt(const char* arg) {
3499 const char* port = nullptr;
3501 if (!strcmp(arg, "--debug")) {
3502 use_debug_agent = true;
3503 } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
3504 use_debug_agent = true;
3505 port = arg + sizeof("--debug=") - 1;
3506 } else if (!strcmp(arg, "--debug-brk")) {
3507 use_debug_agent = true;
3508 debug_wait_connect = true;
3509 } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
3510 use_debug_agent = true;
3511 debug_wait_connect = true;
3512 port = arg + sizeof("--debug-brk=") - 1;
3513 } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
3514 // XXX(bnoordhuis) Misnomer, configures port and listen address.
3515 port = arg + sizeof("--debug-port=") - 1;
3517 // Specifying both --inspect and --debug means debugging is on, using Chromium
3519 } else if (!strcmp(arg, "--inspect")) {
3520 use_debug_agent = true;
3521 use_inspector = true;
3522 } else if (!strncmp(arg, "--inspect=", sizeof("--inspect=") - 1)) {
3523 use_debug_agent = true;
3524 use_inspector = true;
3525 port = arg + sizeof("--inspect=") - 1;
3527 } else if (!strncmp(arg, "--inspect", sizeof("--inspect") - 1)) {
3529 "Inspector support is not available with this Node.js build\n");
3536 if (port == nullptr) {
3540 // FIXME(bnoordhuis) Move IPv6 address parsing logic to lib/net.js.
3541 // It seems reasonable to support [address]:port notation
3542 // in net.Server#listen() and net.Socket#connect().
3543 const size_t port_len = strlen(port);
3544 if (port[0] == '[' && port[port_len - 1] == ']') {
3545 debug_host = new std::string(port + 1, port_len - 2);
3549 const char* const colon = strrchr(port, ':');
3550 if (colon == nullptr) {
3551 // Either a port number or a host name. Assume that
3552 // if it's not all decimal digits, it's a host name.
3553 for (size_t n = 0; port[n] != '\0'; n += 1) {
3554 if (port[n] < '0' || port[n] > '9') {
3555 debug_host = new std::string(port);
3560 const bool skip = (colon > port && port[0] == '[' && colon[-1] == ']');
3561 debug_host = new std::string(port + skip, colon - skip);
3566 const char* const digits = colon != nullptr ? colon + 1 : port;
3567 const long result = strtol(digits, &endptr, 10); // NOLINT(runtime/int)
3568 if (errno != 0 || *endptr != '\0' || result < 1024 || result > 65535) {
3569 fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
3574 debug_port = static_cast<int>(result);
3579 static void PrintHelp() {
3580 // XXX: If you add an option here, please also add it to doc/node.1 and
3582 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
3583 " node debug script.js [arguments] \n"
3586 " -v, --version print Node.js version\n"
3587 " -e, --eval script evaluate script\n"
3588 " -p, --print evaluate script and print result\n"
3589 " -c, --check syntax check script without executing\n"
3590 " -i, --interactive always enter the REPL even if stdin\n"
3591 " does not appear to be a terminal\n"
3592 " -r, --require module to preload (option can be repeated)\n"
3593 " --no-deprecation silence deprecation warnings\n"
3594 " --trace-deprecation show stack traces on deprecations\n"
3595 " --throw-deprecation throw an exception anytime a deprecated "
3596 "function is used\n"
3597 " --no-warnings silence all process warnings\n"
3598 " --trace-warnings show stack traces on process warnings\n"
3599 " --trace-sync-io show stack trace when use of sync IO\n"
3600 " is detected after the first tick\n"
3601 " --track-heap-objects track heap object allocations for heap "
3603 " --prof-process process v8 profiler output generated\n"
3605 " --zero-fill-buffers automatically zero-fill all newly allocated\n"
3606 " Buffer and SlowBuffer instances\n"
3607 " --v8-options print v8 command line options\n"
3608 " --v8-pool-size=num set v8's thread pool size\n"
3610 " --tls-cipher-list=val use an alternative default TLS cipher list\n"
3612 " --enable-fips enable FIPS crypto at startup\n"
3613 " --force-fips force FIPS crypto (cannot be disabled)\n"
3614 #endif /* NODE_FIPS_MODE */
3615 " --openssl-config=path load OpenSSL configuration file from the\n"
3617 #endif /* HAVE_OPENSSL */
3618 #if defined(NODE_HAVE_I18N_SUPPORT)
3619 " --icu-data-dir=dir set ICU data load path to dir\n"
3620 " (overrides NODE_ICU_DATA)\n"
3621 #if !defined(NODE_HAVE_SMALL_ICU)
3622 " note: linked-in ICU data is\n"
3625 " --preserve-symlinks preserve symbolic links when resolving\n"
3626 " and caching modules.\n"
3629 "Environment variables:\n"
3631 "NODE_PATH ';'-separated list of directories\n"
3633 "NODE_PATH ':'-separated list of directories\n"
3635 " prefixed to the module search path.\n"
3636 "NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n"
3637 #if defined(NODE_HAVE_I18N_SUPPORT)
3638 "NODE_ICU_DATA data path for ICU (Intl object) data\n"
3639 #if !defined(NODE_HAVE_SMALL_ICU)
3640 " (will extend linked-in data)\n"
3643 "NODE_REPL_HISTORY path to the persistent REPL history file\n"
3645 "Documentation can be found at https://nodejs.org/\n");
3649 // Parse command line arguments.
3651 // argv is modified in place. exec_argv and v8_argv are out arguments that
3652 // ParseArgs() allocates memory for and stores a pointer to the output
3653 // vector in. The caller should free them with delete[].
3657 // * argv contains the arguments with node and V8 options filtered out.
3658 // * exec_argv contains both node and V8 options and nothing else.
3659 // * v8_argv contains argv[0] plus any V8 options
3660 static void ParseArgs(int* argc,
3663 const char*** exec_argv,
3665 const char*** v8_argv) {
3666 const unsigned int nargs = static_cast<unsigned int>(*argc);
3667 const char** new_exec_argv = new const char*[nargs];
3668 const char** new_v8_argv = new const char*[nargs];
3669 const char** new_argv = new const char*[nargs];
3670 const char** local_preload_modules = new const char*[nargs];
3672 for (unsigned int i = 0; i < nargs; ++i) {
3673 new_exec_argv[i] = nullptr;
3674 new_v8_argv[i] = nullptr;
3675 new_argv[i] = nullptr;
3676 local_preload_modules[i] = nullptr;
3679 // exec_argv starts with the first option, the other two start with argv[0].
3680 unsigned int new_exec_argc = 0;
3681 unsigned int new_v8_argc = 1;
3682 unsigned int new_argc = 1;
3683 new_v8_argv[0] = argv[0];
3684 new_argv[0] = argv[0];
3686 unsigned int index = 1;
3687 bool short_circuit = false;
3688 while (index < nargs && argv[index][0] == '-' && !short_circuit) {
3689 const char* const arg = argv[index];
3690 unsigned int args_consumed = 1;
3692 if (ParseDebugOpt(arg)) {
3693 // Done, consumed by ParseDebugOpt().
3694 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
3695 printf("%s\n", NODE_VERSION);
3697 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3700 } else if (strcmp(arg, "--eval") == 0 ||
3701 strcmp(arg, "-e") == 0 ||
3702 strcmp(arg, "--print") == 0 ||
3703 strcmp(arg, "-pe") == 0 ||
3704 strcmp(arg, "-p") == 0) {
3705 bool is_eval = strchr(arg, 'e') != nullptr;
3706 bool is_print = strchr(arg, 'p') != nullptr;
3707 print_eval = print_eval || is_print;
3708 // --eval, -e and -pe always require an argument.
3709 if (is_eval == true) {
3711 eval_string = argv[index + 1];
3712 if (eval_string == nullptr) {
3713 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3716 } else if ((index + 1 < nargs) &&
3717 argv[index + 1] != nullptr &&
3718 argv[index + 1][0] != '-') {
3720 eval_string = argv[index + 1];
3721 if (strncmp(eval_string, "\\-", 2) == 0) {
3722 // Starts with "\\-": escaped expression, drop the backslash.
3726 } else if (strcmp(arg, "--require") == 0 ||
3727 strcmp(arg, "-r") == 0) {
3728 const char* module = argv[index + 1];
3729 if (module == nullptr) {
3730 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3734 local_preload_modules[preload_module_count++] = module;
3735 } else if (strcmp(arg, "--check") == 0 || strcmp(arg, "-c") == 0) {
3736 syntax_check_only = true;
3737 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3739 } else if (strcmp(arg, "--no-deprecation") == 0) {
3740 no_deprecation = true;
3741 } else if (strcmp(arg, "--no-warnings") == 0) {
3742 no_process_warnings = true;
3743 } else if (strcmp(arg, "--trace-warnings") == 0) {
3744 trace_warnings = true;
3745 } else if (strcmp(arg, "--trace-deprecation") == 0) {
3746 trace_deprecation = true;
3747 } else if (strcmp(arg, "--trace-sync-io") == 0) {
3748 trace_sync_io = true;
3749 } else if (strcmp(arg, "--track-heap-objects") == 0) {
3750 track_heap_objects = true;
3751 } else if (strcmp(arg, "--throw-deprecation") == 0) {
3752 throw_deprecation = true;
3753 } else if (strncmp(arg, "--security-revert=", 18) == 0) {
3754 const char* cve = arg + 18;
3756 } else if (strcmp(arg, "--preserve-symlinks") == 0) {
3757 config_preserve_symlinks = true;
3758 } else if (strcmp(arg, "--prof-process") == 0) {
3759 prof_process = true;
3760 short_circuit = true;
3761 } else if (strcmp(arg, "--zero-fill-buffers") == 0) {
3762 zero_fill_all_buffers = true;
3763 } else if (strcmp(arg, "--v8-options") == 0) {
3764 new_v8_argv[new_v8_argc] = "--help";
3766 } else if (strncmp(arg, "--v8-pool-size=", 15) == 0) {
3767 v8_thread_pool_size = atoi(arg + 15);
3769 } else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
3770 default_cipher_list = arg + 18;
3772 } else if (strcmp(arg, "--enable-fips") == 0) {
3773 enable_fips_crypto = true;
3774 } else if (strcmp(arg, "--force-fips") == 0) {
3775 force_fips_crypto = true;
3776 #endif /* NODE_FIPS_MODE */
3777 } else if (strncmp(arg, "--openssl-config=", 17) == 0) {
3778 openssl_config = arg + 17;
3779 #endif /* HAVE_OPENSSL */
3780 #if defined(NODE_HAVE_I18N_SUPPORT)
3781 } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3782 icu_data_dir = arg + 15;
3784 } else if (strcmp(arg, "--expose-internals") == 0 ||
3785 strcmp(arg, "--expose_internals") == 0) {
3788 // V8 option. Pass through as-is.
3789 new_v8_argv[new_v8_argc] = arg;
3793 memcpy(new_exec_argv + new_exec_argc,
3795 args_consumed * sizeof(*argv));
3797 new_exec_argc += args_consumed;
3798 index += args_consumed;
3801 // Copy remaining arguments.
3802 const unsigned int args_left = nargs - index;
3803 memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3804 new_argc += args_left;
3806 *exec_argc = new_exec_argc;
3807 *exec_argv = new_exec_argv;
3808 *v8_argc = new_v8_argc;
3809 *v8_argv = new_v8_argv;
3811 // Copy new_argv over argv and update argc.
3812 memcpy(argv, new_argv, new_argc * sizeof(*argv));
3814 *argc = static_cast<int>(new_argc);
3816 // Copy the preload_modules from the local array to an appropriately sized
3818 if (preload_module_count > 0) {
3819 CHECK(!preload_modules);
3820 preload_modules = new const char*[preload_module_count];
3821 memcpy(preload_modules, local_preload_modules,
3822 preload_module_count * sizeof(*preload_modules));
3824 delete[] local_preload_modules;
3828 // Called from V8 Debug Agent TCP thread.
3829 static void DispatchMessagesDebugAgentCallback(Environment* env) {
3830 // TODO(indutny): move async handle to environment
3831 uv_async_send(&dispatch_debug_messages_async);
3835 static void StartDebug(Environment* env, const char* path, bool wait) {
3836 CHECK(!debugger_running);
3837 if (use_inspector) {
3838 debugger_running = v8_platform.StartInspector(env, path,
3839 debug_port >= 0 ? debug_port : default_inspector_port, wait);
3841 env->debugger_agent()->set_dispatch_handler(
3842 DispatchMessagesDebugAgentCallback);
3843 const char* host = debug_host ? debug_host->c_str() : "127.0.0.1";
3844 int port = debug_port >= 0 ? debug_port : default_debugger_port;
3846 env->debugger_agent()->Start(host, port, wait);
3847 if (debugger_running == false) {
3848 fprintf(stderr, "Starting debugger on %s:%d failed\n", host, port);
3856 // Called from the main thread.
3857 static void EnableDebug(Environment* env) {
3858 CHECK(debugger_running);
3860 if (use_inspector) {
3864 // Send message to enable debug in workers
3865 HandleScope handle_scope(env->isolate());
3867 Local<Object> message = Object::New(env->isolate());
3868 message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3869 FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3870 Local<Value> argv[] = {
3871 FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
3874 MakeCallback(env, env->process_object(), "emit", arraysize(argv), argv);
3876 // Enabled debugger, possibly making it wait on a semaphore
3877 env->debugger_agent()->Enable();
3881 // Called from an arbitrary thread.
3882 static void TryStartDebugger() {
3883 Mutex::ScopedLock scoped_lock(node_isolate_mutex);
3884 if (auto isolate = node_isolate) {
3885 v8::Debug::DebugBreak(isolate);
3886 uv_async_send(&dispatch_debug_messages_async);
3891 // Called from the main thread.
3892 static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
3893 Mutex::ScopedLock scoped_lock(node_isolate_mutex);
3894 if (auto isolate = node_isolate) {
3895 if (debugger_running == false) {
3896 fprintf(stderr, "Starting debugger agent.\n");
3898 HandleScope scope(isolate);
3899 Environment* env = Environment::GetCurrent(isolate);
3900 Context::Scope context_scope(env->context());
3902 StartDebug(env, nullptr, false);
3906 Isolate::Scope isolate_scope(isolate);
3907 v8::Debug::ProcessDebugMessages(isolate);
3913 static void EnableDebugSignalHandler(int signo) {
3914 uv_sem_post(&debug_semaphore);
3918 void RegisterSignalHandler(int signal,
3919 void (*handler)(int signal),
3920 bool reset_handler) {
3921 struct sigaction sa;
3922 memset(&sa, 0, sizeof(sa));
3923 sa.sa_handler = handler;
3925 // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
3926 // in turn set for a libthr wrapper. This leads to a crash.
3927 // Work around the issue by manually setting SIG_DFL in the signal handler
3928 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
3930 sigfillset(&sa.sa_mask);
3931 CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
3935 void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3936 Environment* env = Environment::GetCurrent(args);
3938 if (args.Length() != 1) {
3939 return env->ThrowError("Invalid number of arguments.");
3945 pid = args[0]->IntegerValue();
3946 r = kill(pid, SIGUSR1);
3948 return env->ThrowErrnoException(errno, "kill");
3953 inline void* DebugSignalThreadMain(void* unused) {
3955 uv_sem_wait(&debug_semaphore);
3962 static int RegisterDebugSignalHandler() {
3963 // Start a watchdog thread for calling v8::Debug::DebugBreak() because
3964 // it's not safe to call directly from the signal handler, it can
3965 // deadlock with the thread it interrupts.
3966 CHECK_EQ(0, uv_sem_init(&debug_semaphore, 0));
3967 pthread_attr_t attr;
3968 CHECK_EQ(0, pthread_attr_init(&attr));
3969 // Don't shrink the thread's stack on FreeBSD. Said platform decided to
3970 // follow the pthreads specification to the letter rather than in spirit:
3971 // https://lists.freebsd.org/pipermail/freebsd-current/2014-March/048885.html
3973 CHECK_EQ(0, pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN));
3974 #endif // __FreeBSD__
3975 CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
3977 sigfillset(&sigmask);
3978 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask));
3981 pthread_create(&thread, &attr, DebugSignalThreadMain, nullptr);
3982 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr));
3983 CHECK_EQ(0, pthread_attr_destroy(&attr));
3985 fprintf(stderr, "node[%d]: pthread_create: %s\n", getpid(), strerror(err));
3987 // Leave SIGUSR1 blocked. We don't install a signal handler,
3988 // receiving the signal would terminate the process.
3991 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
3992 // Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered.
3993 sigemptyset(&sigmask);
3994 sigaddset(&sigmask, SIGUSR1);
3995 CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
4002 DWORD WINAPI EnableDebugThreadProc(void* arg) {
4008 static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
4010 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
4014 static int RegisterDebugSignalHandler() {
4015 wchar_t mapping_name[32];
4016 HANDLE mapping_handle;
4018 LPTHREAD_START_ROUTINE* handler;
4020 pid = GetCurrentProcessId();
4022 if (GetDebugSignalHandlerMappingName(pid,
4024 arraysize(mapping_name)) < 0) {
4028 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
4034 if (mapping_handle == nullptr) {
4038 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
4039 MapViewOfFile(mapping_handle,
4040 FILE_MAP_ALL_ACCESS,
4044 if (handler == nullptr) {
4045 CloseHandle(mapping_handle);
4049 *handler = EnableDebugThreadProc;
4051 UnmapViewOfFile(static_cast<void*>(handler));
4057 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
4058 Environment* env = Environment::GetCurrent(args);
4059 Isolate* isolate = args.GetIsolate();
4061 HANDLE process = nullptr;
4062 HANDLE thread = nullptr;
4063 HANDLE mapping = nullptr;
4064 wchar_t mapping_name[32];
4065 LPTHREAD_START_ROUTINE* handler = nullptr;
4067 if (args.Length() != 1) {
4068 env->ThrowError("Invalid number of arguments.");
4072 pid = (DWORD) args[0]->IntegerValue();
4074 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
4075 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
4079 if (process == nullptr) {
4080 isolate->ThrowException(
4081 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
4085 if (GetDebugSignalHandlerMappingName(pid,
4087 arraysize(mapping_name)) < 0) {
4088 env->ThrowErrnoException(errno, "sprintf");
4092 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
4093 if (mapping == nullptr) {
4094 isolate->ThrowException(WinapiErrnoException(isolate,
4096 "OpenFileMappingW"));
4100 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
4101 MapViewOfFile(mapping,
4106 if (handler == nullptr || *handler == nullptr) {
4107 isolate->ThrowException(
4108 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
4112 thread = CreateRemoteThread(process,
4119 if (thread == nullptr) {
4120 isolate->ThrowException(WinapiErrnoException(isolate,
4122 "CreateRemoteThread"));
4126 // Wait for the thread to terminate
4127 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
4128 isolate->ThrowException(WinapiErrnoException(isolate,
4130 "WaitForSingleObject"));
4135 if (process != nullptr)
4136 CloseHandle(process);
4137 if (thread != nullptr)
4138 CloseHandle(thread);
4139 if (handler != nullptr)
4140 UnmapViewOfFile(handler);
4141 if (mapping != nullptr)
4142 CloseHandle(mapping);
4147 static void DebugPause(const FunctionCallbackInfo<Value>& args) {
4148 v8::Debug::DebugBreak(args.GetIsolate());
4152 static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
4153 if (debugger_running) {
4154 Environment* env = Environment::GetCurrent(args);
4156 if (use_inspector) {
4157 env->inspector_agent()->Stop();
4160 env->debugger_agent()->Stop();
4164 debugger_running = false;
4169 inline void PlatformInit() {
4172 sigemptyset(&sigmask);
4173 sigaddset(&sigmask, SIGUSR1);
4174 const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
4176 // Make sure file descriptors 0-2 are valid before we start logging anything.
4177 for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
4178 struct stat ignored;
4179 if (fstat(fd, &ignored) == 0)
4181 // Anything but EBADF means something is seriously wrong. We don't
4182 // have to special-case EINTR, fstat() is not interruptible.
4185 if (fd != open("/dev/null", O_RDWR))
4191 // Restore signal dispositions, the parent process may have changed them.
4192 struct sigaction act;
4193 memset(&act, 0, sizeof(act));
4195 // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
4196 // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
4197 // Counting up to SIGRTMIN doesn't work for the same reason.
4198 for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
4199 if (nr == SIGKILL || nr == SIGSTOP)
4201 act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
4202 CHECK_EQ(0, sigaction(nr, &act, nullptr));
4205 RegisterSignalHandler(SIGINT, SignalExit, true);
4206 RegisterSignalHandler(SIGTERM, SignalExit, true);
4208 // Raise the open file descriptor limit.
4210 if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
4211 // Do a binary search for the limit.
4212 rlim_t min = lim.rlim_cur;
4213 rlim_t max = 1 << 20;
4214 // But if there's a defined upper bound, don't search, just set it.
4215 if (lim.rlim_max != RLIM_INFINITY) {
4220 lim.rlim_cur = min + (max - min) / 2;
4221 if (setrlimit(RLIMIT_NOFILE, &lim)) {
4226 } while (min + 1 < max);
4232 void Init(int* argc,
4235 const char*** exec_argv,
4236 uv_loop_t* uv_loop_) {
4237 // Initialize prog_start_time to get relative uptime.
4238 prog_start_time = static_cast<double>(uv_now(uv_loop_));
4240 if (g_upstream_node_mode) { // No indent to minimize diff.
4241 // Make inherited handles noninheritable.
4242 uv_disable_stdio_inheritance();
4243 } // g_upstream_node_mode
4245 // init async debug messages dispatching
4246 // Main thread uses uv_default_loop
4247 CHECK_EQ(0, uv_async_init(uv_loop_,
4248 &dispatch_debug_messages_async,
4249 DispatchDebugMessagesAsyncCallback));
4250 uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
4252 #if defined(NODE_HAVE_I18N_SUPPORT)
4253 // Set the ICU casing flag early
4254 // so the user can disable a flag --foo at run-time by passing
4255 // --no_foo from the command line.
4256 const char icu_case_mapping[] = "--icu_case_mapping";
4257 V8::SetFlagsFromString(icu_case_mapping, sizeof(icu_case_mapping) - 1);
4260 #if defined(NODE_V8_OPTIONS)
4261 // Should come before the call to V8::SetFlagsFromCommandLine()
4262 // so the user can disable a flag --foo at run-time by passing
4263 // --no_foo from the command line.
4264 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
4267 // Allow for environment set preserving symlinks.
4268 if (auto preserve_symlinks = secure_getenv("NODE_PRESERVE_SYMLINKS")) {
4269 config_preserve_symlinks = (*preserve_symlinks == '1');
4272 if (g_upstream_node_mode) { // No indent to minimize diff.
4273 // Parse a few arguments which are specific to Node.
4275 const char** v8_argv;
4276 ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
4278 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
4279 // manually? That would give us a little more control over its runtime
4280 // behavior but it could also interfere with the user's intentions in ways
4281 // we fail to anticipate. Dillema.
4282 for (int i = 1; i < v8_argc; ++i) {
4283 if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
4284 v8_is_profiling = true;
4290 // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
4291 // performance penalty of frequent EINTR wakeups when the profiler is running.
4292 // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
4293 if (v8_is_profiling) {
4294 uv_loop_configure(uv_loop_, UV_LOOP_BLOCK_SIGNAL, SIGPROF);
4298 #if defined(NODE_HAVE_I18N_SUPPORT)
4299 if (icu_data_dir == nullptr) {
4300 // if the parameter isn't given, use the env variable.
4301 icu_data_dir = secure_getenv("NODE_ICU_DATA");
4304 // If icu_data_dir is nullptr here, it will load the 'minimal' data.
4305 if (!i18n::InitializeICUDirectory(icu_data_dir)) {
4306 FatalError(nullptr, "Could not initialize ICU "
4307 "(check NODE_ICU_DATA or --icu-data-dir parameters)");
4310 // The const_cast doesn't violate conceptual const-ness. V8 doesn't modify
4311 // the argv array or the elements it points to.
4313 V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
4315 // Anything that's still in v8_argv is not a V8 or a node option.
4316 for (int i = 1; i < v8_argc; i++) {
4317 fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
4325 } // g_upstream_node_mode
4327 // Unconditionally force typed arrays to allocate outside the v8 heap. This
4328 // is to prevent memory pointers from being moved around that are returned by
4330 const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
4331 V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
4333 if (g_upstream_node_mode) { // No indent to minimize diff.
4334 if (!use_debug_agent) {
4335 RegisterDebugSignalHandler();
4337 } // g_upstream_node_mode
4339 // We should set node_is_initialized here instead of in node::Start,
4340 // otherwise embedders using node::Init to initialize everything will not be
4341 // able to set it and native modules will not load for them.
4342 node_is_initialized = true;
4346 struct AtExitCallback {
4347 AtExitCallback* next_;
4348 void (*cb_)(void* arg);
4352 static AtExitCallback* at_exit_functions_;
4355 // TODO(bnoordhuis) Turn into per-context event.
4356 void RunAtExit(Environment* env) {
4357 AtExitCallback* p = at_exit_functions_;
4358 at_exit_functions_ = nullptr;
4361 AtExitCallback* q = p->next_;
4369 void AtExit(void (*cb)(void* arg), void* arg) {
4370 AtExitCallback* p = new AtExitCallback;
4373 p->next_ = at_exit_functions_;
4374 at_exit_functions_ = p;
4378 void EmitBeforeExit(Environment* env) {
4379 HandleScope handle_scope(env->isolate());
4380 Context::Scope context_scope(env->context());
4381 Local<Object> process_object = env->process_object();
4382 Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
4383 Local<Value> args[] = {
4384 FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
4385 process_object->Get(exit_code)->ToInteger(env->isolate())
4387 MakeCallback(env, process_object, "emit", arraysize(args), args);
4391 int EmitExit(Environment* env) {
4392 // process.emit('exit')
4393 HandleScope handle_scope(env->isolate());
4394 Context::Scope context_scope(env->context());
4395 Local<Object> process_object = env->process_object();
4396 process_object->Set(env->exiting_string(), True(env->isolate()));
4398 Local<String> exitCode = env->exit_code_string();
4399 int code = process_object->Get(exitCode)->Int32Value();
4401 Local<Value> args[] = {
4403 Integer::New(env->isolate(), code)
4406 MakeCallback(env, process_object, "emit", arraysize(args), args);
4408 // Reload exit code, it may be changed by `emit('exit')`
4409 return process_object->Get(exitCode)->Int32Value();
4413 IsolateData* CreateIsolateData(Isolate* isolate, uv_loop_t* loop) {
4414 return new IsolateData(isolate, loop);
4418 void FreeIsolateData(IsolateData* isolate_data) {
4419 delete isolate_data;
4423 Environment* CreateEnvironment(IsolateData* isolate_data,
4424 Local<Context> context,
4426 const char* const* argv,
4428 const char* const* exec_argv) {
4429 Isolate* isolate = context->GetIsolate();
4430 HandleScope handle_scope(isolate);
4431 Context::Scope context_scope(context);
4432 auto env = new Environment(isolate_data, context);
4433 env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
4438 void FreeEnvironment(Environment* env) {
4443 inline int Start(Isolate* isolate, IsolateData* isolate_data, // not called
4444 int argc, const char* const* argv,
4445 int exec_argc, const char* const* exec_argv) {
4446 HandleScope handle_scope(isolate);
4447 Local<Context> context = Context::New(isolate);
4448 Context::Scope context_scope(context);
4449 Environment env(isolate_data, context);
4450 env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
4452 // Start debug agent when argv has --debug
4453 if (use_debug_agent) {
4454 const char* path = argc > 1 ? argv[1] : nullptr;
4455 StartDebug(&env, path, debug_wait_connect);
4456 if (use_inspector && !debugger_running)
4457 return 12; // Signal internal error.
4461 Environment::AsyncCallbackScope callback_scope(&env);
4462 LoadEnvironment(&env);
4465 env.set_trace_sync_io(trace_sync_io);
4468 if (use_debug_agent)
4472 SealHandleScope seal(isolate);
4475 v8_platform.PumpMessageLoop(isolate);
4476 more = uv_run(env.event_loop(), UV_RUN_ONCE);
4478 if (more == false) {
4479 v8_platform.PumpMessageLoop(isolate);
4480 EmitBeforeExit(&env);
4482 // Emit `beforeExit` if the loop became alive either after emitting
4483 // event, or after running some callbacks.
4484 more = uv_loop_alive(env.event_loop());
4485 if (uv_run(env.event_loop(), UV_RUN_NOWAIT) != 0)
4488 } while (more == true);
4491 env.set_trace_sync_io(false);
4493 const int exit_code = EmitExit(&env);
4496 WaitForInspectorDisconnect(&env);
4497 #if defined(LEAK_SANITIZER)
4498 __lsan_do_leak_check();
4504 inline int Start(uv_loop_t* event_loop, // not called
4505 int argc, const char* const* argv,
4506 int exec_argc, const char* const* exec_argv) {
4507 Isolate::CreateParams params;
4508 ArrayBufferAllocator allocator;
4509 params.array_buffer_allocator = &allocator;
4510 #ifdef NODE_ENABLE_VTUNE_PROFILING
4511 params.code_event_handler = vTune::GetVtuneCodeEventHandler();
4514 Isolate* const isolate = Isolate::New(params);
4515 if (isolate == nullptr)
4516 return 12; // Signal internal error.
4518 isolate->AddMessageListener(OnMessage);
4519 isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException);
4520 isolate->SetAutorunMicrotasks(false);
4521 isolate->SetFatalErrorHandler(OnFatalError);
4523 if (track_heap_objects) {
4524 isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
4528 Mutex::ScopedLock scoped_lock(node_isolate_mutex);
4529 CHECK_EQ(node_isolate, nullptr);
4530 node_isolate = isolate;
4535 Locker locker(isolate);
4536 Isolate::Scope isolate_scope(isolate);
4537 HandleScope handle_scope(isolate);
4538 IsolateData isolate_data(isolate, event_loop, allocator.zero_fill_field());
4539 exit_code = Start(isolate, &isolate_data, argc, argv, exec_argc, exec_argv);
4543 Mutex::ScopedLock scoped_lock(node_isolate_mutex);
4544 CHECK_EQ(node_isolate, isolate);
4545 node_isolate = nullptr;
4553 int Start(int argc, char** argv) {
4554 atexit([] () { uv_tty_reset_mode(); });
4559 // Hack around with the argv pointer. Used for process.title = "blah".
4560 argv = uv_setup_args(argc, argv);
4562 // This needs to run *before* V8::Initialize(). The const_cast is not
4563 // optional, in case you're wondering.
4565 const char** exec_argv;
4566 // Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
4569 if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS"))
4570 crypto::UseExtraCaCerts(extra);
4571 #ifdef NODE_FIPS_MODE
4572 // In the case of FIPS builds we should make sure
4573 // the random source is properly initialized first.
4575 #endif // NODE_FIPS_MODE
4576 // V8 on Windows doesn't have a good source of entropy. Seed it from
4578 V8::SetEntropySource(crypto::EntropySource);
4581 v8_platform.Initialize(v8_thread_pool_size);
4583 v8_initialized = true;
4584 const int exit_code =
4585 Start(uv_default_loop(), argc, argv, exec_argc, exec_argv);
4586 v8_initialized = false;
4589 v8_platform.Dispose();
4592 exec_argv = nullptr;