diff options
author | Michaël Zasso <targos@protonmail.com> | 2021-06-13 12:46:35 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2021-06-21 20:18:20 +0200 |
commit | 1bbe66f432591aea83555d27dd76c55fea040a0d (patch) | |
tree | 112ae06f8c3c305341967af71acbeb82c1b0d02f /src/node_options-inl.h | |
parent | 86d6d816fd41bb015488c8a0022cc9cf4d1a174b (diff) | |
download | node-new-1bbe66f432591aea83555d27dd76c55fea040a0d.tar.gz |
src: allow to negate boolean CLI flags
This change allows all boolean flags to be negated using the `--no-`
prefix.
Flags that are `true` by default (for example `--deprecation`) are
still documented as negations.
With this change, it becomes possible to easily flip the default
value of a boolean flag and to override the value of a flag passed
in the NODE_OPTIONS environment variable.
`process.allowedNodeEnvironmentFlags` contains both the negated and
non-negated versions of boolean flags.
Co-authored-by: Anna Henningsen <anna@addaleax.net>
PR-URL: https://github.com/nodejs/node/pull/39023
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'src/node_options-inl.h')
-rw-r--r-- | src/node_options-inl.h | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/src/node_options-inl.h b/src/node_options-inl.h index 4e1a12296b..7facb22afc 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -23,12 +23,14 @@ template <typename Options> void OptionsParser<Options>::AddOption(const char* name, const char* help_text, bool Options::* field, - OptionEnvvarSettings env_setting) { + OptionEnvvarSettings env_setting, + bool default_is_true) { options_.emplace(name, OptionInfo{kBoolean, std::make_shared<SimpleOptionField<bool>>(field), env_setting, - help_text}); + help_text, + default_is_true}); } template <typename Options> @@ -186,7 +188,8 @@ auto OptionsParser<Options>::Convert( return OptionInfo{original.type, Convert(original.field, get_child), original.env_setting, - original.help_text}; + original.help_text, + original.default_is_true}; } template <typename Options> @@ -225,6 +228,10 @@ inline std::string RequiresArgumentErr(const std::string& arg) { return arg + " requires an argument"; } +inline std::string NegationImpliesBooleanError(const std::string& arg) { + return arg + " is an invalid negation because it is not a boolean option"; +} + // We store some of the basic information around a single Parse call inside // this struct, to separate storage of command line arguments and their // handling. In particular, this makes it easier to introduce 'synthetic' @@ -325,6 +332,13 @@ void OptionsParser<Options>::Parse( name[i] = '-'; } + // Convert --no-foo to --foo and keep in mind that we're negating. + bool is_negation = false; + if (name.find("--no-") == 0) { + name.erase(2, 3); // remove no- + is_negation = true; + } + { auto it = aliases_.end(); // Expand aliases: @@ -367,7 +381,12 @@ void OptionsParser<Options>::Parse( } { - auto implications = implications_.equal_range(name); + std::string implied_name = name; + if (is_negation) { + // Implications for negated options are defined with "--no-". + implied_name.insert(2, "no-"); + } + auto implications = implications_.equal_range(implied_name); for (auto it = implications.first; it != implications.second; ++it) { if (it->second.type == kV8Option) { v8_args->push_back(it->second.name); @@ -384,6 +403,13 @@ void OptionsParser<Options>::Parse( } const OptionInfo& info = it->second; + + // Some V8 options can be negated and they are validated by V8 later. + if (is_negation && info.type != kBoolean && info.type != kV8Option) { + errors->push_back(NegationImpliesBooleanError(arg)); + break; + } + std::string value; if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option) { if (equals_index != std::string::npos) { @@ -412,7 +438,7 @@ void OptionsParser<Options>::Parse( switch (info.type) { case kBoolean: - *Lookup<bool>(info.field, options) = true; + *Lookup<bool>(info.field, options) = !is_negation; break; case kInteger: *Lookup<int64_t>(info.field, options) = std::atoll(value.c_str()); |