diff options
Diffstat (limited to 'src/node_options.cc')
-rw-r--r-- | src/node_options.cc | 353 |
1 files changed, 305 insertions, 48 deletions
diff --git a/src/node_options.cc b/src/node_options.cc index b10de9ef28..88fac6a01f 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -1,30 +1,55 @@ -#include "node_options-inl.h" #include <errno.h> +#include "node_internals.h" +#include "node_options-inl.h" + +using v8::Boolean; +using v8::Context; +using v8::FunctionCallbackInfo; +using v8::Integer; +using v8::Isolate; +using v8::Local; +using v8::Map; +using v8::Number; +using v8::Object; +using v8::String; +using v8::Undefined; +using v8::Value; namespace node { +namespace options_parser { + +// XXX: If you add an option here, please also add it to doc/node.1 and +// doc/api/cli.md +// TODO(addaleax): Make that unnecessary. DebugOptionsParser::DebugOptionsParser() { - AddOption("--inspect-port", &DebugOptions::host_port, + AddOption("--inspect-port", + "set host:port for inspector", + &DebugOptions::host_port, kAllowedInEnvironment); AddAlias("--debug-port", "--inspect-port"); - AddOption("--inspect", &DebugOptions::inspector_enabled, + AddOption("--inspect", + "activate inspector on host:port (default: 127.0.0.1:9229)", + &DebugOptions::inspector_enabled, kAllowedInEnvironment); AddAlias("--inspect=", { "--inspect-port", "--inspect" }); - AddOption("--debug", &DebugOptions::deprecated_debug); + AddOption("--debug", "", &DebugOptions::deprecated_debug); AddAlias("--debug=", { "--inspect-port", "--debug" }); - AddOption("--inspect-brk", &DebugOptions::break_first_line, + AddOption("--inspect-brk", + "activate inspector on host:port and break at start of user script", + &DebugOptions::break_first_line, kAllowedInEnvironment); Implies("--inspect-brk", "--inspect"); AddAlias("--inspect-brk=", { "--inspect-port", "--inspect-brk" }); - AddOption("--inspect-brk-node", &DebugOptions::break_node_first_line); + AddOption("--inspect-brk-node", "", &DebugOptions::break_node_first_line); Implies("--inspect-brk-node", "--inspect"); AddAlias("--inspect-brk-node=", { "--inspect-port", "--inspect-brk-node" }); - AddOption("--debug-brk", &DebugOptions::break_first_line); + AddOption("--debug-brk", "", &DebugOptions::break_first_line); Implies("--debug-brk", "--debug"); AddAlias("--debug-brk=", { "--inspect-port", "--debug-brk" }); } @@ -32,46 +57,80 @@ DebugOptionsParser::DebugOptionsParser() { DebugOptionsParser DebugOptionsParser::instance; EnvironmentOptionsParser::EnvironmentOptionsParser() { - AddOption("--experimental-modules", &EnvironmentOptions::experimental_modules, + AddOption("--experimental-modules", + "experimental ES Module support and caching modules", + &EnvironmentOptions::experimental_modules, kAllowedInEnvironment); AddOption("--experimental-repl-await", + "experimental await keyword support in REPL", &EnvironmentOptions::experimental_repl_await, kAllowedInEnvironment); AddOption("--experimental-vm-modules", + "experimental ES Module support in vm module", &EnvironmentOptions::experimental_vm_modules, kAllowedInEnvironment); - AddOption("--experimental-worker", &EnvironmentOptions::experimental_worker, + AddOption("--experimental-worker", + "experimental threaded Worker support", + &EnvironmentOptions::experimental_worker, kAllowedInEnvironment); - AddOption("--expose-internals", &EnvironmentOptions::expose_internals); + AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals); // TODO(addaleax): Remove this when adding -/_ canonicalization to the parser. AddAlias("--expose_internals", "--expose-internals"); - AddOption("--loader", &EnvironmentOptions::userland_loader, + AddOption("--loader", + "(with --experimental-modules) use the specified file as a " + "custom loader", + &EnvironmentOptions::userland_loader, kAllowedInEnvironment); - AddOption("--no-deprecation", &EnvironmentOptions::no_deprecation, + AddOption("--no-deprecation", + "silence deprecation warnings", + &EnvironmentOptions::no_deprecation, kAllowedInEnvironment); AddOption("--no-force-async-hooks-checks", + "disable checks for async_hooks", &EnvironmentOptions::no_force_async_hooks_checks, kAllowedInEnvironment); - AddOption("--no-warnings", &EnvironmentOptions::no_warnings, + AddOption("--no-warnings", + "silence all process warnings", + &EnvironmentOptions::no_warnings, kAllowedInEnvironment); - AddOption("--pending-deprecation", &EnvironmentOptions::pending_deprecation, + AddOption("--pending-deprecation", + "emit pending deprecation warnings", + &EnvironmentOptions::pending_deprecation, kAllowedInEnvironment); - AddOption("--preserve-symlinks", &EnvironmentOptions::preserve_symlinks); + AddOption("--preserve-symlinks", + "preserve symbolic links when resolving", + &EnvironmentOptions::preserve_symlinks); AddOption("--preserve-symlinks-main", + "preserve symbolic links when resolving the main module", &EnvironmentOptions::preserve_symlinks_main); - AddOption("--prof-process", &EnvironmentOptions::prof_process); - AddOption("--redirect-warnings", &EnvironmentOptions::redirect_warnings, + AddOption("--prof-process", + "process V8 profiler output generated using --prof", + &EnvironmentOptions::prof_process); + AddOption("--redirect-warnings", + "write warnings to file instead of stderr", + &EnvironmentOptions::redirect_warnings, kAllowedInEnvironment); - AddOption("--throw-deprecation", &EnvironmentOptions::throw_deprecation, + AddOption("--throw-deprecation", + "throw an exception on deprecations", + &EnvironmentOptions::throw_deprecation, kAllowedInEnvironment); - AddOption("--trace-deprecation", &EnvironmentOptions::trace_deprecation, + AddOption("--trace-deprecation", + "show stack traces on deprecations", + &EnvironmentOptions::trace_deprecation, kAllowedInEnvironment); - AddOption("--trace-sync-io", &EnvironmentOptions::trace_sync_io, + AddOption("--trace-sync-io", + "show stack trace when use of sync IO is detected after the " + "first tick", + &EnvironmentOptions::trace_sync_io, kAllowedInEnvironment); - AddOption("--trace-warnings", &EnvironmentOptions::trace_warnings, + AddOption("--trace-warnings", + "show stack traces on process warnings", + &EnvironmentOptions::trace_warnings, kAllowedInEnvironment); - AddOption("--check", &EnvironmentOptions::syntax_check_only); + AddOption("--check", + "syntax check script without executing", + &EnvironmentOptions::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 @@ -79,21 +138,28 @@ 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("--eval", &EnvironmentOptions::eval_string); + AddOption("[has_eval_string]", "", &EnvironmentOptions::has_eval_string); + AddOption("--eval", "evaluate script", &EnvironmentOptions::eval_string); Implies("--eval", "[has_eval_string]"); - AddOption("--print", &EnvironmentOptions::print_eval); + AddOption("--print", + "evaluate script and print result", + &EnvironmentOptions::print_eval); AddAlias("-e", "--eval"); AddAlias("--print <arg>", "-pe"); AddAlias("-pe", { "--print", "--eval" }); AddAlias("-p", "--print"); - AddOption("--require", &EnvironmentOptions::preload_modules, + AddOption("--require", + "module to preload (option can be repeated)", + &EnvironmentOptions::preload_modules, kAllowedInEnvironment); AddAlias("-r", "--require"); - AddOption("--interactive", &EnvironmentOptions::force_repl); + AddOption("--interactive", + "always enter the REPL even if stdin does not appear " + "to be a terminal", + &EnvironmentOptions::force_repl); AddAlias("-i", "--interactive"); - AddOption("--napi-modules", NoOp {}, kAllowedInEnvironment); + AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvironment); Insert(&DebugOptionsParser::instance, &EnvironmentOptions::get_debug_options); @@ -102,16 +168,21 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { EnvironmentOptionsParser EnvironmentOptionsParser::instance; PerIsolateOptionsParser::PerIsolateOptionsParser() { - AddOption("--track-heap-objects", &PerIsolateOptions::track_heap_objects, + AddOption("--track-heap-objects", + "track heap object allocations for heap snapshots", + &PerIsolateOptions::track_heap_objects, kAllowedInEnvironment); // Explicitly add some V8 flags to mark them as allowed in NODE_OPTIONS. - AddOption("--abort_on_uncaught_exception", V8Option {}, + AddOption("--abort_on_uncaught_exception", + "aborting instead of exiting causes a core file to be generated " + "for analysis", + V8Option{}, kAllowedInEnvironment); - AddOption("--max_old_space_size", V8Option {}, kAllowedInEnvironment); - AddOption("--perf_basic_prof", V8Option {}, kAllowedInEnvironment); - AddOption("--perf_prof", V8Option {}, kAllowedInEnvironment); - AddOption("--stack_trace_limit", V8Option {}, kAllowedInEnvironment); + AddOption("--max_old_space_size", "", V8Option{}, kAllowedInEnvironment); + AddOption("--perf_basic_prof", "", V8Option{}, kAllowedInEnvironment); + AddOption("--perf_prof", "", V8Option{}, kAllowedInEnvironment); + AddOption("--stack_trace_limit", "", V8Option{}, kAllowedInEnvironment); Insert(&EnvironmentOptionsParser::instance, &PerIsolateOptions::get_per_env_options); @@ -120,52 +191,89 @@ PerIsolateOptionsParser::PerIsolateOptionsParser() { PerIsolateOptionsParser PerIsolateOptionsParser::instance; PerProcessOptionsParser::PerProcessOptionsParser() { - AddOption("--title", &PerProcessOptions::title, kAllowedInEnvironment); + AddOption("--title", + "the process title to use on startup", + &PerProcessOptions::title, + kAllowedInEnvironment); AddOption("--trace-event-categories", + "comma separated list of trace event categories to record", &PerProcessOptions::trace_event_categories, kAllowedInEnvironment); AddOption("--trace-event-file-pattern", + "Template string specifying the filepath for the trace-events " + "data, it supports ${rotation} and ${pid} log-rotation id. %2$u " + "is the pid.", &PerProcessOptions::trace_event_file_pattern, kAllowedInEnvironment); AddAlias("--trace-events-enabled", { "--trace-event-categories", "v8,node,node.async_hooks" }); - AddOption("--v8-pool-size", &PerProcessOptions::v8_thread_pool_size, + AddOption("--v8-pool-size", + "set V8's thread pool size", + &PerProcessOptions::v8_thread_pool_size, kAllowedInEnvironment); - AddOption("--zero-fill-buffers", &PerProcessOptions::zero_fill_all_buffers, + AddOption("--zero-fill-buffers", + "automatically zero-fill all newly allocated Buffer and " + "SlowBuffer instances", + &PerProcessOptions::zero_fill_all_buffers, kAllowedInEnvironment); - AddOption("--security-reverts", &PerProcessOptions::security_reverts); - AddOption("--help", &PerProcessOptions::print_help); + AddOption("--security-reverts", "", &PerProcessOptions::security_reverts); + AddOption("--help", + "print node command line options", + &PerProcessOptions::print_help); AddAlias("-h", "--help"); - AddOption("--version", &PerProcessOptions::print_version); + AddOption( + "--version", "print Node.js version", &PerProcessOptions::print_version); AddAlias("-v", "--version"); - AddOption("--v8-options", &PerProcessOptions::print_v8_help); + AddOption("--v8-options", + "print V8 command line options", + &PerProcessOptions::print_v8_help); #ifdef NODE_HAVE_I18N_SUPPORT - AddOption("--icu-data-dir", &PerProcessOptions::icu_data_dir, + AddOption("--icu-data-dir", + "set ICU data load path to dir (overrides NODE_ICU_DATA)" +#ifndef NODE_HAVE_SMALL_ICU + " (note: linked-in ICU data is present)\n" +#endif + , + &PerProcessOptions::icu_data_dir, kAllowedInEnvironment); #endif #if HAVE_OPENSSL - AddOption("--openssl-config", &PerProcessOptions::openssl_config, + AddOption("--openssl-config", + "load OpenSSL configuration from the specified file " + "(overrides OPENSSL_CONF)", + &PerProcessOptions::openssl_config, kAllowedInEnvironment); - AddOption("--tls-cipher-list", &PerProcessOptions::tls_cipher_list, + AddOption("--tls-cipher-list", + "use an alternative default TLS cipher list", + &PerProcessOptions::tls_cipher_list, kAllowedInEnvironment); - AddOption("--use-openssl-ca", &PerProcessOptions::use_openssl_ca, + AddOption("--use-openssl-ca", + "use OpenSSL's default CA store", + &PerProcessOptions::use_openssl_ca, kAllowedInEnvironment); - AddOption("--use-bundled-ca", &PerProcessOptions::use_bundled_ca, + AddOption("--use-bundled-ca", + "use bundled CA store", + &PerProcessOptions::use_bundled_ca, kAllowedInEnvironment); // 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); Implies("--use-openssl-ca", "[ssl_openssl_cert_store]"); ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]"); #if NODE_FIPS_MODE - AddOption("--enable-fips", &PerProcessOptions::enable_fips_crypto, + AddOption("--enable-fips", + "enable FIPS crypto at startup", + &PerProcessOptions::enable_fips_crypto, kAllowedInEnvironment); - AddOption("--force-fips", &PerProcessOptions::force_fips_crypto, + AddOption("--force-fips", + "force FIPS crypto (cannot be disabled)", + &PerProcessOptions::force_fips_crypto, kAllowedInEnvironment); #endif #endif @@ -216,4 +324,153 @@ HostPort SplitHostPort(const std::string& arg, std::string* error) { return HostPort { RemoveBrackets(arg.substr(0, colon)), ParseAndValidatePort(arg.substr(colon + 1), error) }; } + +// Usage: Either: +// - getOptions() to get all options + metadata or +// - getOptions(string) to get the value of a particular option +void GetOptions(const FunctionCallbackInfo<Value>& args) { + Mutex::ScopedLock lock(per_process_opts_mutex); + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + Local<Context> context = env->context(); + + // Temporarily act as if the current Environment's/IsolateData's options were + // the default options, i.e. like they are the ones we'd access for global + // options parsing, so that all options are available from the main parser. + auto original_per_isolate = per_process_opts->per_isolate; + per_process_opts->per_isolate = env->isolate_data()->options(); + auto original_per_env = per_process_opts->per_isolate->per_env; + per_process_opts->per_isolate->per_env = env->options(); + OnScopeLeave on_scope_leave([&]() { + per_process_opts->per_isolate->per_env = original_per_env; + per_process_opts->per_isolate = original_per_isolate; + }); + + const auto& parser = PerProcessOptionsParser::instance; + + std::string filter; + if (args[0]->IsString()) filter = *node::Utf8Value(isolate, args[0]); + + Local<Map> options = Map::New(isolate); + for (const auto& item : parser.options_) { + if (!filter.empty() && item.first != filter) continue; + + Local<Value> value; + const auto& option_info = item.second; + auto field = option_info.field; + PerProcessOptions* opts = per_process_opts.get(); + switch (option_info.type) { + case kNoOp: + case kV8Option: + value = Undefined(isolate); + break; + case kBoolean: + value = Boolean::New(isolate, *parser.Lookup<bool>(field, opts)); + break; + case kInteger: + value = Number::New(isolate, *parser.Lookup<int64_t>(field, opts)); + break; + case kString: + if (!ToV8Value(context, *parser.Lookup<std::string>(field, opts)) + .ToLocal(&value)) { + return; + } + break; + case kStringList: + if (!ToV8Value(context, + *parser.Lookup<std::vector<std::string>>(field, opts)) + .ToLocal(&value)) { + return; + } + break; + case kHostPort: { + const HostPort& host_port = *parser.Lookup<HostPort>(field, opts); + Local<Object> obj = Object::New(isolate); + Local<Value> host; + if (!ToV8Value(context, host_port.host_name).ToLocal(&host) || + obj->Set(context, env->host_string(), host).IsNothing() || + obj->Set(context, + env->port_string(), + Integer::New(isolate, host_port.port)) + .IsNothing()) { + return; + } + value = obj; + break; + } + default: + UNREACHABLE(); + } + CHECK(!value.IsEmpty()); + + if (!filter.empty()) { + args.GetReturnValue().Set(value); + return; + } + + Local<Value> name = ToV8Value(context, item.first).ToLocalChecked(); + Local<Object> info = Object::New(isolate); + Local<Value> help_text; + if (!ToV8Value(context, option_info.help_text).ToLocal(&help_text) || + !info->Set(context, env->help_text_string(), help_text) + .FromMaybe(false) || + !info->Set(context, + env->env_var_settings_string(), + Integer::New(isolate, + static_cast<int>(option_info.env_setting))) + .FromMaybe(false) || + !info->Set(context, + env->type_string(), + Integer::New(isolate, static_cast<int>(option_info.type))) + .FromMaybe(false) || + info->Set(context, env->value_string(), value).IsNothing() || + options->Set(context, name, info).IsEmpty()) { + return; + } + } + + if (!filter.empty()) return; + + Local<Value> aliases; + if (!ToV8Value(context, parser.aliases_).ToLocal(&aliases)) return; + + Local<Object> ret = Object::New(isolate); + if (ret->Set(context, env->options_string(), options).IsNothing() || + ret->Set(context, env->aliases_string(), aliases).IsNothing()) { + return; + } + + args.GetReturnValue().Set(ret); +} + +void Initialize(Local<Object> target, + Local<Value> unused, + Local<Context> context) { + Environment* env = Environment::GetCurrent(context); + Isolate* isolate = env->isolate(); + env->SetMethodNoSideEffect(target, "getOptions", GetOptions); + + Local<Object> env_settings = Object::New(isolate); + NODE_DEFINE_CONSTANT(env_settings, kAllowedInEnvironment); + NODE_DEFINE_CONSTANT(env_settings, kDisallowedInEnvironment); + target + ->Set( + context, FIXED_ONE_BYTE_STRING(isolate, "envSettings"), env_settings) + .FromJust(); + + Local<Object> types = Object::New(isolate); + NODE_DEFINE_CONSTANT(types, kNoOp); + NODE_DEFINE_CONSTANT(types, kV8Option); + NODE_DEFINE_CONSTANT(types, kBoolean); + NODE_DEFINE_CONSTANT(types, kInteger); + NODE_DEFINE_CONSTANT(types, kString); + NODE_DEFINE_CONSTANT(types, kHostPort); + NODE_DEFINE_CONSTANT(types, kStringList); + target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "types"), types) + .FromJust(); +} + +} // namespace options_parser } // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(options, node::options_parser::Initialize) |