Skip to content

Commit aba228e

Browse files
committed
chore: use primordials
1 parent 402b059 commit aba228e

8 files changed

Lines changed: 197 additions & 165 deletions

File tree

package-lock.json

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
"node": ">=16 || 14 >=14.17"
5656
},
5757
"dependencies": {
58-
"brace-expansion": "^2.0.1"
58+
"brace-expansion": "^2.0.1",
59+
"node-primordials": "github:MoLow/node-primordials#tmp-build"
5960
},
6061
"devDependencies": {
6162
"@types/brace-expansion": "^1.1.0",

src/ast.ts

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { parseClass } from './brace-expressions.js'
44
import { MinimatchOptions, MMRegExp } from './index.js'
55
import { unescape } from './unescape.js'
6+
import { ArrayPrototypeFilter, ArrayPrototypeJoin, ArrayPrototypeMap, ArrayPrototypePop, ArrayPrototypePush, ArrayPrototypeSlice, ObjectAssign, SafeSet, StringPrototypeCharAt, StringPrototypeReplace, StringPrototypeSubstring, StringPrototypeToLowerCase, StringPrototypeToUpperCase } from "./primordials.js";
67

78
// classes [] are handled by the parseClass method
89
// for positive extglobs, we sub-parse the contents, and combine,
@@ -42,7 +43,7 @@ import { unescape } from './unescape.js'
4243
// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']
4344

4445
export type ExtglobType = '!' | '?' | '+' | '*' | '@'
45-
const types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])
46+
const types = new SafeSet<ExtglobType>(['!', '?', '+', '*', '@'])
4647
const isExtglobType = (c: string): c is ExtglobType =>
4748
types.has(c as ExtglobType)
4849

