mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Remove the OpenSSL 1.x branches and stale version-specific assumptions from src/. BoringSSL does not define OPENSSL_VERSION_MAJOR, so the remaining version guards were excluding it as well; use OPENSSL_IS_BORINGSSL checks instead, including the shared PKCS12 parser and TLS PFX error handling. Gate BoringSSL-only alternatives explicitly instead of leaving them in #else branches, including the MAC/KMAC and OCB fallbacks. Fix the BoringSSL guard on QUIC's unsupported-backend diagnostic. Make the OpenSSL legacy-provider command-line help version-neutral. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/64777 Fixes: https://github.com/nodejs/node/issues/56733 Refs: https://github.com/nodejs/node/pull/64211 Refs: https://github.com/nodejs/node/pull/63966 Refs: https://github.com/nodejs/node/pull/53329 Refs: https://github.com/nodejs/node/pull/48950 Refs: https://github.com/nodejs/node/issues/45465 Refs: https://github.com/nodejs/node/issues/42827 Refs: https://github.com/nodejs/node/issues/47076 Refs: https://github.com/nodejs/node/pull/62862 Refs: https://github.com/nodejs/node/pull/38512 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
825 lines
30 KiB
C++
825 lines
30 KiB
C++
#ifndef SRC_NODE_OPTIONS_H_
|
|
#define SRC_NODE_OPTIONS_H_
|
|
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include "node_constants.h"
|
|
#include "node_mutex.h"
|
|
#include "util.h"
|
|
|
|
#if HAVE_OPENSSL
|
|
#include "openssl/opensslv.h"
|
|
#include "quic/guard.h"
|
|
#endif
|
|
|
|
namespace node {
|
|
|
|
// Helper macro for defining a 1-bit boolean field in a struct.
|
|
#define DEFINE_BOOL_FIELD(field) bool field : 1
|
|
|
|
class HostPort {
|
|
public:
|
|
HostPort(const std::string& host_name, int port)
|
|
: host_name_(host_name), port_(port) {}
|
|
HostPort(const HostPort&) = default;
|
|
HostPort& operator=(const HostPort&) = default;
|
|
HostPort(HostPort&&) = default;
|
|
HostPort& operator=(HostPort&&) = default;
|
|
|
|
void set_host(const std::string& host) { host_name_ = host; }
|
|
|
|
void set_port(uint16_t port) { port_ = port; }
|
|
|
|
const std::string& host() const { return host_name_; }
|
|
|
|
uint16_t port() const { return port_; }
|
|
|
|
void Update(const HostPort& other) {
|
|
if (!other.host_name_.empty()) host_name_ = other.host_name_;
|
|
port_ = other.port_;
|
|
}
|
|
|
|
private:
|
|
std::string host_name_;
|
|
uint16_t port_;
|
|
};
|
|
|
|
class Options {
|
|
public:
|
|
virtual void CheckOptions(std::vector<std::string>* errors,
|
|
std::vector<std::string>* argv) {}
|
|
virtual ~Options() = default;
|
|
};
|
|
|
|
struct InspectPublishUid {
|
|
DEFINE_BOOL_FIELD(console);
|
|
DEFINE_BOOL_FIELD(http);
|
|
};
|
|
|
|
// These options are currently essentially per-Environment, but it can be nice
|
|
// to keep them separate since they are a group of options applying to a very
|
|
// specific part of Node. It might also make more sense for them to be
|
|
// per-Isolate, rather than per-Environment.
|
|
class DebugOptions : public Options {
|
|
public:
|
|
DebugOptions() = default;
|
|
DebugOptions(const DebugOptions&) = default;
|
|
DebugOptions& operator=(const DebugOptions&) = default;
|
|
DebugOptions(DebugOptions&&) = default;
|
|
DebugOptions& operator=(DebugOptions&&) = default;
|
|
|
|
// --inspect-publish-uid
|
|
std::string inspect_publish_uid_string = "stderr,http";
|
|
|
|
DEFINE_BOOL_FIELD(allow_attaching_debugger) = true;
|
|
// --inspect
|
|
DEFINE_BOOL_FIELD(inspector_enabled) = false;
|
|
// --inspect-wait
|
|
DEFINE_BOOL_FIELD(inspect_wait) = false;
|
|
// --debug
|
|
DEFINE_BOOL_FIELD(deprecated_debug) = false;
|
|
// --inspect-brk
|
|
DEFINE_BOOL_FIELD(break_first_line) = false;
|
|
// --inspect-brk-node
|
|
DEFINE_BOOL_FIELD(break_node_first_line) = false;
|
|
|
|
InspectPublishUid inspect_publish_uid;
|
|
|
|
enum { kDefaultInspectorPort = 9229 };
|
|
|
|
HostPort host_port{"127.0.0.1", kDefaultInspectorPort};
|
|
|
|
// Used to patch the options as if --inspect-brk is passed.
|
|
void EnableBreakFirstLine() {
|
|
inspector_enabled = true;
|
|
break_first_line = true;
|
|
}
|
|
|
|
void DisableWaitOrBreakFirstLine() {
|
|
inspect_wait = false;
|
|
break_first_line = false;
|
|
}
|
|
|
|
bool wait_for_connect() const {
|
|
return break_first_line || break_node_first_line || inspect_wait;
|
|
}
|
|
|
|
bool should_break_first_line() const {
|
|
return break_first_line || break_node_first_line;
|
|
}
|
|
|
|
void CheckOptions(std::vector<std::string>* errors,
|
|
std::vector<std::string>* argv) override;
|
|
};
|
|
|
|
#ifndef EXPERIMENTALS_DEFAULT_VALUE
|
|
#define EXPERIMENTALS_DEFAULT_VALUE false
|
|
#endif
|
|
|
|
class EnvironmentOptions : public Options {
|
|
public:
|
|
#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;
|
|
std::string localstorage_file;
|
|
std::string input_type; // Value of --input-type
|
|
std::string heap_snapshot_signal;
|
|
std::string redirect_warnings;
|
|
std::string diagnostic_dir;
|
|
std::string bench_isolation = "process";
|
|
std::string bench_name_pattern;
|
|
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 config_file_path;
|
|
std::string experimental_package_map_path;
|
|
std::string vfs_load_source;
|
|
#if HAVE_INSPECTOR
|
|
std::string cpu_prof_dir;
|
|
std::string cpu_prof_name;
|
|
std::string heap_prof_dir;
|
|
std::string heap_prof_name;
|
|
#endif // HAVE_INSPECTOR
|
|
|
|
std::vector<std::string> conditions;
|
|
std::vector<std::string> allow_env;
|
|
std::vector<std::string> allow_fs_read;
|
|
std::vector<std::string> allow_fs_write;
|
|
std::vector<std::string> disable_warnings;
|
|
std::vector<std::string> bench_reporter;
|
|
std::vector<std::string> bench_reporter_destination;
|
|
std::vector<std::string> env_file;
|
|
std::vector<std::string> optional_env_file;
|
|
std::vector<std::string> test_name_pattern;
|
|
std::vector<std::string> test_reporter;
|
|
std::vector<std::string> test_reporter_destination;
|
|
std::vector<std::string> test_skip_pattern;
|
|
std::vector<std::string> experimental_test_tag_filter;
|
|
std::vector<std::string> coverage_include_pattern;
|
|
std::vector<std::string> coverage_exclude_pattern;
|
|
std::vector<std::string> userland_loaders;
|
|
std::vector<std::string> watch_mode_paths;
|
|
std::vector<std::string> preload_cjs_modules;
|
|
std::vector<std::string> preload_esm_modules;
|
|
std::vector<std::string> user_argv;
|
|
|
|
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 bench_samples = 0;
|
|
uint64_t bench_warmup = 0;
|
|
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_bench) = EXPERIMENTALS_DEFAULT_VALUE;
|
|
DEFINE_BOOL_FIELD(experimental_eventsource) = EXPERIMENTALS_DEFAULT_VALUE;
|
|
DEFINE_BOOL_FIELD(experimental_ffi) = HAVE_FFI;
|
|
DEFINE_BOOL_FIELD(experimental_web_worker) = 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) = true;
|
|
DEFINE_BOOL_FIELD(vfs_load) = false;
|
|
DEFINE_BOOL_FIELD(sea_vfs_archive) = false;
|
|
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_fs_vfs) = 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(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(bench_runner) = false;
|
|
DEFINE_BOOL_FIELD(has_bench_options) = false;
|
|
DEFINE_BOOL_FIELD(has_bench_samples) = false;
|
|
DEFINE_BOOL_FIELD(has_bench_warmup) = 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_forbid_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(experimental_strip_private_modules) =
|
|
EXPERIMENTALS_DEFAULT_VALUE;
|
|
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_; }
|
|
|
|
void CheckOptions(std::vector<std::string>* errors,
|
|
std::vector<std::string>* argv) override;
|
|
|
|
// `--bench` and the other benchmark runner options are gated behind
|
|
// `--experimental-bench`, but the gate and the options it guards can come
|
|
// from different option sources, each of which is parsed in its own
|
|
// options_parser::Parse() pass. CheckOptions() runs at the end of every
|
|
// pass, so this constraint cannot be validated there: the gate may still
|
|
// arrive in a later pass. Callers must invoke this once all of their option
|
|
// sources have been parsed.
|
|
void CheckBenchOptions(std::vector<std::string>* errors) const;
|
|
|
|
private:
|
|
DebugOptions debug_options_;
|
|
};
|
|
|
|
class PerIsolateOptions : public Options {
|
|
public:
|
|
bool worker_snapshot = true; // --[no-]worker-snapshot
|
|
PerIsolateOptions() = default;
|
|
PerIsolateOptions(PerIsolateOptions&&) = default;
|
|
|
|
std::shared_ptr<EnvironmentOptions> per_env{new EnvironmentOptions()};
|
|
|
|
std::string max_old_space_size_percentage;
|
|
std::string max_old_space_size;
|
|
std::string report_signal = "SIGUSR2";
|
|
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<std::string>* errors,
|
|
std::vector<std::string>* argv) override;
|
|
void HandleMaxOldSpaceSizePercentage(std::vector<std::string>* errors,
|
|
std::string* max_old_space_size);
|
|
|
|
inline std::shared_ptr<PerIsolateOptions> Clone() const;
|
|
|
|
private:
|
|
PerIsolateOptions(const PerIsolateOptions&) = default;
|
|
};
|
|
|
|
class PerProcessOptions : public Options {
|
|
public:
|
|
// Options shouldn't be here unless they affect the entire process scope, and
|
|
// that should avoided when possible.
|
|
//
|
|
// When an option is used during process initialization, it does not need
|
|
// protection, but any use after that will likely require synchronization
|
|
// using the node::per_process::cli_options_mutex, typically:
|
|
//
|
|
// Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
|
|
std::shared_ptr<PerIsolateOptions> per_isolate{new PerIsolateOptions()};
|
|
|
|
std::string title;
|
|
std::string trace_event_categories;
|
|
#if defined(V8_USE_PERFETTO)
|
|
std::string trace_event_file_pattern = "node_trace.${rotation}.pftrace";
|
|
#else
|
|
std::string trace_event_file_pattern = "node_trace.${rotation}.log";
|
|
#endif
|
|
std::string disable_proto;
|
|
std::string snapshot_blob;
|
|
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.
|
|
#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";
|
|
// --process-timeout, as passed on the command line (e.g. "30s").
|
|
std::string process_timeout;
|
|
// The parsed value of --process-timeout, or 0 if it was not passed.
|
|
uint64_t process_timeout_ms = 0;
|
|
|
|
std::vector<std::string> security_reverts;
|
|
std::vector<std::string> 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
|
|
DEFINE_BOOL_FIELD(ssl_openssl_cert_store) = true;
|
|
#else
|
|
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(enable_fips_indicator_events) = false;
|
|
DEFINE_BOOL_FIELD(force_fips_crypto) = false;
|
|
std::string force_fips_crypto_policy = "provider";
|
|
#endif // HAVE_OPENSSL
|
|
#if HAVE_OPENSSL && !defined(OPENSSL_IS_BORINGSSL)
|
|
DEFINE_BOOL_FIELD(openssl_legacy_provider) = false;
|
|
DEFINE_BOOL_FIELD(openssl_shared_config) = false;
|
|
#endif
|
|
|
|
DEFINE_BOOL_FIELD(disable_wasm_trap_handler) = false;
|
|
DEFINE_BOOL_FIELD(report_on_fatalerror) = false;
|
|
DEFINE_BOOL_FIELD(report_on_process_timeout) = false;
|
|
DEFINE_BOOL_FIELD(report_compact) = false;
|
|
DEFINE_BOOL_FIELD(trace_sigint) = false;
|
|
// Tracks whether `--run` was passed, since an empty `run` is ambiguous
|
|
// between "not passed" and "passed without a script name" (lists scripts).
|
|
DEFINE_BOOL_FIELD(has_run) = false;
|
|
|
|
inline PerIsolateOptions* get_per_isolate_options();
|
|
void CheckOptions(std::vector<std::string>* errors,
|
|
std::vector<std::string>* argv) override;
|
|
|
|
// `--process-timeout` conflicts with options that can come from different
|
|
// option sources (e.g. `--inspect` from NODE_OPTIONS), each of which is
|
|
// parsed in its own options_parser::Parse() pass. Callers must invoke this
|
|
// once all of their option sources have been parsed. `argv` holds the
|
|
// remaining non-option arguments, starting with the program name.
|
|
void CheckProcessTimeoutOptions(std::vector<std::string>* errors,
|
|
const std::vector<std::string>& argv) const;
|
|
};
|
|
|
|
// The actual options parser, as opposed to the structs containing them:
|
|
|
|
namespace options_parser {
|
|
|
|
HostPort SplitHostPort(const std::string& arg,
|
|
std::vector<std::string>* errors);
|
|
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
std::string GetBashCompletion();
|
|
|
|
enum OptionType {
|
|
kNoOp,
|
|
kV8Option,
|
|
kBoolean,
|
|
kInteger,
|
|
kUInteger,
|
|
kString,
|
|
kHostPort,
|
|
kStringList,
|
|
};
|
|
struct OptionMappingDetails {
|
|
OptionType type;
|
|
std::string help_text;
|
|
};
|
|
std::unordered_map<std::string, OptionMappingDetails>
|
|
MapEnvOptionsFlagInputType();
|
|
std::unordered_map<std::string, OptionMappingDetails> MapOptionsByNamespace(
|
|
std::string namespace_name);
|
|
std::unordered_map<
|
|
std::string,
|
|
std::unordered_map<std::string, options_parser::OptionMappingDetails>>
|
|
MapNamespaceOptionsAssociations();
|
|
std::vector<std::string> MapAvailableNamespaces();
|
|
|
|
// Define all namespace entries
|
|
#define OPTION_NAMESPACE_LIST(V) \
|
|
V(kNoNamespace, "") \
|
|
V(kBenchRunnerNamespace, "bench") \
|
|
V(kTestRunnerNamespace, "test") \
|
|
V(kWatchNamespace, "watch") \
|
|
V(kPermissionNamespace, "permission")
|
|
|
|
enum class OptionNamespaces {
|
|
#define V(name, _) name,
|
|
OPTION_NAMESPACE_LIST(V)
|
|
#undef V
|
|
};
|
|
|
|
inline const std::string NamespaceEnumToString(OptionNamespaces ns) {
|
|
switch (ns) {
|
|
#define V(name, string_value) \
|
|
case OptionNamespaces::name: \
|
|
return string_value;
|
|
OPTION_NAMESPACE_LIST(V)
|
|
#undef V
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
inline constexpr auto AllNamespaces() {
|
|
return std::array{
|
|
#define V(name, _) OptionNamespaces::name,
|
|
OPTION_NAMESPACE_LIST(V)
|
|
#undef V
|
|
};
|
|
}
|
|
|
|
template <typename Options>
|
|
class OptionsParser {
|
|
public:
|
|
virtual ~OptionsParser() = default;
|
|
|
|
typedef Options TargetType;
|
|
|
|
struct NoOp {};
|
|
struct V8Option {};
|
|
|
|
// These methods add a single option to the parser. Optionally, it can be
|
|
// specified whether the option should be allowed from environment variable
|
|
// sources (i.e. NODE_OPTIONS).
|
|
|
|
// default_is_true is only a hint in printing help text, it does not
|
|
// affect the default value of the option. Set the default value in the
|
|
// Options struct instead.
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
bool (*getter)(Options*),
|
|
void (*setter)(Options*, bool),
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
bool default_is_true = false,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(const char* name,
|
|
const char* help_text,
|
|
uint64_t Options::*field,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace,
|
|
bool strict = false);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
int64_t Options::*field,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
std::string Options::*field,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
std::vector<std::string> Options::*field,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
HostPort Options::*field,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
NoOp no_op_tag,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
void AddOption(
|
|
const char* name,
|
|
const char* help_text,
|
|
V8Option v8_option_tag,
|
|
OptionEnvvarSettings env_setting = kDisallowedInEnvvar,
|
|
OptionNamespaces namespace_id = OptionNamespaces::kNoNamespace);
|
|
|
|
// Adds aliases. An alias can be of the form "--option-a" -> "--option-b",
|
|
// or have a more complex group expansion, like
|
|
// "--option-a" -> { "--option-b", "--harmony-foobar", "--eval", "42" }
|
|
// If `from` has the form "--option-a=", the alias will only be expanded if
|
|
// the option is presented in that form (i.e. with a '=').
|
|
// If `from` has the form "--option-a <arg>", the alias will only be expanded
|
|
// if the option has a non-option argument (not starting with -) following it.
|
|
void AddAlias(const char* from, const char* to);
|
|
void AddAlias(const char* from, const std::vector<std::string>& to);
|
|
void AddAlias(const char* from, const std::initializer_list<std::string>& to);
|
|
|
|
// Add implications from some arbitrary option to a boolean one, either
|
|
// in a way that makes `from` set `to` to true or to false.
|
|
void Implies(const char* from, const char* to);
|
|
void ImpliesNot(const char* from, const char* to);
|
|
|
|
// Insert options from another options parser into this one, along with
|
|
// a method that yields the target options type from this parser's options
|
|
// type.
|
|
template <typename ChildOptions>
|
|
void Insert(const OptionsParser<ChildOptions>& child_options_parser,
|
|
ChildOptions* (Options::*get_child)());
|
|
|
|
// Parse a sequence of options into an options struct, a list of
|
|
// arguments that were parsed as options, a list of unknown/JS engine options,
|
|
// and leave the remainder in the input `args` vector.
|
|
//
|
|
// For example, an `args` input of
|
|
//
|
|
// node --foo --harmony-bar --fizzle=42 -- /path/to/cow moo
|
|
//
|
|
// expands as
|
|
//
|
|
// - `args` -> { "node", "/path/to/cow", "moo" }
|
|
// - `exec_args` -> { "--foo", "--harmony-bar", "--fizzle=42" }
|
|
// - `v8_args` -> `{ "node", "--harmony-bar" }
|
|
// - `options->foo == true`, `options->fizzle == 42`.
|
|
//
|
|
// If `*error` is set, the result of the parsing should be discarded and the
|
|
// contents of any of the argument vectors should be considered undefined.
|
|
void Parse(std::vector<std::string>* const args,
|
|
std::vector<std::string>* const exec_args,
|
|
std::vector<std::string>* const v8_args,
|
|
Options* const options,
|
|
OptionEnvvarSettings required_env_settings,
|
|
std::vector<std::string>* const errors) const;
|
|
|
|
private:
|
|
// We support the wide variety of different option types by remembering
|
|
// how to access them, given a certain `Options` struct.
|
|
|
|
// Represents a field within `Options`.
|
|
class BaseOptionField {
|
|
public:
|
|
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<bool*>(LookupImpl(options));
|
|
}
|
|
virtual void SetBool(Options* options, bool value) {
|
|
*static_cast<bool*>(LookupImpl(options)) = value;
|
|
}
|
|
|
|
template <typename T>
|
|
inline T* Lookup(Options* options) const {
|
|
return static_cast<T*>(LookupImpl(options));
|
|
}
|
|
};
|
|
|
|
// Represents a field of type T within `Options` that can be looked up
|
|
// as a C++ member field.
|
|
template <typename T>
|
|
class SimpleOptionField : public BaseOptionField {
|
|
public:
|
|
explicit SimpleOptionField(T Options::* field) : field_(field) {}
|
|
void* LookupImpl(Options* options) const override {
|
|
return static_cast<void*>(&(options->*field_));
|
|
}
|
|
|
|
private:
|
|
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 <typename T>
|
|
inline T* Lookup(std::shared_ptr<BaseOptionField> field,
|
|
Options* options) const {
|
|
return field->template Lookup<T>(options);
|
|
}
|
|
|
|
// An option consists of:
|
|
// - A type.
|
|
// - A way to store/access the property value.
|
|
// - The information of whether it may occur in an env var or not.
|
|
// - A default value (if applicable).
|
|
// - A namespace ID (optional) to allow for namespacing of options.
|
|
struct OptionInfo {
|
|
OptionType type;
|
|
std::shared_ptr<BaseOptionField> field;
|
|
OptionEnvvarSettings env_setting;
|
|
std::string help_text;
|
|
bool default_is_true = false;
|
|
std::string namespace_id;
|
|
bool strict = false;
|
|
};
|
|
|
|
// An implied option is composed of the information on where to store a
|
|
// specific boolean value (if another specific option is encountered).
|
|
struct Implication {
|
|
OptionType type;
|
|
std::string name;
|
|
std::shared_ptr<BaseOptionField> target_field;
|
|
bool target_value;
|
|
};
|
|
|
|
// These are helpers that make `Insert()` support properties of other
|
|
// options structs, if we know how to access them.
|
|
template <typename OriginalField, typename ChildOptions>
|
|
static auto Convert(std::shared_ptr<OriginalField> original,
|
|
ChildOptions* (Options::*get_child)());
|
|
template <typename ChildOptions>
|
|
static auto Convert(typename OptionsParser<ChildOptions>::OptionInfo original,
|
|
ChildOptions* (Options::*get_child)());
|
|
template <typename ChildOptions>
|
|
static auto Convert(
|
|
typename OptionsParser<ChildOptions>::Implication original,
|
|
ChildOptions* (Options::*get_child)());
|
|
|
|
std::unordered_map<std::string, OptionInfo> options_;
|
|
std::unordered_map<std::string, std::vector<std::string>> aliases_;
|
|
std::unordered_multimap<std::string, Implication> implications_;
|
|
|
|
template <typename OtherOptions>
|
|
friend class OptionsParser;
|
|
|
|
friend void GetCLIOptionsValues(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
friend void GetCLIOptionsInfo(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
friend std::string GetBashCompletion();
|
|
friend std::unordered_map<std::string, OptionMappingDetails>
|
|
MapEnvOptionsFlagInputType();
|
|
friend std::unordered_map<std::string, OptionMappingDetails>
|
|
MapOptionsByNamespace(std::string namespace_name);
|
|
friend std::vector<std::string> MapAvailableNamespaces();
|
|
friend void GetEnvOptionsInputType(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
friend void GetOptionsAsFlags(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
};
|
|
|
|
using StringVector = std::vector<std::string>;
|
|
template <class OptionsType, class = Options>
|
|
void Parse(StringVector* const args,
|
|
StringVector* const exec_args,
|
|
StringVector* const v8_args,
|
|
OptionsType* const options,
|
|
OptionEnvvarSettings required_env_settings,
|
|
StringVector* const errors);
|
|
|
|
} // 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;
|
|
extern NODE_EXTERN_PRIVATE std::shared_ptr<PerProcessOptions> cli_options;
|
|
|
|
} // namespace per_process
|
|
|
|
void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options);
|
|
void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options,
|
|
std::function<std::string(const char*)> opt_getter);
|
|
|
|
std::vector<std::string> ParseNodeOptionsEnvVar(
|
|
const std::string& node_options, std::vector<std::string>* errors);
|
|
|
|
#undef DEFINE_BOOL_FIELD
|
|
} // namespace node
|
|
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#endif // SRC_NODE_OPTIONS_H_
|