diff --git a/src/node_options-inl.h b/src/node_options-inl.h index 877e8ce4ded..90603b148be 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -31,17 +31,19 @@ namespace options_parser { template void OptionsParser::AddOption(const char* name, const char* help_text, - bool Options::*field, + bool (*getter)(Options*), + void (*setter)(Options*, bool), OptionEnvvarSettings env_setting, bool default_is_true, OptionNamespaces namespace_id) { - options_.emplace(name, - OptionInfo{kBoolean, - std::make_shared>(field), - env_setting, - help_text, - default_is_true, - NamespaceEnumToString(namespace_id)}); + options_.emplace( + name, + OptionInfo{kBoolean, + std::make_shared(getter, setter), + env_setting, + help_text, + default_is_true, + NamespaceEnumToString(namespace_id)}); } template @@ -207,6 +209,13 @@ auto OptionsParser::Convert( return original->LookupImpl((options->*get_child)()); } + bool GetBool(Options* options) const override { + return original->GetBool((options->*get_child)()); + } + void SetBool(Options* options, bool value) override { + original->SetBool((options->*get_child)(), value); + } + AdaptedField( std::shared_ptr original, ChildOptions* (Options::* get_child)()) @@ -432,8 +441,8 @@ void OptionsParser::Parse( if (value.type == kV8Option) { v8_args->push_back(value.name); } else { - *value.target_field->template Lookup( - options) = value.target_value; + value.target_field->SetBool(options, + value.target_value); } }); } @@ -479,7 +488,7 @@ void OptionsParser::Parse( switch (info.type) { case kBoolean: - *Lookup(info.field, options) = !is_negation; + info.field->SetBool(options, !is_negation); break; case kInteger: { // Special case to pass --stack-trace-limit down to V8. diff --git a/src/node_options.cc b/src/node_options.cc index b9ed1b0c4d6..fedd2cd792d 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -474,30 +474,30 @@ DebugOptionsParser::DebugOptionsParser() { AddOption("--inspect", "activate inspector on host:port (default: 127.0.0.1:9229)", - &DebugOptions::inspector_enabled, + BOOL_FIELD(inspector_enabled), kAllowedInEnvvar); AddAlias("--inspect=", { "--inspect-port", "--inspect" }); - AddOption("--debug", "", &DebugOptions::deprecated_debug); + AddOption("--debug", "", BOOL_FIELD(deprecated_debug)); AddAlias("--debug=", "--debug"); - AddOption("--debug-brk", "", &DebugOptions::deprecated_debug); + AddOption("--debug-brk", "", BOOL_FIELD(deprecated_debug)); AddAlias("--debug-brk=", "--debug-brk"); AddOption("--inspect-brk", "activate inspector on host:port and break at start of user script", - &DebugOptions::break_first_line, + BOOL_FIELD(break_first_line), kAllowedInEnvvar); Implies("--inspect-brk", "--inspect"); AddAlias("--inspect-brk=", { "--inspect-port", "--inspect-brk" }); - AddOption("--inspect-brk-node", "", &DebugOptions::break_node_first_line); + AddOption("--inspect-brk-node", "", BOOL_FIELD(break_node_first_line)); Implies("--inspect-brk-node", "--inspect"); AddAlias("--inspect-brk-node=", { "--inspect-port", "--inspect-brk-node" }); AddOption( "--inspect-wait", "activate inspector on host:port and wait for debugger to be attached", - &DebugOptions::inspect_wait, + BOOL_FIELD(inspect_wait), kAllowedInEnvvar); Implies("--inspect-wait", "--inspect"); AddAlias("--inspect-wait=", {"--inspect-port", "--inspect-wait"}); @@ -518,7 +518,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--experimental-detect-module", "when ambiguous modules fail to evaluate because they contain " "ES module syntax, try again to evaluate them as ES modules", - &EnvironmentOptions::detect_module, + BOOL_FIELD(detect_module), kAllowedInEnvvar, true); AddOption("--experimental-print-required-tla", @@ -526,16 +526,16 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "is true, evaluate asynchronous graphs loaded by `require()` but " "do not run the microtasks, in order to find and print " "top-level await in the graph", - &EnvironmentOptions::print_required_tla, + BOOL_FIELD(print_required_tla), kAllowedInEnvvar); AddOption("--require-module", "Allow loading synchronous ES Modules in require().", - &EnvironmentOptions::require_module, + BOOL_FIELD(require_module), kAllowedInEnvvar, true); AddOption("--experimental-require-module", "Legacy alias for --require-module", - &EnvironmentOptions::require_module, + BOOL_FIELD(require_module), kAllowedInEnvvar, true); Implies("--experimental-require-module", "--require-module"); @@ -546,7 +546,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--disable-sigusr1", "Disable inspector thread to be listening for SIGUSR1 signal", - &EnvironmentOptions::disable_sigusr1, + BOOL_FIELD(disable_sigusr1), kAllowedInEnvvar, false); AddOption("--dns-result-order", @@ -559,7 +559,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--network-family-autoselection", "Disable network address family autodetection algorithm", - &EnvironmentOptions::network_family_autoselection, + BOOL_FIELD(network_family_autoselection), kAllowedInEnvvar, true); AddOption("--network-family-autoselection-attempt-timeout", @@ -571,49 +571,49 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "--network-family-autoselection"); AddOption("--enable-source-maps", "Source Map V3 support for stack traces", - &EnvironmentOptions::enable_source_maps, + BOOL_FIELD(enable_source_maps), kAllowedInEnvvar); AddOption("--entry-url", "Treat the entrypoint as a URL", - &EnvironmentOptions::entry_is_url, + BOOL_FIELD(entry_is_url), kAllowedInEnvvar); AddOption("--experimental-addon-modules", "experimental import support for addons", - &EnvironmentOptions::experimental_addon_modules, + BOOL_FIELD(experimental_addon_modules), kAllowedInEnvvar); AddOption("--experimental-abortcontroller", "", NoOp{}, kAllowedInEnvvar); AddOption("--experimental-eventsource", "experimental EventSource API", - &EnvironmentOptions::experimental_eventsource, + BOOL_FIELD(experimental_eventsource), kAllowedInEnvvar, false); AddOption("--experimental-fetch", "", NoOp{}, kAllowedInEnvvar); #if HAVE_FFI AddOption("--experimental-ffi", "experimental node:ffi module", - &EnvironmentOptions::experimental_ffi, + BOOL_FIELD(experimental_ffi), kAllowedInEnvvar, false); #endif // HAVE_FFI AddOption("--experimental-websocket", "experimental WebSocket API", - &EnvironmentOptions::experimental_websocket, + BOOL_FIELD(experimental_websocket), kAllowedInEnvvar, true); AddOption("--experimental-global-customevent", "", NoOp{}, kAllowedInEnvvar); AddOption("--experimental-sqlite", "experimental node:sqlite module", - &EnvironmentOptions::experimental_sqlite, + BOOL_FIELD(experimental_sqlite), kAllowedInEnvvar, HAVE_SQLITE); AddOption("--experimental-stream-iter", "experimental iterable streams API (node:stream/iter)", - &EnvironmentOptions::experimental_stream_iter, + BOOL_FIELD(experimental_stream_iter), kAllowedInEnvvar); AddOption("--experimental-dtls", #if HAVE_DTLS "experimental DTLS support", - &EnvironmentOptions::experimental_dtls, + BOOL_FIELD(experimental_dtls), #else "" /* undocumented when no-op */, NoOp{}, @@ -621,12 +621,12 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--experimental-vfs", "experimental node:vfs module", - &EnvironmentOptions::experimental_vfs, + BOOL_FIELD(experimental_vfs), kAllowedInEnvvar); AddOption("--experimental-quic", #ifndef OPENSSL_NO_QUIC "experimental QUIC support", - &EnvironmentOptions::experimental_quic, + BOOL_FIELD(experimental_quic), #else "" /* undocumented when no-op */, NoOp{}, @@ -634,7 +634,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--experimental-webstorage", "experimental Web Storage API", - &EnvironmentOptions::webstorage, + BOOL_FIELD(webstorage), kAllowedInEnvvar, HAVE_SQLITE); AddAlias("--webstorage", "--experimental-webstorage"); @@ -644,7 +644,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--experimental-global-navigator", "expose experimental Navigator API on the global scope", - &EnvironmentOptions::experimental_global_navigator, + BOOL_FIELD(experimental_global_navigator), kAllowedInEnvvar, true); AddOption("--experimental-global-webcrypto", "", NoOp{}, kAllowedInEnvvar); @@ -659,21 +659,21 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--experimental-import-text", "experimental support for importing source as text with import " "attributes", - &EnvironmentOptions::experimental_import_text, + BOOL_FIELD(experimental_import_text), kAllowedInEnvvar); AddOption("--experimental-import-meta-resolve", "experimental ES Module import.meta.resolve() parentURL support", - &EnvironmentOptions::experimental_import_meta_resolve, + BOOL_FIELD(experimental_import_meta_resolve), kAllowedInEnvvar); AddOption("--permission", "enable the permission system", - &EnvironmentOptions::permission, + BOOL_FIELD(permission), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--permission-audit", "enable audit only for the permission system", - &EnvironmentOptions::permission_audit, + BOOL_FIELD(permission_audit), kAllowedInEnvvar, false); AddOption("--allow-fs-read", @@ -688,57 +688,57 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kPermissionNamespace); AddOption("--allow-addons", "allow use of addons when any permissions are set", - &EnvironmentOptions::allow_addons, + BOOL_FIELD(allow_addons), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--allow-child-process", "allow use of child process when any permissions are set", - &EnvironmentOptions::allow_child_process, + BOOL_FIELD(allow_child_process), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); #if HAVE_FFI AddOption("--allow-ffi", "allow use of FFI when any permissions are set", - &EnvironmentOptions::allow_ffi, + BOOL_FIELD(allow_ffi), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); #endif // HAVE_FFI AddOption("--allow-inspector", "allow use of inspector when any permissions are set", - &EnvironmentOptions::allow_inspector, + BOOL_FIELD(allow_inspector), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--allow-net", "allow use of network when any permissions are set", - &EnvironmentOptions::allow_net, + BOOL_FIELD(allow_net), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--allow-wasi", "allow wasi when any permissions are set", - &EnvironmentOptions::allow_wasi, + BOOL_FIELD(allow_wasi), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--allow-worker", "allow worker threads when any permissions are set", - &EnvironmentOptions::allow_worker_threads, + BOOL_FIELD(allow_worker_threads), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--allow-openssl-store", "allow use of OpenSSL STORE loaders when any permissions are set", - &EnvironmentOptions::allow_openssl_store, + BOOL_FIELD(allow_openssl_store), kAllowedInEnvvar, false, OptionNamespaces::kPermissionNamespace); AddOption("--experimental-vm-modules", "experimental ES Module support in vm module", - &EnvironmentOptions::experimental_vm_modules, + BOOL_FIELD(experimental_vm_modules), kAllowedInEnvvar); AddOption("--experimental-worker", "", NoOp{}, kAllowedInEnvvar); AddOption("--experimental-report", "", NoOp{}, kAllowedInEnvvar); @@ -747,13 +747,13 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--expose-gc", "expose gc extension", V8Option{}, kAllowedInEnvvar); AddOption("--async-context-frame", "Improve AsyncLocalStorage performance with AsyncContextFrame", - &EnvironmentOptions::async_context_frame, + BOOL_FIELD(async_context_frame), kAllowedInEnvvar, true); - AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals); + AddOption("--expose-internals", "", BOOL_FIELD(expose_internals)); AddOption("--frozen-intrinsics", "experimental frozen intrinsics support", - &EnvironmentOptions::frozen_intrinsics, + BOOL_FIELD(frozen_intrinsics), kAllowedInEnvvar); AddOption("--heapsnapshot-signal", "Generate heap snapshot on specified signal", @@ -768,7 +768,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--http-parser", "", NoOp{}, kAllowedInEnvvar); AddOption("--insecure-http-parser", "use an insecure HTTP parser that accepts invalid HTTP headers", - &EnvironmentOptions::insecure_http_parser, + BOOL_FIELD(insecure_http_parser), kAllowedInEnvvar); AddOption("--input-type", "set module type for string input", @@ -780,33 +780,33 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "--experimental-specifier-resolution"); AddOption("--deprecation", "silence deprecation warnings", - &EnvironmentOptions::deprecation, + BOOL_FIELD(deprecation), kAllowedInEnvvar, true); AddOption("--force-async-hooks-checks", "disable checks for async_hooks", - &EnvironmentOptions::force_async_hooks_checks, + BOOL_FIELD(force_async_hooks_checks), kAllowedInEnvvar, true); AddOption( "--force-node-api-uncaught-exceptions-policy", "enforces 'uncaughtException' event on Node API asynchronous callbacks", - &EnvironmentOptions::force_node_api_uncaught_exceptions_policy, + BOOL_FIELD(force_node_api_uncaught_exceptions_policy), kAllowedInEnvvar, false); AddOption("--addons", "disable loading native addons", - &EnvironmentOptions::allow_native_addons, + BOOL_FIELD(allow_native_addons), kAllowedInEnvvar, true); AddOption("--global-search-paths", "disable global module search paths", - &EnvironmentOptions::global_search_paths, + BOOL_FIELD(global_search_paths), kAllowedInEnvvar, true); AddOption("--warnings", "silence all process warnings", - &EnvironmentOptions::warnings, + BOOL_FIELD(warnings), kAllowedInEnvvar, true); AddOption("--disable-warning", @@ -815,32 +815,32 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--force-context-aware", "disable loading non-context-aware addons", - &EnvironmentOptions::force_context_aware, + BOOL_FIELD(force_context_aware), kAllowedInEnvvar); AddOption("--pending-deprecation", "emit pending deprecation warnings", - &EnvironmentOptions::pending_deprecation, + BOOL_FIELD(pending_deprecation), kAllowedInEnvvar); AddOption("--use-env-proxy", "parse proxy settings from HTTP_PROXY/HTTPS_PROXY/NO_PROXY" "environment variables and apply the setting in global HTTP/HTTPS " "clients", - &EnvironmentOptions::use_env_proxy, + BOOL_FIELD(use_env_proxy), kAllowedInEnvvar); AddOption("--preserve-symlinks", "preserve symbolic links when resolving", - &EnvironmentOptions::preserve_symlinks, + BOOL_FIELD(preserve_symlinks), kAllowedInEnvvar); AddOption("--preserve-symlinks-main", "preserve symbolic links when resolving the main module", - &EnvironmentOptions::preserve_symlinks_main, + BOOL_FIELD(preserve_symlinks_main), kAllowedInEnvvar); AddOption("--prof", "Generate V8 profiler output.", V8Option{}); AddOption("--prof-process", "process V8 profiler output generated using --prof", - &EnvironmentOptions::prof_process); + BOOL_FIELD(prof_process)); // Options after --prof-process are passed through to the prof processor. AddAlias("--prof-process", {"--prof-process", "--"}); #if HAVE_INSPECTOR @@ -848,7 +848,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "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.", - &EnvironmentOptions::cpu_prof, + BOOL_FIELD(cpu_prof), kAllowedInEnvvar); AddOption("--cpu-prof-name", "specified file name of the V8 CPU profile generated with " @@ -867,22 +867,22 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--experimental-network-inspection", "experimental network inspection support", - &EnvironmentOptions::experimental_network_inspection); + BOOL_FIELD(experimental_network_inspection)); AddOption("--experimental-storage-inspection", "experimental storage inspection support", - &EnvironmentOptions::experimental_storage_inspection); + BOOL_FIELD(experimental_storage_inspection)); AddOption("--experimental-worker-inspection", "experimental worker inspection support", - &EnvironmentOptions::experimental_worker_inspection); + BOOL_FIELD(experimental_worker_inspection)); AddOption("--experimental-inspector-network-resource", "experimental load network resources via the inspector", - &EnvironmentOptions::experimental_inspector_network_resource); + BOOL_FIELD(experimental_inspector_network_resource)); AddOption( "--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.", - &EnvironmentOptions::heap_prof, + BOOL_FIELD(heap_prof), kAllowedInEnvvar); AddOption("--heap-prof-name", "specified file name of the V8 heap profile generated with " @@ -908,8 +908,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "write warnings to file instead of stderr", &EnvironmentOptions::redirect_warnings, kAllowedInEnvvar); - AddOption( - "[has_env_file_string]", "", &EnvironmentOptions::has_env_file_string); + AddOption("[has_env_file_string]", "", BOOL_FIELD(has_env_file_string)); AddOption("--env-file", "set environment variables from supplied file", &EnvironmentOptions::env_file); @@ -929,7 +928,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--test", "launch test runner on startup", - &EnvironmentOptions::test_runner, + BOOL_FIELD(test_runner), kDisallowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -940,7 +939,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kTestRunnerNamespace); AddOption("--test-force-exit", "force test runner to exit upon completion", - &EnvironmentOptions::test_runner_force_exit, + BOOL_FIELD(test_runner_force_exit), kDisallowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -951,13 +950,13 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kTestRunnerNamespace); AddOption("--test-update-snapshots", "regenerate test snapshots", - &EnvironmentOptions::test_runner_update_snapshots, + BOOL_FIELD(test_runner_update_snapshots), kDisallowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); AddOption("--experimental-test-coverage", "enable code coverage in the test runner", - &EnvironmentOptions::test_runner_coverage, + BOOL_FIELD(test_runner_coverage), kDisallowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -985,7 +984,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddAlias("--experimental-test-isolation", "--test-isolation"); AddOption("--experimental-test-module-mocks", "enable module mocking in the test runner", - &EnvironmentOptions::test_runner_module_mocks, + BOOL_FIELD(test_runner_module_mocks), kDisallowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -1011,7 +1010,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kTestRunnerNamespace); AddOption("--test-only", "run tests with 'only' option set", - &EnvironmentOptions::test_only, + BOOL_FIELD(test_only), kAllowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -1038,7 +1037,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--test-coverage-include-all", "include source files that were never loaded in the coverage " "report", - &EnvironmentOptions::coverage_include_all, + BOOL_FIELD(coverage_include_all), kAllowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); @@ -1054,12 +1053,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kTestRunnerNamespace); AddOption("--test-randomize", "run tests in a random order", - &EnvironmentOptions::test_randomize, + BOOL_FIELD(test_randomize), kAllowedInEnvvar, false, OptionNamespaces::kTestRunnerNamespace); - AddOption( - "[has_test_random_seed]", "", &EnvironmentOptions::has_test_random_seed); + AddOption("[has_test_random_seed]", "", BOOL_FIELD(has_test_random_seed)); AddOption("--test-random-seed", "seed used to randomize test execution order", &EnvironmentOptions::test_random_seed, @@ -1073,63 +1071,63 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kTestRunnerNamespace); AddOption("--test-udp-no-try-send", "", // For testing only. - &EnvironmentOptions::test_udp_no_try_send, + BOOL_FIELD(test_udp_no_try_send), kDisallowedInEnvvar); AddOption("--throw-deprecation", "throw an exception on deprecations", - &EnvironmentOptions::throw_deprecation, + BOOL_FIELD(throw_deprecation), kAllowedInEnvvar); AddOption("--trace-deprecation", "show stack traces on deprecations", - &EnvironmentOptions::trace_deprecation, + BOOL_FIELD(trace_deprecation), kAllowedInEnvvar); AddOption("--trace-exit", "show stack trace when an environment exits", - &EnvironmentOptions::trace_exit, + BOOL_FIELD(trace_exit), kAllowedInEnvvar); AddOption("--trace-sync-io", "show stack trace when use of sync IO is detected after the " "first tick", - &EnvironmentOptions::trace_sync_io, + BOOL_FIELD(trace_sync_io), kAllowedInEnvvar); AddOption("--trace-tls", "prints TLS packet trace information to stderr", - &EnvironmentOptions::trace_tls, + BOOL_FIELD(trace_tls), kAllowedInEnvvar); AddOption("--trace-uncaught", "show stack traces for the `throw` behind uncaught exceptions", - &EnvironmentOptions::trace_uncaught, + BOOL_FIELD(trace_uncaught), kAllowedInEnvvar); AddOption("--trace-warnings", "show stack traces on process warnings", - &EnvironmentOptions::trace_warnings, + BOOL_FIELD(trace_warnings), kAllowedInEnvvar); AddOption("--trace-promises", "show stack traces on promise initialization and resolution", - &EnvironmentOptions::trace_promises, + BOOL_FIELD(trace_promises), kAllowedInEnvvar); AddOption("--trace-env", "Print accesses to the environment variables", - &EnvironmentOptions::trace_env, + BOOL_FIELD(trace_env), kAllowedInEnvvar); Implies("--trace-env-js-stack", "--trace-env"); Implies("--trace-env-native-stack", "--trace-env"); AddOption("--trace-env-js-stack", "Print accesses to the environment variables and the JavaScript " "stack trace", - &EnvironmentOptions::trace_env_js_stack, + BOOL_FIELD(trace_env_js_stack), kAllowedInEnvvar); AddOption( "--trace-env-native-stack", "Print accesses to the environment variables and the native stack trace", - &EnvironmentOptions::trace_env_native_stack, + BOOL_FIELD(trace_env_native_stack), kAllowedInEnvvar); #if HAVE_OPENSSL AddOption("--use-system-ca", "use system's CA store", - &EnvironmentOptions::use_system_ca, + BOOL_FIELD(use_system_ca), kAllowedInEnvvar); #endif // HAVE_OPENSSL @@ -1142,7 +1140,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--extra-info-on-fatal-exception", "hide extra information on fatal exception that causes exit", - &EnvironmentOptions::extra_info_on_fatal_exception, + BOOL_FIELD(extra_info_on_fatal_exception), kAllowedInEnvvar, true); AddOption("--unhandled-rejections", @@ -1156,11 +1154,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--verify-base-objects", "", /* undocumented, only for debugging */ - &EnvironmentOptions::verify_base_objects, + BOOL_FIELD(verify_base_objects), kAllowedInEnvvar); AddOption("--watch", "run in watch mode", - &EnvironmentOptions::watch_mode, + BOOL_FIELD(watch_mode), kAllowedInEnvvar, false, OptionNamespaces::kWatchNamespace); @@ -1177,14 +1175,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { OptionNamespaces::kWatchNamespace); AddOption("--watch-preserve-output", "preserve outputs on watch mode restart", - &EnvironmentOptions::watch_mode_preserve_output, + BOOL_FIELD(watch_mode_preserve_output), kAllowedInEnvvar, false, OptionNamespaces::kWatchNamespace); Implies("--watch-path", "--watch"); AddOption("--check", "syntax check script without executing", - &EnvironmentOptions::syntax_check_only); + BOOL_FIELD(syntax_check_only)); AddAlias("-c", "--check"); // This option is only so that we can tell --eval with an empty string from // no eval at all. Having it not start with a dash makes it inaccessible @@ -1192,12 +1190,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { // TODO(addaleax): When moving --help over to something generated from the // programmatic descriptions, this will need some special care. // (See also [ssl_openssl_cert_store] below.) - AddOption("[has_eval_string]", "", &EnvironmentOptions::has_eval_string); + AddOption("[has_eval_string]", "", BOOL_FIELD(has_eval_string)); AddOption("--eval", "evaluate script", &EnvironmentOptions::eval_string); Implies("--eval", "[has_eval_string]"); - AddOption("--print", - "evaluate script and print result", - &EnvironmentOptions::print_eval); + AddOption( + "--print", "evaluate script and print result", BOOL_FIELD(print_eval)); AddAlias("-e", "--eval"); AddAlias("--print ", "-pe"); AddAlias("-pe", { "--print", "--eval" }); @@ -1213,14 +1210,14 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--strip-types", "Type-stripping for TypeScript files.", - &EnvironmentOptions::strip_types, + BOOL_FIELD(strip_types), kAllowedInEnvvar, HAVE_AMARO); AddAlias("--experimental-strip-types", "--strip-types"); AddOption("--interactive", "always enter the REPL even if stdin does not appear " "to be a terminal", - &EnvironmentOptions::force_repl); + BOOL_FIELD(force_repl)); AddAlias("-i", "--interactive"); AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvvar); @@ -1232,23 +1229,23 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--tls-min-v1.0", "set default TLS minimum to TLSv1.0 (default: TLSv1.2)", - &EnvironmentOptions::tls_min_v1_0, + BOOL_FIELD(tls_min_v1_0), kAllowedInEnvvar); AddOption("--tls-min-v1.1", "set default TLS minimum to TLSv1.1 (default: TLSv1.2)", - &EnvironmentOptions::tls_min_v1_1, + BOOL_FIELD(tls_min_v1_1), kAllowedInEnvvar); AddOption("--tls-min-v1.2", "set default TLS minimum to TLSv1.2 (default: TLSv1.2)", - &EnvironmentOptions::tls_min_v1_2, + BOOL_FIELD(tls_min_v1_2), kAllowedInEnvvar); AddOption("--tls-min-v1.3", "set default TLS minimum to TLSv1.3 (default: TLSv1.2)", - &EnvironmentOptions::tls_min_v1_3, + BOOL_FIELD(tls_min_v1_3), kAllowedInEnvvar); AddOption("--tls-max-v1.2", "set default TLS maximum to TLSv1.2 (default: TLSv1.3)", - &EnvironmentOptions::tls_max_v1_2, + BOOL_FIELD(tls_max_v1_2), kAllowedInEnvvar); // Current plan is: // - 11.x and below: TLS1.3 is opt-in with --tls-max-v1.3 @@ -1256,18 +1253,18 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { // In either case, support both options they are uniformly available. AddOption("--tls-max-v1.3", "set default TLS maximum to TLSv1.3 (default: TLSv1.3)", - &EnvironmentOptions::tls_max_v1_3, + BOOL_FIELD(tls_max_v1_3), kAllowedInEnvvar); AddOption("--report-exclude-env", "Exclude environment variables when generating report" " (default: false)", - &EnvironmentOptions::report_exclude_env, + BOOL_FIELD(report_exclude_env), kAllowedInEnvvar); AddOption("--report-exclude-network", "exclude network interface diagnostics." " (default: false)", - &EnvironmentOptions::report_exclude_network, + BOOL_FIELD(report_exclude_network), kAllowedInEnvvar); } @@ -1275,7 +1272,7 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( const EnvironmentOptionsParser& eop) { AddOption("--track-heap-objects", "track heap object allocations for heap snapshots", - &PerIsolateOptions::track_heap_objects, + BOOL_FIELD(track_heap_objects), kAllowedInEnvvar); // Explicitly add some V8 flags to mark them as allowed in NODE_OPTIONS. @@ -1315,11 +1312,11 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( kAllowedInEnvvar); AddOption("--report-uncaught-exception", "generate diagnostic report on uncaught exceptions", - &PerIsolateOptions::report_uncaught_exception, + BOOL_FIELD(report_uncaught_exception), kAllowedInEnvvar); AddOption("--report-on-signal", "generate diagnostic report upon receiving signals", - &PerIsolateOptions::report_on_signal, + BOOL_FIELD(report_on_signal), kAllowedInEnvvar); AddOption("--report-signal", "causes diagnostic report to be produced on provided signal," @@ -1336,7 +1333,7 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( AddOption("--experimental-shadow-realm", "", - &PerIsolateOptions::experimental_shadow_realm, + BOOL_FIELD(experimental_shadow_realm), kAllowedInEnvvar); AddOption("--harmony-shadow-realm", "", V8Option{}); Implies("--experimental-shadow-realm", "--harmony-shadow-realm"); @@ -1344,7 +1341,7 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( ImpliesNot("--no-harmony-shadow-realm", "--experimental-shadow-realm"); AddOption("--build-snapshot", "Generate a snapshot blob when the process exits.", - &PerIsolateOptions::build_snapshot, + BOOL_FIELD(build_snapshot), kDisallowedInEnvvar); AddOption("--build-snapshot-config", "Generate a snapshot blob when the process exits using a" @@ -1379,11 +1376,11 @@ PerProcessOptionsParser::PerProcessOptionsParser( kAllowedInEnvvar); AddOption("--zero-fill-buffers", "automatically zero-fill all newly allocated Buffer instances", - &PerProcessOptions::zero_fill_all_buffers, + BOOL_FIELD(zero_fill_all_buffers), kAllowedInEnvvar); AddOption("--debug-arraybuffer-allocations", "", /* undocumented, only for debugging */ - &PerProcessOptions::debug_arraybuffer_allocations, + BOOL_FIELD(debug_arraybuffer_allocations), kAllowedInEnvvar); AddOption("--disable-proto", "disable Object.prototype.__proto__", @@ -1391,7 +1388,7 @@ PerProcessOptionsParser::PerProcessOptionsParser( kAllowedInEnvvar); AddOption("--node-snapshot", "", // It's a debug-only option. - &PerProcessOptions::node_snapshot, + BOOL_FIELD(node_snapshot), kAllowedInEnvvar); AddOption("--snapshot-blob", "Path to the snapshot blob that's either the result of snapshot" @@ -1407,20 +1404,18 @@ PerProcessOptionsParser::PerProcessOptionsParser( AddAlias("--security-reverts", "--security-revert"); AddOption("--completion-bash", "print source-able bash completion script", - &PerProcessOptions::print_bash_completion); - AddOption("--help", - "print node command line options", - &PerProcessOptions::print_help); - AddAlias("-h", "--help"); + BOOL_FIELD(print_bash_completion)); AddOption( - "--version", "print Node.js version", &PerProcessOptions::print_version); + "--help", "print node command line options", BOOL_FIELD(print_help)); + AddAlias("-h", "--help"); + AddOption("--version", "print Node.js version", BOOL_FIELD(print_version)); AddAlias("-v", "--version"); AddOption("--v8-options", "print V8 command line options", - &PerProcessOptions::print_v8_help); + BOOL_FIELD(print_v8_help)); AddOption("--report-compact", "output compact single-line JSON", - &PerProcessOptions::report_compact, + BOOL_FIELD(report_compact), kAllowedInEnvvar); AddOption("--report-dir", "define custom report pathname." @@ -1435,7 +1430,7 @@ PerProcessOptionsParser::PerProcessOptionsParser( kAllowedInEnvvar); AddOption("--report-on-fatalerror", "generate diagnostic report on fatal (internal) errors", - &PerProcessOptions::report_on_fatalerror, + BOOL_FIELD(report_on_fatalerror), kAllowedInEnvvar); #ifdef NODE_HAVE_I18N_SUPPORT @@ -1465,7 +1460,7 @@ PerProcessOptionsParser::PerProcessOptionsParser( " (default)" #endif , - &PerProcessOptions::use_openssl_ca, + BOOL_FIELD(use_openssl_ca), kAllowedInEnvvar); AddOption("--use-bundled-ca", "use bundled CA store" @@ -1473,23 +1468,21 @@ PerProcessOptionsParser::PerProcessOptionsParser( " (default)" #endif , - &PerProcessOptions::use_bundled_ca, + BOOL_FIELD(use_bundled_ca), kAllowedInEnvvar); // Similar to [has_eval_string] above, except that the separation between // this and use_openssl_ca only exists for option validation after parsing. // This is not ideal. - AddOption("[ssl_openssl_cert_store]", - "", - &PerProcessOptions::ssl_openssl_cert_store); + AddOption("[ssl_openssl_cert_store]", "", BOOL_FIELD(ssl_openssl_cert_store)); Implies("--use-openssl-ca", "[ssl_openssl_cert_store]"); ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]"); AddOption("--enable-fips", "enable FIPS crypto at startup", - &PerProcessOptions::enable_fips_crypto, + BOOL_FIELD(enable_fips_crypto), kAllowedInEnvvar); AddOption("--force-fips", "force FIPS crypto (cannot be disabled)", - &PerProcessOptions::force_fips_crypto, + BOOL_FIELD(force_fips_crypto), kAllowedInEnvvar); #ifndef V8_ENABLE_SANDBOX AddOption("--secure-heap", @@ -1505,11 +1498,11 @@ PerProcessOptionsParser::PerProcessOptionsParser( #if OPENSSL_VERSION_MAJOR >= 3 AddOption("--openssl-legacy-provider", "enable OpenSSL 3.0 legacy provider", - &PerProcessOptions::openssl_legacy_provider, + BOOL_FIELD(openssl_legacy_provider), kAllowedInEnvvar); AddOption("--openssl-shared-config", "enable OpenSSL shared configuration", - &PerProcessOptions::openssl_shared_config, + BOOL_FIELD(openssl_shared_config), kAllowedInEnvvar); #endif // OPENSSL_VERSION_MAJOR @@ -1523,7 +1516,7 @@ PerProcessOptionsParser::PerProcessOptionsParser( AddOption("--trace-sigint", "enable printing JavaScript stacktrace on SIGINT", - &PerProcessOptions::trace_sigint, + BOOL_FIELD(trace_sigint), kAllowedInEnvvar); Insert(iop, &PerProcessOptions::get_per_isolate_options); @@ -1548,7 +1541,7 @@ PerProcessOptionsParser::PerProcessOptionsParser( "Disable trap-handler-based WebAssembly bound checks. V8 will insert " "inline bound checks when compiling WebAssembly which may slow down " "performance.", - &PerProcessOptions::disable_wasm_trap_handler, + BOOL_FIELD(disable_wasm_trap_handler), kAllowedInEnvvar); AddOption("--build-sea", @@ -1773,7 +1766,7 @@ void GetCLIOptionsValues(const FunctionCallbackInfo& args) { } break; case kBoolean: { - bool original_value = *_ppop_instance.Lookup(field, opts); + bool original_value = field->GetBool(opts); value = Boolean::New(isolate, original_value); // Add --no-* entries. @@ -2090,7 +2083,7 @@ void GetOptionsAsFlags(const FunctionCallbackInfo& args) { switch (option_info.type) { case kBoolean: { - bool current_value = *_ppop_instance.Lookup(field, opts); + bool current_value = field->GetBool(opts); // For boolean options with default_is_true, we want the opposite logic if (option_info.default_is_true) { if (!current_value) { diff --git a/src/node_options.h b/src/node_options.h index 17faf4868bc..2421acbb78b 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -18,6 +18,9 @@ namespace node { +// Helper macro for defining a 1-bit boolean field in a struct. +#define DEFINE_BOOL_FIELD(field) uint8_t field : 1 + class HostPort { public: HostPort(const std::string& host_name, int port) @@ -53,8 +56,8 @@ class Options { }; struct InspectPublishUid { - bool console; - bool http; + DEFINE_BOOL_FIELD(console); + DEFINE_BOOL_FIELD(http); }; // These options are currently essentially per-Environment, but it can be nice @@ -69,19 +72,20 @@ class DebugOptions : public Options { DebugOptions(DebugOptions&&) = default; DebugOptions& operator=(DebugOptions&&) = default; - bool allow_attaching_debugger = true; + // --inspect-publish-uid + std::string inspect_publish_uid_string = "stderr,http"; + + DEFINE_BOOL_FIELD(allow_attaching_debugger) = true; // --inspect - bool inspector_enabled = false; + DEFINE_BOOL_FIELD(inspector_enabled) = false; // --inspect-wait - bool inspect_wait = false; + DEFINE_BOOL_FIELD(inspect_wait) = false; // --debug - bool deprecated_debug = false; + DEFINE_BOOL_FIELD(deprecated_debug) = false; // --inspect-brk - bool break_first_line = false; + DEFINE_BOOL_FIELD(break_first_line) = false; // --inspect-brk-node - bool break_node_first_line = false; - // --inspect-publish-uid - std::string inspect_publish_uid_string = "stderr,http"; + DEFINE_BOOL_FIELD(break_node_first_line) = false; InspectPublishUid inspect_publish_uid; @@ -118,170 +122,180 @@ class DebugOptions : public Options { class EnvironmentOptions : public Options { public: - bool abort_on_uncaught_exception = false; - std::vector conditions; - bool detect_module = true; - bool disable_sigusr1 = false; - bool print_required_tla = false; - bool require_module = true; +#if HAVE_INSPECTOR + static constexpr uint64_t kDefaultCpuProfInterval = 1000; + static constexpr uint64_t kDefaultHeapProfInterval = 512 * 1024; +#endif + static constexpr bool IS_DEBUG = +#ifdef DEBUG + true; +#else + false; +#endif // DEBUG + std::string dns_result_order; - bool enable_source_maps = false; - bool experimental_addon_modules = true; - bool experimental_eventsource = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_ffi = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_websocket = true; - bool experimental_sqlite = HAVE_SQLITE; - bool experimental_stream_iter = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_vfs = EXPERIMENTALS_DEFAULT_VALUE; - bool webstorage = HAVE_SQLITE; - bool experimental_dtls = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_quic = EXPERIMENTALS_DEFAULT_VALUE; std::string localstorage_file; - bool experimental_global_navigator = true; - bool experimental_global_web_crypto = true; - bool experimental_import_text = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_import_meta_resolve = EXPERIMENTALS_DEFAULT_VALUE; std::string input_type; // Value of --input-type - bool entry_is_url = false; - bool permission = false; - bool permission_audit = false; - std::vector allow_fs_read; - std::vector allow_fs_write; - bool allow_addons = false; - bool allow_inspector = false; - bool allow_child_process = false; - bool allow_net = false; - bool allow_wasi = false; - bool allow_ffi = false; - bool allow_openssl_store = false; - bool allow_worker_threads = false; - bool experimental_vm_modules = EXPERIMENTALS_DEFAULT_VALUE; - bool async_context_frame = true; - bool expose_internals = false; - bool force_node_api_uncaught_exceptions_policy = false; - bool frozen_intrinsics = false; - int64_t heap_snapshot_near_heap_limit = 0; std::string heap_snapshot_signal; - bool network_family_autoselection = true; - uint64_t network_family_autoselection_attempt_timeout = 500; - uint64_t max_http_header_size = 16 * 1024; - bool deprecation = true; - bool force_async_hooks_checks = true; - bool allow_native_addons = true; - bool global_search_paths = true; - bool warnings = true; - std::vector disable_warnings; - bool force_context_aware = false; - bool pending_deprecation = false; - bool preserve_symlinks = false; - bool preserve_symlinks_main = false; - bool prof_process = false; + std::string redirect_warnings; + std::string diagnostic_dir; + std::string test_rerun_failures_path; + std::string test_global_setup_path; + std::string test_isolation = "process"; + std::string test_shard; + std::string trace_require_module; + std::string unhandled_rejections; + std::string watch_mode_kill_signal = "SIGTERM"; + std::string eval_string; + std::string tls_keylog; + std::string experimental_config_file_path; + std::string experimental_package_map_path; #if HAVE_INSPECTOR std::string cpu_prof_dir; - static const uint64_t kDefaultCpuProfInterval = 1000; - uint64_t cpu_prof_interval = kDefaultCpuProfInterval; std::string cpu_prof_name; - bool cpu_prof = false; - bool experimental_network_inspection = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_worker_inspection = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_storage_inspection = EXPERIMENTALS_DEFAULT_VALUE; - bool experimental_inspector_network_resource = EXPERIMENTALS_DEFAULT_VALUE; std::string heap_prof_dir; std::string heap_prof_name; - static const uint64_t kDefaultHeapProfInterval = 512 * 1024; - uint64_t heap_prof_interval = kDefaultHeapProfInterval; - bool heap_prof = false; #endif // HAVE_INSPECTOR - std::string redirect_warnings; - std::string diagnostic_dir; + + std::vector conditions; + std::vector allow_fs_read; + std::vector allow_fs_write; + std::vector disable_warnings; std::vector env_file; std::vector optional_env_file; - bool has_env_file_string = false; - bool test_runner = false; - uint64_t test_runner_concurrency = 0; - uint64_t test_runner_timeout = 0; - bool test_runner_coverage = false; - bool test_runner_force_exit = false; - uint64_t test_coverage_branches = 0; - uint64_t test_coverage_functions = 0; - uint64_t test_coverage_lines = 0; - bool test_runner_module_mocks = false; - bool test_runner_update_snapshots = false; std::vector test_name_pattern; std::vector test_reporter; - std::string test_rerun_failures_path; std::vector test_reporter_destination; - std::string test_global_setup_path; - bool test_randomize = false; - bool has_test_random_seed = false; - uint64_t test_random_seed = 0; - bool test_only = false; - bool test_udp_no_try_send = false; - std::string test_isolation = "process"; - std::string test_shard; std::vector test_skip_pattern; std::vector experimental_test_tag_filter; std::vector coverage_include_pattern; - bool coverage_include_all = false; std::vector coverage_exclude_pattern; - bool throw_deprecation = false; - bool trace_deprecation = false; - bool trace_exit = false; - bool trace_sync_io = false; - bool trace_tls = false; - bool trace_uncaught = false; - bool trace_warnings = false; - bool trace_promises = false; - bool trace_env = false; - bool trace_env_js_stack = false; - bool trace_env_native_stack = false; - bool use_system_ca = false; - std::string trace_require_module; - bool extra_info_on_fatal_exception = true; - std::string unhandled_rejections; std::vector userland_loaders; - bool verify_base_objects = -#ifdef DEBUG - true; -#else - false; -#endif // DEBUG - - bool watch_mode = false; - bool watch_mode_report_to_parent = false; - bool watch_mode_preserve_output = false; - std::string watch_mode_kill_signal = "SIGTERM"; std::vector watch_mode_paths; - - bool syntax_check_only = false; - bool has_eval_string = false; - std::string eval_string; - bool print_eval = false; - bool force_repl = false; - - bool insecure_http_parser = false; - bool use_env_proxy = false; - - bool tls_min_v1_0 = false; - bool tls_min_v1_1 = false; - bool tls_min_v1_2 = false; - bool tls_min_v1_3 = false; - bool tls_max_v1_2 = false; - bool tls_max_v1_3 = false; - std::string tls_keylog; - std::vector preload_cjs_modules; - std::vector preload_esm_modules; - - bool strip_types = HAVE_AMARO; - std::vector user_argv; - bool report_exclude_env = false; - bool report_exclude_network = false; - std::string experimental_config_file_path; - std::string experimental_package_map_path; + int64_t heap_snapshot_near_heap_limit = 0; + uint64_t network_family_autoselection_attempt_timeout = 500; + uint64_t max_http_header_size = 16 * 1024; + uint64_t test_runner_concurrency = 0; + uint64_t test_runner_timeout = 0; + uint64_t test_coverage_branches = 0; + uint64_t test_coverage_functions = 0; + uint64_t test_coverage_lines = 0; + uint64_t test_random_seed = 0; +#if HAVE_INSPECTOR + uint64_t cpu_prof_interval = kDefaultCpuProfInterval; + uint64_t heap_prof_interval = kDefaultHeapProfInterval; +#endif // HAVE_INSPECTOR + + // These are intentionally not bools. They are 1 bit packed flags in + // order to reduce the overall size of the struct. + + DEFINE_BOOL_FIELD(abort_on_uncaught_exception) = false; + DEFINE_BOOL_FIELD(detect_module) = true; + DEFINE_BOOL_FIELD(disable_sigusr1) = false; + DEFINE_BOOL_FIELD(print_required_tla) = false; + DEFINE_BOOL_FIELD(require_module) = true; + DEFINE_BOOL_FIELD(enable_source_maps) = false; + DEFINE_BOOL_FIELD(experimental_addon_modules) = true; + DEFINE_BOOL_FIELD(experimental_eventsource) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_ffi) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_websocket) = true; + DEFINE_BOOL_FIELD(experimental_sqlite) = HAVE_SQLITE; + DEFINE_BOOL_FIELD(experimental_stream_iter) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_vfs) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(webstorage) = HAVE_SQLITE; + DEFINE_BOOL_FIELD(experimental_dtls) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_quic) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_global_navigator) = true; + DEFINE_BOOL_FIELD(experimental_global_web_crypto) = true; + DEFINE_BOOL_FIELD(experimental_import_text) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_import_meta_resolve) = + EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(entry_is_url) = false; + DEFINE_BOOL_FIELD(permission) = false; + DEFINE_BOOL_FIELD(permission_audit) = false; + DEFINE_BOOL_FIELD(allow_addons) = false; + DEFINE_BOOL_FIELD(allow_inspector) = false; + DEFINE_BOOL_FIELD(allow_child_process) = false; + DEFINE_BOOL_FIELD(allow_net) = false; + DEFINE_BOOL_FIELD(allow_wasi) = false; + DEFINE_BOOL_FIELD(allow_ffi) = false; + DEFINE_BOOL_FIELD(allow_openssl_store) = false; + DEFINE_BOOL_FIELD(allow_worker_threads) = false; + DEFINE_BOOL_FIELD(experimental_vm_modules) = EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(async_context_frame) = true; + DEFINE_BOOL_FIELD(expose_internals) = false; + DEFINE_BOOL_FIELD(force_node_api_uncaught_exceptions_policy) = false; + DEFINE_BOOL_FIELD(frozen_intrinsics) = false; + DEFINE_BOOL_FIELD(network_family_autoselection) = true; + DEFINE_BOOL_FIELD(deprecation) = true; + DEFINE_BOOL_FIELD(force_async_hooks_checks) = true; + DEFINE_BOOL_FIELD(allow_native_addons) = true; + DEFINE_BOOL_FIELD(global_search_paths) = true; + DEFINE_BOOL_FIELD(warnings) = true; + DEFINE_BOOL_FIELD(force_context_aware) = false; + DEFINE_BOOL_FIELD(pending_deprecation) = false; + DEFINE_BOOL_FIELD(preserve_symlinks) = false; + DEFINE_BOOL_FIELD(preserve_symlinks_main) = false; + DEFINE_BOOL_FIELD(prof_process) = false; + DEFINE_BOOL_FIELD(has_env_file_string) = false; + DEFINE_BOOL_FIELD(test_runner) = false; + DEFINE_BOOL_FIELD(test_runner_coverage) = false; + DEFINE_BOOL_FIELD(test_runner_force_exit) = false; + DEFINE_BOOL_FIELD(test_runner_module_mocks) = false; + DEFINE_BOOL_FIELD(test_runner_update_snapshots) = false; + DEFINE_BOOL_FIELD(test_randomize) = false; + DEFINE_BOOL_FIELD(has_test_random_seed) = false; + DEFINE_BOOL_FIELD(test_only) = false; + DEFINE_BOOL_FIELD(test_udp_no_try_send) = false; + DEFINE_BOOL_FIELD(coverage_include_all) = false; + DEFINE_BOOL_FIELD(throw_deprecation) = false; + DEFINE_BOOL_FIELD(trace_deprecation) = false; + DEFINE_BOOL_FIELD(trace_exit) = false; + DEFINE_BOOL_FIELD(trace_sync_io) = false; + DEFINE_BOOL_FIELD(trace_tls) = false; + DEFINE_BOOL_FIELD(trace_uncaught) = false; + DEFINE_BOOL_FIELD(trace_warnings) = false; + DEFINE_BOOL_FIELD(trace_promises) = false; + DEFINE_BOOL_FIELD(trace_env) = false; + DEFINE_BOOL_FIELD(trace_env_js_stack) = false; + DEFINE_BOOL_FIELD(trace_env_native_stack) = false; + DEFINE_BOOL_FIELD(use_system_ca) = false; + DEFINE_BOOL_FIELD(extra_info_on_fatal_exception) = true; + DEFINE_BOOL_FIELD(verify_base_objects) = IS_DEBUG; + DEFINE_BOOL_FIELD(watch_mode) = false; + DEFINE_BOOL_FIELD(watch_mode_report_to_parent) = false; + DEFINE_BOOL_FIELD(watch_mode_preserve_output) = false; + DEFINE_BOOL_FIELD(syntax_check_only) = false; + DEFINE_BOOL_FIELD(has_eval_string) = false; + DEFINE_BOOL_FIELD(print_eval) = false; + DEFINE_BOOL_FIELD(force_repl) = false; + DEFINE_BOOL_FIELD(insecure_http_parser) = false; + DEFINE_BOOL_FIELD(use_env_proxy) = false; + DEFINE_BOOL_FIELD(tls_min_v1_0) = false; + DEFINE_BOOL_FIELD(tls_min_v1_1) = false; + DEFINE_BOOL_FIELD(tls_min_v1_2) = false; + DEFINE_BOOL_FIELD(tls_min_v1_3) = false; + DEFINE_BOOL_FIELD(tls_max_v1_2) = false; + DEFINE_BOOL_FIELD(tls_max_v1_3) = false; + DEFINE_BOOL_FIELD(strip_types) = HAVE_AMARO; + DEFINE_BOOL_FIELD(report_exclude_env) = false; + DEFINE_BOOL_FIELD(report_exclude_network) = false; +#if HAVE_INSPECTOR + DEFINE_BOOL_FIELD(cpu_prof) = false; + DEFINE_BOOL_FIELD(experimental_network_inspection) = + EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_worker_inspection) = + EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_storage_inspection) = + EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(experimental_inspector_network_resource) = + EXPERIMENTALS_DEFAULT_VALUE; + DEFINE_BOOL_FIELD(heap_prof) = false; +#endif // HAVE_INSPECTOR inline DebugOptions* get_debug_options() { return &debug_options_; } inline const DebugOptions& debug_options() const { return debug_options_; } @@ -299,16 +313,20 @@ class PerIsolateOptions : public Options { PerIsolateOptions(PerIsolateOptions&&) = default; std::shared_ptr per_env{new EnvironmentOptions()}; - bool track_heap_objects = false; - bool report_uncaught_exception = false; - bool report_on_signal = false; - bool experimental_shadow_realm = false; + std::string max_old_space_size_percentage; std::string max_old_space_size; - int64_t stack_trace_limit = 10; std::string report_signal = "SIGUSR2"; - bool build_snapshot = false; std::string build_snapshot_config; + + int64_t stack_trace_limit = 10; + + DEFINE_BOOL_FIELD(track_heap_objects) = false; + DEFINE_BOOL_FIELD(report_uncaught_exception) = false; + DEFINE_BOOL_FIELD(report_on_signal) = false; + DEFINE_BOOL_FIELD(experimental_shadow_realm) = false; + DEFINE_BOOL_FIELD(build_snapshot) = false; + inline EnvironmentOptions* get_per_env_options(); void CheckOptions(std::vector* errors, std::vector* argv) override; @@ -340,63 +358,67 @@ class PerProcessOptions : public Options { #else std::string trace_event_file_pattern = "node_trace.${rotation}.log"; #endif - int64_t v8_thread_pool_size = 4; - bool zero_fill_all_buffers = false; - bool debug_arraybuffer_allocations = false; std::string disable_proto; - // We enable the shared read-only heap which currently requires that the - // snapshot used in different isolates in the same process to be the same. - // Therefore --node-snapshot is a per-process option. - bool node_snapshot = true; std::string snapshot_blob; - - std::vector security_reverts; - bool print_bash_completion = false; - bool print_help = false; - bool print_v8_help = false; - bool print_version = false; std::string experimental_sea_config; std::string run; - std::string build_sea; #ifdef NODE_HAVE_I18N_SUPPORT std::string icu_data_dir; #endif - - // Per-process because they affect singleton OpenSSL shared library state, - // or are used once during process initialization. +// Per-process because they affect singleton OpenSSL shared library state, +// or are used once during process initialization. #if HAVE_OPENSSL std::string openssl_config; std::string tls_cipher_list = DEFAULT_CIPHER_LIST_CORE; +#endif // HAVE_OPENSSL + std::string report_directory; + std::string report_filename; + // TODO(addaleax): Some of these could probably be per-Environment. + std::string use_largepages = "off"; + + std::vector security_reverts; + std::vector cmdline; + + int64_t v8_thread_pool_size = 4; +#if HAVE_OPENSSL int64_t secure_heap = 0; int64_t secure_heap_min = 2; +#endif // HAVE_OPENSSL + + DEFINE_BOOL_FIELD(zero_fill_all_buffers) = false; + DEFINE_BOOL_FIELD(debug_arraybuffer_allocations) = false; + + // We enable the shared read-only heap which currently requires that the + // snapshot used in different isolates in the same process to be the same. + // Therefore --node-snapshot is a per-process option. + DEFINE_BOOL_FIELD(node_snapshot) = true; + + DEFINE_BOOL_FIELD(print_bash_completion) = false; + DEFINE_BOOL_FIELD(print_help) = false; + DEFINE_BOOL_FIELD(print_v8_help) = false; + DEFINE_BOOL_FIELD(print_version) = false; + +#if HAVE_OPENSSL #ifdef NODE_OPENSSL_CERT_STORE - bool ssl_openssl_cert_store = true; + DEFINE_BOOL_FIELD(ssl_openssl_cert_store) = true; #else - bool ssl_openssl_cert_store = false; -#endif - bool use_openssl_ca = false; - bool use_bundled_ca = false; - bool enable_fips_crypto = false; - bool force_fips_crypto = false; -#endif + DEFINE_BOOL_FIELD(ssl_openssl_cert_store) = false; +#endif // NODE_OPENSSL_CERT_STORE + DEFINE_BOOL_FIELD(use_openssl_ca) = false; + DEFINE_BOOL_FIELD(use_bundled_ca) = false; + DEFINE_BOOL_FIELD(enable_fips_crypto) = false; + DEFINE_BOOL_FIELD(force_fips_crypto) = false; +#endif // HAVE_OPENSSL #if OPENSSL_VERSION_MAJOR >= 3 - bool openssl_legacy_provider = false; - bool openssl_shared_config = false; + DEFINE_BOOL_FIELD(openssl_legacy_provider) = false; + DEFINE_BOOL_FIELD(openssl_shared_config) = false; #endif - bool disable_wasm_trap_handler = false; - - // Per-process because reports can be triggered outside a known V8 context. - bool report_on_fatalerror = false; - bool report_compact = false; - std::string report_directory; - std::string report_filename; - - // TODO(addaleax): Some of these could probably be per-Environment. - std::string use_largepages = "off"; - bool trace_sigint = false; - std::vector cmdline; + DEFINE_BOOL_FIELD(disable_wasm_trap_handler) = false; + DEFINE_BOOL_FIELD(report_on_fatalerror) = false; + DEFINE_BOOL_FIELD(report_compact) = false; + DEFINE_BOOL_FIELD(trace_sigint) = false; inline PerIsolateOptions* get_per_isolate_options(); void CheckOptions(std::vector* errors, @@ -489,7 +511,8 @@ class OptionsParser { void AddOption( const char* name, const char* help_text, - bool Options::*field, + bool (*getter)(Options*), + void (*setter)(Options*, bool), OptionEnvvarSettings env_setting = kDisallowedInEnvvar, bool default_is_true = false, OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace); @@ -593,6 +616,16 @@ class OptionsParser { virtual ~BaseOptionField() = default; virtual void* LookupImpl(Options* options) const = 0; + // For boolean bit-field options, we can't return a pointer so we + // use virtual getter/setter methods instead. The default + // implementations go through LookupImpl for non-bit-field types. + virtual bool GetBool(Options* options) const { + return *static_cast(LookupImpl(options)); + } + virtual void SetBool(Options* options, bool value) { + *static_cast(LookupImpl(options)) = value; + } + template inline T* Lookup(Options* options) const { return static_cast(LookupImpl(options)); @@ -613,6 +646,28 @@ class OptionsParser { T Options::* field_; }; + // Represents a boolean bit-field within `Options`. Bit-fields cannot + // have their address taken, so we use getter/setter function pointers + // instead of a pointer-to-member. + class BitFieldOptionField : public BaseOptionField { + public: + using Getter = bool (*)(Options*); + using Setter = void (*)(Options*, bool); + + BitFieldOptionField(Getter get, Setter set) : get_(get), set_(set) {} + + void* LookupImpl(Options* options) const override { UNREACHABLE(); } + + bool GetBool(Options* options) const override { return get_(options); } + void SetBool(Options* options, bool value) override { + set_(options, value); + } + + private: + Getter get_; + Setter set_; + }; + template inline T* Lookup(std::shared_ptr field, Options* options) const { @@ -690,6 +745,14 @@ void Parse(StringVector* const args, } // namespace options_parser +// Helper macro for passing bit-field members to AddOption(). Expands to a +// getter and setter function pointer pair that can read/write the named +// bit-field without requiring a pointer-to-member (which is illegal for +// bit-fields). +#define BOOL_FIELD(field) \ + +[](TargetType* opts) -> bool { return opts->field; }, \ + +[](TargetType* opts, bool v) { opts->field = v; } + namespace per_process { extern Mutex cli_options_mutex; @@ -703,6 +766,8 @@ void HandleEnvOptions(std::shared_ptr env_options, std::vector ParseNodeOptionsEnvVar( const std::string& node_options, std::vector* errors); + +#undef DEFINE_BOOL_FIELD } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/node_report_module.cc b/src/node_report_module.cc index 6525214ab9d..6de949facfa 100644 --- a/src/node_report_module.cc +++ b/src/node_report_module.cc @@ -77,7 +77,8 @@ void GetReport(const FunctionCallbackInfo& info) { static void GetCompact(const FunctionCallbackInfo& info) { Mutex::ScopedLock lock(per_process::cli_options_mutex); - info.GetReturnValue().Set(per_process::cli_options->report_compact); + info.GetReturnValue().Set( + static_cast(per_process::cli_options->report_compact)); } static void SetCompact(const FunctionCallbackInfo& info) { @@ -89,7 +90,8 @@ static void SetCompact(const FunctionCallbackInfo& info) { static void GetExcludeNetwork(const FunctionCallbackInfo& info) { Environment* env = Environment::GetCurrent(info); - info.GetReturnValue().Set(env->options()->report_exclude_network); + info.GetReturnValue().Set( + static_cast(env->options()->report_exclude_network)); } static void SetExcludeNetwork(const FunctionCallbackInfo& info) { @@ -161,7 +163,8 @@ static void SetSignal(const FunctionCallbackInfo& info) { static void ShouldReportOnFatalError(const FunctionCallbackInfo& info) { Mutex::ScopedLock lock(per_process::cli_options_mutex); - info.GetReturnValue().Set(per_process::cli_options->report_on_fatalerror); + info.GetReturnValue().Set( + static_cast(per_process::cli_options->report_on_fatalerror)); } static void SetReportOnFatalError(const FunctionCallbackInfo& info) { @@ -172,7 +175,8 @@ static void SetReportOnFatalError(const FunctionCallbackInfo& info) { static void ShouldReportOnSignal(const FunctionCallbackInfo& info) { Environment* env = Environment::GetCurrent(info); - info.GetReturnValue().Set(env->isolate_data()->options()->report_on_signal); + info.GetReturnValue().Set( + static_cast(env->isolate_data()->options()->report_on_signal)); } static void SetReportOnSignal(const FunctionCallbackInfo& info) { @@ -184,8 +188,8 @@ static void SetReportOnSignal(const FunctionCallbackInfo& info) { static void ShouldReportOnUncaughtException( const FunctionCallbackInfo& info) { Environment* env = Environment::GetCurrent(info); - info.GetReturnValue().Set( - env->isolate_data()->options()->report_uncaught_exception); + info.GetReturnValue().Set(static_cast( + env->isolate_data()->options()->report_uncaught_exception)); } static void SetReportOnUncaughtException(