GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_options.cc Lines: 497 539 92.2 %
Date: 2020-02-19 22:14:06 Branches: 180 246 73.2 %

Line Branch Exec Source
1
#include "node_options.h"  // NOLINT(build/include_inline)
2
#include "node_options-inl.h"
3
4
#include "env-inl.h"
5
#include "node_binding.h"
6
#include "node_internals.h"
7
8
#include <errno.h>
9
#include <sstream>
10
#include <cstdlib>  // strtoul, errno
11
12
using v8::Boolean;
13
using v8::Context;
14
using v8::FunctionCallbackInfo;
15
using v8::Integer;
16
using v8::Isolate;
17
using v8::Local;
18
using v8::Map;
19
using v8::Number;
20
using v8::Object;
21
using v8::String;
22
using v8::Undefined;
23
using v8::Value;
24
25
namespace node {
26
27
namespace per_process {
28
4186
Mutex cli_options_mutex;
29
4186
std::shared_ptr<PerProcessOptions> cli_options{new PerProcessOptions()};
30
}  // namespace per_process
31
32
8316
void DebugOptions::CheckOptions(std::vector<std::string>* errors) {
33
#if !NODE_USE_V8_PLATFORM && !HAVE_INSPECTOR
34
  if (inspector_enabled) {
35
    errors->push_back("Inspector is not available when Node is compiled "
36
                      "--without-v8-platform and --without-inspector.");
37
  }
38
#endif
39
40
8316
  if (deprecated_debug) {
41
10
    errors->push_back("[DEP0062]: `node --debug` and `node --debug-brk` "
42
                      "are invalid. Please use `node --inspect` and "
43
5
                      "`node --inspect-brk` instead.");
44
  }
45
46
  std::vector<std::string> destinations =
47
16632
      SplitString(inspect_publish_uid_string, ',');
48
8316
  inspect_publish_uid.console = false;
49
8316
  inspect_publish_uid.http = false;
50
24946
  for (const std::string& destination : destinations) {
51
16630
    if (destination == "stderr") {
52
8315
      inspect_publish_uid.console = true;
53
8315
    } else if (destination == "http") {
54
8315
      inspect_publish_uid.http = true;
55
    } else {
56
      errors->push_back("--inspect-publish-uid destination can be "
57
                        "stderr or http");
58
    }
59
  }
60
8316
}
61
62
8257
void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) {
63
#if HAVE_OPENSSL
64

8257
  if (use_openssl_ca && use_bundled_ca) {
65
2
    errors->push_back("either --use-openssl-ca or --use-bundled-ca can be "
66
1
                      "used, not both");
67
  }
68
#endif
69

16516
  if (use_largepages != "off" &&
70

8258
      use_largepages != "on" &&
71
1
      use_largepages != "silent") {
72
1
    errors->push_back("invalid value for --use-largepages");
73
  }
74
8257
  per_isolate->CheckOptions(errors);
75
8257
}
76
77
8316
void PerIsolateOptions::CheckOptions(std::vector<std::string>* errors) {
78
8316
  per_env->CheckOptions(errors);
79
#ifdef NODE_REPORT
80
8316
  if (per_env->experimental_report) {
81
    // Assign the report_signal default value here. Once the
82
    // --experimental-report flag is dropped, move this initialization to
83
    // node_options.h, where report_signal is declared.
84
11
    if (report_signal.empty())
85
11
      report_signal = "SIGUSR2";
86
11
    return;
87
  }
88
89
8305
  if (!report_directory.empty()) {
90
    errors->push_back("--report-directory option is valid only when "
91
                      "--experimental-report is set");
92
  }
93
94
8305
  if (!report_filename.empty()) {
95
    errors->push_back("--report-filename option is valid only when "
96
                      "--experimental-report is set");
97
  }
98
99
8305
  if (!report_signal.empty()) {
100
    errors->push_back("--report-signal option is valid only when "
101
                      "--experimental-report is set");
102
  }
103
104
8305
  if (report_on_fatalerror) {
105
    errors->push_back(
106
        "--report-on-fatalerror option is valid only when "
107
        "--experimental-report is set");
108
  }
109
110
8305
  if (report_on_signal) {
111
    errors->push_back("--report-on-signal option is valid only when "
112
                      "--experimental-report is set");
113
  }
114
115
8305
  if (report_uncaught_exception) {
116
    errors->push_back(
117
        "--report-uncaught-exception option is valid only when "
118
        "--experimental-report is set");
119
  }
120
#endif  // NODE_REPORT
121
}
122
123
8316
void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
124

8316
  if (has_policy_integrity_string && experimental_policy.empty()) {
125
    errors->push_back("--policy-integrity requires "
126
                      "--experimental-policy be enabled");
127
  }
128

8316
  if (has_policy_integrity_string && experimental_policy_integrity.empty()) {
129
1
    errors->push_back("--policy-integrity cannot be empty");
130
  }
131
132
8316
  if (!module_type.empty()) {
133

14
    if (module_type != "commonjs" && module_type != "module") {
134
      errors->push_back("--input-type must be \"module\" or \"commonjs\"");
135
    }
136
  }
137
138
8316
  if (!es_module_specifier_resolution.empty()) {
139
6
    if (!experimental_specifier_resolution.empty()) {
140
2
      errors->push_back(
141
        "bad option: cannot use --es-module-specifier-resolution"
142
1
        " and --experimental-specifier-resolution at the same time");
143
    } else {
144
5
      experimental_specifier_resolution = es_module_specifier_resolution;
145

5
      if (experimental_specifier_resolution != "node" &&
146
          experimental_specifier_resolution != "explicit") {
147
        errors->push_back(
148
          "invalid value for --es-module-specifier-resolution");
149
      }
150
    }
151
8310
  } else if (!experimental_specifier_resolution.empty()) {
152

1
    if (experimental_specifier_resolution != "node" &&
153
        experimental_specifier_resolution != "explicit") {
154
      errors->push_back(
155
        "invalid value for --experimental-specifier-resolution");
156
    }
157
  }
158
159

8316
  if (syntax_check_only && has_eval_string) {
160
4
    errors->push_back("either --check or --eval can be used, not both");
161
  }
162
163

