33import { parseClass } from './brace-expressions.js'
44import { MinimatchOptions , MMRegExp } from './index.js'
55import { unescape } from './unescape.js'
6+ import {
7+ ArrayPrototypeFilter ,
8+ ArrayPrototypeJoin ,
9+ ArrayPrototypeMap ,
10+ ArrayPrototypePop ,
11+ ArrayPrototypePush ,
12+ ArrayPrototypeSlice ,
13+ ObjectAssign ,
14+ SafeSet ,
15+ StringPrototypeCharAt ,
16+ StringPrototypeReplace ,
17+ StringPrototypeSubstring ,
18+ StringPrototypeToLowerCase ,
19+ StringPrototypeToUpperCase ,
20+ } from './primordials.js'
621
722// classes [] are handled by the parseClass method
823// for positive extglobs, we sub-parse the contents, and combine,
@@ -42,7 +57,7 @@ import { unescape } from './unescape.js'
4257// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']
4358
4459export type ExtglobType = '!' | '?' | '+' | '*' | '@'
45- const types = new Set < ExtglobType > ( [ '!' , '?' , '+' , '*' , '@' ] )
60+ const types = new SafeSet < ExtglobType > ( [ '!' , '?' , '+' , '*' , '@' ] )
4661const isExtglobType = ( c : string ) : c is ExtglobType =>
4762 types . has ( c as ExtglobType )
4863
@@ -56,12 +71,28 @@ const startNoDot = '(?!\\.)'
5671// characters that indicate a start of pattern needs the "no dots" bit,
5772// because a dot *might* be matched. ( is not in the list, because in
5873// the case of a child extglob, it will handle the prevention itself.
59- const addPatternStart = new Set ( [ '[' , '.' ] )
74+ const addPatternStart = new SafeSet ( [ '[' , '.' ] )
6075// cases where traversal is A-OK, no dot prevention needed
61- const justDots = new Set ( [ '..' , '.' ] )
62- const reSpecials = new Set ( '().*{}+?[]^$\\!' )
76+ const justDots = new SafeSet ( [ '..' , '.' ] )
77+ const reSpecials = new SafeSet ( [
78+ "'" ,
79+ '(' ,
80+ ')' ,
81+ '.' ,
82+ '*' ,
83+ '{' ,
84+ '}' ,
85+ '+' ,
86+ '?' ,
87+ '[' ,
88+ ']' ,
89+ '^' ,
90+ '$' ,
91+ '\\' ,
92+ '!' ,
93+ ] )
6394const regExpEscape = ( s : string ) =>
64- s . replace ( / [ - [ \] { } ( ) * + ? . , \\ ^ $ | # \s ] / g, '\\$&' )
95+ StringPrototypeReplace ( s , / [ - [ \] { } ( ) * + ? . , \\ ^ $ | # \s ] / g, '\\$&' )
6596
6697// any single thing other than /
6798const qmark = '[^/]'
@@ -95,7 +126,7 @@ export class AST {
95126 constructor (
96127 type : ExtglobType | null ,
97128 parent ?: AST ,
98- options : MinimatchOptions = { }
129+ options : MinimatchOptions = { __proto__ : null } as MinimatchOptions
99130 ) {
100131 this . type = type
101132 // extglobs are inherently magical
@@ -104,15 +135,17 @@ export class AST {
104135 this . #root = this . #parent ? this . #parent. #root : this
105136 this . #options = this . #root === this ? options : this . #root. #options
106137 this . #negs = this . #root === this ? [ ] : this . #root. #negs
107- if ( type === '!' && ! this . #root. #filledNegs) this . #negs. push ( this )
138+ if ( type === '!' && ! this . #root. #filledNegs)
139+ ArrayPrototypePush ( this . #negs, this )
108140 this . #parentIndex = this . #parent ? this . #parent. #parts. length : 0
109141 }
110142
111143 get hasMagic ( ) : boolean | undefined {
112144 /* c8 ignore start */
113145 if ( this . #hasMagic !== undefined ) return this . #hasMagic
114146 /* c8 ignore stop */
115- for ( const p of this . #parts) {
147+ for ( let i = 0 ; i < this . #parts. length ; i ++ ) {
148+ const p = this . #parts[ i ]
116149 if ( typeof p === 'string' ) continue
117150 if ( p . type || p . hasMagic ) return ( this . #hasMagic = true )
118151 }
@@ -123,11 +156,12 @@ export class AST {
123156 // reconstructs the pattern
124157 toString ( ) : string {
125158 if ( this . #toString !== undefined ) return this . #toString
159+ const parts = ArrayPrototypeMap ( this . #parts, p => String ( p ) )
126160 if ( ! this . type ) {
127- return ( this . #toString = this . #parts . map ( p => String ( p ) ) . join ( '' ) )
161+ return ( this . #toString = ArrayPrototypeJoin ( parts , '' ) )
128162 } else {
129163 return ( this . #toString =
130- this . type + '(' + this . #parts . map ( p => String ( p ) ) . join ( '|' ) + ')' )
164+ this . type + '(' + ArrayPrototypeJoin ( parts , '|' ) + ')' )
131165 }
132166 }
133167
@@ -141,7 +175,7 @@ export class AST {
141175 this . toString ( )
142176 this . #filledNegs = true
143177 let n : AST | undefined
144- while ( ( n = this . #negs. pop ( ) ) ) {
178+ while ( ( n = ArrayPrototypePop ( this . #negs) ) ) {
145179 if ( n . type !== '!' ) continue
146180 // walk up the tree, appending everthing that comes AFTER parentIndex
147181 let p : AST | undefined = n
@@ -152,7 +186,8 @@ export class AST {
152186 ! pp . type && i < pp . #parts. length ;
153187 i ++
154188 ) {
155- for ( const part of n . #parts) {
189+ for ( let y = 0 ; y < n . #parts. length ; y ++ ) {
190+ const part = n . #parts[ y ]
156191 /* c8 ignore start */
157192 if ( typeof part === 'string' ) {
158193 throw new Error ( 'string part in extglob AST??' )
@@ -169,7 +204,8 @@ export class AST {
169204 }
170205
171206 push ( ...parts : ( string | AST ) [ ] ) {
172- for ( const p of parts ) {
207+ for ( let i = 0 ; i < parts . length ; i ++ ) {
208+ const p = parts [ i ]
173209 if ( p === '' ) continue
174210 /* c8 ignore start */
175211 if ( typeof p !== 'string' && ! ( p instanceof AST && p . #parent === this ) ) {
@@ -183,8 +219,11 @@ export class AST {
183219 toJSON ( ) {
184220 const ret : any [ ] =
185221 this . type === null
186- ? this . #parts. slice ( ) . map ( p => ( typeof p === 'string' ? p : p . toJSON ( ) ) )
187- : [ this . type , ...this . #parts. map ( p => ( p as AST ) . toJSON ( ) ) ]
222+ ? ArrayPrototypeMap (
223+ ArrayPrototypeSlice ( this . #parts) ,
224+ ( p : string | AST ) => ( typeof p === 'string' ? p : p . toJSON ( ) )
225+ )
226+ : [ this . type , ...ArrayPrototypeMap ( this . #parts, ( p : AST ) => p . toJSON ( ) ) ]
188227 if ( this . isStart ( ) && ! this . type ) ret . unshift ( [ ] )
189228 if (
190229 this . isEnd ( ) &&
@@ -231,8 +270,8 @@ export class AST {
231270
232271 clone ( parent : AST ) {
233272 const c = new AST ( this . type , parent )
234- for ( const p of this . #parts) {
235- c . copyIn ( p )
273+ for ( let i = 0 ; i < this . #parts. length ; i ++ ) {
274+ c . copyIn ( this . #parts [ i ] )
236275 }
237276 return c
238277 }
@@ -252,7 +291,7 @@ export class AST {
252291 let i = pos
253292 let acc = ''
254293 while ( i < str . length ) {
255- const c = str . charAt ( i ++ )
294+ const c = StringPrototypeCharAt ( str , i ++ )
256295 // still accumulate escapes at this point, but we do ignore
257296 // starts that are escaped
258297 if ( escaping || c === '\\' ) {
@@ -279,7 +318,11 @@ export class AST {
279318 continue
280319 }
281320
282- if ( ! opt . noext && isExtglobType ( c ) && str . charAt ( i ) === '(' ) {
321+ if (
322+ ! opt . noext &&
323+ isExtglobType ( c ) &&
324+ StringPrototypeCharAt ( str , i ) === '('
325+ ) {
283326 ast . push ( acc )
284327 acc = ''
285328 const ext = new AST ( c , ast )
@@ -300,7 +343,7 @@ export class AST {
300343 const parts : AST [ ] = [ ]
301344 let acc = ''
302345 while ( i < str . length ) {
303- const c = str . charAt ( i ++ )
346+ const c = StringPrototypeCharAt ( str , i ++ )
304347 // still accumulate escapes at this point, but we do ignore
305348 // starts that are escaped
306349 if ( escaping || c === '\\' ) {
@@ -327,7 +370,7 @@ export class AST {
327370 continue
328371 }
329372
330- if ( isExtglobType ( c ) && str . charAt ( i ) === '(' ) {
373+ if ( isExtglobType ( c ) && StringPrototypeCharAt ( str , i ) === '(' ) {
331374 part . push ( acc )
332375 acc = ''
333376 const ext = new AST ( c , part )
@@ -338,7 +381,7 @@ export class AST {
338381 if ( c === '|' ) {
339382 part . push ( acc )
340383 acc = ''
341- parts . push ( part )
384+ ArrayPrototypePush ( parts , part )
342385 part = new AST ( null , ast )
343386 continue
344387 }
@@ -359,11 +402,14 @@ export class AST {
359402 // maybe something else in there.
360403 ast . type = null
361404 ast . #hasMagic = undefined
362- ast . #parts = [ str . substring ( pos - 1 ) ]
405+ ast . #parts = [ StringPrototypeSubstring ( str , pos - 1 ) ]
363406 return i
364407 }
365408
366- static fromGlob ( pattern : string , options : MinimatchOptions = { } ) {
409+ static fromGlob (
410+ pattern : string ,
411+ options : MinimatchOptions = { __proto__ : null } as MinimatchOptions
412+ ) {
367413 const ast = new AST ( null , undefined , options )
368414 AST . #parseAST( pattern , ast , 0 , options )
369415 return ast
@@ -386,13 +432,13 @@ export class AST {
386432 this . #hasMagic ||
387433 ( this . #options. nocase &&
388434 ! this . #options. nocaseMagicOnly &&
389- glob . toUpperCase ( ) !== glob . toLowerCase ( ) )
435+ StringPrototypeToUpperCase ( glob ) !== StringPrototypeToLowerCase ( glob ) )
390436 if ( ! anyMagic ) {
391437 return body
392438 }
393439
394440 const flags = ( this . #options. nocase ? 'i' : '' ) + ( uflag ? 'u' : '' )
395- return Object . assign ( new RegExp ( `^${ re } $` , flags ) , {
441+ return ObjectAssign ( new RegExp ( `^${ re } $` , flags ) , {
396442 _src : re ,
397443 _glob : glob ,
398444 } )
@@ -474,17 +520,18 @@ export class AST {
474520 if ( this . #root === this ) this . #fillNegs( )
475521 if ( ! this . type ) {
476522 const noEmpty = this . isStart ( ) && this . isEnd ( )
477- const src = this . #parts
478- . map ( p => {
523+ const src = ArrayPrototypeJoin (
524+ ArrayPrototypeMap ( this . #parts , ( p : string | AST ) => {
479525 const [ re , _ , hasMagic , uflag ] =
480526 typeof p === 'string'
481527 ? AST . #parseGlob( p , this . #hasMagic, noEmpty )
482528 : p . toRegExpSource ( allowDot )
483529 this . #hasMagic = this . #hasMagic || hasMagic
484530 this . #uflag = this . #uflag || uflag
485531 return re
486- } )
487- . join ( '' )
532+ } ) ,
533+ ''
534+ )
488535
489536 let start = ''
490537 if ( this . isStart ( ) ) {
@@ -502,14 +549,17 @@ export class AST {
502549 // and prevent that.
503550 const needNoTrav =
504551 // dots are allowed, and the pattern starts with [ or .
505- ( dot && aps . has ( src . charAt ( 0 ) ) ) ||
552+ ( dot && aps . has ( StringPrototypeCharAt ( src , 0 ) ) ) ||
506553 // the pattern starts with \., and then [ or .
507- ( src . startsWith ( '\\.' ) && aps . has ( src . charAt ( 2 ) ) ) ||
554+ ( src . startsWith ( '\\.' ) &&
555+ aps . has ( StringPrototypeCharAt ( src , 2 ) ) ) ||
508556 // the pattern starts with \.\., and then [ or .
509- ( src . startsWith ( '\\.\\.' ) && aps . has ( src . charAt ( 4 ) ) )
557+ ( src . startsWith ( '\\.\\.' ) &&
558+ aps . has ( StringPrototypeCharAt ( src , 4 ) ) )
510559 // no need to prevent dots if it can't match a dot, or if a
511560 // sub-pattern will be preventing it anyway.
512- const needNoDot = ! dot && ! allowDot && aps . has ( src . charAt ( 0 ) )
561+ const needNoDot =
562+ ! dot && ! allowDot && aps . has ( StringPrototypeCharAt ( src , 0 ) )
513563
514564 start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : ''
515565 }
@@ -597,21 +647,24 @@ export class AST {
597647 }
598648
599649 #partsToRegExp( dot : boolean ) {
600- return this . #parts
601- . map ( p => {
602- // extglob ASTs should only contain parent ASTs
603- /* c8 ignore start */
604- if ( typeof p === 'string' ) {
605- throw new Error ( 'string type in extglob ast??' )
606- }
607- /* c8 ignore stop */
608- // can ignore hasMagic, because extglobs are already always magic
609- const [ re , _ , _hasMagic , uflag ] = p . toRegExpSource ( dot )
610- this . #uflag = this . #uflag || uflag
611- return re
612- } )
613- . filter ( p => ! ( this . isStart ( ) && this . isEnd ( ) ) || ! ! p )
614- . join ( '|' )
650+ return ArrayPrototypeJoin (
651+ ArrayPrototypeFilter (
652+ ArrayPrototypeMap ( this . #parts, ( p : string | AST ) => {
653+ // extglob ASTs should only contain parent ASTs
654+ /* c8 ignore start */
655+ if ( typeof p === 'string' ) {
656+ throw new Error ( 'string type in extglob ast??' )
657+ }
658+ /* c8 ignore stop */
659+ // can ignore hasMagic, because extglobs are already always magic
660+ const [ re , _ , _hasMagic , uflag ] = p . toRegExpSource ( dot )
661+ this . #uflag = this . #uflag || uflag
662+ return re
663+ } ) ,
664+ ( p : any ) => ! ( this . isStart ( ) && this . isEnd ( ) ) || ! ! p
665+ ) ,
666+ '|'
667+ )
615668 }
616669
617670 static #parseGlob(
@@ -623,7 +676,7 @@ export class AST {
623676 let re = ''
624677 let uflag = false
625678 for ( let i = 0 ; i < glob . length ; i ++ ) {
626- const c = glob . charAt ( i )
679+ const c = StringPrototypeCharAt ( glob , i )
627680 if ( escaping ) {
628681 escaping = false
629682 re += ( reSpecials . has ( c ) ? '\\' : '' ) + c
0 commit comments