6
6
// so that Node.js's builtin modules do not need to later look these up from
7
7
// the global proxy, which can be mutated by users.
8
8
9
+ const {
10
+ defineProperty : ReflectDefineProperty ,
11
+ getOwnPropertyDescriptor : ReflectGetOwnPropertyDescriptor ,
12
+ ownKeys : ReflectOwnKeys ,
13
+ } = Reflect ;
14
+
9
15
// TODO(joyeecheung): we can restrict access to these globals in builtin
10
16
// modules through the JS linter, for example: ban access such as `Object`
11
17
// (which falls back to a lookup in the global proxy) in favor of
@@ -19,159 +25,66 @@ const { bind, call } = Function.prototype;
19
25
const uncurryThis = bind . bind ( call ) ;
20
26
primordials . uncurryThis = uncurryThis ;
21
27
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
-
33
28
function getNewKey ( key ) {
34
29
return typeof key === 'symbol' ?
35
30
`Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
36
31
`${ key [ 0 ] . toUpperCase ( ) } ${ key . slice ( 1 ) } ` ;
37
32
}
38
33
39
34
function copyAccessor ( dest , prefix , key , { enumerable, get, set } ) {
40
- Reflect . defineProperty ( dest , `${ prefix } Get${ key } ` , {
35
+ ReflectDefineProperty ( dest , `${ prefix } Get${ key } ` , {
41
36
value : uncurryThis ( get ) ,
42
37
enumerable
43
38
} ) ;
44
39
if ( set !== undefined ) {
45
- Reflect . defineProperty ( dest , `${ prefix } Set${ key } ` , {
40
+ ReflectDefineProperty ( dest , `${ prefix } Set${ key } ` , {
46
41
value : uncurryThis ( set ) ,
47
42
enumerable
48
43
} ) ;
49
44
}
50
45
}
51
46
52
47
function copyPropsRenamed ( src , dest , prefix ) {
53
- for ( const key of Reflect . ownKeys ( src ) ) {
48
+ for ( const key of ReflectOwnKeys ( src ) ) {
54
49
const newKey = getNewKey ( key ) ;
55
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
50
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
56
51
if ( 'get' in desc ) {
57
52
copyAccessor ( dest , prefix , newKey , desc ) ;
58
53
} else {
59
- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
54
+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
60
55
}
61
56
}
62
57
}
63
58
64
59
function copyPropsRenamedBound ( src , dest , prefix ) {
65
- for ( const key of Reflect . ownKeys ( src ) ) {
60
+ for ( const key of ReflectOwnKeys ( src ) ) {
66
61
const newKey = getNewKey ( key ) ;
67
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
62
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
68
63
if ( 'get' in desc ) {
69
64
copyAccessor ( dest , prefix , newKey , desc ) ;
70
65
} else {
71
66
if ( typeof desc . value === 'function' ) {
72
67
desc . value = desc . value . bind ( src ) ;
73
68
}
74
- Reflect . defineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
69
+ ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
75
70
}
76
71
}
77
72
}
78
73
79
74
function copyPrototype ( src , dest , prefix ) {
80
- for ( const key of Reflect . ownKeys ( src ) ) {
75
+ for ( const key of ReflectOwnKeys ( src ) ) {
81
76
const newKey = getNewKey ( key ) ;
82
- const desc = Reflect . getOwnPropertyDescriptor ( src , key ) ;
77
+ const desc = ReflectGetOwnPropertyDescriptor ( src , key ) ;
83
78
if ( 'get' in desc ) {
84
79
copyAccessor ( dest , prefix , newKey , desc ) ;
85
80
} else {
86
81
if ( typeof desc . value === 'function' ) {
87
82
desc . value = uncurryThis ( desc . value ) ;
88
83
}
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 ) ;
134
85
}
135
- } else {
136
- copyProps ( unsafe . prototype , safe . prototype ) ;
137
86
}
138
- copyProps ( unsafe , safe ) ;
139
-
140
- Object . setPrototypeOf ( safe . prototype , null ) ;
141
- Object . freeze ( safe . prototype ) ;
142
- Object . freeze ( safe ) ;
143
- return safe ;
144
87
}
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
- ) ;
175
88
176
89
// Create copies of the namespace objects
177
90
[
@@ -256,6 +169,41 @@ primordials.SafeWeakSet = makeSafe(
256
169
copyPrototype ( original . prototype , primordials , `${ name } Prototype` ) ;
257
170
} ) ;
258
171
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
+
259
207
primordials . SafeArrayIterator = createSafeIterator (
260
208
primordials . ArrayPrototypeSymbolIterator ,
261
209
primordials . ArrayIteratorPrototypeNext
@@ -265,5 +213,80 @@ primordials.SafeStringIterator = createSafeIterator(
265
213
primordials . StringIteratorPrototypeNext
266
214
) ;
267
215
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