Skip to content

Commit 64a0b11

Browse files
refackBridgeAR
authored andcommitted
src: refactor node options parsers to mitigate MSVC bug
PR-URL: #26280 Fixes: #25593 Reviewed-By: Joyee Cheung <[email protected]>
1 parent 2908e63 commit 64a0b11

File tree

4 files changed

+83
-65
lines changed

4 files changed

+83
-65
lines changed

src/node.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ int ProcessGlobalArgs(std::vector<std::string>* args,
546546
std::vector<std::string> v8_args;
547547

548548
Mutex::ScopedLock lock(per_process::cli_options_mutex);
549-
options_parser::PerProcessOptionsParser::instance.Parse(
549+
options_parser::Parse(
550550
args,
551551
exec_args,
552552
&v8_args,

src/node_options.cc

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,60 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
102102

103103
namespace options_parser {
104104

105-
// Explicitly access the singelton instances in their dependancy order.
106-
// This was moved here to workaround a compiler bug.
107-
// Refs: https://github.com/nodejs/node/issues/25593
105+
class DebugOptionsParser : public OptionsParser<DebugOptions> {
106+
public:
107+
DebugOptionsParser();
108+
};
109+
110+
class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
111+
public:
112+
EnvironmentOptionsParser();
113+
explicit EnvironmentOptionsParser(const DebugOptionsParser& dop)
114+
: EnvironmentOptionsParser() {
115+
Insert(&dop, &EnvironmentOptions::get_debug_options);
116+
}
117+
};
108118

109-
#if HAVE_INSPECTOR
110-
const DebugOptionsParser DebugOptionsParser::instance;
111-
#endif // HAVE_INSPECTOR
119+
class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> {
120+
public:
121+
PerIsolateOptionsParser() = delete;
122+
explicit PerIsolateOptionsParser(const EnvironmentOptionsParser& eop);
123+
};
112124

113-
const EnvironmentOptionsParser EnvironmentOptionsParser::instance;
125+
class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
126+
public:
127+
PerProcessOptionsParser() = delete;
128+
explicit PerProcessOptionsParser(const PerIsolateOptionsParser& iop);
129+
};
114130

115-
const PerIsolateOptionsParser PerIsolateOptionsParser::instance;
131+
#if HAVE_INSPECTOR
132+
const DebugOptionsParser _dop_instance{};
133+
const EnvironmentOptionsParser _eop_instance{_dop_instance};
134+
#else
135+
const EnvironmentOptionsParser _eop_instance{};
136+
#endif // HAVE_INSPECTOR
137+
const PerIsolateOptionsParser _piop_instance{_eop_instance};
138+
const PerProcessOptionsParser _ppop_instance{_piop_instance};
139+
140+
template <>
141+
void Parse(
142+
StringVector* const args, StringVector* const exec_args,
143+
StringVector* const v8_args,
144+
PerIsolateOptions* const options,
145+
OptionEnvvarSettings required_env_settings, StringVector* const errors) {
146+
_piop_instance.Parse(
147+
args, exec_args, v8_args, options, required_env_settings, errors);
148+
}
116149

117-
const PerProcessOptionsParser PerProcessOptionsParser::instance;
150+
template <>
151+
void Parse(
152+
StringVector* const args, StringVector* const exec_args,
153+
StringVector* const v8_args,
154+
PerProcessOptions* const options,
155+
OptionEnvvarSettings required_env_settings, StringVector* const errors) {
156+
_ppop_instance.Parse(
157+
args, exec_args, v8_args, options, required_env_settings, errors);
158+
}
118159

119160
// XXX: If you add an option here, please also add it to doc/node.1 and
120161
// doc/api/cli.md
@@ -273,14 +314,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
273314
AddAlias("-i", "--interactive");
274315

275316
AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvironment);
276-
277-
#if HAVE_INSPECTOR
278-
Insert(&DebugOptionsParser::instance,
279-
&EnvironmentOptions::get_debug_options);
280-
#endif // HAVE_INSPECTOR
281317
}
282318

