diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 3a42ce7df23bb9..a654182982f96a 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -39,8 +39,6 @@ function startup() { // Do this good and early, since it handles errors. setupProcessFatal(); - setupProcessICUVersions(); - setupGlobalVariables(); // Bootstrappers for all threads, including worker threads and main thread @@ -647,25 +645,6 @@ function setupProcessFatal() { }; } -function setupProcessICUVersions() { - const icu = internalBinding('config').hasIntl ? - internalBinding('icu') : undefined; - if (!icu) return; // no Intl/ICU: nothing to add here. - // With no argument, getVersion() returns a comma separated list - // of possible types. - const versionTypes = icu.getVersion().split(','); - - for (var n = 0; n < versionTypes.length; n++) { - const name = versionTypes[n]; - const version = icu.getVersion(name); - Object.defineProperty(process.versions, name, { - writable: false, - enumerable: true, - value: version - }); - } -} - function wrapForBreakOnFirstLine(source) { if (!process._breakFirstLine) return source; diff --git a/src/node.cc b/src/node.cc index 497e865737eadc..faf3ebb9ad1305 100644 --- a/src/node.cc +++ b/src/node.cc @@ -880,7 +880,10 @@ void SetupProcessObject(Environment* env, READONLY_PROPERTY(process, "versions", versions); #define V(key) \ - READONLY_STRING_PROPERTY(versions, #key, per_process::metadata.versions.key); + if (!per_process::metadata.versions.key.empty()) { \ + READONLY_STRING_PROPERTY( \ + versions, #key, per_process::metadata.versions.key); \ + } NODE_VERSIONS_KEYS(V) #undef V @@ -1672,6 +1675,7 @@ void Init(std::vector* argv, argv->at(0).c_str()); exit(9); } + per_process::metadata.versions.InitializeIntlVersions(); #endif // We should set node_is_initialized here instead of in node::Start, diff --git a/src/node_i18n.cc b/src/node_i18n.cc index d2a8c381820fa2..b4bc73ecbeb5dd 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -510,67 +510,6 @@ void ICUErrorName(const FunctionCallbackInfo& args) { NewStringType::kNormal).ToLocalChecked()); } -#define TYPE_ICU "icu" -#define TYPE_UNICODE "unicode" -#define TYPE_CLDR "cldr" -#define TYPE_TZ "tz" - -/** - * This is the workhorse function that deals with the actual version info. - * Get an ICU version. - * @param type the type of version to get. One of VERSION_TYPES - * @param buf optional buffer for result - * @param status ICU error status. If failure, assume result is undefined. - * @return version number, or NULL. May or may not be buf. - */ -const char* GetVersion(const char* type, - char buf[U_MAX_VERSION_STRING_LENGTH], - UErrorCode* status) { - if (!strcmp(type, TYPE_ICU)) { - return U_ICU_VERSION; - } else if (!strcmp(type, TYPE_UNICODE)) { - return U_UNICODE_VERSION; - } else if (!strcmp(type, TYPE_TZ)) { - return icu::TimeZone::getTZDataVersion(*status); - } else if (!strcmp(type, TYPE_CLDR)) { - UVersionInfo versionArray; - ulocdata_getCLDRVersion(versionArray, status); - if (U_SUCCESS(*status)) { - u_versionToString(versionArray, buf); - return buf; - } - } - // Fall through - unknown type or error case - return nullptr; -} - -void GetVersion(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - if ( args.Length() == 0 ) { - // With no args - return a comma-separated list of allowed values - args.GetReturnValue().Set( - String::NewFromUtf8(env->isolate(), - TYPE_ICU "," - TYPE_UNICODE "," - TYPE_CLDR "," - TYPE_TZ, NewStringType::kNormal).ToLocalChecked()); - } else { - CHECK_GE(args.Length(), 1); - CHECK(args[0]->IsString()); - Utf8Value val(env->isolate(), args[0]); - UErrorCode status = U_ZERO_ERROR; - char buf[U_MAX_VERSION_STRING_LENGTH] = ""; // Possible output buffer. - const char* versionString = GetVersion(*val, buf, &status); - - if (U_SUCCESS(status) && versionString) { - // Success. - args.GetReturnValue().Set( - String::NewFromUtf8(env->isolate(), - versionString, NewStringType::kNormal).ToLocalChecked()); - } - } -} - } // anonymous namespace bool InitializeICUDirectory(const std::string& path) { @@ -868,7 +807,6 @@ void Initialize(Local target, env->SetMethod(target, "toUnicode", ToUnicode); env->SetMethod(target, "toASCII", ToASCII); env->SetMethod(target, "getStringWidth", GetStringWidth); - env->SetMethod(target, "getVersion", GetVersion); // One-shot converters env->SetMethod(target, "icuErrName", ICUErrorName); diff --git a/src/node_metadata.cc b/src/node_metadata.cc index 1f86ebc5973fe7..3bfed6d4b57ea2 100644 --- a/src/node_metadata.cc +++ b/src/node_metadata.cc @@ -12,6 +12,13 @@ #include #endif // HAVE_OPENSSL +#ifdef NODE_HAVE_I18N_SUPPORT +#include +#include +#include +#include +#endif // NODE_HAVE_I18N_SUPPORT + namespace node { namespace per_process { @@ -35,6 +42,25 @@ std::string GetOpenSSLVersion() { } #endif // HAVE_OPENSSL +#ifdef NODE_HAVE_I18N_SUPPORT +void Metadata::Versions::InitializeIntlVersions() { + UErrorCode status = U_ZERO_ERROR; + + const char* tz_version = icu::TimeZone::getTZDataVersion(status); + if (U_SUCCESS(status)) { + tz = tz_version; + } + + char buf[U_MAX_VERSION_STRING_LENGTH]; + UVersionInfo versionArray; + ulocdata_getCLDRVersion(versionArray, &status); + if (U_SUCCESS(status)) { + u_versionToString(versionArray, buf); + cldr = buf; + } +} +#endif // NODE_HAVE_I18N_SUPPORT + Metadata::Versions::Versions() { node = NODE_VERSION_STRING; v8 = v8::V8::GetVersion(); @@ -57,6 +83,11 @@ Metadata::Versions::Versions() { #if HAVE_OPENSSL openssl = GetOpenSSLVersion(); #endif + +#ifdef NODE_HAVE_I18N_SUPPORT + icu = U_ICU_VERSION; + unicode = U_UNICODE_VERSION; +#endif // NODE_HAVE_I18N_SUPPORT } } // namespace node diff --git a/src/node_metadata.h b/src/node_metadata.h index bf1a7cb9e07c20..ef93c7b7e41707 100644 --- a/src/node_metadata.h +++ b/src/node_metadata.h @@ -26,14 +26,38 @@ namespace node { #define NODE_VERSIONS_KEY_CRYPTO(V) #endif +#ifdef NODE_HAVE_I18N_SUPPORT +#define NODE_VERSIONS_KEY_INTL(V) \ + V(cldr) \ + V(icu) \ + V(tz) \ + V(unicode) +#else +#define NODE_VERSIONS_KEY_INTL(V) +#endif // NODE_HAVE_I18N_SUPPORT + #define NODE_VERSIONS_KEYS(V) \ NODE_VERSIONS_KEYS_BASE(V) \ - NODE_VERSIONS_KEY_CRYPTO(V) + NODE_VERSIONS_KEY_CRYPTO(V) \ + NODE_VERSIONS_KEY_INTL(V) class Metadata { public: + Metadata() = default; + Metadata(Metadata&) = delete; + Metadata(Metadata&&) = delete; + Metadata operator=(Metadata&) = delete; + Metadata operator=(Metadata&&) = delete; + struct Versions { Versions(); + +#ifdef NODE_HAVE_I18N_SUPPORT + // Must be called on the main thread after + // i18n::InitializeICUDirectory() + void InitializeIntlVersions(); +#endif // NODE_HAVE_I18N_SUPPORT + #define V(key) std::string key; NODE_VERSIONS_KEYS(V) #undef V