@@ -56,12 +57,12 @@ const startNoDot = '(?!\\.)'
5657
// characters that indicate a start of pattern needs the "no dots" bit,
5758
// because a dot *might* be matched. ( is not in the list, because in
5859
// the case of a child extglob, it will handle the prevention itself.
59-
const addPatternStart = new Set(['[', '.'])
60+
const addPatternStart = new SafeSet(['[', '.'])
6061
// cases where traversal is A-OK, no dot prevention needed
61-
const justDots = new Set(['..', '.'])
62-
const reSpecials = new Set('().*{}+?[]^$\\!')
62+
const justDots = new SafeSet(['..', '.'])
63+
const reSpecials = new SafeSet(["'", '(', ')', '.', '*', '{', '}', '+', '?','[', ']', '^', '$', '\\', '!'])
6364
const regExpEscape = (s: string) =>
64-
s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
65+
StringPrototypeReplace(s, /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
6566

6667
// any single thing other than /
6768
const qmark = '[^/]'
@@ -95,7 +96,7 @@ export class AST {
9596
constructor(
9697
type: ExtglobType | null,
9798
parent?: AST,
98-
options: MinimatchOptions = {}
99+
options: MinimatchOptions = { __proto__: null } as MinimatchOptions
99100
) {
100101
this.type = type
101102
// extglobs are inherently magical
@@ -104,15 +105,16 @@ export class AST {
104105
this.#root = this.#parent ? this.#parent.#root : this
105106
this.#options = this.#root === this ? options : this.#root.#options
106107
this.#negs = this.#root === this ? [] : this.#root.#negs
107-
if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)
108+
if (type === '!' && !this.#root.#filledNegs) ArrayPrototypePush(this.#negs, this)
108109
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0
109110
}
110111

111112
get hasMagic(): boolean | undefined {
112113
/* c8 ignore start */
113114
if (this.#hasMagic !== undefined) return this.#hasMagic
114115
/* c8 ignore stop */
115-
for (const p of this.#parts) {
116+
for (let i = 0; i < this.#parts.length; i++) {
117+
const p = this.#parts[i]
116118
if (typeof p === 'string') continue
117119
if (p.type || p.hasMagic) return (this.#hasMagic = true)
118120
}
@@ -123,11 +125,12 @@ export class AST {
123125
// reconstructs the pattern
124126
toString(): string {
125127
if (this.#toString !== undefined) return this.#toString
128+
const parts = ArrayPrototypeMap(this.#parts, p => String(p));
126129
if (!this.type) {
127-
return (this.#toString = this.#parts.map(p => String(p)).join(''))
130+
return (this.#toString = ArrayPrototypeJoin(parts, ''))
128131
} else {
129132
return (this.#toString =
130-
this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')')
133+
this.type + '(' + ArrayPrototypeJoin(parts, '|') + ')')
131134
}
132135
}
133136

@@ -141,7 +144,7 @@ export class AST {
141144
this.toString()
142145
this.#filledNegs = true
143146
let n: AST | undefined
144-
while ((n = this.#negs.pop())) {
147+
while ((n = ArrayPrototypePop(this.#negs))) {
145148
if (n.type !== '!') continue
146149
// walk up the tree, appending everthing that comes AFTER parentIndex
147150
let p: AST | undefined = n
@@ -152,7 +155,8 @@ export class AST {
152155
!pp.type && i < pp.#parts.length;
153156
i++
154157
) {
155-
for (const part of n.#parts) {
158+
for (let y = 0; y < n.#parts.length; y++) {
159+
const part = n.#parts[y];
156160
/* c8 ignore start */
157161
if (typeof part === 'string') {
158162
throw new Error('string part in extglob AST??')
@@ -169,7 +173,8 @@ export class AST {
169173
}
170174

171175
push(...parts: (string | AST)[]) {
172-
for (const p of parts) {
176+
for (let i = 0; i < parts.length; i++) {
177+
const p = parts[i];
173178
if (p === '') continue
174179
/* c8 ignore start */
175180
if (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {
@@ -183,8 +188,8 @@ export class AST {
183188
toJSON() {
184189
const ret: any[] =
185190
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())]
191+
? ArrayPrototypeMap(ArrayPrototypeSlice(this.#parts), (p: string | AST) => (typeof p === 'string' ? p : p.toJSON()))
192+
: [this.type, ...ArrayPrototypeMap(this.#parts, (p: AST) => p.toJSON())]
188193
if (this.isStart() && !this.type) ret.unshift([])
189194
if (
190195
this.isEnd() &&
@@ -231,8 +236,8 @@ export class AST {
231236

232237
clone(parent: AST) {
233238
const c = new AST(this.type, parent)
234-
for (const p of this.#parts) {
235-
c.copyIn(p)
239+
for (let i = 0; i < this.#parts.length; i++) {
240+
c.copyIn(this.#parts[i])
236241
}
237242
return c
238243
}
@@ -252,7 +257,7 @@ export class AST {
252257
let i = pos
253258
let acc = ''
254259
while (i < str.length) {
255-
const c = str.charAt(i++)
260+
const c = StringPrototypeCharAt(str, i++)
256261
// still accumulate escapes at this point, but we do ignore
257262
// starts that are escaped
258263
if (escaping || c === '\\') {
@@ -279,7 +284,7 @@ export class AST {
279284
continue
280285
}
281286

282-
if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {
287+
if (!opt.noext && isExtglobType(c) && StringPrototypeCharAt(str, i) === '(') {
283288
ast.push(acc)
284289
acc = ''
285290
const ext = new AST(c, ast)
@@ -300,7 +305,7 @@ export class AST {
300305
const parts: AST[] = []
301306
let acc = ''
302307
while (i < str.length) {
303-
const c = str.charAt(i++)
308+
const c = StringPrototypeCharAt(str, i++);
304309
// still accumulate escapes at this point, but we do ignore
305310
// starts that are escaped
306311
if (escaping || c === '\\') {
@@ -327,7 +332,7 @@ export class AST {
327332
continue
328333
}
329334

330-
if (isExtglobType(c) && str.charAt(i) === '(') {
335+
if (isExtglobType(c) && StringPrototypeCharAt(str, i) === '(') {
331336
part.push(acc)
332337
acc = ''
333338
const ext = new AST(c, part)
@@ -338,7 +343,7 @@ export class AST {
338343
if (c === '|') {
339344
part.push(acc)
340345
acc = ''
341-
parts.push(part)
346+
ArrayPrototypePush(parts, part)
342347
part = new AST(null, ast)
343348
continue
344349
}
@@ -359,11 +364,11 @@ export class AST {
359364
// maybe something else in there.
360365
ast.type = null
361366
ast.#hasMagic = undefined
362-
ast.#parts = [str.substring(pos - 1)]
367+
ast.#parts = [StringPrototypeSubstring(str, pos - 1)]
363368
return i
364369
}
365370

366-
static fromGlob(pattern: string, options: MinimatchOptions = {}) {
371+
static fromGlob(pattern: string, options: MinimatchOptions = { __proto__: null } as MinimatchOptions) {
367372
const ast = new AST(null, undefined, options)
368373
AST.#parseAST(pattern, ast, 0, options)
369374
return ast
@@ -386,13 +391,13 @@ export class AST {
386391
this.#hasMagic ||
387392
(this.#options.nocase &&
388393
!this.#options.nocaseMagicOnly &&
389-
glob.toUpperCase() !== glob.toLowerCase())
394+
StringPrototypeToUpperCase(glob) !== StringPrototypeToLowerCase(glob))
390395
if (!anyMagic) {
391396
return body
392397
}
393398

394399
const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')
395-
return Object.assign(new RegExp(`^${re}$`, flags), {
400+
return ObjectAssign(new RegExp(`^${re}$`, flags), {
396401
_src: re,
397402
_glob: glob,
398403
})
@@ -474,8 +479,8 @@ export class AST {
474479
if (this.#root === this) this.#fillNegs()
475480
if (!this.type) {
476481
const noEmpty = this.isStart() && this.isEnd()
477-
const src = this.#parts
478-
.map(p => {
482+
const src = ArrayPrototypeJoin(
483+
ArrayPrototypeMap(this.#parts, (p: string | AST) => {
479484
const [re, _, hasMagic, uflag] =
480485
typeof p === 'string'
481486
? AST.#parseGlob(p, this.#hasMagic, noEmpty)
@@ -484,7 +489,7 @@ export class AST {
484489
this.#uflag = this.#uflag || uflag
485490
return re
486491
})
487-
.join('')
492+
,'')
488493

489494
let start = ''
490495
if (this.isStart()) {
@@ -502,14 +507,14 @@ export class AST {
502507
// and prevent that.
503508
const needNoTrav =
504509
// dots are allowed, and the pattern starts with [ or .
505-
(dot && aps.has(src.charAt(0))) ||
510+
(dot && aps.has(StringPrototypeCharAt(src, 0))) ||
506511
// the pattern starts with \., and then [ or .
507-
(src.startsWith('\\.') && aps.has(src.charAt(2))) ||
512+
(src.startsWith('\\.') && aps.has(StringPrototypeCharAt(src, 2))) ||
508513
// the pattern starts with \.\., and then [ or .
509-
(src.startsWith('\\.\\.') && aps.has(src.charAt(4)))
514+
(src.startsWith('\\.\\.') && aps.has(StringPrototypeCharAt(src, 4)))
510515
// no need to prevent dots if it can't match a dot, or if a
511516
// sub-pattern will be preventing it anyway.
512-
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))
517+
const needNoDot = !dot && !allowDot && aps.has(StringPrototypeCharAt(src, 0))
513518

514519
start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : ''
515520
}
@@ -597,8 +602,9 @@ export class AST {
597602
}
598603

599604
#partsToRegExp(dot: boolean) {
600-
return this.#parts
601-
.map(p => {
605+
return ArrayPrototypeJoin(
606+
ArrayPrototypeFilter(
607+
ArrayPrototypeMap(this.#parts, (p: string | AST) => {
602608
// extglob ASTs should only contain parent ASTs
603609
/* c8 ignore start */
604610
if (typeof p === 'string') {
@@ -610,8 +616,8 @@ export class AST {
610616
this.#uflag = this.#uflag || uflag
611617
return re
612618
})
613-
.filter(p => !(this.isStart() && this.isEnd()) || !!p)
614-
.join('|')
619+
, (p: any) => !(this.isStart() && this.isEnd()) || !!p)
620+
, '|')
615621
}
616622

617623
static #parseGlob(
@@ -623,7 +629,7 @@ export class AST {
623629
let re = ''
624630
let uflag = false
625631
for (let i = 0; i < glob.length; i++) {
626-
const c = glob.charAt(i)
632+
const c = StringPrototypeCharAt(glob, i)
627633
if (escaping) {
628634
escaping = false
629635
re += (reSpecials.has(c) ? '\\' : '') + c

0 commit comments

Comments
 (0)