16643
  if (!unhandled_rejections.empty() &&
164
20
      unhandled_rejections != "strict" &&
165

8332
      unhandled_rejections != "warn" &&
166
7
      unhandled_rejections != "none") {
167
1
    errors->push_back("invalid value for --unhandled-rejections");
168
  }
169
170

8316
  if (tls_min_v1_3 && tls_max_v1_2) {
171
2
    errors->push_back("either --tls-min-v1.3 or --tls-max-v1.2 can be "
172
1
                      "used, not both");
173
  }
174
175
#if HAVE_INSPECTOR
176
8316
  if (!cpu_prof) {
177
8307
    if (!cpu_prof_name.empty()) {
178
1
      errors->push_back("--cpu-prof-name must be used with --cpu-prof");
179
    }
180
8307
    if (!cpu_prof_dir.empty()) {
181
1
      errors->push_back("--cpu-prof-dir must be used with --cpu-prof");
182
    }
183
    // We can't catch the case where the value passed is the default value,
184
    // then the option just becomes a noop which is fine.
185
8307
    if (cpu_prof_interval != kDefaultCpuProfInterval) {
186
1
      errors->push_back("--cpu-prof-interval must be used with --cpu-prof");
187
    }
188
  }
189
190
8316
  if (!heap_prof) {
191
8307
    if (!heap_prof_name.empty()) {
192
1
      errors->push_back("--heap-prof-name must be used with --heap-prof");
193
    }
194
8307
    if (!heap_prof_dir.empty()) {
195
1
      errors->push_back("--heap-prof-dir must be used with --heap-prof");
196
    }
197
    // We can't catch the case where the value passed is the default value,
198
    // then the option just becomes a noop which is fine.
199
8307
    if (heap_prof_interval != kDefaultHeapProfInterval) {
200
1
      errors->push_back("--heap-prof-interval must be used with --heap-prof");
201
    }
202
  }
203
8316
  debug_options_.CheckOptions(errors);
204
#endif  // HAVE_INSPECTOR
205
8316
}
206
207
namespace options_parser {
208
209
4186
class DebugOptionsParser : public OptionsParser<DebugOptions> {
210
 public:
211
  DebugOptionsParser();
212
};
213
214
4186
class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
215
 public:
216
  EnvironmentOptionsParser();
217
4186
  explicit EnvironmentOptionsParser(const DebugOptionsParser& dop)
218
4186
    : EnvironmentOptionsParser() {
219
4186
    Insert(dop, &EnvironmentOptions::get_debug_options);
220
4186
  }
221
};
222
223
4186
class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> {
224
 public:
225
  PerIsolateOptionsParser() = delete;
226
  explicit PerIsolateOptionsParser(const EnvironmentOptionsParser& eop);
227
};
228
229
4186
class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
230
 public:
231
  PerProcessOptionsParser() = delete;
232
  explicit PerProcessOptionsParser(const PerIsolateOptionsParser& iop);
