src: initialize ICU version in per_process::metadata.versions
Instead of - Initialize the ICU versions in JS land after consulting internalBinding('config').hasIntl - Joining the version keys in C++ - Splitting the keys in JS and call into C++ again to get the value for each of the keys Do: - Guard the initialization code behind `NODE_HAVE_I18N_SUPPORT` - Do the initialization in C++ right after ICU data is loaded - Initialize each version directly using ICU functions/constants, and put them in per_process::metadata.versions. These will be copied into `process.versions` naturally later. This way, the initialization of the versions won't be called in worker threads again. PR-URL: https://github.com/nodejs/node/pull/25115 Reviewed-By: Steven R Loomis <srloomis@us.ibm.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Minwoo Jung <minwoo@nodesource.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
a29c93a147
commit
263d13766f
@ -38,8 +38,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
|
||||
@ -638,25 +636,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;
|
||||
|
@ -877,7 +877,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
|
||||
|
||||
@ -1664,6 +1667,7 @@ void Init(std::vector<std::string>* 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,
|
||||
|
@ -510,67 +510,6 @@ void ICUErrorName(const FunctionCallbackInfo<Value>& 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<Value>& 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<Object> 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);
|
||||
|
@ -11,6 +11,13 @@
|
||||
#include <openssl/opensslv.h>
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
#ifdef NODE_HAVE_I18N_SUPPORT
|
||||
#include <unicode/timezone.h>
|
||||
#include <unicode/ulocdata.h>
|
||||
#include <unicode/uvernum.h>
|
||||
#include <unicode/uversion.h>
|
||||
#endif // NODE_HAVE_I18N_SUPPORT
|
||||
|
||||
namespace node {
|
||||
|
||||
namespace per_process {
|
||||
@ -34,6 +41,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();
|
||||
@ -49,6 +75,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
|
||||
|
@ -25,14 +25,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
|
||||
|
Loading…
x
Reference in New Issue
Block a user