1use std::collections::HashMap;
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum OptionType {
20 NoOp,
21 V8Option,
22 Boolean,
23 Integer,
24 UInteger,
25 String,
26 HostPort,
27 StringList,
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum OptionEnvvarSettings {
32 DisallowedInEnvvar,
33 AllowedInEnvvar,
34}
35
36#[derive(Debug, Clone)]
37pub struct HostPort {
38 pub host: String,
39 pub port: u16,
40}
41
42impl Default for HostPort {
43 fn default() -> Self {
44 Self {
45 host: "127.0.0.1".to_string(),
46 port: 9229,
47 }
48 }
49}
50
51impl HostPort {
52 pub fn new(host: String, port: u16) -> Self {
53 Self { host, port }
54 }
55
56 pub fn update(&mut self, other: &HostPort) {
57 if !other.host.is_empty() {
58 self.host = other.host.clone();
59 }
60 self.port = other.port;
61 }
62}
63
64#[derive(Debug, Clone, Default)]
65pub struct InspectPublishUid {
66 pub console: bool,
67 pub http: bool,
68}
69
70#[derive(Debug, Clone)]
71pub struct DebugOptions {
72 pub allow_attaching_debugger: bool,
73 pub inspector_enabled: bool,
74 pub inspect_wait: bool,
75 pub deprecated_debug: bool,
76 pub break_first_line: bool,
77 pub break_node_first_line: bool,
78 pub inspect_publish_uid_string: String,
79 pub inspect_publish_uid: InspectPublishUid,
80 pub host_port: HostPort,
81}
82
83impl Default for DebugOptions {
84 fn default() -> Self {
85 Self {
86 allow_attaching_debugger: true,
87 inspector_enabled: false,
88 inspect_wait: false,
89 deprecated_debug: false,
90 break_first_line: false,
91 break_node_first_line: false,
92 inspect_publish_uid_string: "stderr,http".to_string(),
93 inspect_publish_uid: InspectPublishUid::default(),
94 host_port: HostPort::default(),
95 }
96 }
97}
98
99impl DebugOptions {
100 pub fn enable_break_first_line(&mut self) {
101 self.inspector_enabled = true;
102 self.break_first_line = true;
103 }
104
105 pub fn disable_wait_or_break_first_line(&mut self) {
106 self.inspect_wait = false;
107 self.break_first_line = false;
108 }
109
110 pub fn wait_for_connect(&self) -> bool {
111 self.break_first_line || self.break_node_first_line || self.inspect_wait
112 }
113
114 pub fn should_break_first_line(&self) -> bool {
115 self.break_first_line || self.break_node_first_line
116 }
117
118 pub fn check_options(&mut self, errors: &mut Vec<String>) {
119 let entries: Vec<&str> =
120 self.inspect_publish_uid_string.split(',').collect();
121 self.inspect_publish_uid.console = false;
122 self.inspect_publish_uid.http = false;
123
124 for entry in entries {
125 let destination = entry.trim();
126 match destination {
127 "stderr" => self.inspect_publish_uid.console = true,
128 "http" => self.inspect_publish_uid.http = true,
129 _ => errors.push(
130 "--inspect-publish-uid destination can be stderr or http".to_string(),
131 ),
132 }
133 }
134
135 if self.deprecated_debug {
136 errors.push("[DEP0062]: `node --debug` and `node --debug-brk` are invalid. Please use `node --inspect` and `node --inspect-brk` instead.".to_string());
137 }
138 }
139}
140
141#[derive(Debug, Clone)]
142pub struct EnvironmentOptions {
143 pub abort_on_uncaught_exception: bool,
144 pub conditions: Vec<String>,
145 pub detect_module: bool,
146 pub disable_sigusr1: bool,
147 pub print_required_tla: bool,
148 pub require_module: bool,
149 pub dns_result_order: String,
150 pub enable_source_maps: bool,
151 pub experimental_addon_modules: bool,
152 pub experimental_eventsource: bool,
153 pub experimental_fetch: bool,
154 pub experimental_websocket: bool,
155 pub experimental_sqlite: bool,
156 pub experimental_webstorage: bool,
157 pub experimental_quic: bool,
158 pub localstorage_file: String,
159 pub experimental_global_navigator: bool,
160 pub experimental_global_web_crypto: bool,
161 pub experimental_wasm_modules: bool,
162 pub experimental_import_meta_resolve: bool,
163 pub input_type: String,
164 pub entry_is_url: bool,
165 pub permission: bool,
166 pub allow_fs_read: Vec<String>,
167 pub allow_fs_write: Vec<String>,
168 pub allow_addons: bool,
169 pub allow_child_process: bool,
170 pub allow_net: Vec<String>,
171 pub allow_wasi: bool,
172 pub allow_worker_threads: bool,
173 pub experimental_repl_await: bool,
174 pub experimental_vm_modules: bool,
175 pub async_context_frame: bool,
176 pub expose_internals: bool,
177 pub force_node_api_uncaught_exceptions_policy: bool,
178 pub frozen_intrinsics: bool,
179 pub heap_snapshot_near_heap_limit: i64,
180 pub heapsnapshot_signal: String,
181 pub network_family_autoselection: bool,
182 pub network_family_autoselection_attempt_timeout: u64,
183 pub max_http_header_size: u64,
184 pub deprecation: bool,
185 pub force_async_hooks_checks: bool,
186 pub allow_native_addons: bool,
187 pub global_search_paths: bool,
188 pub warnings: bool,
189 pub disable_warnings: Vec<String>,
190 pub force_context_aware: bool,
191 pub pending_deprecation: bool,
192 pub preserve_symlinks: bool,
193 pub preserve_symlinks_main: bool,
194 pub prof_process: bool,
195 pub cpu_prof_dir: String,
196 pub cpu_prof_interval: u64,
197 pub cpu_prof_name: String,
198 pub cpu_prof: bool,
199 pub experimental_network_inspection: bool,
200 pub experimental_worker_inspection: bool,
201 pub heap_prof_dir: String,
202 pub heap_prof_name: String,
203 pub heap_prof_interval: u64,
204 pub heap_prof: bool,
205 pub redirect_warnings: String,
206 pub diagnostic_dir: String,
207 pub env_file: String,
208 pub optional_env_file: String,
209 pub has_env_file_string: bool,
210 pub test_runner: bool,
211 pub test_runner_concurrency: u64,
212 pub test_runner_timeout: u64,
213 pub test_runner_coverage: bool,
214 pub test_runner_force_exit: bool,
215 pub test_coverage_branches: u64,
216 pub test_coverage_functions: u64,
217 pub test_coverage_lines: u64,
218 pub test_runner_module_mocks: bool,
219 pub test_runner_update_snapshots: bool,
220 pub test_name_pattern: Vec<String>,
221 pub test_reporter: Vec<String>,
222 pub test_reporter_destination: Vec<String>,
223 pub test_global_setup_path: String,
224 pub test_only: bool,
225 pub test_udp_no_try_send: bool,
226 pub test_isolation: String,
227 pub test_shard: String,
228 pub test_skip_pattern: Vec<String>,
229 pub coverage_include_pattern: Vec<String>,
230 pub coverage_exclude_pattern: Vec<String>,
231 pub throw_deprecation: bool,
232 pub trace_deprecation: bool,
233 pub trace_exit: bool,
234 pub trace_sync_io: bool,
235 pub trace_tls: bool,
236 pub trace_uncaught: bool,
237 pub trace_warnings: bool,
238 pub trace_promises: bool,
239 pub trace_env: bool,
240 pub trace_env_js_stack: bool,
241 pub trace_env_native_stack: bool,
242 pub trace_require_module: String,
243 pub extra_info_on_fatal_exception: bool,
244 pub unhandled_rejections: String,
245 pub userland_loaders: Vec<String>,
246 pub verify_base_objects: bool,
247 pub watch_mode: bool,
248 pub watch_mode_report_to_parent: bool,
249 pub watch_mode_preserve_output: bool,
250 pub watch_mode_kill_signal: String,
251 pub watch_mode_paths: Vec<String>,
252 pub syntax_check_only: bool,
253 pub has_eval_string: bool,
254 pub eval_string: String,
255 pub print_eval: bool,
256 pub force_repl: bool,
257 pub insecure_http_parser: bool,
258 pub tls_min_v1_0: bool,
259 pub tls_min_v1_1: bool,
260 pub tls_min_v1_2: bool,
261 pub tls_min_v1_3: bool,
262 pub tls_max_v1_2: bool,
263 pub tls_max_v1_3: bool,
264 pub tls_keylog: String,
265 pub preload_cjs_modules: Vec<String>,
266 pub preload_esm_modules: Vec<String>,
267 pub experimental_strip_types: bool,
268 pub experimental_transform_types: bool,
269 pub user_argv: Vec<String>,
270 pub report_exclude_env: bool,
271 pub report_exclude_network: bool,
272 pub experimental_config_file_path: String,
273 pub experimental_default_config_file: bool,
274 pub debug_options: DebugOptions,
275}
276
277impl Default for EnvironmentOptions {
278 fn default() -> Self {
279 Self {
280 abort_on_uncaught_exception: false,
281 conditions: Vec::new(),
282 detect_module: true,
283 disable_sigusr1: false,
284 print_required_tla: false,
285 require_module: true,
286 dns_result_order: String::new(),
287 enable_source_maps: false,
288 experimental_addon_modules: false,
289 experimental_eventsource: false,
290 experimental_fetch: true,
291 experimental_websocket: true,
292 experimental_sqlite: true,
293 experimental_webstorage: false,
294 experimental_quic: false,
295 localstorage_file: String::new(),
296 experimental_global_navigator: true,
297 experimental_global_web_crypto: true,
298 experimental_wasm_modules: false,
299 experimental_import_meta_resolve: false,
300 input_type: String::new(),
301 entry_is_url: false,
302 permission: false,
303 allow_fs_read: Vec::new(),
304 allow_fs_write: Vec::new(),
305 allow_addons: false,
306 allow_child_process: false,
307 allow_net: Vec::new(),
308 allow_wasi: false,
309 allow_worker_threads: false,
310 experimental_repl_await: true,
311 experimental_vm_modules: false,
312 async_context_frame: true,
313 expose_internals: false,
314 force_node_api_uncaught_exceptions_policy: false,
315 frozen_intrinsics: false,
316 heap_snapshot_near_heap_limit: 0,
317 heapsnapshot_signal: String::new(),
318 network_family_autoselection: true,
319 network_family_autoselection_attempt_timeout: 250,
320 max_http_header_size: 16 * 1024,
321 deprecation: true,
322 force_async_hooks_checks: true,
323 allow_native_addons: true,
324 global_search_paths: true,
325 warnings: true,
326 disable_warnings: Vec::new(),
327 force_context_aware: false,
328 pending_deprecation: false,
329 preserve_symlinks: false,
330 preserve_symlinks_main: false,
331 prof_process: false,
332 cpu_prof_dir: String::new(),
333 cpu_prof_interval: 1000,
334 cpu_prof_name: String::new(),
335 cpu_prof: false,
336 experimental_network_inspection: false,
337 experimental_worker_inspection: false,
338 heap_prof_dir: String::new(),
339 heap_prof_name: String::new(),
340 heap_prof_interval: 512 * 1024,
341 heap_prof: false,
342 redirect_warnings: String::new(),
343 diagnostic_dir: String::new(),
344 env_file: String::new(),
345 optional_env_file: String::new(),
346 has_env_file_string: false,
347 test_runner: false,
348 test_runner_concurrency: 0,
349 test_runner_timeout: 0,
350 test_runner_coverage: false,
351 test_runner_force_exit: false,
352 test_coverage_branches: 0,
353 test_coverage_functions: 0,
354 test_coverage_lines: 0,
355 test_runner_module_mocks: false,
356 test_runner_update_snapshots: false,
357 test_name_pattern: Vec::new(),
358 test_reporter: Vec::new(),
359 test_reporter_destination: Vec::new(),
360 test_global_setup_path: String::new(),
361 test_only: false,
362 test_udp_no_try_send: false,
363 test_isolation: "process".to_string(),
364 test_shard: String::new(),
365 test_skip_pattern: Vec::new(),
366 coverage_include_pattern: Vec::new(),
367 coverage_exclude_pattern: Vec::new(),
368 throw_deprecation: false,
369 trace_deprecation: false,
370 trace_exit: false,
371 trace_sync_io: false,
372 trace_tls: false,
373 trace_uncaught: false,
374 trace_warnings: false,
375 trace_promises: false,
376 trace_env: false,
377 trace_env_js_stack: false,
378 trace_env_native_stack: false,
379 trace_require_module: String::new(),
380 extra_info_on_fatal_exception: true,
381 unhandled_rejections: String::new(),
382 userland_loaders: Vec::new(),
383 verify_base_objects: false,
384 watch_mode: false,
385 watch_mode_report_to_parent: false,
386 watch_mode_preserve_output: false,
387 watch_mode_kill_signal: "SIGTERM".to_string(),
388 watch_mode_paths: Vec::new(),
389 syntax_check_only: false,
390 has_eval_string: false,
391 eval_string: String::new(),
392 print_eval: false,
393 force_repl: false,
394 insecure_http_parser: false,
395 tls_min_v1_0: false,
396 tls_min_v1_1: false,
397 tls_min_v1_2: false,
398 tls_min_v1_3: false,
399 tls_max_v1_2: false,
400 tls_max_v1_3: false,
401 tls_keylog: String::new(),
402 preload_cjs_modules: Vec::new(),
403 preload_esm_modules: Vec::new(),
404 experimental_strip_types: true,
405 experimental_transform_types: false,
406 user_argv: Vec::new(),
407 report_exclude_env: false,
408 report_exclude_network: false,
409 experimental_config_file_path: String::new(),
410 experimental_default_config_file: false,
411 debug_options: DebugOptions::default(),
412 }
413 }
414}
415
416impl EnvironmentOptions {
417 pub fn check_options(&mut self, errors: &mut Vec<String>) {
418 if !self.input_type.is_empty()
419 && !matches!(
420 self.input_type.as_str(),
421 "commonjs" | "module" | "commonjs-typescript" | "module-typescript"
422 )
423 {
424 errors.push("--input-type must be \"module\", \"commonjs\", \"module-typescript\" or \"commonjs-typescript\"".to_string());
425 }
426
427 if self.syntax_check_only && self.has_eval_string {
428 errors.push("either --check or --eval can be used, not both".to_string());
429 }
430
431 if !self.unhandled_rejections.is_empty()
432 && !matches!(
433 self.unhandled_rejections.as_str(),
434 "warn-with-error-code" | "throw" | "strict" | "warn" | "none"
435 )
436 {
437 errors.push("invalid value for --unhandled-rejections".to_string());
438 }
439
440 if self.tls_min_v1_3 && self.tls_max_v1_2 {
441 errors.push(
442 "either --tls-min-v1.3 or --tls-max-v1.2 can be used, not both"
443 .to_string(),
444 );
445 }
446
447 if self.heap_snapshot_near_heap_limit < 0 {
448 errors.push(
449 "--heapsnapshot-near-heap-limit must not be negative".to_string(),
450 );
451 }
452
453 if !self.trace_require_module.is_empty()
454 && !matches!(
455 self.trace_require_module.as_str(),
456 "all" | "no-node-modules"
457 )
458 {
459 errors.push("invalid value for --trace-require-module".to_string());
460 }
461
462 if self.test_runner {
463 if self.test_isolation == "none" {
464 self.debug_options.allow_attaching_debugger = true;
465 } else if self.test_isolation != "process" {
466 errors.push("invalid value for --test-isolation".to_string());
467 }
468
469 if self.syntax_check_only {
470 errors
471 .push("either --test or --check can be used, not both".to_string());
472 }
473
474 if self.has_eval_string {
475 errors
476 .push("either --test or --eval can be used, not both".to_string());
477 }
478
479 if self.force_repl {
480 errors.push(
481 "either --test or --interactive can be used, not both".to_string(),
482 );
483 }
484
485 if !self.watch_mode_paths.is_empty() {
486 errors.push(
487 "--watch-path cannot be used in combination with --test".to_string(),
488 );
489 }
490 }
491
492 if self.watch_mode {
493 if self.syntax_check_only {
494 errors
495 .push("either --watch or --check can be used, not both".to_string());
496 } else if self.has_eval_string {
497 errors
498 .push("either --watch or --eval can be used, not both".to_string());
499 } else if self.force_repl {
500 errors.push(
501 "either --watch or --interactive can be used, not both".to_string(),
502 );
503 } else if self.test_runner_force_exit {
504 errors.push(
505 "either --watch or --test-force-exit can be used, not both"
506 .to_string(),
507 );
508 }
509
510 self.debug_options.allow_attaching_debugger = false;
511 }
512
513 if !self.cpu_prof {
515 if !self.cpu_prof_name.is_empty() {
516 errors.push("--cpu-prof-name must be used with --cpu-prof".to_string());
517 }
518 if !self.cpu_prof_dir.is_empty() {
519 errors.push("--cpu-prof-dir must be used with --cpu-prof".to_string());
520 }
521 if self.cpu_prof_interval != 1000 {
522 errors
523 .push("--cpu-prof-interval must be used with --cpu-prof".to_string());
524 }
525 }
526
527 if self.cpu_prof
528 && self.cpu_prof_dir.is_empty()
529 && !self.diagnostic_dir.is_empty()
530 {
531 self.cpu_prof_dir = self.diagnostic_dir.clone();
532 }
533
534 if !self.heap_prof {
536 if !self.heap_prof_name.is_empty() {
537 errors
538 .push("--heap-prof-name must be used with --heap-prof".to_string());
539 }
540 if !self.heap_prof_dir.is_empty() {
541 errors
542 .push("--heap-prof-dir must be used with --heap-prof".to_string());
543 }
544 if self.heap_prof_interval != 512 * 1024 {
545 errors.push(
546 "--heap-prof-interval must be used with --heap-prof".to_string(),
547 );
548 }
549 }
550
551 if self.heap_prof
552 && self.heap_prof_dir.is_empty()
553 && !self.diagnostic_dir.is_empty()
554 {
555 self.heap_prof_dir = self.diagnostic_dir.clone();
556 }
557
558 self.debug_options.check_options(errors);
559 }
560}
561
562#[derive(Debug, Clone)]
563pub struct PerIsolateOptions {
564 pub per_env: EnvironmentOptions,
565 pub track_heap_objects: bool,
566 pub report_uncaught_exception: bool,
567 pub report_on_signal: bool,
568 pub experimental_shadow_realm: bool,
569 pub stack_trace_limit: i64,
570 pub report_signal: String,
571 pub build_snapshot: bool,
572 pub build_snapshot_config: String,
573}
574
575impl Default for PerIsolateOptions {
576 fn default() -> Self {
577 Self {
578 per_env: EnvironmentOptions::default(),
579 track_heap_objects: false,
580 report_uncaught_exception: false,
581 report_on_signal: false,
582 experimental_shadow_realm: false,
583 stack_trace_limit: 10,
584 report_signal: "SIGUSR2".to_string(),
585 build_snapshot: false,
586 build_snapshot_config: String::new(),
587 }
588 }
589}
590
591impl PerIsolateOptions {
592 pub fn check_options(&mut self, errors: &mut Vec<String>) {
593 self.per_env.check_options(errors);
594 }
595}
596
597#[derive(Debug, Clone)]
598pub struct PerProcessOptions {
599 pub per_isolate: PerIsolateOptions,
600 pub title: String,
601 pub trace_event_categories: String,
602 pub trace_event_file_pattern: String,
603 pub v8_thread_pool_size: i64,
604 pub zero_fill_all_buffers: bool,
605 pub debug_arraybuffer_allocations: bool,
606 pub disable_proto: String,
607 pub node_snapshot: bool,
608 pub snapshot_blob: String,
609 pub security_reverts: Vec<String>,
610 pub print_bash_completion: bool,
611 pub print_help: bool,
612 pub print_v8_help: bool,
613 pub print_version: bool,
614 pub experimental_sea_config: String,
615 pub run: String,
616 pub icu_data_dir: String,
617 pub openssl_config: String,
618 pub tls_cipher_list: String,
619 pub secure_heap: i64,
620 pub secure_heap_min: i64,
621 pub ssl_openssl_cert_store: bool,
622 pub use_openssl_ca: bool,
623 pub use_system_ca: bool,
624 pub use_bundled_ca: bool,
625 pub enable_fips_crypto: bool,
626 pub force_fips_crypto: bool,
627 pub openssl_legacy_provider: bool,
628 pub openssl_shared_config: bool,
629 pub disable_wasm_trap_handler: bool,
630 pub report_on_fatalerror: bool,
631 pub report_compact: bool,
632 pub report_directory: String,
633 pub report_filename: String,
634 pub use_largepages: String,
635 pub trace_sigint: bool,
636}
637
638impl Default for PerProcessOptions {
639 fn default() -> Self {
640 Self {
641 per_isolate: PerIsolateOptions::default(),
642 title: String::new(),
643 trace_event_categories: String::new(),
644 trace_event_file_pattern: "node_trace.${rotation}.log".to_string(),
645 v8_thread_pool_size: 4,
646 zero_fill_all_buffers: false,
647 debug_arraybuffer_allocations: false,
648 disable_proto: String::new(),
649 node_snapshot: true,
650 snapshot_blob: String::new(),
651 security_reverts: Vec::new(),
652 print_bash_completion: false,
653 print_help: false,
654 print_v8_help: false,
655 print_version: false,
656 experimental_sea_config: String::new(),
657 run: String::new(),
658 icu_data_dir: String::new(),
659 openssl_config: String::new(),
660 tls_cipher_list:
661 "ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS"
662 .to_string(),
663 secure_heap: 0,
664 secure_heap_min: 2,
665 ssl_openssl_cert_store: false,
666 use_openssl_ca: false,
667 use_system_ca: false,
668 use_bundled_ca: false,
669 enable_fips_crypto: false,
670 force_fips_crypto: false,
671 openssl_legacy_provider: false,
672 openssl_shared_config: false,
673 disable_wasm_trap_handler: false,
674 report_on_fatalerror: false,
675 report_compact: false,
676 report_directory: String::new(),
677 report_filename: String::new(),
678 use_largepages: "off".to_string(),
679 trace_sigint: false,
680 }
681 }
682}
683
684impl PerProcessOptions {
685 pub fn check_options(&mut self, errors: &mut Vec<String>) {
686 if self.use_openssl_ca && self.use_bundled_ca {
687 errors.push(
688 "either --use-openssl-ca or --use-bundled-ca can be used, not both"
689 .to_string(),
690 );
691 }
692
693 if self.secure_heap >= 2 {
694 if (self.secure_heap & (self.secure_heap - 1)) != 0 {
695 errors.push("--secure-heap must be a power of 2".to_string());
696 }
697 self.secure_heap_min = self
698 .secure_heap
699 .min(self.secure_heap_min)
700 .min(i32::MAX as i64);
701 self.secure_heap_min = self.secure_heap_min.max(2);
702 if (self.secure_heap_min & (self.secure_heap_min - 1)) != 0 {
703 errors.push("--secure-heap-min must be a power of 2".to_string());
704 }
705 }
706
707 if !matches!(self.use_largepages.as_str(), "off" | "on" | "silent") {
708 errors.push("invalid value for --use-largepages".to_string());
709 }
710
711 self.per_isolate.check_options(errors);
712 }
713}
714
715fn remove_brackets(host: &str) -> String {
716 if !host.is_empty() && host.starts_with('[') && host.ends_with(']') {
717 host[1..host.len() - 1].to_string()
718 } else {
719 host.to_string()
720 }
721}
722
723fn parse_and_validate_port(port_str: &str, errors: &mut Vec<String>) -> u16 {
724 match port_str.parse::<u16>() {
725 Ok(port) => {
726 if port != 0 && port < 1024 {
727 errors.push("must be 0 or in range 1024 to 65535.".to_string());
728 0
729 } else {
730 port
731 }
732 }
733 Err(_) => {
734 errors.push("must be 0 or in range 1024 to 65535.".to_string());
735 0
736 }
737 }
738}
739
740fn split_host_port(arg: &str, errors: &mut Vec<String>) -> HostPort {
741 let host = remove_brackets(arg);
742 if host.len() < arg.len() {
743 return HostPort::new(host, 9229);
744 }
745
746 if let Some(colon_index) = arg.rfind(':') {
747 let host_part = remove_brackets(&arg[..colon_index]);
748 let port_part = &arg[colon_index + 1..];
749 HostPort::new(host_part, parse_and_validate_port(port_part, errors))
750 } else {
751 if arg.chars().all(|c| c.is_ascii_digit()) {
753 HostPort::new(String::new(), parse_and_validate_port(arg, errors))
754 } else {
755 HostPort::new(arg.to_string(), 9229)
756 }
757 }
758}
759
760#[derive(Debug, Clone)]
761#[allow(dead_code)]
762struct OptionInfo {
763 option_type: OptionType,
764 env_setting: OptionEnvvarSettings,
765 help_text: String,
766 default_is_true: bool,
767}
768
769pub struct OptionsParser {
770 options: HashMap<String, OptionInfo>,
771 aliases: HashMap<String, Vec<String>>,
772 implications: HashMap<String, Vec<String>>,
773}
774
775impl Default for OptionsParser {
776 fn default() -> Self {
777 Self::new()
778 }
779}
780
781impl OptionsParser {
782 pub fn new() -> Self {
783 let mut parser = Self {
784 options: HashMap::new(),
785 aliases: HashMap::new(),
786 implications: HashMap::new(),
787 };
788 parser.setup_options();
789 parser
790 }
791
792 fn add_option(
793 &mut self,
794 name: &str,
795 help_text: &str,
796 option_type: OptionType,
797 env_setting: OptionEnvvarSettings,
798 default_is_true: bool,
799 ) {
800 self.options.insert(
801 name.to_string(),
802 OptionInfo {
803 option_type,
804 env_setting,
805 help_text: help_text.to_string(),
806 default_is_true,
807 },
808 );
809 }
810
811 fn add_alias(&mut self, from: &str, to: Vec<&str>) {
812 self
813 .aliases
814 .insert(from.to_string(), to.iter().map(|s| s.to_string()).collect());
815 }
816
817 fn add_implication(&mut self, from: &str, to: Vec<&str>) {
818 self
819 .implications
820 .insert(from.to_string(), to.iter().map(|s| s.to_string()).collect());
821 }
822
823 fn setup_options(&mut self) {
824 self.add_option(
826 "--inspect-port",
827 "set host:port for inspector",
828 OptionType::HostPort,
829 OptionEnvvarSettings::AllowedInEnvvar,
830 false,
831 );
832 self.add_option(
833 "--inspect",
834 "activate inspector on host:port (default: 127.0.0.1:9229)",
835 OptionType::Boolean,
836 OptionEnvvarSettings::AllowedInEnvvar,
837 false,
838 );
839 self.add_option(
840 "--debug",
841 "",
842 OptionType::Boolean,
843 OptionEnvvarSettings::DisallowedInEnvvar,
844 false,
845 );
846 self.add_option(
847 "--debug-brk",
848 "",
849 OptionType::Boolean,
850 OptionEnvvarSettings::DisallowedInEnvvar,
851 false,
852 );
853 self.add_option(
854 "--inspect-brk",
855 "activate inspector on host:port and break at start of user script",
856 OptionType::Boolean,
857 OptionEnvvarSettings::AllowedInEnvvar,
858 false,
859 );
860 self.add_option(
861 "--inspect-brk-node",
862 "",
863 OptionType::Boolean,
864 OptionEnvvarSettings::DisallowedInEnvvar,
865 false,
866 );
867 self.add_option(
868 "--inspect-wait",
869 "activate inspector on host:port and wait for debugger to be attached",
870 OptionType::Boolean,
871 OptionEnvvarSettings::AllowedInEnvvar,
872 false,
873 );
874 self.add_option(
875 "--inspect-publish-uid",
876 "comma separated list of destinations for inspector uid (default: stderr,http)",
877 OptionType::String,
878 OptionEnvvarSettings::AllowedInEnvvar,
879 false,
880 );
881
882 self.add_option(
884 "--conditions",
885 "additional user conditions for conditional exports and imports",
886 OptionType::StringList,
887 OptionEnvvarSettings::AllowedInEnvvar,
888 false,
889 );
890 self.add_option("--experimental-detect-module", "when ambiguous modules fail to evaluate because they contain ES module syntax, try again to evaluate them as ES modules", OptionType::Boolean, OptionEnvvarSettings::AllowedInEnvvar, true);
891 self.add_option("--experimental-print-required-tla", "Print pending top-level await. If --experimental-require-module is true, evaluate asynchronous graphs loaded by `require()` but do not run the microtasks, in order to to find and print top-level await in the graph", OptionType::Boolean, OptionEnvvarSettings::AllowedInEnvvar, false);
892 self.add_option(
893 "--experimental-require-module",
894 "Allow loading synchronous ES Modules in require().",
895 OptionType::Boolean,
896 OptionEnvvarSettings::AllowedInEnvvar,
897 true,
898 );
899 self.add_option(
900 "--diagnostic-dir",
901 "set dir for all output files (default: current working directory)",
902 OptionType::String,
903 OptionEnvvarSettings::AllowedInEnvvar,
904 false,
905 );
906 self.add_option(
907 "--disable-sigusr1",
908 "Disable inspector thread to be listening for SIGUSR1 signal",
909 OptionType::Boolean,
910 OptionEnvvarSettings::AllowedInEnvvar,
911 false,
912 );
913 self.add_option("--dns-result-order", "set default value of verbatim in dns.lookup. Options are 'ipv4first' (IPv4 addresses are placed before IPv6 addresses) 'ipv6first' (IPv6 addresses are placed before IPv4 addresses) 'verbatim' (addresses are in the order the DNS resolver returned)", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
914 self.add_option(
915 "--network-family-autoselection",
916 "Disable network address family autodetection algorithm",
917 OptionType::Boolean,
918 OptionEnvvarSettings::AllowedInEnvvar,
919 true,
920 );
921 self.add_option(
922 "--network-family-autoselection-attempt-timeout",
923 "Sets the default value for the network family autoselection attempt timeout.",
924 OptionType::UInteger,
925 OptionEnvvarSettings::AllowedInEnvvar,
926 false,
927 );
928 self.add_option(
929 "--enable-source-maps",
930 "Source Map V3 support for stack traces",
931 OptionType::Boolean,
932 OptionEnvvarSettings::AllowedInEnvvar,
933 false,
934 );
935 self.add_option(
936 "--entry-url",
937 "Treat the entrypoint as a URL",
938 OptionType::Boolean,
939 OptionEnvvarSettings::AllowedInEnvvar,
940 false,
941 );
942 self.add_option(
943 "--experimental-addon-modules",
944 "experimental import support for addons",
945 OptionType::Boolean,
946 OptionEnvvarSettings::AllowedInEnvvar,
947 false,
948 );
949 self.add_option(
950 "--experimental-abortcontroller",
951 "",
952 OptionType::NoOp,
953 OptionEnvvarSettings::AllowedInEnvvar,
954 false,
955 );
956 self.add_option(
957 "--experimental-eventsource",
958 "experimental EventSource API",
959 OptionType::Boolean,
960 OptionEnvvarSettings::AllowedInEnvvar,
961 false,
962 );
963 self.add_option(
964 "--experimental-fetch",
965 "",
966 OptionType::NoOp,
967 OptionEnvvarSettings::AllowedInEnvvar,
968 false,
969 );
970 self.add_option(
971 "--experimental-websocket",
972 "experimental WebSocket API",
973 OptionType::Boolean,
974 OptionEnvvarSettings::AllowedInEnvvar,
975 true,
976 );
977 self.add_option(
978 "--experimental-global-customevent",
979 "",
980 OptionType::NoOp,
981 OptionEnvvarSettings::AllowedInEnvvar,
982 false,
983 );
984 self.add_option(
985 "--experimental-sqlite",
986 "experimental node:sqlite module",
987 OptionType::Boolean,
988 OptionEnvvarSettings::AllowedInEnvvar,
989 true,
990 );
991 self.add_option(
992 "--experimental-quic",
993 "",
994 OptionType::Boolean,
995 OptionEnvvarSettings::AllowedInEnvvar,
996 false,
997 );
998 self.add_option(
999 "--experimental-webstorage",
1000 "experimental Web Storage API",
1001 OptionType::Boolean,
1002 OptionEnvvarSettings::AllowedInEnvvar,
1003 false,
1004 );
1005 self.add_option(
1006 "--localstorage-file",
1007 "file used to persist localStorage data",
1008 OptionType::String,
1009 OptionEnvvarSettings::AllowedInEnvvar,
1010 false,
1011 );
1012 self.add_option(
1013 "--experimental-global-navigator",
1014 "expose experimental Navigator API on the global scope",
1015 OptionType::Boolean,
1016 OptionEnvvarSettings::AllowedInEnvvar,
1017 true,
1018 );
1019 self.add_option(
1020 "--experimental-global-webcrypto",
1021 "",
1022 OptionType::NoOp,
1023 OptionEnvvarSettings::AllowedInEnvvar,
1024 false,
1025 );
1026 self.add_option(
1027 "--experimental-json-modules",
1028 "",
1029 OptionType::NoOp,
1030 OptionEnvvarSettings::AllowedInEnvvar,
1031 false,
1032 );
1033 self.add_option(
1034 "--experimental-loader",
1035 "use the specified module as a custom loader",
1036 OptionType::StringList,
1037 OptionEnvvarSettings::AllowedInEnvvar,
1038 false,
1039 );
1040 self.add_option(
1041 "--experimental-modules",
1042 "",
1043 OptionType::NoOp,
1044 OptionEnvvarSettings::AllowedInEnvvar,
1045 false,
1046 );
1047 self.add_option(
1048 "--experimental-wasm-modules",
1049 "experimental ES Module support for webassembly modules",
1050 OptionType::Boolean,
1051 OptionEnvvarSettings::AllowedInEnvvar,
1052 false,
1053 );
1054 self.add_option(
1055 "--experimental-import-meta-resolve",
1056 "experimental ES Module import.meta.resolve() parentURL support",
1057 OptionType::Boolean,
1058 OptionEnvvarSettings::AllowedInEnvvar,
1059 false,
1060 );
1061 self.add_option(
1062 "--permission",
1063 "enable the permission system",
1064 OptionType::Boolean,
1065 OptionEnvvarSettings::AllowedInEnvvar,
1066 false,
1067 );
1068 self.add_option(
1069 "--allow-fs-read",
1070 "allow permissions to read the filesystem",
1071 OptionType::StringList,
1072 OptionEnvvarSettings::AllowedInEnvvar,
1073 false,
1074 );
1075 self.add_option(
1076 "--allow-fs-write",
1077 "allow permissions to write in the filesystem",
1078 OptionType::StringList,
1079 OptionEnvvarSettings::AllowedInEnvvar,
1080 false,
1081 );
1082 self.add_option(
1083 "--allow-addons",
1084 "allow use of addons when any permissions are set",
1085 OptionType::Boolean,
1086 OptionEnvvarSettings::AllowedInEnvvar,
1087 false,
1088 );
1089 self.add_option(
1090 "--allow-child-process",
1091 "allow use of child process when any permissions are set",
1092 OptionType::Boolean,
1093 OptionEnvvarSettings::AllowedInEnvvar,
1094 false,
1095 );
1096 self.add_option(
1097 "--allow-net",
1098 "allow use of network when any permissions are set",
1099 OptionType::StringList,
1100 OptionEnvvarSettings::AllowedInEnvvar,
1101 false,
1102 );
1103 self.add_option(
1104 "--allow-wasi",
1105 "allow wasi when any permissions are set",
1106 OptionType::Boolean,
1107 OptionEnvvarSettings::AllowedInEnvvar,
1108 false,
1109 );
1110 self.add_option(
1111 "--allow-worker",
1112 "allow worker threads when any permissions are set",
1113 OptionType::Boolean,
1114 OptionEnvvarSettings::AllowedInEnvvar,
1115 false,
1116 );
1117 self.add_option(
1118 "--experimental-repl-await",
1119 "experimental await keyword support in REPL",
1120 OptionType::Boolean,
1121 OptionEnvvarSettings::AllowedInEnvvar,
1122 true,
1123 );
1124 self.add_option(
1125 "--experimental-vm-modules",
1126 "experimental ES Module support in vm module",
1127 OptionType::Boolean,
1128 OptionEnvvarSettings::AllowedInEnvvar,
1129 false,
1130 );
1131 self.add_option(
1132 "--experimental-worker",
1133 "",
1134 OptionType::NoOp,
1135 OptionEnvvarSettings::AllowedInEnvvar,
1136 false,
1137 );
1138 self.add_option(
1139 "--experimental-report",
1140 "",
1141 OptionType::NoOp,
1142 OptionEnvvarSettings::AllowedInEnvvar,
1143 false,
1144 );
1145 self.add_option(
1146 "--experimental-wasi-unstable-preview1",
1147 "",
1148 OptionType::NoOp,
1149 OptionEnvvarSettings::AllowedInEnvvar,
1150 false,
1151 );
1152 self.add_option(
1153 "--expose-gc",
1154 "expose gc extension",
1155 OptionType::V8Option,
1156 OptionEnvvarSettings::AllowedInEnvvar,
1157 false,
1158 );
1159 self.add_option(
1160 "--async-context-frame",
1161 "Improve AsyncLocalStorage performance with AsyncContextFrame",
1162 OptionType::Boolean,
1163 OptionEnvvarSettings::AllowedInEnvvar,
1164 true,
1165 );
1166 self.add_option(
1167 "--expose-internals",
1168 "",
1169 OptionType::Boolean,
1170 OptionEnvvarSettings::DisallowedInEnvvar,
1171 false,
1172 );
1173 self.add_option(
1174 "--frozen-intrinsics",
1175 "experimental frozen intrinsics support",
1176 OptionType::Boolean,
1177 OptionEnvvarSettings::AllowedInEnvvar,
1178 false,
1179 );
1180 self.add_option(
1181 "--heapsnapshot-signal",
1182 "Generate heap snapshot on specified signal",
1183 OptionType::String,
1184 OptionEnvvarSettings::AllowedInEnvvar,
1185 false,
1186 );
1187 self.add_option("--heapsnapshot-near-heap-limit", "Generate heap snapshots whenever V8 is approaching the heap limit. No more than the specified number of heap snapshots will be generated.", OptionType::Integer, OptionEnvvarSettings::AllowedInEnvvar, false);
1188 self.add_option(
1189 "--http-parser",
1190 "",
1191 OptionType::NoOp,
1192 OptionEnvvarSettings::AllowedInEnvvar,
1193 false,
1194 );
1195 self.add_option(
1196 "--insecure-http-parser",
1197 "use an insecure HTTP parser that accepts invalid HTTP headers",
1198 OptionType::Boolean,
1199 OptionEnvvarSettings::AllowedInEnvvar,
1200 false,
1201 );
1202 self.add_option(
1203 "--input-type",
1204 "set module type for string input",
1205 OptionType::String,
1206 OptionEnvvarSettings::AllowedInEnvvar,
1207 false,
1208 );
1209 self.add_option(
1210 "--experimental-specifier-resolution",
1211 "",
1212 OptionType::NoOp,
1213 OptionEnvvarSettings::AllowedInEnvvar,
1214 false,
1215 );
1216 self.add_option(
1217 "--deprecation",
1218 "silence deprecation warnings",
1219 OptionType::Boolean,
1220 OptionEnvvarSettings::AllowedInEnvvar,
1221 true,
1222 );
1223 self.add_option(
1224 "--force-async-hooks-checks",
1225 "disable checks for async_hooks",
1226 OptionType::Boolean,
1227 OptionEnvvarSettings::AllowedInEnvvar,
1228 true,
1229 );
1230 self.add_option(
1231 "--force-node-api-uncaught-exceptions-policy",
1232 "enforces 'uncaughtException' event on Node API asynchronous callbacks",
1233 OptionType::Boolean,
1234 OptionEnvvarSettings::AllowedInEnvvar,
1235 false,
1236 );
1237 self.add_option(
1238 "--addons",
1239 "disable loading native addons",
1240 OptionType::Boolean,
1241 OptionEnvvarSettings::AllowedInEnvvar,
1242 true,
1243 );
1244 self.add_option(
1245 "--global-search-paths",
1246 "disable global module search paths",
1247 OptionType::Boolean,
1248 OptionEnvvarSettings::AllowedInEnvvar,
1249 true,
1250 );
1251 self.add_option(
1252 "--warnings",
1253 "silence all process warnings",
1254 OptionType::Boolean,
1255 OptionEnvvarSettings::AllowedInEnvvar,
1256 true,
1257 );
1258 self.add_option(
1259 "--disable-warning",
1260 "silence specific process warnings",
1261 OptionType::StringList,
1262 OptionEnvvarSettings::AllowedInEnvvar,
1263 false,
1264 );
1265 self.add_option(
1266 "--force-context-aware",
1267 "disable loading non-context-aware addons",
1268 OptionType::Boolean,
1269 OptionEnvvarSettings::AllowedInEnvvar,
1270 false,
1271 );
1272 self.add_option(
1273 "--pending-deprecation",
1274 "emit pending deprecation warnings",
1275 OptionType::Boolean,
1276 OptionEnvvarSettings::AllowedInEnvvar,
1277 false,
1278 );
1279 self.add_option(
1280 "--preserve-symlinks",
1281 "preserve symbolic links when resolving",
1282 OptionType::Boolean,
1283 OptionEnvvarSettings::AllowedInEnvvar,
1284 false,
1285 );
1286 self.add_option(
1287 "--preserve-symlinks-main",
1288 "preserve symbolic links when resolving the main module",
1289 OptionType::Boolean,
1290 OptionEnvvarSettings::AllowedInEnvvar,
1291 false,
1292 );
1293 self.add_option(
1294 "--prof",
1295 "Generate V8 profiler output.",
1296 OptionType::V8Option,
1297 OptionEnvvarSettings::DisallowedInEnvvar,
1298 false,
1299 );
1300 self.add_option(
1301 "--prof-process",
1302 "process V8 profiler output generated using --prof",
1303 OptionType::Boolean,
1304 OptionEnvvarSettings::DisallowedInEnvvar,
1305 false,
1306 );
1307 self.add_option("--cpu-prof", "Start the V8 CPU profiler on start up, and write the CPU profile to disk before exit. If --cpu-prof-dir is not specified, write the profile to the current working directory.", OptionType::Boolean, OptionEnvvarSettings::AllowedInEnvvar, false);
1308 self.add_option(
1309 "--cpu-prof-name",
1310 "specified file name of the V8 CPU profile generated with --cpu-prof",
1311 OptionType::String,
1312 OptionEnvvarSettings::AllowedInEnvvar,
1313 false,
1314 );
1315 self.add_option("--cpu-prof-interval", "specified sampling interval in microseconds for the V8 CPU profile generated with --cpu-prof. (default: 1000)", OptionType::UInteger, OptionEnvvarSettings::AllowedInEnvvar, false);
1316 self.add_option("--cpu-prof-dir", "Directory where the V8 profiles generated by --cpu-prof will be placed. Does not affect --prof.", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1317 self.add_option(
1318 "--experimental-network-inspection",
1319 "experimental network inspection support",
1320 OptionType::Boolean,
1321 OptionEnvvarSettings::DisallowedInEnvvar,
1322 false,
1323 );
1324 self.add_option(
1325 "--experimental-worker-inspection",
1326 "experimental worker inspection support",
1327 OptionType::Boolean,
1328 OptionEnvvarSettings::DisallowedInEnvvar,
1329 false,
1330 );
1331 self.add_option("--heap-prof", "Start the V8 heap profiler on start up, and write the heap profile to disk before exit. If --heap-prof-dir is not specified, write the profile to the current working directory.", OptionType::Boolean, OptionEnvvarSettings::AllowedInEnvvar, false);
1332 self.add_option(
1333 "--heap-prof-name",
1334 "specified file name of the V8 heap profile generated with --heap-prof",
1335 OptionType::String,
1336 OptionEnvvarSettings::AllowedInEnvvar,
1337 false,
1338 );
1339 self.add_option(
1340 "--heap-prof-dir",
1341 "Directory where the V8 heap profiles generated by --heap-prof will be placed.",
1342 OptionType::String,
1343 OptionEnvvarSettings::AllowedInEnvvar,
1344 false,
1345 );
1346 self.add_option("--heap-prof-interval", "specified sampling interval in bytes for the V8 heap profile generated with --heap-prof. (default: 512 * 1024)", OptionType::UInteger, OptionEnvvarSettings::AllowedInEnvvar, false);
1347 self.add_option(
1348 "--max-http-header-size",
1349 "set the maximum size of HTTP headers (default: 16384 (16KB))",
1350 OptionType::UInteger,
1351 OptionEnvvarSettings::AllowedInEnvvar,
1352 false,
1353 );
1354 self.add_option(
1355 "--redirect-warnings",
1356 "write warnings to file instead of stderr",
1357 OptionType::String,
1358 OptionEnvvarSettings::AllowedInEnvvar,
1359 false,
1360 );
1361 self.add_option(
1362 "[has_env_file_string]",
1363 "",
1364 OptionType::Boolean,
1365 OptionEnvvarSettings::DisallowedInEnvvar,
1366 false,
1367 );
1368 self.add_option(
1369 "--env-file",
1370 "set environment variables from supplied file",
1371 OptionType::String,
1372 OptionEnvvarSettings::DisallowedInEnvvar,
1373 false,
1374 );
1375 self.add_option(
1376 "--env-file-if-exists",
1377 "set environment variables from supplied file",
1378 OptionType::String,
1379 OptionEnvvarSettings::DisallowedInEnvvar,
1380 false,
1381 );
1382 self.add_option(
1383 "--experimental-config-file",
1384 "set config file from supplied file",
1385 OptionType::String,
1386 OptionEnvvarSettings::DisallowedInEnvvar,
1387 false,
1388 );
1389 self.add_option(
1390 "--experimental-default-config-file",
1391 "set config file from default config file",
1392 OptionType::Boolean,
1393 OptionEnvvarSettings::DisallowedInEnvvar,
1394 false,
1395 );
1396 self.add_option(
1397 "--test",
1398 "launch test runner on startup",
1399 OptionType::Boolean,
1400 OptionEnvvarSettings::DisallowedInEnvvar,
1401 false,
1402 );
1403 self.add_option(
1404 "--test-concurrency",
1405 "specify test runner concurrency",
1406 OptionType::UInteger,
1407 OptionEnvvarSettings::DisallowedInEnvvar,
1408 false,
1409 );
1410 self.add_option(
1411 "--test-force-exit",
1412 "force test runner to exit upon completion",
1413 OptionType::Boolean,
1414 OptionEnvvarSettings::DisallowedInEnvvar,
1415 false,
1416 );
1417 self.add_option(
1418 "--test-timeout",
1419 "specify test runner timeout",
1420 OptionType::UInteger,
1421 OptionEnvvarSettings::DisallowedInEnvvar,
1422 false,
1423 );
1424 self.add_option(
1425 "--test-update-snapshots",
1426 "regenerate test snapshots",
1427 OptionType::Boolean,
1428 OptionEnvvarSettings::DisallowedInEnvvar,
1429 false,
1430 );
1431 self.add_option(
1432 "--experimental-test-coverage",
1433 "enable code coverage in the test runner",
1434 OptionType::Boolean,
1435 OptionEnvvarSettings::DisallowedInEnvvar,
1436 false,
1437 );
1438 self.add_option(
1439 "--test-coverage-branches",
1440 "the branch coverage minimum threshold",
1441 OptionType::UInteger,
1442 OptionEnvvarSettings::AllowedInEnvvar,
1443 false,
1444 );
1445 self.add_option(
1446 "--test-coverage-functions",
1447 "the function coverage minimum threshold",
1448 OptionType::UInteger,
1449 OptionEnvvarSettings::AllowedInEnvvar,
1450 false,
1451 );
1452 self.add_option(
1453 "--test-coverage-lines",
1454 "the line coverage minimum threshold",
1455 OptionType::UInteger,
1456 OptionEnvvarSettings::AllowedInEnvvar,
1457 false,
1458 );
1459 self.add_option(
1460 "--test-isolation",
1461 "configures the type of test isolation used in the test runner",
1462 OptionType::String,
1463 OptionEnvvarSettings::AllowedInEnvvar,
1464 false,
1465 );
1466 self.add_option(
1467 "--experimental-test-module-mocks",
1468 "enable module mocking in the test runner",
1469 OptionType::Boolean,
1470 OptionEnvvarSettings::DisallowedInEnvvar,
1471 false,
1472 );
1473 self.add_option(
1474 "--experimental-test-snapshots",
1475 "",
1476 OptionType::NoOp,
1477 OptionEnvvarSettings::DisallowedInEnvvar,
1478 false,
1479 );
1480 self.add_option(
1481 "--test-name-pattern",
1482 "run tests whose name matches this regular expression",
1483 OptionType::StringList,
1484 OptionEnvvarSettings::AllowedInEnvvar,
1485 false,
1486 );
1487 self.add_option(
1488 "--test-reporter",
1489 "report test output using the given reporter",
1490 OptionType::StringList,
1491 OptionEnvvarSettings::AllowedInEnvvar,
1492 false,
1493 );
1494 self.add_option(
1495 "--test-reporter-destination",
1496 "report given reporter to the given destination",
1497 OptionType::StringList,
1498 OptionEnvvarSettings::AllowedInEnvvar,
1499 false,
1500 );
1501 self.add_option(
1502 "--test-only",
1503 "run tests with 'only' option set",
1504 OptionType::Boolean,
1505 OptionEnvvarSettings::AllowedInEnvvar,
1506 false,
1507 );
1508 self.add_option(
1509 "--test-shard",
1510 "run test at specific shard",
1511 OptionType::String,
1512 OptionEnvvarSettings::AllowedInEnvvar,
1513 false,
1514 );
1515 self.add_option(
1516 "--test-skip-pattern",
1517 "run tests whose name do not match this regular expression",
1518 OptionType::StringList,
1519 OptionEnvvarSettings::AllowedInEnvvar,
1520 false,
1521 );
1522 self.add_option(
1523 "--test-coverage-include",
1524 "include files in coverage report that match this glob pattern",
1525 OptionType::StringList,
1526 OptionEnvvarSettings::AllowedInEnvvar,
1527 false,
1528 );
1529 self.add_option(
1530 "--test-coverage-exclude",
1531 "exclude files from coverage report that match this glob pattern",
1532 OptionType::StringList,
1533 OptionEnvvarSettings::AllowedInEnvvar,
1534 false,
1535 );
1536 self.add_option(
1537 "--test-global-setup",
1538 "specifies the path to the global setup file",
1539 OptionType::String,
1540 OptionEnvvarSettings::AllowedInEnvvar,
1541 false,
1542 );
1543 self.add_option(
1544 "--test-udp-no-try-send",
1545 "",
1546 OptionType::Boolean,
1547 OptionEnvvarSettings::DisallowedInEnvvar,
1548 false,
1549 );
1550 self.add_option(
1551 "--throw-deprecation",
1552 "throw an exception on deprecations",
1553 OptionType::Boolean,
1554 OptionEnvvarSettings::AllowedInEnvvar,
1555 false,
1556 );
1557 self.add_option(
1558 "--trace-deprecation",
1559 "show stack traces on deprecations",
1560 OptionType::Boolean,
1561 OptionEnvvarSettings::AllowedInEnvvar,
1562 false,
1563 );
1564 self.add_option(
1565 "--trace-exit",
1566 "show stack trace when an environment exits",
1567 OptionType::Boolean,
1568 OptionEnvvarSettings::AllowedInEnvvar,
1569 false,
1570 );
1571 self.add_option(
1572 "--trace-sync-io",
1573 "show stack trace when use of sync IO is detected after the first tick",
1574 OptionType::Boolean,
1575 OptionEnvvarSettings::AllowedInEnvvar,
1576 false,
1577 );
1578 self.add_option(
1579 "--trace-tls",
1580 "prints TLS packet trace information to stderr",
1581 OptionType::Boolean,
1582 OptionEnvvarSettings::AllowedInEnvvar,
1583 false,
1584 );
1585 self.add_option(
1586 "--trace-uncaught",
1587 "show stack traces for the `throw` behind uncaught exceptions",
1588 OptionType::Boolean,
1589 OptionEnvvarSettings::AllowedInEnvvar,
1590 false,
1591 );
1592 self.add_option(
1593 "--trace-warnings",
1594 "show stack traces on process warnings",
1595 OptionType::Boolean,
1596 OptionEnvvarSettings::AllowedInEnvvar,
1597 false,
1598 );
1599 self.add_option(
1600 "--trace-promises",
1601 "show stack traces on promise initialization and resolution",
1602 OptionType::Boolean,
1603 OptionEnvvarSettings::AllowedInEnvvar,
1604 false,
1605 );
1606 self.add_option(
1607 "--trace-env",
1608 "Print accesses to the environment variables",
1609 OptionType::Boolean,
1610 OptionEnvvarSettings::AllowedInEnvvar,
1611 false,
1612 );
1613 self.add_option(
1614 "--trace-env-js-stack",
1615 "Print accesses to the environment variables and the JavaScript stack trace",
1616 OptionType::Boolean,
1617 OptionEnvvarSettings::AllowedInEnvvar,
1618 false,
1619 );
1620 self.add_option(
1621 "--trace-env-native-stack",
1622 "Print accesses to the environment variables and the native stack trace",
1623 OptionType::Boolean,
1624 OptionEnvvarSettings::AllowedInEnvvar,
1625 false,
1626 );
1627 self.add_option("--trace-require-module", "Print access to require(esm). Options are 'all' (print all usage) and 'no-node-modules' (excluding usage from the node_modules folder)", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1628 self.add_option(
1629 "--extra-info-on-fatal-exception",
1630 "hide extra information on fatal exception that causes exit",
1631 OptionType::Boolean,
1632 OptionEnvvarSettings::AllowedInEnvvar,
1633 true,
1634 );
1635 self.add_option("--unhandled-rejections", "define unhandled rejections behavior. Options are 'strict' (always raise an error), 'throw' (raise an error unless 'unhandledRejection' hook is set), 'warn' (log a warning), 'none' (silence warnings), 'warn-with-error-code' (log a warning and set exit code 1 unless 'unhandledRejection' hook is set). (default: throw)", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1636 self.add_option(
1637 "--verify-base-objects",
1638 "",
1639 OptionType::Boolean,
1640 OptionEnvvarSettings::AllowedInEnvvar,
1641 false,
1642 );
1643 self.add_option(
1644 "--watch",
1645 "run in watch mode",
1646 OptionType::Boolean,
1647 OptionEnvvarSettings::AllowedInEnvvar,
1648 false,
1649 );
1650 self.add_option(
1651 "--watch-path",
1652 "path to watch",
1653 OptionType::StringList,
1654 OptionEnvvarSettings::AllowedInEnvvar,
1655 false,
1656 );
1657 self.add_option(
1658 "--watch-kill-signal",
1659 "kill signal to send to the process on watch mode restarts (default: SIGTERM)",
1660 OptionType::String,
1661 OptionEnvvarSettings::AllowedInEnvvar,
1662 false,
1663 );
1664 self.add_option(
1665 "--watch-preserve-output",
1666 "preserve outputs on watch mode restart",
1667 OptionType::Boolean,
1668 OptionEnvvarSettings::AllowedInEnvvar,
1669 false,
1670 );
1671 self.add_option(
1672 "--check",
1673 "syntax check script without executing",
1674 OptionType::Boolean,
1675 OptionEnvvarSettings::DisallowedInEnvvar,
1676 false,
1677 );
1678 self.add_option(
1679 "[has_eval_string]",
1680 "",
1681 OptionType::Boolean,
1682 OptionEnvvarSettings::DisallowedInEnvvar,
1683 false,
1684 );
1685 self.add_option(
1686 "--eval",
1687 "evaluate script",
1688 OptionType::String,
1689 OptionEnvvarSettings::DisallowedInEnvvar,
1690 false,
1691 );
1692 self.add_option(
1693 "--print",
1694 "evaluate script and print result",
1695 OptionType::Boolean,
1696 OptionEnvvarSettings::DisallowedInEnvvar,
1697 false,
1698 );
1699 self.add_option(
1700 "--require",
1701 "CommonJS module to preload (option can be repeated)",
1702 OptionType::StringList,
1703 OptionEnvvarSettings::AllowedInEnvvar,
1704 false,
1705 );
1706 self.add_option(
1707 "--import",
1708 "ES module to preload (option can be repeated)",
1709 OptionType::StringList,
1710 OptionEnvvarSettings::AllowedInEnvvar,
1711 false,
1712 );
1713 self.add_option(
1714 "--experimental-strip-types",
1715 "Experimental type-stripping for TypeScript files.",
1716 OptionType::Boolean,
1717 OptionEnvvarSettings::AllowedInEnvvar,
1718 true,
1719 );
1720 self.add_option(
1721 "--experimental-transform-types",
1722 "enable transformation of TypeScript-only syntax into JavaScript code",
1723 OptionType::Boolean,
1724 OptionEnvvarSettings::AllowedInEnvvar,
1725 false,
1726 );
1727 self.add_option(
1728 "--interactive",
1729 "always enter the REPL even if stdin does not appear to be a terminal",
1730 OptionType::Boolean,
1731 OptionEnvvarSettings::DisallowedInEnvvar,
1732 false,
1733 );
1734 self.add_option(
1735 "--napi-modules",
1736 "",
1737 OptionType::NoOp,
1738 OptionEnvvarSettings::AllowedInEnvvar,
1739 false,
1740 );
1741 self.add_option(
1742 "--tls-keylog",
1743 "log TLS decryption keys to named file for traffic analysis",
1744 OptionType::String,
1745 OptionEnvvarSettings::AllowedInEnvvar,
1746 false,
1747 );
1748 self.add_option(
1749 "--tls-min-v1.0",
1750 "set default TLS minimum to TLSv1.0 (default: TLSv1.2)",
1751 OptionType::Boolean,
1752 OptionEnvvarSettings::AllowedInEnvvar,
1753 false,
1754 );
1755 self.add_option(
1756 "--tls-min-v1.1",
1757 "set default TLS minimum to TLSv1.1 (default: TLSv1.2)",
1758 OptionType::Boolean,
1759 OptionEnvvarSettings::AllowedInEnvvar,
1760 false,
1761 );
1762 self.add_option(
1763 "--tls-min-v1.2",
1764 "set default TLS minimum to TLSv1.2 (default: TLSv1.2)",
1765 OptionType::Boolean,
1766 OptionEnvvarSettings::AllowedInEnvvar,
1767 false,
1768 );
1769 self.add_option(
1770 "--tls-min-v1.3",
1771 "set default TLS minimum to TLSv1.3 (default: TLSv1.2)",
1772 OptionType::Boolean,
1773 OptionEnvvarSettings::AllowedInEnvvar,
1774 false,
1775 );
1776 self.add_option(
1777 "--tls-max-v1.2",
1778 "set default TLS maximum to TLSv1.2 (default: TLSv1.3)",
1779 OptionType::Boolean,
1780 OptionEnvvarSettings::AllowedInEnvvar,
1781 false,
1782 );
1783 self.add_option(
1784 "--tls-max-v1.3",
1785 "set default TLS maximum to TLSv1.3 (default: TLSv1.3)",
1786 OptionType::Boolean,
1787 OptionEnvvarSettings::AllowedInEnvvar,
1788 false,
1789 );
1790 self.add_option(
1791 "--report-exclude-env",
1792 "Exclude environment variables when generating report (default: false)",
1793 OptionType::Boolean,
1794 OptionEnvvarSettings::AllowedInEnvvar,
1795 false,
1796 );
1797 self.add_option(
1798 "--report-exclude-network",
1799 "exclude network interface diagnostics. (default: false)",
1800 OptionType::Boolean,
1801 OptionEnvvarSettings::AllowedInEnvvar,
1802 false,
1803 );
1804
1805 self.add_option(
1807 "--track-heap-objects",
1808 "track heap object allocations for heap snapshots",
1809 OptionType::Boolean,
1810 OptionEnvvarSettings::AllowedInEnvvar,
1811 false,
1812 );
1813 self.add_option(
1814 "--abort-on-uncaught-exception",
1815 "aborting instead of exiting causes a core file to be generated for analysis",
1816 OptionType::V8Option,
1817 OptionEnvvarSettings::AllowedInEnvvar,
1818 false,
1819 );
1820 self.add_option(
1821 "--interpreted-frames-native-stack",
1822 "help system profilers to translate JavaScript interpreted frames",
1823 OptionType::V8Option,
1824 OptionEnvvarSettings::AllowedInEnvvar,
1825 false,
1826 );
1827 self.add_option(
1828 "--max-old-space-size",
1829 "",
1830 OptionType::V8Option,
1831 OptionEnvvarSettings::AllowedInEnvvar,
1832 false,
1833 );
1834 self.add_option(
1835 "--max-semi-space-size",
1836 "",
1837 OptionType::V8Option,
1838 OptionEnvvarSettings::AllowedInEnvvar,
1839 false,
1840 );
1841 self.add_option(
1842 "--perf-basic-prof",
1843 "",
1844 OptionType::V8Option,
1845 OptionEnvvarSettings::AllowedInEnvvar,
1846 false,
1847 );
1848 self.add_option(
1849 "--perf-basic-prof-only-functions",
1850 "",
1851 OptionType::V8Option,
1852 OptionEnvvarSettings::AllowedInEnvvar,
1853 false,
1854 );
1855 self.add_option(
1856 "--perf-prof",
1857 "",
1858 OptionType::V8Option,
1859 OptionEnvvarSettings::AllowedInEnvvar,
1860 false,
1861 );
1862 self.add_option(
1863 "--perf-prof-unwinding-info",
1864 "",
1865 OptionType::V8Option,
1866 OptionEnvvarSettings::AllowedInEnvvar,
1867 false,
1868 );
1869 self.add_option(
1870 "--stack-trace-limit",
1871 "",
1872 OptionType::Integer,
1873 OptionEnvvarSettings::AllowedInEnvvar,
1874 false,
1875 );
1876 self.add_option(
1877 "--disallow-code-generation-from-strings",
1878 "disallow eval and friends",
1879 OptionType::V8Option,
1880 OptionEnvvarSettings::AllowedInEnvvar,
1881 false,
1882 );
1883 self.add_option(
1884 "--jitless",
1885 "disable runtime allocation of executable memory",
1886 OptionType::V8Option,
1887 OptionEnvvarSettings::AllowedInEnvvar,
1888 false,
1889 );
1890 self.add_option(
1891 "--report-uncaught-exception",
1892 "generate diagnostic report on uncaught exceptions",
1893 OptionType::Boolean,
1894 OptionEnvvarSettings::AllowedInEnvvar,
1895 false,
1896 );
1897 self.add_option(
1898 "--report-on-signal",
1899 "generate diagnostic report upon receiving signals",
1900 OptionType::Boolean,
1901 OptionEnvvarSettings::AllowedInEnvvar,
1902 false,
1903 );
1904 self.add_option("--report-signal", "causes diagnostic report to be produced on provided signal, unsupported in Windows. (default: SIGUSR2)", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1905 self.add_option(
1906 "--enable-etw-stack-walking",
1907 "provides heap data to ETW Windows native tracing",
1908 OptionType::V8Option,
1909 OptionEnvvarSettings::AllowedInEnvvar,
1910 false,
1911 );
1912 self.add_option(
1913 "--experimental-top-level-await",
1914 "",
1915 OptionType::NoOp,
1916 OptionEnvvarSettings::AllowedInEnvvar,
1917 false,
1918 );
1919 self.add_option(
1920 "--experimental-shadow-realm",
1921 "",
1922 OptionType::Boolean,
1923 OptionEnvvarSettings::AllowedInEnvvar,
1924 false,
1925 );
1926 self.add_option(
1927 "--harmony-shadow-realm",
1928 "",
1929 OptionType::V8Option,
1930 OptionEnvvarSettings::DisallowedInEnvvar,
1931 false,
1932 );
1933 self.add_option(
1934 "--build-snapshot",
1935 "Generate a snapshot blob when the process exits.",
1936 OptionType::Boolean,
1937 OptionEnvvarSettings::DisallowedInEnvvar,
1938 false,
1939 );
1940 self.add_option("--build-snapshot-config", "Generate a snapshot blob when the process exits using a JSON configuration in the specified path.", OptionType::String, OptionEnvvarSettings::DisallowedInEnvvar, false);
1941
1942 self.add_option(
1944 "--title",
1945 "the process title to use on startup",
1946 OptionType::String,
1947 OptionEnvvarSettings::AllowedInEnvvar,
1948 false,
1949 );
1950 self.add_option(
1951 "--trace-event-categories",
1952 "comma separated list of trace event categories to record",
1953 OptionType::String,
1954 OptionEnvvarSettings::AllowedInEnvvar,
1955 false,
1956 );
1957 self.add_option("--trace-event-file-pattern", "Template string specifying the filepath for the trace-events data, it supports ${rotation} and ${pid}.", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1958 self.add_option(
1959 "--v8-pool-size",
1960 "set V8's thread pool size",
1961 OptionType::Integer,
1962 OptionEnvvarSettings::AllowedInEnvvar,
1963 false,
1964 );
1965 self.add_option(
1966 "--zero-fill-buffers",
1967 "automatically zero-fill all newly allocated Buffer instances",
1968 OptionType::Boolean,
1969 OptionEnvvarSettings::AllowedInEnvvar,
1970 false,
1971 );
1972 self.add_option(
1973 "--debug-arraybuffer-allocations",
1974 "",
1975 OptionType::Boolean,
1976 OptionEnvvarSettings::AllowedInEnvvar,
1977 false,
1978 );
1979 self.add_option(
1980 "--disable-proto",
1981 "disable Object.prototype.__proto__",
1982 OptionType::String,
1983 OptionEnvvarSettings::AllowedInEnvvar,
1984 false,
1985 );
1986 self.add_option(
1987 "--node-snapshot",
1988 "",
1989 OptionType::Boolean,
1990 OptionEnvvarSettings::AllowedInEnvvar,
1991 false,
1992 );
1993 self.add_option("--snapshot-blob", "Path to the snapshot blob that's either the result of snapshot building, or the blob that is used to restore the application state", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
1994 self.add_option(
1995 "--security-revert",
1996 "",
1997 OptionType::StringList,
1998 OptionEnvvarSettings::DisallowedInEnvvar,
1999 false,
2000 );
2001 self.add_option(
2002 "--completion-bash",
2003 "print source-able bash completion script",
2004 OptionType::Boolean,
2005 OptionEnvvarSettings::DisallowedInEnvvar,
2006 false,
2007 );
2008 self.add_option(
2009 "--help",
2010 "print node command line options",
2011 OptionType::Boolean,
2012 OptionEnvvarSettings::DisallowedInEnvvar,
2013 false,
2014 );
2015 self.add_option(
2016 "--version",
2017 "print Node.js version",
2018 OptionType::Boolean,
2019 OptionEnvvarSettings::DisallowedInEnvvar,
2020 false,
2021 );
2022 self.add_option(
2023 "--v8-options",
2024 "print V8 command line options",
2025 OptionType::Boolean,
2026 OptionEnvvarSettings::DisallowedInEnvvar,
2027 false,
2028 );
2029 self.add_option(
2030 "--report-compact",
2031 "output compact single-line JSON",
2032 OptionType::Boolean,
2033 OptionEnvvarSettings::AllowedInEnvvar,
2034 false,
2035 );
2036 self.add_option(
2037 "--report-dir",
2038 "define custom report pathname. (default: current working directory)",
2039 OptionType::String,
2040 OptionEnvvarSettings::AllowedInEnvvar,
2041 false,
2042 );
2043 self.add_option(
2044 "--report-filename",
2045 "define custom report file name. (default: YYYYMMDD.HHMMSS.PID.SEQUENCE#.txt)",
2046 OptionType::String,
2047 OptionEnvvarSettings::AllowedInEnvvar,
2048 false,
2049 );
2050 self.add_option(
2051 "--report-on-fatalerror",
2052 "generate diagnostic report on fatal (internal) errors",
2053 OptionType::Boolean,
2054 OptionEnvvarSettings::AllowedInEnvvar,
2055 false,
2056 );
2057 self.add_option(
2058 "--icu-data-dir",
2059 "set ICU data load path to dir (overrides NODE_ICU_DATA)",
2060 OptionType::String,
2061 OptionEnvvarSettings::AllowedInEnvvar,
2062 false,
2063 );
2064 self.add_option(
2065 "--openssl-config",
2066 "load OpenSSL configuration from the specified file (overrides OPENSSL_CONF)",
2067 OptionType::String,
2068 OptionEnvvarSettings::AllowedInEnvvar,
2069 false,
2070 );
2071 self.add_option(
2072 "--tls-cipher-list",
2073 "use an alternative default TLS cipher list",
2074 OptionType::String,
2075 OptionEnvvarSettings::AllowedInEnvvar,
2076 false,
2077 );
2078 self.add_option(
2079 "--use-openssl-ca",
2080 "use OpenSSL's default CA store",
2081 OptionType::Boolean,
2082 OptionEnvvarSettings::AllowedInEnvvar,
2083 false,
2084 );
2085 self.add_option(
2086 "--use-system-ca",
2087 "use system's CA store",
2088 OptionType::Boolean,
2089 OptionEnvvarSettings::AllowedInEnvvar,
2090 false,
2091 );
2092 self.add_option(
2093 "--use-bundled-ca",
2094 "use bundled CA store",
2095 OptionType::Boolean,
2096 OptionEnvvarSettings::AllowedInEnvvar,
2097 false,
2098 );
2099 self.add_option(
2100 "[ssl_openssl_cert_store]",
2101 "",
2102 OptionType::Boolean,
2103 OptionEnvvarSettings::DisallowedInEnvvar,
2104 false,
2105 );
2106 self.add_option(
2107 "--enable-fips",
2108 "enable FIPS crypto at startup",
2109 OptionType::Boolean,
2110 OptionEnvvarSettings::AllowedInEnvvar,
2111 false,
2112 );
2113 self.add_option(
2114 "--force-fips",
2115 "force FIPS crypto (cannot be disabled)",
2116 OptionType::Boolean,
2117 OptionEnvvarSettings::AllowedInEnvvar,
2118 false,
2119 );
2120 self.add_option(
2121 "--secure-heap",
2122 "total size of the OpenSSL secure heap",
2123 OptionType::Integer,
2124 OptionEnvvarSettings::AllowedInEnvvar,
2125 false,
2126 );
2127 self.add_option(
2128 "--secure-heap-min",
2129 "minimum allocation size from the OpenSSL secure heap",
2130 OptionType::Integer,
2131 OptionEnvvarSettings::AllowedInEnvvar,
2132 false,
2133 );
2134 self.add_option(
2135 "--openssl-legacy-provider",
2136 "enable OpenSSL 3.0 legacy provider",
2137 OptionType::Boolean,
2138 OptionEnvvarSettings::AllowedInEnvvar,
2139 false,
2140 );
2141 self.add_option(
2142 "--openssl-shared-config",
2143 "enable OpenSSL shared configuration",
2144 OptionType::Boolean,
2145 OptionEnvvarSettings::AllowedInEnvvar,
2146 false,
2147 );
2148 self.add_option("--use-largepages", "Map the Node.js static code to large pages. Options are 'off' (the default value, meaning do not map), 'on' (map and ignore failure, reporting it to stderr), or 'silent' (map and silently ignore failure)", OptionType::String, OptionEnvvarSettings::AllowedInEnvvar, false);
2149 self.add_option(
2150 "--trace-sigint",
2151 "enable printing JavaScript stacktrace on SIGINT",
2152 OptionType::Boolean,
2153 OptionEnvvarSettings::AllowedInEnvvar,
2154 false,
2155 );
2156 self.add_option(
2157 "--node-memory-debug",
2158 "Run with extra debug checks for memory leaks in Node.js itself",
2159 OptionType::NoOp,
2160 OptionEnvvarSettings::AllowedInEnvvar,
2161 false,
2162 );
2163 self.add_option(
2164 "--experimental-sea-config",
2165 "Generate a blob that can be embedded into the single executable application",
2166 OptionType::String,
2167 OptionEnvvarSettings::DisallowedInEnvvar,
2168 false,
2169 );
2170 self.add_option(
2171 "--run",
2172 "Run a script specified in package.json",
2173 OptionType::String,
2174 OptionEnvvarSettings::DisallowedInEnvvar,
2175 false,
2176 );
2177 self.add_option("--disable-wasm-trap-handler", "Disable trap-handler-based WebAssembly bound checks. V8 will insert inline bound checks when compiling WebAssembly which may slow down performance.", OptionType::Boolean, OptionEnvvarSettings::AllowedInEnvvar, false);
2178
2179 self.add_alias("--debug-port", vec!["--inspect-port"]);
2181 self.add_alias("--inspect=", vec!["--inspect-port", "--inspect"]);
2182 self.add_alias("--debug=", vec!["--debug"]);
2183 self.add_alias("--debug-brk=", vec!["--debug-brk"]);
2184 self.add_alias("--inspect-brk=", vec!["--inspect-port", "--inspect-brk"]);
2185 self.add_alias(
2186 "--inspect-brk-node=",
2187 vec!["--inspect-port", "--inspect-brk-node"],
2188 );
2189 self.add_alias("--inspect-wait=", vec!["--inspect-port", "--inspect-wait"]);
2190 self.add_alias("-C", vec!["--conditions"]);
2191 self.add_alias("--loader", vec!["--experimental-loader"]);
2192 self.add_alias(
2193 "--enable-network-family-autoselection",
2194 vec!["--network-family-autoselection"],
2195 );
2196 self.add_alias(
2197 "--es-module-specifier-resolution",
2198 vec!["--experimental-specifier-resolution"],
2199 );
2200 self.add_alias("--prof-process", vec!["--prof-process", "--"]);
2201 self.add_alias("--experimental-test-isolation", vec!["--test-isolation"]);
2202 self.add_alias("-c", vec!["--check"]);
2203 self.add_alias("-e", vec!["--eval"]);
2204 self.add_alias("--print <arg>", vec!["-pe"]);
2205 self.add_alias("-pe", vec!["--print", "--eval"]);
2206 self.add_alias("-p", vec!["--print"]);
2207 self.add_alias("-r", vec!["--require"]);
2208 self.add_alias("-i", vec!["--interactive"]);
2209 self.add_alias("--security-reverts", vec!["--security-revert"]);
2210 self.add_alias("-h", vec!["--help"]);
2211 self.add_alias("-v", vec!["--version"]);
2212 self.add_alias("--report-directory", vec!["--report-dir"]);
2213 self.add_alias(
2214 "--trace-events-enabled",
2215 vec!["--trace-event-categories", "v8,node,node.async_hooks"],
2216 );
2217
2218 self.add_implication("--inspect-brk", vec!["--inspect"]);
2220 self.add_implication("--inspect-brk-node", vec!["--inspect"]);
2221 self.add_implication("--inspect-wait", vec!["--inspect"]);
2222 self.add_implication("--env-file", vec!["[has_env_file_string]"]);
2223 self.add_implication("--env-file-if-exists", vec!["[has_env_file_string]"]);
2224 self.add_implication("--eval", vec!["[has_eval_string]"]);
2225 self.add_implication(
2226 "--experimental-transform-types",
2227 vec!["--experimental-strip-types", "--enable-source-maps"],
2228 );
2229 self.add_implication("--watch-path", vec!["--watch"]);
2230 self.add_implication("--trace-env-js-stack", vec!["--trace-env"]);
2231 self.add_implication("--trace-env-native-stack", vec!["--trace-env"]);
2232 self.add_implication("--report-signal", vec!["--report-on-signal"]);
2233 self.add_implication(
2234 "--experimental-shadow-realm",
2235 vec!["--harmony-shadow-realm"],
2236 );
2237 self.add_implication(
2238 "--harmony-shadow-realm",
2239 vec!["--experimental-shadow-realm"],
2240 );
2241 self.add_implication("--build-snapshot-config", vec!["--build-snapshot"]);
2242 self.add_implication("--use-openssl-ca", vec!["[ssl_openssl_cert_store]"]);
2243 self.add_implication(
2244 "--node-memory-debug",
2245 vec!["--debug-arraybuffer-allocations", "--verify-base-objects"],
2246 );
2247 }
2248
2249 fn apply_option_value(
2250 &self,
2251 options: &mut PerProcessOptions,
2252 name: &str,
2253 value: &str,
2254 is_negation: bool,
2255 option_info: &OptionInfo,
2256 errors: &mut Vec<String>,
2257 ) {
2258 match option_info.option_type {
2259 OptionType::Boolean => {
2260 self.set_boolean_field(options, name, !is_negation);
2261 }
2262 OptionType::Integer => {
2263 if let Ok(val) = value.parse::<i64>() {
2264 self.set_integer_field(options, name, val);
2265 } else {
2266 errors.push(format!("Invalid integer value for {}: {}", name, value));
2267 }
2268 }
2269 OptionType::UInteger => {
2270 if let Ok(val) = value.parse::<u64>() {
2271 self.set_uinteger_field(options, name, val);
2272 } else {
2273 errors.push(format!(
2274 "Invalid unsigned integer value for {}: {}",
2275 name, value
2276 ));
2277 }
2278 }
2279 OptionType::String => {
2280 self.set_string_field(options, name, value.to_string());
2281 }
2282 OptionType::StringList => {
2283 self.add_to_string_list_field(options, name, value.to_string());
2284 }
2285 OptionType::HostPort => {
2286 let host_port = split_host_port(value, errors);
2287 self.set_host_port_field(options, name, host_port);
2288 }
2289 OptionType::NoOp | OptionType::V8Option => {
2290 }
2292 }
2293 }
2294
2295 fn set_boolean_field(
2296 &self,
2297 options: &mut PerProcessOptions,
2298 name: &str,
2299 value: bool,
2300 ) {
2301 match name {
2302 "--inspect" => {
2304 options.per_isolate.per_env.debug_options.inspector_enabled = value
2305 }
2306 "--inspect-wait" => {
2307 options.per_isolate.per_env.debug_options.inspect_wait = value
2308 }
2309 "--debug" | "--debug-brk" => {
2310 options.per_isolate.per_env.debug_options.deprecated_debug = value
2311 }
2312 "--inspect-brk" => {
2313 options.per_isolate.per_env.debug_options.break_first_line = value
2314 }
2315 "--inspect-brk-node" => {
2316 options
2317 .per_isolate
2318 .per_env
2319 .debug_options
2320 .break_node_first_line = value
2321 }
2322
2323 "--experimental-detect-module" => {
2325 options.per_isolate.per_env.detect_module = value
2326 }
2327 "--disable-sigusr1" => {
2328 options.per_isolate.per_env.disable_sigusr1 = value
2329 }
2330 "--experimental-print-required-tla" => {
2331 options.per_isolate.per_env.print_required_tla = value
2332 }
2333 "--experimental-require-module" => {
2334 options.per_isolate.per_env.require_module = value
2335 }
2336 "--enable-source-maps" => {
2337 options.per_isolate.per_env.enable_source_maps = value
2338 }
2339 "--entry-url" => options.per_isolate.per_env.entry_is_url = value,
2340 "--experimental-addon-modules" => {
2341 options.per_isolate.per_env.experimental_addon_modules = value
2342 }
2343 "--experimental-eventsource" => {
2344 options.per_isolate.per_env.experimental_eventsource = value
2345 }
2346 "--experimental-websocket" => {
2347 options.per_isolate.per_env.experimental_websocket = value
2348 }
2349 "--experimental-sqlite" => {
2350 options.per_isolate.per_env.experimental_sqlite = value
2351 }
2352 "--experimental-quic" => {
2353 options.per_isolate.per_env.experimental_quic = value
2354 }
2355 "--experimental-webstorage" => {
2356 options.per_isolate.per_env.experimental_webstorage = value
2357 }
2358 "--experimental-global-navigator" => {
2359 options.per_isolate.per_env.experimental_global_navigator = value
2360 }
2361 "--experimental-wasm-modules" => {
2362 options.per_isolate.per_env.experimental_wasm_modules = value
2363 }
2364 "--experimental-import-meta-resolve" => {
2365 options.per_isolate.per_env.experimental_import_meta_resolve = value
2366 }
2367 "--permission" => options.per_isolate.per_env.permission = value,
2368 "--allow-addons" => options.per_isolate.per_env.allow_addons = value,
2369 "--allow-child-process" => {
2370 options.per_isolate.per_env.allow_child_process = value
2371 }
2372 "--allow-wasi" => options.per_isolate.per_env.allow_wasi = value,
2373 "--allow-worker" => {
2374 options.per_isolate.per_env.allow_worker_threads = value
2375 }
2376 "--experimental-repl-await" => {
2377 options.per_isolate.per_env.experimental_repl_await = value
2378 }
2379 "--experimental-vm-modules" => {
2380 options.per_isolate.per_env.experimental_vm_modules = value
2381 }
2382 "--async-context-frame" => {
2383 options.per_isolate.per_env.async_context_frame = value
2384 }
2385 "--expose-internals" => {
2386 options.per_isolate.per_env.expose_internals = value
2387 }
2388 "--frozen-intrinsics" => {
2389 options.per_isolate.per_env.frozen_intrinsics = value
2390 }
2391 "--network-family-autoselection" => {
2392 options.per_isolate.per_env.network_family_autoselection = value
2393 }
2394 "--deprecation" => options.per_isolate.per_env.deprecation = value,
2395 "--force-async-hooks-checks" => {
2396 options.per_isolate.per_env.force_async_hooks_checks = value
2397 }
2398 "--force-node-api-uncaught-exceptions-policy" => {
2399 options
2400 .per_isolate
2401 .per_env
2402 .force_node_api_uncaught_exceptions_policy = value
2403 }
2404 "--addons" => options.per_isolate.per_env.allow_native_addons = value,
2405 "--global-search-paths" => {
2406 options.per_isolate.per_env.global_search_paths = value
2407 }
2408 "--warnings" => options.per_isolate.per_env.warnings = value,
2409 "--force-context-aware" => {
2410 options.per_isolate.per_env.force_context_aware = value
2411 }
2412 "--pending-deprecation" => {
2413 options.per_isolate.per_env.pending_deprecation = value
2414 }
2415 "--preserve-symlinks" => {
2416 options.per_isolate.per_env.preserve_symlinks = value
2417 }
2418 "--preserve-symlinks-main" => {
2419 options.per_isolate.per_env.preserve_symlinks_main = value
2420 }
2421 "--prof-process" => options.per_isolate.per_env.prof_process = value,
2422 "--cpu-prof" => options.per_isolate.per_env.cpu_prof = value,
2423 "--experimental-network-inspection" => {
2424 options.per_isolate.per_env.experimental_network_inspection = value
2425 }
2426 "--experimental-worker-inspection" => {
2427 options.per_isolate.per_env.experimental_worker_inspection = value
2428 }
2429 "--heap-prof" => options.per_isolate.per_env.heap_prof = value,
2430 "--insecure-http-parser" => {
2431 options.per_isolate.per_env.insecure_http_parser = value
2432 }
2433 "[has_env_file_string]" => {
2434 options.per_isolate.per_env.has_env_file_string = value
2435 }
2436 "--experimental-default-config-file" => {
2437 options.per_isolate.per_env.experimental_default_config_file = value
2438 }
2439 "--test" => options.per_isolate.per_env.test_runner = value,
2440 "--test-force-exit" => {
2441 options.per_isolate.per_env.test_runner_force_exit = value
2442 }
2443 "--test-update-snapshots" => {
2444 options.per_isolate.per_env.test_runner_update_snapshots = value
2445 }
2446 "--experimental-test-coverage" => {
2447 options.per_isolate.per_env.test_runner_coverage = value
2448 }
2449 "--experimental-test-module-mocks" => {
2450 options.per_isolate.per_env.test_runner_module_mocks = value
2451 }
2452 "--test-only" => options.per_isolate.per_env.test_only = value,
2453 "--test-udp-no-try-send" => {
2454 options.per_isolate.per_env.test_udp_no_try_send = value
2455 }
2456 "--throw-deprecation" => {
2457 options.per_isolate.per_env.throw_deprecation = value
2458 }
2459 "--trace-deprecation" => {
2460 options.per_isolate.per_env.trace_deprecation = value
2461 }
2462 "--trace-exit" => options.per_isolate.per_env.trace_exit = value,
2463 "--trace-sync-io" => options.per_isolate.per_env.trace_sync_io = value,
2464 "--trace-tls" => options.per_isolate.per_env.trace_tls = value,
2465 "--trace-uncaught" => options.per_isolate.per_env.trace_uncaught = value,
2466 "--trace-warnings" => options.per_isolate.per_env.trace_warnings = value,
2467 "--trace-promises" => options.per_isolate.per_env.trace_promises = value,
2468 "--trace-env" => options.per_isolate.per_env.trace_env = value,
2469 "--trace-env-js-stack" => {
2470 options.per_isolate.per_env.trace_env_js_stack = value
2471 }
2472 "--trace-env-native-stack" => {
2473 options.per_isolate.per_env.trace_env_native_stack = value
2474 }
2475 "--extra-info-on-fatal-exception" => {
2476 options.per_isolate.per_env.extra_info_on_fatal_exception = value
2477 }
2478 "--verify-base-objects" => {
2479 options.per_isolate.per_env.verify_base_objects = value
2480 }
2481 "--watch" => options.per_isolate.per_env.watch_mode = value,
2482 "--watch-preserve-output" => {
2483 options.per_isolate.per_env.watch_mode_preserve_output = value
2484 }
2485 "--check" => options.per_isolate.per_env.syntax_check_only = value,
2486 "[has_eval_string]" => {
2487 options.per_isolate.per_env.has_eval_string = value
2488 }
2489 "--print" => options.per_isolate.per_env.print_eval = value,
2490 "--experimental-strip-types" => {
2491 options.per_isolate.per_env.experimental_strip_types = value
2492 }
2493 "--experimental-transform-types" => {
2494 options.per_isolate.per_env.experimental_transform_types = value
2495 }
2496 "--interactive" => options.per_isolate.per_env.force_repl = value,
2497 "--tls-min-v1.0" => options.per_isolate.per_env.tls_min_v1_0 = value,
2498 "--tls-min-v1.1" => options.per_isolate.per_env.tls_min_v1_1 = value,
2499 "--tls-min-v1.2" => options.per_isolate.per_env.tls_min_v1_2 = value,
2500 "--tls-min-v1.3" => options.per_isolate.per_env.tls_min_v1_3 = value,
2501 "--tls-max-v1.2" => options.per_isolate.per_env.tls_max_v1_2 = value,
2502 "--tls-max-v1.3" => options.per_isolate.per_env.tls_max_v1_3 = value,
2503 "--report-exclude-env" => {
2504 options.per_isolate.per_env.report_exclude_env = value
2505 }
2506 "--report-exclude-network" => {
2507 options.per_isolate.per_env.report_exclude_network = value
2508 }
2509
2510 "--track-heap-objects" => options.per_isolate.track_heap_objects = value,
2512 "--report-uncaught-exception" => {
2513 options.per_isolate.report_uncaught_exception = value
2514 }
2515 "--report-on-signal" => options.per_isolate.report_on_signal = value,
2516 "--experimental-shadow-realm" => {
2517 options.per_isolate.experimental_shadow_realm = value
2518 }
2519 "--build-snapshot" => options.per_isolate.build_snapshot = value,
2520
2521 "--zero-fill-buffers" => options.zero_fill_all_buffers = value,
2523 "--debug-arraybuffer-allocations" => {
2524 options.debug_arraybuffer_allocations = value
2525 }
2526 "--node-snapshot" => options.node_snapshot = value,
2527 "--completion-bash" => options.print_bash_completion = value,
2528 "--help" => options.print_help = value,
2529 "--version" => options.print_version = value,
2530 "--v8-options" => options.print_v8_help = value,
2531 "--report-compact" => options.report_compact = value,
2532 "--report-on-fatalerror" => options.report_on_fatalerror = value,
2533 "--use-openssl-ca" => options.use_openssl_ca = value,
2534 "--use-system-ca" => options.use_system_ca = value,
2535 "--use-bundled-ca" => options.use_bundled_ca = value,
2536 "[ssl_openssl_cert_store]" => options.ssl_openssl_cert_store = value,
2537 "--enable-fips" => options.enable_fips_crypto = value,
2538 "--force-fips" => options.force_fips_crypto = value,
2539 "--openssl-legacy-provider" => options.openssl_legacy_provider = value,
2540 "--openssl-shared-config" => options.openssl_shared_config = value,
2541 "--disable-wasm-trap-handler" => {
2542 options.disable_wasm_trap_handler = value
2543 }
2544 "--trace-sigint" => options.trace_sigint = value,
2545
2546 _ => {
2547 }
2549 }
2550 }
2551
2552 fn set_integer_field(
2553 &self,
2554 options: &mut PerProcessOptions,
2555 name: &str,
2556 value: i64,
2557 ) {
2558 match name {
2559 "--heapsnapshot-near-heap-limit" => {
2560 options.per_isolate.per_env.heap_snapshot_near_heap_limit = value
2561 }
2562 "--stack-trace-limit" => options.per_isolate.stack_trace_limit = value,
2563 "--v8-pool-size" => options.v8_thread_pool_size = value,
2564 "--secure-heap" => options.secure_heap = value,
2565 "--secure-heap-min" => options.secure_heap_min = value,
2566 _ => {
2567 }
2569 }
2570 }
2571
2572 fn set_uinteger_field(
2573 &self,
2574 options: &mut PerProcessOptions,
2575 name: &str,
2576 value: u64,
2577 ) {
2578 match name {
2579 "--network-family-autoselection-attempt-timeout" => {
2580 options
2581 .per_isolate
2582 .per_env
2583 .network_family_autoselection_attempt_timeout = value
2584 }
2585 "--max-http-header-size" => {
2586 options.per_isolate.per_env.max_http_header_size = value
2587 }
2588 "--cpu-prof-interval" => {
2589 options.per_isolate.per_env.cpu_prof_interval = value
2590 }
2591 "--heap-prof-interval" => {
2592 options.per_isolate.per_env.heap_prof_interval = value
2593 }
2594 "--test-concurrency" => {
2595 options.per_isolate.per_env.test_runner_concurrency = value
2596 }
2597 "--test-timeout" => {
2598 options.per_isolate.per_env.test_runner_timeout = value
2599 }
2600 "--test-coverage-branches" => {
2601 options.per_isolate.per_env.test_coverage_branches = value
2602 }
2603 "--test-coverage-functions" => {
2604 options.per_isolate.per_env.test_coverage_functions = value
2605 }
2606 "--test-coverage-lines" => {
2607 options.per_isolate.per_env.test_coverage_lines = value
2608 }
2609 _ => {
2610 }
2612 }
2613 }
2614
2615 fn set_string_field(
2616 &self,
2617 options: &mut PerProcessOptions,
2618 name: &str,
2619 value: String,
2620 ) {
2621 match name {
2622 "--inspect-publish-uid" => {
2624 options
2625 .per_isolate
2626 .per_env
2627 .debug_options
2628 .inspect_publish_uid_string = value
2629 }
2630
2631 "--dns-result-order" => {
2633 options.per_isolate.per_env.dns_result_order = value
2634 }
2635 "--diagnostic-dir" => options.per_isolate.per_env.diagnostic_dir = value,
2636 "--localstorage-file" => {
2637 options.per_isolate.per_env.localstorage_file = value
2638 }
2639 "--input-type" => options.per_isolate.per_env.input_type = value,
2640 "--heapsnapshot-signal" => {
2641 options.per_isolate.per_env.heapsnapshot_signal = value
2642 }
2643 "--cpu-prof-name" => options.per_isolate.per_env.cpu_prof_name = value,
2644 "--cpu-prof-dir" => options.per_isolate.per_env.cpu_prof_dir = value,
2645 "--heap-prof-name" => options.per_isolate.per_env.heap_prof_name = value,
2646 "--heap-prof-dir" => options.per_isolate.per_env.heap_prof_dir = value,
2647 "--redirect-warnings" => {
2648 options.per_isolate.per_env.redirect_warnings = value
2649 }
2650 "--env-file" => options.per_isolate.per_env.env_file = value,
2651 "--env-file-if-exists" => {
2652 options.per_isolate.per_env.optional_env_file = value
2653 }
2654 "--experimental-config-file" => {
2655 options.per_isolate.per_env.experimental_config_file_path = value
2656 }
2657 "--test-isolation" => options.per_isolate.per_env.test_isolation = value,
2658 "--test-global-setup" => {
2659 options.per_isolate.per_env.test_global_setup_path = value
2660 }
2661 "--test-shard" => options.per_isolate.per_env.test_shard = value,
2662 "--trace-require-module" => {
2663 options.per_isolate.per_env.trace_require_module = value
2664 }
2665 "--unhandled-rejections" => {
2666 options.per_isolate.per_env.unhandled_rejections = value
2667 }
2668 "--watch-kill-signal" => {
2669 options.per_isolate.per_env.watch_mode_kill_signal = value
2670 }
2671 "--eval" => options.per_isolate.per_env.eval_string = value,
2672 "--tls-keylog" => options.per_isolate.per_env.tls_keylog = value,
2673
2674 "--report-signal" => options.per_isolate.report_signal = value,
2676 "--build-snapshot-config" => {
2677 options.per_isolate.build_snapshot_config = value
2678 }
2679
2680 "--title" => options.title = value,
2682 "--trace-event-categories" => options.trace_event_categories = value,
2683 "--trace-event-file-pattern" => options.trace_event_file_pattern = value,
2684 "--disable-proto" => options.disable_proto = value,
2685 "--snapshot-blob" => options.snapshot_blob = value,
2686 "--experimental-sea-config" => options.experimental_sea_config = value,
2687 "--run" => options.run = value,
2688 "--icu-data-dir" => options.icu_data_dir = value,
2689 "--openssl-config" => options.openssl_config = value,
2690 "--tls-cipher-list" => options.tls_cipher_list = value,
2691 "--report-dir" => options.report_directory = value,
2692 "--report-filename" => options.report_filename = value,
2693 "--use-largepages" => options.use_largepages = value,
2694
2695 _ => {
2696 }
2698 }
2699 }
2700
2701 fn add_to_string_list_field(
2702 &self,
2703 options: &mut PerProcessOptions,
2704 name: &str,
2705 value: String,
2706 ) {
2707 match name {
2708 "--conditions" => options.per_isolate.per_env.conditions.push(value),
2709 "--allow-fs-read" => {
2710 options.per_isolate.per_env.allow_fs_read.push(value)
2711 }
2712 "--allow-fs-write" => {
2713 options.per_isolate.per_env.allow_fs_write.push(value)
2714 }
2715 "--allow-net" => options.per_isolate.per_env.allow_net.push(value),
2716 "--experimental-loader" => {
2717 options.per_isolate.per_env.userland_loaders.push(value)
2718 }
2719 "--disable-warning" => {
2720 options.per_isolate.per_env.disable_warnings.push(value)
2721 }
2722 "--test-name-pattern" => {
2723 options.per_isolate.per_env.test_name_pattern.push(value)
2724 }
2725 "--test-reporter" => {
2726 options.per_isolate.per_env.test_reporter.push(value)
2727 }
2728 "--test-reporter-destination" => options
2729 .per_isolate
2730 .per_env
2731 .test_reporter_destination
2732 .push(value),
2733 "--test-skip-pattern" => {
2734 options.per_isolate.per_env.test_skip_pattern.push(value)
2735 }
2736 "--test-coverage-include" => options
2737 .per_isolate
2738 .per_env
2739 .coverage_include_pattern
2740 .push(value),
2741 "--test-coverage-exclude" => options
2742 .per_isolate
2743 .per_env
2744 .coverage_exclude_pattern
2745 .push(value),
2746 "--watch-path" => {
2747 options.per_isolate.per_env.watch_mode_paths.push(value)
2748 }
2749 "--require" => {
2750 options.per_isolate.per_env.preload_cjs_modules.push(value)
2751 }
2752 "--import" => options.per_isolate.per_env.preload_esm_modules.push(value),
2753 "--security-revert" => options.security_reverts.push(value),
2754 _ => {
2755 }
2757 }
2758 }
2759
2760 fn set_host_port_field(
2761 &self,
2762 options: &mut PerProcessOptions,
2763 name: &str,
2764 value: HostPort,
2765 ) {
2766 match name {
2767 "--inspect-port" => options
2768 .per_isolate
2769 .per_env
2770 .debug_options
2771 .host_port
2772 .update(&value),
2773 _ => {
2774 }
2776 }
2777 }
2778
2779 pub fn parse(&self, args: Vec<String>) -> Result<ParseResult, Vec<String>> {
2780 let mut args = args;
2781
2782 let mut v8_args = Vec::new();
2783 let mut errors = Vec::new();
2784 let mut options = PerProcessOptions::default();
2785 let mut synthetic_args = Vec::new();
2786
2787 let mut i = 0;
2789
2790 while i < args.len() + synthetic_args.len() && errors.is_empty() {
2791 let arg = if !synthetic_args.is_empty() {
2792 synthetic_args.remove(0)
2793 } else {
2794 if i >= args.len() {
2795 break;
2796 }
2797 let arg = args[i].clone();
2798 i += 1;
2799 arg
2800 };
2801
2802 if arg.len() <= 1 || !arg.starts_with('-') {
2803 if synthetic_args.is_empty() {
2805 i -= 1; }
2807 break;
2808 }
2809
2810 if arg == "--" {
2811 break;
2812 }
2813
2814 let (name, value, has_equals) = if arg.starts_with("--") {
2815 if let Some(eq_pos) = arg.find('=') {
2816 (
2817 arg[..eq_pos].to_string(),
2818 Some(arg[eq_pos + 1..].to_string()),
2819 true,
2820 )
2821 } else {
2822 (arg.clone(), None, false)
2823 }
2824 } else {
2825 (arg.clone(), None, false)
2826 };
2827
2828 let original_name = if has_equals {
2829 name.clone() + "="
2830 } else {
2831 name.clone()
2832 };
2833
2834 let mut normalized_name = name.clone();
2836 if normalized_name.starts_with("--") {
2837 normalized_name = normalized_name.replace('_', "-");
2838 }
2839
2840 let (is_negation, final_name) =
2842 if let Some(stripped) = normalized_name.strip_prefix("--no-") {
2843 (true, "--".to_string() + stripped)
2844 } else {
2845 (false, normalized_name)
2846 };
2847
2848 let mut current_name = final_name.clone();
2850 let mut expansion_count = 0;
2851 while expansion_count < 10 && current_name != "--" {
2852 if let Some(alias_expansion) = self.aliases.get(¤t_name) {
2853 if !alias_expansion.is_empty() {
2854 let new_name = alias_expansion[0].clone();
2855 if new_name == current_name {
2857 if alias_expansion.len() > 1 {
2858 for item in alias_expansion[1..].iter().rev() {
2859 synthetic_args.insert(0, item.clone());
2860 }
2861 }
2862 break;
2863 }
2864 current_name = new_name;
2865 if alias_expansion.len() > 1 {
2866 for item in alias_expansion[1..].iter().rev() {
2867 synthetic_args.insert(0, item.clone());
2868 }
2869 }
2870 expansion_count += 1;
2871 } else {
2872 break;
2873 }
2874 } else if has_equals {
2875 if let Some(alias_expansion) =
2876 self.aliases.get(&(current_name.clone() + "="))
2877 {
2878 if !alias_expansion.is_empty() {
2879 let new_name = alias_expansion[0].clone();
2880 if new_name == current_name {
2882 if alias_expansion.len() > 1 {
2883 for item in alias_expansion[1..].iter().rev() {
2884 synthetic_args.insert(0, item.clone());
2885 }
2886 }
2887 break;
2888 }
2889 current_name = new_name;
2890 if alias_expansion.len() > 1 {
2891 for item in alias_expansion[1..].iter().rev() {
2892 synthetic_args.insert(0, item.clone());
2893 }
2894 }
2895 expansion_count += 1;
2896 } else {
2897 break;
2898 }
2899 } else {
2900 break;
2901 }
2902 } else {
2903 break;
2904 }
2905 }
2906
2907 let implied_name = if is_negation {
2909 "--no-".to_string() + ¤t_name[2..]
2910 } else {
2911 current_name.clone()
2912 };
2913
2914 if let Some(implications) = self.implications.get(&implied_name) {
2915 for implication in implications {
2916 if implication.starts_with("--") {
2917 if let Some(stripped) = implication.strip_prefix("--no-") {
2918 let target_name = "--".to_string() + stripped;
2919 if let Some(option_info) = self.options.get(&target_name)
2920 && option_info.option_type == OptionType::Boolean
2921 {
2922 self.set_boolean_field(&mut options, &target_name, false);
2923 }
2924 } else {
2925 if let Some(option_info) = self.options.get(implication) {
2927 if option_info.option_type == OptionType::Boolean {
2928 self.set_boolean_field(&mut options, implication, true);
2929 } else {
2930 v8_args.push(implication.clone());
2931 }
2932 } else {
2933 v8_args.push(implication.clone());
2934 }
2935 }
2936 } else {
2937 if let Some(option_info) = self.options.get(implication)
2939 && option_info.option_type == OptionType::Boolean
2940 {
2941 self.set_boolean_field(&mut options, implication, true);
2942 }
2943 }
2944 }
2945 }
2946
2947 if let Some(option_info) = self.options.get(¤t_name) {
2949 if is_negation
2951 && option_info.option_type != OptionType::Boolean
2952 && option_info.option_type != OptionType::V8Option
2953 {
2954 errors.push(format!(
2955 "{} is an invalid negation because it is not a boolean option",
2956 arg
2957 ));
2958 break;
2959 }
2960
2961 let option_value = if matches!(
2963 option_info.option_type,
2964 OptionType::Boolean | OptionType::NoOp | OptionType::V8Option
2965 ) {
2966 String::new()
2967 } else if let Some(val) = value {
2968 if val.is_empty() {
2969 errors.push(format!("{} requires an argument", original_name));
2970 break;
2971 }
2972 val
2973 } else {
2974 let next_val = if !synthetic_args.is_empty() {
2976 synthetic_args.remove(0)
2977 } else if i < args.len() {
2978 let val = args[i].clone();
2979 i += 1;
2980 val
2981 } else {
2982 errors.push(format!("{} requires an argument", original_name));
2983 break;
2984 };
2985
2986 if next_val.starts_with('-')
2987 && (next_val.len() == 1
2988 || !next_val[1..].chars().all(|c| c.is_ascii_digit()))
2989 {
2990 errors.push(format!("{} requires an argument", original_name));
2991 break;
2992 }
2993
2994 if next_val.starts_with("\\-") {
2996 next_val[1..].to_string()
2997 } else {
2998 next_val
2999 }
3000 };
3001
3002 match option_info.option_type {
3004 OptionType::V8Option => {
3005 v8_args.push(arg);
3006 }
3007 _ => {
3008 self.apply_option_value(
3009 &mut options,
3010 ¤t_name,
3011 &option_value,
3012 is_negation,
3013 option_info,
3014 &mut errors,
3015 );
3016 }
3017 }
3018 } else {
3019 v8_args.push(arg);
3021 }
3022 }
3023
3024 args.drain(0..i);
3026 args.splice(0..0, synthetic_args);
3027
3028 if options.per_isolate.per_env.watch_mode
3030 && !options.per_isolate.per_env.test_runner
3031 && args.is_empty()
3032 {
3033 errors.push("--watch requires specifying a file".to_string());
3034 }
3035
3036 options.check_options(&mut errors);
3038
3039 if errors.is_empty() {
3040 Ok(ParseResult {
3041 options,
3042 remaining_args: args,
3043 v8_args,
3044 })
3045 } else {
3046 Err(errors)
3047 }
3048 }
3049}
3050
3051#[derive(Debug, Clone)]
3052pub struct ParseResult {
3053 pub options: PerProcessOptions,
3054 pub remaining_args: Vec<String>,
3055 pub v8_args: Vec<String>,
3056}
3057
3058pub fn parse_node_options_env_var(
3060 node_options: &str,
3061) -> Result<Vec<String>, Vec<String>> {
3062 let mut env_argv = Vec::new();
3063 let mut errors = Vec::new();
3064 let mut is_in_string = false;
3065 let mut will_start_new_arg = true;
3066
3067 let chars: Vec<char> = node_options.chars().collect();
3068 let mut index = 0;
3069
3070 while index < chars.len() {
3071 let mut c = chars[index];
3072
3073 if c == '\\' && is_in_string {
3075 if index + 1 == chars.len() {
3076 errors
3077 .push("invalid value for NODE_OPTIONS (invalid escape)".to_string());
3078 return Err(errors);
3079 } else {
3080 index += 1;
3081 c = chars[index];
3082 }
3083 } else if c == ' ' && !is_in_string {
3084 will_start_new_arg = true;
3085 index += 1;
3086 continue;
3087 } else if c == '"' {
3088 is_in_string = !is_in_string;
3089 index += 1;
3090 continue;
3091 }
3092
3093 if will_start_new_arg {
3094 env_argv.push(c.to_string());
3095 will_start_new_arg = false;
3096 } else if let Some(last) = env_argv.last_mut() {
3097 last.push(c);
3098 }
3099
3100 index += 1;
3101 }
3102
3103 if is_in_string {
3104 errors
3105 .push("invalid value for NODE_OPTIONS (unterminated string)".to_string());
3106 return Err(errors);
3107 }
3108
3109 Ok(env_argv)
3110}
3111
3112pub fn parse_args(args: Vec<String>) -> Result<ParseResult, Vec<String>> {
3114 let parser = OptionsParser::new();
3115 parser.parse(args)
3116}
3117
3118#[derive(Debug, Clone, Default)]
3120pub struct TranslateOptions {
3121 pub use_node_subcommand: bool,
3124 pub add_unstable_flags: bool,
3127 pub add_standalone_config: bool,
3130 pub wrap_eval_code: bool,
3132}
3133
3134impl TranslateOptions {
3135 pub fn for_node_cli() -> Self {
3137 Self {
3138 use_node_subcommand: true,
3139 add_unstable_flags: true,
3140 add_standalone_config: true,
3141 wrap_eval_code: false,
3142 }
3143 }
3144
3145 pub fn for_child_process() -> Self {
3147 Self {
3148 use_node_subcommand: false,
3149 add_unstable_flags: true,
3150 add_standalone_config: false,
3151 wrap_eval_code: true,
3152 }
3153 }
3154
3155 pub fn for_shell_command() -> Self {
3159 Self {
3160 use_node_subcommand: false,
3161 add_unstable_flags: true,
3162 add_standalone_config: false,
3163 wrap_eval_code: false,
3164 }
3165 }
3166}
3167
3168#[derive(Debug, Clone, Default)]
3170pub struct TranslatedArgs {
3171 pub deno_args: Vec<String>,
3173 pub node_options: Vec<String>,
3175 pub use_system_ca: bool,
3177}
3178
3179pub fn wrap_eval_code(source_code: &str) -> String {
3182 let json_escaped = serde_json::to_string(source_code).unwrap_or_else(|_| {
3184 format!(
3186 "\"{}\"",
3187 source_code.replace('\\', "\\\\").replace('"', "\\\"")
3188 )
3189 });
3190
3191 format!(
3192 r#"(
3193 globalThis.require = process.getBuiltinModule("module").createRequire(import.meta.url),
3194 process.getBuiltinModule("module").builtinModules
3195 .filter((m) => !/\/|crypto|process/.test(m))
3196 .forEach((m) => {{ globalThis[m] = process.getBuiltinModule(m); }}),
3197 process.getBuiltinModule("vm").runInThisContext({})
3198 )"#,
3199 json_escaped
3200 )
3201}
3202
3203const DENO_SUBCOMMANDS: &[&str] = &[
3205 "add",
3206 "bench",
3207 "cache",
3208 "check",
3209 "compile",
3210 "completions",
3211 "coverage",
3212 "doc",
3213 "eval",
3214 "fmt",
3215 "help",
3216 "info",
3217 "init",
3218 "install",
3219 "lint",
3220 "lsp",
3221 "publish",
3222 "repl",
3223 "run",
3224 "task",
3225 "tasks",
3226 "test",
3227 "types",
3228 "uninstall",
3229 "upgrade",
3230 "vendor",
3231];
3232
3233pub fn is_deno_subcommand(arg: &str) -> bool {
3235 DENO_SUBCOMMANDS.contains(&arg)
3236}
3237
3238pub fn translate_to_deno_args(
3240 parsed_args: ParseResult,
3241 options: &TranslateOptions,
3242) -> TranslatedArgs {
3243 let mut result = TranslatedArgs::default();
3244 let deno_args = &mut result.deno_args;
3245 let node_options = &mut result.node_options;
3246
3247 if let Some(first_arg) = parsed_args.remaining_args.first()
3250 && is_deno_subcommand(first_arg)
3251 {
3252 result.deno_args = parsed_args.remaining_args;
3254 return result;
3255 }
3256
3257 let opts = &parsed_args.options;
3258 let env_opts = &opts.per_isolate.per_env;
3259
3260 if opts.use_system_ca || opts.use_openssl_ca {
3262 result.use_system_ca = true;
3263 }
3264
3265 if opts.print_version {
3267 if options.use_node_subcommand {
3268 deno_args.push("node".to_string());
3269 }
3270 deno_args.push("--version".to_string());
3271 return result;
3272 }
3273
3274 if opts.print_v8_help {
3276 if options.use_node_subcommand {
3277 deno_args.push("node".to_string());
3278 deno_args.push("run".to_string());
3279 }
3280 deno_args.push("--v8-flags=--help".to_string());
3281 return result;
3282 }
3283
3284 if opts.print_help {
3286 if options.use_node_subcommand {
3287 deno_args.push("node".to_string());
3289 }
3290 deno_args.push("--help".to_string());
3291 return result;
3292 }
3293
3294 if opts.print_bash_completion {
3296 deno_args.push("completions".to_string());
3297 deno_args.push("bash".to_string());
3298 return result;
3299 }
3300
3301 if !opts.run.is_empty() {
3303 if options.use_node_subcommand {
3304 deno_args.push("node".to_string());
3305 }
3306 deno_args.push("task".to_string());
3307 deno_args.push(opts.run.clone());
3308 deno_args.extend(parsed_args.remaining_args);
3309 return result;
3310 }
3311
3312 let eval_string_for_print = if !env_opts.has_eval_string
3315 && env_opts.print_eval
3316 && !parsed_args.remaining_args.is_empty()
3317 {
3318 Some(parsed_args.remaining_args[0].clone())
3319 } else {
3320 None
3321 };
3322
3323 if env_opts.has_eval_string || eval_string_for_print.is_some() {
3324 if options.use_node_subcommand {
3325 deno_args.push("node".to_string());
3326 }
3327 deno_args.push("eval".to_string());
3328 if options.add_unstable_flags {
3331 deno_args.push("--unstable-node-globals".to_string());
3332 deno_args.push("--unstable-bare-node-builtins".to_string());
3333 deno_args.push("--unstable-detect-cjs".to_string());
3334 }
3335 if options.add_standalone_config {
3336 deno_args.push("--node-modules-dir=manual".to_string());
3337 deno_args.push("--no-config".to_string());
3338 }
3339
3340 if env_opts.has_env_file_string {
3341 if env_opts.env_file.is_empty() {
3342 deno_args.push("--env-file".to_string());
3343 } else {
3344 deno_args.push(format!("--env-file={}", env_opts.env_file));
3345 }
3346 }
3347
3348 if env_opts.print_eval {
3349 deno_args.push("--print".to_string());
3350 }
3351
3352 if !parsed_args.v8_args.is_empty() {
3353 deno_args.push(format!("--v8-flags={}", parsed_args.v8_args.join(",")));
3354 }
3355
3356 add_conditions(deno_args, env_opts);
3358 add_inspector_flags(deno_args, env_opts);
3359
3360 let raw_eval_code = eval_string_for_print
3362 .as_ref()
3363 .unwrap_or(&env_opts.eval_string);
3364 let eval_code = if options.wrap_eval_code {
3365 wrap_eval_code(raw_eval_code)
3366 } else {
3367 raw_eval_code.clone()
3368 };
3369 deno_args.push(eval_code);
3370
3371 if options.use_node_subcommand {
3372 deno_args.push("--".to_string());
3373 }
3374 let remaining_args = if eval_string_for_print.is_some() {
3376 parsed_args.remaining_args[1..].to_vec()
3377 } else {
3378 parsed_args.remaining_args
3379 };
3380 deno_args.extend(remaining_args);
3381 return result;
3382 }
3383
3384 if env_opts.test_runner {
3386 if options.use_node_subcommand {
3387 deno_args.push("node".to_string());
3388 }
3389 deno_args.push("test".to_string());
3390 deno_args.push("-A".to_string());
3391
3392 if options.add_unstable_flags {
3393 deno_args.push("--unstable-node-globals".to_string());
3394 deno_args.push("--unstable-bare-node-builtins".to_string());
3395 deno_args.push("--unstable-detect-cjs".to_string());
3396 }
3397 if options.add_standalone_config {
3398 deno_args.push("--node-modules-dir=manual".to_string());
3399 deno_args.push("--no-config".to_string());
3400 }
3401
3402 add_common_flags(deno_args, &parsed_args, env_opts);
3403 deno_args.extend(parsed_args.remaining_args);
3404 return result;
3405 }
3406
3407 if parsed_args.remaining_args.is_empty() || env_opts.force_repl {
3409 if options.use_node_subcommand {
3410 deno_args.push("node".to_string());
3411 deno_args.push("repl".to_string());
3412 deno_args.push("-A".to_string());
3413
3414 if !parsed_args.v8_args.is_empty() {
3415 deno_args.push(format!("--v8-flags={}", parsed_args.v8_args.join(",")));
3416 }
3417
3418 add_conditions(deno_args, env_opts);
3419 add_inspector_flags(deno_args, env_opts);
3420
3421 deno_args.push("--".to_string());
3422 deno_args.extend(parsed_args.remaining_args);
3423 } else {
3424 if !parsed_args.v8_args.is_empty() {
3426 deno_args.push(format!("--v8-flags={}", parsed_args.v8_args.join(",")));
3427 }
3428 }
3429 return result;
3430 }
3431
3432 if options.use_node_subcommand {
3434 deno_args.push("node".to_string());
3435 }
3436 deno_args.push("run".to_string());
3437 deno_args.push("-A".to_string());
3438
3439 if options.add_unstable_flags {
3440 deno_args.push("--unstable-node-globals".to_string());
3441 deno_args.push("--unstable-bare-node-builtins".to_string());
3442 deno_args.push("--unstable-detect-cjs".to_string());
3443 }
3444 if options.add_standalone_config {
3445 deno_args.push("--node-modules-dir=manual".to_string());
3446 deno_args.push("--no-config".to_string());
3447 }
3448
3449 add_common_flags(deno_args, &parsed_args, env_opts);
3450
3451 if !env_opts.warnings {
3453 deno_args.push("--quiet".to_string());
3454 node_options.push("--no-warnings".to_string());
3455 }
3456
3457 if env_opts.pending_deprecation {
3459 node_options.push("--pending-deprecation".to_string());
3460 }
3461
3462 deno_args.extend(parsed_args.remaining_args);
3464
3465 result
3466}
3467
3468fn add_common_flags(
3469 deno_args: &mut Vec<String>,
3470 parsed_args: &ParseResult,
3471 env_opts: &EnvironmentOptions,
3472) {
3473 if env_opts.watch_mode {
3475 if env_opts.watch_mode_paths.is_empty() {
3476 deno_args.push("--watch".to_string());
3477 } else {
3478 deno_args.push(format!(
3479 "--watch={}",
3480 env_opts
3481 .watch_mode_paths
3482 .iter()
3483 .map(|p| p.replace(',', ",,"))
3484 .collect::<Vec<String>>()
3485 .join(",")
3486 ));
3487 }
3488 }
3489
3490 if env_opts.has_env_file_string {
3492 if env_opts.env_file.is_empty() {
3493 deno_args.push("--env-file".to_string());
3494 } else {
3495 deno_args.push(format!("--env-file={}", env_opts.env_file));
3496 }
3497 }
3498
3499 if !parsed_args.v8_args.is_empty() {
3501 deno_args.push(format!("--v8-flags={}", parsed_args.v8_args.join(",")));
3502 }
3503
3504 add_conditions(deno_args, env_opts);
3506
3507 add_inspector_flags(deno_args, env_opts);
3509}
3510
3511fn add_conditions(deno_args: &mut Vec<String>, env_opts: &EnvironmentOptions) {
3512 if !env_opts.conditions.is_empty() {
3513 for condition in &env_opts.conditions {
3514 deno_args.push(format!("--conditions={}", condition));
3515 }
3516 }
3517}
3518
3519fn add_inspector_flags(
3520 deno_args: &mut Vec<String>,
3521 env_opts: &EnvironmentOptions,
3522) {
3523 if env_opts.debug_options.inspector_enabled {
3524 let arg = if env_opts.debug_options.break_first_line {
3525 "--inspect-brk"
3526 } else if env_opts.debug_options.inspect_wait {
3527 "--inspect-wait"
3528 } else {
3529 "--inspect"
3530 };
3531 deno_args.push(format!(
3532 "{}={}:{}",
3533 arg,
3534 env_opts.debug_options.host_port.host,
3535 env_opts.debug_options.host_port.port
3536 ));
3537 deno_args.push(format!(
3538 "--inspect-publish-uid={}",
3539 env_opts.debug_options.inspect_publish_uid_string
3540 ));
3541 }
3542}
3543
3544#[cfg(test)]
3545mod tests {
3546 use super::*;
3547
3548 macro_rules! svec {
3550 ($($x:expr),* $(,)?) => {
3551 vec![$($x.to_string()),*]
3552 };
3553 }
3554
3555 #[test]
3556 fn test_basic_parsing() {
3557 let result = parse_args(svec!["--version"]).unwrap();
3558 assert!(result.options.print_version);
3559 }
3560
3561 #[test]
3562 fn test_help_parsing() {
3563 let result = parse_args(svec!["--help"]).unwrap();
3564 assert!(result.options.print_help);
3565 }
3566
3567 #[test]
3568 fn test_debug_options() {
3569 let result = parse_args(svec!["--inspect"]).unwrap();
3570 assert!(
3571 result
3572 .options
3573 .per_isolate
3574 .per_env
3575 .debug_options
3576 .inspector_enabled
3577 );
3578 }
3579
3580 #[test]
3581 fn test_string_option() {
3582 let result = parse_args(svec!["--title", "myapp"]).unwrap();
3583 assert_eq!(result.options.title, "myapp");
3584 }
3585
3586 #[test]
3587 fn test_boolean_negation() {
3588 let result = parse_args(svec!["--no-warnings"]).unwrap();
3589 assert!(!result.options.per_isolate.per_env.warnings);
3590 }
3591
3592 #[test]
3593 fn test_alias_expansion() {
3594 let result = parse_args(svec!["-v"]).unwrap();
3595 assert!(result.options.print_version);
3596 }
3597
3598 #[test]
3599 fn test_node_options_parsing() {
3600 let env_args =
3601 parse_node_options_env_var("--inspect --title \"my app\"").unwrap();
3602 assert_eq!(env_args, vec!["--inspect", "--title", "my app"]);
3603 }
3604
3605 #[test]
3606 fn test_host_port_parsing() {
3607 let result = parse_args(svec!["--inspect-port", "127.0.0.1:9229"]).unwrap();
3608 assert_eq!(
3609 result
3610 .options
3611 .per_isolate
3612 .per_env
3613 .debug_options
3614 .host_port
3615 .host,
3616 "127.0.0.1"
3617 );
3618 assert_eq!(
3619 result
3620 .options
3621 .per_isolate
3622 .per_env
3623 .debug_options
3624 .host_port
3625 .port,
3626 9229
3627 );
3628 }
3629
3630 #[test]
3632 fn test_check_eval_incompatible() {
3633 let result = parse_args(svec!["--check", "--eval", "console.log(42)"]);
3634 assert!(result.is_err());
3635 let errors = result.unwrap_err();
3636 assert!(
3637 errors
3638 .iter()
3639 .any(|e| e.contains("either --check or --eval can be used, not both"))
3640 );
3641 }
3642
3643 #[test]
3644 fn test_test_check_incompatible() {
3645 let result = parse_args(svec!["--test", "--check"]);
3646 assert!(result.is_err());
3647 let errors = result.unwrap_err();
3648 assert!(
3649 errors
3650 .iter()
3651 .any(|e| e.contains("either --test or --check can be used, not both"))
3652 );
3653 }
3654
3655 #[test]
3656 fn test_test_eval_incompatible() {
3657 let result = parse_args(svec!["--test", "--eval", "console.log(42)"]);
3658 assert!(result.is_err());
3659 let errors = result.unwrap_err();
3660 assert!(
3661 errors
3662 .iter()
3663 .any(|e| e.contains("either --test or --eval can be used, not both"))
3664 );
3665 }
3666
3667 #[test]
3668 fn test_test_interactive_incompatible() {
3669 let result = parse_args(svec!["--test", "--interactive"]);
3670 assert!(result.is_err());
3671 let errors = result.unwrap_err();
3672 assert!(errors.iter().any(|e| {
3673 e.contains("either --test or --interactive can be used, not both")
3674 }));
3675 }
3676
3677 #[test]
3678 fn test_test_watch_path_incompatible() {
3679 let result = parse_args(svec!["--test", "--watch-path", "."]);
3680 assert!(result.is_err());
3681 let errors = result.unwrap_err();
3682 assert!(errors.iter().any(|e| {
3683 e.contains("--watch-path cannot be used in combination with --test")
3684 }));
3685 }
3686
3687 #[test]
3688 fn test_watch_check_incompatible() {
3689 let result = parse_args(svec!["--watch", "--check"]);
3690 assert!(result.is_err());
3691 let errors = result.unwrap_err();
3692 assert!(
3693 errors
3694 .iter()
3695 .any(|e| e.contains("either --watch or --check can be used, not both"))
3696 );
3697 }
3698
3699 #[test]
3700 fn test_watch_eval_incompatible() {
3701 let result = parse_args(svec!["--watch", "--eval", "console.log(42)"]);
3702 assert!(result.is_err());
3703 let errors = result.unwrap_err();
3704 assert!(
3705 errors
3706 .iter()
3707 .any(|e| e.contains("either --watch or --eval can be used, not both"))
3708 );
3709 }
3710
3711 #[test]
3712 fn test_watch_interactive_incompatible() {
3713 let result = parse_args(svec!["--watch", "--interactive"]);
3714 assert!(result.is_err());
3715 let errors = result.unwrap_err();
3716 assert!(errors.iter().any(|e| {
3717 e.contains("either --watch or --interactive can be used, not both")
3718 }));
3719 }
3720
3721 #[test]
3722 fn test_watch_test_force_exit_incompatible() {
3723 let result = parse_args(svec!["--watch", "--test-force-exit"]);
3724 assert!(result.is_err());
3725 let errors = result.unwrap_err();
3726 assert!(errors.iter().any(|e| {
3727 e.contains("either --watch or --test-force-exit can be used, not both")
3728 }));
3729 }
3730
3731 #[test]
3732 fn test_tls_min_max_incompatible() {
3733 let result = parse_args(svec!["--tls-min-v1.3", "--tls-max-v1.2"]);
3734 assert!(result.is_err());
3735 let errors = result.unwrap_err();
3736 assert!(errors.iter().any(|e| e.contains(
3737 "either --tls-min-v1.3 or --tls-max-v1.2 can be used, not both"
3738 )));
3739 }
3740
3741 #[test]
3742 fn test_openssl_ca_bundled_ca_incompatible() {
3743 let result = parse_args(svec!["--use-openssl-ca", "--use-bundled-ca"]);
3744 assert!(result.is_err());
3745 let errors = result.unwrap_err();
3746 assert!(errors.iter().any(|e| {
3747 e.contains(
3748 "either --use-openssl-ca or --use-bundled-ca can be used, not both",
3749 )
3750 }));
3751 }
3752
3753 #[test]
3754 fn test_cpu_prof_name_without_cpu_prof() {
3755 let result = parse_args(svec!["--cpu-prof-name", "profile.log"]);
3756 assert!(result.is_err());
3757 let errors = result.unwrap_err();
3758 assert!(
3759 errors
3760 .iter()
3761 .any(|e| e.contains("--cpu-prof-name must be used with --cpu-prof"))
3762 );
3763 }
3764
3765 #[test]
3766 fn test_cpu_prof_dir_without_cpu_prof() {
3767 let result = parse_args(svec!["--cpu-prof-dir", "/tmp"]);
3768 assert!(result.is_err());
3769 let errors = result.unwrap_err();
3770 assert!(
3771 errors
3772 .iter()
3773 .any(|e| e.contains("--cpu-prof-dir must be used with --cpu-prof"))
3774 );
3775 }
3776
3777 #[test]
3778 fn test_cpu_prof_interval_without_cpu_prof() {
3779 let result = parse_args(svec!["--cpu-prof-interval", "500"]);
3780 assert!(result.is_err());
3781 let errors = result.unwrap_err();
3782 assert!(
3783 errors
3784 .iter()
3785 .any(|e| e.contains("--cpu-prof-interval must be used with --cpu-prof"))
3786 );
3787 }
3788
3789 #[test]
3790 fn test_heap_prof_name_without_heap_prof() {
3791 let result = parse_args(svec!["--heap-prof-name", "heap.log"]);
3792 assert!(result.is_err());
3793 let errors = result.unwrap_err();
3794 assert!(
3795 errors
3796 .iter()
3797 .any(|e| e.contains("--heap-prof-name must be used with --heap-prof"))
3798 );
3799 }
3800
3801 #[test]
3802 fn test_heap_prof_dir_without_heap_prof() {
3803 let result = parse_args(svec!["--heap-prof-dir", "/tmp"]);
3804 assert!(result.is_err());
3805 let errors = result.unwrap_err();
3806 assert!(
3807 errors
3808 .iter()
3809 .any(|e| e.contains("--heap-prof-dir must be used with --heap-prof"))
3810 );
3811 }
3812
3813 #[test]
3814 fn test_heap_prof_interval_without_heap_prof() {
3815 let result = parse_args(svec!["--heap-prof-interval", "1024"]);
3816 assert!(result.is_err());
3817 let errors = result.unwrap_err();
3818 assert!(errors.iter().any(|e| {
3819 e.contains("--heap-prof-interval must be used with --heap-prof")
3820 }));
3821 }
3822
3823 #[test]
3824 fn test_invalid_input_type() {
3825 let result = parse_args(svec!["--input-type", "invalid"]);
3826 assert!(result.is_err());
3827 let errors = result.unwrap_err();
3828 assert!(errors.iter().any(|e| e.contains("--input-type must be \"module\", \"commonjs\", \"module-typescript\" or \"commonjs-typescript\"")));
3829 }
3830
3831 #[test]
3832 fn test_invalid_unhandled_rejections() {
3833 let result = parse_args(svec!["--unhandled-rejections", "invalid"]);
3834 assert!(result.is_err());
3835 let errors = result.unwrap_err();
3836 assert!(
3837 errors
3838 .iter()
3839 .any(|e| e.contains("invalid value for --unhandled-rejections"))
3840 );
3841 }
3842
3843 #[test]
3844 fn test_invalid_trace_require_module() {
3845 let result = parse_args(svec!["--trace-require-module", "invalid"]);
3846 assert!(result.is_err());
3847 let errors = result.unwrap_err();
3848 assert!(
3849 errors
3850 .iter()
3851 .any(|e| e.contains("invalid value for --trace-require-module"))
3852 );
3853 }
3854
3855 #[test]
3856 fn test_invalid_test_isolation() {
3857 let result = parse_args(svec!["--test", "--test-isolation", "invalid"]);
3858 assert!(result.is_err());
3859 let errors = result.unwrap_err();
3860 assert!(
3861 errors
3862 .iter()
3863 .any(|e| e.contains("invalid value for --test-isolation"))
3864 );
3865 }
3866
3867 #[test]
3868 fn test_invalid_use_largepages() {
3869 let result = parse_args(svec!["--use-largepages", "invalid"]);
3870 assert!(result.is_err());
3871 let errors = result.unwrap_err();
3872 assert!(
3873 errors
3874 .iter()
3875 .any(|e| e.contains("invalid value for --use-largepages"))
3876 );
3877 }
3878
3879 #[test]
3880 fn test_negative_heapsnapshot_near_heap_limit() {
3881 let result = parse_args(svec!["--heapsnapshot-near-heap-limit", "-1"]);
3882 assert!(result.is_err());
3883 let errors = result.unwrap_err();
3884 assert!(errors.iter().any(|e| {
3885 e.contains("--heapsnapshot-near-heap-limit must not be negative")
3886 }));
3887 }
3888
3889 #[test]
3890 fn test_secure_heap_not_power_of_two() {
3891 let result = parse_args(svec!["--secure-heap", "3"]);
3892 assert!(result.is_err());
3893 let errors = result.unwrap_err();
3894 assert!(
3895 errors
3896 .iter()
3897 .any(|e| e.contains("--secure-heap must be a power of 2"))
3898 );
3899 }
3900
3901 #[test]
3902 fn test_secure_heap_min_not_power_of_two() {
3903 let result =
3904 parse_args(svec!["--secure-heap", "4", "--secure-heap-min", "3"]);
3905 assert!(result.is_err());
3906 let errors = result.unwrap_err();
3907 assert!(
3908 errors
3909 .iter()
3910 .any(|e| e.contains("--secure-heap-min must be a power of 2"))
3911 );
3912 }
3913
3914 #[test]
3915 fn test_deprecated_debug_options() {
3916 let result = parse_args(svec!["--debug"]);
3917 assert!(result.is_err());
3918 let errors = result.unwrap_err();
3919 assert!(errors.iter().any(|e| e.contains("[DEP0062]: `node --debug` and `node --debug-brk` are invalid. Please use `node --inspect` and `node --inspect-brk` instead.")));
3920 }
3921
3922 #[test]
3923 fn test_deprecated_debug_brk_options() {
3924 let result = parse_args(svec!["--debug-brk"]);
3925 assert!(result.is_err());
3926 let errors = result.unwrap_err();
3927 assert!(errors.iter().any(|e| e.contains("[DEP0062]: `node --debug` and `node --debug-brk` are invalid. Please use `node --inspect` and `node --inspect-brk` instead.")));
3928 }
3929
3930 #[test]
3931 fn test_invalid_inspect_publish_uid() {
3932 let result = parse_args(svec!["--inspect-publish-uid", "invalid"]);
3933 assert!(result.is_err());
3934 let errors = result.unwrap_err();
3935 assert!(errors.iter().any(|e| {
3936 e.contains("--inspect-publish-uid destination can be stderr or http")
3937 }));
3938 }
3939
3940 #[test]
3941 fn test_watch_requires_file_when_not_test() {
3942 let result = parse_args(svec!["--watch"]);
3943 assert!(result.is_err());
3944 let errors = result.unwrap_err();
3945 assert!(
3946 errors
3947 .iter()
3948 .any(|e| e.contains("--watch requires specifying a file"))
3949 );
3950 }
3951
3952 #[test]
3953 fn test_invalid_negation_for_non_boolean() {
3954 let result = parse_args(svec!["--no-title"]);
3955 assert!(result.is_err());
3956 let errors = result.unwrap_err();
3957 assert!(errors.iter().any(|e| {
3958 e.contains("is an invalid negation because it is not a boolean option")
3959 }));
3960 }
3961
3962 #[test]
3963 fn test_option_requires_argument() {
3964 let result = parse_args(svec!["--title"]);
3965 assert!(result.is_err());
3966 let errors = result.unwrap_err();
3967 assert!(
3968 errors
3969 .iter()
3970 .any(|e| e.contains("--title requires an argument"))
3971 );
3972 }
3973
3974 #[test]
3975 fn test_option_with_empty_equals_value() {
3976 let result = parse_args(svec!["--title="]);
3977 assert!(result.is_err());
3978 let errors = result.unwrap_err();
3979 assert!(
3980 errors
3981 .iter()
3982 .any(|e| e.contains("--title= requires an argument"))
3983 );
3984 }
3985
3986 #[test]
3987 fn test_option_with_dash_as_value() {
3988 let result = parse_args(svec!["--title", "-"]);
3989 assert!(result.is_err());
3990 let errors = result.unwrap_err();
3991 assert!(
3992 errors
3993 .iter()
3994 .any(|e| e.contains("--title requires an argument"))
3995 );
3996 }
3997
3998 #[test]
3999 fn test_invalid_port_range() {
4000 let result = parse_args(svec!["--inspect-port", "99999"]);
4001 assert!(result.is_err());
4002 let errors = result.unwrap_err();
4003 assert!(
4004 errors
4005 .iter()
4006 .any(|e| e.contains("must be 0 or in range 1024 to 65535"))
4007 );
4008 }
4009
4010 #[test]
4011 fn test_invalid_port_low() {
4012 let result = parse_args(svec!["--inspect-port", "500"]);
4013 assert!(result.is_err());
4014 let errors = result.unwrap_err();
4015 assert!(
4016 errors
4017 .iter()
4018 .any(|e| e.contains("must be 0 or in range 1024 to 65535"))
4019 );
4020 }
4021
4022 #[test]
4023 fn test_escaped_dash_in_value() {
4024 let result = parse_args(svec!["--title", "\\-mytitle"]).unwrap();
4025 assert_eq!(result.options.title, "-mytitle");
4026 }
4027
4028 #[test]
4029 fn test_compatible_profiling_options() {
4030 let result = parse_args(svec![
4031 "--cpu-prof",
4032 "--cpu-prof-name",
4033 "profile.log",
4034 "--cpu-prof-dir",
4035 "/tmp",
4036 "--cpu-prof-interval",
4037 "500"
4038 ])
4039 .unwrap();
4040 assert!(result.options.per_isolate.per_env.cpu_prof);
4041 assert_eq!(
4042 result.options.per_isolate.per_env.cpu_prof_name,
4043 "profile.log"
4044 );
4045 assert_eq!(result.options.per_isolate.per_env.cpu_prof_dir, "/tmp");
4046 assert_eq!(result.options.per_isolate.per_env.cpu_prof_interval, 500);
4047 }
4048
4049 #[test]
4050 fn test_compatible_heap_profiling_options() {
4051 let result = parse_args(svec![
4052 "--heap-prof",
4053 "--heap-prof-name",
4054 "heap.log",
4055 "--heap-prof-dir",
4056 "/tmp",
4057 "--heap-prof-interval",
4058 "1024"
4059 ])
4060 .unwrap();
4061 assert!(result.options.per_isolate.per_env.heap_prof);
4062 assert_eq!(
4063 result.options.per_isolate.per_env.heap_prof_name,
4064 "heap.log"
4065 );
4066 assert_eq!(result.options.per_isolate.per_env.heap_prof_dir, "/tmp");
4067 assert_eq!(result.options.per_isolate.per_env.heap_prof_interval, 1024);
4068 }
4069
4070 #[test]
4071 fn test_diagnostic_dir_used_for_prof_dirs() {
4072 let result = parse_args(svec![
4073 "--cpu-prof",
4074 "--heap-prof",
4075 "--diagnostic-dir",
4076 "/tmp/diag"
4077 ])
4078 .unwrap();
4079 assert_eq!(result.options.per_isolate.per_env.cpu_prof_dir, "/tmp/diag");
4080 assert_eq!(
4081 result.options.per_isolate.per_env.heap_prof_dir,
4082 "/tmp/diag"
4083 );
4084 }
4085
4086 #[test]
4087 fn test_valid_input_types() {
4088 for input_type in &[
4089 "commonjs",
4090 "module",
4091 "commonjs-typescript",
4092 "module-typescript",
4093 ] {
4094 let result = parse_args(svec!["--input-type", input_type]).unwrap();
4095 assert_eq!(result.options.per_isolate.per_env.input_type, *input_type);
4096 }
4097 }
4098
4099 #[test]
4100 fn test_valid_unhandled_rejections() {
4101 for rejection_type in
4102 &["warn-with-error-code", "throw", "strict", "warn", "none"]
4103 {
4104 let result =
4105 parse_args(svec!["--unhandled-rejections", rejection_type]).unwrap();
4106 assert_eq!(
4107 result.options.per_isolate.per_env.unhandled_rejections,
4108 *rejection_type
4109 );
4110 }
4111 }
4112
4113 #[test]
4114 fn test_valid_trace_require_module() {
4115 for trace_type in &["all", "no-node-modules"] {
4116 let result =
4117 parse_args(svec!["--trace-require-module", trace_type]).unwrap();
4118 assert_eq!(
4119 result.options.per_isolate.per_env.trace_require_module,
4120 *trace_type
4121 );
4122 }
4123 }
4124
4125 #[test]
4126 fn test_valid_test_isolation() {
4127 for isolation_type in &["process", "none"] {
4128 let result =
4129 parse_args(svec!["--test", "--test-isolation", isolation_type])
4130 .unwrap();
4131 assert_eq!(
4132 result.options.per_isolate.per_env.test_isolation,
4133 *isolation_type
4134 );
4135 }
4136 }
4137
4138 #[test]
4139 fn test_valid_use_largepages() {
4140 for largepages_type in &["off", "on", "silent"] {
4141 let result =
4142 parse_args(svec!["--use-largepages", largepages_type]).unwrap();
4143 assert_eq!(result.options.use_largepages, *largepages_type);
4144 }
4145 }
4146
4147 #[test]
4148 fn test_valid_inspect_publish_uid() {
4149 let result =
4150 parse_args(svec!["--inspect-publish-uid", "stderr,http"]).unwrap();
4151 assert!(
4152 result
4153 .options
4154 .per_isolate
4155 .per_env
4156 .debug_options
4157 .inspect_publish_uid
4158 .console
4159 );
4160 assert!(
4161 result
4162 .options
4163 .per_isolate
4164 .per_env
4165 .debug_options
4166 .inspect_publish_uid
4167 .http
4168 );
4169 }
4170
4171 #[test]
4172 fn test_valid_secure_heap_power_of_two() {
4173 let result =
4174 parse_args(svec!["--secure-heap", "4", "--secure-heap-min", "2"])
4175 .unwrap();
4176 assert_eq!(result.options.secure_heap, 4);
4177 assert_eq!(result.options.secure_heap_min, 2);
4178 }
4179
4180 #[test]
4181 fn test_implications_work() {
4182 let result = parse_args(svec!["--inspect-brk"]).unwrap();
4184 assert!(
4185 result
4186 .options
4187 .per_isolate
4188 .per_env
4189 .debug_options
4190 .break_first_line
4191 );
4192 assert!(
4193 result
4194 .options
4195 .per_isolate
4196 .per_env
4197 .debug_options
4198 .inspector_enabled
4199 );
4200 }
4201
4202 #[test]
4203 fn test_alias_expansion_works() {
4204 let result = parse_args(svec!["-v"]).unwrap();
4206 assert!(result.options.print_version);
4207
4208 let result = parse_args(svec!["-pe", "console.log(42)"]).unwrap();
4210 assert!(result.options.per_isolate.per_env.print_eval);
4211 assert!(result.options.per_isolate.per_env.has_eval_string);
4212 assert_eq!(
4213 result.options.per_isolate.per_env.eval_string,
4214 "console.log(42)"
4215 );
4216 }
4217
4218 #[test]
4219 fn test_underscore_normalization() {
4220 let result = parse_args(svec!["--zero_fill_buffers"]).unwrap();
4222 assert!(result.options.zero_fill_all_buffers);
4223 }
4224
4225 #[test]
4228 fn test_prof_process_alias_does_not_infinite_loop() {
4229 let result = parse_args(svec!["--prof-process", "somefile.log"]).unwrap();
4231 assert!(result.options.per_isolate.per_env.prof_process);
4232 assert_eq!(result.remaining_args, svec!["somefile.log"]);
4234 }
4235
4236 #[test]
4237 fn test_alias_short_c_to_check() {
4238 let result = parse_args(svec!["-c", "script.js"]).unwrap();
4239 assert!(result.options.per_isolate.per_env.syntax_check_only);
4240 }
4241
4242 #[test]
4243 fn test_alias_short_e_to_eval() {
4244 let result = parse_args(svec!["-e", "console.log(1)"]).unwrap();
4245 assert!(result.options.per_isolate.per_env.has_eval_string);
4246 assert_eq!(
4247 result.options.per_isolate.per_env.eval_string,
4248 "console.log(1)"
4249 );
4250 }
4251
4252 #[test]
4253 fn test_alias_short_p_to_print() {
4254 let result = parse_args(svec!["-p", "42"]).unwrap();
4258 assert!(result.options.per_isolate.per_env.print_eval);
4259 assert_eq!(result.remaining_args, svec!["42"]);
4260 }
4261
4262 #[test]
4263 fn test_alias_short_r_to_require() {
4264 let result = parse_args(svec!["-r", "dotenv/config", "script.js"]).unwrap();
4265 assert_eq!(
4266 result.options.per_isolate.per_env.preload_cjs_modules,
4267 svec!["dotenv/config"]
4268 );
4269 }
4270
4271 #[test]
4272 fn test_alias_short_i_to_interactive() {
4273 let result = parse_args(svec!["-i"]).unwrap();
4274 assert!(result.options.per_isolate.per_env.force_repl);
4275 }
4276
4277 #[test]
4278 fn test_alias_short_h_to_help() {
4279 let result = parse_args(svec!["-h"]).unwrap();
4280 assert!(result.options.print_help);
4281 }
4282
4283 #[test]
4284 fn test_alias_loader_to_experimental_loader() {
4285 let result =
4286 parse_args(svec!["--loader", "./my-loader.js", "script.js"]).unwrap();
4287 assert_eq!(
4288 result.options.per_isolate.per_env.userland_loaders,
4289 svec!["./my-loader.js"]
4290 );
4291 }
4292
4293 #[test]
4294 fn test_alias_conditions_short() {
4295 let result = parse_args(svec!["-C", "development", "script.js"]).unwrap();
4296 assert_eq!(
4297 result.options.per_isolate.per_env.conditions,
4298 svec!["development"]
4299 );
4300 }
4301
4302 #[test]
4305 fn test_v8_option_max_old_space_size() {
4306 let result =
4307 parse_args(svec!["--max-old-space-size=4096", "script.js"]).unwrap();
4308 assert!(
4309 result
4310 .v8_args
4311 .contains(&"--max-old-space-size=4096".to_string())
4312 );
4313 }
4314
4315 #[test]
4316 fn test_v8_option_max_semi_space_size() {
4317 let result =
4318 parse_args(svec!["--max-semi-space-size=64", "script.js"]).unwrap();
4319 assert!(
4320 result
4321 .v8_args
4322 .contains(&"--max-semi-space-size=64".to_string())
4323 );
4324 }
4325
4326 #[test]
4327 fn test_v8_option_expose_gc() {
4328 let result = parse_args(svec!["--expose-gc", "script.js"]).unwrap();
4329 assert!(result.v8_args.contains(&"--expose-gc".to_string()));
4330 }
4331
4332 #[test]
4333 fn test_multiple_v8_options() {
4334 let result = parse_args(svec![
4335 "--max-old-space-size=4096",
4336 "--expose-gc",
4337 "script.js"
4338 ])
4339 .unwrap();
4340 assert!(
4341 result
4342 .v8_args
4343 .contains(&"--max-old-space-size=4096".to_string())
4344 );
4345 assert!(result.v8_args.contains(&"--expose-gc".to_string()));
4346 }
4347
4348 #[test]
4351 fn test_script_with_args() {
4352 let result =
4353 parse_args(svec!["script.js", "arg1", "arg2", "--flag"]).unwrap();
4354 assert_eq!(
4355 result.remaining_args,
4356 svec!["script.js", "arg1", "arg2", "--flag"]
4357 );
4358 }
4359
4360 #[test]
4361 fn test_options_before_script() {
4362 let result =
4363 parse_args(svec!["--no-warnings", "script.js", "--my-arg"]).unwrap();
4364 assert!(!result.options.per_isolate.per_env.warnings);
4365 assert_eq!(result.remaining_args, svec!["script.js", "--my-arg"]);
4366 }
4367
4368 #[test]
4369 fn test_double_dash_stops_option_parsing() {
4370 let result = parse_args(svec!["--", "--version"]).unwrap();
4371 assert!(!result.options.print_version);
4373 assert_eq!(result.remaining_args, svec!["--version"]);
4374 }
4375
4376 #[test]
4377 fn test_double_dash_with_script_and_args() {
4378 let result =
4379 parse_args(svec!["--no-warnings", "--", "script.js", "--help"]).unwrap();
4380 assert!(!result.options.per_isolate.per_env.warnings);
4381 assert_eq!(result.remaining_args, svec!["script.js", "--help"]);
4382 }
4383
4384 #[test]
4387 fn test_run_option() {
4388 let result = parse_args(svec!["--run", "build"]).unwrap();
4389 assert_eq!(result.options.run, "build");
4390 }
4391
4392 #[test]
4393 fn test_eval_option_with_code() {
4394 let result = parse_args(svec!["--eval", "console.log('hello')"]).unwrap();
4395 assert!(result.options.per_isolate.per_env.has_eval_string);
4396 assert_eq!(
4397 result.options.per_isolate.per_env.eval_string,
4398 "console.log('hello')"
4399 );
4400 }
4401
4402 #[test]
4403 fn test_print_eval_option() {
4404 let result = parse_args(svec!["-pe", "1 + 1"]).unwrap();
4406 assert!(result.options.per_isolate.per_env.print_eval);
4407 assert!(result.options.per_isolate.per_env.has_eval_string);
4408 assert_eq!(result.options.per_isolate.per_env.eval_string, "1 + 1");
4409 }
4410
4411 #[test]
4412 fn test_test_runner_option() {
4413 let result = parse_args(svec!["--test"]).unwrap();
4414 assert!(result.options.per_isolate.per_env.test_runner);
4415 }
4416
4417 #[test]
4418 fn test_test_with_files() {
4419 let result = parse_args(svec!["--test", "test/*.js"]).unwrap();
4420 assert!(result.options.per_isolate.per_env.test_runner);
4421 assert_eq!(result.remaining_args, svec!["test/*.js"]);
4422 }
4423
4424 #[test]
4425 fn test_test_timeout_option() {
4426 let result = parse_args(svec!["--test", "--test-timeout", "5000"]).unwrap();
4427 assert!(result.options.per_isolate.per_env.test_runner);
4428 assert_eq!(result.options.per_isolate.per_env.test_runner_timeout, 5000);
4429 }
4430
4431 #[test]
4432 fn test_test_concurrency_option() {
4433 let result =
4434 parse_args(svec!["--test", "--test-concurrency", "4"]).unwrap();
4435 assert!(result.options.per_isolate.per_env.test_runner);
4436 assert_eq!(
4437 result.options.per_isolate.per_env.test_runner_concurrency,
4438 4
4439 );
4440 }
4441
4442 #[test]
4443 fn test_test_name_pattern_option() {
4444 let result =
4445 parse_args(svec!["--test", "--test-name-pattern", "should.*work"])
4446 .unwrap();
4447 assert!(result.options.per_isolate.per_env.test_runner);
4448 assert_eq!(
4449 result.options.per_isolate.per_env.test_name_pattern,
4450 svec!["should.*work"]
4451 );
4452 }
4453
4454 #[test]
4455 fn test_test_skip_pattern_option() {
4456 let result =
4457 parse_args(svec!["--test", "--test-skip-pattern", "slow"]).unwrap();
4458 assert!(result.options.per_isolate.per_env.test_runner);
4459 assert_eq!(
4460 result.options.per_isolate.per_env.test_skip_pattern,
4461 svec!["slow"]
4462 );
4463 }
4464
4465 #[test]
4468 fn test_multiple_conditions() {
4469 let result = parse_args(svec![
4470 "--conditions",
4471 "development",
4472 "--conditions",
4473 "browser",
4474 "script.js"
4475 ])
4476 .unwrap();
4477 assert_eq!(
4478 result.options.per_isolate.per_env.conditions,
4479 svec!["development", "browser"]
4480 );
4481 }
4482
4483 #[test]
4484 fn test_multiple_require() {
4485 let result = parse_args(svec![
4486 "--require",
4487 "dotenv/config",
4488 "--require",
4489 "./setup.js",
4490 "script.js"
4491 ])
4492 .unwrap();
4493 assert_eq!(
4494 result.options.per_isolate.per_env.preload_cjs_modules,
4495 svec!["dotenv/config", "./setup.js"]
4496 );
4497 }
4498
4499 #[test]
4500 fn test_import_option() {
4501 let result =
4502 parse_args(svec!["--import", "./register.js", "script.js"]).unwrap();
4503 assert_eq!(
4504 result.options.per_isolate.per_env.preload_esm_modules,
4505 svec!["./register.js"]
4506 );
4507 }
4508
4509 #[test]
4510 fn test_multiple_import() {
4511 let result = parse_args(svec![
4512 "--import",
4513 "./a.js",
4514 "--import",
4515 "./b.js",
4516 "script.js"
4517 ])
4518 .unwrap();
4519 assert_eq!(
4520 result.options.per_isolate.per_env.preload_esm_modules,
4521 svec!["./a.js", "./b.js"]
4522 );
4523 }
4524
4525 #[test]
4528 fn test_watch_with_script() {
4529 let result = parse_args(svec!["--watch", "script.js"]).unwrap();
4530 assert!(result.options.per_isolate.per_env.watch_mode);
4531 assert_eq!(result.remaining_args, svec!["script.js"]);
4532 }
4533
4534 #[test]
4535 fn test_watch_with_test() {
4536 let result = parse_args(svec!["--test", "--watch"]).unwrap();
4537 assert!(result.options.per_isolate.per_env.test_runner);
4538 assert!(result.options.per_isolate.per_env.watch_mode);
4539 }
4540
4541 #[test]
4542 fn test_watch_path_option() {
4543 let result =
4544 parse_args(svec!["--watch", "--watch-path", "./src", "script.js"])
4545 .unwrap();
4546 assert!(result.options.per_isolate.per_env.watch_mode);
4547 assert_eq!(
4548 result.options.per_isolate.per_env.watch_mode_paths,
4549 svec!["./src"]
4550 );
4551 }
4552
4553 #[test]
4554 fn test_watch_preserve_output() {
4555 let result =
4556 parse_args(svec!["--watch", "--watch-preserve-output", "script.js"])
4557 .unwrap();
4558 assert!(result.options.per_isolate.per_env.watch_mode);
4559 assert!(
4560 result
4561 .options
4562 .per_isolate
4563 .per_env
4564 .watch_mode_preserve_output
4565 );
4566 }
4567
4568 #[test]
4571 fn test_node_options_with_escaped_quotes() {
4572 let env_args =
4573 parse_node_options_env_var("--title \"hello \\\"world\\\"\"").unwrap();
4574 assert_eq!(env_args, vec!["--title", "hello \"world\""]);
4575 }
4576
4577 #[test]
4578 fn test_node_options_with_backslash() {
4579 let env_args =
4580 parse_node_options_env_var("--title \"path\\\\to\\\\file\"").unwrap();
4581 assert_eq!(env_args, vec!["--title", "path\\to\\file"]);
4582 }
4583
4584 #[test]
4585 fn test_node_options_multiple_spaces() {
4586 let env_args =
4587 parse_node_options_env_var("--no-warnings --no-deprecation").unwrap();
4588 assert_eq!(env_args, vec!["--no-warnings", "--no-deprecation"]);
4589 }
4590
4591 #[test]
4592 fn test_node_options_unterminated_string_error() {
4593 let result = parse_node_options_env_var("--title \"unterminated");
4594 assert!(result.is_err());
4595 let errors = result.unwrap_err();
4596 assert!(errors.iter().any(|e| e.contains("unterminated string")));
4597 }
4598
4599 #[test]
4600 fn test_node_options_invalid_escape_error() {
4601 let result = parse_node_options_env_var("--title \"test\\");
4602 assert!(result.is_err());
4603 let errors = result.unwrap_err();
4604 assert!(errors.iter().any(|e| e.contains("invalid escape")));
4605 }
4606
4607 #[test]
4608 fn test_node_options_empty_string() {
4609 let env_args = parse_node_options_env_var("").unwrap();
4610 assert!(env_args.is_empty());
4611 }
4612
4613 #[test]
4614 fn test_node_options_only_spaces() {
4615 let env_args = parse_node_options_env_var(" ").unwrap();
4616 assert!(env_args.is_empty());
4617 }
4618
4619 #[test]
4622 fn test_inspect_brk_option() {
4623 let result = parse_args(svec!["--inspect-brk"]).unwrap();
4624 assert!(
4625 result
4626 .options
4627 .per_isolate
4628 .per_env
4629 .debug_options
4630 .inspector_enabled
4631 );
4632 assert!(
4633 result
4634 .options
4635 .per_isolate
4636 .per_env
4637 .debug_options
4638 .break_first_line
4639 );
4640 }
4641
4642 #[test]
4643 fn test_inspect_wait_option() {
4644 let result = parse_args(svec!["--inspect-wait"]).unwrap();
4645 assert!(
4646 result
4647 .options
4648 .per_isolate
4649 .per_env
4650 .debug_options
4651 .inspector_enabled
4652 );
4653 assert!(
4654 result
4655 .options
4656 .per_isolate
4657 .per_env
4658 .debug_options
4659 .inspect_wait
4660 );
4661 }
4662
4663 #[test]
4664 fn test_inspect_with_custom_port() {
4665 let result = parse_args(svec!["--inspect=9230"]).unwrap();
4666 assert!(
4667 result
4668 .options
4669 .per_isolate
4670 .per_env
4671 .debug_options
4672 .inspector_enabled
4673 );
4674 assert_eq!(
4675 result
4676 .options
4677 .per_isolate
4678 .per_env
4679 .debug_options
4680 .host_port
4681 .port,
4682 9230
4683 );
4684 }
4685
4686 #[test]
4687 fn test_inspect_with_host_and_port() {
4688 let result = parse_args(svec!["--inspect=0.0.0.0:9230"]).unwrap();
4689 assert!(
4690 result
4691 .options
4692 .per_isolate
4693 .per_env
4694 .debug_options
4695 .inspector_enabled
4696 );
4697 assert_eq!(
4698 result
4699 .options
4700 .per_isolate
4701 .per_env
4702 .debug_options
4703 .host_port
4704 .host,
4705 "0.0.0.0"
4706 );
4707 assert_eq!(
4708 result
4709 .options
4710 .per_isolate
4711 .per_env
4712 .debug_options
4713 .host_port
4714 .port,
4715 9230
4716 );
4717 }
4718
4719 #[test]
4720 fn test_inspect_port_zero() {
4721 let result = parse_args(svec!["--inspect-port", "0"]).unwrap();
4722 assert_eq!(
4723 result
4724 .options
4725 .per_isolate
4726 .per_env
4727 .debug_options
4728 .host_port
4729 .port,
4730 0
4731 );
4732 }
4733
4734 #[test]
4737 fn test_env_file_option() {
4738 let result = parse_args(svec!["--env-file", ".env", "script.js"]).unwrap();
4739 assert!(result.options.per_isolate.per_env.has_env_file_string);
4740 assert_eq!(result.options.per_isolate.per_env.env_file, ".env");
4741 }
4742
4743 #[test]
4744 fn test_env_file_if_exists_option() {
4745 let result =
4746 parse_args(svec!["--env-file-if-exists", ".env.local", "script.js"])
4747 .unwrap();
4748 assert!(result.options.per_isolate.per_env.has_env_file_string);
4749 assert_eq!(
4750 result.options.per_isolate.per_env.optional_env_file,
4751 ".env.local"
4752 );
4753 }
4754
4755 #[test]
4758 fn test_no_deprecation() {
4759 let result = parse_args(svec!["--no-deprecation"]).unwrap();
4760 assert!(!result.options.per_isolate.per_env.deprecation);
4761 }
4762
4763 #[test]
4764 fn test_throw_deprecation() {
4765 let result = parse_args(svec!["--throw-deprecation"]).unwrap();
4766 assert!(result.options.per_isolate.per_env.throw_deprecation);
4767 }
4768
4769 #[test]
4770 fn test_trace_deprecation() {
4771 let result = parse_args(svec!["--trace-deprecation"]).unwrap();
4772 assert!(result.options.per_isolate.per_env.trace_deprecation);
4773 }
4774
4775 #[test]
4776 fn test_pending_deprecation() {
4777 let result = parse_args(svec!["--pending-deprecation"]).unwrap();
4778 assert!(result.options.per_isolate.per_env.pending_deprecation);
4779 }
4780
4781 #[test]
4782 fn test_preserve_symlinks() {
4783 let result = parse_args(svec!["--preserve-symlinks"]).unwrap();
4784 assert!(result.options.per_isolate.per_env.preserve_symlinks);
4785 }
4786
4787 #[test]
4788 fn test_preserve_symlinks_main() {
4789 let result = parse_args(svec!["--preserve-symlinks-main"]).unwrap();
4790 assert!(result.options.per_isolate.per_env.preserve_symlinks_main);
4791 }
4792
4793 #[test]
4794 fn test_no_extra_info_on_fatal_exception() {
4795 let result =
4796 parse_args(svec!["--no-extra-info-on-fatal-exception"]).unwrap();
4797 assert!(
4798 !result
4799 .options
4800 .per_isolate
4801 .per_env
4802 .extra_info_on_fatal_exception
4803 );
4804 }
4805
4806 #[test]
4807 fn test_enable_source_maps() {
4808 let result = parse_args(svec!["--enable-source-maps"]).unwrap();
4809 assert!(result.options.per_isolate.per_env.enable_source_maps);
4810 }
4811
4812 #[test]
4813 fn test_experimental_strip_types() {
4814 let result = parse_args(svec!["--experimental-strip-types"]).unwrap();
4815 assert!(result.options.per_isolate.per_env.experimental_strip_types);
4816 }
4817
4818 #[test]
4821 fn test_option_with_equals() {
4822 let result = parse_args(svec!["--title=myapp"]).unwrap();
4823 assert_eq!(result.options.title, "myapp");
4824 }
4825
4826 #[test]
4827 fn test_option_with_equals_and_spaces_in_value() {
4828 let result = parse_args(svec!["--title=my app"]).unwrap();
4830 assert_eq!(result.options.title, "my app");
4831 }
4832
4833 #[test]
4834 fn test_boolean_option_positive() {
4835 let result = parse_args(svec!["--warnings"]).unwrap();
4837 assert!(result.options.per_isolate.per_env.warnings);
4838 }
4839
4840 #[test]
4841 fn test_boolean_option_negative() {
4842 let result = parse_args(svec!["--no-warnings"]).unwrap();
4844 assert!(!result.options.per_isolate.per_env.warnings);
4845 }
4846
4847 #[test]
4848 fn test_boolean_option_double_negation() {
4849 let result = parse_args(svec!["--no-deprecation"]).unwrap();
4851 assert!(!result.options.per_isolate.per_env.deprecation);
4852 }
4853
4854 #[test]
4857 fn test_unknown_option_passed_to_v8() {
4858 let result =
4860 parse_args(svec!["--unknown-option-that-does-not-exist", "script.js"])
4861 .unwrap();
4862 assert!(
4863 result
4864 .v8_args
4865 .contains(&"--unknown-option-that-does-not-exist".to_string())
4866 );
4867 }
4868
4869 #[test]
4872 fn test_stack_trace_limit() {
4873 let result = parse_args(svec!["--stack-trace-limit", "50"]).unwrap();
4874 assert_eq!(result.options.per_isolate.stack_trace_limit, 50);
4875 }
4876
4877 #[test]
4878 fn test_v8_pool_size() {
4879 let result = parse_args(svec!["--v8-pool-size", "8"]).unwrap();
4880 assert_eq!(result.options.v8_thread_pool_size, 8);
4881 }
4882
4883 #[test]
4886 fn test_combined_options_for_debugging() {
4887 let result = parse_args(svec![
4888 "--inspect-brk=9230",
4889 "--no-warnings",
4890 "--enable-source-maps",
4891 "script.js",
4892 "--arg1"
4893 ])
4894 .unwrap();
4895 assert!(
4896 result
4897 .options
4898 .per_isolate
4899 .per_env
4900 .debug_options
4901 .inspector_enabled
4902 );
4903 assert!(
4904 result
4905 .options
4906 .per_isolate
4907 .per_env
4908 .debug_options
4909 .break_first_line
4910 );
4911 assert_eq!(
4912 result
4913 .options
4914 .per_isolate
4915 .per_env
4916 .debug_options
4917 .host_port
4918 .port,
4919 9230
4920 );
4921 assert!(!result.options.per_isolate.per_env.warnings);
4922 assert!(result.options.per_isolate.per_env.enable_source_maps);
4923 assert_eq!(result.remaining_args, svec!["script.js", "--arg1"]);
4924 }
4925
4926 #[test]
4927 fn test_combined_options_for_testing() {
4928 let result = parse_args(svec![
4929 "--test",
4930 "--test-timeout",
4931 "10000",
4932 "--test-concurrency",
4933 "2",
4934 "--test-reporter",
4935 "spec",
4936 "test/**/*.test.js"
4937 ])
4938 .unwrap();
4939 assert!(result.options.per_isolate.per_env.test_runner);
4940 assert_eq!(
4941 result.options.per_isolate.per_env.test_runner_timeout,
4942 10000
4943 );
4944 assert_eq!(
4945 result.options.per_isolate.per_env.test_runner_concurrency,
4946 2
4947 );
4948 assert_eq!(
4949 result.options.per_isolate.per_env.test_reporter,
4950 svec!["spec"]
4951 );
4952 assert_eq!(result.remaining_args, svec!["test/**/*.test.js"]);
4953 }
4954
4955 #[test]
4956 fn test_combined_options_for_esm_loader() {
4957 let result = parse_args(svec![
4958 "--import",
4959 "./register.js",
4960 "--conditions",
4961 "development",
4962 "script.js"
4963 ])
4964 .unwrap();
4965 assert_eq!(
4966 result.options.per_isolate.per_env.preload_esm_modules,
4967 svec!["./register.js"]
4968 );
4969 assert_eq!(
4970 result.options.per_isolate.per_env.conditions,
4971 svec!["development"]
4972 );
4973 assert_eq!(result.remaining_args, svec!["script.js"]);
4974 }
4975
4976 macro_rules! test {
4978 ($name:ident, $input:tt , $expected:tt) => {
4979 #[test]
4980 fn $name() {
4981 let parsed_args = parse_args(svec! $input).unwrap();
4982 let options = TranslateOptions::for_node_cli();
4983 let result = translate_to_deno_args(parsed_args, &options);
4984 assert_eq!(result.deno_args, svec! $expected);
4985 }
4986 };
4987 }
4988
4989 test!(test_repl_no_args, [], ["node", "repl", "-A", "--"]);
4990
4991 test!(
4992 test_run_script,
4993 ["foo.js"],
4994 [
4995 "node",
4996 "run",
4997 "-A",
4998 "--unstable-node-globals",
4999 "--unstable-bare-node-builtins",
5000 "--unstable-detect-cjs",
5001 "--node-modules-dir=manual",
5002 "--no-config",
5003 "foo.js"
5004 ]
5005 );
5006}