1010// benchmark all changes made in performance-sensitive areas of the codebase.
1111// See: https://github.com/nodejs/node/pull/38248
1212
13+ const {
14+ defineProperty : ReflectDefineProperty ,
15+ getOwnPropertyDescriptor : ReflectGetOwnPropertyDescriptor ,
16+ ownKeys : ReflectOwnKeys ,
17+ } = Reflect ;
18+
1319// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
1420// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
1521// and `Function.prototype.call` after it may have been mutated by users.
1622const { bind, call } = Function . prototype ;
1723const uncurryThis = bind . bind ( call ) ;
1824primordials . uncurryThis = uncurryThis ;
1925
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-
3126function getNewKey ( key ) {
3227 return typeof key === 'symbol' ?
3328 `Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
3429 `${ key [ 0 ] . toUpperCase ( ) } ${ key . slice ( 1 ) } ` ;
3530}
3631
3732function copyAccessor ( dest , prefix , key , { enumerable, get, set } ) {
38- Reflect . defineProperty ( dest , `${ prefix } Get${ key } ` , {
33+ ReflectDefineProperty ( dest , `${ prefix } Get${ key } ` , {
3934 value : uncurryThis ( get ) ,
4035 enumerable
4136 } ) ;
4237 if ( set !== undefined ) {
43- Reflect . defineProperty ( dest , `${ prefix } Set${ key } ` , {
38+ ReflectDefineProperty ( dest , `${ prefix } Set${ key } ` , {
4439 value : uncurryThis ( set ) ,
4540 enumerable
4641 } ) ;
4742 }
4843}
4944
5045function copyPropsRenamed ( src , dest , prefix ) {
51- for ( const key of Reflect . ownKeys ( src ) ) {
46+ for ( const key of ReflectOwnKeys ( src ) ) {
5247 const newKey = getNewKey ( key ) ;
53- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
48+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
5449 if ( 'get' in desc ) {
5550 copyAccessor ( dest , prefix , newKey , desc ) ;
5651 } else {
57- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
52+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
5853 }
5954 }
6055}
6156
6257function copyPropsRenamedBound ( src , dest , prefix ) {
63- for ( const key of Reflect . ownKeys ( src ) ) {
58+ for ( const key of ReflectOwnKeys ( src ) ) {
6459 const newKey = getNewKey ( key ) ;
65- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
60+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
6661 if ( 'get' in desc ) {
6762 copyAccessor ( dest , prefix , newKey , desc ) ;
6863 } else {
6964 if ( typeof desc . value === 'function' ) {
7065 desc . value = desc . value . bind ( src ) ;
7166 }
72- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
67+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
7368 }
7469 }
7570}
7671
7772function copyPrototype ( src , dest , prefix ) {
78- for ( const key of Reflect . ownKeys ( src ) ) {
73+ for ( const key of ReflectOwnKeys ( src ) ) {
7974 const newKey = getNewKey ( key ) ;
80- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
75+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
8176 if ( 'get' in desc ) {
8277 copyAccessor ( dest , prefix , newKey , desc ) ;
8378 } else {
8479 if ( typeof desc . value === 'function' ) {
8580 desc . value = uncurryThis ( desc . value ) ;
8681 }
87- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
82+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
8883 }
8984 }
9085}
9186
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-
17487// Create copies of configurable value properties of the global object
17588[
17689 'Proxy' ,
@@ -277,6 +190,41 @@ primordials.SafeWeakSet = makeSafe(
277190 copyPrototype ( original . prototype , primordials , `${ name } Prototype` ) ;
278191} ) ;
279192
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+
280228primordials . SafeArrayIterator = createSafeIterator (
281229 primordials . ArrayPrototypeSymbolIterator ,
282230 primordials . ArrayIteratorPrototypeNext
@@ -286,5 +234,80 @@ primordials.SafeStringIterator = createSafeIterator(
286234 primordials . StringIteratorPrototypeNext
287235) ;
288236
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