From ea66bfc9c655be293a60a62584342712d9d1e90e Mon Sep 17 00:00:00 2001 From: snek Date: Sun, 31 Aug 2025 17:08:02 +0200 Subject: [PATCH] src: add NODE_OPTIONS_STANDALONE --- argparse.cc | 108 +++++++++++++++++++++++++++++++++++++ src/node_options.cc | 127 ++++++++++++++++++++++++-------------------- src/node_options.h | 5 +- 3 files changed, 181 insertions(+), 59 deletions(-) create mode 100644 argparse.cc diff --git a/argparse.cc b/argparse.cc new file mode 100644 index 00000000000000..725a52b4cd68d1 --- /dev/null +++ b/argparse.cc @@ -0,0 +1,108 @@ +#include "src/node_options.h" +#include "src/util.h" + +#include +#include +#include +#include + +extern "C" { + +uint64_t uv_get_total_memory() { + return 0; +} + +uint64_t uv_get_constrained_memory() { + return 0; +} +}; + +namespace node { + +void Assert(const AssertionInfo& info) { + fprintf(stderr, + "\n" + " # %s at %s\n" + " # Assertion failed: %s\n\n", + info.function ? info.function : "(unknown function)", + info.file_line ? info.file_line : "(unknown source location)", + info.message); + + fflush(stderr); + + abort(); +} + +} // namespace node + +int main(int argc, char** argv) { + std::vector args(argv, argv + argc); + std::vector exec_args; + std::vector errors; + + node::PerProcessOptions cli_options; + + cli_options.cmdline = args; + + if (const char* result = std::getenv("NODE_OPTIONS")) { + std::string node_options(result); + + std::vector env_argv = + node::ParseNodeOptionsEnvVar(node_options, &errors); + for (auto error : errors) { + std::cout << "error: " << error << std::endl; + } + if (!errors.empty()) return 1; + + env_argv.insert(env_argv.begin(), args.at(0)); + + { + std::vector v8_args; + node::options_parser::Parse(&env_argv, + nullptr, + &v8_args, + &cli_options, + node::OptionEnvvarSettings::kAllowedInEnvvar, + &errors); + + for (auto arg : v8_args | std::views::drop(1)) { + std::cout << "v8_arg: " << arg << std::endl; + } + } + } + + node::HandleEnvOptions(cli_options.per_isolate->per_env, + [](const char* name) { + const char* value = std::getenv(name); + if (value != nullptr) { + return std::string(value); + } + return std::string(""); + }); + + { + std::vector v8_args; + node::options_parser::Parse(&args, + &exec_args, + &v8_args, + &cli_options, + node::OptionEnvvarSettings::kDisallowedInEnvvar, + &errors); + + for (auto arg : v8_args | std::views::drop(1)) { + std::cout << "v8_arg: " << arg << std::endl; + } + } + + for (auto arg : args) { + std::cout << "arg: " << arg << std::endl; + } + + for (auto arg : exec_args) { + std::cout << "exec_arg: " << arg << std::endl; + } + + for (auto error : errors) { + std::cout << "error: " << error << std::endl; + } +} diff --git a/src/node_options.cc b/src/node_options.cc index d74ed1ca5afe53..4cfbe1b74b1858 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -21,6 +21,7 @@ #include #include +#ifndef NODE_OPTIONS_STANDALONE using v8::Boolean; using v8::Context; using v8::FunctionCallbackInfo; @@ -36,12 +37,16 @@ using v8::Object; using v8::String; using v8::Undefined; using v8::Value; +#endif // NODE_OPTIONS_STANDALONE + namespace node { +#ifndef NODE_OPTIONS_STANDALONE namespace per_process { Mutex cli_options_mutex; std::shared_ptr cli_options{new PerProcessOptions()}; } // namespace per_process +#endif // NODE_OPTIONS_STANDALONE void DebugOptions::CheckOptions(std::vector* errors, std::vector* argv) { @@ -293,64 +298,6 @@ void EnvironmentOptions::CheckOptions(std::vector* errors, namespace options_parser { -// Helper function to convert option types to their string representation -// and add them to a V8 Map -static bool AddOptionTypeToMap(Isolate* isolate, - Local context, - Local map, - const std::string& option_name, - const OptionType& option_type) { - std::string type; - switch (static_cast(option_type)) { - case 0: // No-op - case 1: // V8 flags - break; // V8 and NoOp flags are not supported - - case 2: - type = "boolean"; - break; - case 3: // integer - case 4: // unsigned integer - case 6: // host port - type = "number"; - break; - case 5: // string - type = "string"; - break; - case 7: // string array - type = "array"; - break; - default: - UNREACHABLE(); - } - - if (type.empty()) { - return true; // Skip this entry but continue processing - } - - Local option_key; - if (!String::NewFromUtf8(isolate, - option_name.data(), - v8::NewStringType::kNormal, - option_name.size()) - .ToLocal(&option_key)) { - return true; // Skip this entry but continue processing - } - - Local type_value; - if (!String::NewFromUtf8( - isolate, type.data(), v8::NewStringType::kNormal, type.size()) - .ToLocal(&type_value)) { - return true; // Skip this entry but continue processing - } - - if (map->Set(context, option_key, type_value).IsEmpty()) { - return false; // Error occurred, stop processing - } - - return true; -} - class DebugOptionsParser : public OptionsParser { public: DebugOptionsParser(); @@ -1445,6 +1392,65 @@ HostPort SplitHostPort(const std::string& arg, ParseAndValidatePort(arg.substr(colon + 1), errors) }; } +#ifndef NODE_OPTIONS_STANDALONE +// Helper function to convert option types to their string representation +// and add them to a V8 Map +static bool AddOptionTypeToMap(Isolate* isolate, + Local context, + Local map, + const std::string& option_name, + const OptionType& option_type) { + std::string type; + switch (static_cast(option_type)) { + case 0: // No-op + case 1: // V8 flags + break; // V8 and NoOp flags are not supported + + case 2: + type = "boolean"; + break; + case 3: // integer + case 4: // unsigned integer + case 6: // host port + type = "number"; + break; + case 5: // string + type = "string"; + break; + case 7: // string array + type = "array"; + break; + default: + UNREACHABLE(); + } + + if (type.empty()) { + return true; // Skip this entry but continue processing + } + + Local option_key; + if (!String::NewFromUtf8(isolate, + option_name.data(), + v8::NewStringType::kNormal, + option_name.size()) + .ToLocal(&option_key)) { + return true; // Skip this entry but continue processing + } + + Local type_value; + if (!String::NewFromUtf8( + isolate, type.data(), v8::NewStringType::kNormal, type.size()) + .ToLocal(&type_value)) { + return true; // Skip this entry but continue processing + } + + if (map->Set(context, option_key, type_value).IsEmpty()) { + return false; // Error occurred, stop processing + } + + return true; +} + std::string GetBashCompletion() { Mutex::ScopedLock lock(per_process::cli_options_mutex); const auto& parser = _ppop_instance; @@ -2033,14 +2039,17 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetEnvOptionsInputType); registry->Register(GetNamespaceOptionsInputType); } +#endif // NODE_OPTIONS_STANDALONE } // namespace options_parser +#ifndef NODE_OPTIONS_STANDALONE void HandleEnvOptions(std::shared_ptr env_options) { HandleEnvOptions(env_options, [](const char* name) { std::string text; return credentials::SafeGetenv(name, &text) ? text : ""; }); } +#endif // NODE_OPTIONS_STANDALONE void HandleEnvOptions(std::shared_ptr env_options, std::function opt_getter) { @@ -2100,6 +2109,8 @@ std::vector ParseNodeOptionsEnvVar( } } // namespace node +#ifndef NODE_OPTIONS_STANDALONE NODE_BINDING_CONTEXT_AWARE_INTERNAL(options, node::options_parser::Initialize) NODE_BINDING_EXTERNAL_REFERENCE( options, node::options_parser::RegisterExternalReferences) +#endif // NODE_OPTIONS_STANDALONE diff --git a/src/node_options.h b/src/node_options.h index d56a2c536f7df2..0de12f788c9d7e 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -389,7 +389,6 @@ namespace options_parser { HostPort SplitHostPort(const std::string& arg, std::vector* errors); -void GetOptions(const v8::FunctionCallbackInfo& args); std::string GetBashCompletion(); enum OptionType { @@ -638,6 +637,7 @@ class OptionsParser { template friend class OptionsParser; +#ifndef NODE_OPTIONS_STANDALONE friend void GetCLIOptionsValues( const v8::FunctionCallbackInfo& args); friend void GetCLIOptionsInfo( @@ -652,6 +652,7 @@ class OptionsParser { const v8::FunctionCallbackInfo& args); friend void GetOptionsAsFlags( const v8::FunctionCallbackInfo& args); +#endif // NODE_OPTIONS_STANDALONE }; using StringVector = std::vector; @@ -663,6 +664,7 @@ void Parse( } // namespace options_parser +#ifndef NODE_OPTIONS_STANDALONE namespace per_process { extern Mutex cli_options_mutex; @@ -671,6 +673,7 @@ extern NODE_EXTERN_PRIVATE std::shared_ptr cli_options; } // namespace per_process void HandleEnvOptions(std::shared_ptr env_options); +#endif // NODE_OPTIONS_STANDALONE void HandleEnvOptions(std::shared_ptr env_options, std::function opt_getter);