src: clean up node::Init()
wrt embedder scenarios
This makes the STL variant of `node::Init()` a bit more suitable for inclusion in a proper embedder API, as errors or other output are reported to the caller rather than directly being printed, and the process is not exited directly either. PR-URL: https://github.com/nodejs/node/pull/25370 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
f9b129ec6b
commit
eb664c3b6d
115
src/node.cc
115
src/node.cc
@ -1147,42 +1147,23 @@ inline void PlatformInit() {
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
void ProcessArgv(std::vector<std::string>* args,
|
||||
std::vector<std::string>* exec_args,
|
||||
bool is_env) {
|
||||
int ProcessGlobalArgs(std::vector<std::string>* args,
|
||||
std::vector<std::string>* exec_args,
|
||||
std::vector<std::string>* errors,
|
||||
bool is_env) {
|
||||
// Parse a few arguments which are specific to Node.
|
||||
std::vector<std::string> v8_args;
|
||||
std::vector<std::string> errors{};
|
||||
|
||||
{
|
||||
// TODO(addaleax): The mutex here should ideally be held during the
|
||||
// entire function, but that doesn't play well with the exit() calls below.
|
||||
Mutex::ScopedLock lock(per_process::cli_options_mutex);
|
||||
options_parser::PerProcessOptionsParser::instance.Parse(
|
||||
args,
|
||||
exec_args,
|
||||
&v8_args,
|
||||
per_process::cli_options.get(),
|
||||
is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
|
||||
&errors);
|
||||
}
|
||||
Mutex::ScopedLock lock(per_process::cli_options_mutex);
|
||||
options_parser::PerProcessOptionsParser::instance.Parse(
|
||||
args,
|
||||
exec_args,
|
||||
&v8_args,
|
||||
per_process::cli_options.get(),
|
||||
is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
|
||||
errors);
|
||||
|
||||
if (!errors.empty()) {
|
||||
for (auto const& error : errors) {
|
||||
fprintf(stderr, "%s: %s\n", args->at(0).c_str(), error.c_str());
|
||||
}
|
||||
exit(9);
|
||||
}
|
||||
|
||||
if (per_process::cli_options->print_version) {
|
||||
printf("%s\n", NODE_VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (per_process::cli_options->print_v8_help) {
|
||||
V8::SetFlagsFromString("--help", 6);
|
||||
exit(0);
|
||||
}
|
||||
if (!errors->empty()) return 9;
|
||||
|
||||
for (const std::string& cve : per_process::cli_options->security_reverts)
|
||||
Revert(cve.c_str());
|
||||
@ -1222,19 +1203,17 @@ void ProcessArgv(std::vector<std::string>* args,
|
||||
}
|
||||
|
||||
// Anything that's still in v8_argv is not a V8 or a node option.
|
||||
for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++) {
|
||||
fprintf(stderr, "%s: bad option: %s\n",
|
||||
args->at(0).c_str(), v8_args_as_char_ptr[i]);
|
||||
}
|
||||
for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++)
|
||||
errors->push_back("bad option: " + std::string(v8_args_as_char_ptr[i]));
|
||||
|
||||
if (v8_args_as_char_ptr.size() > 1) {
|
||||
exit(9);
|
||||
}
|
||||
if (v8_args_as_char_ptr.size() > 1) return 9;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Init(std::vector<std::string>* argv,
|
||||
std::vector<std::string>* exec_argv) {
|
||||
int Init(std::vector<std::string>* argv,
|
||||
std::vector<std::string>* exec_argv,
|
||||
std::vector<std::string>* errors) {
|
||||
// Initialize prog_start_time to get relative uptime.
|
||||
per_process::prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
|
||||
|
||||
@ -1295,11 +1274,13 @@ void Init(std::vector<std::string>* argv,
|
||||
std::vector<std::string> env_argv = SplitString("x " + node_options, ' ');
|
||||
env_argv[0] = argv->at(0);
|
||||
|
||||
ProcessArgv(&env_argv, nullptr, true);
|
||||
const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
|
||||
if (exit_code != 0) return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
ProcessArgv(argv, exec_argv, false);
|
||||
const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, false);
|
||||
if (exit_code != 0) return exit_code;
|
||||
|
||||
// Set the process.title immediately after processing argv if --title is set.
|
||||
if (!per_process::cli_options->title.empty())
|
||||
@ -1313,11 +1294,9 @@ void Init(std::vector<std::string>* argv,
|
||||
// Initialize ICU.
|
||||
// If icu_data_dir is empty here, it will load the 'minimal' data.
|
||||
if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
|
||||
fprintf(stderr,
|
||||
"%s: could not initialize ICU "
|
||||
"(check NODE_ICU_DATA or --icu-data-dir parameters)\n",
|
||||
argv->at(0).c_str());
|
||||
exit(9);
|
||||
errors->push_back("could not initialize ICU "
|
||||
"(check NODE_ICU_DATA or --icu-data-dir parameters)\n");
|
||||
return 9;
|
||||
}
|
||||
per_process::metadata.versions.InitializeIntlVersions();
|
||||
#endif
|
||||
@ -1326,6 +1305,7 @@ void Init(std::vector<std::string>* argv,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(addaleax): Deprecate and eventually remove this.
|
||||
@ -1335,8 +1315,25 @@ void Init(int* argc,
|
||||
const char*** exec_argv) {
|
||||
std::vector<std::string> argv_(argv, argv + *argc); // NOLINT
|
||||
std::vector<std::string> exec_argv_;
|
||||
std::vector<std::string> errors;
|
||||
|
||||
Init(&argv_, &exec_argv_);
|
||||
// This (approximately) duplicates some logic that has been moved to
|
||||
// node::Start(), with the difference that here we explicitly call `exit()`.
|
||||
int exit_code = Init(&argv_, &exec_argv_, &errors);
|
||||
|
||||
for (const std::string& error : errors)
|
||||
fprintf(stderr, "%s: %s\n", argv_.at(0).c_str(), error.c_str());
|
||||
if (exit_code != 0) exit(exit_code);
|
||||
|
||||
if (per_process::cli_options->print_version) {
|
||||
printf("%s\n", NODE_VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (per_process::cli_options->print_v8_help) {
|
||||
V8::SetFlagsFromString("--help", 6); // Doesn't return.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
*argc = argv_.size();
|
||||
*exec_argc = exec_argv_.size();
|
||||
@ -1653,6 +1650,16 @@ inline int Start(uv_loop_t* event_loop,
|
||||
if (isolate == nullptr)
|
||||
return 12; // Signal internal error.
|
||||
|
||||
if (per_process::cli_options->print_version) {
|
||||
printf("%s\n", NODE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (per_process::cli_options->print_v8_help) {
|
||||
V8::SetFlagsFromString("--help", 6); // Doesn't return.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
{
|
||||
Mutex::ScopedLock scoped_lock(per_process::main_isolate_mutex);
|
||||
CHECK_NULL(per_process::main_isolate);
|
||||
@ -1712,8 +1719,14 @@ int Start(int argc, char** argv) {
|
||||
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
std::vector<std::string> exec_args;
|
||||
std::vector<std::string> errors;
|
||||
// This needs to run *before* V8::Initialize().
|
||||
Init(&args, &exec_args);
|
||||
{
|
||||
const int exit_code = Init(&args, &exec_args, &errors);
|
||||
for (const std::string& error : errors)
|
||||
fprintf(stderr, "%s: %s\n", args.at(0).c_str(), error.c_str());
|
||||
if (exit_code != 0) return exit_code;
|
||||
}
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user