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 #include "libplatform/libplatform.h"
44 #include "v8-profiler.h"
48 #include <limits.h> // PATH_MAX
54 #include <sys/types.h>
57 #if defined(NODE_HAVE_I18N_SUPPORT)
58 #include <unicode/uvernum.h>
61 #if defined(LEAK_SANITIZER)
62 #include <sanitizer/lsan_interface.h>
68 #define strcasecmp _stricmp
69 #define getpid GetCurrentProcessId
73 #include <sys/resource.h> // getrlimit, setrlimit
74 #include <unistd.h> // setuid, getuid
77 #if defined(__POSIX__) && !defined(__ANDROID__)
78 #include <pwd.h> // getpwnam()
79 #include <grp.h> // getgrnam()
83 #include <crt_externs.h>
84 #define environ (*_NSGetEnviron())
85 #elif !defined(_MSC_VER)
86 extern char **environ;
90 #include "atomic-polyfill.h" // NOLINT(build/include_order)
91 namespace node { template <typename T> using atomic = nonstd::atomic<T>; }
94 namespace node { template <typename T> using atomic = std::atomic<T>; }
100 using v8::ArrayBuffer;
103 using v8::EscapableHandleScope;
106 using v8::FunctionCallbackInfo;
107 using v8::FunctionTemplate;
108 using v8::HandleScope;
109 using v8::HeapStatistics;
117 using v8::ObjectTemplate;
119 using v8::PromiseRejectMessage;
120 using v8::PropertyCallbackInfo;
121 using v8::SealHandleScope;
122 using v8::StackFrame;
123 using v8::StackTrace;
127 using v8::Uint32Array;
131 static bool print_eval = false;
132 static bool force_repl = false;
133 static bool syntax_check_only = false;
134 static bool trace_deprecation = false;
135 static bool throw_deprecation = false;
136 static bool trace_sync_io = false;
137 static bool track_heap_objects = false;
138 static const char* eval_string = nullptr;
139 static unsigned int preload_module_count = 0;
140 static const char** preload_modules = nullptr;
141 static bool use_debug_agent = false;
142 static bool debug_wait_connect = false;
143 static int debug_port = 5858;
144 static bool prof_process = false;
145 static bool v8_is_profiling = false;
146 static bool node_is_initialized = false;
147 static node_module* modpending;
148 static node_module* modlist_builtin;
149 static node_module* modlist_linked;
150 static node_module* modlist_addon;
152 #if defined(NODE_HAVE_I18N_SUPPORT)
153 // Path to ICU data (for i18n / Intl)
154 static const char* icu_data_dir = nullptr;
157 // used by C++ modules as well
158 bool no_deprecation = false;
160 // process-relative uptime base, initialized at start-up
161 static double prog_start_time;
162 static bool debugger_running;
163 static uv_async_t dispatch_debug_messages_async;
165 static node::atomic<Isolate*> node_isolate;
166 static v8::Platform* default_platform;
169 static void PrintErrorString(const char* format, ...) {
171 va_start(ap, format);
173 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
175 // Check if stderr is something other than a tty/console
176 if (stderr_handle == INVALID_HANDLE_VALUE ||
177 stderr_handle == nullptr ||
178 uv_guess_handle(_fileno(stderr)) != UV_TTY) {
179 vfprintf(stderr, format, ap);
184 // Fill in any placeholders
185 int n = _vscprintf(format, ap);
186 std::vector<char> out(n + 1);
187 vsprintf(out.data(), format, ap);
189 // Get required wide buffer size
190 n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
192 std::vector<wchar_t> wbuf(n);
193 MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
194 WriteConsoleW(stderr_handle, wbuf.data(), n, nullptr, nullptr);
196 vfprintf(stderr, format, ap);
202 static void CheckImmediate(uv_check_t* handle) {
203 Environment* env = Environment::from_immediate_check_handle(handle);
204 HandleScope scope(env->isolate());
205 Context::Scope context_scope(env->context());
206 MakeCallback(env, env->process_object(), env->immediate_callback_string());
210 static void IdleImmediateDummy(uv_idle_t* handle) {
211 // Do nothing. Only for maintaining event loop.
212 // TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
216 static inline const char *errno_string(int errorno) {
217 #define ERRNO_CASE(e) case e: return #e;
224 ERRNO_CASE(EADDRINUSE);
228 ERRNO_CASE(EADDRNOTAVAIL);
232 ERRNO_CASE(EAFNOSUPPORT);
240 # if EAGAIN != EWOULDBLOCK
241 ERRNO_CASE(EWOULDBLOCK);
246 ERRNO_CASE(EALREADY);
262 ERRNO_CASE(ECANCELED);
270 ERRNO_CASE(ECONNABORTED);
274 ERRNO_CASE(ECONNREFUSED);
278 ERRNO_CASE(ECONNRESET);
286 ERRNO_CASE(EDESTADDRREQ);
310 ERRNO_CASE(EHOSTUNREACH);
322 ERRNO_CASE(EINPROGRESS);
358 ERRNO_CASE(EMSGSIZE);
362 ERRNO_CASE(EMULTIHOP);
366 ERRNO_CASE(ENAMETOOLONG);
370 ERRNO_CASE(ENETDOWN);
374 ERRNO_CASE(ENETRESET);
378 ERRNO_CASE(ENETUNREACH);
410 # if ENOLINK != ENOLCK
424 ERRNO_CASE(ENOPROTOOPT);
444 ERRNO_CASE(ENOTCONN);
452 # if ENOTEMPTY != EEXIST
453 ERRNO_CASE(ENOTEMPTY);
458 ERRNO_CASE(ENOTSOCK);
465 ERRNO_CASE(EOPNOTSUPP);
479 ERRNO_CASE(EOVERFLOW);
494 #ifdef EPROTONOSUPPORT
495 ERRNO_CASE(EPROTONOSUPPORT);
499 ERRNO_CASE(EPROTOTYPE);
527 ERRNO_CASE(ETIMEDOUT);
542 const char *signo_string(int signo) {
543 #define SIGNO_CASE(e) case e: return #e;
570 # if SIGABRT != SIGIOT
614 SIGNO_CASE(SIGSTKFLT);
631 SIGNO_CASE(SIGBREAK);
655 SIGNO_CASE(SIGVTALRM);
663 SIGNO_CASE(SIGWINCH);
671 # if SIGPOLL != SIGIO
677 # if SIGLOST != SIGABRT
683 # if SIGPWR != SIGLOST
697 // Convenience methods
700 void ThrowError(v8::Isolate* isolate, const char* errmsg) {
701 Environment::GetCurrent(isolate)->ThrowError(errmsg);
705 void ThrowTypeError(v8::Isolate* isolate, const char* errmsg) {
706 Environment::GetCurrent(isolate)->ThrowTypeError(errmsg);
710 void ThrowRangeError(v8::Isolate* isolate, const char* errmsg) {
711 Environment::GetCurrent(isolate)->ThrowRangeError(errmsg);
715 void ThrowErrnoException(v8::Isolate* isolate,
720 Environment::GetCurrent(isolate)->ThrowErrnoException(errorno,
727 void ThrowUVException(v8::Isolate* isolate,
733 Environment::GetCurrent(isolate)
734 ->ThrowUVException(errorno, syscall, message, path, dest);
738 Local<Value> ErrnoException(Isolate* isolate,
743 Environment* env = Environment::GetCurrent(isolate);
746 Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
747 if (msg == nullptr || msg[0] == '\0') {
748 msg = strerror(errorno);
750 Local<String> message = OneByteString(env->isolate(), msg);
753 String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
754 cons = String::Concat(cons, message);
756 Local<String> path_string;
757 if (path != nullptr) {
758 // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
759 path_string = String::NewFromUtf8(env->isolate(), path);
762 if (path_string.IsEmpty() == false) {
763 cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
764 cons = String::Concat(cons, path_string);
765 cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
767 e = Exception::Error(cons);
769 Local<Object> obj = e->ToObject(env->isolate());
770 obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
771 obj->Set(env->code_string(), estring);
773 if (path_string.IsEmpty() == false) {
774 obj->Set(env->path_string(), path_string);
777 if (syscall != nullptr) {
778 obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
785 static Local<String> StringFromPath(Isolate* isolate, const char* path) {
787 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
788 return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
789 String::NewFromUtf8(isolate, path + 8));
790 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
791 return String::NewFromUtf8(isolate, path + 4);
795 return String::NewFromUtf8(isolate, path);
799 Local<Value> UVException(Isolate* isolate,
804 return UVException(isolate, errorno, syscall, msg, path, nullptr);
808 Local<Value> UVException(Isolate* isolate,
814 Environment* env = Environment::GetCurrent(isolate);
817 msg = uv_strerror(errorno);
819 Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
820 Local<String> js_syscall = OneByteString(isolate, syscall);
821 Local<String> js_path;
822 Local<String> js_dest;
824 Local<String> js_msg = js_code;
825 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
826 js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
827 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
828 js_msg = String::Concat(js_msg, js_syscall);
830 if (path != nullptr) {
831 js_path = StringFromPath(isolate, path);
833 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
834 js_msg = String::Concat(js_msg, js_path);
835 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
838 if (dest != nullptr) {
839 js_dest = StringFromPath(isolate, dest);
841 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
842 js_msg = String::Concat(js_msg, js_dest);
843 js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
846 Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
848 // TODO(piscisaureus) errno should probably go; the user has no way of
849 // knowing which uv errno value maps to which error.
850 e->Set(env->errno_string(), Integer::New(isolate, errorno));
851 e->Set(env->code_string(), js_code);
852 e->Set(env->syscall_string(), js_syscall);
853 if (!js_path.IsEmpty())
854 e->Set(env->path_string(), js_path);
855 if (!js_dest.IsEmpty())
856 e->Set(env->dest_string(), js_dest);
862 // Look up environment variable unless running as setuid root.
863 inline const char* secure_getenv(const char* key) {
865 if (getuid() != geteuid() || getgid() != getegid())
873 // Does about the same as strerror(),
874 // but supports all windows error messages
875 static const char *winapi_strerror(const int errorno, bool* must_free) {
876 char *errmsg = nullptr;
878 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
879 FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
880 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
885 // Remove trailing newlines
886 for (int i = strlen(errmsg) - 1;
887 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
893 // FormatMessage failed
895 return "Unknown error";
900 Local<Value> WinapiErrnoException(Isolate* isolate,
905 Environment* env = Environment::GetCurrent(isolate);
907 bool must_free = false;
908 if (!msg || !msg[0]) {
909 msg = winapi_strerror(errorno, &must_free);
911 Local<String> message = OneByteString(env->isolate(), msg);
914 Local<String> cons1 =
915 String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
916 Local<String> cons2 =
917 String::Concat(cons1, String::NewFromUtf8(isolate, path));
918 Local<String> cons3 =
919 String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
920 e = Exception::Error(cons3);
922 e = Exception::Error(message);
925 Local<Object> obj = e->ToObject(env->isolate());
926 obj->Set(env->errno_string(), Integer::New(isolate, errorno));
928 if (path != nullptr) {
929 obj->Set(env->path_string(), String::NewFromUtf8(isolate, path));
932 if (syscall != nullptr) {
933 obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
937 LocalFree((HLOCAL)msg);
944 void* ArrayBufferAllocator::Allocate(size_t size) {
945 if (env_ == nullptr || !env_->array_buffer_allocator_info()->no_zero_fill())
946 return calloc(size, 1);
947 env_->array_buffer_allocator_info()->reset_fill_flag();
951 static bool DomainHasErrorHandler(const Environment* env,
952 const Local<Object>& domain) {
953 HandleScope scope(env->isolate());
955 Local<Value> domain_event_listeners_v = domain->Get(env->events_string());
956 if (!domain_event_listeners_v->IsObject())
959 Local<Object> domain_event_listeners_o =
960 domain_event_listeners_v.As<Object>();
962 Local<Value> domain_error_listeners_v =
963 domain_event_listeners_o->Get(env->error_string());
965 if (domain_error_listeners_v->IsFunction() ||
966 (domain_error_listeners_v->IsArray() &&
967 domain_error_listeners_v.As<Array>()->Length() > 0))
973 static bool TopDomainHasErrorHandler(const Environment* env) {
974 HandleScope scope(env->isolate());
976 if (!env->using_domains())
979 Local<Array> domains_stack_array = env->domains_stack_array().As<Array>();
980 if (domains_stack_array->Length() == 0)
983 uint32_t domains_stack_length = domains_stack_array->Length();
984 if (domains_stack_length == 0)
987 Local<Value> top_domain_v =
988 domains_stack_array->Get(domains_stack_length - 1);
990 if (!top_domain_v->IsObject())
993 Local<Object> top_domain = top_domain_v.As<Object>();
994 if (DomainHasErrorHandler(env, top_domain))
1001 static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
1002 HandleScope scope(isolate);
1004 Environment* env = Environment::GetCurrent(isolate);
1005 Local<Object> process_object = env->process_object();
1006 Local<String> emitting_top_level_domain_error_key =
1007 env->emitting_top_level_domain_error_string();
1008 bool isEmittingTopLevelDomainError =
1009 process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
1011 return isEmittingTopLevelDomainError || !TopDomainHasErrorHandler(env);
1015 void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
1016 Environment* env = Environment::GetCurrent(args);
1018 if (env->using_domains())
1020 env->set_using_domains(true);
1022 HandleScope scope(env->isolate());
1023 Local<Object> process_object = env->process_object();
1025 Local<String> tick_callback_function_key = env->tick_domain_cb_string();
1026 Local<Function> tick_callback_function =
1027 process_object->Get(tick_callback_function_key).As<Function>();
1029 if (!tick_callback_function->IsFunction()) {
1030 fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
1034 process_object->Set(env->tick_callback_string(), tick_callback_function);
1035 env->set_tick_callback_function(tick_callback_function);
1037 CHECK(args[0]->IsArray());
1038 env->set_domain_array(args[0].As<Array>());
1040 CHECK(args[1]->IsArray());
1041 env->set_domains_stack_array(args[1].As<Array>());
1043 // Do a little housekeeping.
1044 env->process_object()->Delete(
1045 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse"));
1047 uint32_t* const fields = env->domain_flag()->fields();
1048 uint32_t const fields_count = env->domain_flag()->fields_count();
1050 Local<ArrayBuffer> array_buffer =
1051 ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1053 args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1056 void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
1057 args.GetIsolate()->RunMicrotasks();
1061 void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
1062 Environment* env = Environment::GetCurrent(args);
1064 CHECK(args[0]->IsFunction());
1065 CHECK(args[1]->IsObject());
1067 env->set_tick_callback_function(args[0].As<Function>());
1069 env->SetMethod(args[1].As<Object>(), "runMicrotasks", RunMicrotasks);
1071 // Do a little housekeeping.
1072 env->process_object()->Delete(
1073 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
1075 // Values use to cross communicate with processNextTick.
1076 uint32_t* const fields = env->tick_info()->fields();
1077 uint32_t const fields_count = env->tick_info()->fields_count();
1079 Local<ArrayBuffer> array_buffer =
1080 ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1082 args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
1085 void PromiseRejectCallback(PromiseRejectMessage message) {
1086 Local<Promise> promise = message.GetPromise();
1087 Isolate* isolate = promise->GetIsolate();
1088 Local<Value> value = message.GetValue();
1089 Local<Integer> event = Integer::New(isolate, message.GetEvent());
1091 Environment* env = Environment::GetCurrent(isolate);
1092 Local<Function> callback = env->promise_reject_function();
1094 if (value.IsEmpty())
1095 value = Undefined(isolate);
1097 Local<Value> args[] = { event, promise, value };
1098 Local<Object> process = env->process_object();
1100 callback->Call(process, ARRAY_SIZE(args), args);
1103 void SetupPromises(const FunctionCallbackInfo<Value>& args) {
1104 Environment* env = Environment::GetCurrent(args);
1105 Isolate* isolate = env->isolate();
1107 CHECK(args[0]->IsFunction());
1109 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
1110 env->set_promise_reject_function(args[0].As<Function>());
1112 env->process_object()->Delete(
1113 FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupPromises"));
1117 Local<Value> MakeCallback(Environment* env,
1119 const Local<Function> callback,
1121 Local<Value> argv[]) {
1122 // If you hit this assertion, you forgot to enter the v8::Context first.
1123 CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
1125 Local<Function> pre_fn = env->async_hooks_pre_function();
1126 Local<Function> post_fn = env->async_hooks_post_function();
1127 Local<Object> object, domain;
1128 bool ran_init_callback = false;
1129 bool has_domain = false;
1131 // TODO(trevnorris): Adding "_asyncQueue" to the "this" in the init callback
1132 // is a horrible way to detect usage. Rethink how detection should happen.
1133 if (recv->IsObject()) {
1134 object = recv.As<Object>();
1135 Local<Value> async_queue_v = object->Get(env->async_queue_string());
1136 if (async_queue_v->IsObject())
1137 ran_init_callback = true;
1140 if (env->using_domains()) {
1141 CHECK(recv->IsObject());
1142 Local<Value> domain_v = object->Get(env->domain_string());
1143 has_domain = domain_v->IsObject();
1145 domain = domain_v.As<Object>();
1146 if (domain->Get(env->disposed_string())->IsTrue())
1147 return Undefined(env->isolate());
1152 try_catch.SetVerbose(true);
1155 Local<Value> enter_v = domain->Get(env->enter_string());
1156 if (enter_v->IsFunction()) {
1157 enter_v.As<Function>()->Call(domain, 0, nullptr);
1158 if (try_catch.HasCaught())
1159 return Undefined(env->isolate());
1163 if (ran_init_callback && !pre_fn.IsEmpty()) {
1164 try_catch.SetVerbose(false);
1165 pre_fn->Call(object, 0, nullptr);
1166 if (try_catch.HasCaught())
1167 FatalError("node::MakeCallback", "pre hook threw");
1168 try_catch.SetVerbose(true);
1171 Local<Value> ret = callback->Call(recv, argc, argv);
1173 if (ran_init_callback && !post_fn.IsEmpty()) {
1174 try_catch.SetVerbose(false);
1175 post_fn->Call(object, 0, nullptr);
1176 if (try_catch.HasCaught())
1177 FatalError("node::MakeCallback", "post hook threw");
1178 try_catch.SetVerbose(true);
1182 Local<Value> exit_v = domain->Get(env->exit_string());
1183 if (exit_v->IsFunction()) {
1184 exit_v.As<Function>()->Call(domain, 0, nullptr);
1185 if (try_catch.HasCaught())
1186 return Undefined(env->isolate());
1190 if (try_catch.HasCaught()) {
1191 return Undefined(env->isolate());
1194 if (!env->KickNextTick())
1195 return Undefined(env->isolate());
1202 Local<Value> MakeCallback(Environment* env,
1206 Local<Value> argv[]) {
1207 Local<Value> cb_v = recv->Get(index);
1208 CHECK(cb_v->IsFunction());
1209 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
1213 Local<Value> MakeCallback(Environment* env,
1215 Local<String> symbol,
1217 Local<Value> argv[]) {
1218 Local<Value> cb_v = recv->Get(symbol);
1219 CHECK(cb_v->IsFunction());
1220 return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
1224 Local<Value> MakeCallback(Environment* env,
1228 Local<Value> argv[]) {
1229 Local<String> method_string = OneByteString(env->isolate(), method);
1230 return MakeCallback(env, recv, method_string, argc, argv);
1234 Local<Value> MakeCallback(Isolate* isolate,
1238 Local<Value> argv[]) {
1239 EscapableHandleScope handle_scope(isolate);
1240 Local<Context> context = recv->CreationContext();
1241 Environment* env = Environment::GetCurrent(context);
1242 Context::Scope context_scope(context);
1243 return handle_scope.Escape(
1244 Local<Value>::New(isolate, MakeCallback(env, recv, method, argc, argv)));
1248 Local<Value> MakeCallback(Isolate* isolate,
1250 Local<String> symbol,
1252 Local<Value> argv[]) {
1253 EscapableHandleScope handle_scope(isolate);
1254 Local<Context> context = recv->CreationContext();
1255 Environment* env = Environment::GetCurrent(context);
1256 Context::Scope context_scope(context);
1257 return handle_scope.Escape(
1258 Local<Value>::New(isolate, MakeCallback(env, recv, symbol, argc, argv)));
1262 Local<Value> MakeCallback(Isolate* isolate,
1264 Local<Function> callback,
1266 Local<Value> argv[]) {
1267 EscapableHandleScope handle_scope(isolate);
1268 Local<Context> context = recv->CreationContext();
1269 Environment* env = Environment::GetCurrent(context);
1270 Context::Scope context_scope(context);
1271 return handle_scope.Escape(Local<Value>::New(
1273 MakeCallback(env, recv.As<Value>(), callback, argc, argv)));
1277 enum encoding ParseEncoding(const char* encoding,
1278 enum encoding default_encoding) {
1279 switch (encoding[0]) {
1282 if (encoding[1] == 't' && encoding[2] == 'f') {
1284 encoding += encoding[3] == '-' ? 4 : 3;
1285 if (encoding[0] == '8' && encoding[1] == '\0')
1287 if (strncmp(encoding, "16le", 4) == 0)
1291 } else if (encoding[1] == 'c' && encoding[2] == 's') {
1292 encoding += encoding[3] == '-' ? 4 : 3;
1293 if (encoding[0] == '2' && encoding[1] == '\0')
1299 if (encoding[1] == 'i') {
1300 if (strncmp(encoding + 2, "nary", 4) == 0)
1304 } else if (encoding[1] == 'u') {
1305 if (strncmp(encoding + 2, "ffer", 4) == 0)
1310 return default_encoding;
1315 if (strcasecmp(encoding, "utf8") == 0) {
1317 } else if (strcasecmp(encoding, "utf-8") == 0) {
1319 } else if (strcasecmp(encoding, "ascii") == 0) {
1321 } else if (strcasecmp(encoding, "base64") == 0) {
1323 } else if (strcasecmp(encoding, "ucs2") == 0) {
1325 } else if (strcasecmp(encoding, "ucs-2") == 0) {
1327 } else if (strcasecmp(encoding, "utf16le") == 0) {
1329 } else if (strcasecmp(encoding, "utf-16le") == 0) {
1331 } else if (strcasecmp(encoding, "binary") == 0) {
1333 } else if (strcasecmp(encoding, "buffer") == 0) {
1335 } else if (strcasecmp(encoding, "hex") == 0) {
1337 } else if (strcasecmp(encoding, "raw") == 0) {
1338 if (!no_deprecation) {
1339 fprintf(stderr, "'raw' (array of integers) has been removed. "
1343 } else if (strcasecmp(encoding, "raws") == 0) {
1344 if (!no_deprecation) {
1345 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1346 "Please update your code.\n");
1350 return default_encoding;
1355 enum encoding ParseEncoding(Isolate* isolate,
1356 Local<Value> encoding_v,
1357 enum encoding default_encoding) {
1358 if (!encoding_v->IsString())
1359 return default_encoding;
1361 node::Utf8Value encoding(isolate, encoding_v);
1363 return ParseEncoding(*encoding, default_encoding);
1366 Local<Value> Encode(Isolate* isolate,
1369 enum encoding encoding) {
1370 CHECK_NE(encoding, UCS2);
1371 return StringBytes::Encode(isolate, buf, len, encoding);
1374 Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
1375 return StringBytes::Encode(isolate, buf, len);
1378 // Returns -1 if the handle was not valid for decoding
1379 ssize_t DecodeBytes(Isolate* isolate,
1381 enum encoding encoding) {
1382 HandleScope scope(isolate);
1384 if (val->IsArray()) {
1385 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1391 return StringBytes::Size(isolate, val, encoding);
1394 // Returns number of bytes written.
1395 ssize_t DecodeWrite(Isolate* isolate,
1399 enum encoding encoding) {
1400 return StringBytes::Write(isolate, buf, buflen, val, encoding, nullptr);
1403 void AppendExceptionLine(Environment* env,
1405 Local<Message> message) {
1406 if (message.IsEmpty())
1409 HandleScope scope(env->isolate());
1410 Local<Object> err_obj;
1411 if (!er.IsEmpty() && er->IsObject()) {
1412 err_obj = er.As<Object>();
1414 // Do it only once per message
1415 if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
1417 err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
1420 // Print (filename):(line number): (message).
1421 node::Utf8Value filename(env->isolate(), message->GetScriptResourceName());
1422 const char* filename_string = *filename;
1423 int linenum = message->GetLineNumber();
1424 // Print line of source code.
1425 node::Utf8Value sourceline(env->isolate(), message->GetSourceLine());
1426 const char* sourceline_string = *sourceline;
1428 // Because of how node modules work, all scripts are wrapped with a
1429 // "function (module, exports, __filename, ...) {"
1430 // to provide script local variables.
1432 // When reporting errors on the first line of a script, this wrapper
1433 // function is leaked to the user. There used to be a hack here to
1434 // truncate off the first 62 characters, but it caused numerous other
1435 // problems when vm.runIn*Context() methods were used for non-module
1438 // If we ever decide to re-instate such a hack, the following steps
1441 // 1. Pass a flag around to say "this code was wrapped"
1442 // 2. Update the stack frame output so that it is also correct.
1444 // It would probably be simpler to add a line rather than add some
1445 // number of characters to the first line, since V8 truncates the
1446 // sourceline to 78 characters, and we end up not providing very much
1447 // useful debugging info to the user if we remove 62 characters.
1449 int start = message->GetStartColumn();
1450 int end = message->GetEndColumn();
1453 int max_off = sizeof(arrow) - 2;
1455 int off = snprintf(arrow,
1462 if (off > max_off) {
1466 // Print wavy underline (GetUnderline is deprecated).
1467 for (int i = 0; i < start; i++) {
1468 if (sourceline_string[i] == '\0' || off >= max_off) {
1471 CHECK_LT(off, max_off);
1472 arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
1474 for (int i = start; i < end; i++) {
1475 if (sourceline_string[i] == '\0' || off >= max_off) {
1478 CHECK_LT(off, max_off);
1481 CHECK_LE(off, max_off);
1483 arrow[off + 1] = '\0';
1485 Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
1487 // Allocation failed, just print it out
1488 if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
1491 err_obj->SetHiddenValue(env->arrow_message_string(), arrow_str);
1495 if (env->printed_error())
1497 env->set_printed_error(true);
1498 uv_tty_reset_mode();
1499 PrintErrorString("\n%s", arrow);
1503 static void ReportException(Environment* env,
1505 Local<Message> message) {
1506 HandleScope scope(env->isolate());
1508 AppendExceptionLine(env, er, message);
1510 Local<Value> trace_value;
1513 if (er->IsUndefined() || er->IsNull()) {
1514 trace_value = Undefined(env->isolate());
1516 Local<Object> err_obj = er->ToObject(env->isolate());
1518 trace_value = err_obj->Get(env->stack_string());
1519 arrow = err_obj->GetHiddenValue(env->arrow_message_string());
1522 node::Utf8Value trace(env->isolate(), trace_value);
1524 // range errors have a trace member set to undefined
1525 if (trace.length() > 0 && !trace_value->IsUndefined()) {
1526 if (arrow.IsEmpty() || !arrow->IsString()) {
1527 PrintErrorString("%s\n", *trace);
1529 node::Utf8Value arrow_string(env->isolate(), arrow);
1530 PrintErrorString("%s\n%s\n", *arrow_string, *trace);
1533 // this really only happens for RangeErrors, since they're the only
1534 // kind that won't have all this info in the trace, or when non-Error
1535 // objects are thrown manually.
1536 Local<Value> message;
1539 if (er->IsObject()) {
1540 Local<Object> err_obj = er.As<Object>();
1541 message = err_obj->Get(env->message_string());
1542 name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
1545 if (message.IsEmpty() ||
1546 message->IsUndefined() ||
1548 name->IsUndefined()) {
1549 // Not an error object. Just print as-is.
1550 String::Utf8Value message(er);
1552 PrintErrorString("%s\n", *message ? *message :
1553 "<toString() threw exception>");
1555 node::Utf8Value name_string(env->isolate(), name);
1556 node::Utf8Value message_string(env->isolate(), message);
1558 if (arrow.IsEmpty() || !arrow->IsString()) {
1559 PrintErrorString("%s: %s\n", *name_string, *message_string);
1561 node::Utf8Value arrow_string(env->isolate(), arrow);
1562 PrintErrorString("%s\n%s: %s\n",
1574 static void ReportException(Environment* env, const TryCatch& try_catch) {
1575 ReportException(env, try_catch.Exception(), try_catch.Message());
1579 // Executes a str within the current v8 context.
1580 static Local<Value> ExecuteString(Environment* env,
1581 Local<String> source,
1582 Local<String> filename) {
1583 EscapableHandleScope scope(env->isolate());
1586 // try_catch must be nonverbose to disable FatalException() handler,
1587 // we will handle exceptions ourself.
1588 try_catch.SetVerbose(false);
1590 Local<v8::Script> script = v8::Script::Compile(source, filename);
1591 if (script.IsEmpty()) {
1592 ReportException(env, try_catch);
1596 Local<Value> result = script->Run();
1597 if (result.IsEmpty()) {
1598 ReportException(env, try_catch);
1602 return scope.Escape(result);
1606 static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1607 Environment* env = Environment::GetCurrent(args);
1609 Local<Array> ary = Array::New(args.GetIsolate());
1612 for (auto w : *env->req_wrap_queue())
1613 if (w->persistent().IsEmpty() == false)
1614 ary->Set(i++, w->object());
1616 args.GetReturnValue().Set(ary);
1620 // Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1621 // implemented here for consistency with GetActiveRequests().
1622 void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1623 Environment* env = Environment::GetCurrent(args);
1625 Local<Array> ary = Array::New(env->isolate());
1628 Local<String> owner_sym = env->owner_string();
1630 for (auto w : *env->handle_wrap_queue()) {
1631 if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1633 Local<Object> object = w->object();
1634 Local<Value> owner = object->Get(owner_sym);
1635 if (owner->IsUndefined())
1637 ary->Set(i++, owner);
1640 args.GetReturnValue().Set(ary);
1644 static void Abort(const FunctionCallbackInfo<Value>& args) {
1649 static void Chdir(const FunctionCallbackInfo<Value>& args) {
1650 Environment* env = Environment::GetCurrent(args);
1652 if (args.Length() != 1 || !args[0]->IsString()) {
1653 return env->ThrowTypeError("Bad argument.");
1656 node::Utf8Value path(args.GetIsolate(), args[0]);
1657 int err = uv_chdir(*path);
1659 return env->ThrowUVException(err, "uv_chdir");
1664 static void Cwd(const FunctionCallbackInfo<Value>& args) {
1665 Environment* env = Environment::GetCurrent(args);
1667 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1668 char buf[MAX_PATH * 4];
1673 size_t cwd_len = sizeof(buf);
1674 int err = uv_cwd(buf, &cwd_len);
1676 return env->ThrowUVException(err, "uv_cwd");
1679 Local<String> cwd = String::NewFromUtf8(env->isolate(),
1681 String::kNormalString,
1683 args.GetReturnValue().Set(cwd);
1687 static void Umask(const FunctionCallbackInfo<Value>& args) {
1688 Environment* env = Environment::GetCurrent(args);
1691 if (args.Length() < 1 || args[0]->IsUndefined()) {
1693 umask(static_cast<mode_t>(old));
1694 } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1695 return env->ThrowTypeError("argument must be an integer or octal string.");
1698 if (args[0]->IsInt32()) {
1699 oct = args[0]->Uint32Value();
1702 node::Utf8Value str(env->isolate(), args[0]);
1704 // Parse the octal string.
1705 for (size_t i = 0; i < str.length(); i++) {
1707 if (c > '7' || c < '0') {
1708 return env->ThrowTypeError("invalid octal string");
1714 old = umask(static_cast<mode_t>(oct));
1717 args.GetReturnValue().Set(old);
1721 #if defined(__POSIX__) && !defined(__ANDROID__)
1723 static const uid_t uid_not_found = static_cast<uid_t>(-1);
1724 static const gid_t gid_not_found = static_cast<gid_t>(-1);
1727 static uid_t uid_by_name(const char* name) {
1735 if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1739 return uid_not_found;
1743 static char* name_by_uid(uid_t uid) {
1752 if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1754 return strdup(pp->pw_name);
1765 static gid_t gid_by_name(const char* name) {
1773 if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
1777 return gid_not_found;
1781 #if 0 // For future use.
1782 static const char* name_by_gid(gid_t gid) {
1791 if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 &&
1793 return strdup(pp->gr_name);
1805 static uid_t uid_by_name(Isolate* isolate, Local<Value> value) {
1806 if (value->IsUint32()) {
1807 return static_cast<uid_t>(value->Uint32Value());
1809 node::Utf8Value name(isolate, value);
1810 return uid_by_name(*name);
1815 static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
1816 if (value->IsUint32()) {
1817 return static_cast<gid_t>(value->Uint32Value());
1819 node::Utf8Value name(isolate, value);
1820 return gid_by_name(*name);
1825 static void GetUid(const FunctionCallbackInfo<Value>& args) {
1826 // uid_t is an uint32_t on all supported platforms.
1827 args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1831 static void GetGid(const FunctionCallbackInfo<Value>& args) {
1832 // gid_t is an uint32_t on all supported platforms.
1833 args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1837 static void GetEUid(const FunctionCallbackInfo<Value>& args) {
1838 // uid_t is an uint32_t on all supported platforms.
1839 args.GetReturnValue().Set(static_cast<uint32_t>(geteuid()));
1843 static void GetEGid(const FunctionCallbackInfo<Value>& args) {
1844 // gid_t is an uint32_t on all supported platforms.
1845 args.GetReturnValue().Set(static_cast<uint32_t>(getegid()));
1849 static void SetGid(const FunctionCallbackInfo<Value>& args) {
1850 Environment* env = Environment::GetCurrent(args);
1852 if (!args[0]->IsUint32() && !args[0]->IsString()) {
1853 return env->ThrowTypeError("setgid argument must be a number or a string");
1856 gid_t gid = gid_by_name(env->isolate(), args[0]);
1858 if (gid == gid_not_found) {
1859 return env->ThrowError("setgid group id does not exist");
1863 return env->ThrowErrnoException(errno, "setgid");
1868 static void SetEGid(const FunctionCallbackInfo<Value>& args) {
1869 Environment* env = Environment::GetCurrent(args);
1871 if (!args[0]->IsUint32() && !args[0]->IsString()) {
1872 return env->ThrowTypeError("setegid argument must be a number or string");
1875 gid_t gid = gid_by_name(env->isolate(), args[0]);
1877 if (gid == gid_not_found) {
1878 return env->ThrowError("setegid group id does not exist");
1882 return env->ThrowErrnoException(errno, "setegid");
1887 static void SetUid(const FunctionCallbackInfo<Value>& args) {
1888 Environment* env = Environment::GetCurrent(args);
1890 if (!args[0]->IsUint32() && !args[0]->IsString()) {
1891 return env->ThrowTypeError("setuid argument must be a number or a string");
1894 uid_t uid = uid_by_name(env->isolate(), args[0]);
1896 if (uid == uid_not_found) {
1897 return env->ThrowError("setuid user id does not exist");
1901 return env->ThrowErrnoException(errno, "setuid");
1906 static void SetEUid(const FunctionCallbackInfo<Value>& args) {
1907 Environment* env = Environment::GetCurrent(args);
1909 if (!args[0]->IsUint32() && !args[0]->IsString()) {
1910 return env->ThrowTypeError("seteuid argument must be a number or string");
1913 uid_t uid = uid_by_name(env->isolate(), args[0]);
1915 if (uid == uid_not_found) {
1916 return env->ThrowError("seteuid user id does not exist");
1920 return env->ThrowErrnoException(errno, "seteuid");
1925 static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1926 Environment* env = Environment::GetCurrent(args);
1928 int ngroups = getgroups(0, nullptr);
1930 if (ngroups == -1) {
1931 return env->ThrowErrnoException(errno, "getgroups");
1934 gid_t* groups = new gid_t[ngroups];
1936 ngroups = getgroups(ngroups, groups);
1938 if (ngroups == -1) {
1940 return env->ThrowErrnoException(errno, "getgroups");
1943 Local<Array> groups_list = Array::New(env->isolate(), ngroups);
1944 bool seen_egid = false;
1945 gid_t egid = getegid();
1947 for (int i = 0; i < ngroups; i++) {
1948 groups_list->Set(i, Integer::New(env->isolate(), groups[i]));
1949 if (groups[i] == egid)
1955 if (seen_egid == false) {
1956 groups_list->Set(ngroups, Integer::New(env->isolate(), egid));
1959 args.GetReturnValue().Set(groups_list);
1963 static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1964 Environment* env = Environment::GetCurrent(args);
1966 if (!args[0]->IsArray()) {
1967 return env->ThrowTypeError("argument 1 must be an array");
1970 Local<Array> groups_list = args[0].As<Array>();
1971 size_t size = groups_list->Length();
1972 gid_t* groups = new gid_t[size];
1974 for (size_t i = 0; i < size; i++) {
1975 gid_t gid = gid_by_name(env->isolate(), groups_list->Get(i));
1977 if (gid == gid_not_found) {
1979 return env->ThrowError("group name not found");
1985 int rc = setgroups(size, groups);
1989 return env->ThrowErrnoException(errno, "setgroups");
1994 static void InitGroups(const FunctionCallbackInfo<Value>& args) {
1995 Environment* env = Environment::GetCurrent(args);
1997 if (!args[0]->IsUint32() && !args[0]->IsString()) {
1998 return env->ThrowTypeError("argument 1 must be a number or a string");
2001 if (!args[1]->IsUint32() && !args[1]->IsString()) {
2002 return env->ThrowTypeError("argument 2 must be a number or a string");
2005 node::Utf8Value arg0(env->isolate(), args[0]);
2010 if (args[0]->IsUint32()) {
2011 user = name_by_uid(args[0]->Uint32Value());
2018 if (user == nullptr) {
2019 return env->ThrowError("initgroups user not found");
2022 extra_group = gid_by_name(env->isolate(), args[1]);
2024 if (extra_group == gid_not_found) {
2027 return env->ThrowError("initgroups extra group not found");
2030 int rc = initgroups(user, extra_group);
2037 return env->ThrowErrnoException(errno, "initgroups");
2041 #endif // __POSIX__ && !defined(__ANDROID__)
2044 void Exit(const FunctionCallbackInfo<Value>& args) {
2045 exit(args[0]->Int32Value());
2049 static void Uptime(const FunctionCallbackInfo<Value>& args) {
2050 Environment* env = Environment::GetCurrent(args);
2053 uv_update_time(env->event_loop());
2054 uptime = uv_now(env->event_loop()) - prog_start_time;
2056 args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
2060 void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
2061 Environment* env = Environment::GetCurrent(args);
2064 int err = uv_resident_set_memory(&rss);
2066 return env->ThrowUVException(err, "uv_resident_set_memory");
2070 HeapStatistics v8_heap_stats;
2071 env->isolate()->GetHeapStatistics(&v8_heap_stats);
2073 Local<Number> heap_total =
2074 Number::New(env->isolate(), v8_heap_stats.total_heap_size());
2075 Local<Number> heap_used =
2076 Number::New(env->isolate(), v8_heap_stats.used_heap_size());
2078 Local<Object> info = Object::New(env->isolate());
2079 info->Set(env->rss_string(), Number::New(env->isolate(), rss));
2080 info->Set(env->heap_total_string(), heap_total);
2081 info->Set(env->heap_used_string(), heap_used);
2083 args.GetReturnValue().Set(info);
2087 void Kill(const FunctionCallbackInfo<Value>& args) {
2088 Environment* env = Environment::GetCurrent(args);
2090 if (args.Length() != 2) {
2091 return env->ThrowError("Bad argument.");
2094 int pid = args[0]->Int32Value();
2095 int sig = args[1]->Int32Value();
2096 int err = uv_kill(pid, sig);
2097 args.GetReturnValue().Set(err);
2100 // used in Hrtime() below
2101 #define NANOS_PER_SEC 1000000000
2103 // Hrtime exposes libuv's uv_hrtime() high-resolution timer.
2104 // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2105 // so this function instead returns an Array with 2 entries representing seconds
2106 // and nanoseconds, to avoid any integer overflow possibility.
2107 // Pass in an Array from a previous hrtime() call to instead get a time diff.
2108 void Hrtime(const FunctionCallbackInfo<Value>& args) {
2109 Environment* env = Environment::GetCurrent(args);
2111 uint64_t t = uv_hrtime();
2113 if (args.Length() > 0) {
2114 // return a time diff tuple
2115 if (!args[0]->IsArray()) {
2116 return env->ThrowTypeError(
2117 "process.hrtime() only accepts an Array tuple.");
2119 Local<Array> inArray = Local<Array>::Cast(args[0]);
2120 uint64_t seconds = inArray->Get(0)->Uint32Value();
2121 uint64_t nanos = inArray->Get(1)->Uint32Value();
2122 t -= (seconds * NANOS_PER_SEC) + nanos;
2125 Local<Array> tuple = Array::New(env->isolate(), 2);
2126 tuple->Set(0, Integer::NewFromUnsigned(env->isolate(), t / NANOS_PER_SEC));
2127 tuple->Set(1, Integer::NewFromUnsigned(env->isolate(), t % NANOS_PER_SEC));
2128 args.GetReturnValue().Set(tuple);
2131 extern "C" void node_module_register(void* m) {
2132 struct node_module* mp = reinterpret_cast<struct node_module*>(m);
2134 if (mp->nm_flags & NM_F_BUILTIN) {
2135 mp->nm_link = modlist_builtin;
2136 modlist_builtin = mp;
2137 } else if (!node_is_initialized) {
2138 // "Linked" modules are included as part of the node project.
2139 // Like builtins they are registered *before* node::Init runs.
2140 mp->nm_flags = NM_F_LINKED;
2141 mp->nm_link = modlist_linked;
2142 modlist_linked = mp;
2148 struct node_module* get_builtin_module(const char* name) {
2149 struct node_module* mp;
2151 for (mp = modlist_builtin; mp != nullptr; mp = mp->nm_link) {
2152 if (strcmp(mp->nm_modname, name) == 0)
2156 CHECK(mp == nullptr || (mp->nm_flags & NM_F_BUILTIN) != 0);
2160 struct node_module* get_linked_module(const char* name) {
2161 struct node_module* mp;
2163 for (mp = modlist_linked; mp != nullptr; mp = mp->nm_link) {
2164 if (strcmp(mp->nm_modname, name) == 0)
2168 CHECK(mp == nullptr || (mp->nm_flags & NM_F_LINKED) != 0);
2172 typedef void (UV_DYNAMIC* extInit)(Local<Object> exports);
2174 // DLOpen is process.dlopen(module, filename).
2175 // Used to load 'module.node' dynamically shared objects.
2177 // FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2178 // when two contexts try to load the same shared object. Maybe have a shadow
2179 // cache that's a plain C list or hash table that's shared across contexts?
2180 void DLOpen(const FunctionCallbackInfo<Value>& args) {
2181 Environment* env = Environment::GetCurrent(args);
2184 CHECK_EQ(modpending, nullptr);
2186 if (args.Length() != 2) {
2187 env->ThrowError("process.dlopen takes exactly 2 arguments.");
2191 Local<Object> module = args[0]->ToObject(env->isolate()); // Cast
2192 node::Utf8Value filename(env->isolate(), args[1]); // Cast
2193 const bool is_dlopen_error = uv_dlopen(*filename, &lib);
2195 // Objects containing v14 or later modules will have registered themselves
2196 // on the pending list. Activate all of them now. At present, only one
2197 // module per object is supported.
2198 node_module* const mp = modpending;
2199 modpending = nullptr;
2201 if (is_dlopen_error) {
2202 Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
2205 // Windows needs to add the filename into the error message
2206 errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
2208 env->isolate()->ThrowException(Exception::Error(errmsg));
2212 if (mp == nullptr) {
2214 env->ThrowError("Module did not self-register.");
2217 if (mp->nm_version != NODE_MODULE_VERSION) {
2221 "Module version mismatch. Expected %d, got %d.",
2222 NODE_MODULE_VERSION, mp->nm_version);
2224 // NOTE: `mp` is allocated inside of the shared library's memory, calling
2225 // `uv_dlclose` will deallocate it
2227 env->ThrowError(errmsg);
2230 if (mp->nm_flags & NM_F_BUILTIN) {
2232 env->ThrowError("Built-in module self-registered.");
2236 mp->nm_dso_handle = lib.handle;
2237 mp->nm_link = modlist_addon;
2240 Local<String> exports_string = env->exports_string();
2241 Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());
2243 if (mp->nm_context_register_func != nullptr) {
2244 mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
2245 } else if (mp->nm_register_func != nullptr) {
2246 mp->nm_register_func(exports, module, mp->nm_priv);
2249 env->ThrowError("Module has no declared entry point.");
2253 // Tell coverity that 'handle' should not be freed when we return.
2254 // coverity[leaked_storage]
2258 static void OnFatalError(const char* location, const char* message) {
2260 PrintErrorString("FATAL ERROR: %s %s\n", location, message);
2262 PrintErrorString("FATAL ERROR: %s\n", message);
2269 NO_RETURN void FatalError(const char* location, const char* message) {
2270 OnFatalError(location, message);
2271 // to suppress compiler warning
2276 void FatalException(Isolate* isolate,
2278 Local<Message> message) {
2279 HandleScope scope(isolate);
2281 Environment* env = Environment::GetCurrent(isolate);
2282 Local<Object> process_object = env->process_object();
2283 Local<String> fatal_exception_string = env->fatal_exception_string();
2284 Local<Function> fatal_exception_function =
2285 process_object->Get(fatal_exception_string).As<Function>();
2287 if (!fatal_exception_function->IsFunction()) {
2288 // failed before the process._fatalException function was added!
2289 // this is probably pretty bad. Nothing to do but report and exit.
2290 ReportException(env, error, message);
2294 TryCatch fatal_try_catch;
2296 // Do not call FatalException when _fatalException handler throws
2297 fatal_try_catch.SetVerbose(false);
2299 // this will return true if the JS layer handled it, false otherwise
2300 Local<Value> caught =
2301 fatal_exception_function->Call(process_object, 1, &error);
2303 if (fatal_try_catch.HasCaught()) {
2304 // the fatal exception function threw, so we must exit
2305 ReportException(env, fatal_try_catch);
2309 if (false == caught->BooleanValue()) {
2310 ReportException(env, error, message);
2316 void FatalException(Isolate* isolate, const TryCatch& try_catch) {
2317 HandleScope scope(isolate);
2318 // TODO(bajtos) do not call FatalException if try_catch is verbose
2319 // (requires V8 API to expose getter for try_catch.is_verbose_)
2320 FatalException(isolate, try_catch.Exception(), try_catch.Message());
2324 void OnMessage(Local<Message> message, Local<Value> error) {
2325 // The current version of V8 sends messages for errors only
2326 // (thus `error` is always set).
2327 FatalException(Isolate::GetCurrent(), error, message);
2331 static void Binding(const FunctionCallbackInfo<Value>& args) {
2332 Environment* env = Environment::GetCurrent(args);
2334 Local<String> module = args[0]->ToString(env->isolate());
2335 node::Utf8Value module_v(env->isolate(), module);
2337 Local<Object> cache = env->binding_cache_object();
2338 Local<Object> exports;
2340 if (cache->Has(module)) {
2341 exports = cache->Get(module)->ToObject(env->isolate());
2342 args.GetReturnValue().Set(exports);
2346 // Append a string to process.moduleLoadList
2348 snprintf(buf, sizeof(buf), "Binding %s", *module_v);
2350 Local<Array> modules = env->module_load_list_array();
2351 uint32_t l = modules->Length();
2352 modules->Set(l, OneByteString(env->isolate(), buf));
2354 node_module* mod = get_builtin_module(*module_v);
2355 if (mod != nullptr) {
2356 exports = Object::New(env->isolate());
2357 // Internal bindings don't have a "module" object, only exports.
2358 CHECK_EQ(mod->nm_register_func, nullptr);
2359 CHECK_NE(mod->nm_context_register_func, nullptr);
2360 Local<Value> unused = Undefined(env->isolate());
2361 mod->nm_context_register_func(exports, unused,
2362 env->context(), mod->nm_priv);
2363 cache->Set(module, exports);
2364 } else if (!strcmp(*module_v, "constants")) {
2365 exports = Object::New(env->isolate());
2366 DefineConstants(exports);
2367 cache->Set(module, exports);
2368 } else if (!strcmp(*module_v, "natives")) {
2369 exports = Object::New(env->isolate());
2370 DefineJavaScript(env, exports);
2371 cache->Set(module, exports);
2376 "No such module: %s",
2378 return env->ThrowError(errmsg);
2381 args.GetReturnValue().Set(exports);
2384 static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
2385 Environment* env = Environment::GetCurrent(args.GetIsolate());
2387 Local<String> module = args[0]->ToString(env->isolate());
2389 Local<Object> cache = env->binding_cache_object();
2390 Local<Value> exports_v = cache->Get(module);
2392 if (exports_v->IsObject())
2393 return args.GetReturnValue().Set(exports_v.As<Object>());
2395 node::Utf8Value module_v(env->isolate(), module);
2396 node_module* mod = get_linked_module(*module_v);
2398 if (mod == nullptr) {
2402 "No such module was linked: %s",
2404 return env->ThrowError(errmsg);
2407 Local<Object> exports = Object::New(env->isolate());
2409 if (mod->nm_context_register_func != nullptr) {
2410 mod->nm_context_register_func(exports,
2414 } else if (mod->nm_register_func != nullptr) {
2415 mod->nm_register_func(exports, module, mod->nm_priv);
2417 return env->ThrowError("Linked module has no declared entry point.");
2420 cache->Set(module, exports);
2422 args.GetReturnValue().Set(exports);
2425 static void ProcessTitleGetter(Local<String> property,
2426 const PropertyCallbackInfo<Value>& info) {
2428 uv_get_process_title(buffer, sizeof(buffer));
2429 info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer));
2433 static void ProcessTitleSetter(Local<String> property,
2435 const PropertyCallbackInfo<void>& info) {
2436 node::Utf8Value title(info.GetIsolate(), value);
2437 // TODO(piscisaureus): protect with a lock
2438 uv_set_process_title(*title);
2442 static void EnvGetter(Local<String> property,
2443 const PropertyCallbackInfo<Value>& info) {
2444 Isolate* isolate = info.GetIsolate();
2446 node::Utf8Value key(isolate, property);
2447 const char* val = getenv(*key);
2449 return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val));
2452 String::Value key(property);
2453 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
2454 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2456 ARRAY_SIZE(buffer));
2457 // If result >= sizeof buffer the buffer was too small. That should never
2458 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2460 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2461 result < ARRAY_SIZE(buffer)) {
2462 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2463 Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
2464 return info.GetReturnValue().Set(rc);
2470 static void EnvSetter(Local<String> property,
2472 const PropertyCallbackInfo<Value>& info) {
2474 node::Utf8Value key(info.GetIsolate(), property);
2475 node::Utf8Value val(info.GetIsolate(), value);
2476 setenv(*key, *val, 1);
2478 String::Value key(property);
2479 String::Value val(value);
2480 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2481 // Environment variables that start with '=' are read-only.
2482 if (key_ptr[0] != L'=') {
2483 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2486 // Whether it worked or not, always return rval.
2487 info.GetReturnValue().Set(value);
2491 static void EnvQuery(Local<String> property,
2492 const PropertyCallbackInfo<Integer>& info) {
2493 int32_t rc = -1; // Not found unless proven otherwise.
2495 node::Utf8Value key(info.GetIsolate(), property);
2499 String::Value key(property);
2500 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2501 if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
2502 GetLastError() == ERROR_SUCCESS) {
2504 if (key_ptr[0] == L'=') {
2505 // Environment variables that start with '=' are hidden and read-only.
2506 rc = static_cast<int32_t>(v8::ReadOnly) |
2507 static_cast<int32_t>(v8::DontDelete) |
2508 static_cast<int32_t>(v8::DontEnum);
2513 info.GetReturnValue().Set(rc);
2517 static void EnvDeleter(Local<String> property,
2518 const PropertyCallbackInfo<Boolean>& info) {
2521 node::Utf8Value key(info.GetIsolate(), property);
2522 rc = getenv(*key) != nullptr;
2526 String::Value key(property);
2527 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2528 if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, nullptr)) {
2529 // Deletion failed. Return true if the key wasn't there in the first place,
2530 // false if it is still there.
2531 rc = GetEnvironmentVariableW(key_ptr, nullptr, 0) == 0 &&
2532 GetLastError() != ERROR_SUCCESS;
2535 info.GetReturnValue().Set(rc);
2539 static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2540 Isolate* isolate = info.GetIsolate();
2543 while (environ[size])
2546 Local<Array> envarr = Array::New(isolate, size);
2548 for (int i = 0; i < size; ++i) {
2549 const char* var = environ[i];
2550 const char* s = strchr(var, '=');
2551 const int length = s ? s - var : strlen(var);
2552 Local<String> name = String::NewFromUtf8(isolate,
2554 String::kNormalString,
2556 envarr->Set(i, name);
2559 WCHAR* environment = GetEnvironmentStringsW();
2560 if (environment == nullptr)
2561 return; // This should not happen.
2562 Local<Array> envarr = Array::New(isolate);
2563 WCHAR* p = environment;
2568 // If the key starts with '=' it is a hidden environment variable.
2572 s = wcschr(p, L'=');
2577 const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2578 const size_t two_byte_buffer_len = s - p;
2579 Local<String> value = String::NewFromTwoByte(isolate,
2581 String::kNormalString,
2582 two_byte_buffer_len);
2583 envarr->Set(i++, value);
2584 p = s + wcslen(s) + 1;
2586 FreeEnvironmentStringsW(environment);
2589 info.GetReturnValue().Set(envarr);
2593 static Local<Object> GetFeatures(Environment* env) {
2594 EscapableHandleScope scope(env->isolate());
2596 Local<Object> obj = Object::New(env->isolate());
2597 #if defined(DEBUG) && DEBUG
2598 Local<Value> debug = True(env->isolate());
2600 Local<Value> debug = False(env->isolate());
2601 #endif // defined(DEBUG) && DEBUG
2603 obj->Set(env->debug_string(), debug);
2605 obj->Set(env->uv_string(), True(env->isolate()));
2606 // TODO(bnoordhuis) ping libuv
2607 obj->Set(env->ipv6_lc_string(), True(env->isolate()));
2609 #ifdef OPENSSL_NPN_NEGOTIATED
2610 Local<Boolean> tls_npn = True(env->isolate());
2612 Local<Boolean> tls_npn = False(env->isolate());
2614 obj->Set(env->tls_npn_string(), tls_npn);
2616 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2617 Local<Boolean> tls_sni = True(env->isolate());
2619 Local<Boolean> tls_sni = False(env->isolate());
2621 obj->Set(env->tls_sni_string(), tls_sni);
2623 #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2624 Local<Boolean> tls_ocsp = True(env->isolate());
2626 Local<Boolean> tls_ocsp = False(env->isolate());
2627 #endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb)
2628 obj->Set(env->tls_ocsp_string(), tls_ocsp);
2630 obj->Set(env->tls_string(),
2631 Boolean::New(env->isolate(),
2632 get_builtin_module("crypto") != nullptr));
2634 return scope.Escape(obj);
2638 static void DebugPortGetter(Local<String> property,
2639 const PropertyCallbackInfo<Value>& info) {
2640 info.GetReturnValue().Set(debug_port);
2644 static void DebugPortSetter(Local<String> property,
2646 const PropertyCallbackInfo<void>& info) {
2647 debug_port = value->Int32Value();
2651 static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2652 static void DebugPause(const FunctionCallbackInfo<Value>& args);
2653 static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2656 void NeedImmediateCallbackGetter(Local<String> property,
2657 const PropertyCallbackInfo<Value>& info) {
2658 Environment* env = Environment::GetCurrent(info);
2659 const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2660 bool active = uv_is_active(
2661 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2662 info.GetReturnValue().Set(active);
2666 static void NeedImmediateCallbackSetter(
2667 Local<String> property,
2669 const PropertyCallbackInfo<void>& info) {
2670 Environment* env = Environment::GetCurrent(info);
2672 uv_check_t* immediate_check_handle = env->immediate_check_handle();
2673 bool active = uv_is_active(
2674 reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2676 if (active == value->BooleanValue())
2679 uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2682 uv_check_stop(immediate_check_handle);
2683 uv_idle_stop(immediate_idle_handle);
2685 uv_check_start(immediate_check_handle, CheckImmediate);
2686 // Idle handle is needed only to stop the event loop from blocking in poll.
2687 uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2692 void SetIdle(uv_prepare_t* handle) {
2693 Environment* env = Environment::from_idle_prepare_handle(handle);
2694 env->isolate()->GetCpuProfiler()->SetIdle(true);
2698 void ClearIdle(uv_check_t* handle) {
2699 Environment* env = Environment::from_idle_check_handle(handle);
2700 env->isolate()->GetCpuProfiler()->SetIdle(false);
2704 void StartProfilerIdleNotifier(Environment* env) {
2705 uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2706 uv_check_start(env->idle_check_handle(), ClearIdle);
2710 void StopProfilerIdleNotifier(Environment* env) {
2711 uv_prepare_stop(env->idle_prepare_handle());
2712 uv_check_stop(env->idle_check_handle());
2716 void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2717 Environment* env = Environment::GetCurrent(args);
2718 StartProfilerIdleNotifier(env);
2722 void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2723 Environment* env = Environment::GetCurrent(args);
2724 StopProfilerIdleNotifier(env);
2728 #define READONLY_PROPERTY(obj, str, var) \
2730 obj->ForceSet(OneByteString(env->isolate(), str), var, v8::ReadOnly); \
2733 #define READONLY_DONT_ENUM_PROPERTY(obj, str, var) \
2735 obj->ForceSet(OneByteString(env->isolate(), str), \
2737 static_cast<v8::PropertyAttribute>(v8::ReadOnly | \
2742 void SetupProcessObject(Environment* env,
2744 const char* const* argv,
2746 const char* const* exec_argv) {
2747 HandleScope scope(env->isolate());
2749 Local<Object> process = env->process_object();
2751 process->SetAccessor(env->title_string(),
2754 env->as_external());
2757 READONLY_PROPERTY(process,
2759 FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
2761 // process.moduleLoadList
2762 READONLY_PROPERTY(process,
2764 env->module_load_list_array());
2767 Local<Object> versions = Object::New(env->isolate());
2768 READONLY_PROPERTY(process, "versions", versions);
2770 const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2772 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
2774 NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
2775 READONLY_PROPERTY(versions,
2777 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
2779 // +1 to get rid of the leading 'v'
2780 READONLY_PROPERTY(versions,
2782 OneByteString(env->isolate(), NODE_VERSION + 1));
2783 READONLY_PROPERTY(versions,
2785 OneByteString(env->isolate(), V8::GetVersion()));
2786 READONLY_PROPERTY(versions,
2788 OneByteString(env->isolate(), uv_version_string()));
2789 READONLY_PROPERTY(versions,
2791 FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
2792 READONLY_PROPERTY(versions,
2794 FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
2796 #if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
2797 READONLY_PROPERTY(versions,
2799 OneByteString(env->isolate(), U_ICU_VERSION));
2802 const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
2806 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
2808 // process._promiseRejectEvent
2809 Local<Object> promiseRejectEvent = Object::New(env->isolate());
2810 READONLY_DONT_ENUM_PROPERTY(process,
2811 "_promiseRejectEvent",
2812 promiseRejectEvent);
2813 READONLY_PROPERTY(promiseRejectEvent,
2815 Integer::New(env->isolate(),
2816 v8::kPromiseRejectWithNoHandler));
2817 READONLY_PROPERTY(promiseRejectEvent,
2819 Integer::New(env->isolate(),
2820 v8::kPromiseHandlerAddedAfterReject));
2823 // Stupid code to slice out the version string.
2824 { // NOLINT(whitespace/braces)
2827 for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2828 c = OPENSSL_VERSION_TEXT[i];
2829 if ('0' <= c && c <= '9') {
2830 for (j = i + 1; j < k; ++j) {
2831 c = OPENSSL_VERSION_TEXT[j];
2841 OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
2846 READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH));
2849 READONLY_PROPERTY(process,
2851 OneByteString(env->isolate(), NODE_PLATFORM));
2854 Local<Object> release = Object::New(env->isolate());
2855 READONLY_PROPERTY(process, "release", release);
2856 READONLY_PROPERTY(release, "name", OneByteString(env->isolate(), "node"));
2858 #if NODE_VERSION_IS_LTS
2859 READONLY_PROPERTY(release, "lts",
2860 OneByteString(env->isolate(), NODE_VERSION_LTS_CODENAME));
2863 // if this is a release build and no explicit base has been set
2864 // substitute the standard release download URL
2865 #ifndef NODE_RELEASE_URLBASE
2866 # if NODE_VERSION_IS_RELEASE
2867 # define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
2871 #if defined(NODE_RELEASE_URLBASE)
2872 # define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
2873 # define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
2875 READONLY_PROPERTY(release,
2877 OneByteString(env->isolate(),
2878 NODE_RELEASE_URLFPFX ".tar.gz"));
2879 READONLY_PROPERTY(release,
2881 OneByteString(env->isolate(),
2882 NODE_RELEASE_URLFPFX "-headers.tar.gz"));
2884 READONLY_PROPERTY(release,
2886 OneByteString(env->isolate(),
2887 strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-"
2888 NODE_ARCH "/node.lib"
2889 : NODE_RELEASE_URLPFX
2890 "win-x86/node.lib"));
2895 Local<Array> arguments = Array::New(env->isolate(), argc);
2896 for (int i = 0; i < argc; ++i) {
2897 arguments->Set(i, String::NewFromUtf8(env->isolate(), argv[i]));
2899 process->Set(env->argv_string(), arguments);
2902 Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
2903 for (int i = 0; i < exec_argc; ++i) {
2904 exec_arguments->Set(i, String::NewFromUtf8(env->isolate(), exec_argv[i]));
2906 process->Set(env->exec_argv_string(), exec_arguments);
2908 // create process.env
2909 Local<ObjectTemplate> process_env_template =
2910 ObjectTemplate::New(env->isolate());
2911 process_env_template->SetNamedPropertyHandler(EnvGetter,
2916 env->as_external());
2917 Local<Object> process_env = process_env_template->NewInstance();
2918 process->Set(env->env_string(), process_env);
2920 READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
2921 READONLY_PROPERTY(process, "features", GetFeatures(env));
2922 process->SetAccessor(env->need_imm_cb_string(),
2923 NeedImmediateCallbackGetter,
2924 NeedImmediateCallbackSetter,
2925 env->as_external());
2929 READONLY_PROPERTY(process,
2931 String::NewFromUtf8(env->isolate(), eval_string));
2936 READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
2940 if (syntax_check_only) {
2941 READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
2944 // -i, --interactive
2946 READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
2949 if (preload_module_count) {
2950 CHECK(preload_modules);
2951 Local<Array> array = Array::New(env->isolate());
2952 for (unsigned int i = 0; i < preload_module_count; ++i) {
2953 Local<String> module = String::NewFromUtf8(env->isolate(),
2954 preload_modules[i]);
2955 array->Set(i, module);
2957 READONLY_PROPERTY(process,
2961 delete[] preload_modules;
2962 preload_modules = nullptr;
2963 preload_module_count = 0;
2967 if (no_deprecation) {
2968 READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
2971 // --throw-deprecation
2972 if (throw_deprecation) {
2973 READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
2978 READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
2981 // --trace-deprecation
2982 if (trace_deprecation) {
2983 READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
2986 // --security-revert flags
2987 #define V(code, _, __) \
2989 if (IsReverted(REVERT_ ## code)) { \
2990 READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
2996 size_t exec_path_len = 2 * PATH_MAX;
2997 char* exec_path = new char[exec_path_len];
2998 Local<String> exec_path_value;
2999 if (uv_exepath(exec_path, &exec_path_len) == 0) {
3000 exec_path_value = String::NewFromUtf8(env->isolate(),
3002 String::kNormalString,
3005 exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
3007 process->Set(env->exec_path_string(), exec_path_value);
3010 process->SetAccessor(env->debug_port_string(),
3013 env->as_external());
3015 // define various internal methods
3016 env->SetMethod(process,
3017 "_startProfilerIdleNotifier",
3018 StartProfilerIdleNotifier);
3019 env->SetMethod(process,
3020 "_stopProfilerIdleNotifier",
3021 StopProfilerIdleNotifier);
3022 env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
3023 env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
3024 env->SetMethod(process, "reallyExit", Exit);
3025 env->SetMethod(process, "abort", Abort);
3026 env->SetMethod(process, "chdir", Chdir);
3027 env->SetMethod(process, "cwd", Cwd);
3029 env->SetMethod(process, "umask", Umask);
3031 #if defined(__POSIX__) && !defined(__ANDROID__)
3032 env->SetMethod(process, "getuid", GetUid);
3033 env->SetMethod(process, "geteuid", GetEUid);
3034 env->SetMethod(process, "setuid", SetUid);
3035 env->SetMethod(process, "seteuid", SetEUid);
3037 env->SetMethod(process, "setgid", SetGid);
3038 env->SetMethod(process, "setegid", SetEGid);
3039 env->SetMethod(process, "getgid", GetGid);
3040 env->SetMethod(process, "getegid", GetEGid);
3042 env->SetMethod(process, "getgroups", GetGroups);
3043 env->SetMethod(process, "setgroups", SetGroups);
3044 env->SetMethod(process, "initgroups", InitGroups);
3045 #endif // __POSIX__ && !defined(__ANDROID__)
3047 env->SetMethod(process, "_kill", Kill);
3049 env->SetMethod(process, "_debugProcess", DebugProcess);
3050 env->SetMethod(process, "_debugPause", DebugPause);
3051 env->SetMethod(process, "_debugEnd", DebugEnd);
3053 env->SetMethod(process, "hrtime", Hrtime);
3055 env->SetMethod(process, "dlopen", DLOpen);
3057 env->SetMethod(process, "uptime", Uptime);
3058 env->SetMethod(process, "memoryUsage", MemoryUsage);
3060 env->SetMethod(process, "binding", Binding);
3061 env->SetMethod(process, "_linkedBinding", LinkedBinding);
3063 env->SetMethod(process, "_setupNextTick", SetupNextTick);
3064 env->SetMethod(process, "_setupPromises", SetupPromises);
3065 env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
3067 // pre-set _events object for faster emit checks
3068 process->Set(env->events_string(), Object::New(env->isolate()));
3072 #undef READONLY_PROPERTY
3075 static void AtExit() {
3076 uv_tty_reset_mode();
3080 static void SignalExit(int signo) {
3081 uv_tty_reset_mode();
3083 // FreeBSD has a nasty bug, see RegisterSignalHandler for details
3084 struct sigaction sa;
3085 memset(&sa, 0, sizeof(sa));
3086 sa.sa_handler = SIG_DFL;
3087 CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
3093 // Most of the time, it's best to use `console.error` to write
3094 // to the process.stderr stream. However, in some cases, such as
3095 // when debugging the stream.Writable class or the process.nextTick
3096 // function, it is useful to bypass JavaScript entirely.
3097 static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3098 CHECK(args.Length() == 1 && args[0]->IsString() &&
3099 "must be called with a single string");
3100 node::Utf8Value message(args.GetIsolate(), args[0]);
3101 PrintErrorString("%s\n", *message);
3106 void LoadEnvironment(Environment* env) {
3107 HandleScope handle_scope(env->isolate());
3109 env->isolate()->SetFatalErrorHandler(node::OnFatalError);
3110 env->isolate()->AddMessageListener(OnMessage);
3112 // Compile, execute the src/node.js file. (Which was included as static C
3113 // string in node_natives.h. 'native_node' is the string containing that
3116 // The node.js file returns a function 'f'
3121 // Disable verbose mode to stop FatalException() handler from trying
3122 // to handle the exception. Errors this early in the start-up phase
3123 // are not safe to ignore.
3124 try_catch.SetVerbose(false);
3126 Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
3127 Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
3128 if (try_catch.HasCaught()) {
3129 ReportException(env, try_catch);
3132 CHECK(f_value->IsFunction());
3133 Local<Function> f = Local<Function>::Cast(f_value);
3135 // Now we call 'f' with the 'process' variable that we've built up with
3136 // all our bindings. Inside node.js we'll take care of assigning things to
3139 // We start the process this way in order to be more modular. Developers
3140 // who do not like how 'src/node.js' setups the module system but do like
3141 // Node's I/O bindings may want to replace 'f' with their own function.
3143 // Add a reference to the global object
3144 Local<Object> global = env->context()->Global();
3146 #if defined HAVE_DTRACE || defined HAVE_ETW
3147 InitDTrace(env, global);
3150 #if defined HAVE_LTTNG
3151 InitLTTNG(env, global);
3154 #if defined HAVE_PERFCTR
3155 InitPerfCounters(env, global);
3158 // Enable handling of uncaught exceptions
3159 // (FatalException(), break on uncaught exception in debugger)
3161 // This is not strictly necessary since it's almost impossible
3162 // to attach the debugger fast enought to break on exception
3163 // thrown during process startup.
3164 try_catch.SetVerbose(true);
3166 env->SetMethod(env->process_object(), "_rawDebug", RawDebug);
3168 Local<Value> arg = env->process_object();
3169 f->Call(global, 1, &arg);
3172 static void PrintHelp();
3174 static bool ParseDebugOpt(const char* arg) {
3175 const char* port = nullptr;
3177 if (!strcmp(arg, "--debug")) {
3178 use_debug_agent = true;
3179 } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
3180 use_debug_agent = true;
3181 port = arg + sizeof("--debug=") - 1;
3182 } else if (!strcmp(arg, "--debug-brk")) {
3183 use_debug_agent = true;
3184 debug_wait_connect = true;
3185 } else if (!strncmp(arg, "--debug-brk=", sizeof("--debug-brk=") - 1)) {
3186 use_debug_agent = true;
3187 debug_wait_connect = true;
3188 port = arg + sizeof("--debug-brk=") - 1;
3189 } else if (!strncmp(arg, "--debug-port=", sizeof("--debug-port=") - 1)) {
3190 port = arg + sizeof("--debug-port=") - 1;
3195 if (port != nullptr) {
3196 debug_port = atoi(port);
3197 if (debug_port < 1024 || debug_port > 65535) {
3198 fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
3207 static void PrintHelp() {
3208 // XXX: If you add an option here, please also add it to doc/node.1 and
3209 // doc/api/cli.markdown
3210 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
3211 " node debug script.js [arguments] \n"
3214 " -v, --version print Node.js version\n"
3215 " -e, --eval script evaluate script\n"
3216 " -p, --print evaluate script and print result\n"
3217 " -c, --check syntax check script without executing\n"
3218 " -i, --interactive always enter the REPL even if stdin\n"
3219 " does not appear to be a terminal\n"
3220 " -r, --require module to preload (option can be repeated)\n"
3221 " --no-deprecation silence deprecation warnings\n"
3222 " --trace-deprecation show stack traces on deprecations\n"
3223 " --throw-deprecation throw an exception anytime a deprecated "
3224 "function is used\n"
3225 " --trace-sync-io show stack trace when use of sync IO\n"
3226 " is detected after the first tick\n"
3227 " --track-heap-objects track heap object allocations for heap "
3229 " --prof-process process v8 profiler output generated\n"
3231 " --v8-options print v8 command line options\n"
3233 " --tls-cipher-list=val use an alternative default TLS cipher list\n"
3235 #if defined(NODE_HAVE_I18N_SUPPORT)
3236 " --icu-data-dir=dir set ICU data load path to dir\n"
3237 " (overrides NODE_ICU_DATA)\n"
3238 #if !defined(NODE_HAVE_SMALL_ICU)
3239 " note: linked-in ICU data is\n"
3244 "Environment variables:\n"
3246 "NODE_PATH ';'-separated list of directories\n"
3248 "NODE_PATH ':'-separated list of directories\n"
3250 " prefixed to the module search path.\n"
3251 "NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n"
3252 #if defined(NODE_HAVE_I18N_SUPPORT)
3253 "NODE_ICU_DATA data path for ICU (Intl object) data\n"
3254 #if !defined(NODE_HAVE_SMALL_ICU)
3255 " (will extend linked-in data)\n"
3258 "NODE_REPL_HISTORY path to the persistent REPL history file\n"
3260 "Documentation can be found at https://nodejs.org/\n");
3264 // Parse command line arguments.
3266 // argv is modified in place. exec_argv and v8_argv are out arguments that
3267 // ParseArgs() allocates memory for and stores a pointer to the output
3268 // vector in. The caller should free them with delete[].
3272 // * argv contains the arguments with node and V8 options filtered out.
3273 // * exec_argv contains both node and V8 options and nothing else.
3274 // * v8_argv contains argv[0] plus any V8 options
3275 static void ParseArgs(int* argc,
3278 const char*** exec_argv,
3280 const char*** v8_argv) {
3281 const unsigned int nargs = static_cast<unsigned int>(*argc);
3282 const char** new_exec_argv = new const char*[nargs];
3283 const char** new_v8_argv = new const char*[nargs];
3284 const char** new_argv = new const char*[nargs];
3285 const char** local_preload_modules = new const char*[nargs];
3287 for (unsigned int i = 0; i < nargs; ++i) {
3288 new_exec_argv[i] = nullptr;
3289 new_v8_argv[i] = nullptr;
3290 new_argv[i] = nullptr;
3291 local_preload_modules[i] = nullptr;
3294 // exec_argv starts with the first option, the other two start with argv[0].
3295 unsigned int new_exec_argc = 0;
3296 unsigned int new_v8_argc = 1;
3297 unsigned int new_argc = 1;
3298 new_v8_argv[0] = argv[0];
3299 new_argv[0] = argv[0];
3301 unsigned int index = 1;
3302 bool short_circuit = false;
3303 while (index < nargs && argv[index][0] == '-' && !short_circuit) {
3304 const char* const arg = argv[index];
3305 unsigned int args_consumed = 1;
3307 if (ParseDebugOpt(arg)) {
3308 // Done, consumed by ParseDebugOpt().
3309 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
3310 printf("%s\n", NODE_VERSION);
3312 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
3315 } else if (strcmp(arg, "--eval") == 0 ||
3316 strcmp(arg, "-e") == 0 ||
3317 strcmp(arg, "--print") == 0 ||
3318 strcmp(arg, "-pe") == 0 ||
3319 strcmp(arg, "-p") == 0) {
3320 bool is_eval = strchr(arg, 'e') != nullptr;
3321 bool is_print = strchr(arg, 'p') != nullptr;
3322 print_eval = print_eval || is_print;
3323 // --eval, -e and -pe always require an argument.
3324 if (is_eval == true) {
3326 eval_string = argv[index + 1];
3327 if (eval_string == nullptr) {
3328 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3331 } else if ((index + 1 < nargs) &&
3332 argv[index + 1] != nullptr &&
3333 argv[index + 1][0] != '-') {
3335 eval_string = argv[index + 1];
3336 if (strncmp(eval_string, "\\-", 2) == 0) {
3337 // Starts with "\\-": escaped expression, drop the backslash.
3341 } else if (strcmp(arg, "--require") == 0 ||
3342 strcmp(arg, "-r") == 0) {
3343 const char* module = argv[index + 1];
3344 if (module == nullptr) {
3345 fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
3349 local_preload_modules[preload_module_count++] = module;
3350 } else if (strcmp(arg, "--check") == 0 || strcmp(arg, "-c") == 0) {
3351 syntax_check_only = true;
3352 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
3354 } else if (strcmp(arg, "--no-deprecation") == 0) {
3355 no_deprecation = true;
3356 } else if (strcmp(arg, "--trace-deprecation") == 0) {
3357 trace_deprecation = true;
3358 } else if (strcmp(arg, "--trace-sync-io") == 0) {
3359 trace_sync_io = true;
3360 } else if (strcmp(arg, "--track-heap-objects") == 0) {
3361 track_heap_objects = true;
3362 } else if (strcmp(arg, "--throw-deprecation") == 0) {
3363 throw_deprecation = true;
3364 } else if (strncmp(arg, "--security-revert=", 18) == 0) {
3365 const char* cve = arg + 18;
3367 } else if (strcmp(arg, "--prof-process") == 0) {
3368 prof_process = true;
3369 short_circuit = true;
3370 } else if (strcmp(arg, "--v8-options") == 0) {
3371 new_v8_argv[new_v8_argc] = "--help";
3374 } else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
3375 default_cipher_list = arg + 18;
3377 #if defined(NODE_HAVE_I18N_SUPPORT)
3378 } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3379 icu_data_dir = arg + 15;
3381 } else if (strcmp(arg, "--expose-internals") == 0 ||
3382 strcmp(arg, "--expose_internals") == 0) {
3385 // V8 option. Pass through as-is.
3386 new_v8_argv[new_v8_argc] = arg;
3390 memcpy(new_exec_argv + new_exec_argc,
3392 args_consumed * sizeof(*argv));
3394 new_exec_argc += args_consumed;
3395 index += args_consumed;
3398 // Copy remaining arguments.
3399 const unsigned int args_left = nargs - index;
3400 memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
3401 new_argc += args_left;
3403 *exec_argc = new_exec_argc;
3404 *exec_argv = new_exec_argv;
3405 *v8_argc = new_v8_argc;
3406 *v8_argv = new_v8_argv;
3408 // Copy new_argv over argv and update argc.
3409 memcpy(argv, new_argv, new_argc * sizeof(*argv));
3411 *argc = static_cast<int>(new_argc);
3413 // Copy the preload_modules from the local array to an appropriately sized
3415 if (preload_module_count > 0) {
3416 CHECK(!preload_modules);
3417 preload_modules = new const char*[preload_module_count];
3418 memcpy(preload_modules, local_preload_modules,
3419 preload_module_count * sizeof(*preload_modules));
3421 delete[] local_preload_modules;
3425 // Called from V8 Debug Agent TCP thread.
3426 static void DispatchMessagesDebugAgentCallback(Environment* env) {
3427 // TODO(indutny): move async handle to environment
3428 uv_async_send(&dispatch_debug_messages_async);
3432 static void StartDebug(Environment* env, bool wait) {
3433 CHECK(!debugger_running);
3435 env->debugger_agent()->set_dispatch_handler(
3436 DispatchMessagesDebugAgentCallback);
3437 debugger_running = env->debugger_agent()->Start(debug_port, wait);
3438 if (debugger_running == false) {
3439 fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
3446 // Called from the main thread.
3447 static void EnableDebug(Environment* env) {
3448 CHECK(debugger_running);
3450 // Send message to enable debug in workers
3451 HandleScope handle_scope(env->isolate());
3453 Local<Object> message = Object::New(env->isolate());
3454 message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
3455 FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
3456 Local<Value> argv[] = {
3457 FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
3460 MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
3462 // Enabled debugger, possibly making it wait on a semaphore
3463 env->debugger_agent()->Enable();
3467 // Called from an arbitrary thread.
3468 static void TryStartDebugger() {
3469 // Call only async signal-safe functions here! Don't retry the exchange,
3470 // it will deadlock when the thread is interrupted inside a critical section.
3471 if (auto isolate = node_isolate.exchange(nullptr)) {
3472 v8::Debug::DebugBreak(isolate);
3473 uv_async_send(&dispatch_debug_messages_async);
3474 CHECK_EQ(nullptr, node_isolate.exchange(isolate));
3479 // Called from the main thread.
3480 static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
3481 // Synchronize with signal handler, see TryStartDebugger.
3484 isolate = node_isolate.exchange(nullptr);
3485 } while (isolate == nullptr);
3487 if (debugger_running == false) {
3488 fprintf(stderr, "Starting debugger agent.\n");
3490 HandleScope scope(isolate);
3491 Environment* env = Environment::GetCurrent(isolate);
3492 Context::Scope context_scope(env->context());
3494 StartDebug(env, false);
3498 Isolate::Scope isolate_scope(isolate);
3499 v8::Debug::ProcessDebugMessages();
3500 CHECK_EQ(nullptr, node_isolate.exchange(isolate));
3505 static void EnableDebugSignalHandler(int signo) {
3510 static void RegisterSignalHandler(int signal,
3511 void (*handler)(int signal),
3512 bool reset_handler = false) {
3513 struct sigaction sa;
3514 memset(&sa, 0, sizeof(sa));
3515 sa.sa_handler = handler;
3517 // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
3518 // in turn set for a libthr wrapper. This leads to a crash.
3519 // Work around the issue by manually setting SIG_DFL in the signal handler
3520 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
3522 sigfillset(&sa.sa_mask);
3523 CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
3527 void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3528 Environment* env = Environment::GetCurrent(args);
3530 if (args.Length() != 1) {
3531 return env->ThrowError("Invalid number of arguments.");
3537 pid = args[0]->IntegerValue();
3538 r = kill(pid, SIGUSR1);
3540 return env->ThrowErrnoException(errno, "kill");
3545 static int RegisterDebugSignalHandler() {
3546 // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3547 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
3548 // Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered.
3550 sigemptyset(&sigmask);
3551 sigaddset(&sigmask, SIGUSR1);
3552 CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
3559 DWORD WINAPI EnableDebugThreadProc(void* arg) {
3565 static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
3567 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
3571 static int RegisterDebugSignalHandler() {
3572 wchar_t mapping_name[32];
3573 HANDLE mapping_handle;
3575 LPTHREAD_START_ROUTINE* handler;
3577 pid = GetCurrentProcessId();
3579 if (GetDebugSignalHandlerMappingName(pid,
3581 ARRAY_SIZE(mapping_name)) < 0) {
3585 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
3591 if (mapping_handle == nullptr) {
3595 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3596 MapViewOfFile(mapping_handle,
3597 FILE_MAP_ALL_ACCESS,
3601 if (handler == nullptr) {
3602 CloseHandle(mapping_handle);
3606 *handler = EnableDebugThreadProc;
3608 UnmapViewOfFile(static_cast<void*>(handler));
3614 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
3615 Environment* env = Environment::GetCurrent(args);
3616 Isolate* isolate = args.GetIsolate();
3618 HANDLE process = nullptr;
3619 HANDLE thread = nullptr;
3620 HANDLE mapping = nullptr;
3621 wchar_t mapping_name[32];
3622 LPTHREAD_START_ROUTINE* handler = nullptr;
3624 if (args.Length() != 1) {
3625 env->ThrowError("Invalid number of arguments.");
3629 pid = (DWORD) args[0]->IntegerValue();
3631 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
3632 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
3636 if (process == nullptr) {
3637 isolate->ThrowException(
3638 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
3642 if (GetDebugSignalHandlerMappingName(pid,
3644 ARRAY_SIZE(mapping_name)) < 0) {
3645 env->ThrowErrnoException(errno, "sprintf");
3649 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
3650 if (mapping == nullptr) {
3651 isolate->ThrowException(WinapiErrnoException(isolate,
3653 "OpenFileMappingW"));
3657 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
3658 MapViewOfFile(mapping,
3663 if (handler == nullptr || *handler == nullptr) {
3664 isolate->ThrowException(
3665 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
3669 thread = CreateRemoteThread(process,
3676 if (thread == nullptr) {
3677 isolate->ThrowException(WinapiErrnoException(isolate,
3679 "CreateRemoteThread"));
3683 // Wait for the thread to terminate
3684 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
3685 isolate->ThrowException(WinapiErrnoException(isolate,
3687 "WaitForSingleObject"));
3692 if (process != nullptr)
3693 CloseHandle(process);
3694 if (thread != nullptr)
3695 CloseHandle(thread);
3696 if (handler != nullptr)
3697 UnmapViewOfFile(handler);
3698 if (mapping != nullptr)
3699 CloseHandle(mapping);
3704 static void DebugPause(const FunctionCallbackInfo<Value>& args) {
3705 v8::Debug::DebugBreak(args.GetIsolate());
3709 static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
3710 if (debugger_running) {
3711 Environment* env = Environment::GetCurrent(args);
3712 env->debugger_agent()->Stop();
3713 debugger_running = false;
3718 inline void PlatformInit() {
3721 sigemptyset(&sigmask);
3722 sigaddset(&sigmask, SIGUSR1);
3723 const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
3725 // Make sure file descriptors 0-2 are valid before we start logging anything.
3726 for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
3727 struct stat ignored;
3728 if (fstat(fd, &ignored) == 0)
3730 // Anything but EBADF means something is seriously wrong. We don't
3731 // have to special-case EINTR, fstat() is not interruptible.
3734 if (fd != open("/dev/null", O_RDWR))
3740 // Restore signal dispositions, the parent process may have changed them.
3741 struct sigaction act;
3742 memset(&act, 0, sizeof(act));
3744 // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
3745 // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
3746 // Counting up to SIGRTMIN doesn't work for the same reason.
3747 for (unsigned nr = 1; nr < 32; nr += 1) {
3748 if (nr == SIGKILL || nr == SIGSTOP)
3750 act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
3751 CHECK_EQ(0, sigaction(nr, &act, nullptr));
3754 RegisterSignalHandler(SIGINT, SignalExit, true);
3755 RegisterSignalHandler(SIGTERM, SignalExit, true);
3757 // Raise the open file descriptor limit.
3759 if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
3760 // Do a binary search for the limit.
3761 rlim_t min = lim.rlim_cur;
3762 rlim_t max = 1 << 20;
3763 // But if there's a defined upper bound, don't search, just set it.
3764 if (lim.rlim_max != RLIM_INFINITY) {
3769 lim.rlim_cur = min + (max - min) / 2;
3770 if (setrlimit(RLIMIT_NOFILE, &lim)) {
3775 } while (min + 1 < max);
3781 void Init(int* argc,
3784 const char*** exec_argv) {
3785 // Initialize prog_start_time to get relative uptime.
3786 prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
3788 // Make inherited handles noninheritable.
3789 uv_disable_stdio_inheritance();
3791 // init async debug messages dispatching
3792 // Main thread uses uv_default_loop
3793 uv_async_init(uv_default_loop(),
3794 &dispatch_debug_messages_async,
3795 DispatchDebugMessagesAsyncCallback);
3796 uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3798 #if defined(NODE_V8_OPTIONS)
3799 // Should come before the call to V8::SetFlagsFromCommandLine()
3800 // so the user can disable a flag --foo at run-time by passing
3801 // --no_foo from the command line.
3802 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
3805 // Parse a few arguments which are specific to Node.
3807 const char** v8_argv;
3808 ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
3810 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3811 // manually? That would give us a little more control over its runtime
3812 // behavior but it could also interfere with the user's intentions in ways
3813 // we fail to anticipate. Dillema.
3814 for (int i = 1; i < v8_argc; ++i) {
3815 if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3816 v8_is_profiling = true;
3822 // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
3823 // performance penalty of frequent EINTR wakeups when the profiler is running.
3824 // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
3825 if (v8_is_profiling) {
3826 uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
3830 #if defined(NODE_HAVE_I18N_SUPPORT)
3831 if (icu_data_dir == nullptr) {
3832 // if the parameter isn't given, use the env variable.
3833 icu_data_dir = secure_getenv("NODE_ICU_DATA");
3836 // If icu_data_dir is nullptr here, it will load the 'minimal' data.
3837 if (!i18n::InitializeICUDirectory(icu_data_dir)) {
3838 FatalError(nullptr, "Could not initialize ICU "
3839 "(check NODE_ICU_DATA or --icu-data-dir parameters)");
3842 // The const_cast doesn't violate conceptual const-ness. V8 doesn't modify
3843 // the argv array or the elements it points to.
3845 V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3847 // Anything that's still in v8_argv is not a V8 or a node option.
3848 for (int i = 1; i < v8_argc; i++) {
3849 fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3858 if (debug_wait_connect) {
3859 const char expose_debug_as[] = "--expose_debug_as=v8debug";
3860 V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3863 // Unconditionally force typed arrays to allocate outside the v8 heap. This
3864 // is to prevent memory pointers from being moved around that are returned by
3866 const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
3867 V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
3869 if (!use_debug_agent) {
3870 RegisterDebugSignalHandler();
3873 // We should set node_is_initialized here instead of in node::Start,
3874 // otherwise embedders using node::Init to initialize everything will not be
3875 // able to set it and native modules will not load for them.
3876 node_is_initialized = true;
3880 struct AtExitCallback {
3881 AtExitCallback* next_;
3882 void (*cb_)(void* arg);
3886 static AtExitCallback* at_exit_functions_;
3889 // TODO(bnoordhuis) Turn into per-context event.
3890 void RunAtExit(Environment* env) {
3891 AtExitCallback* p = at_exit_functions_;
3892 at_exit_functions_ = nullptr;
3895 AtExitCallback* q = p->next_;
3903 void AtExit(void (*cb)(void* arg), void* arg) {
3904 AtExitCallback* p = new AtExitCallback;
3907 p->next_ = at_exit_functions_;
3908 at_exit_functions_ = p;
3912 void EmitBeforeExit(Environment* env) {
3913 HandleScope handle_scope(env->isolate());
3914 Context::Scope context_scope(env->context());
3915 Local<Object> process_object = env->process_object();
3916 Local<String> exit_code = FIXED_ONE_BYTE_STRING(env->isolate(), "exitCode");
3917 Local<Value> args[] = {
3918 FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
3919 process_object->Get(exit_code)->ToInteger(env->isolate())
3921 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3925 int EmitExit(Environment* env) {
3926 // process.emit('exit')
3927 HandleScope handle_scope(env->isolate());
3928 Context::Scope context_scope(env->context());
3929 Local<Object> process_object = env->process_object();
3930 process_object->Set(env->exiting_string(), True(env->isolate()));
3932 Local<String> exitCode = env->exit_code_string();
3933 int code = process_object->Get(exitCode)->Int32Value();
3935 Local<Value> args[] = {
3937 Integer::New(env->isolate(), code)
3940 MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3942 // Reload exit code, it may be changed by `emit('exit')`
3943 return process_object->Get(exitCode)->Int32Value();
3947 // Just a convenience method
3948 Environment* CreateEnvironment(Isolate* isolate,
3949 Local<Context> context,
3951 const char* const* argv,
3953 const char* const* exec_argv) {
3955 Context::Scope context_scope(context);
3957 env = CreateEnvironment(isolate,
3965 LoadEnvironment(env);
3970 static Environment* CreateEnvironment(Isolate* isolate,
3971 Local<Context> context,
3972 NodeInstanceData* instance_data) {
3973 return CreateEnvironment(isolate,
3974 instance_data->event_loop(),
3976 instance_data->argc(),
3977 instance_data->argv(),
3978 instance_data->exec_argc(),
3979 instance_data->exec_argv());
3983 static void HandleCloseCb(uv_handle_t* handle) {
3984 Environment* env = reinterpret_cast<Environment*>(handle->data);
3985 env->FinishHandleCleanup(handle);
3989 static void HandleCleanup(Environment* env,
3990 uv_handle_t* handle,
3993 uv_close(handle, HandleCloseCb);
3997 Environment* CreateEnvironment(Isolate* isolate,
3999 Local<Context> context,
4001 const char* const* argv,
4003 const char* const* exec_argv) {
4004 HandleScope handle_scope(isolate);
4006 Context::Scope context_scope(context);
4007 Environment* env = Environment::New(context, loop);
4009 isolate->SetAutorunMicrotasks(false);
4011 uv_check_init(env->event_loop(), env->immediate_check_handle());
4013 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
4015 uv_idle_init(env->event_loop(), env->immediate_idle_handle());
4017 // Inform V8's CPU profiler when we're idle. The profiler is sampling-based
4018 // but not all samples are created equal; mark the wall clock time spent in
4019 // epoll_wait() and friends so profiling tools can filter it out. The samples
4020 // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
4021 // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
4022 // probably fortify in the API contract, namely that the last started prepare
4023 // or check watcher runs first. It's not 100% foolproof; if an add-on starts
4024 // a prepare or check watcher after us, any samples attributed to its callback
4025 // will be recorded with state=IDLE.
4026 uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
4027 uv_check_init(env->event_loop(), env->idle_check_handle());
4028 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
4029 uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
4031 // Register handle cleanups
4032 env->RegisterHandleCleanup(
4033 reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
4036 env->RegisterHandleCleanup(
4037 reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
4040 env->RegisterHandleCleanup(
4041 reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
4044 env->RegisterHandleCleanup(
4045 reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
4049 if (v8_is_profiling) {
4050 StartProfilerIdleNotifier(env);
4053 Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
4054 process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
4056 Local<Object> process_object = process_template->GetFunction()->NewInstance();
4057 env->set_process_object(process_object);
4059 SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
4060 LoadAsyncWrapperInfo(env);
4066 // Entry point for new node instances, also called directly for the main
4068 static void StartNodeInstance(void* arg) {
4069 NodeInstanceData* instance_data = static_cast<NodeInstanceData*>(arg);
4070 Isolate::CreateParams params;
4071 ArrayBufferAllocator* array_buffer_allocator = new ArrayBufferAllocator();
4072 params.array_buffer_allocator = array_buffer_allocator;
4073 Isolate* isolate = Isolate::New(params);
4074 if (track_heap_objects) {
4075 isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
4078 // Fetch a reference to the main isolate, so we have a reference to it
4079 // even when we need it to access it from another (debugger) thread.
4080 if (instance_data->is_main())
4081 CHECK_EQ(nullptr, node_isolate.exchange(isolate));
4084 Locker locker(isolate);
4085 Isolate::Scope isolate_scope(isolate);
4086 HandleScope handle_scope(isolate);
4087 Local<Context> context = Context::New(isolate);
4088 Environment* env = CreateEnvironment(isolate, context, instance_data);
4089 array_buffer_allocator->set_env(env);
4090 Context::Scope context_scope(context);
4092 isolate->SetAbortOnUncaughtExceptionCallback(
4093 ShouldAbortOnUncaughtException);
4095 // Start debug agent when argv has --debug
4096 if (instance_data->use_debug_agent())
4097 StartDebug(env, debug_wait_connect);
4099 LoadEnvironment(env);
4101 env->set_trace_sync_io(trace_sync_io);
4104 if (instance_data->use_debug_agent())
4108 SealHandleScope seal(isolate);
4111 v8::platform::PumpMessageLoop(default_platform, isolate);
4112 more = uv_run(env->event_loop(), UV_RUN_ONCE);
4114 if (more == false) {
4115 v8::platform::PumpMessageLoop(default_platform, isolate);
4116 EmitBeforeExit(env);
4118 // Emit `beforeExit` if the loop became alive either after emitting
4119 // event, or after running some callbacks.
4120 more = uv_loop_alive(env->event_loop());
4121 if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
4124 } while (more == true);
4127 env->set_trace_sync_io(false);
4129 int exit_code = EmitExit(env);
4130 if (instance_data->is_main())
4131 instance_data->set_exit_code(exit_code);
4134 #if defined(LEAK_SANITIZER)
4135 __lsan_do_leak_check();
4138 array_buffer_allocator->set_env(nullptr);
4143 if (instance_data->is_main()) {
4144 // Synchronize with signal handler, see TryStartDebugger.
4145 while (isolate != node_isolate.exchange(nullptr)); // NOLINT
4148 CHECK_NE(isolate, nullptr);
4151 delete array_buffer_allocator;
4154 int Start(int argc, char** argv) {
4159 // Hack around with the argv pointer. Used for process.title = "blah".
4160 argv = uv_setup_args(argc, argv);
4162 // This needs to run *before* V8::Initialize(). The const_cast is not
4163 // optional, in case you're wondering.
4165 const char** exec_argv;
4166 Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
4169 // V8 on Windows doesn't have a good source of entropy. Seed it from
4171 V8::SetEntropySource(crypto::EntropySource);
4174 const int thread_pool_size = 4;
4175 default_platform = v8::platform::CreateDefaultPlatform(thread_pool_size);
4176 V8::InitializePlatform(default_platform);
4181 NodeInstanceData instance_data(NodeInstanceType::MAIN,
4184 const_cast<const char**>(argv),
4188 StartNodeInstance(&instance_data);
4189 exit_code = instance_data.exit_code();
4193 delete default_platform;
4194 default_platform = nullptr;
4197 exec_argv = nullptr;