diff --git a/node.gyp b/node.gyp index 4ad5ef3a9f8706..6a92db00d13836 100644 --- a/node.gyp +++ b/node.gyp @@ -356,6 +356,7 @@ 'src/node_http2.cc', 'src/node_i18n.cc', 'src/node_messaging.cc', + 'src/node_metadata.cc', 'src/node_native_module.cc', 'src/node_options.cc', 'src/node_os.cc', @@ -427,6 +428,7 @@ 'src/node_i18n.h', 'src/node_internals.h', 'src/node_messaging.h', + 'src/node_metadata.h', 'src/node_mutex.h', 'src/node_native_module.h', 'src/node_object_wrap.h', diff --git a/src/node.cc b/src/node.cc index 01690a1e6c94da..dcdc002ae59430 100644 --- a/src/node.cc +++ b/src/node.cc @@ -25,6 +25,7 @@ #include "node_context_data.h" #include "node_errors.h" #include "node_internals.h" +#include "node_metadata.h" #include "node_native_module.h" #include "node_perf.h" #include "node_platform.h" @@ -48,16 +49,9 @@ #include "node_dtrace.h" #endif -#include "ares.h" #include "async_wrap-inl.h" #include "env-inl.h" #include "handle_wrap.h" -#ifdef NODE_EXPERIMENTAL_HTTP -# include "llhttp.h" -#else /* !NODE_EXPERIMENTAL_HTTP */ -# include "http_parser.h" -#endif /* NODE_EXPERIMENTAL_HTTP */ -#include "nghttp2/nghttp2ver.h" #include "req_wrap-inl.h" #include "string_bytes.h" #include "tracing/agent.h" @@ -68,7 +62,6 @@ #include "libplatform/libplatform.h" #endif // NODE_USE_V8_PLATFORM #include "v8-profiler.h" -#include "zlib.h" #ifdef NODE_ENABLE_VTUNE_PROFILING #include "../deps/v8/src/third_party/vtune/v8-vtune.h" @@ -123,7 +116,6 @@ using v8::Array; using v8::Boolean; using v8::Context; using v8::DEFAULT; -using v8::DontEnum; using v8::EscapableHandleScope; using v8::Exception; using v8::Function; @@ -146,8 +138,6 @@ using v8::Nothing; using v8::Null; using v8::Object; using v8::ObjectTemplate; -using v8::PropertyAttribute; -using v8::ReadOnly; using v8::Script; using v8::ScriptOrigin; using v8::SealHandleScope; @@ -161,22 +151,6 @@ using v8::Value; static bool v8_is_profiling = false; -#ifdef NODE_EXPERIMENTAL_HTTP -static const char llhttp_version[] = - NODE_STRINGIFY(LLHTTP_VERSION_MAJOR) - "." - NODE_STRINGIFY(LLHTTP_VERSION_MINOR) - "." - NODE_STRINGIFY(LLHTTP_VERSION_PATCH); -#else /* !NODE_EXPERIMENTAL_HTTP */ -static const char http_parser_version[] = - NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) - "." - NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR) - "." - NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH); -#endif /* NODE_EXPERIMENTAL_HTTP */ - // Bit flag used to track security reverts (see node_revert.h) unsigned int reverted = 0; @@ -215,27 +189,12 @@ class NodeTraceStateObserver : auto trace_process = tracing::TracedValue::Create(); trace_process->BeginDictionary("versions"); -#ifdef NODE_EXPERIMENTAL_HTTP - trace_process->SetString("llhttp", llhttp_version); -#else /* !NODE_EXPERIMENTAL_HTTP */ - trace_process->SetString("http_parser", http_parser_version); -#endif /* NODE_EXPERIMENTAL_HTTP */ - - const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION); - const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION); +#define V(key) \ + trace_process->SetString(#key, per_process::metadata.versions.key.c_str()); - trace_process->SetString("node", NODE_VERSION_STRING); - trace_process->SetString("v8", V8::GetVersion()); - trace_process->SetString("uv", uv_version_string()); - trace_process->SetString("zlib", ZLIB_VERSION); - trace_process->SetString("ares", ARES_VERSION_STR); - trace_process->SetString("modules", node_modules_version); - trace_process->SetString("nghttp2", NGHTTP2_VERSION); - trace_process->SetString("napi", node_napi_version); + NODE_VERSIONS_KEYS(V) +#undef V -#if HAVE_OPENSSL - trace_process->SetString("openssl", crypto::GetOpenSSLVersion()); -#endif trace_process->EndDictionary(); trace_process->SetString("arch", NODE_ARCH); @@ -954,31 +913,12 @@ static Local GetFeatures(Environment* env) { static void DebugProcess(const FunctionCallbackInfo& args); static void DebugEnd(const FunctionCallbackInfo& args); -namespace { - -#define READONLY_PROPERTY(obj, str, var) \ - do { \ - obj->DefineOwnProperty(env->context(), \ - OneByteString(env->isolate(), str), \ - var, \ - ReadOnly).FromJust(); \ - } while (0) - -#define READONLY_DONT_ENUM_PROPERTY(obj, str, var) \ - do { \ - obj->DefineOwnProperty(env->context(), \ - OneByteString(env->isolate(), str), \ - var, \ - static_cast(ReadOnly|DontEnum)) \ - .FromJust(); \ - } while (0) - -} // anonymous namespace - void SetupProcessObject(Environment* env, const std::vector& args, const std::vector& exec_args) { - HandleScope scope(env->isolate()); + Isolate* isolate = env->isolate(); + HandleScope scope(isolate); + Local context = env->context(); Local process = env->process_object(); @@ -1002,53 +942,10 @@ void SetupProcessObject(Environment* env, Local versions = Object::New(env->isolate()); READONLY_PROPERTY(process, "versions", versions); -#ifdef NODE_EXPERIMENTAL_HTTP - READONLY_PROPERTY(versions, - "llhttp", - FIXED_ONE_BYTE_STRING(env->isolate(), llhttp_version)); -#else /* !NODE_EXPERIMENTAL_HTTP */ - READONLY_PROPERTY(versions, - "http_parser", - FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version)); -#endif /* NODE_EXPERIMENTAL_HTTP */ - - // +1 to get rid of the leading 'v' - READONLY_PROPERTY(versions, - "node", - OneByteString(env->isolate(), NODE_VERSION + 1)); - READONLY_PROPERTY(versions, - "v8", - OneByteString(env->isolate(), V8::GetVersion())); - READONLY_PROPERTY(versions, - "uv", - OneByteString(env->isolate(), uv_version_string())); - READONLY_PROPERTY(versions, - "zlib", - FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION)); - READONLY_PROPERTY(versions, - "ares", - FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR)); - - const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION); - READONLY_PROPERTY( - versions, - "modules", - FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version)); - READONLY_PROPERTY(versions, - "nghttp2", - FIXED_ONE_BYTE_STRING(env->isolate(), NGHTTP2_VERSION)); - const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION); - READONLY_PROPERTY( - versions, - "napi", - FIXED_ONE_BYTE_STRING(env->isolate(), node_napi_version)); - -#if HAVE_OPENSSL - READONLY_PROPERTY( - versions, - "openssl", - OneByteString(env->isolate(), crypto::GetOpenSSLVersion().c_str())); -#endif +#define V(key) \ + READONLY_STRING_PROPERTY(versions, #key, per_process::metadata.versions.key); + NODE_VERSIONS_KEYS(V) +#undef V // process.arch READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), NODE_ARCH)); @@ -1319,9 +1216,6 @@ void SetupProcessObject(Environment* env, } -#undef READONLY_PROPERTY - - void SignalExit(int signo) { uv_tty_reset_mode(); #ifdef __FreeBSD__ diff --git a/src/node_config.cc b/src/node_config.cc index c3592dc3e8803d..6b7f4e62b7cd94 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -12,8 +12,6 @@ using v8::Isolate; using v8::Local; using v8::Number; using v8::Object; -using v8::ReadOnly; -using v8::String; using v8::Value; // The config binding is used to provide an internal view of compile or runtime @@ -21,32 +19,6 @@ using v8::Value; // alternative to dropping additional properties onto the process object as // has been the practice previously in node.cc. -#define READONLY_BOOLEAN_PROPERTY(str) \ - do { \ - target->DefineOwnProperty(context, \ - FIXED_ONE_BYTE_STRING(isolate, str), \ - True(isolate), ReadOnly).FromJust(); \ - } while (0) - -#define READONLY_STRING_PROPERTY(obj, str, val) \ - do { \ - (obj)->DefineOwnProperty(context, \ - FIXED_ONE_BYTE_STRING(isolate, str), \ - String::NewFromUtf8( \ - isolate, \ - val.data(), \ - v8::NewStringType::kNormal).ToLocalChecked(), \ - ReadOnly).FromJust(); \ - } while (0) - - -#define READONLY_PROPERTY(obj, name, value) \ - do { \ - obj->DefineOwnProperty(env->context(), \ - FIXED_ONE_BYTE_STRING(isolate, name), \ - value, ReadOnly).FromJust(); \ - } while (0) - static void Initialize(Local target, Local unused, Local context) { @@ -54,26 +26,26 @@ static void Initialize(Local target, Isolate* isolate = env->isolate(); #ifdef NODE_FIPS_MODE - READONLY_BOOLEAN_PROPERTY("fipsMode"); + READONLY_TRUE_PROPERTY(target, "fipsMode"); // TODO(addaleax): Use options parser variable instead. if (per_process_opts->force_fips_crypto) - READONLY_BOOLEAN_PROPERTY("fipsForced"); + READONLY_TRUE_PROPERTY(target, "fipsForced"); #endif #ifdef NODE_HAVE_I18N_SUPPORT - READONLY_BOOLEAN_PROPERTY("hasIntl"); + READONLY_TRUE_PROPERTY(target, "hasIntl"); #ifdef NODE_HAVE_SMALL_ICU - READONLY_BOOLEAN_PROPERTY("hasSmallICU"); + READONLY_TRUE_PROPERTY(target, "hasSmallICU"); #endif // NODE_HAVE_SMALL_ICU #if NODE_USE_V8_PLATFORM - READONLY_BOOLEAN_PROPERTY("hasTracing"); + READONLY_TRUE_PROPERTY(target, "hasTracing"); #endif #if !defined(NODE_WITHOUT_NODE_OPTIONS) - READONLY_BOOLEAN_PROPERTY("hasNodeOptions"); + READONLY_TRUE_PROPERTY(target, "hasNodeOptions"); #endif // TODO(addaleax): This seems to be an unused, private API. Remove it? @@ -83,12 +55,12 @@ static void Initialize(Local target, #endif // NODE_HAVE_I18N_SUPPORT if (env->options()->preserve_symlinks) - READONLY_BOOLEAN_PROPERTY("preserveSymlinks"); + READONLY_TRUE_PROPERTY(target, "preserveSymlinks"); if (env->options()->preserve_symlinks_main) - READONLY_BOOLEAN_PROPERTY("preserveSymlinksMain"); + READONLY_TRUE_PROPERTY(target, "preserveSymlinksMain"); if (env->options()->experimental_modules) { - READONLY_BOOLEAN_PROPERTY("experimentalModules"); + READONLY_TRUE_PROPERTY(target, "experimentalModules"); const std::string& userland_loader = env->options()->userland_loader; if (!userland_loader.empty()) { READONLY_STRING_PROPERTY(target, "userLoader", userland_loader); @@ -96,22 +68,22 @@ static void Initialize(Local target, } if (env->options()->experimental_vm_modules) - READONLY_BOOLEAN_PROPERTY("experimentalVMModules"); + READONLY_TRUE_PROPERTY(target, "experimentalVMModules"); if (env->options()->experimental_worker) - READONLY_BOOLEAN_PROPERTY("experimentalWorker"); + READONLY_TRUE_PROPERTY(target, "experimentalWorker"); if (env->options()->experimental_repl_await) - READONLY_BOOLEAN_PROPERTY("experimentalREPLAwait"); + READONLY_TRUE_PROPERTY(target, "experimentalREPLAwait"); if (env->options()->pending_deprecation) - READONLY_BOOLEAN_PROPERTY("pendingDeprecation"); + READONLY_TRUE_PROPERTY(target, "pendingDeprecation"); if (env->options()->expose_internals) - READONLY_BOOLEAN_PROPERTY("exposeInternals"); + READONLY_TRUE_PROPERTY(target, "exposeInternals"); if (env->abort_on_uncaught_exception()) - READONLY_BOOLEAN_PROPERTY("shouldAbortOnUncaughtException"); + READONLY_TRUE_PROPERTY(target, "shouldAbortOnUncaughtException"); READONLY_PROPERTY(target, "bits", diff --git a/src/node_metadata.cc b/src/node_metadata.cc new file mode 100644 index 00000000000000..1bf2fcfce9561c --- /dev/null +++ b/src/node_metadata.cc @@ -0,0 +1,49 @@ +#include "node_metadata.h" +#include "ares.h" +#include "nghttp2/nghttp2ver.h" +#include "node.h" +#include "util.h" +#include "uv.h" +#include "v8.h" +#include "zlib.h" + +#if HAVE_OPENSSL +#include "node_crypto.h" +#endif + +#ifdef NODE_EXPERIMENTAL_HTTP +#include "llhttp.h" +#else /* !NODE_EXPERIMENTAL_HTTP */ +#include "http_parser.h" +#endif /* NODE_EXPERIMENTAL_HTTP */ + +namespace node { + +namespace per_process { +Metadata metadata; +} + +Metadata::Versions::Versions() { + node = NODE_VERSION_STRING; + v8 = v8::V8::GetVersion(); + uv = uv_version_string(); + zlib = ZLIB_VERSION; + ares = ARES_VERSION_STR; + modules = NODE_STRINGIFY(NODE_MODULE_VERSION); + nghttp2 = NGHTTP2_VERSION; + napi = NODE_STRINGIFY(NAPI_VERSION); + +#ifdef NODE_EXPERIMENTAL_HTTP + llhttp = NODE_STRINGIFY(LLHTTP_VERSION_MAJOR) "." NODE_STRINGIFY( + LLHTTP_VERSION_MINOR) "." NODE_STRINGIFY(LLHTTP_VERSION_PATCH); +#else /* !NODE_EXPERIMENTAL_HTTP */ + http_parser = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "." NODE_STRINGIFY( + HTTP_PARSER_VERSION_MINOR) "." NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH); +#endif /* NODE_EXPERIMENTAL_HTTP */ + +#if HAVE_OPENSSL + openssl = crypto::GetOpenSSLVersion(); +#endif +} + +} // namespace node diff --git a/src/node_metadata.h b/src/node_metadata.h new file mode 100644 index 00000000000000..0f32fcf21d1600 --- /dev/null +++ b/src/node_metadata.h @@ -0,0 +1,57 @@ +#ifndef SRC_NODE_METADATA_H_ +#define SRC_NODE_METADATA_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include + +namespace node { + +#define NODE_VERSIONS_KEYS_BASE(V) \ + V(node) \ + V(v8) \ + V(uv) \ + V(zlib) \ + V(ares) \ + V(modules) \ + V(nghttp2) \ + V(napi) + +#ifdef NODE_EXPERIMENTAL_HTTP +#define NODE_VERSIONS_KEY_HTTP(V) V(llhttp) +#else /* !NODE_EXPERIMENTAL_HTTP */ +#define NODE_VERSIONS_KEY_HTTP(V) V(http_parser) +#endif /* NODE_EXPERIMENTAL_HTTP */ + +#if HAVE_OPENSSL +#define NODE_VERSIONS_KEY_CRYPTO(V) V(openssl) +#else +#define NODE_VERSIONS_KEY_CRYPTO(V) +#endif + +#define NODE_VERSIONS_KEYS(V) \ + NODE_VERSIONS_KEYS_BASE(V) \ + NODE_VERSIONS_KEY_HTTP(V) \ + NODE_VERSIONS_KEY_CRYPTO(V) + +class Metadata { + public: + struct Versions { + Versions(); +#define V(key) std::string key; + NODE_VERSIONS_KEYS(V) +#undef V + }; + + Versions versions; +}; + +// Per-process global +namespace per_process { +extern Metadata metadata; +} + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#endif // SRC_NODE_METADATA_H_ diff --git a/src/util.h b/src/util.h index 086e33933e6b5a..ca35ed7fc98508 100644 --- a/src/util.h +++ b/src/util.h @@ -470,6 +470,31 @@ template inline v8::MaybeLocal ToV8Value(v8::Local context, const std::unordered_map& map); +// These macros expects a `Isolate* isolate` and a `Local context` +// to be in the scope. +#define READONLY_PROPERTY(obj, name, value) \ + do { \ + obj->DefineOwnProperty( \ + context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \ + .FromJust(); \ + } while (0) + +#define READONLY_DONT_ENUM_PROPERTY(obj, name, var) \ + do { \ + obj->DefineOwnProperty( \ + context, \ + OneByteString(isolate, name), \ + var, \ + static_cast(v8::ReadOnly | v8::DontEnum)) \ + .FromJust(); \ + } while (0) + +#define READONLY_TRUE_PROPERTY(obj, name) \ + READONLY_PROPERTY(obj, name, True(isolate)) + +#define READONLY_STRING_PROPERTY(obj, name, str) \ + READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked()) + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS