10
10
// benchmark all changes made in performance-sensitive areas of the codebase.
11
11
// See: https://github.com/nodejs/node/pull/38248
12
12
13
+ const {
14
+ defineProperty : ReflectDefineProperty ,
15
+ getOwnPropertyDescriptor : ReflectGetOwnPropertyDescriptor ,
16
+ ownKeys : ReflectOwnKeys ,
17
+ } = Reflect ;
18
+
13
19
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
14
20
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
15
21
// and `Function.prototype.call` after it may have been mutated by users.
16
22
const { bind, call } = Function . prototype ;
17
23
const uncurryThis = bind . bind ( call ) ;
18
24
primordials . uncurryThis = uncurryThis ;
19
25
20
- function copyProps ( src , dest ) {
21
- for ( const key of Reflect . ownKeys ( src ) ) {
22
- if ( ! Reflect . getOwnPropertyDescriptor ( dest , key ) ) {
23
- Reflect . defineProperty (
24
- dest ,
25
- key ,
26
- Reflect . getOwnPropertyDescriptor ( src , key ) ) ;
27
- }
28
- }
29
- }
30
-
31
26
function getNewKey ( key ) {
32
27
return typeof key === 'symbol' ?
33
28
`Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
34
29
`${ key [ 0 ] . toUpperCase ( ) } ${ key . slice ( 1 ) } ` ;
35
30
}
36
31
37
32
function copyAccessor ( dest , prefix , key , { enumerable, get, set } ) {
38
- Reflect . defineProperty ( dest , `${ prefix } Get${ key } ` , {
33
+ ReflectDefineProperty ( dest , `${ prefix } Get${ key } ` , {
39
34
value : uncurryThis ( get ) ,
40
35
enumerable
41
36
} ) ;
42
37
if ( set !== undefined ) {
43
- Reflect . defineProperty ( dest , `${ prefix } Set${ key } ` , {
38
+ ReflectDefineProperty ( dest , `${ prefix } Set${ key } ` , {
44
39
value : uncurryThis ( set ) ,
45
40
enumerable
46
41
} ) ;
47
42
}
48
43
}
49
44
50
45
function copyPropsRenamed ( src , dest , prefix ) {
51
- for ( const key of Reflect . ownKeys ( src ) ) {
46
+ for ( const key of ReflectOwnKeys ( src ) ) {
52
47
const newKey = getNewKey ( key ) ;
53
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
48
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
54
49
if ( 'get' in desc ) {
55
50
copyAccessor ( dest , prefix , newKey , desc ) ;
56
51
} else {
57
- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
52
+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
58
53
}
59
54
}
60
55
}
61
56
62
57
function copyPropsRenamedBound ( src , dest , prefix ) {
63
- for ( const key of Reflect . ownKeys ( src ) ) {
58
+ for ( const key of ReflectOwnKeys ( src ) ) {
64
59
const newKey = getNewKey ( key ) ;
65
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
60
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
66
61
if ( 'get' in desc ) {
67
62
copyAccessor ( dest , prefix , newKey , desc ) ;
68
63
} else {
69
64
if ( typeof desc . value === 'function' ) {
70
65
desc . value = desc . value . bind ( src ) ;
71
66
}
72
- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
67
+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
73
68
}
74
69
}
75
70
}
76
71
77
72
function copyPrototype ( src , dest , prefix ) {
78
- for ( const key of Reflect . ownKeys ( src ) ) {
73
+ for ( const key of ReflectOwnKeys ( src ) ) {
79
74
const newKey = getNewKey ( key ) ;
80
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
75
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
81
76
if ( 'get' in desc ) {
82
77
copyAccessor ( dest , prefix , newKey , desc ) ;
83
78
} else {
84
79
if ( typeof desc . value === 'function' ) {
85
80
desc . value = uncurryThis ( desc . value ) ;
86
81
}
87
- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
82
+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
88
83
}
89
84
}
90
85
}
91
86
92
- const createSafeIterator = ( factory , next ) => {
93
- class SafeIterator {
94
- constructor ( iterable ) {
95
- this . _iterator = factory ( iterable ) ;
96
- }
97
- next ( ) {
98
- return next ( this . _iterator ) ;
99
- }
100
- [ Symbol . iterator ] ( ) {
101
- return this ;
102
- }
103
- }
104
- Object . setPrototypeOf ( SafeIterator . prototype , null ) ;
105
- Object . freeze ( SafeIterator . prototype ) ;
106
- Object . freeze ( SafeIterator ) ;
107
- return SafeIterator ;
108
- } ;
109
-
110
- function makeSafe ( unsafe , safe ) {
111
- if ( Symbol . iterator in unsafe . prototype ) {
112
- const dummy = new unsafe ( ) ;
113
- let next ; // We can reuse the same `next` method.
114
-
115
- for ( const key of Reflect . ownKeys ( unsafe . prototype ) ) {
116
- if ( ! Reflect . getOwnPropertyDescriptor ( safe . prototype , key ) ) {
117
- const desc = Reflect . getOwnPropertyDescriptor ( unsafe . prototype , key ) ;
118
- if (
119
- typeof desc . value === 'function' &&
120
- desc . value . length === 0 &&
121
- Symbol . iterator in ( desc . value . call ( dummy ) ?? { } )
122
- ) {
123
- const createIterator = uncurryThis ( desc . value ) ;
124
- if ( next == null ) next = uncurryThis ( createIterator ( dummy ) . next ) ;
125
- const SafeIterator = createSafeIterator ( createIterator , next ) ;
126
- desc . value = function ( ) {
127
- return new SafeIterator ( this ) ;
128
- } ;
129
- }
130
- Reflect . defineProperty ( safe . prototype , key , desc ) ;
131
- }
132
- }
133
- } else {
134
- copyProps ( unsafe . prototype , safe . prototype ) ;
135
- }
136
- copyProps ( unsafe , safe ) ;
137
-
138
- Object . setPrototypeOf ( safe . prototype , null ) ;
139
- Object . freeze ( safe . prototype ) ;
140
- Object . freeze ( safe ) ;
141
- return safe ;
142
- }
143
- primordials . makeSafe = makeSafe ;
144
-
145
- // Subclass the constructors because we need to use their prototype
146
- // methods later.
147
- // Defining the `constructor` is necessary here to avoid the default
148
- // constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.
149
- primordials . SafeMap = makeSafe (
150
- Map ,
151
- class SafeMap extends Map {
152
- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
153
- }
154
- ) ;
155
- primordials . SafeWeakMap = makeSafe (
156
- WeakMap ,
157
- class SafeWeakMap extends WeakMap {
158
- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
159
- }
160
- ) ;
161
- primordials . SafeSet = makeSafe (
162
- Set ,
163
- class SafeSet extends Set {
164
- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
165
- }
166
- ) ;
167
- primordials . SafeWeakSet = makeSafe (
168
- WeakSet ,
169
- class SafeWeakSet extends WeakSet {
170
- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
171
- }
172
- ) ;
173
-
174
87
// Create copies of configurable value properties of the global object
175
88
[
176
89
'Proxy' ,
@@ -277,6 +190,41 @@ primordials.SafeWeakSet = makeSafe(
277
190
copyPrototype ( original . prototype , primordials , `${ name } Prototype` ) ;
278
191
} ) ;
279
192
193
+ /* eslint-enable node-core/prefer-primordials */
194
+
195
+ const {
196
+ ArrayPrototypeForEach,
197
+ FunctionPrototypeCall,
198
+ Map,
199
+ ObjectFreeze,
200
+ ObjectSetPrototypeOf,
201
+ Set,
202
+ SymbolIterator,
203
+ WeakMap,
204
+ WeakSet,
205
+ } = primordials ;
206
+
207
+ // Because these functions are used by `makeSafe`, which is exposed
208
+ // on the `primordials` object, it's important to use const references
209
+ // to the primordials that they use:
210
+ const createSafeIterator = ( factory , next ) => {
211
+ class SafeIterator {
212
+ constructor ( iterable ) {
213
+ this . _iterator = factory ( iterable ) ;
214
+ }
215
+ next ( ) {
216
+ return next ( this . _iterator ) ;
217
+ }
218
+ [ SymbolIterator ] ( ) {
219
+ return this ;
220
+ }
221
+ }
222
+ ObjectSetPrototypeOf ( SafeIterator . prototype , null ) ;
223
+ ObjectFreeze ( SafeIterator . prototype ) ;
224
+ ObjectFreeze ( SafeIterator ) ;
225
+ return SafeIterator ;
226
+ } ;
227
+
280
228
primordials . SafeArrayIterator = createSafeIterator (
281
229
primordials . ArrayPrototypeSymbolIterator ,
282
230
primordials . ArrayIteratorPrototypeNext
@@ -286,5 +234,80 @@ primordials.SafeStringIterator = createSafeIterator(
286
234
primordials . StringIteratorPrototypeNext
287
235
) ;
288
236
289
- Object . setPrototypeOf ( primordials , null ) ;
290
- Object . freeze ( primordials ) ;
237
+ const copyProps = ( src , dest ) => {
238
+ ArrayPrototypeForEach ( ReflectOwnKeys ( src ) , ( key ) => {
239
+ if ( ! ReflectGetOwnPropertyDescriptor ( dest , key ) ) {
240
+ ReflectDefineProperty (
241
+ dest ,
242
+ key ,
243
+ ReflectGetOwnPropertyDescriptor ( src , key ) ) ;
244
+ }
245
+ } ) ;
246
+ } ;
247
+
248
+ const makeSafe = ( unsafe , safe ) => {
249
+ if ( SymbolIterator in unsafe . prototype ) {
250
+ const dummy = new unsafe ( ) ;
251
+ let next ; // We can reuse the same `next` method.
252
+
253
+ ArrayPrototypeForEach ( ReflectOwnKeys ( unsafe . prototype ) , ( key ) => {
254
+ if ( ! ReflectGetOwnPropertyDescriptor ( safe . prototype , key ) ) {
255
+ const desc = ReflectGetOwnPropertyDescriptor ( unsafe . prototype , key ) ;
256
+ if (
257
+ typeof desc . value === 'function' &&
258
+ desc . value . length === 0 &&
259
+ SymbolIterator in ( FunctionPrototypeCall ( desc . value , dummy ) ?? { } )
260
+ ) {
261
+ const createIterator = uncurryThis ( desc . value ) ;
262
+ next = next ?? uncurryThis ( createIterator ( dummy ) . next ) ;
263
+ const SafeIterator = createSafeIterator ( createIterator , next ) ;
264
+ desc . value = function ( ) {
265
+ return new SafeIterator ( this ) ;
266
+ } ;
267
+ }
268
+ ReflectDefineProperty ( safe . prototype , key , desc ) ;
269
+ }
270
+ } ) ;
271
+ } else {
272
+ copyProps ( unsafe . prototype , safe . prototype ) ;
273
+ }
274
+ copyProps ( unsafe , safe ) ;
275
+
276
+ ObjectSetPrototypeOf ( safe . prototype , null ) ;
277
+ ObjectFreeze ( safe . prototype ) ;
278
+ ObjectFreeze ( safe ) ;
279
+ return safe ;
280
+ } ;
281
+ primordials . makeSafe = makeSafe ;
282
+
283
+ // Subclass the constructors because we need to use their prototype
284
+ // methods later.
285
+ // Defining the `constructor` is necessary here to avoid the default
286
+ // constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.
287
+ primordials . SafeMap = makeSafe (
288
+ Map ,
289
+ class SafeMap extends Map {
290
+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
291
+ }
292
+ ) ;
293
+ primordials . SafeWeakMap = makeSafe (
294
+ WeakMap ,
295
+ class SafeWeakMap extends WeakMap {
296
+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
297
+ }
298
+ ) ;
299
+ primordials . SafeSet = makeSafe (
300
+ Set ,
301
+ class SafeSet extends Set {
302
+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
303
+ }
304
+ ) ;
305
+ primordials . SafeWeakSet = makeSafe (
306
+ WeakSet ,
307
+ class SafeWeakSet extends WeakSet {
308
+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
309
+ }
310
+ ) ;
311
+
312
+ ObjectSetPrototypeOf ( primordials , null ) ;
313
+ ObjectFreeze ( primordials ) ;
0 commit comments