@@ -225,6 +225,8 @@ function copyPrototype(src, dest, prefix) {
225
225
copyPrototype ( original . prototype , primordials , `${ name } Prototype` ) ;
226
226
} ) ;
227
227
228
+ const { String } = primordials ;
229
+
228
230
// Create copies of abstract intrinsic objects that are not directly exposed
229
231
// on the global object.
230
232
// Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object
@@ -248,20 +250,208 @@ function copyPrototype(src, dest, prefix) {
248
250
249
251
const {
250
252
ArrayPrototypeForEach,
253
+ Error,
251
254
FinalizationRegistry,
252
255
FunctionPrototypeCall,
253
256
Map,
257
+ MathMax,
258
+ MathMin,
259
+ ObjectCreate,
260
+ ObjectDefineProperties,
254
261
ObjectFreeze,
255
262
ObjectSetPrototypeOf,
256
263
Promise,
257
264
PromisePrototypeThen,
265
+ RegExp,
266
+ RegExpPrototype,
267
+ RegExpPrototypeExec,
268
+ RegExpPrototypeGetUnicode,
269
+ RegExpPrototypeGetSticky,
270
+ RegExpPrototypeSymbolMatch,
271
+ RegExpPrototypeSymbolReplace,
272
+ RegExpPrototypeSymbolSearch,
258
273
Set,
274
+ StringPrototypeReplace,
275
+ StringPrototypeReplaceAll,
276
+ StringPrototypeSlice,
277
+ StringPrototypeSplit,
259
278
SymbolIterator,
279
+ SymbolMatch,
280
+ SymbolMatchAll,
281
+ SymbolReplace,
282
+ SymbolSearch,
283
+ SymbolSplit,
260
284
WeakMap,
261
285
WeakRef,
262
286
WeakSet,
263
287
} = primordials ;
264
288
289
+ {
290
+ const undefinedDesc = ObjectCreate ( null ) ;
291
+ undefinedDesc . value = undefined ;
292
+ const safeTextTransformProperties = {
293
+ [ SymbolMatch ] : undefinedDesc ,
294
+ [ SymbolMatchAll ] : undefinedDesc ,
295
+ [ SymbolReplace ] : undefinedDesc ,
296
+ [ SymbolSearch ] : undefinedDesc ,
297
+ [ SymbolSplit ] : undefinedDesc ,
298
+ exec : undefinedDesc ,
299
+ } ;
300
+ const defineRegExpGetter = ( name ) => {
301
+ safeTextTransformProperties [ name ] =
302
+ ReflectGetOwnPropertyDescriptor ( RegExpPrototype , name ) ;
303
+ } ;
304
+ defineRegExpGetter ( 'flags' ) ;
305
+ defineRegExpGetter ( 'global' ) ;
306
+ defineRegExpGetter ( 'ignoreCase' ) ;
307
+ defineRegExpGetter ( 'multiline' ) ;
308
+ defineRegExpGetter ( 'dotAll' ) ;
309
+ defineRegExpGetter ( 'unicode' ) ;
310
+ defineRegExpGetter ( 'sticky' ) ;
311
+ ObjectFreeze ( safeTextTransformProperties ) ;
312
+
313
+ const toSafeRegex = ( stringOrRegex ) =>
314
+ ObjectDefineProperties ( stringOrRegex , safeTextTransformProperties ) ;
315
+ const toSafeString = ( string ) => toSafeRegex ( new String ( string ) ) ;
316
+ primordials . makeSafeStringObject = toSafeString ;
317
+
318
+ /**
319
+ * @param {string } thisString
320
+ * @param {string } needle
321
+ * @returns {string[] }
322
+ */
323
+ primordials . SafeStringPrototypeMatch = ( thisString , needle ) =>
324
+ RegExpPrototypeSymbolMatch ( toSafeRegex ( new RegExp ( needle ) ) , thisString ) ;
325
+
326
+ /**
327
+ * @param {string } thisStr
328
+ * @param {string } needle
329
+ * @returns {string[] }
330
+ */
331
+ primordials . SafeStringPrototypeMatchAll = ( thisStr , needle ) =>
332
+ RegExpPrototypeSymbolMatch ( toSafeRegex ( new RegExp ( needle , 'g' ) ) , thisStr ) ;
333
+
334
+ /**
335
+ * @param {string } thisStr
336
+ * @param {string } searchVal
337
+ * @param {string | (substring: string, ...args: any[]) => string } replaceVal
338
+ * @returns {string }
339
+ */
340
+ primordials . SafeStringPrototypeReplace = ( thisStr , searchVal , replaceVal ) =>
341
+ StringPrototypeReplace ( thisStr , toSafeString ( searchVal ) , replaceVal ) ;
342
+
343
+ /**
344
+ * @param {string } thisStr
345
+ * @param {string } searchVal
346
+ * @param {string | (substring: string, ...args: any[]) => string } replaceVal
347
+ * @returns {string }
348
+ */
349
+ primordials . SafeStringPrototypeReplaceAll =
350
+ ( thisStr , searchVal , replaceVal ) =>
351
+ StringPrototypeReplaceAll ( thisStr , toSafeString ( searchVal ) , replaceVal ) ;
352
+
353
+ /**
354
+ * @param {string } thisString
355
+ * @param {string } needle
356
+ * @returns {number }
357
+ */
358
+ primordials . SafeStringPrototypeSearch = ( thisString , needle ) =>
359
+ RegExpPrototypeSymbolSearch ( toSafeRegex ( new RegExp ( needle ) ) , thisString ) ;
360
+
361
+ /**
362
+ * @param {string } thisString
363
+ * @param {string } splitter
364
+ * @param {number } [limit]
365
+ * @returns {string }
366
+ */
367
+ primordials . SafeStringPrototypeSplit = ( thisString , splitter , limit ) =>
368
+ StringPrototypeSplit ( thisString , toSafeString ( splitter ) , limit ) ;
369
+
370
+ /**
371
+ * @param {RegExp } thisRegex
372
+ * @param {string } string
373
+ * @returns {string[] }
374
+ */
375
+ primordials . SafeRegExpPrototypeSymbolMatch = ( thisRegex , string ) =>
376
+ RegExpPrototypeSymbolMatch ( toSafeRegex ( thisRegex ) , string ) ;
377
+
378
+ /**
379
+ * @param {RegExp } thisRegex
380
+ * @param {string } string
381
+ * @param {string | (substring: string, ...args: any[]) => string } replaceVal
382
+ * @returns {string }
383
+ */
384
+ primordials . SafeRegExpPrototypeSymbolReplace =
385
+ ( thisRegex , string , replaceVal ) =>
386
+ RegExpPrototypeSymbolReplace ( toSafeRegex ( thisRegex ) , string , replaceVal ) ;
387
+
388
+ /**
389
+ * @param {RegExp } thisRegex
390
+ * @param {string } string
391
+ * @returns {number }
392
+ */
393
+ primordials . SafeRegExpPrototypeSymbolSearch = ( thisRegex , string ) =>
394
+ RegExpPrototypeSymbolSearch ( toSafeRegex ( thisRegex ) , string ) ;
395
+
396
+ /**
397
+ * Re-implementation of `RegExp.prototype [ @@split ]` that do not rely on
398
+ * user-mutable methods.
399
+ * @ref https://tc39.es/ecma262/#sec-regexp.prototype-@@split
400
+ * @param {RegExp } splitter
401
+ * @param {string } string
402
+ * @param {number } [limit]
403
+ * @returns {string[] }
404
+ */
405
+ primordials . SafeRegExpPrototypeSymbolSplit = ( splitter , string , limit ) => {
406
+ if ( ! RegExpPrototypeGetSticky ( splitter ) )
407
+ // eslint-disable-next-line no-restricted-syntax
408
+ throw new Error ( 'You must use sticky flag (y).' ) ;
409
+ if ( RegExpPrototypeGetUnicode ( splitter ) )
410
+ // eslint-disable-next-line no-restricted-syntax
411
+ throw new Error ( 'Unicode matching regex not supported' ) ;
412
+ const S = string ;
413
+ const A = [ ] ;
414
+ let lengthA = 0 ;
415
+ if ( limit === 0 ) return A ;
416
+ const size = S . length ;
417
+ if ( size === 0 ) {
418
+ const z = RegExpPrototypeExec ( splitter , S ) ;
419
+ if ( z === null ) A [ 0 ] = S ;
420
+ return A ;
421
+ }
422
+
423
+ let p = 0 ;
424
+ let q = p ;
425
+ while ( q < size ) {
426
+ splitter . lastIndex = q ;
427
+ const z = RegExpPrototypeExec ( splitter , S ) ;
428
+ if ( z === null ) q ++ ;
429
+ else {
430
+ const e = MathMin ( splitter . lastIndex , size ) ;
431
+ if ( e === p ) q ++ ;
432
+ else {
433
+ const T = StringPrototypeSlice ( S , p , q ) ;
434
+ A [ lengthA ++ ] = T ;
435
+ if ( lengthA === limit ) return A ;
436
+ p = e ;
437
+ const numberOfCaptures = MathMax ( z . length - 1 , 0 ) ;
438
+ for ( let i = 1 ; i <= numberOfCaptures ; i ++ ) {
439
+ const nextCapture = z [ i ] ;
440
+ A [ lengthA ++ ] = nextCapture ;
441
+ if ( lengthA === limit ) return A ;
442
+ }
443
+ q = p ;
444
+ }
445
+ }
446
+ }
447
+ A [ lengthA ] = StringPrototypeSlice ( S , p , size ) ;
448
+ return A ;
449
+ } ;
450
+
451
+ primordials . SafeRegExpPrototypeTest = ( thisRegex , string ) =>
452
+ RegExpPrototypeExec ( thisRegex , string ) !== null ;
453
+ }
454
+
265
455
// Because these functions are used by `makeSafe`, which is exposed
266
456
// on the `primordials` object, it's important to use const references
267
457
// to the primordials that they use:
0 commit comments