233
};
234
235
#if HAVE_INSPECTOR
236
4186
const DebugOptionsParser _dop_instance{};
237
4186
const EnvironmentOptionsParser _eop_instance{_dop_instance};
238
239
// This Parse is not dead code. It is used by embedders (e.g., Electron).
240
template <>
241
void Parse(
242
  StringVector* const args, StringVector* const exec_args,
243
  StringVector* const v8_args,
244
  DebugOptions* const options,
245
  OptionEnvvarSettings required_env_settings, StringVector* const errors) {
246
  _dop_instance.Parse(
247
    args, exec_args, v8_args, options, required_env_settings, errors);
248
}
249
#else
250
const EnvironmentOptionsParser _eop_instance{};
251
#endif  // HAVE_INSPECTOR
252
4186
const PerIsolateOptionsParser _piop_instance{_eop_instance};
253
4186
const PerProcessOptionsParser _ppop_instance{_piop_instance};
254
255
template <>
256
59
void Parse(
257
  StringVector* const args, StringVector* const exec_args,
258
  StringVector* const v8_args,
259
  PerIsolateOptions* const options,
260
  OptionEnvvarSettings required_env_settings, StringVector* const errors) {
261
  _piop_instance.Parse(
262
59
    args, exec_args, v8_args, options, required_env_settings, errors);
263
59
}
264
265
template <>
266
8257
void Parse(
267
  StringVector* const args, StringVector* const exec_args,
268
  StringVector* const v8_args,
269
  PerProcessOptions* const options,
270
  OptionEnvvarSettings required_env_settings, StringVector* const errors) {
271
  _ppop_instance.Parse(
272
8257
    args, exec_args, v8_args, options, required_env_settings, errors);
273
8257
}
274
275
// XXX: If you add an option here, please also add it to doc/node.1 and
276
// doc/api/cli.md
277
// TODO(addaleax): Make that unnecessary.
278
279
4186
DebugOptionsParser::DebugOptionsParser() {
280
4186
  AddOption("--inspect-port",
281
            "set host:port for inspector",
282
            &DebugOptions::host_port,
283
4186
            kAllowedInEnvironment);
284
4186
  AddAlias("--debug-port", "--inspect-port");
285
286
4186
  AddOption("--inspect",
287
            "activate inspector on host:port (default: 127.0.0.1:9229)",
288
            &DebugOptions::inspector_enabled,
289
4186
            kAllowedInEnvironment);
290
4186
  AddAlias("--inspect=", { "--inspect-port", "--inspect" });
291
292
4186
  AddOption("--debug", "", &DebugOptions::deprecated_debug);
293
4186
  AddAlias("--debug=", "--debug");
294
4186
  AddOption("--debug-brk", "", &DebugOptions::deprecated_debug);
295
4186
  AddAlias("--debug-brk=", "--debug-brk");
296
297
4186
  AddOption("--inspect-brk",
298
            "activate inspector on host:port and break at start of user script",
299
            &DebugOptions::break_first_line,
300
4186
            kAllowedInEnvironment);
301
4186
  Implies("--inspect-brk", "--inspect");
302
4186
  AddAlias("--inspect-brk=", { "--inspect-port", "--inspect-brk" });
303
304
4186
  AddOption("--inspect-brk-node", "", &DebugOptions::break_node_first_line);
305
4186
  Implies("--inspect-brk-node", "--inspect");
306
4186
  AddAlias("--inspect-brk-node=", { "--inspect-port", "--inspect-brk-node" });
307
308
4186
  AddOption("--inspect-publish-uid",
309
            "comma separated list of destinations for inspector uid"
310
            "(default: stderr,http)",
311
            &DebugOptions::inspect_publish_uid_string,
312
4186
            kAllowedInEnvironment);
313
4186
}
314
315
4186
EnvironmentOptionsParser::EnvironmentOptionsParser() {
316
4186
  AddOption("--enable-source-maps",
317
            "experimental Source Map V3 support",
318
            &EnvironmentOptions::enable_source_maps,
319
4186
            kAllowedInEnvironment);
320
4186
  AddOption("--experimental-json-modules",
321
            "experimental JSON interop support for the ES Module loader",
322
            &EnvironmentOptions::experimental_json_modules,
323
4186
            kAllowedInEnvironment);
324
4186
  AddOption("--experimental-loader",
325
            "use the specified module as a custom loader",
326
            &EnvironmentOptions::userland_loader,
327
4186
            kAllowedInEnvironment);
328
4186
  AddAlias("--loader", "--experimental-loader");
329
4186
  AddOption("--experimental-modules",
330
            "experimental modules features",
331
            &EnvironmentOptions::experimental_modules,
332
4186
            kAllowedInEnvironment);
333
4186
  AddOption("--experimental-wasm-modules",
334
            "experimental ES Module support for webassembly modules",
335
            &EnvironmentOptions::experimental_wasm_modules,
336
4186
            kAllowedInEnvironment);
337
4186
  AddOption("--experimental-import-meta-resolve",
338
            "experimental ES Module import.meta.resolve() support",
339
            &EnvironmentOptions::experimental_import_meta_resolve,
340
4186
            kAllowedInEnvironment);
341
4186
  AddOption("--experimental-policy",
342
            "use the specified file as a "
343
            "security policy",
344
            &EnvironmentOptions::experimental_policy,
345
4186
            kAllowedInEnvironment);
346
4186
  AddOption("[has_policy_integrity_string]",
347
            "",
348
4186
            &EnvironmentOptions::has_policy_integrity_string);
349
4186
  AddOption("--policy-integrity",
350
            "ensure the security policy contents match "
351
            "the specified integrity",
352
            &EnvironmentOptions::experimental_policy_integrity,
353
4186
            kAllowedInEnvironment);
354
4186
  Implies("--policy-integrity", "[has_policy_integrity_string]");
355
4186
  AddOption("--experimental-repl-await",
356
            "experimental await keyword support in REPL",
357
            &EnvironmentOptions::experimental_repl_await,
358
4186
            kAllowedInEnvironment);
359
4186
  AddOption("--experimental-vm-modules",
360
            "experimental ES Module support in vm module",
361
            &EnvironmentOptions::experimental_vm_modules,
362
4186
            kAllowedInEnvironment);
363
4186
  AddOption("--experimental-worker", "", NoOp{}, kAllowedInEnvironment);
364
#ifdef NODE_REPORT
365
4186
  AddOption("--experimental-report",
366
            "enable report generation",
367
            &EnvironmentOptions::experimental_report,
368
4186
            kAllowedInEnvironment);
369
#endif  // NODE_REPORT
370
4186
  AddOption("--experimental-wasi-unstable-preview1",
371
            "experimental WASI support",
372
            &EnvironmentOptions::experimental_wasi,
373
4186
            kAllowedInEnvironment);
374
4186
  AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
375
4186
  AddOption("--frozen-intrinsics",
376
            "experimental frozen intrinsics support",
377
            &EnvironmentOptions::frozen_intrinsics,
378
4186
            kAllowedInEnvironment);
379
4186
  AddOption("--heapsnapshot-signal",
380
            "Generate heap snapshot on specified signal",
381
            &EnvironmentOptions::heap_snapshot_signal,
382
4186
            kAllowedInEnvironment);
383
4186
  AddOption("--http-parser", "", NoOp{}, kAllowedInEnvironment);
384
4186
  AddOption("--insecure-http-parser",
385
            "use an insecure HTTP parser that accepts invalid HTTP headers",
386
            &EnvironmentOptions::insecure_http_parser,
387
4186
            kAllowedInEnvironment);
388
4186
  AddOption("--input-type",
389
            "set module type for string input",
390
            &EnvironmentOptions::module_type,
391
4186
            kAllowedInEnvironment);
392
4186
  AddOption("--experimental-specifier-resolution",
393
            "Select extension resolution algorithm for es modules; "
394
            "either 'explicit' (default) or 'node'",
395
            &EnvironmentOptions::experimental_specifier_resolution,
396
4186
            kAllowedInEnvironment);
397
4186
  AddOption("--es-module-specifier-resolution",
398
            "",
399
            &EnvironmentOptions::es_module_specifier_resolution,
400
4186
            kAllowedInEnvironment);
401
4186
  AddOption("--no-deprecation",
402
            "silence deprecation warnings",
403
            &EnvironmentOptions::no_deprecation,
404
4186
            kAllowedInEnvironment);
405
4186
  AddOption("--no-force-async-hooks-checks",
406
            "disable checks for async_hooks",
407
            &EnvironmentOptions::no_force_async_hooks_checks,
408
4186
            kAllowedInEnvironment);
409
4186
  AddOption("--no-warnings",
410
            "silence all process warnings",
411
            &EnvironmentOptions::no_warnings,
412
4186
            kAllowedInEnvironment);
413
4186
  AddOption("--force-context-aware",
414
            "disable loading non-context-aware addons",
415
            &EnvironmentOptions::force_context_aware,
416
4186
            kAllowedInEnvironment);
417
4186
  AddOption("--pending-deprecation",
418
            "emit pending deprecation warnings",
419
            &EnvironmentOptions::pending_deprecation,
420
4186
            kAllowedInEnvironment);
421
4186
  AddOption("--preserve-symlinks",
422
            "preserve symbolic links when resolving",
423
            &EnvironmentOptions::preserve_symlinks,
424
4186
            kAllowedInEnvironment);
425
4186
  AddOption("--preserve-symlinks-main",
426
            "preserve symbolic links when resolving the main module",
427
            &EnvironmentOptions::preserve_symlinks_main,
428
4186
            kAllowedInEnvironment);
429
4186
  AddOption("--prof-process",
430
            "process V8 profiler output generated using --prof",
431
4186
            &EnvironmentOptions::prof_process);
432
  // Options after --prof-process are passed through to the prof processor.
433
4186
  AddAlias("--prof-process", { "--prof-process", "--" });
434
#if HAVE_INSPECTOR
435
4186
  AddOption("--cpu-prof",
436
            "Start the V8 CPU profiler on start up, and write the CPU profile "
437
            "to disk before exit. If --cpu-prof-dir is not specified, write "
438
            "the profile to the current working directory.",
439
4186
            &EnvironmentOptions::cpu_prof);
440
4186
  AddOption("--cpu-prof-name",
441
            "specified file name of the V8 CPU profile generated with "
442
            "--cpu-prof",
443
4186
            &EnvironmentOptions::cpu_prof_name);
444
4186
  AddOption("--cpu-prof-interval",
445
            "specified sampling interval in microseconds for the V8 CPU "
446
            "profile generated with --cpu-prof. (default: 1000)",
447
4186
            &EnvironmentOptions::cpu_prof_interval);
448
4186
  AddOption("--cpu-prof-dir",
449
            "Directory where the V8 profiles generated by --cpu-prof will be "
450
            "placed. Does not affect --prof.",
451
4186
            &EnvironmentOptions::cpu_prof_dir);
452
4186
  AddOption(
453
      "--heap-prof",
454
      "Start the V8 heap profiler on start up, and write the heap profile "
455
      "to disk before exit. If --heap-prof-dir is not specified, write "
456
      "the profile to the current working directory.",
457
4186
      &EnvironmentOptions::heap_prof);
458
4186
  AddOption("--heap-prof-name",
459
            "specified file name of the V8 CPU profile generated with "
460
            "--heap-prof",
461
4186
            &EnvironmentOptions::heap_prof_name);
462
4186
  AddOption("--heap-prof-dir",
463
            "Directory where the V8 heap profiles generated by --heap-prof "
464
            "will be placed.",
465
4186
            &EnvironmentOptions::heap_prof_dir);
466
4186
  AddOption("--heap-prof-interval",
467
            "specified sampling interval in bytes for the V8 heap "
468
            "profile generated with --heap-prof. (default: 512 * 1024)",
469
4186
            &EnvironmentOptions::heap_prof_interval);
470
#endif  // HAVE_INSPECTOR
471
4186
  AddOption("--max-http-header-size",
472
            "set the maximum size of HTTP headers (default: 8192 (8KB))",
473
            &EnvironmentOptions::max_http_header_size,
474
4186
            kAllowedInEnvironment);
475
4186
  AddOption("--redirect-warnings",
476
            "write warnings to file instead of stderr",
477
            &EnvironmentOptions::redirect_warnings,
478
4186
            kAllowedInEnvironment);
479
4186
  AddOption("--test-udp-no-try-send", "",  // For testing only.
480
4186
            &EnvironmentOptions::test_udp_no_try_send);
481
4186
  AddOption("--throw-deprecation",
482
            "throw an exception on deprecations",
483
            &EnvironmentOptions::throw_deprecation,
484
4186
            kAllowedInEnvironment);
485
4186
  AddOption("--trace-deprecation",
486
            "show stack traces on deprecations",
487
            &EnvironmentOptions::trace_deprecation,
488
4186
            kAllowedInEnvironment);
489
4186
  AddOption("--trace-exit",
490
            "show stack trace when an environment exits",
491
            &EnvironmentOptions::trace_exit,
492
4186
            kAllowedInEnvironment);
493
4186
  AddOption("--trace-sync-io",
494
            "show stack trace when use of sync IO is detected after the "
495
            "first tick",
496
            &EnvironmentOptions::trace_sync_io,
497
4186
            kAllowedInEnvironment);
498
4186
  AddOption("--trace-tls",
499
            "prints TLS packet trace information to stderr",
500
            &EnvironmentOptions::trace_tls,
501
4186
            kAllowedInEnvironment);
502
4186
  AddOption("--trace-uncaught",
503
            "show stack traces for the `throw` behind uncaught exceptions",
504
            &EnvironmentOptions::trace_uncaught,
505
4186
            kAllowedInEnvironment);
506
4186
  AddOption("--trace-warnings",
507
            "show stack traces on process warnings",
508
            &EnvironmentOptions::trace_warnings,
509
4186
            kAllowedInEnvironment);
510
4186
  AddOption("--unhandled-rejections",
511
            "define unhandled rejections behavior. Options are 'strict' (raise "
512
            "an error), 'warn' (enforce warnings) or 'none' (silence warnings)",
513
            &EnvironmentOptions::unhandled_rejections,
514
4186
            kAllowedInEnvironment);
515
516
4186
  AddOption("--check",
517
            "syntax check script without executing",
518
4186
            &EnvironmentOptions::syntax_check_only);
519
4186
  AddAlias("-c", "--check");
520
  // This option is only so that we can tell --eval with an empty string from
521
  // no eval at all. Having it not start with a dash makes it inaccessible
522
  // from the parser itself, but available for using Implies().
523
  // TODO(addaleax): When moving --help over to something generated from the
524
  // programmatic descriptions, this will need some special care.
525
  // (See also [ssl_openssl_cert_store] below.)
526
4186
  AddOption("[has_eval_string]", "", &EnvironmentOptions::has_eval_string);
527
4186
  AddOption("--eval", "evaluate script", &EnvironmentOptions::eval_string);
528
4186
  Implies("--eval", "[has_eval_string]");
529
4186
  AddOption("--print",
530
            "evaluate script and print result",
531
4186
            &EnvironmentOptions::print_eval);
532
4186
  AddAlias("-e", "--eval");
533
4186
  AddAlias("--print <arg>", "-pe");
534
4186
  AddAlias("-pe", { "--print", "--eval" });
535
4186
  AddAlias("-p", "--print");
536
4186
  AddOption("--require",
537
            "module to preload (option can be repeated)",
538
            &EnvironmentOptions::preload_modules,
539
4186
            kAllowedInEnvironment);
540
4186
  AddAlias("-r", "--require");
541
4186
  AddOption("--interactive",
542
            "always enter the REPL even if stdin does not appear "
543
            "to be a terminal",
544
4186
            &EnvironmentOptions::force_repl);
545
4186
  AddAlias("-i", "--interactive");
546
547
4186
  AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvironment);