283-
PerIsolateOptionsParser::PerIsolateOptionsParser() {
319+
PerIsolateOptionsParser::PerIsolateOptionsParser(
320+
const EnvironmentOptionsParser& eop) {
284321
AddOption("--track-heap-objects",
285322
"track heap object allocations for heap snapshots",
286323
&PerIsolateOptions::track_heap_objects,
@@ -336,11 +373,11 @@ PerIsolateOptionsParser::PerIsolateOptionsParser() {
336373
kAllowedInEnvironment);
337374
#endif // NODE_REPORT
338375

339-
Insert(&EnvironmentOptionsParser::instance,
340-
&PerIsolateOptions::get_per_env_options);
376+
Insert(&eop, &PerIsolateOptions::get_per_env_options);
341377
}
342378

343-
PerProcessOptionsParser::PerProcessOptionsParser() {
379+
PerProcessOptionsParser::PerProcessOptionsParser(
380+
const PerIsolateOptionsParser& iop) {
344381
AddOption("--title",
345382
"the process title to use on startup",
346383
&PerProcessOptions::title,
@@ -446,8 +483,7 @@ PerProcessOptionsParser::PerProcessOptionsParser() {
446483
#endif
447484
#endif
448485

449-
Insert(&PerIsolateOptionsParser::instance,
450-
&PerProcessOptions::get_per_isolate_options);
486+
Insert(&iop, &PerProcessOptions::get_per_isolate_options);
451487
}
452488

453489
inline std::string RemoveBrackets(const std::string& host) {
@@ -513,10 +549,8 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
513549
per_process::cli_options->per_isolate = original_per_isolate;
514550
});
515551

516-
const auto& parser = PerProcessOptionsParser::instance;
517-
518552
Local<Map> options = Map::New(isolate);
519-
for (const auto& item : parser.options_) {
553+
for (const auto& item : _ppop_instance.options_) {
520554
Local<Value> value;
521555
const auto& option_info = item.second;
522556
auto field = option_info.field;
@@ -534,29 +568,34 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
534568
}
535569
break;
536570
case kBoolean:
537-
value = Boolean::New(isolate, *parser.Lookup<bool>(field, opts));
571+
value = Boolean::New(isolate,
572+
*_ppop_instance.Lookup<bool>(field, opts));
538573
break;
539574
case kInteger:
540-
value = Number::New(isolate, *parser.Lookup<int64_t>(field, opts));
575+
value = Number::New(isolate,
576+
*_ppop_instance.Lookup<int64_t>(field, opts));
541577
break;
542578
case kUInteger:
543-
value = Number::New(isolate, *parser.Lookup<uint64_t>(field, opts));
579+
value = Number::New(isolate,
580+
*_ppop_instance.Lookup<uint64_t>(field, opts));
544581
break;
545582
case kString:
546-
if (!ToV8Value(context, *parser.Lookup<std::string>(field, opts))
583+
if (!ToV8Value(context,
584+
*_ppop_instance.Lookup<std::string>(field, opts))
547585
.ToLocal(&value)) {
548586
return;
549587
}
550588
break;
551589
case kStringList:
552590
if (!ToV8Value(context,
553-
*parser.Lookup<std::vector<std::string>>(field, opts))
591+
*_ppop_instance.Lookup<StringVector>(field, opts))
554592
.ToLocal(&value)) {
555593
return;
556594
}
557595
break;
558596
case kHostPort: {
559-
const HostPort& host_port = *parser.Lookup<HostPort>(field, opts);
597+
const HostPort& host_port =
598+
*_ppop_instance.Lookup<HostPort>(field, opts);
560599
Local<Object> obj = Object::New(isolate);
561600
Local<Value> host;
562601
if (!ToV8Value(context, host_port.host()).ToLocal(&host) ||
@@ -597,7 +636,7 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
597636
}
598637

599638
Local<Value> aliases;
600-
if (!ToV8Value(context, parser.aliases_).ToLocal(&aliases)) return;
639+
if (!ToV8Value(context, _ppop_instance.aliases_).ToLocal(&aliases)) return;
601640

602641
Local<Object> ret = Object::New(isolate);
603642
if (ret->Set(context, env->options_string(), options).IsNothing() ||

src/node_options.h

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,12 @@ class OptionsParser {
320320
//
321321
// If `*error` is set, the result of the parsing should be discarded and the
322322
// contents of any of the argument vectors should be considered undefined.
323-
virtual void Parse(std::vector<std::string>* const args,
324-
std::vector<std::string>* const exec_args,
325-
std::vector<std::string>* const v8_args,
326-
Options* const options,
327-
OptionEnvvarSettings required_env_settings,
328-
std::vector<std::string>* const errors) const;
323+
void Parse(std::vector<std::string>* const args,
324+
std::vector<std::string>* const exec_args,
325+
std::vector<std::string>* const v8_args,
326+
Options* const options,
327+
OptionEnvvarSettings required_env_settings,
328+
std::vector<std::string>* const errors) const;
329329

330330
private:
331331
// We support the wide variety of different option types by remembering
@@ -406,33 +406,12 @@ class OptionsParser {
406406
friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
407407
};
408408

409-
class DebugOptionsParser : public OptionsParser<DebugOptions> {
410-
public:
411-
DebugOptionsParser();
412-
413-
static const DebugOptionsParser instance;
414-
};
415-
416-
class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
417-
public:
418-
EnvironmentOptionsParser();
419-
420-
static const EnvironmentOptionsParser instance;
421-
};
422-
423-
class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> {
424-
public:
425-
PerIsolateOptionsParser();
426-
427-
static const PerIsolateOptionsParser instance;
428-
};
429-
430-
class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
431-
public:
432-
PerProcessOptionsParser();
433-
434-
static const PerProcessOptionsParser instance;
435-
};
409+
using StringVector = std::vector<std::string>;
410+
template <class OptionsType, class = Options>
411+
void Parse(
412+
StringVector* const args, StringVector* const exec_args,
413+
StringVector* const v8_args, OptionsType* const options,
414+
OptionEnvvarSettings required_env_settings, StringVector* const errors);
436415

437416
} // namespace options_parser
438417

src/node_worker.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
476476

477477
// Using invalid_args as the v8_args argument as it stores unknown
478478
// options for the per isolate parser.
479-
options_parser::PerIsolateOptionsParser::instance.Parse(
479+
options_parser::Parse(
480480
&exec_argv,
481481
&exec_argv_out,
482482
&invalid_args,

0 commit comments

Comments
 (0)