From c66c0732e0887c3f07a3e387d8a90b432eae134e Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 20 Dec 2018 05:33:10 +0800 Subject: src: lazily load internalBinding('uv') and build the errmap lazily This removes the `internalBinding('uv')` call from the normal bootstrap for now, and avoids building `errmap` by default which expands to a lot of calls into V8. PR-URL: https://github.com/nodejs/node/pull/25143 Reviewed-By: Anna Henningsen Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- src/uv.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 22 deletions(-) (limited to 'src/uv.cc') diff --git a/src/uv.cc b/src/uv.cc index 27daed556e..a7d0b1012c 100644 --- a/src/uv.cc +++ b/src/uv.cc @@ -25,20 +25,39 @@ #include "env-inl.h" namespace node { + +namespace per_process { +struct UVError { + int value; + const char* name; + const char* message; +}; + +// We only expand the macro once here to reduce the amount of code +// generated. +static const struct UVError uv_errors_map[] = { +#define V(name, message) {UV_##name, #name, message}, + UV_ERRNO_MAP(V) +#undef V +}; +} // namespace per_process + namespace { using v8::Array; using v8::Context; +using v8::DontDelete; using v8::FunctionCallbackInfo; using v8::Integer; using v8::Isolate; using v8::Local; using v8::Map; using v8::Object; +using v8::PropertyAttribute; +using v8::ReadOnly; using v8::String; using v8::Value; - void ErrName(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (env->options()->pending_deprecation && env->EmitErrNameWarning()) { @@ -57,6 +76,29 @@ void ErrName(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(OneByteString(env->isolate(), name)); } +void GetErrMap(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + Local context = env->context(); + + Local err_map = Map::New(isolate); + + size_t errors_len = arraysize(per_process::uv_errors_map); + for (size_t i = 0; i < errors_len; ++i) { + const auto& error = per_process::uv_errors_map[i]; + Local arr[] = {OneByteString(isolate, error.name), + OneByteString(isolate, error.message)}; + if (err_map + ->Set(context, + Integer::New(isolate, error.value), + Array::New(isolate, arr, arraysize(arr))) + .IsEmpty()) { + return; + } + } + + args.GetReturnValue().Set(err_map); +} void Initialize(Local target, Local unused, @@ -70,28 +112,21 @@ void Initialize(Local target, ->GetFunction(env->context()) .ToLocalChecked()).FromJust(); -#define V(name, _) NODE_DEFINE_CONSTANT(target, UV_##name); - UV_ERRNO_MAP(V) -#undef V - - Local err_map = Map::New(isolate); - -#define V(name, msg) do { \ - Local arr[] = { \ - OneByteString(isolate, #name), \ - OneByteString(isolate, msg) \ - }; \ - if (err_map->Set(context, \ - Integer::New(isolate, UV_##name), \ - Array::New(isolate, arr, arraysize(arr))).IsEmpty()) { \ - return; \ - } \ -} while (0); - UV_ERRNO_MAP(V) -#undef V + // TODO(joyeecheung): This should be deprecated in user land in favor of + // `util.getSystemErrorName(err)`. + PropertyAttribute attributes = + static_cast(ReadOnly | DontDelete); + size_t errors_len = arraysize(per_process::uv_errors_map); + const std::string prefix = "UV_"; + for (size_t i = 0; i < errors_len; ++i) { + const auto& error = per_process::uv_errors_map[i]; + const std::string prefixed_name = prefix + error.name; + Local name = OneByteString(isolate, prefixed_name.c_str()); + Local value = Integer::New(isolate, error.value); + target->DefineOwnProperty(context, name, value, attributes).FromJust(); + } - target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "errmap"), - err_map).FromJust(); + env->SetMethod(target, "getErrorMap", GetErrMap); } } // anonymous namespace -- cgit v1.2.3