548
549
4186
  AddOption("--tls-keylog",
550
            "log TLS decryption keys to named file for traffic analysis",
551
4186
            &EnvironmentOptions::tls_keylog, kAllowedInEnvironment);
552
553
4186
  AddOption("--tls-min-v1.0",
554
            "set default TLS minimum to TLSv1.0 (default: TLSv1.2)",
555
            &EnvironmentOptions::tls_min_v1_0,
556
4186
            kAllowedInEnvironment);
557
4186
  AddOption("--tls-min-v1.1",
558
            "set default TLS minimum to TLSv1.1 (default: TLSv1.2)",
559
            &EnvironmentOptions::tls_min_v1_1,
560
4186
            kAllowedInEnvironment);
561
4186
  AddOption("--tls-min-v1.2",
562
            "set default TLS minimum to TLSv1.2 (default: TLSv1.2)",
563
            &EnvironmentOptions::tls_min_v1_2,
564
4186
            kAllowedInEnvironment);
565
4186
  AddOption("--tls-min-v1.3",
566
            "set default TLS minimum to TLSv1.3 (default: TLSv1.2)",
567
            &EnvironmentOptions::tls_min_v1_3,
568
4186
            kAllowedInEnvironment);
569
4186
  AddOption("--tls-max-v1.2",
570
            "set default TLS maximum to TLSv1.2 (default: TLSv1.3)",
571
            &EnvironmentOptions::tls_max_v1_2,
572
4186
            kAllowedInEnvironment);
