Skip to content

Commit 62f9049

Browse files
refacktargos
authored andcommitted
src: refactor node options parsers to mitigate MSVC bug
Backport-PR-URL: #26649 PR-URL: #26280 Fixes: #25593 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent 26640ce commit 62f9049

File tree

4 files changed

+83
-65
lines changed

4 files changed

+83
-65
lines changed

src/node.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ int ProcessGlobalArgs(std::vector<std::string>* args,
572572
std::vector<std::string> v8_args;
573573

574574
Mutex::ScopedLock lock(per_process::cli_options_mutex);
575-
options_parser::PerProcessOptionsParser::instance.Parse(
575+
options_parser::Parse(
576576
args,
577577
exec_args,
578578
&v8_args,

src/node_options.cc

+69-30
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,60 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
111111

112112
namespace options_parser {
113113

114-
// Explicitly access the singelton instances in their dependancy order.
115-
// This was moved here to workaround a compiler bug.
116-
// Refs: https://github.com/nodejs/node/issues/25593
114+
class DebugOptionsParser : public OptionsParser<DebugOptions> {
115+
public:
116+
DebugOptionsParser();
117+
};
118+
119+
class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
120+
public:
121+
EnvironmentOptionsParser();
122+
explicit EnvironmentOptionsParser(const DebugOptionsParser& dop)
123+
: EnvironmentOptionsParser() {
124+
Insert(&dop, &EnvironmentOptions::get_debug_options);
125+
}
126+
};
117127

118-
#if HAVE_INSPECTOR
119-
const DebugOptionsParser DebugOptionsParser::instance;
120-
#endif // HAVE_INSPECTOR
128+
class PerIsolateOptionsParser : public OptionsParser<PerIsolateOptions> {
129+
public:
130+
PerIsolateOptionsParser() = delete;
131+
explicit PerIsolateOptionsParser(const EnvironmentOptionsParser& eop);
132+
};
121133

122-
const EnvironmentOptionsParser EnvironmentOptionsParser::instance;
134+
class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
135+
public:
136+
PerProcessOptionsParser() = delete;
137+
explicit PerProcessOptionsParser(const PerIsolateOptionsParser& iop);
138+
};
123139

124-
const PerIsolateOptionsParser PerIsolateOptionsParser::instance;
140+
#if HAVE_INSPECTOR
141+
const DebugOptionsParser _dop_instance{};
142+
const EnvironmentOptionsParser _eop_instance{_dop_instance};
143+
#else
144+
const EnvironmentOptionsParser _eop_instance{};
145+
#endif // HAVE_INSPECTOR
146+
const PerIsolateOptionsParser _piop_instance{_eop_instance};
147+
const PerProcessOptionsParser _ppop_instance{_piop_instance};
148+
149+
template <>
150+
void Parse(
151+
StringVector* const args, StringVector* const exec_args,
152+
StringVector* const v8_args,
153+
PerIsolateOptions* const options,
154+
OptionEnvvarSettings required_env_settings, StringVector* const errors) {
155+
_piop_instance.Parse(
156+
args, exec_args, v8_args, options, required_env_settings, errors);
157+
}
125158

126-
const PerProcessOptionsParser PerProcessOptionsParser::instance;
159+
template <>
160+
void Parse(
161+
StringVector* const args, StringVector* const exec_args,
162+
StringVector* const v8_args,
163+
PerProcessOptions* const options,
164+
OptionEnvvarSettings required_env_settings, StringVector* const errors) {
165+
_ppop_instance.Parse(
166+
args, exec_args, v8_args, options, required_env_settings, errors);
167+
}
127168

128169
// XXX: If you add an option here, please also add it to doc/node.1 and
129170
// doc/api/cli.md
@@ -286,14 +327,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
286327
AddAlias("-i", "--interactive");
287328

288329
AddOption("--napi-modules", "", NoOp{}, kAllowedInEnvironment);
289-
290-
#if HAVE_INSPECTOR
291-
Insert(&DebugOptionsParser::instance,
292-
&EnvironmentOptions::get_debug_options);
293-
#endif // HAVE_INSPECTOR
294330
}
295331

296-
PerIsolateOptionsParser::PerIsolateOptionsParser() {
332+
PerIsolateOptionsParser::PerIsolateOptionsParser(
333+
const EnvironmentOptionsParser& eop) {
297334
AddOption("--track-heap-objects",
298335
"track heap object allocations for heap snapshots",
299336
&PerIsolateOptions::track_heap_objects,
@@ -349,11 +386,11 @@ PerIsolateOptionsParser::PerIsolateOptionsParser() {
349386
kAllowedInEnvironment);
350387
#endif // NODE_REPORT
351388

352-
Insert(&EnvironmentOptionsParser::instance,
353-
&PerIsolateOptions::get_per_env_options);
389+
Insert(&eop, &PerIsolateOptions::get_per_env_options);
354390
}
355391

356-
PerProcessOptionsParser::PerProcessOptionsParser() {
392+
PerProcessOptionsParser::PerProcessOptionsParser(
393+
const PerIsolateOptionsParser& iop) {
357394
AddOption("--title",
358395
"the process title to use on startup",
359396
&PerProcessOptions::title,
@@ -459,8 +496,7 @@ PerProcessOptionsParser::PerProcessOptionsParser() {
459496
#endif
460497
#endif
461498

462-
Insert(&PerIsolateOptionsParser::instance,
463-
&PerProcessOptions::get_per_isolate_options);
499+
Insert(&iop, &PerProcessOptions::get_per_isolate_options);
464500
}
465501

466502
inline std::string RemoveBrackets(const std::string& host) {
@@ -526,10 +562,8 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
526562
per_process::cli_options->per_isolate = original_per_isolate;
527563
});
528564

529-
const auto& parser = PerProcessOptionsParser::instance;
530-
531565
Local<Map> options = Map::New(isolate);
532-
for (const auto& item : parser.options_) {
566+
for (const auto& item : _ppop_instance.options_) {
533567
Local<Value> value;
534568
const auto& option_info = item.second;
535569
auto field = option_info.field;
@@ -547,29 +581,34 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
547581
}
548582
break;
549583
case kBoolean:
550-
value = Boolean::New(isolate, *parser.Lookup<bool>(field, opts));
584+
value = Boolean::New(isolate,
585+
*_ppop_instance.Lookup<bool>(field, opts));
551586
break;
552587
case kInteger:
553-
value = Number::New(isolate, *parser.Lookup<int64_t>(field, opts));
588+
value = Number::New(isolate,
589+
*_ppop_instance.Lookup<int64_t>(field, opts));
554590
break;
555591
case kUInteger:
556-
value = Number::New(isolate, *parser.Lookup<uint64_t>(field, opts));
592+
value = Number::New(isolate,
593+
*_ppop_instance.Lookup<uint64_t>(field, opts));
557594
break;
558595
case kString:
559-
if (!ToV8Value(context, *parser.Lookup<std::string>(field, opts))
596+
if (!ToV8Value(context,
597+
*_ppop_instance.Lookup<std::string>(field, opts))
560598
.ToLocal(&value)) {
561599
return;
562600
}
563601
break;
564602
case kStringList:
565603
if (!ToV8Value(context,
566-
*parser.Lookup<std::vector<std::string>>(field, opts))
604+
*_ppop_instance.Lookup<StringVector>(field, opts))
567605
.ToLocal(&value)) {
568606
return;
569607
}
570608
break;
571609
case kHostPort: {
572-
const HostPort& host_port = *parser.Lookup<HostPort>(field, opts);
610+
const HostPort& host_port =
611+
*_ppop_instance.Lookup<HostPort>(field, opts);
573612
Local<Object> obj = Object::New(isolate);
574613
Local<Value> host;
575614
if (!ToV8Value(context, host_port.host()).ToLocal(&host) ||
@@ -610,7 +649,7 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
610649
}
611650

612651
Local<Value> aliases;
613-
if (!ToV8Value(context, parser.aliases_).ToLocal(&aliases)) return;
652+
if (!ToV8Value(context, _ppop_instance.aliases_).ToLocal(&aliases)) return;
614653

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

src/node_options.h

+12-33
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,12 @@ class OptionsParser {
317317
//
318318
// If `*error` is set, the result of the parsing should be discarded and the
319319
// contents of any of the argument vectors should be considered undefined.
320-
virtual void Parse(std::vector<std::string>* const args,
321-
std::vector<std::string>* const exec_args,
322-
std::vector<std::string>* const v8_args,
323-
Options* const options,
324-
OptionEnvvarSettings required_env_settings,
325-
std::vector<std::string>* const errors) const;
320+
void Parse(std::vector<std::string>* const args,
321+
std::vector<std::string>* const exec_args,
322+
std::vector<std::string>* const v8_args,
323+
Options* const options,
324+
OptionEnvvarSettings required_env_settings,
325+
std::vector<std::string>* const errors) const;
326326

327327
private:
328328
// We support the wide variety of different option types by remembering
@@ -403,33 +403,12 @@ class OptionsParser {
403403
friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
404404
};
405405

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

434413
} // namespace options_parser
435414

src/node_worker.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
436436

437437
// Using invalid_args as the v8_args argument as it stores unknown
438438
// options for the per isolate parser.
439-
options_parser::PerIsolateOptionsParser::instance.Parse(
439+
options_parser::Parse(
440440
&exec_argv,
441441
&exec_argv_out,
442442
&invalid_args,

0 commit comments

Comments
 (0)