66// so that Node.js's builtin modules do not need to later look these up from
77// the global proxy, which can be mutated by users.
88
9+ const {
10+ defineProperty : ReflectDefineProperty ,
11+ getOwnPropertyDescriptor : ReflectGetOwnPropertyDescriptor ,
12+ ownKeys : ReflectOwnKeys ,
13+ } = Reflect ;
14+
915// TODO(joyeecheung): we can restrict access to these globals in builtin
1016// modules through the JS linter, for example: ban access such as `Object`
1117// (which falls back to a lookup in the global proxy) in favor of
@@ -19,159 +25,66 @@ const { bind, call } = Function.prototype;
1925const uncurryThis = bind . bind ( call ) ;
2026primordials . uncurryThis = uncurryThis ;
2127
22- function copyProps ( src , dest ) {
23- for ( const key of Reflect . ownKeys ( src ) ) {
24- if ( ! Reflect . getOwnPropertyDescriptor ( dest , key ) ) {
25- Reflect . defineProperty (
26- dest ,
27- key ,
28- Reflect . getOwnPropertyDescriptor ( src , key ) ) ;
29- }
30- }
31- }
32-
3328function getNewKey ( key ) {
3429 return typeof key === 'symbol' ?
3530 `Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
3631 `${ key [ 0 ] . toUpperCase ( ) } ${ key . slice ( 1 ) } ` ;
3732}
3833
3934function copyAccessor ( dest , prefix , key , { enumerable, get, set } ) {
40- Reflect . defineProperty ( dest , `${ prefix } Get${ key } ` , {
35+ ReflectDefineProperty ( dest , `${ prefix } Get${ key } ` , {
4136 value : uncurryThis ( get ) ,
4237 enumerable
4338 } ) ;
4439 if ( set !== undefined ) {
45- Reflect . defineProperty ( dest , `${ prefix } Set${ key } ` , {
40+ ReflectDefineProperty ( dest , `${ prefix } Set${ key } ` , {
4641 value : uncurryThis ( set ) ,
4742 enumerable
4843 } ) ;
4944 }
5045}
5146
5247function copyPropsRenamed ( src , dest , prefix ) {
53- for ( const key of Reflect . ownKeys ( src ) ) {
48+ for ( const key of ReflectOwnKeys ( src ) ) {
5449 const newKey = getNewKey ( key ) ;
55- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
50+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
5651 if ( 'get' in desc ) {
5752 copyAccessor ( dest , prefix , newKey , desc ) ;
5853 } else {
59- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
54+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
6055 }
6156 }
6257}
6358
6459function copyPropsRenamedBound ( src , dest , prefix ) {
65- for ( const key of Reflect . ownKeys ( src ) ) {
60+ for ( const key of ReflectOwnKeys ( src ) ) {
6661 const newKey = getNewKey ( key ) ;
67- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
62+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
6863 if ( 'get' in desc ) {
6964 copyAccessor ( dest , prefix , newKey , desc ) ;
7065 } else {
7166 if ( typeof desc . value === 'function' ) {
7267 desc . value = desc . value . bind ( src ) ;
7368 }
74- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
69+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
7570 }
7671 }
7772}
7873
7974function copyPrototype ( src , dest , prefix ) {
80- for ( const key of Reflect . ownKeys ( src ) ) {
75+ for ( const key of ReflectOwnKeys ( src ) ) {
8176 const newKey = getNewKey ( key ) ;
82- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
77+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
8378 if ( 'get' in desc ) {
8479 copyAccessor ( dest , prefix , newKey , desc ) ;
8580 } else {
8681 if ( typeof desc . value === 'function' ) {
8782 desc . value = uncurryThis ( desc . value ) ;
8883 }
89- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
90- }
91- }
92- }
93-
94- const createSafeIterator = ( factory , next ) => {
95- class SafeIterator {
96- constructor ( iterable ) {
97- this . _iterator = factory ( iterable ) ;
98- }
99- next ( ) {
100- return next ( this . _iterator ) ;
101- }
102- [ Symbol . iterator ] ( ) {
103- return this ;
104- }
105- }
106- Object . setPrototypeOf ( SafeIterator . prototype , null ) ;
107- Object . freeze ( SafeIterator . prototype ) ;
108- Object . freeze ( SafeIterator ) ;
109- return SafeIterator ;
110- } ;
111-
112- function makeSafe ( unsafe , safe ) {
113- if ( Symbol . iterator in unsafe . prototype ) {
114- const dummy = new unsafe ( ) ;
115- let next ; // We can reuse the same `next` method.
116-
117- for ( const key of Reflect . ownKeys ( unsafe . prototype ) ) {
118- if ( ! Reflect . getOwnPropertyDescriptor ( safe . prototype , key ) ) {
119- const desc = Reflect . getOwnPropertyDescriptor ( unsafe . prototype , key ) ;
120- if (
121- typeof desc . value === 'function' &&
122- desc . value . length === 0 &&
123- Symbol . iterator in ( desc . value . call ( dummy ) ?? { } )
124- ) {
125- const createIterator = uncurryThis ( desc . value ) ;
126- next ??= uncurryThis ( createIterator ( dummy ) . next ) ;
127- const SafeIterator = createSafeIterator ( createIterator , next ) ;
128- desc . value = function ( ) {
129- return new SafeIterator ( this ) ;
130- } ;
131- }
132- Reflect . defineProperty ( safe . prototype , key , desc ) ;
133- }
84+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
13485 }
135- } else {
136- copyProps ( unsafe . prototype , safe . prototype ) ;
13786 }
138- copyProps ( unsafe , safe ) ;
139-
140- Object . setPrototypeOf ( safe . prototype , null ) ;
141- Object . freeze ( safe . prototype ) ;
142- Object . freeze ( safe ) ;
143- return safe ;
14487}
145- primordials . makeSafe = makeSafe ;
146-
147- // Subclass the constructors because we need to use their prototype
148- // methods later.
149- // Defining the `constructor` is necessary here to avoid the default
150- // constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.
151- primordials . SafeMap = makeSafe (
152- Map ,
153- class SafeMap extends Map {
154- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
155- }
156- ) ;
157- primordials . SafeWeakMap = makeSafe (
158- WeakMap ,
159- class SafeWeakMap extends WeakMap {
160- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
161- }
162- ) ;
163- primordials . SafeSet = makeSafe (
164- Set ,
165- class SafeSet extends Set {
166- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
167- }
168- ) ;
169- primordials . SafeWeakSet = makeSafe (
170- WeakSet ,
171- class SafeWeakSet extends WeakSet {
172- constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
173- }
174- ) ;
17588
17689// Create copies of the namespace objects
17790[
@@ -256,6 +169,41 @@ primordials.SafeWeakSet = makeSafe(
256169 copyPrototype ( original . prototype , primordials , `${ name } Prototype` ) ;
257170} ) ;
258171
172+ /* eslint-enable node-core/prefer-primordials */
173+
174+ const {
175+ ArrayPrototypeForEach,
176+ FunctionPrototypeCall,
177+ Map,
178+ ObjectFreeze,
179+ ObjectSetPrototypeOf,
180+ Set,
181+ SymbolIterator,
182+ WeakMap,
183+ WeakSet,
184+ } = primordials ;
185+
186+ // Because these functions are used by `makeSafe`, which is exposed
187+ // on the `primordials` object, it's important to use const references
188+ // to the primordials that they use:
189+ const createSafeIterator = ( factory , next ) => {
190+ class SafeIterator {
191+ constructor ( iterable ) {
192+ this . _iterator = factory ( iterable ) ;
193+ }
194+ next ( ) {
195+ return next ( this . _iterator ) ;
196+ }
197+ [ SymbolIterator ] ( ) {
198+ return this ;
199+ }
200+ }
201+ ObjectSetPrototypeOf ( SafeIterator . prototype , null ) ;
202+ ObjectFreeze ( SafeIterator . prototype ) ;
203+ ObjectFreeze ( SafeIterator ) ;
204+ return SafeIterator ;
205+ } ;
206+
259207primordials . SafeArrayIterator = createSafeIterator (
260208 primordials . ArrayPrototypeSymbolIterator ,
261209 primordials . ArrayIteratorPrototypeNext
@@ -265,5 +213,80 @@ primordials.SafeStringIterator = createSafeIterator(
265213 primordials . StringIteratorPrototypeNext
266214) ;
267215
268- Object . setPrototypeOf ( primordials , null ) ;
269- Object . freeze ( primordials ) ;
216+ const copyProps = ( src , dest ) => {
217+ ArrayPrototypeForEach ( ReflectOwnKeys ( src ) , ( key ) => {
218+ if ( ! ReflectGetOwnPropertyDescriptor ( dest , key ) ) {
219+ ReflectDefineProperty (
220+ dest ,
221+ key ,
222+ ReflectGetOwnPropertyDescriptor ( src , key ) ) ;
223+ }
224+ } ) ;
225+ } ;
226+
227+ const makeSafe = ( unsafe , safe ) => {
228+ if ( SymbolIterator in unsafe . prototype ) {
229+ const dummy = new unsafe ( ) ;
230+ let next ; // We can reuse the same `next` method.
231+
232+ ArrayPrototypeForEach ( ReflectOwnKeys ( unsafe . prototype ) , ( key ) => {
233+ if ( ! ReflectGetOwnPropertyDescriptor ( safe . prototype , key ) ) {
234+ const desc = ReflectGetOwnPropertyDescriptor ( unsafe . prototype , key ) ;
235+ if (
236+ typeof desc . value === 'function' &&
237+ desc . value . length === 0 &&
238+ SymbolIterator in ( FunctionPrototypeCall ( desc . value , dummy ) ?? { } )
239+ ) {
240+ const createIterator = uncurryThis ( desc . value ) ;
241+ next ??= uncurryThis ( createIterator ( dummy ) . next ) ;
242+ const SafeIterator = createSafeIterator ( createIterator , next ) ;
243+ desc . value = function ( ) {
244+ return new SafeIterator ( this ) ;
245+ } ;
246+ }
247+ ReflectDefineProperty ( safe . prototype , key , desc ) ;
248+ }
249+ } ) ;
250+ } else {
251+ copyProps ( unsafe . prototype , safe . prototype ) ;
252+ }
253+ copyProps ( unsafe , safe ) ;
254+
255+ ObjectSetPrototypeOf ( safe . prototype , null ) ;
256+ ObjectFreeze ( safe . prototype ) ;
257+ ObjectFreeze ( safe ) ;
258+ return safe ;
259+ } ;
260+ primordials . makeSafe = makeSafe ;
261+
262+ // Subclass the constructors because we need to use their prototype
263+ // methods later.
264+ // Defining the `constructor` is necessary here to avoid the default
265+ // constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.
266+ primordials . SafeMap = makeSafe (
267+ Map ,
268+ class SafeMap extends Map {
269+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
270+ }
271+ ) ;
272+ primordials . SafeWeakMap = makeSafe (
273+ WeakMap ,
274+ class SafeWeakMap extends WeakMap {
275+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
276+ }
277+ ) ;
278+ primordials . SafeSet = makeSafe (
279+ Set ,
280+ class SafeSet extends Set {
281+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
282+ }
283+ ) ;
284+ primordials . SafeWeakSet = makeSafe (
285+ WeakSet ,
286+ class SafeWeakSet extends WeakSet {
287+ constructor ( i ) { super ( i ) ; } // eslint-disable-line no-useless-constructor
288+ }
289+ ) ;
290+
291+ ObjectSetPrototypeOf ( primordials , null ) ;
292+ ObjectFreeze ( primordials ) ;
0 commit comments