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