573
  // Current plan is:
574
  // - 11.x and below: TLS1.3 is opt-in with --tls-max-v1.3
575
  // - 12.x: TLS1.3 is opt-out with --tls-max-v1.2
576
  // In either case, support both options they are uniformly available.
577
4186
  AddOption("--tls-max-v1.3",
578
            "set default TLS maximum to TLSv1.3 (default: TLSv1.3)",
579
            &EnvironmentOptions::tls_max_v1_3,
580
4186
            kAllowedInEnvironment);
581
4186
}
582
583
4186
PerIsolateOptionsParser::PerIsolateOptionsParser(
584
4186
  const EnvironmentOptionsParser& eop) {
585
4186
  AddOption("--track-heap-objects",
586
            "track heap object allocations for heap snapshots",
587
            &PerIsolateOptions::track_heap_objects,
588
4186
            kAllowedInEnvironment);
589
4186
  AddOption("--no-node-snapshot",
590
            "",  // It's a debug-only option.
591
            &PerIsolateOptions::no_node_snapshot,
592
4186
            kAllowedInEnvironment);
593
594
  // Explicitly add some V8 flags to mark them as allowed in NODE_OPTIONS.
595
4186
  AddOption("--abort-on-uncaught-exception",
596
            "aborting instead of exiting causes a core file to be generated "
597
            "for analysis",
598
4186
            V8Option{},
599
4186
            kAllowedInEnvironment);
600
4186
  AddOption("--interpreted-frames-native-stack",
601
            "help system profilers to translate JavaScript interpreted frames",
602
4186
            V8Option{}, kAllowedInEnvironment);
603
4186
  AddOption("--max-old-space-size", "", V8Option{}, kAllowedInEnvironment);
604
4186
  AddOption("--perf-basic-prof", "", V8Option{}, kAllowedInEnvironment);
605
4186
  AddOption("--perf-basic-prof-only-functions",
606
            "",
607
4186
            V8Option{},
608
4186
            kAllowedInEnvironment);
609
4186
  AddOption("--perf-prof", "", V8Option{}, kAllowedInEnvironment);
610
4186
  AddOption("--perf-prof-unwinding-info",
611
            "",
612
4186
            V8Option{},
613
4186
            kAllowedInEnvironment);
614
4186
  AddOption("--stack-trace-limit", "", V8Option{}, kAllowedInEnvironment);
615
4186
  AddOption("--disallow-code-generation-from-strings",
616
            "disallow eval and friends",
617
4186
            V8Option{},
618
4186
            kAllowedInEnvironment);
619
620
#ifdef NODE_REPORT
621
4186
  AddOption("--report-uncaught-exception",
622
            "generate diagnostic report on uncaught exceptions",
623
            &PerIsolateOptions::report_uncaught_exception,
624
4186
            kAllowedInEnvironment);
625
4186
  AddOption("--report-on-signal",
626
            "generate diagnostic report upon receiving signals",
627
            &PerIsolateOptions::report_on_signal,
628
4186
            kAllowedInEnvironment);
629
4186
  AddOption("--report-on-fatalerror",
630
            "generate diagnostic report on fatal (internal) errors",
631
            &PerIsolateOptions::report_on_fatalerror,
632
4186
            kAllowedInEnvironment);
633
4186
  AddOption("--report-signal",
634
            "causes diagnostic report to be produced on provided signal,"
635
            " unsupported in Windows. (default: SIGUSR2)",
636
            &PerIsolateOptions::report_signal,
637
4186
            kAllowedInEnvironment);
638
4186
  Implies("--report-signal", "--report-on-signal");
639
4186
  AddOption("--report-filename",
640
            "define custom report file name."
641
            " (default: YYYYMMDD.HHMMSS.PID.SEQUENCE#.txt)",
642
            &PerIsolateOptions::report_filename,
643
4186
            kAllowedInEnvironment);
644
4186
  AddOption("--report-directory",
645
            "define custom report pathname."
646
            " (default: current working directory of Node.js process)",
647
            &PerIsolateOptions::report_directory,
648
4186
            kAllowedInEnvironment);
649
#endif  // NODE_REPORT
650
651
4186
  Insert(eop, &PerIsolateOptions::get_per_env_options);
652
4186
}
653
654
4186
PerProcessOptionsParser::PerProcessOptionsParser(
655
4186
  const PerIsolateOptionsParser& iop) {
656
4186
  AddOption("--title",
657
            "the process title to use on startup",
658
            &PerProcessOptions::title,
659
4186
            kAllowedInEnvironment);
660
4186
  AddOption("--trace-event-categories",
661
            "comma separated list of trace event categories to record",
662
            &PerProcessOptions::trace_event_categories,
663
4186
            kAllowedInEnvironment);
664
4186
  AddOption("--trace-event-file-pattern",
665
            "Template string specifying the filepath for the trace-events "
666
            "data, it supports ${rotation} and ${pid}.",
667
            &PerProcessOptions::trace_event_file_pattern,
668
4186
            kAllowedInEnvironment);
669
16744
  AddAlias("--trace-events-enabled", {
670
12558
    "--trace-event-categories", "v8,node,node.async_hooks" });
671
4186
  AddOption("--v8-pool-size",
672
            "set V8's thread pool size",
673
            &PerProcessOptions::v8_thread_pool_size,
674
4186
            kAllowedInEnvironment);
675
4186
  AddOption("--zero-fill-buffers",
676
            "automatically zero-fill all newly allocated Buffer and "
677
            "SlowBuffer instances",
678
            &PerProcessOptions::zero_fill_all_buffers,
679
4186
            kAllowedInEnvironment);
680
4186
  AddOption("--debug-arraybuffer-allocations",
681
            "", /* undocumented, only for debugging */
682
            &PerProcessOptions::debug_arraybuffer_allocations,
683
4186
            kAllowedInEnvironment);
684
685
686
  // 12.x renamed this inadvertently, so alias it for consistency within the
687
  // release line, while using the original name for consistency with older
688
  // release lines.
689
4186
  AddOption("--security-revert", "", &PerProcessOptions::security_reverts);
690
4186
  AddAlias("--security-reverts", "--security-revert");
691
4186
  AddOption("--completion-bash",
692
            "print source-able bash completion script",
693
4186
            &PerProcessOptions::print_bash_completion);
694
4186
  AddOption("--help",
695
            "print node command line options",
696
4186
            &PerProcessOptions::print_help);
697
4186
  AddAlias("-h", "--help");
698
4186
  AddOption(
699
4186
      "--version", "print Node.js version", &PerProcessOptions::print_version);
700
4186
  AddAlias("-v", "--version");
701
4186
  AddOption("--v8-options",
702
            "print V8 command line options",
703
4186
            &PerProcessOptions::print_v8_help);
704
705
#ifdef NODE_HAVE_I18N_SUPPORT
706
4186
  AddOption("--icu-data-dir",
707
            "set ICU data load path to dir (overrides NODE_ICU_DATA)"
708
#ifndef NODE_HAVE_SMALL_ICU
709
            " (note: linked-in ICU data is present)\n"
710
#endif
711
            ,
712
            &PerProcessOptions::icu_data_dir,
713
4186
            kAllowedInEnvironment);
714
#endif
715
716
#if HAVE_OPENSSL
717
4186
  AddOption("--openssl-config",
718
            "load OpenSSL configuration from the specified file "
719
            "(overrides OPENSSL_CONF)",
720
            &PerProcessOptions::openssl_config,
721
4186
            kAllowedInEnvironment);
722
4186
  AddOption("--tls-cipher-list",
723
            "use an alternative default TLS cipher list",
724
            &PerProcessOptions::tls_cipher_list,
725
4186
            kAllowedInEnvironment);
726
4186
  AddOption("--use-openssl-ca",
727
            "use OpenSSL's default CA store"
728
#if defined(NODE_OPENSSL_CERT_STORE)
729
            " (default)"
730
#endif
731
            ,
732
            &PerProcessOptions::use_openssl_ca,
733
4186
            kAllowedInEnvironment);
734
4186
  AddOption("--use-bundled-ca",
735
            "use bundled CA store"
736
#if !defined(NODE_OPENSSL_CERT_STORE)
737
            " (default)"
738
#endif
739
            ,
740
            &PerProcessOptions::use_bundled_ca,
741
4186
            kAllowedInEnvironment);
742
  // Similar to [has_eval_string] above, except that the separation between
743
  // this and use_openssl_ca only exists for option validation after parsing.
744
  // This is not ideal.
745
4186
  AddOption("[ssl_openssl_cert_store]",
746
            "",
747
4186
            &PerProcessOptions::ssl_openssl_cert_store);
748
4186
  Implies("--use-openssl-ca", "[ssl_openssl_cert_store]");
749
4186
  ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]");
