/src/node/src/node_options.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "node_options.h" // NOLINT(build/include_inline) |
2 | | #include "node_options-inl.h" |
3 | | |
4 | | #include "env-inl.h" |
5 | | #include "node_binding.h" |
6 | | #include "node_external_reference.h" |
7 | | #include "node_internals.h" |
8 | | #include "node_sea.h" |
9 | | #if HAVE_OPENSSL |
10 | | #include "openssl/opensslv.h" |
11 | | #endif |
12 | | |
13 | | #include <algorithm> |
14 | | #include <charconv> |
15 | | #include <limits> |
16 | | #include <sstream> |
17 | | #include <string_view> |
18 | | |
19 | | using v8::Boolean; |
20 | | using v8::Context; |
21 | | using v8::FunctionCallbackInfo; |
22 | | using v8::Integer; |
23 | | using v8::Isolate; |
24 | | using v8::Local; |
25 | | using v8::Map; |
26 | | using v8::Number; |
27 | | using v8::Object; |
28 | | using v8::Undefined; |
29 | | using v8::Value; |
30 | | |
31 | | namespace node { |
32 | | |
33 | | namespace per_process { |
34 | | Mutex cli_options_mutex; |
35 | | std::shared_ptr<PerProcessOptions> cli_options{new PerProcessOptions()}; |
36 | | } // namespace per_process |
37 | | |
38 | | void DebugOptions::CheckOptions(std::vector<std::string>* errors, |
39 | 132k | std::vector<std::string>* argv) { |
40 | | #if !NODE_USE_V8_PLATFORM && !HAVE_INSPECTOR |
41 | | if (inspector_enabled) { |
42 | | errors->push_back("Inspector is not available when Node is compiled " |
43 | | "--without-v8-platform and --without-inspector."); |
44 | | } |
45 | | #endif |
46 | | |
47 | 132k | if (deprecated_debug) { |
48 | 0 | errors->push_back("[DEP0062]: `node --debug` and `node --debug-brk` " |
49 | 0 | "are invalid. Please use `node --inspect` and " |
50 | 0 | "`node --inspect-brk` instead."); |
51 | 0 | } |
52 | | |
53 | 132k | using std::string_view_literals::operator""sv; |
54 | 132k | const std::vector<std::string_view> destinations = |
55 | 132k | SplitString(inspect_publish_uid_string, ","sv); |
56 | 132k | inspect_publish_uid.console = false; |
57 | 132k | inspect_publish_uid.http = false; |
58 | 264k | for (const std::string_view destination : destinations) { |
59 | 264k | if (destination == "stderr"sv) { |
60 | 132k | inspect_publish_uid.console = true; |
61 | 132k | } else if (destination == "http"sv) { |
62 | 132k | inspect_publish_uid.http = true; |
63 | 132k | } else { |
64 | 0 | errors->push_back("--inspect-publish-uid destination can be " |
65 | 0 | "stderr or http"); |
66 | 0 | } |
67 | 264k | } |
68 | 132k | } |
69 | | |
70 | | void PerProcessOptions::CheckOptions(std::vector<std::string>* errors, |
71 | 132k | std::vector<std::string>* argv) { |
72 | 132k | #if HAVE_OPENSSL |
73 | 132k | if (use_openssl_ca && use_bundled_ca) { |
74 | 0 | errors->push_back("either --use-openssl-ca or --use-bundled-ca can be " |
75 | 0 | "used, not both"); |
76 | 0 | } |
77 | | |
78 | | // Any value less than 2 disables use of the secure heap. |
79 | 132k | if (secure_heap >= 2) { |
80 | 0 | if ((secure_heap & (secure_heap - 1)) != 0) |
81 | 0 | errors->push_back("--secure-heap must be a power of 2"); |
82 | 0 | secure_heap_min = |
83 | 0 | std::min({ |
84 | 0 | secure_heap, |
85 | 0 | secure_heap_min, |
86 | 0 | static_cast<int64_t>(std::numeric_limits<int>::max())}); |
87 | 0 | secure_heap_min = std::max(static_cast<int64_t>(2), secure_heap_min); |
88 | 0 | if ((secure_heap_min & (secure_heap_min - 1)) != 0) |
89 | 0 | errors->push_back("--secure-heap-min must be a power of 2"); |
90 | 0 | } |
91 | 132k | #endif // HAVE_OPENSSL |
92 | | |
93 | 132k | if (use_largepages != "off" && |
94 | 132k | use_largepages != "on" && |
95 | 132k | use_largepages != "silent") { |
96 | 0 | errors->push_back("invalid value for --use-largepages"); |
97 | 0 | } |
98 | 132k | per_isolate->CheckOptions(errors, argv); |
99 | 132k | } |
100 | | |
101 | | void PerIsolateOptions::CheckOptions(std::vector<std::string>* errors, |
102 | 132k | std::vector<std::string>* argv) { |
103 | 132k | per_env->CheckOptions(errors, argv); |
104 | 132k | } |
105 | | |
106 | | void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors, |
107 | 132k | std::vector<std::string>* argv) { |
108 | 132k | if (has_policy_integrity_string && experimental_policy.empty()) { |
109 | 0 | errors->push_back("--policy-integrity requires " |
110 | 0 | "--experimental-policy be enabled"); |
111 | 0 | } |
112 | 132k | if (has_policy_integrity_string && experimental_policy_integrity.empty()) { |
113 | 0 | errors->push_back("--policy-integrity cannot be empty"); |
114 | 0 | } |
115 | | |
116 | 132k | if (!input_type.empty()) { |
117 | 0 | if (input_type != "commonjs" && input_type != "module") { |
118 | 0 | errors->push_back("--input-type must be \"module\" or \"commonjs\""); |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | 132k | if (!type.empty()) { |
123 | 0 | if (type != "commonjs" && type != "module") { |
124 | 0 | errors->push_back("--experimental-default-type must be " |
125 | 0 | "\"module\" or \"commonjs\""); |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | 132k | if (syntax_check_only && has_eval_string) { |
130 | 0 | errors->push_back("either --check or --eval can be used, not both"); |
131 | 0 | } |
132 | | |
133 | 132k | if (!unhandled_rejections.empty() && |
134 | 132k | unhandled_rejections != "warn-with-error-code" && |
135 | 132k | unhandled_rejections != "throw" && |
136 | 132k | unhandled_rejections != "strict" && |
137 | 132k | unhandled_rejections != "warn" && |
138 | 132k | unhandled_rejections != "none") { |
139 | 0 | errors->push_back("invalid value for --unhandled-rejections"); |
140 | 0 | } |
141 | | |
142 | 132k | if (tls_min_v1_3 && tls_max_v1_2) { |
143 | 0 | errors->push_back("either --tls-min-v1.3 or --tls-max-v1.2 can be " |
144 | 0 | "used, not both"); |
145 | 0 | } |
146 | | |
147 | 132k | if (heap_snapshot_near_heap_limit < 0) { |
148 | 0 | errors->push_back("--heapsnapshot-near-heap-limit must not be negative"); |
149 | 0 | } |
150 | | |
151 | 132k | if (test_runner) { |
152 | 0 | if (syntax_check_only) { |
153 | 0 | errors->push_back("either --test or --check can be used, not both"); |
154 | 0 | } |
155 | |
|
156 | 0 | if (has_eval_string) { |
157 | 0 | errors->push_back("either --test or --eval can be used, not both"); |
158 | 0 | } |
159 | |
|
160 | 0 | if (force_repl) { |
161 | 0 | errors->push_back("either --test or --interactive can be used, not both"); |
162 | 0 | } |
163 | |
|
164 | 0 | if (watch_mode_paths.size() > 0) { |
165 | 0 | errors->push_back( |
166 | 0 | "--watch-path cannot be used in combination with --test"); |
167 | 0 | } |
168 | |
|
169 | 0 | #ifndef ALLOW_ATTACHING_DEBUGGER_IN_TEST_RUNNER |
170 | 0 | debug_options_.allow_attaching_debugger = false; |
171 | 0 | #endif |
172 | 0 | } |
173 | | |
174 | 132k | if (watch_mode) { |
175 | 0 | if (syntax_check_only) { |
176 | 0 | errors->push_back("either --watch or --check can be used, not both"); |
177 | 0 | } else if (has_eval_string) { |
178 | 0 | errors->push_back("either --watch or --eval can be used, not both"); |
179 | 0 | } else if (force_repl) { |
180 | 0 | errors->push_back("either --watch or --interactive " |
181 | 0 | "can be used, not both"); |
182 | 0 | } else if (test_runner_force_exit) { |
183 | 0 | errors->push_back("either --watch or --test-force-exit " |
184 | 0 | "can be used, not both"); |
185 | 0 | } else if (!test_runner && (argv->size() < 1 || (*argv)[1].empty())) { |
186 | 0 | errors->push_back("--watch requires specifying a file"); |
187 | 0 | } |
188 | |
|
189 | 0 | #ifndef ALLOW_ATTACHING_DEBUGGER_IN_WATCH_MODE |
190 | 0 | debug_options_.allow_attaching_debugger = false; |
191 | 0 | #endif |
192 | 0 | } |
193 | | |
194 | 132k | #if HAVE_INSPECTOR |
195 | 132k | if (!cpu_prof) { |
196 | 132k | if (!cpu_prof_name.empty()) { |
197 | 0 | errors->push_back("--cpu-prof-name must be used with --cpu-prof"); |
198 | 0 | } |
199 | 132k | if (!cpu_prof_dir.empty()) { |
200 | 0 | errors->push_back("--cpu-prof-dir must be used with --cpu-prof"); |
201 | 0 | } |
202 | | // We can't catch the case where the value passed is the default value, |
203 | | // then the option just becomes a noop which is fine. |
204 | 132k | if (cpu_prof_interval != kDefaultCpuProfInterval) { |
205 | 0 | errors->push_back("--cpu-prof-interval must be used with --cpu-prof"); |
206 | 0 | } |
207 | 132k | } |
208 | | |
209 | 132k | if (cpu_prof && cpu_prof_dir.empty() && !diagnostic_dir.empty()) { |
210 | 0 | cpu_prof_dir = diagnostic_dir; |
211 | 0 | } |
212 | | |
213 | 132k | if (!heap_prof) { |
214 | 132k | if (!heap_prof_name.empty()) { |
215 | 0 | errors->push_back("--heap-prof-name must be used with --heap-prof"); |
216 | 0 | } |
217 | 132k | if (!heap_prof_dir.empty()) { |
218 | 0 | errors->push_back("--heap-prof-dir must be used with --heap-prof"); |
219 | 0 | } |
220 | | // We can't catch the case where the value passed is the default value, |
221 | | // then the option just becomes a noop which is fine. |
222 | 132k | if (heap_prof_interval != kDefaultHeapProfInterval) { |
223 | 0 | errors->push_back("--heap-prof-interval must be used with --heap-prof"); |
224 | 0 | } |
225 | 132k | } |
226 | | |
227 | 132k | if (heap_prof && heap_prof_dir.empty() && !diagnostic_dir.empty()) { |
228 | 0 | heap_prof_dir = diagnostic_dir; |
229 | 0 | } |
230 | | |
231 | 132k | debug_options_.CheckOptions(errors, argv); |
232 | 132k | #endif // HAVE_INSPECTOR |
233 | 132k | } |
234 | | |
235 | | namespace options_parser { |
236 | | |
237 | | class DebugOptionsParser : public OptionsParser<DebugOptions> { |
238 | | public: |
239 | | DebugOptionsParser(); |
240 | | }; |
241 | | |
242 | | class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> { |
243 | | public: |
244 | | EnvironmentOptionsParser(); |
245 | | explicit EnvironmentOptionsParser(const DebugOptionsParser& dop) |
246 | 132k | : EnvironmentOptionsParser() { |
247 | 132k | Insert(dop, &EnvironmentOptions::get_debug_options); |
248 | 132k | } |
249 | | }; |
250 | | |
251 | | class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> { |
252 | | public: |
253 | | PerIsolateOptionsParser() = delete; |
254 | | explicit PerIsolateOptionsParser(const EnvironmentOptionsParser& eop); |
255 | | }; |
256 | | |
257 | | class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> { |
258 | | public: |
259 | | PerProcessOptionsParser() = delete; |
260 | | explicit PerProcessOptionsParser(const PerIsolateOptionsParser& iop); |
261 | | }; |
262 | | |
263 | | #if HAVE_INSPECTOR |
264 | | const DebugOptionsParser _dop_instance{}; |
265 | | const EnvironmentOptionsParser _eop_instance{_dop_instance}; |
266 | | |
267 | | // This Parse is not dead code. It is used by embedders (e.g., Electron). |
268 | | template <> |
269 | | void Parse( |
270 | | StringVector* const args, StringVector* const exec_args, |
271 | | StringVector* const v8_args, |
272 | | DebugOptions* const options, |
273 | 0 | OptionEnvvarSettings required_env_settings, StringVector* const errors) { |
274 | 0 | _dop_instance.Parse( |
275 | 0 | args, exec_args, v8_args, options, required_env_settings, errors); |
276 | 0 | } |
277 | | #else |
278 | | const EnvironmentOptionsParser _eop_instance{}; |
279 | | #endif // HAVE_INSPECTOR |
280 | | const PerIsolateOptionsParser _piop_instance{_eop_instance}; |
281 | | const PerProcessOptionsParser _ppop_instance{_piop_instance}; |
282 | | |
283 | | template <> |
284 | | void Parse( |
285 | | StringVector* const args, StringVector* const exec_args, |
286 | | StringVector* const v8_args, |
287 | | PerIsolateOptions* const options, |
288 | 0 | OptionEnvvarSettings required_env_settings, StringVector* const errors) { |
289 | 0 | _piop_instance.Parse( |
290 | 0 | args, exec_args, v8_args, options, required_env_settings, errors); |
291 | 0 | } |
292 | | |
293 | | template <> |
294 | | void Parse( |
295 | | StringVector* const args, StringVector* const exec_args, |
296 | | StringVector* const v8_args, |
297 | | PerProcessOptions* const options, |
298 | 132k | OptionEnvvarSettings required_env_settings, StringVector* const errors) { |
299 | 132k | _ppop_instance.Parse( |
300 | 132k | args, exec_args, v8_args, options, required_env_settings, errors); |
301 | 132k | } |
302 | | |
303 | | // XXX: If you add an option here, please also add it to doc/node.1 and |
304 | | // doc/api/cli.md |
305 | | // TODO(addaleax): Make that unnecessary. |
306 | | |
307 | 132k | DebugOptionsParser::DebugOptionsParser() { |
308 | 132k | #ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION |
309 | 132k | if (sea::IsSingleExecutable()) return; |
310 | 132k | #endif |
311 | | |
312 | 132k | AddOption("--inspect-port", |
313 | 132k | "set host:port for inspector", |
314 | 132k | &DebugOptions::host_port, |
315 | 132k | kAllowedInEnvvar); |
316 | 132k | AddAlias("--debug-port", "--inspect-port"); |
317 | | |
318 | 132k | AddOption("--inspect", |
319 | 132k | "activate inspector on host:port (default: 127.0.0.1:9229)", |
320 | 132k | &DebugOptions::inspector_enabled, |
321 | 132k | kAllowedInEnvvar); |
322 | 132k | AddAlias("--inspect=", { "--inspect-port", "--inspect" }); |
323 | | |
324 | 132k | AddOption("--debug", "", &DebugOptions::deprecated_debug); |
325 | 132k | AddAlias("--debug=", "--debug"); |
326 | 132k | AddOption("--debug-brk", "", &DebugOptions::deprecated_debug); |
327 | 132k | AddAlias("--debug-brk=", "--debug-brk"); |
328 | | |
329 | 132k | AddOption("--inspect-brk", |
330 | 132k | "activate inspector on host:port and break at start of user script", |
331 | 132k | &DebugOptions::break_first_line, |
332 | 132k | kAllowedInEnvvar); |
333 | 132k | Implies("--inspect-brk", "--inspect"); |
334 | 132k | AddAlias("--inspect-brk=", { "--inspect-port", "--inspect-brk" }); |
335 | | |
336 | 132k | AddOption("--inspect-brk-node", "", &DebugOptions::break_node_first_line); |
337 | 132k | Implies("--inspect-brk-node", "--inspect"); |
338 | 132k | AddAlias("--inspect-brk-node=", { "--inspect-port", "--inspect-brk-node" }); |
339 | | |
340 | 132k | AddOption("--inspect-publish-uid", |
341 | 132k | "comma separated list of destinations for inspector uid" |
342 | 132k | "(default: stderr,http)", |
343 | 132k | &DebugOptions::inspect_publish_uid_string, |
344 | 132k | kAllowedInEnvvar); |
345 | 132k | } |
346 | | |
347 | 132k | EnvironmentOptionsParser::EnvironmentOptionsParser() { |
348 | 132k | AddOption("--conditions", |
349 | 132k | "additional user conditions for conditional exports and imports", |
350 | 132k | &EnvironmentOptions::conditions, |
351 | 132k | kAllowedInEnvvar); |
352 | 132k | AddAlias("-C", "--conditions"); |
353 | 132k | AddOption("--experimental-detect-module", |
354 | 132k | "when ambiguous modules fail to evaluate because they contain " |
355 | 132k | "ES module syntax, try again to evaluate them as ES modules", |
356 | 132k | &EnvironmentOptions::detect_module, |
357 | 132k | kAllowedInEnvvar); |
358 | 132k | AddOption("--experimental-print-required-tla", |
359 | 132k | "Print pending top-level await. If --experimental-require-module " |
360 | 132k | "is true, evaluate asynchronous graphs loaded by `require()` but " |
361 | 132k | "do not run the microtasks, in order to to find and print " |
362 | 132k | "top-level await in the graph", |
363 | 132k | &EnvironmentOptions::print_required_tla, |
364 | 132k | kAllowedInEnvvar); |
365 | 132k | AddOption("--experimental-require-module", |
366 | 132k | "Allow loading explicit ES Modules in require().", |
367 | 132k | &EnvironmentOptions::require_module, |
368 | 132k | kAllowedInEnvvar); |
369 | 132k | AddOption("--diagnostic-dir", |
370 | 132k | "set dir for all output files" |
371 | 132k | " (default: current working directory)", |
372 | 132k | &EnvironmentOptions::diagnostic_dir, |
373 | 132k | kAllowedInEnvvar); |
374 | 132k | AddOption("--dns-result-order", |
375 | 132k | "set default value of verbatim in dns.lookup. Options are " |
376 | 132k | "'ipv4first' (IPv4 addresses are placed before IPv6 addresses) " |
377 | 132k | "'verbatim' (addresses are in the order the DNS resolver " |
378 | 132k | "returned)", |
379 | 132k | &EnvironmentOptions::dns_result_order, |
380 | 132k | kAllowedInEnvvar); |
381 | 132k | AddOption("--network-family-autoselection", |
382 | 132k | "Disable network address family autodetection algorithm", |
383 | 132k | &EnvironmentOptions::network_family_autoselection, |
384 | 132k | kAllowedInEnvvar, |
385 | 132k | true); |
386 | 132k | AddAlias("--enable-network-family-autoselection", |
387 | 132k | "--network-family-autoselection"); |
388 | 132k | AddOption("--enable-source-maps", |
389 | 132k | "Source Map V3 support for stack traces", |
390 | 132k | &EnvironmentOptions::enable_source_maps, |
391 | 132k | kAllowedInEnvvar); |
392 | 132k | AddOption("--experimental-abortcontroller", "", NoOp{}, kAllowedInEnvvar); |
393 | 132k | AddOption("--experimental-fetch", |
394 | 132k | "experimental Fetch API", |
395 | 132k | &EnvironmentOptions::experimental_fetch, |
396 | 132k | kAllowedInEnvvar, |
397 | 132k | true); |
398 | 132k | AddOption("--experimental-websocket", |
399 | 132k | "experimental WebSocket API", |
400 | 132k | &EnvironmentOptions::experimental_websocket, |
401 | 132k | kAllowedInEnvvar, |
402 | 132k | true); |
403 | 132k | AddOption("--experimental-global-customevent", |
404 | 132k | "expose experimental CustomEvent on the global scope", |
405 | 132k | &EnvironmentOptions::experimental_global_customevent, |
406 | 132k | kAllowedInEnvvar, |
407 | 132k | true); |
408 | 132k | AddOption("--experimental-global-navigator", |
409 | 132k | "expose experimental Navigator API on the global scope", |
410 | 132k | &EnvironmentOptions::experimental_global_navigator, |
411 | 132k | kAllowedInEnvvar, |
412 | 132k | true); |
413 | 132k | AddOption("--experimental-global-webcrypto", |
414 | 132k | "expose experimental Web Crypto API on the global scope", |
415 | 132k | &EnvironmentOptions::experimental_global_web_crypto, |
416 | 132k | kAllowedInEnvvar, |
417 | 132k | true); |
418 | 132k | AddOption("--experimental-json-modules", "", NoOp{}, kAllowedInEnvvar); |
419 | 132k | AddOption("--experimental-loader", |
420 | 132k | "use the specified module as a custom loader", |
421 | 132k | &EnvironmentOptions::userland_loaders, |
422 | 132k | kAllowedInEnvvar); |
423 | 132k | AddAlias("--loader", "--experimental-loader"); |
424 | 132k | AddOption("--experimental-modules", "", NoOp{}, kAllowedInEnvvar); |
425 | 132k | AddOption("--experimental-network-imports", |
426 | 132k | "experimental https: support for the ES Module loader", |
427 | 132k | &EnvironmentOptions::experimental_https_modules, |
428 | 132k | kAllowedInEnvvar); |
429 | 132k | AddOption("--experimental-wasm-modules", |
430 | 132k | "experimental ES Module support for webassembly modules", |
431 | 132k | &EnvironmentOptions::experimental_wasm_modules, |
432 | 132k | kAllowedInEnvvar); |
433 | 132k | AddOption("--experimental-import-meta-resolve", |
434 | 132k | "experimental ES Module import.meta.resolve() parentURL support", |
435 | 132k | &EnvironmentOptions::experimental_import_meta_resolve, |
436 | 132k | kAllowedInEnvvar); |
437 | 132k | AddOption("--experimental-permission", |
438 | 132k | "enable the permission system", |
439 | 132k | &EnvironmentOptions::experimental_permission, |
440 | 132k | kAllowedInEnvvar, |
441 | 132k | false); |
442 | 132k | AddOption("--experimental-policy", |
443 | 132k | "use the specified file as a " |
444 | 132k | "security policy", |
445 | 132k | &EnvironmentOptions::experimental_policy, |
446 | 132k | kAllowedInEnvvar); |
447 | 132k | AddOption("[has_policy_integrity_string]", |
448 | 132k | "", |
449 | 132k | &EnvironmentOptions::has_policy_integrity_string); |
450 | 132k | AddOption("--policy-integrity", |
451 | 132k | "ensure the security policy contents match " |
452 | 132k | "the specified integrity", |
453 | 132k | &EnvironmentOptions::experimental_policy_integrity, |
454 | 132k | kAllowedInEnvvar); |
455 | 132k | Implies("--policy-integrity", "[has_policy_integrity_string]"); |
456 | 132k | AddOption("--allow-fs-read", |
457 | 132k | "allow permissions to read the filesystem", |
458 | 132k | &EnvironmentOptions::allow_fs_read, |
459 | 132k | kAllowedInEnvvar); |
460 | 132k | AddOption("--allow-fs-write", |
461 | 132k | "allow permissions to write in the filesystem", |
462 | 132k | &EnvironmentOptions::allow_fs_write, |
463 | 132k | kAllowedInEnvvar); |
464 | 132k | AddOption("--allow-addons", |
465 | 132k | "allow use of addons when any permissions are set", |
466 | 132k | &EnvironmentOptions::allow_addons, |
467 | 132k | kAllowedInEnvvar); |
468 | 132k | AddOption("--allow-child-process", |
469 | 132k | "allow use of child process when any permissions are set", |
470 | 132k | &EnvironmentOptions::allow_child_process, |
471 | 132k | kAllowedInEnvvar); |
472 | 132k | AddOption("--allow-worker", |
473 | 132k | "allow worker threads when any permissions are set", |
474 | 132k | &EnvironmentOptions::allow_worker_threads, |
475 | 132k | kAllowedInEnvvar); |
476 | 132k | AddOption("--experimental-repl-await", |
477 | 132k | "experimental await keyword support in REPL", |
478 | 132k | &EnvironmentOptions::experimental_repl_await, |
479 | 132k | kAllowedInEnvvar, |
480 | 132k | true); |
481 | 132k | AddOption("--experimental-vm-modules", |
482 | 132k | "experimental ES Module support in vm module", |
483 | 132k | &EnvironmentOptions::experimental_vm_modules, |
484 | 132k | kAllowedInEnvvar); |
485 | 132k | AddOption("--experimental-worker", "", NoOp{}, kAllowedInEnvvar); |
486 | 132k | AddOption("--experimental-report", "", NoOp{}, kAllowedInEnvvar); |
487 | 132k | AddOption( |
488 | 132k | "--experimental-wasi-unstable-preview1", "", NoOp{}, kAllowedInEnvvar); |
489 | 132k | AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals); |
490 | 132k | AddOption("--frozen-intrinsics", |
491 | 132k | "experimental frozen intrinsics support", |
492 | 132k | &EnvironmentOptions::frozen_intrinsics, |
493 | 132k | kAllowedInEnvvar); |
494 | 132k | AddOption("--heapsnapshot-signal", |
495 | 132k | "Generate heap snapshot on specified signal", |
496 | 132k | &EnvironmentOptions::heap_snapshot_signal, |
497 | 132k | kAllowedInEnvvar); |
498 | 132k | AddOption("--heapsnapshot-near-heap-limit", |
499 | 132k | "Generate heap snapshots whenever V8 is approaching " |
500 | 132k | "the heap limit. No more than the specified number of " |
501 | 132k | "heap snapshots will be generated.", |
502 | 132k | &EnvironmentOptions::heap_snapshot_near_heap_limit, |
503 | 132k | kAllowedInEnvvar); |
504 | 132k | AddOption("--http-parser", "", NoOp{}, kAllowedInEnvvar); |
505 | 132k | AddOption("--insecure-http-parser", |
506 | 132k | "use an insecure HTTP parser that accepts invalid HTTP headers", |
507 | 132k | &EnvironmentOptions::insecure_http_parser, |
508 | 132k | kAllowedInEnvvar); |
509 | 132k | AddOption("--input-type", |
510 | 132k | "set module type for string input", |
511 | 132k | &EnvironmentOptions::input_type, |
512 | 132k | kAllowedInEnvvar); |
513 | 132k | AddOption( |
514 | 132k | "--experimental-specifier-resolution", "", NoOp{}, kAllowedInEnvvar); |
515 | 132k | AddAlias("--es-module-specifier-resolution", |
516 | 132k | "--experimental-specifier-resolution"); |
517 | 132k | AddOption("--deprecation", |
518 | 132k | "silence deprecation warnings", |
519 | 132k | &EnvironmentOptions::deprecation, |
520 | 132k | kAllowedInEnvvar, |
521 | 132k | true); |
522 | 132k | AddOption("--force-async-hooks-checks", |
523 | 132k | "disable checks for async_hooks", |
524 | 132k | &EnvironmentOptions::force_async_hooks_checks, |
525 | 132k | kAllowedInEnvvar, |
526 | 132k | true); |
527 | 132k | AddOption( |
528 | 132k | "--force-node-api-uncaught-exceptions-policy", |
529 | 132k | "enforces 'uncaughtException' event on Node API asynchronous callbacks", |
530 | 132k | &EnvironmentOptions::force_node_api_uncaught_exceptions_policy, |
531 | 132k | kAllowedInEnvvar, |
532 | 132k | false); |
533 | 132k | AddOption("--addons", |
534 | 132k | "disable loading native addons", |
535 | 132k | &EnvironmentOptions::allow_native_addons, |
536 | 132k | kAllowedInEnvvar, |
537 | 132k | true); |
538 | 132k | AddOption("--global-search-paths", |
539 | 132k | "disable global module search paths", |
540 | 132k | &EnvironmentOptions::global_search_paths, |
541 | 132k | kAllowedInEnvvar, |
542 | 132k | true); |
543 | 132k | AddOption("--warnings", |
544 | 132k | "silence all process warnings", |
545 | 132k | &EnvironmentOptions::warnings, |
546 | 132k | kAllowedInEnvvar, |
547 | 132k | true); |
548 | 132k | AddOption("--disable-warning", |
549 | 132k | "silence specific process warnings", |
550 | 132k | &EnvironmentOptions::disable_warnings, |
551 | 132k | kAllowedInEnvvar); |
552 | 132k | AddOption("--force-context-aware", |
553 | 132k | "disable loading non-context-aware addons", |
554 | 132k | &EnvironmentOptions::force_context_aware, |
555 | 132k | kAllowedInEnvvar); |
556 | 132k | AddOption("--pending-deprecation", |
557 | 132k | "emit pending deprecation warnings", |
558 | 132k | &EnvironmentOptions::pending_deprecation, |
559 | 132k | kAllowedInEnvvar); |
560 | 132k | AddOption("--preserve-symlinks", |
561 | 132k | "preserve symbolic links when resolving", |
562 | 132k | &EnvironmentOptions::preserve_symlinks, |
563 | 132k | kAllowedInEnvvar); |
564 | 132k | AddOption("--preserve-symlinks-main", |
565 | 132k | "preserve symbolic links when resolving the main module", |
566 | 132k | &EnvironmentOptions::preserve_symlinks_main, |
567 | 132k | kAllowedInEnvvar); |
568 | 132k | AddOption("--prof", |
569 | 132k | "Generate V8 profiler output.", |
570 | 132k | V8Option{}); |
571 | 132k | AddOption("--prof-process", |
572 | 132k | "process V8 profiler output generated using --prof", |
573 | 132k | &EnvironmentOptions::prof_process); |
574 | | // Options after --prof-process are passed through to the prof processor. |
575 | 132k | AddAlias("--prof-process", { "--prof-process", "--" }); |
576 | 132k | #if HAVE_INSPECTOR |
577 | 132k | AddOption("--cpu-prof", |
578 | 132k | "Start the V8 CPU profiler on start up, and write the CPU profile " |
579 | 132k | "to disk before exit. If --cpu-prof-dir is not specified, write " |
580 | 132k | "the profile to the current working directory.", |
581 | 132k | &EnvironmentOptions::cpu_prof); |
582 | 132k | AddOption("--cpu-prof-name", |
583 | 132k | "specified file name of the V8 CPU profile generated with " |
584 | 132k | "--cpu-prof", |
585 | 132k | &EnvironmentOptions::cpu_prof_name); |
586 | 132k | AddOption("--cpu-prof-interval", |
587 | 132k | "specified sampling interval in microseconds for the V8 CPU " |
588 | 132k | "profile generated with --cpu-prof. (default: 1000)", |
589 | 132k | &EnvironmentOptions::cpu_prof_interval); |
590 | 132k | AddOption("--cpu-prof-dir", |
591 | 132k | "Directory where the V8 profiles generated by --cpu-prof will be " |
592 | 132k | "placed. Does not affect --prof.", |
593 | 132k | &EnvironmentOptions::cpu_prof_dir); |
594 | 132k | AddOption( |
595 | 132k | "--heap-prof", |
596 | 132k | "Start the V8 heap profiler on start up, and write the heap profile " |
597 | 132k | "to disk before exit. If --heap-prof-dir is not specified, write " |
598 | 132k | "the profile to the current working directory.", |
599 | 132k | &EnvironmentOptions::heap_prof); |
600 | 132k | AddOption("--heap-prof-name", |
601 | 132k | "specified file name of the V8 heap profile generated with " |
602 | 132k | "--heap-prof", |
603 | 132k | &EnvironmentOptions::heap_prof_name); |
604 | 132k | AddOption("--heap-prof-dir", |
605 | 132k | "Directory where the V8 heap profiles generated by --heap-prof " |
606 | 132k | "will be placed.", |
607 | 132k | &EnvironmentOptions::heap_prof_dir); |
608 | 132k | AddOption("--heap-prof-interval", |
609 | 132k | "specified sampling interval in bytes for the V8 heap " |
610 | 132k | "profile generated with --heap-prof. (default: 512 * 1024)", |
611 | 132k | &EnvironmentOptions::heap_prof_interval); |
612 | 132k | #endif // HAVE_INSPECTOR |
613 | 132k | AddOption("--max-http-header-size", |
614 | 132k | "set the maximum size of HTTP headers (default: 16384 (16KB))", |
615 | 132k | &EnvironmentOptions::max_http_header_size, |
616 | 132k | kAllowedInEnvvar); |
617 | 132k | AddOption("--redirect-warnings", |
618 | 132k | "write warnings to file instead of stderr", |
619 | 132k | &EnvironmentOptions::redirect_warnings, |
620 | 132k | kAllowedInEnvvar); |
621 | 132k | AddOption( |
622 | 132k | "[has_env_file_string]", "", &EnvironmentOptions::has_env_file_string); |
623 | 132k | AddOption("--env-file", |
624 | 132k | "set environment variables from supplied file", |
625 | 132k | &EnvironmentOptions::env_file); |
626 | 132k | Implies("--env-file", "[has_env_file_string]"); |
627 | 132k | AddOption("--test", |
628 | 132k | "launch test runner on startup", |
629 | 132k | &EnvironmentOptions::test_runner); |
630 | 132k | AddOption("--test-concurrency", |
631 | 132k | "specify test runner concurrency", |
632 | 132k | &EnvironmentOptions::test_runner_concurrency); |
633 | 132k | AddOption("--test-force-exit", |
634 | 132k | "force test runner to exit upon completion", |
635 | 132k | &EnvironmentOptions::test_runner_force_exit); |
636 | 132k | AddOption("--test-timeout", |
637 | 132k | "specify test runner timeout", |
638 | 132k | &EnvironmentOptions::test_runner_timeout); |
639 | 132k | AddOption("--experimental-test-coverage", |
640 | 132k | "enable code coverage in the test runner", |
641 | 132k | &EnvironmentOptions::test_runner_coverage); |
642 | 132k | AddOption("--test-name-pattern", |
643 | 132k | "run tests whose name matches this regular expression", |
644 | 132k | &EnvironmentOptions::test_name_pattern); |
645 | 132k | AddOption("--test-reporter", |
646 | 132k | "report test output using the given reporter", |
647 | 132k | &EnvironmentOptions::test_reporter, |
648 | 132k | kAllowedInEnvvar); |
649 | 132k | AddOption("--test-reporter-destination", |
650 | 132k | "report given reporter to the given destination", |
651 | 132k | &EnvironmentOptions::test_reporter_destination, |
652 | 132k | kAllowedInEnvvar); |
653 | 132k | AddOption("--test-only", |
654 | 132k | "run tests with 'only' option set", |
655 | 132k | &EnvironmentOptions::test_only, |
656 | 132k | kAllowedInEnvvar); |
657 | 132k | AddOption("--test-shard", |
658 | 132k | "run test at specific shard", |
659 | 132k | &EnvironmentOptions::test_shard, |
660 | 132k | kAllowedInEnvvar); |
661 | 132k | AddOption("--test-udp-no-try-send", "", // For testing only. |
662 | 132k | &EnvironmentOptions::test_udp_no_try_send); |
663 | 132k | AddOption("--throw-deprecation", |
664 | 132k | "throw an exception on deprecations", |
665 | 132k | &EnvironmentOptions::throw_deprecation, |
666 | 132k | kAllowedInEnvvar); |
667 | 132k | AddOption("--trace-atomics-wait", |
668 | 132k | "(deprecated) trace Atomics.wait() operations", |
669 | 132k | &EnvironmentOptions::trace_atomics_wait, |
670 | 132k | kAllowedInEnvvar); |
671 | 132k | AddOption("--trace-deprecation", |
672 | 132k | "show stack traces on deprecations", |
673 | 132k | &EnvironmentOptions::trace_deprecation, |
674 | 132k | kAllowedInEnvvar); |
675 | 132k | AddOption("--trace-exit", |
676 | 132k | "show stack trace when an environment exits", |
677 | 132k | &EnvironmentOptions::trace_exit, |
678 | 132k | kAllowedInEnvvar); |
679 | 132k | AddOption("--trace-sync-io", |
680 | 132k | "show stack trace when use of sync IO is detected after the " |
681 | 132k | "first tick", |
682 | 132k | &EnvironmentOptions::trace_sync_io, |
683 | 132k | kAllowedInEnvvar); |
684 | 132k | AddOption("--trace-tls", |
685 | 132k | "prints TLS packet trace information to stderr", |
686 | 132k | &EnvironmentOptions::trace_tls, |
687 | 132k | kAllowedInEnvvar); |
688 | 132k | AddOption("--trace-uncaught", |
689 | 132k | "show stack traces for the `throw` behind uncaught exceptions", |
690 | 132k | &EnvironmentOptions::trace_uncaught, |
691 | 132k | kAllowedInEnvvar); |
692 | 132k | AddOption("--trace-warnings", |
693 | 132k | "show stack traces on process warnings", |
694 | 132k | &EnvironmentOptions::trace_warnings, |
695 | 132k | kAllowedInEnvvar); |
696 | 132k | AddOption("--trace-promises", |
697 | 132k | "show stack traces on promise initialization and resolution", |
698 | 132k | &EnvironmentOptions::trace_promises, |
699 | 132k | kAllowedInEnvvar); |
700 | 132k | AddOption("--experimental-default-type", |
701 | 132k | "set module system to use by default", |
702 | 132k | &EnvironmentOptions::type, |
703 | 132k | kAllowedInEnvvar); |
704 | 132k | AddOption("--extra-info-on-fatal-exception", |
705 | 132k | "hide extra information on fatal exception that causes exit", |
706 | 132k | &EnvironmentOptions::extra_info_on_fatal_exception, |
707 | 132k | kAllowedInEnvvar, |
708 | 132k | true); |
709 | 132k | AddOption("--unhandled-rejections", |
710 | 132k | "define unhandled rejections behavior. Options are 'strict' " |
711 | 132k | "(always raise an error), 'throw' (raise an error unless " |
712 | 132k | "'unhandledRejection' hook is set), 'warn' (log a warning), 'none' " |
713 | 132k | "(silence warnings), 'warn-with-error-code' (log a warning and set " |
714 | 132k | "exit code 1 unless 'unhandledRejection' hook is set). (default: " |
715 | 132k | "throw)", |
716 | 132k | &EnvironmentOptions::unhandled_rejections, |
717 | 132k | kAllowedInEnvvar); |
718 | 132k | AddOption("--verify-base-objects", |
719 | 132k | "", /* undocumented, only for debugging */ |
720 | 132k | &EnvironmentOptions::verify_base_objects, |
721 | 132k | kAllowedInEnvvar); |
722 | 132k | AddOption("--watch", |
723 | 132k | "run in watch mode", |
724 | 132k | &EnvironmentOptions::watch_mode, |
725 | 132k | kAllowedInEnvvar); |
726 | 132k | AddOption("--watch-path", |
727 | 132k | "path to watch", |
728 | 132k | &EnvironmentOptions::watch_mode_paths, |
729 | 132k | kAllowedInEnvvar); |
730 | 132k | AddOption("--watch-preserve-output", |
731 | 132k | "preserve outputs on watch mode restart", |
732 | 132k | &EnvironmentOptions::watch_mode_preserve_output, |
733 | 132k | kAllowedInEnvvar); |
734 | 132k | Implies("--watch-path", "--watch"); |
735 | 132k | AddOption("--check", |
736 | 132k | "syntax check script without executing", |
737 | 132k | &EnvironmentOptions::syntax_check_only); |
738 | 132k | AddAlias("-c", "--check"); |
739 | | // This option is only so that we can tell --eval with an empty string from |
740 | | // no eval at all. Having it not start with a dash makes it inaccessible |
741 | | // from the parser itself, but available for using Implies(). |
742 | | // TODO(addaleax): When moving --help over to something generated from the |
743 | | // programmatic descriptions, this will need some special care. |
744 | | // (See also [ssl_openssl_cert_store] below.) |
745 | 132k | AddOption("[has_eval_string]", "", &EnvironmentOptions::has_eval_string); |
746 | 132k | AddOption("--eval", "evaluate script", &EnvironmentOptions::eval_string); |
747 | 132k | Implies("--eval", "[has_eval_string]"); |
748 | 132k | AddOption("--print", |
749 | 132k | "evaluate script and print result", |
750 | 132k | &EnvironmentOptions::print_eval); |
751 | 132k | AddAlias("-e", "--eval"); |
752 | 132k | AddAlias("--print <arg>", "-pe"); |
753 | 132k | AddAlias("-pe", { "--print", "--eval" }); |
754 | 132k | AddAlias("-p", "--print"); |
755 | 132k | AddOption("--require", |
756 | 132k | "CommonJS module to preload (option can be repeated)", |
757 | 132k | &EnvironmentOptions::preload_cjs_modules, |
758 | 132k | kAllowedInEnvvar); |
759 | 132k | AddAlias("-r", "--require"); |
760 | 132k | AddOption("--import", |
761 | 132k | "ES module to preload (option can be repeated)", |
762 | 132k | &EnvironmentOptions::preload_esm_modules, |
763 | 132k | kAllowedInEnvvar); |
764 | 132k | AddOption("--interactive", |
765 | 132k | "always enter the REPL even if stdin does not appear " |
766 | 132k | "to be a terminal", |
767 | 132k | &EnvironmentOptions::force_repl); |
768 | 132k | AddAlias("-i", "--interactive"); |
769 | | |
770 | 132k | AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvvar); |
771 | | |
772 | 132k | AddOption("--tls-keylog", |
773 | 132k | "log TLS decryption keys to named file for traffic analysis", |
774 | 132k | &EnvironmentOptions::tls_keylog, |
775 | 132k | kAllowedInEnvvar); |
776 | | |
777 | 132k | AddOption("--tls-min-v1.0", |
778 | 132k | "set default TLS minimum to TLSv1.0 (default: TLSv1.2)", |
779 | 132k | &EnvironmentOptions::tls_min_v1_0, |
780 | 132k | kAllowedInEnvvar); |
781 | 132k | AddOption("--tls-min-v1.1", |
782 | 132k | "set default TLS minimum to TLSv1.1 (default: TLSv1.2)", |
783 | 132k | &EnvironmentOptions::tls_min_v1_1, |
784 | 132k | kAllowedInEnvvar); |
785 | 132k | AddOption("--tls-min-v1.2", |
786 | 132k | "set default TLS minimum to TLSv1.2 (default: TLSv1.2)", |
787 | 132k | &EnvironmentOptions::tls_min_v1_2, |
788 | 132k | kAllowedInEnvvar); |
789 | 132k | AddOption("--tls-min-v1.3", |
790 | 132k | "set default TLS minimum to TLSv1.3 (default: TLSv1.2)", |
791 | 132k | &EnvironmentOptions::tls_min_v1_3, |
792 | 132k | kAllowedInEnvvar); |
793 | 132k | AddOption("--tls-max-v1.2", |
794 | 132k | "set default TLS maximum to TLSv1.2 (default: TLSv1.3)", |
795 | 132k | &EnvironmentOptions::tls_max_v1_2, |
796 | 132k | kAllowedInEnvvar); |
797 | | // Current plan is: |
798 | | // - 11.x and below: TLS1.3 is opt-in with --tls-max-v1.3 |
799 | | // - 12.x: TLS1.3 is opt-out with --tls-max-v1.2 |
800 | | // In either case, support both options they are uniformly available. |
801 | 132k | AddOption("--tls-max-v1.3", |
802 | 132k | "set default TLS maximum to TLSv1.3 (default: TLSv1.3)", |
803 | 132k | &EnvironmentOptions::tls_max_v1_3, |
804 | 132k | kAllowedInEnvvar); |
805 | | |
806 | 132k | AddOption("--report-exclude-network", |
807 | 132k | "exclude network interface diagnostics." |
808 | 132k | " (default: false)", |
809 | 132k | &EnvironmentOptions::report_exclude_network, |
810 | 132k | kAllowedInEnvvar); |
811 | 132k | } |
812 | | |
813 | | PerIsolateOptionsParser::PerIsolateOptionsParser( |
814 | 132k | const EnvironmentOptionsParser& eop) { |
815 | 132k | AddOption("--track-heap-objects", |
816 | 132k | "track heap object allocations for heap snapshots", |
817 | 132k | &PerIsolateOptions::track_heap_objects, |
818 | 132k | kAllowedInEnvvar); |
819 | | |
820 | | // Explicitly add some V8 flags to mark them as allowed in NODE_OPTIONS. |
821 | 132k | AddOption("--abort-on-uncaught-exception", |
822 | 132k | "aborting instead of exiting causes a core file to be generated " |
823 | 132k | "for analysis", |
824 | 132k | V8Option{}, |
825 | 132k | kAllowedInEnvvar); |
826 | 132k | AddOption("--interpreted-frames-native-stack", |
827 | 132k | "help system profilers to translate JavaScript interpreted frames", |
828 | 132k | V8Option{}, |
829 | 132k | kAllowedInEnvvar); |
830 | 132k | AddOption("--max-old-space-size", "", V8Option{}, kAllowedInEnvvar); |
831 | 132k | AddOption("--max-semi-space-size", "", V8Option{}, kAllowedInEnvvar); |
832 | 132k | AddOption("--perf-basic-prof", "", V8Option{}, kAllowedInEnvvar); |
833 | 132k | AddOption( |
834 | 132k | "--perf-basic-prof-only-functions", "", V8Option{}, kAllowedInEnvvar); |
835 | 132k | AddOption("--perf-prof", "", V8Option{}, kAllowedInEnvvar); |
836 | 132k | AddOption("--perf-prof-unwinding-info", "", V8Option{}, kAllowedInEnvvar); |
837 | 132k | AddOption("--stack-trace-limit", "", V8Option{}, kAllowedInEnvvar); |
838 | 132k | AddOption("--disallow-code-generation-from-strings", |
839 | 132k | "disallow eval and friends", |
840 | 132k | V8Option{}, |
841 | 132k | kAllowedInEnvvar); |
842 | 132k | AddOption("--huge-max-old-generation-size", |
843 | 132k | "increase default maximum heap size on machines with 16GB memory " |
844 | 132k | "or more", |
845 | 132k | V8Option{}, |
846 | 132k | kAllowedInEnvvar); |
847 | 132k | AddOption("--jitless", |
848 | 132k | "disable runtime allocation of executable memory", |
849 | 132k | V8Option{}, |
850 | 132k | kAllowedInEnvvar); |
851 | 132k | AddOption("--report-uncaught-exception", |
852 | 132k | "generate diagnostic report on uncaught exceptions", |
853 | 132k | &PerIsolateOptions::report_uncaught_exception, |
854 | 132k | kAllowedInEnvvar); |
855 | 132k | AddOption("--report-on-signal", |
856 | 132k | "generate diagnostic report upon receiving signals", |
857 | 132k | &PerIsolateOptions::report_on_signal, |
858 | 132k | kAllowedInEnvvar); |
859 | 132k | AddOption("--report-signal", |
860 | 132k | "causes diagnostic report to be produced on provided signal," |
861 | 132k | " unsupported in Windows. (default: SIGUSR2)", |
862 | 132k | &PerIsolateOptions::report_signal, |
863 | 132k | kAllowedInEnvvar); |
864 | 132k | Implies("--report-signal", "--report-on-signal"); |
865 | 132k | AddOption("--enable-etw-stack-walking", |
866 | 132k | "provides heap data to ETW Windows native tracing", |
867 | 132k | V8Option{}, |
868 | 132k | kAllowedInEnvvar); |
869 | | |
870 | 132k | AddOption("--experimental-top-level-await", "", NoOp{}, kAllowedInEnvvar); |
871 | | |
872 | 132k | AddOption("--experimental-shadow-realm", |
873 | 132k | "", |
874 | 132k | &PerIsolateOptions::experimental_shadow_realm, |
875 | 132k | kAllowedInEnvvar); |
876 | 132k | AddOption("--harmony-shadow-realm", "", V8Option{}); |
877 | 132k | Implies("--experimental-shadow-realm", "--harmony-shadow-realm"); |
878 | 132k | Implies("--harmony-shadow-realm", "--experimental-shadow-realm"); |
879 | 132k | ImpliesNot("--no-harmony-shadow-realm", "--experimental-shadow-realm"); |
880 | 132k | AddOption("--build-snapshot", |
881 | 132k | "Generate a snapshot blob when the process exits.", |
882 | 132k | &PerIsolateOptions::build_snapshot, |
883 | 132k | kDisallowedInEnvvar); |
884 | 132k | AddOption("--build-snapshot-config", |
885 | 132k | "Generate a snapshot blob when the process exits using a" |
886 | 132k | "JSON configuration in the specified path.", |
887 | 132k | &PerIsolateOptions::build_snapshot_config, |
888 | 132k | kDisallowedInEnvvar); |
889 | 132k | Implies("--build-snapshot-config", "--build-snapshot"); |
890 | | |
891 | 132k | Insert(eop, &PerIsolateOptions::get_per_env_options); |
892 | 132k | } |
893 | | |
894 | | PerProcessOptionsParser::PerProcessOptionsParser( |
895 | 132k | const PerIsolateOptionsParser& iop) { |
896 | 132k | AddOption("--title", |
897 | 132k | "the process title to use on startup", |
898 | 132k | &PerProcessOptions::title, |
899 | 132k | kAllowedInEnvvar); |
900 | 132k | AddOption("--trace-event-categories", |
901 | 132k | "comma separated list of trace event categories to record", |
902 | 132k | &PerProcessOptions::trace_event_categories, |
903 | 132k | kAllowedInEnvvar); |
904 | 132k | AddOption("--trace-event-file-pattern", |
905 | 132k | "Template string specifying the filepath for the trace-events " |
906 | 132k | "data, it supports ${rotation} and ${pid}.", |
907 | 132k | &PerProcessOptions::trace_event_file_pattern, |
908 | 132k | kAllowedInEnvvar); |
909 | 132k | AddAlias("--trace-events-enabled", { |
910 | 132k | "--trace-event-categories", "v8,node,node.async_hooks" }); |
911 | 132k | AddOption("--v8-pool-size", |
912 | 132k | "set V8's thread pool size", |
913 | 132k | &PerProcessOptions::v8_thread_pool_size, |
914 | 132k | kAllowedInEnvvar); |
915 | 132k | AddOption("--zero-fill-buffers", |
916 | 132k | "automatically zero-fill all newly allocated Buffer and " |
917 | 132k | "SlowBuffer instances", |
918 | 132k | &PerProcessOptions::zero_fill_all_buffers, |
919 | 132k | kAllowedInEnvvar); |
920 | 132k | AddOption("--debug-arraybuffer-allocations", |
921 | 132k | "", /* undocumented, only for debugging */ |
922 | 132k | &PerProcessOptions::debug_arraybuffer_allocations, |
923 | 132k | kAllowedInEnvvar); |
924 | 132k | AddOption("--disable-proto", |
925 | 132k | "disable Object.prototype.__proto__", |
926 | 132k | &PerProcessOptions::disable_proto, |
927 | 132k | kAllowedInEnvvar); |
928 | 132k | AddOption("--node-snapshot", |
929 | 132k | "", // It's a debug-only option. |
930 | 132k | &PerProcessOptions::node_snapshot, |
931 | 132k | kAllowedInEnvvar); |
932 | 132k | AddOption("--snapshot-blob", |
933 | 132k | "Path to the snapshot blob that's either the result of snapshot" |
934 | 132k | "building, or the blob that is used to restore the application " |
935 | 132k | "state", |
936 | 132k | &PerProcessOptions::snapshot_blob, |
937 | 132k | kAllowedInEnvvar); |
938 | | |
939 | | // 12.x renamed this inadvertently, so alias it for consistency within the |
940 | | // release line, while using the original name for consistency with older |
941 | | // release lines. |
942 | 132k | AddOption("--security-revert", "", &PerProcessOptions::security_reverts); |
943 | 132k | AddAlias("--security-reverts", "--security-revert"); |
944 | 132k | AddOption("--completion-bash", |
945 | 132k | "print source-able bash completion script", |
946 | 132k | &PerProcessOptions::print_bash_completion); |
947 | 132k | AddOption("--help", |
948 | 132k | "print node command line options", |
949 | 132k | &PerProcessOptions::print_help); |
950 | 132k | AddAlias("-h", "--help"); |
951 | 132k | AddOption( |
952 | 132k | "--version", "print Node.js version", &PerProcessOptions::print_version); |
953 | 132k | AddAlias("-v", "--version"); |
954 | 132k | AddOption("--v8-options", |
955 | 132k | "print V8 command line options", |
956 | 132k | &PerProcessOptions::print_v8_help); |
957 | 132k | AddOption("--report-compact", |
958 | 132k | "output compact single-line JSON", |
959 | 132k | &PerProcessOptions::report_compact, |
960 | 132k | kAllowedInEnvvar); |
961 | 132k | AddOption("--report-dir", |
962 | 132k | "define custom report pathname." |
963 | 132k | " (default: current working directory)", |
964 | 132k | &PerProcessOptions::report_directory, |
965 | 132k | kAllowedInEnvvar); |
966 | 132k | AddAlias("--report-directory", "--report-dir"); |
967 | 132k | AddOption("--report-filename", |
968 | 132k | "define custom report file name." |
969 | 132k | " (default: YYYYMMDD.HHMMSS.PID.SEQUENCE#.txt)", |
970 | 132k | &PerProcessOptions::report_filename, |
971 | 132k | kAllowedInEnvvar); |
972 | 132k | AddOption("--report-on-fatalerror", |
973 | 132k | "generate diagnostic report on fatal (internal) errors", |
974 | 132k | &PerProcessOptions::report_on_fatalerror, |
975 | 132k | kAllowedInEnvvar); |
976 | | |
977 | 132k | #ifdef NODE_HAVE_I18N_SUPPORT |
978 | 132k | AddOption("--icu-data-dir", |
979 | 132k | "set ICU data load path to dir (overrides NODE_ICU_DATA)" |
980 | 132k | #ifndef NODE_HAVE_SMALL_ICU |
981 | 132k | " (note: linked-in ICU data is present)" |
982 | 132k | #endif |
983 | 132k | , |
984 | 132k | &PerProcessOptions::icu_data_dir, |
985 | 132k | kAllowedInEnvvar); |
986 | 132k | #endif |
987 | | |
988 | 132k | #if HAVE_OPENSSL |
989 | 132k | AddOption("--openssl-config", |
990 | 132k | "load OpenSSL configuration from the specified file " |
991 | 132k | "(overrides OPENSSL_CONF)", |
992 | 132k | &PerProcessOptions::openssl_config, |
993 | 132k | kAllowedInEnvvar); |
994 | 132k | AddOption("--tls-cipher-list", |
995 | 132k | "use an alternative default TLS cipher list", |
996 | 132k | &PerProcessOptions::tls_cipher_list, |
997 | 132k | kAllowedInEnvvar); |
998 | 132k | AddOption("--use-openssl-ca", |
999 | 132k | "use OpenSSL's default CA store" |
1000 | | #if defined(NODE_OPENSSL_CERT_STORE) |
1001 | | " (default)" |
1002 | | #endif |
1003 | 132k | , |
1004 | 132k | &PerProcessOptions::use_openssl_ca, |
1005 | 132k | kAllowedInEnvvar); |
1006 | 132k | AddOption("--use-bundled-ca", |
1007 | 132k | "use bundled CA store" |
1008 | 132k | #if !defined(NODE_OPENSSL_CERT_STORE) |
1009 | 132k | " (default)" |
1010 | 132k | #endif |
1011 | 132k | , |
1012 | 132k | &PerProcessOptions::use_bundled_ca, |
1013 | 132k | kAllowedInEnvvar); |
1014 | | // Similar to [has_eval_string] above, except that the separation between |
1015 | | // this and use_openssl_ca only exists for option validation after parsing. |
1016 | | // This is not ideal. |
1017 | 132k | AddOption("[ssl_openssl_cert_store]", |
1018 | 132k | "", |
1019 | 132k | &PerProcessOptions::ssl_openssl_cert_store); |
1020 | 132k | Implies("--use-openssl-ca", "[ssl_openssl_cert_store]"); |
1021 | 132k | ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]"); |
1022 | 132k | AddOption("--enable-fips", |
1023 | 132k | "enable FIPS crypto at startup", |
1024 | 132k | &PerProcessOptions::enable_fips_crypto, |
1025 | 132k | kAllowedInEnvvar); |
1026 | 132k | AddOption("--force-fips", |
1027 | 132k | "force FIPS crypto (cannot be disabled)", |
1028 | 132k | &PerProcessOptions::force_fips_crypto, |
1029 | 132k | kAllowedInEnvvar); |
1030 | 132k | AddOption("--secure-heap", |
1031 | 132k | "total size of the OpenSSL secure heap", |
1032 | 132k | &PerProcessOptions::secure_heap, |
1033 | 132k | kAllowedInEnvvar); |
1034 | 132k | AddOption("--secure-heap-min", |
1035 | 132k | "minimum allocation size from the OpenSSL secure heap", |
1036 | 132k | &PerProcessOptions::secure_heap_min, |
1037 | 132k | kAllowedInEnvvar); |
1038 | 132k | #endif // HAVE_OPENSSL |
1039 | 132k | #if OPENSSL_VERSION_MAJOR >= 3 |
1040 | 132k | AddOption("--openssl-legacy-provider", |
1041 | 132k | "enable OpenSSL 3.0 legacy provider", |
1042 | 132k | &PerProcessOptions::openssl_legacy_provider, |
1043 | 132k | kAllowedInEnvvar); |
1044 | 132k | AddOption("--openssl-shared-config", |
1045 | 132k | "enable OpenSSL shared configuration", |
1046 | 132k | &PerProcessOptions::openssl_shared_config, |
1047 | 132k | kAllowedInEnvvar); |
1048 | | |
1049 | 132k | #endif // OPENSSL_VERSION_MAJOR |
1050 | 132k | AddOption("--use-largepages", |
1051 | 132k | "Map the Node.js static code to large pages. Options are " |
1052 | 132k | "'off' (the default value, meaning do not map), " |
1053 | 132k | "'on' (map and ignore failure, reporting it to stderr), " |
1054 | 132k | "or 'silent' (map and silently ignore failure)", |
1055 | 132k | &PerProcessOptions::use_largepages, |
1056 | 132k | kAllowedInEnvvar); |
1057 | | |
1058 | 132k | AddOption("--trace-sigint", |
1059 | 132k | "enable printing JavaScript stacktrace on SIGINT", |
1060 | 132k | &PerProcessOptions::trace_sigint, |
1061 | 132k | kAllowedInEnvvar); |
1062 | | |
1063 | 132k | Insert(iop, &PerProcessOptions::get_per_isolate_options); |
1064 | | |
1065 | 132k | AddOption("--node-memory-debug", |
1066 | 132k | "Run with extra debug checks for memory leaks in Node.js itself", |
1067 | 132k | NoOp{}, |
1068 | 132k | kAllowedInEnvvar); |
1069 | 132k | Implies("--node-memory-debug", "--debug-arraybuffer-allocations"); |
1070 | 132k | Implies("--node-memory-debug", "--verify-base-objects"); |
1071 | | |
1072 | 132k | AddOption("--experimental-sea-config", |
1073 | 132k | "Generate a blob that can be embedded into the single executable " |
1074 | 132k | "application", |
1075 | 132k | &PerProcessOptions::experimental_sea_config); |
1076 | 132k | } |
1077 | | |
1078 | 0 | inline std::string RemoveBrackets(const std::string& host) { |
1079 | 0 | if (!host.empty() && host.front() == '[' && host.back() == ']') |
1080 | 0 | return host.substr(1, host.size() - 2); |
1081 | 0 | else |
1082 | 0 | return host; |
1083 | 0 | } |
1084 | | |
1085 | | inline uint16_t ParseAndValidatePort(const std::string_view port, |
1086 | 0 | std::vector<std::string>* errors) { |
1087 | 0 | uint16_t result{}; |
1088 | 0 | auto r = std::from_chars(port.data(), port.data() + port.size(), result); |
1089 | |
|
1090 | 0 | if (r.ec == std::errc::result_out_of_range || |
1091 | 0 | (result != 0 && result < 1024)) { |
1092 | 0 | errors->push_back(" must be 0 or in range 1024 to 65535."); |
1093 | 0 | } |
1094 | |
|
1095 | 0 | return result; |
1096 | 0 | } |
1097 | | |
1098 | | HostPort SplitHostPort(const std::string& arg, |
1099 | 0 | std::vector<std::string>* errors) { |
1100 | | // remove_brackets only works if no port is specified |
1101 | | // so if it has an effect only an IPv6 address was specified. |
1102 | 0 | std::string host = RemoveBrackets(arg); |
1103 | 0 | if (host.length() < arg.length()) |
1104 | 0 | return HostPort{host, DebugOptions::kDefaultInspectorPort}; |
1105 | | |
1106 | 0 | size_t colon = arg.rfind(':'); |
1107 | 0 | if (colon == std::string::npos) { |
1108 | | // Either a port number or a host name. Assume that |
1109 | | // if it's not all decimal digits, it's a host name. |
1110 | 0 | for (char c : arg) { |
1111 | 0 | if (c < '0' || c > '9') { |
1112 | 0 | return HostPort{arg, DebugOptions::kDefaultInspectorPort}; |
1113 | 0 | } |
1114 | 0 | } |
1115 | 0 | return HostPort { "", ParseAndValidatePort(arg, errors) }; |
1116 | 0 | } |
1117 | | // Host and port found: |
1118 | 0 | return HostPort { RemoveBrackets(arg.substr(0, colon)), |
1119 | 0 | ParseAndValidatePort(arg.substr(colon + 1), errors) }; |
1120 | 0 | } |
1121 | | |
1122 | 0 | std::string GetBashCompletion() { |
1123 | 0 | Mutex::ScopedLock lock(per_process::cli_options_mutex); |
1124 | 0 | const auto& parser = _ppop_instance; |
1125 | |
|
1126 | 0 | std::ostringstream out; |
1127 | |
|
1128 | 0 | out << "_node_complete() {\n" |
1129 | 0 | " local cur_word options\n" |
1130 | 0 | " cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n" |
1131 | 0 | " if [[ \"${cur_word}\" == -* ]] ; then\n" |
1132 | 0 | " COMPREPLY=( $(compgen -W '"; |
1133 | |
|
1134 | 0 | for (const auto& item : parser.options_) { |
1135 | 0 | if (item.first[0] != '[') { |
1136 | 0 | out << item.first << " "; |
1137 | 0 | } |
1138 | 0 | } |
1139 | 0 | for (const auto& item : parser.aliases_) { |
1140 | 0 | if (item.first[0] != '[') { |
1141 | 0 | out << item.first << " "; |
1142 | 0 | } |
1143 | 0 | } |
1144 | 0 | if (parser.aliases_.size() > 0) { |
1145 | 0 | out.seekp(-1, out.cur); // Strip the trailing space |
1146 | 0 | } |
1147 | |
|
1148 | 0 | out << "' -- \"${cur_word}\") )\n" |
1149 | 0 | " return 0\n" |
1150 | 0 | " else\n" |
1151 | 0 | " COMPREPLY=( $(compgen -f \"${cur_word}\") )\n" |
1152 | 0 | " return 0\n" |
1153 | 0 | " fi\n" |
1154 | 0 | "}\n" |
1155 | 0 | "complete -o filenames -o nospace -o bashdefault " |
1156 | 0 | "-F _node_complete node node_g"; |
1157 | 0 | return out.str(); |
1158 | 0 | } |
1159 | | |
1160 | | // Return a map containing all the options and their metadata as well |
1161 | | // as the aliases |
1162 | 134k | void GetCLIOptions(const FunctionCallbackInfo<Value>& args) { |
1163 | 134k | Mutex::ScopedLock lock(per_process::cli_options_mutex); |
1164 | 134k | Environment* env = Environment::GetCurrent(args); |
1165 | 134k | if (!env->has_run_bootstrapping_code()) { |
1166 | | // No code because this is an assertion. |
1167 | 0 | return env->ThrowError( |
1168 | 0 | "Should not query options before bootstrapping is done"); |
1169 | 0 | } |
1170 | 134k | env->set_has_serialized_options(true); |
1171 | | |
1172 | 134k | Isolate* isolate = env->isolate(); |
1173 | 134k | Local<Context> context = env->context(); |
1174 | | |
1175 | | // Temporarily act as if the current Environment's/IsolateData's options were |
1176 | | // the default options, i.e. like they are the ones we'd access for global |
1177 | | // options parsing, so that all options are available from the main parser. |
1178 | 134k | auto original_per_isolate = per_process::cli_options->per_isolate; |
1179 | 134k | per_process::cli_options->per_isolate = env->isolate_data()->options(); |
1180 | 134k | auto original_per_env = per_process::cli_options->per_isolate->per_env; |
1181 | 134k | per_process::cli_options->per_isolate->per_env = env->options(); |
1182 | 134k | auto on_scope_leave = OnScopeLeave([&]() { |
1183 | 134k | per_process::cli_options->per_isolate->per_env = original_per_env; |
1184 | 134k | per_process::cli_options->per_isolate = original_per_isolate; |
1185 | 134k | }); |
1186 | | |
1187 | 134k | Local<Map> options = Map::New(isolate); |
1188 | 134k | if (options |
1189 | 134k | ->SetPrototype(context, env->primordials_safe_map_prototype_object()) |
1190 | 134k | .IsNothing()) { |
1191 | 0 | return; |
1192 | 0 | } |
1193 | | |
1194 | 23.2M | for (const auto& item : _ppop_instance.options_) { |
1195 | 23.2M | Local<Value> value; |
1196 | 23.2M | const auto& option_info = item.second; |
1197 | 23.2M | auto field = option_info.field; |
1198 | 23.2M | PerProcessOptions* opts = per_process::cli_options.get(); |
1199 | 23.2M | switch (option_info.type) { |
1200 | 1.48M | case kNoOp: |
1201 | 3.49M | case kV8Option: |
1202 | | // Special case for --abort-on-uncaught-exception which is also |
1203 | | // respected by Node.js internals |
1204 | 3.49M | if (item.first == "--abort-on-uncaught-exception") { |
1205 | 134k | value = Boolean::New( |
1206 | 134k | isolate, original_per_env->abort_on_uncaught_exception); |
1207 | 3.36M | } else { |
1208 | 3.36M | value = Undefined(isolate); |
1209 | 3.36M | } |
1210 | 3.49M | break; |
1211 | 12.5M | case kBoolean: |
1212 | 12.5M | value = Boolean::New(isolate, |
1213 | 12.5M | *_ppop_instance.Lookup<bool>(field, opts)); |
1214 | 12.5M | break; |
1215 | 538k | case kInteger: |
1216 | 538k | value = Number::New( |
1217 | 538k | isolate, |
1218 | 538k | static_cast<double>(*_ppop_instance.Lookup<int64_t>(field, opts))); |
1219 | 538k | break; |
1220 | 672k | case kUInteger: |
1221 | 672k | value = Number::New( |
1222 | 672k | isolate, |
1223 | 672k | static_cast<double>(*_ppop_instance.Lookup<uint64_t>(field, opts))); |
1224 | 672k | break; |
1225 | 4.30M | case kString: |
1226 | 4.30M | if (!ToV8Value(context, |
1227 | 4.30M | *_ppop_instance.Lookup<std::string>(field, opts)) |
1228 | 4.30M | .ToLocal(&value)) { |
1229 | 0 | return; |
1230 | 0 | } |
1231 | 4.30M | break; |
1232 | 4.30M | case kStringList: |
1233 | 1.61M | if (!ToV8Value(context, |
1234 | 1.61M | *_ppop_instance.Lookup<StringVector>(field, opts)) |
1235 | 1.61M | .ToLocal(&value)) { |
1236 | 0 | return; |
1237 | 0 | } |
1238 | 1.61M | break; |
1239 | 1.61M | case kHostPort: { |
1240 | 134k | const HostPort& host_port = |
1241 | 134k | *_ppop_instance.Lookup<HostPort>(field, opts); |
1242 | 134k | Local<Object> obj = Object::New(isolate); |
1243 | 134k | Local<Value> host; |
1244 | 134k | if (!ToV8Value(context, host_port.host()).ToLocal(&host) || |
1245 | 134k | obj->Set(context, env->host_string(), host).IsNothing() || |
1246 | 134k | obj->Set(context, |
1247 | 134k | env->port_string(), |
1248 | 134k | Integer::New(isolate, host_port.port())) |
1249 | 134k | .IsNothing()) { |
1250 | 0 | return; |
1251 | 0 | } |
1252 | 134k | value = obj; |
1253 | 134k | break; |
1254 | 134k | } |
1255 | 0 | default: |
1256 | 0 | UNREACHABLE(); |
1257 | 23.2M | } |
1258 | 23.2M | CHECK(!value.IsEmpty()); |
1259 | | |
1260 | 23.2M | Local<Value> name = ToV8Value(context, item.first).ToLocalChecked(); |
1261 | 23.2M | Local<Object> info = Object::New(isolate); |
1262 | 23.2M | Local<Value> help_text; |
1263 | 23.2M | if (!ToV8Value(context, option_info.help_text).ToLocal(&help_text) || |
1264 | 23.2M | !info->Set(context, env->help_text_string(), help_text) |
1265 | 23.2M | .FromMaybe(false) || |
1266 | 23.2M | !info->Set(context, |
1267 | 23.2M | env->env_var_settings_string(), |
1268 | 23.2M | Integer::New(isolate, |
1269 | 23.2M | static_cast<int>(option_info.env_setting))) |
1270 | 23.2M | .FromMaybe(false) || |
1271 | 23.2M | !info->Set(context, |
1272 | 23.2M | env->type_string(), |
1273 | 23.2M | Integer::New(isolate, static_cast<int>(option_info.type))) |
1274 | 23.2M | .FromMaybe(false) || |
1275 | 23.2M | !info->Set(context, |
1276 | 23.2M | env->default_is_true_string(), |
1277 | 23.2M | Boolean::New(isolate, option_info.default_is_true)) |
1278 | 23.2M | .FromMaybe(false) || |
1279 | 23.2M | info->Set(context, env->value_string(), value).IsNothing() || |
1280 | 23.2M | options->Set(context, name, info).IsEmpty()) { |
1281 | 0 | return; |
1282 | 0 | } |
1283 | 23.2M | } |
1284 | | |
1285 | 134k | Local<Value> aliases; |
1286 | 134k | if (!ToV8Value(context, _ppop_instance.aliases_).ToLocal(&aliases)) return; |
1287 | | |
1288 | 134k | if (aliases.As<Object>() |
1289 | 134k | ->SetPrototype(context, env->primordials_safe_map_prototype_object()) |
1290 | 134k | .IsNothing()) { |
1291 | 0 | return; |
1292 | 0 | } |
1293 | | |
1294 | 134k | Local<Object> ret = Object::New(isolate); |
1295 | 134k | if (ret->Set(context, env->options_string(), options).IsNothing() || |
1296 | 134k | ret->Set(context, env->aliases_string(), aliases).IsNothing()) { |
1297 | 0 | return; |
1298 | 0 | } |
1299 | | |
1300 | 134k | args.GetReturnValue().Set(ret); |
1301 | 134k | } |
1302 | | |
1303 | 134k | void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) { |
1304 | 134k | Environment* env = Environment::GetCurrent(args); |
1305 | 134k | if (!env->has_run_bootstrapping_code()) { |
1306 | | // No code because this is an assertion. |
1307 | 0 | return env->ThrowError( |
1308 | 0 | "Should not query options before bootstrapping is done"); |
1309 | 0 | } |
1310 | 134k | Isolate* isolate = args.GetIsolate(); |
1311 | 134k | Local<Context> context = env->context(); |
1312 | 134k | Local<Object> ret = Object::New(isolate); |
1313 | | |
1314 | 134k | if (ret->Set(context, |
1315 | 134k | FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"), |
1316 | 134k | Boolean::New(isolate, env->should_not_register_esm_loader())) |
1317 | 134k | .IsNothing()) return; |
1318 | | |
1319 | 134k | if (ret->Set(context, |
1320 | 134k | FIXED_ONE_BYTE_STRING(env->isolate(), "noGlobalSearchPaths"), |
1321 | 134k | Boolean::New(isolate, env->no_global_search_paths())) |
1322 | 134k | .IsNothing()) return; |
1323 | | |
1324 | 134k | if (ret->Set(context, |
1325 | 134k | FIXED_ONE_BYTE_STRING(env->isolate(), "noBrowserGlobals"), |
1326 | 134k | Boolean::New(isolate, env->no_browser_globals())) |
1327 | 134k | .IsNothing()) |
1328 | 0 | return; |
1329 | | |
1330 | 134k | if (ret->Set(context, |
1331 | 134k | FIXED_ONE_BYTE_STRING(env->isolate(), "hasEmbedderPreload"), |
1332 | 134k | Boolean::New(isolate, env->embedder_preload() != nullptr)) |
1333 | 134k | .IsNothing()) |
1334 | 0 | return; |
1335 | | |
1336 | 134k | args.GetReturnValue().Set(ret); |
1337 | 134k | } |
1338 | | |
1339 | | void Initialize(Local<Object> target, |
1340 | | Local<Value> unused, |
1341 | | Local<Context> context, |
1342 | 134k | void* priv) { |
1343 | 134k | Environment* env = Environment::GetCurrent(context); |
1344 | 134k | Isolate* isolate = env->isolate(); |
1345 | 134k | SetMethodNoSideEffect(context, target, "getCLIOptions", GetCLIOptions); |
1346 | 134k | SetMethodNoSideEffect( |
1347 | 134k | context, target, "getEmbedderOptions", GetEmbedderOptions); |
1348 | | |
1349 | 134k | Local<Object> env_settings = Object::New(isolate); |
1350 | 134k | NODE_DEFINE_CONSTANT(env_settings, kAllowedInEnvvar); |
1351 | 134k | NODE_DEFINE_CONSTANT(env_settings, kDisallowedInEnvvar); |
1352 | 134k | target |
1353 | 134k | ->Set( |
1354 | 134k | context, FIXED_ONE_BYTE_STRING(isolate, "envSettings"), env_settings) |
1355 | 134k | .Check(); |
1356 | | |
1357 | 134k | Local<Object> types = Object::New(isolate); |
1358 | 134k | NODE_DEFINE_CONSTANT(types, kNoOp); |
1359 | 134k | NODE_DEFINE_CONSTANT(types, kV8Option); |
1360 | 134k | NODE_DEFINE_CONSTANT(types, kBoolean); |
1361 | 134k | NODE_DEFINE_CONSTANT(types, kInteger); |
1362 | 134k | NODE_DEFINE_CONSTANT(types, kUInteger); |
1363 | 134k | NODE_DEFINE_CONSTANT(types, kString); |
1364 | 134k | NODE_DEFINE_CONSTANT(types, kHostPort); |
1365 | 134k | NODE_DEFINE_CONSTANT(types, kStringList); |
1366 | 134k | target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "types"), types) |
1367 | 134k | .Check(); |
1368 | 134k | } |
1369 | | |
1370 | 0 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
1371 | 0 | registry->Register(GetCLIOptions); |
1372 | 0 | registry->Register(GetEmbedderOptions); |
1373 | 0 | } |
1374 | | } // namespace options_parser |
1375 | | |
1376 | 132k | void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options) { |
1377 | 529k | HandleEnvOptions(env_options, [](const char* name) { |
1378 | 529k | std::string text; |
1379 | 529k | return credentials::SafeGetenv(name, &text) ? text : ""; |
1380 | 529k | }); |
1381 | 132k | } |
1382 | | |
1383 | | void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options, |
1384 | 132k | std::function<std::string(const char*)> opt_getter) { |
1385 | 132k | env_options->pending_deprecation = |
1386 | 132k | opt_getter("NODE_PENDING_DEPRECATION") == "1"; |
1387 | | |
1388 | 132k | env_options->preserve_symlinks = opt_getter("NODE_PRESERVE_SYMLINKS") == "1"; |
1389 | | |
1390 | 132k | env_options->preserve_symlinks_main = |
1391 | 132k | opt_getter("NODE_PRESERVE_SYMLINKS_MAIN") == "1"; |
1392 | | |
1393 | 132k | if (env_options->redirect_warnings.empty()) |
1394 | 132k | env_options->redirect_warnings = opt_getter("NODE_REDIRECT_WARNINGS"); |
1395 | 132k | } |
1396 | | |
1397 | | std::vector<std::string> ParseNodeOptionsEnvVar( |
1398 | 0 | const std::string& node_options, std::vector<std::string>* errors) { |
1399 | 0 | std::vector<std::string> env_argv; |
1400 | |
|
1401 | 0 | bool is_in_string = false; |
1402 | 0 | bool will_start_new_arg = true; |
1403 | 0 | for (std::string::size_type index = 0; index < node_options.size(); ++index) { |
1404 | 0 | char c = node_options.at(index); |
1405 | | |
1406 | | // Backslashes escape the following character |
1407 | 0 | if (c == '\\' && is_in_string) { |
1408 | 0 | if (index + 1 == node_options.size()) { |
1409 | 0 | errors->push_back("invalid value for NODE_OPTIONS " |
1410 | 0 | "(invalid escape)\n"); |
1411 | 0 | return env_argv; |
1412 | 0 | } else { |
1413 | 0 | c = node_options.at(++index); |
1414 | 0 | } |
1415 | 0 | } else if (c == ' ' && !is_in_string) { |
1416 | 0 | will_start_new_arg = true; |
1417 | 0 | continue; |
1418 | 0 | } else if (c == '"') { |
1419 | 0 | is_in_string = !is_in_string; |
1420 | 0 | continue; |
1421 | 0 | } |
1422 | | |
1423 | 0 | if (will_start_new_arg) { |
1424 | 0 | env_argv.emplace_back(std::string(1, c)); |
1425 | 0 | will_start_new_arg = false; |
1426 | 0 | } else { |
1427 | 0 | env_argv.back() += c; |
1428 | 0 | } |
1429 | 0 | } |
1430 | | |
1431 | 0 | if (is_in_string) { |
1432 | 0 | errors->push_back("invalid value for NODE_OPTIONS " |
1433 | 0 | "(unterminated string)\n"); |
1434 | 0 | } |
1435 | 0 | return env_argv; |
1436 | 0 | } |
1437 | | } // namespace node |
1438 | | |
1439 | | NODE_BINDING_CONTEXT_AWARE_INTERNAL(options, node::options_parser::Initialize) |
1440 | | NODE_BINDING_EXTERNAL_REFERENCE( |
1441 | | options, node::options_parser::RegisterExternalReferences) |