Skip to content

Commit 112cc7c

Browse files
committed
lib: use safe methods from primordials
This changes the primordials to expose built-in prototypes with their methods already uncurried. The uncurryThis function is therefore moved to the primordials. All uses of uncurryThis on built-ins are changed to import the relevant prototypes from primordials. All uses of Function.call.bind are also changed to use primordials. PR-URL: #27096 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 969bd1e commit 112cc7c

File tree

20 files changed

+206
-189
lines changed

20 files changed

+206
-189
lines changed

‎lib/_http_outgoing.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
'use strict';
2323

24+
const{ ObjectPrototype }=primordials;
25+
2426
constassert=require('internal/assert');
2527
constStream=require('stream');
2628
constinternalUtil=require('internal/util');
@@ -53,8 +55,6 @@ const{CRLF, debug } = common;
5355

5456
constkIsCorked=Symbol('isCorked');
5557

56-
consthasOwnProperty=Function.call.bind(Object.prototype.hasOwnProperty);
57-
5858
constRE_CONN_CLOSE=/(?:^|\W)close(?:$|\W)/i;
5959
constRE_TE_CHUNKED=common.chunkExpression;
6060

@@ -310,7 +310,7 @@ function _storeHeader(firstLine, headers){
310310
}
311311
}else{
312312
for(constkeyinheaders){
313-
if(hasOwnProperty(headers,key)){
313+
if(ObjectPrototype.hasOwnProperty(headers,key)){
314314
processHeader(this,state,key,headers[key],true);
315315
}
316316
}

‎lib/internal/async_hooks.js‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const{ Reflect }=primordials;
3+
const{FunctionPrototype,Reflect }=primordials;
44

55
const{
66
ERR_ASYNC_TYPE,
@@ -77,8 +77,6 @@ const{kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve,
7777
kCheck, kExecutionAsyncId, kAsyncIdCounter, kTriggerAsyncId,
7878
kDefaultTriggerAsyncId, kStackLength }=async_wrap.constants;
7979

80-
constFunctionBind=Function.call.bind(Function.prototype.bind);
81-
8280
// Used in AsyncHook and AsyncResource.
8381
constasync_id_symbol=Symbol('asyncId');
8482
consttrigger_async_id_symbol=Symbol('triggerAsyncId');
@@ -181,7 +179,7 @@ function emitHook(symbol, asyncId){
181179
}
182180

183181
functionemitHookFactory(symbol,name){
184-
constfn=FunctionBind(emitHook,undefined,symbol);
182+
constfn=FunctionPrototype.bind(emitHook,undefined,symbol);
185183

186184
// Set the name property of the function as it looks good in the stack trace.
187185
Object.defineProperty(fn,'name',{

‎lib/internal/bootstrap/loaders.js‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ NativeModule.prototype.compileForPublicLoader = function(needToProxify){
225225
};
226226

227227
constgetOwn=(target,property,receiver)=>{
228-
returnReflect.apply(ObjectPrototype.hasOwnProperty,target,[property]) ?
228+
returnObjectPrototype.hasOwnProperty(target,property) ?
229229
Reflect.get(target,property,receiver) :
230230
undefined;
231231
};
@@ -239,8 +239,7 @@ NativeModule.prototype.proxifyExports = function(){
239239

240240
constupdate=(property,value)=>{
241241
if(this.reflect!==undefined&&
242-
Reflect.apply(ObjectPrototype.hasOwnProperty,
243-
this.reflect.exports,[property]))
242+
ObjectPrototype.hasOwnProperty(this.reflect.exports,property))
244243
this.reflect.exports[property].set(value);
245244
};
246245

@@ -254,7 +253,7 @@ NativeModule.prototype.proxifyExports = function(){
254253
!Reflect.has(handler,'get')){
255254
handler.get=(target,prop,receiver)=>{
256255
constvalue=Reflect.get(target,prop,receiver);
257-
if(Reflect.apply(ObjectPrototype.hasOwnProperty,target,[prop]))
256+
if(ObjectPrototype.hasOwnProperty(target,prop))
258257
update(prop,value);
259258
returnvalue;
260259
};

‎lib/internal/bootstrap/primordials.js‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212
// `primordials.Object` where `primordials` is a lexical variable passed
1313
// by the native module compiler.
1414

15+
constReflectApply=Reflect.apply;
16+
17+
// This function is borrowed from the function with the same name on V8 Extras'
18+
// `utils` object. V8 implements Reflect.apply very efficiently in conjunction
19+
// with the spread syntax, such that no additional special case is needed for
20+
// function calls w/o arguments.
21+
// Refs: https://github.com/v8/v8/blob/d6ead37d265d7215cf9c5f768f279e21bd170212/src/js/prologue.js#L152-L156
22+
functionuncurryThis(func){
23+
return(thisArg, ...args)=>ReflectApply(func,thisArg,args);
24+
}
25+
26+
primordials.uncurryThis=uncurryThis;
27+
1528
functioncopyProps(src,dest){
1629
for(constkeyofReflect.ownKeys(src)){
1730
if(!Reflect.getOwnPropertyDescriptor(dest,key)){
@@ -23,6 +36,18 @@ function copyProps(src, dest){
2336
}
2437
}
2538

39+
functioncopyPrototype(src,dest){
40+
for(constkeyofReflect.ownKeys(src)){
41+
if(!Reflect.getOwnPropertyDescriptor(dest,key)){
42+
constdesc=Reflect.getOwnPropertyDescriptor(src,key);
43+
if(typeofdesc.value==='function'){
44+
desc.value=uncurryThis(desc.value);
45+
}
46+
Reflect.defineProperty(dest,key,desc);
47+
}
48+
}
49+
}
50+
2651
functionmakeSafe(unsafe,safe){
2752
copyProps(unsafe.prototype,safe.prototype);
2853
copyProps(unsafe,safe);
@@ -64,17 +89,23 @@ primordials.SafePromise = makeSafe(
6489
// Create copies of intrinsic objects
6590
[
6691
'Array',
92+
'BigInt',
93+
'Boolean',
6794
'Date',
95+
'Error',
6896
'Function',
97+
'Map',
98+
'Number',
6999
'Object',
70100
'RegExp',
101+
'Set',
71102
'String',
72103
'Symbol',
73104
].forEach((name)=>{
74105
consttarget=primordials[name]=Object.create(null);
75106
copyProps(global[name],target);
76107
constproto=primordials[name+'Prototype']=Object.create(null);
77-
copyProps(global[name].prototype,proto);
108+
copyPrototype(global[name].prototype,proto);
78109
});
79110

80111
Object.setPrototypeOf(primordials,null);

‎lib/internal/cli_table.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
'use strict';
22

3-
const{ Math }=primordials;
3+
const{ Math, ObjectPrototype}=primordials;
44

55
const{ Buffer }=require('buffer');
66
const{ removeColors }=require('internal/util');
7-
constHasOwnProperty=Function.call.bind(Object.prototype.hasOwnProperty);
87

98
// The use of Unicode characters below is the only non-comment use of non-ASCII
109
// Unicode characters in Node.js built-in modules. If they are ever removed or
@@ -61,7 +60,8 @@ const table = (head, columns) =>{
6160
for(varj=0;j<longestColumn;j++){
6261
if(rows[j]===undefined)
6362
rows[j]=[];
64-
constvalue=rows[j][i]=HasOwnProperty(column,j) ? column[j] : '';
63+
constvalue=rows[j][i]=
64+
ObjectPrototype.hasOwnProperty(column,j) ? column[j] : '';
6565
constwidth=columnWidths[i]||0;
6666
constcounted=countSymbols(value);
6767
columnWidths[i]=Math.max(width,counted);

‎lib/internal/console/constructor.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// The Console constructor is not actually used to construct the global
44
// console. It's exported for backwards compatibility.
55

6-
const{ Reflect }=primordials;
6+
const{ObjectPrototype,Reflect }=primordials;
77

88
const{ trace }=internalBinding('trace_events');
99
const{
@@ -36,7 +36,6 @@ const{
3636
keys: ObjectKeys,
3737
values: ObjectValues,
3838
}=Object;
39-
consthasOwnProperty=Function.call.bind(Object.prototype.hasOwnProperty);
4039

4140
const{
4241
isArray: ArrayIsArray,
@@ -493,7 +492,8 @@ const consoleMethods ={
493492
for(constkeyofkeys){
494493
if(map[key]===undefined)
495494
map[key]=[];
496-
if((primitive&&properties)||!hasOwnProperty(item,key))
495+
if((primitive&&properties)||
496+
!ObjectPrototype.hasOwnProperty(item,key))
497497
map[key][i]='';
498498
else
499499
map[key][i]=_inspect(item[key]);

‎lib/internal/error-serdes.js‎

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,17 @@
22

33
constBuffer=require('buffer').Buffer;
44
const{
5-
SafeSet,
5+
ArrayPrototype,
6+
FunctionPrototype,
67
Object,
78
ObjectPrototype,
8-
FunctionPrototype,
9-
ArrayPrototype
9+
SafeSet,
1010
}=primordials;
1111

1212
constkSerializedError=0;
1313
constkSerializedObject=1;
1414
constkInspectedError=2;
1515

16-
constGetPrototypeOf=Object.getPrototypeOf;
17-
constGetOwnPropertyDescriptor=Object.getOwnPropertyDescriptor;
18-
constGetOwnPropertyNames=Object.getOwnPropertyNames;
19-
constDefineProperty=Object.defineProperty;
20-
constAssign=Object.assign;
21-
constObjectPrototypeToString=
22-
FunctionPrototype.call.bind(ObjectPrototype.toString);
23-
constForEach=FunctionPrototype.call.bind(ArrayPrototype.forEach);
24-
constCall=FunctionPrototype.call.bind(FunctionPrototype.call);
25-
2616
consterrors={
2717
Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError
2818
};
@@ -32,17 +22,18 @@ function TryGetAllProperties(object, target = object){
3222
constall=Object.create(null);
3323
if(object===null)
3424
returnall;
35-
Assign(all,TryGetAllProperties(GetPrototypeOf(object),target));
36-
constkeys=GetOwnPropertyNames(object);
37-
ForEach(keys,(key)=>{
25+
Object.assign(all,
26+
TryGetAllProperties(Object.getPrototypeOf(object),target));
27+
constkeys=Object.getOwnPropertyNames(object);
28+
ArrayPrototype.forEach(keys,(key)=>{
3829
letdescriptor;
3930
try{
40-
descriptor=GetOwnPropertyDescriptor(object,key);
31+
descriptor=Object.getOwnPropertyDescriptor(object,key);
4132
}catch{return;}
4233
constgetter=descriptor.get;
4334
if(getter&&key!=='__proto__'){
4435
try{
45-
descriptor.value=Call(getter,target);
36+
descriptor.value=FunctionPrototype.call(getter,target);
4637
}catch{}
4738
}
4839
if('value'indescriptor&&typeofdescriptor.value!=='function'){
@@ -59,10 +50,10 @@ function GetConstructors(object){
5950

6051
for(varcurrent=object;
6152
current!==null;
62-
current=GetPrototypeOf(current)){
63-
constdesc=GetOwnPropertyDescriptor(current,'constructor');
53+
current=Object.getPrototypeOf(current)){
54+
constdesc=Object.getOwnPropertyDescriptor(current,'constructor');
6455
if(desc&&desc.value){
65-
DefineProperty(constructors,constructors.length,{
56+
Object.defineProperty(constructors,constructors.length,{
6657
value: desc.value,enumerable: true
6758
});
6859
}
@@ -72,7 +63,7 @@ function GetConstructors(object){
7263
}
7364

7465
functionGetName(object){
75-
constdesc=GetOwnPropertyDescriptor(object,'name');
66+
constdesc=Object.getOwnPropertyDescriptor(object,'name');
7667
returndesc&&desc.value;
7768
}
7869

@@ -89,7 +80,7 @@ function serializeError(error){
8980
if(!serialize)serialize=require('v8').serialize;
9081
try{
9182
if(typeoferror==='object'&&
92-
ObjectPrototypeToString(error)==='[object Error]'){
83+
ObjectPrototype.toString(error)==='[object Error]'){
9384
constconstructors=GetConstructors(error);
9485
for(vari=0;i<constructors.length;i++){
9586
constname=GetName(constructors[i]);

‎lib/internal/modules/esm/create_dynamic_module.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
'use strict';
22

3+
const{ ArrayPrototype }=primordials;
4+
35
const{ ModuleWrap, callbackMap }=internalBinding('module_wrap');
46
constdebug=require('util').debuglog('esm');
5-
constArrayJoin=Function.call.bind(Array.prototype.join);
6-
constArrayMap=Function.call.bind(Array.prototype.map);
77

88
constcreateDynamicModule=(exports,url='',evaluate)=>{
99
debug('creating ESM facade for %s with exports: %j',url,exports);
10-
constnames=ArrayMap(exports,(name)=>`${name}`);
10+
constnames=ArrayPrototype.map(exports,(name)=>`${name}`);
1111

1212
constsource=`
13-
${ArrayJoin(ArrayMap(names,(name)=>
13+
${ArrayPrototype.join(ArrayPrototype.map(names,(name)=>
1414
`let $${name};
1515
export{$${name} as ${name} };
1616
import.meta.exports.${name} ={

‎lib/internal/modules/esm/loader.js‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const{ FunctionPrototype }=primordials;
4+
35
const{
46
ERR_INVALID_RETURN_PROPERTY,
57
ERR_INVALID_RETURN_PROPERTY_VALUE,
@@ -18,8 +20,6 @@ const createDynamicModule = require(
1820
const{ translators }=require('internal/modules/esm/translators');
1921
const{ ModuleWrap }=internalBinding('module_wrap');
2022

21-
constFunctionBind=Function.call.bind(Function.prototype.bind);
22-
2323
constdebug=require('internal/util/debuglog').debuglog('esm');
2424

2525
const{
@@ -132,9 +132,11 @@ class Loader{
132132
hook({ resolve, dynamicInstantiate }){
133133
// Use .bind() to avoid giving access to the Loader instance when called.
134134
if(resolve!==undefined)
135-
this._resolve=FunctionBind(resolve,null);
136-
if(dynamicInstantiate!==undefined)
137-
this._dynamicInstantiate=FunctionBind(dynamicInstantiate,null);
135+
this._resolve=FunctionPrototype.bind(resolve,null);
136+
if(dynamicInstantiate!==undefined){
137+
this._dynamicInstantiate=
138+
FunctionPrototype.bind(dynamicInstantiate,null);
139+
}
138140
}
139141

140142
asyncgetModuleJob(specifier,parentURL){

‎lib/internal/modules/esm/translators.js‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
'use strict';
22

3+
const{
4+
SafeMap,
5+
StringPrototype,
6+
JSON
7+
}=primordials;
8+
39
const{ NativeModule }=require('internal/bootstrap/loaders');
410
const{ ModuleWrap, callbackMap }=internalBinding('module_wrap');
511
const{
@@ -11,10 +17,6 @@ const internalURLModule = require('internal/url');
1117
constcreateDynamicModule=require(
1218
'internal/modules/esm/create_dynamic_module');
1319
constfs=require('fs');
14-
const{
15-
SafeMap,
16-
JSON
17-
}=primordials;
1820
const{ fileURLToPath,URL}=require('url');
1921
const{ debuglog }=require('internal/util/debuglog');
2022
const{ promisify }=require('internal/util');
@@ -23,7 +25,6 @@ const{
2325
ERR_UNKNOWN_BUILTIN_MODULE
2426
}=require('internal/errors').codes;
2527
constreadFileAsync=promisify(fs.readFile);
26-
constStringReplace=Function.call.bind(String.prototype.replace);
2728
constJsonParse=JSON.parse;
2829

2930
constdebug=debuglog('esm');
@@ -67,7 +68,8 @@ translators.set('commonjs', async function commonjsStrategy(url, isMain){
6768
returncached;
6869
}
6970
constmodule=CJSModule._cache[
70-
isWindows ? StringReplace(pathname,winSepRegEx,'\\') : pathname];
71+
isWindows ? StringPrototype.replace(pathname,winSepRegEx,'\\') : pathname
72+
];
7173
if(module&&module.loaded){
7274
constexports=module.exports;
7375
returncreateDynamicModule(['default'],url,(reflect)=>{
@@ -110,7 +112,7 @@ translators.set('json', async function jsonStrategy(url){
110112
debug(`Loading JSONModule ${url}`);
111113
constpathname=fileURLToPath(url);
112114
constmodulePath=isWindows ?
113-
StringReplace(pathname,winSepRegEx,'\\') : pathname;
115+
StringPrototype.replace(pathname,winSepRegEx,'\\') : pathname;
114116
letmodule=CJSModule._cache[modulePath];
115117
if(module&&module.loaded){
116118
constexports=module.exports;

0 commit comments

Comments
(0)