750
#if NODE_FIPS_MODE
751
  AddOption("--enable-fips",
752
            "enable FIPS crypto at startup",
753
            &PerProcessOptions::enable_fips_crypto,
754
            kAllowedInEnvironment);
755
  AddOption("--force-fips",
756
            "force FIPS crypto (cannot be disabled)",
757
            &PerProcessOptions::force_fips_crypto,
758
            kAllowedInEnvironment);
759
#endif
760
#endif
761
4186
  AddOption("--use-largepages",
762
            "Map the Node.js static code to large pages. Options are "
763
            "'off' (the default value, meaning do not map), "
764
            "'on' (map and ignore failure, reporting it to stderr), "
765
            "or 'silent' (map and silently ignore failure)",
766
            &PerProcessOptions::use_largepages,
767
4186
            kAllowedInEnvironment);
768
769
4186
  AddOption("--trace-sigint",
770
            "enable printing JavaScript stacktrace on SIGINT",
771
            &PerProcessOptions::trace_sigint,
772
4186
            kAllowedInEnvironment);
773
774
4186
  Insert(iop, &PerProcessOptions::get_per_isolate_options);
775
4186
}
776
777
110
inline std::string RemoveBrackets(const std::string& host) {
778


110
  if (!host.empty() && host.front() == '[' && host.back() == ']')
779
4
    return host.substr(1, host.size() - 2);
780
  else
781
106
    return host;
782
}
783
784
98
inline int ParseAndValidatePort(const std::string& port,
785
                                std::vector<std::string>* errors) {
786
  char* endptr;
787
98
  errno = 0;
788
  const unsigned long result =                 // NOLINT(runtime/int)
789
98
    strtoul(port.c_str(), &endptr, 10);
790

98
  if (errno != 0 || *endptr != '\0'||
791

63
      (result != 0 && result < 1024) || result > 65535) {
792
    errors->push_back(" must be 0 or in range 1024 to 65535.");
793
  }
794
98
  return static_cast<int>(result);
795
}
796
797
98
HostPort SplitHostPort(const std::string& arg,
798
                      std::vector<std::string>* errors) {
799
  // remove_brackets only works if no port is specified
800
  // so if it has an effect only an IPv6 address was specified.
801
196
  std::string host = RemoveBrackets(arg);
802
98
  if (host.length() < arg.length())
803
    return HostPort{host, DebugOptions::kDefaultInspectorPort};
804
805
98
  size_t colon = arg.rfind(':');
806
98
  if (colon == std::string::npos) {
807
    // Either a port number or a host name.  Assume that
808
    // if it's not all decimal digits, it's a host name.
809
386
    for (char c : arg) {
810

300
      if (c < '0' || c > '9') {
811
        return HostPort{arg, DebugOptions::kDefaultInspectorPort};
812
      }
813
    }
814
86
    return HostPort { "", ParseAndValidatePort(arg, errors) };
815
  }
816
  // Host and port found:
817
24
  return HostPort { RemoveBrackets(arg.substr(0, colon)),
818
12
                    ParseAndValidatePort(arg.substr(colon + 1), errors) };
819
}
820
821
1
std::string GetBashCompletion() {
822
2
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
823
1
  const auto& parser = _ppop_instance;
824
825
2
  std::ostringstream out;
826
827
  out << "_node_complete() {\n"
828
         "  local cur_word options\n"
829
         "  cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n"
830
         "  if [[ \"${cur_word}\" == -* ]] ; then\n"
831
1
         "    COMPREPLY=( $(compgen -W '";
832
833
107
  for (const auto& item : parser.options_) {
834
106
    if (item.first[0] != '[') {
835
103
      out << item.first << " ";
836
    }
837
  }
838
20
  for (const auto& item : parser.aliases_) {
839
19
    if (item.first[0] != '[') {
840
19
      out << item.first << " ";
841
    }
842
  }
843
1
  if (parser.aliases_.size() > 0) {
844
1
    out.seekp(-1, out.cur);  // Strip the trailing space
845
  }
846
847
  out << "' -- \"${cur_word}\") )\n"
848
         "    return 0\n"
849
         "  else\n"
850
         "    COMPREPLY=( $(compgen -f \"${cur_word}\") )\n"
851
         "    return 0\n"
852
         "  fi\n"
853
         "}\n"
854
1
         "complete -F _node_complete node node_g";
855
2
  return out.str();
856
}
857
858
// Return a map containing all the options and their metadata as well
859
// as the aliases
860
4377
void GetOptions(const FunctionCallbackInfo<Value>& args) {
861
8754
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
862
4377
  Environment* env = Environment::GetCurrent(args);
863
4377
  if (!env->has_run_bootstrapping_code()) {
864
    // No code because this is an assertion.
865
    return env->ThrowError(
866
        "Should not query options before bootstrapping is done");
867
  }
868
4377
  env->set_has_serialized_options(true);
869
870
4377
  Isolate* isolate = env->isolate();
871
4377
  Local<Context> context = env->context();
872
873
  // Temporarily act as if the current Environment's/IsolateData's options were
874
  // the default options, i.e. like they are the ones we'd access for global
875
  // options parsing, so that all options are available from the main parser.
876
8754
  auto original_per_isolate = per_process::cli_options->per_isolate;
877
4377
  per_process::cli_options->per_isolate = env->isolate_data()->options();
878
8754
  auto original_per_env = per_process::cli_options->per_isolate->per_env;
879
4377
  per_process::cli_options->per_isolate->per_env = env->options();
880
4377
  auto on_scope_leave = OnScopeLeave([&]() {
881
4377
    per_process::cli_options->per_isolate->per_env = original_per_env;
882
4377
    per_process::cli_options->per_isolate = original_per_isolate;
883
13131
  });
884
885
4377
  Local<Map> options = Map::New(isolate);
886
468339
  for (const auto& item : _ppop_instance.options_) {
887
    Local<Value> value;
888
463962
    const auto& option_info = item.second;
889
927924
    auto field = option_info.field;
890
463962
    PerProcessOptions* opts = per_process::cli_options.get();
891


463962
    switch (option_info.type) {
892
      case kNoOp:
893
      case kV8Option:
894
        // Special case for --abort-on-uncaught-exception which is also
895
        // respected by Node.js internals
896
52524
        if (item.first == "--abort-on-uncaught-exception") {
897
4377
          value = Boolean::New(
898
8754
            isolate, original_per_env->abort_on_uncaught_exception);
899
        } else {
900
48147
          value = Undefined(isolate);
901
        }
902
52524
        break;
903
      case kBoolean:
904
266997
        value = Boolean::New(isolate,
905
533994
                             *_ppop_instance.Lookup<bool>(field, opts));
906
266997
        break;
907
      case kInteger:
908
4377
        value = Number::New(isolate,
909
8754
                            *_ppop_instance.Lookup<int64_t>(field, opts));
910
4377
        break;
911
      case kUInteger:
912
13131
        value = Number::New(isolate,
913
26262
                            *_ppop_instance.Lookup<uint64_t>(field, opts));
914
13131
        break;
915
      case kString:
916
341406
        if (!ToV8Value(context,
917
227604
                       *_ppop_instance.Lookup<std::string>(field, opts))
918
113802
                 .ToLocal(&value)) {
919
          return;
920
        }
921
113802
        break;
922
      case kStringList:
923
26262
        if (!ToV8Value(context,
924
17508
                       *_ppop_instance.Lookup<StringVector>(field, opts))
925
8754
                 .ToLocal(&value)) {
926
          return;
927
        }
928
8754
        break;
929
      case kHostPort: {
930
        const HostPort& host_port =
931
4377
          *_ppop_instance.Lookup<HostPort>(field, opts);
932
4377
        Local<Object> obj = Object::New(isolate);
933
        Local<Value> host;
934

21885
        if (!ToV8Value(context, host_port.host()).ToLocal(&host) ||
935

21885
            obj->Set(context, env->host_string(), host).IsNothing() ||
936
8754
            obj->Set(context,
937
                     env->port_string(),
938
17508
                     Integer::New(isolate, host_port.port()))
939
4377
                .IsNothing()) {
940
          return;
941
        }
942
4377
        value = obj;
943
4377
        break;
944
      }
945
      default:
946
        UNREACHABLE();
947
    }
948
463962
    CHECK(!value.IsEmpty());
949
950
927924
    Local<Value> name = ToV8Value(context, item.first).ToLocalChecked();
951
463962
    Local<Object> info = Object::New(isolate);
952
    Local<Value> help_text;
953

2319810
    if (!ToV8Value(context, option_info.help_text).ToLocal(&help_text) ||
954
1855848
        !info->Set(context, env->help_text_string(), help_text)
955
1855848
             .FromMaybe(false) ||
956
1391886
        !info->Set(context,
957
                   env->env_var_settings_string(),
958
                   Integer::New(isolate,
959
1855848
                                static_cast<int>(option_info.env_setting)))
960
1855848
             .FromMaybe(false) ||
961
1391886
        !info->Set(context,
962
                   env->type_string(),
963
1855848
                   Integer::New(isolate, static_cast<int>(option_info.type)))
964
1855848
             .FromMaybe(false) ||
965

2783772
        info->Set(context, env->value_string(), value).IsNothing() ||
966
1391886
        options->Set(context, name, info).IsEmpty()) {
967
      return;
968
    }
969
  }
970
971
  Local<Value> aliases;
972
8754
  if (!ToV8Value(context, _ppop_instance.aliases_).ToLocal(&aliases)) return;
973
974
4377
  Local<Object> ret = Object::New(isolate);
975

21885
  if (ret->Set(context, env->options_string(), options).IsNothing() ||
976
17508
      ret->Set(context, env->aliases_string(), aliases).IsNothing()) {
977
    return;
978
  }
979
980
8754
  args.GetReturnValue().Set(ret);
981
}
982
983
4377
void Initialize(Local<Object> target,
984
                Local<Value> unused,
985
                Local<Context> context,
986
                void* priv) {
987
4377
  Environment* env = Environment::GetCurrent(context);
988
4377
  Isolate* isolate = env->isolate();
989
4377
  env->SetMethodNoSideEffect(target, "getOptions", GetOptions);
990
991
4377
  Local<Object> env_settings = Object::New(isolate);
992
17508
  NODE_DEFINE_CONSTANT(env_settings, kAllowedInEnvironment);
993
17508
  NODE_DEFINE_CONSTANT(env_settings, kDisallowedInEnvironment);
994
  target
995
8754
      ->Set(
996
13131
          context, FIXED_ONE_BYTE_STRING(isolate, "envSettings"), env_settings)
997
      .Check();
998
999
4377
  Local<Object> types = Object::New(isolate);
1000
17508
  NODE_DEFINE_CONSTANT(types, kNoOp);
1001
17508
  NODE_DEFINE_CONSTANT(types, kV8Option);
1002
17508
  NODE_DEFINE_CONSTANT(types, kBoolean);
1003
17508
  NODE_DEFINE_CONSTANT(types, kInteger);
1004
17508
  NODE_DEFINE_CONSTANT(types, kUInteger);
1005
17508
  NODE_DEFINE_CONSTANT(types, kString);
1006
17508
  NODE_DEFINE_CONSTANT(types, kHostPort);
1007
17508
  NODE_DEFINE_CONSTANT(types, kStringList);
1008
13131
  target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "types"), types)
