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