Skip to content

Commit dd6667d

Browse files
joyeecheungtargos
authored andcommitted
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: #25143 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent c7d2dbd commit dd6667d

3 files changed

Lines changed: 90 additions & 33 deletions

File tree

‎lib/internal/errors.js‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@ const kInfo = Symbol('info');
1515
constmessages=newMap();
1616
constcodes={};
1717

18-
const{
19-
errmap,
20-
UV_EAI_NODATA,
21-
UV_EAI_NONAME
22-
}=internalBinding('uv');
2318
const{ kMaxLength }=internalBinding('buffer');
2419
const{ defineProperty }=Object;
2520

@@ -237,6 +232,24 @@ function getMessage(key, args) {
237232
returnutil.format.apply(null,args);
238233
}
239234

235+
letuvBinding;
236+
237+
functionlazyUv(){
238+
if(!uvBinding){
239+
uvBinding=internalBinding('uv');
240+
}
241+
returnuvBinding;
242+
}
243+
244+
functionlazyErrmapGet(name){
245+
uvBinding=lazyUv();
246+
if(!uvBinding.errmap){
247+
uvBinding.errmap=uvBinding.getErrorMap();
248+
}
249+
returnuvBinding.errmap.get(name);
250+
}
251+
252+
240253
/**
241254
* This creates an error compatible with errors produced in the C++
242255
* function UVException using a context object with data assembled in C++.
@@ -247,7 +260,7 @@ function getMessage(key, args) {
247260
* @returns {Error}
248261
*/
249262
functionuvException(ctx){
250-
const[code,uvmsg]=errmap.get(ctx.errno);
263+
const[code,uvmsg]=lazyErrmapGet(ctx.errno);
251264
letmessage=`${code}: ${ctx.message||uvmsg}, ${ctx.syscall}`;
252265

253266
letpath;
@@ -303,7 +316,7 @@ function uvException(ctx) {
303316
* @returns {Error}
304317
*/
305318
functionuvExceptionWithHostPort(err,syscall,address,port){
306-
const[code,uvmsg]=errmap.get(err);
319+
const[code,uvmsg]=lazyErrmapGet(err);
307320
constmessage=`${syscall}${code}: ${uvmsg}`;
308321
letdetails='';
309322

@@ -421,7 +434,7 @@ function dnsException(code, syscall, hostname) {
421434
if(typeofcode==='number'){
422435
// FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass
423436
// the true error to the user. ENOTFOUND is not even a proper POSIX error!
424-
if(code===UV_EAI_NODATA||code===UV_EAI_NONAME){
437+
if(code===lazyUv().UV_EAI_NODATA||code===lazyUv().UV_EAI_NONAME){
425438
code='ENOTFOUND';// Fabricated error name.
426439
}else{
427440
code=lazyInternalUtil().getSystemErrorName(code);

‎lib/internal/util.js‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ const {
1616
isNativeError
1717
}=internalBinding('types');
1818

19-
const{ errmap }=internalBinding('uv');
20-
2119
constnoCrypto=!process.versions.openssl;
2220

2321
constexperimentalWarnings=newSet();
@@ -250,8 +248,19 @@ function getConstructorOf(obj) {
250248
returnnull;
251249
}
252250

251+
letuvBinding;
252+
functionlazyErrmapGet(name){
253+
if(!uvBinding){
254+
uvBinding=internalBinding('uv');
255+
}
256+
if(!uvBinding.errmap){
257+
uvBinding.errmap=uvBinding.getErrorMap();
258+
}
259+
returnuvBinding.errmap.get(name);
260+
}
261+
253262
functiongetSystemErrorName(err){
254-
constentry=errmap.get(err);
263+
constentry=lazyErrmapGet(err);
255264
returnentry ? entry[0] : `Unknown system error ${err}`;
256265
}
257266

‎src/uv.cc‎

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,39 @@
2525
#include"env-inl.h"
2626

2727
namespacenode {
28+
29+
namespaceper_process {
30+
structUVError {
31+
int value;
32+
constchar* name;
33+
constchar* message;
34+
};
35+
36+
// We only expand the macro once here to reduce the amount of code
37+
// generated.
38+
staticconststructUVError uv_errors_map[] = {
39+
#defineV(name, message) {UV_##name, #name, message},
40+
UV_ERRNO_MAP(V)
41+
#undef V
42+
};
43+
} // namespace per_process
44+
2845
namespace {
2946

3047
using v8::Array;
3148
using v8::Context;
49+
using v8::DontDelete;
3250
using v8::FunctionCallbackInfo;
3351
using v8::Integer;
3452
using v8::Isolate;
3553
using v8::Local;
3654
using v8::Map;
3755
using v8::Object;
56+
using v8::PropertyAttribute;
57+
using v8::ReadOnly;
3858
using v8::String;
3959
using v8::Value;
4060

41-
4261
voidErrName(const FunctionCallbackInfo<Value>& args) {
4362
Environment* env = Environment::GetCurrent(args);
4463
if (env->options()->pending_deprecation && env->EmitErrNameWarning()) {
@@ -57,6 +76,29 @@ void ErrName(const FunctionCallbackInfo<Value>& args) {
5776
args.GetReturnValue().Set(OneByteString(env->isolate(), name));
5877
}
5978

79+
voidGetErrMap(const FunctionCallbackInfo<Value>& args) {
80+
Environment* env = Environment::GetCurrent(args);
81+
Isolate* isolate = env->isolate();
82+
Local<Context> context = env->context();
83+
84+
Local<Map> err_map = Map::New(isolate);
85+
86+
size_t errors_len = arraysize(per_process::uv_errors_map);
87+
for (size_t i = 0; i < errors_len; ++i) {
88+
constauto& error = per_process::uv_errors_map[i];
89+
Local<Value> arr[] = {OneByteString(isolate, error.name),
90+
OneByteString(isolate, error.message)};
91+
if (err_map
92+
->Set(context,
93+
Integer::New(isolate, error.value),
94+
Array::New(isolate, arr, arraysize(arr)))
95+
.IsEmpty()) {
96+
return;
97+
}
98+
}
99+
100+
args.GetReturnValue().Set(err_map);
101+
}
60102

61103
voidInitialize(Local<Object> target,
62104
Local<Value> unused,
@@ -70,28 +112,21 @@ void Initialize(Local<Object> target,
70112
->GetFunction(env->context())
71113
.ToLocalChecked()).FromJust();
72114

73-
#defineV(name, _) NODE_DEFINE_CONSTANT(target, UV_##name);
74-
UV_ERRNO_MAP(V)
75-
#undef V
76-
77-
Local<Map> err_map = Map::New(isolate);
78-
79-
#defineV(name, msg) do { \
80-
Local<Value> arr[] = { \
81-
OneByteString(isolate, #name), \
82-
OneByteString(isolate, msg) \
83-
}; \
84-
if (err_map->Set(context, \
85-
Integer::New(isolate, UV_##name), \
86-
Array::New(isolate, arr, arraysize(arr))).IsEmpty()) { \
87-
return; \
88-
} \
89-
} while (0);
90-
UV_ERRNO_MAP(V)
91-
#undef V
115+
// TODO(joyeecheung): This should be deprecated in user land in favor of
116+
// `util.getSystemErrorName(err)`.
117+
PropertyAttribute attributes =
118+
static_cast<PropertyAttribute>(ReadOnly | DontDelete);
119+
size_t errors_len = arraysize(per_process::uv_errors_map);
120+
const std::string prefix = "UV_";
121+
for (size_t i = 0; i < errors_len; ++i) {
122+
constauto& error = per_process::uv_errors_map[i];
123+
const std::string prefixed_name = prefix + error.name;
124+
Local<String> name = OneByteString(isolate, prefixed_name.c_str());
125+
Local<Integer> value = Integer::New(isolate, error.value);
126+
target->DefineOwnProperty(context, name, value, attributes).FromJust();
127+
}
92128

93-
target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "errmap"),
94-
err_map).FromJust();
129+
env->SetMethod(target, "getErrorMap", GetErrMap);
95130
}
96131

97132
} // anonymous namespace

0 commit comments

Comments
 (0)