1009
      .Check();
1010
4377
}
1011
1012
}  // namespace options_parser
1013
1014
4185
void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options) {
1015
25110
  HandleEnvOptions(env_options, [](const char* name) {
1016
33480
    std::string text;
1017

33480
    return credentials::SafeGetenv(name, &text) ? text : "";
1018
4185
  });
1019
4185
}
1020
1021
4216
void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options,
1022
                      std::function<std::string(const char*)> opt_getter) {
1023
8432
  env_options->pending_deprecation =
1024
8432
      opt_getter("NODE_PENDING_DEPRECATION") == "1";
1025
1026
4216
  env_options->preserve_symlinks = opt_getter("NODE_PRESERVE_SYMLINKS") == "1";
1027
1028
8432
  env_options->preserve_symlinks_main =
1029
8432
      opt_getter("NODE_PRESERVE_SYMLINKS_MAIN") == "1";
1030
1031
4216
  if (env_options->redirect_warnings.empty())
1032
4216
    env_options->redirect_warnings = opt_getter("NODE_REDIRECT_WARNINGS");
1033
4216
}
1034
1035
4117
std::vector<std::string> ParseNodeOptionsEnvVar(
1036
    const std::string& node_options, std::vector<std::string>* errors) {
1037
4117
  std::vector<std::string> env_argv;
1038
1039
4117
  bool is_in_string = false;
1040
4117
  bool will_start_new_arg = true;
1041
6634
  for (std::string::size_type index = 0; index < node_options.size(); ++index) {
1042
2517
    char c = node_options.at(index);
1043
1044
    // Backslashes escape the following character
1045

2517
    if (c == '\\' && is_in_string) {
1046
      if (index + 1 == node_options.size()) {
1047
        errors->push_back("invalid value for NODE_OPTIONS "
1048
                          "(invalid escape)\n");
1049
        return env_argv;
1050
      } else {
1051
        c = node_options.at(++index);
1052
      }
1053

2517
    } else if (c == ' ' && !is_in_string) {
1054
32
      will_start_new_arg = true;
1055
32
      continue;
1056
2485
    } else if (c == '"') {
1057
4
      is_in_string = !is_in_string;
1058
4
      continue;
1059
    }
1060
1061
2481
    if (will_start_new_arg) {
1062
97
      env_argv.emplace_back(std::string(1, c));
1063
97
      will_start_new_arg = false;
1064
    } else {
1065
2384
      env_argv.back() += c;
1066
    }
1067
  }
1068
1069
4117
  if (is_in_string) {
1070
    errors->push_back("invalid value for NODE_OPTIONS "
1071
                      "(unterminated string)\n");
1072
  }
1073
4117
  return env_argv;
1074
}
1075
}  // namespace node
1076
1077

16743
NODE_MODULE_CONTEXT_AWARE_INTERNAL(options, node::options_parser::Initialize)