Skip to content

Commit 0348137

Browse files
authored
refactor: use dedicated regex methods (#15228)
1 parent 5b85040 commit 0348137

18 files changed

+60
-67
lines changed

packages/vite/src/node/__tests__/plugins/css.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ require("other-module");`
325325
`"require("some-module"),/* empty css */require("other-module");"`,
326326
)
327327
// So there should be no pure css chunk anymore
328-
expect(newCode.match(/pure_css_chunk\.js/)).toBeNull()
328+
expect(newCode).not.toContain('pure_css_chunk.js')
329329
})
330330

331331
test('replaces require call in minified code that uses comma operator followed by assignment', () => {

packages/vite/src/node/__tests__/scan.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ describe('optimizer-scan:script-test', () => {
106106
`import type Bar from 'foo'`,
107107
]
108108
shouldFailArray.forEach((str) => {
109+
importsRE.lastIndex = 0
109110
expect(importsRE.test(str)).toBe(false)
110111
})
111112
})

packages/vite/src/node/build.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ export function onRollupWarning(
910910
const id = warning.id
911911
const exporter = warning.exporter
912912
// throw unless it's commonjs external...
913-
if (!id || !/\?commonjs-external$/.test(id)) {
913+
if (!id || !id.endsWith('?commonjs-external')) {
914914
throw new Error(
915915
`[vite]: Rollup failed to resolve import "${exporter}" from "${id}".\n` +
916916
`This is most likely unintended because it can break your application at runtime.\n` +

packages/vite/src/node/optimizer/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ export function runOptimizeDeps(
642642
}
643643

644644
for (const o of Object.keys(meta.outputs)) {
645-
if (!o.match(jsMapExtensionRE)) {
645+
if (!jsMapExtensionRE.test(o)) {
646646
const id = path
647647
.relative(processingCacheDirOutputPath, o)
648648
.replace(jsExtensionRE, '')

packages/vite/src/node/plugins/assetImportMetaUrl.ts

+8-10
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,13 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
5353
) {
5454
let s: MagicString | undefined
5555
const assetImportMetaUrlRE =
56-
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/g
56+
// eslint-disable-next-line regexp/no-unused-capturing-group -- https://git.1-hub.cnota-meshi/eslint-plugin-regexp/issues/675
57+
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
5758
const cleanString = stripLiteral(code)
5859

5960
let match: RegExpExecArray | null
6061
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
61-
const { 0: exp, 1: emptyUrl, index } = match
62-
63-
const urlStart = cleanString.indexOf(emptyUrl, index)
64-
const urlEnd = urlStart + emptyUrl.length
62+
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
6563
const rawUrl = code.slice(urlStart, urlEnd)
6664

6765
if (!s) s = new MagicString(code)
@@ -93,8 +91,8 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
9391
query: injectQuery(queryString, 'url'),
9492
}
9593
s.update(
96-
index,
97-
index + exp.length,
94+
startIndex,
95+
endIndex,
9896
`new URL((import.meta.glob(${JSON.stringify(
9997
pattern,
10098
)}, ${JSON.stringify(
@@ -141,15 +139,15 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
141139
}
142140
}
143141
if (!builtUrl) {
144-
const rawExp = code.slice(index, index + exp.length)
142+
const rawExp = code.slice(startIndex, endIndex)
145143
config.logger.warnOnce(
146144
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime`,
147145
)
148146
builtUrl = url
149147
}
150148
s.update(
151-
index,
152-
index + exp.length,
149+
startIndex,
150+
endIndex,
153151
`new URL(${JSON.stringify(builtUrl)}, import.meta.url)`,
154152
)
155153
}

packages/vite/src/node/plugins/css.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -1288,8 +1288,6 @@ export async function preprocessCSS(
12881288
return await compileCSS(filename, code, config)
12891289
}
12901290

1291-
const postcssReturnsVirtualFilesRE = /^<.+>$/
1292-
12931291
export async function formatPostcssSourceMap(
12941292
rawMap: ExistingRawSourceMap,
12951293
file: string,
@@ -1299,7 +1297,8 @@ export async function formatPostcssSourceMap(
12991297
const sources = rawMap.sources.map((source) => {
13001298
const cleanSource = cleanUrl(decodeURIComponent(source))
13011299

1302-
if (postcssReturnsVirtualFilesRE.test(cleanSource)) {
1300+
// postcss virtual files
1301+
if (cleanSource[0] === '<' && cleanSource[cleanSource.length - 1] === '>') {
13031302
return `\0${cleanSource}`
13041303
}
13051304

@@ -1373,7 +1372,7 @@ async function resolvePostcssConfig(
13731372
const searchPath =
13741373
typeof inlineOptions === 'string' ? inlineOptions : config.root
13751374
result = postcssrc({}, searchPath).catch((e) => {
1376-
if (!/No PostCSS Config found/.test(e.message)) {
1375+
if (!e.message.includes('No PostCSS Config found')) {
13771376
if (e instanceof Error) {
13781377
const { name, message, stack } = e
13791378
e.name = 'Failed to load PostCSS config'
@@ -1654,6 +1653,11 @@ function resolveMinifyCssEsbuildOptions(
16541653
}
16551654
}
16561655

1656+
const atImportRE =
1657+
/@import(?:\s*(?:url\([^)]*\)|"(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*').*?|[^;]*);/g
1658+
const atCharsetRE =
1659+
/@charset(?:\s*(?:"(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*').*?|[^;]*);/g
1660+
16571661
export async function hoistAtRules(css: string): Promise<string> {
16581662
const s = new MagicString(css)
16591663
const cleanCss = emptyCssComments(css)
@@ -1663,8 +1667,7 @@ export async function hoistAtRules(css: string): Promise<string> {
16631667
// CSS @import can only appear at top of the file. We need to hoist all @import
16641668
// to top when multiple files are concatenated.
16651669
// match until semicolon that's not in quotes
1666-
const atImportRE =
1667-
/@import(?:\s*(?:url\([^)]*\)|"(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*').*?|[^;]*);/g
1670+
atImportRE.lastIndex = 0
16681671
while ((match = atImportRE.exec(cleanCss))) {
16691672
s.remove(match.index, match.index + match[0].length)
16701673
// Use `appendLeft` instead of `prepend` to preserve original @import order
@@ -1673,8 +1676,7 @@ export async function hoistAtRules(css: string): Promise<string> {
16731676

16741677
// #6333
16751678
// CSS @charset must be the top-first in the file, hoist the first to top
1676-
const atCharsetRE =
1677-
/@charset(?:\s*(?:"(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*').*?|[^;]*);/g
1679+
atCharsetRE.lastIndex = 0
16781680
let foundCharset = false
16791681
while ((match = atCharsetRE.exec(cleanCss))) {
16801682
s.remove(match.index, match.index + match[0].length)
@@ -2406,8 +2408,8 @@ export const convertTargets = (
24062408

24072409
for (const entry of entriesWithoutES) {
24082410
if (entry === 'esnext') continue
2409-
const index = entry.match(versionRE)?.index
2410-
if (index) {
2411+
const index = entry.search(versionRE)
2412+
if (index >= 0) {
24112413
const browser = map[entry.slice(0, index)]
24122414
if (browser === false) continue // No mapping available
24132415
if (browser) {

packages/vite/src/node/plugins/esbuild.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ export const buildEsbuildPlugin = (config: ResolvedConfig): Plugin => {
320320
const esbuildCode = res.code
321321
const contentIndex =
322322
opts.format === 'iife'
323-
? esbuildCode.match(IIFE_BEGIN_RE)?.index || 0
323+
? Math.max(esbuildCode.search(IIFE_BEGIN_RE), 0)
324324
: opts.format === 'umd'
325325
? esbuildCode.indexOf(`(function(`) // same for minified or not
326326
: 0

packages/vite/src/node/plugins/html.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ const htmlProxyRE =
4848
const inlineCSSRE = /__VITE_INLINE_CSS__([a-z\d]{8}_\d+)__/g
4949
// Do not allow preceding '.', but do allow preceding '...' for spread operations
5050
const inlineImportRE =
51-
/(?<!(?<!\.\.)\.)\bimport\s*\(("(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*')\)/g
51+
// eslint-disable-next-line regexp/no-unused-capturing-group -- https://git.1-hub.cnota-meshi/eslint-plugin-regexp/issues/675
52+
/(?<!(?<!\.\.)\.)\bimport\s*\(("(?:[^"]|(?<=\\)")*"|'(?:[^']|(?<=\\)')*')\)/dg
5253
const htmlLangRE = /\.(?:html|htm)$/
5354

5455
const importMapRE =
@@ -926,10 +927,9 @@ export function extractImportExpressionFromClassicScript(
926927
let match: RegExpExecArray | null
927928
inlineImportRE.lastIndex = 0
928929
while ((match = inlineImportRE.exec(cleanCode))) {
929-
const { 1: url, index } = match
930-
const startUrl = cleanCode.indexOf(url, index)
931-
const start = startUrl + 1
932-
const end = start + url.length - 2
930+
const [, [urlStart, urlEnd]] = match.indices!
931+
const start = urlStart + 1
932+
const end = urlEnd - 1
933933
scriptUrls.push({
934934
start: start + startOffset,
935935
end: end + startOffset,
@@ -1004,11 +1004,11 @@ export function preImportMapHook(
10041004
config: ResolvedConfig,
10051005
): IndexHtmlTransformHook {
10061006
return (html, ctx) => {
1007-
const importMapIndex = html.match(importMapRE)?.index
1008-
if (importMapIndex === undefined) return
1007+
const importMapIndex = html.search(importMapRE)
1008+
if (importMapIndex < 0) return
10091009

1010-
const importMapAppendIndex = html.match(importMapAppendRE)?.index
1011-
if (importMapAppendIndex === undefined) return
1010+
const importMapAppendIndex = html.search(importMapAppendRE)
1011+
if (importMapAppendIndex < 0) return
10121012

10131013
if (importMapAppendIndex < importMapIndex) {
10141014
const relativeHtml = normalizePath(

packages/vite/src/node/plugins/importAnalysis.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
366366
if (
367367
(isRelative || isSelfImport) &&
368368
!hasImportInQueryParamsRE.test(url) &&
369-
!url.match(DEP_VERSION_RE)
369+
!DEP_VERSION_RE.test(url)
370370
) {
371371
const versionMatch = importer.match(DEP_VERSION_RE)
372372
if (versionMatch) {
@@ -535,7 +535,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
535535
let rewriteDone = false
536536
if (
537537
depsOptimizer?.isOptimizedDepFile(resolvedId) &&
538-
!resolvedId.match(optimizedDepChunkRE)
538+
!optimizedDepChunkRE.test(resolvedId)
539539
) {
540540
// for optimized cjs deps, support named imports by rewriting named imports to const assignments.
541541
// internal optimized chunks don't need es interop and are excluded
@@ -555,7 +555,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
555555
// Non-entry dynamic imports from dependencies will reach here as there isn't
556556
// optimize info for them, but they don't need es interop. If the request isn't
557557
// a dynamic import, then it is an internal Vite error
558-
if (!file.match(optimizedDepDynamicRE)) {
558+
if (!optimizedDepDynamicRE.test(file)) {
559559
config.logger.error(
560560
colors.red(
561561
`Vite Error, ${url} optimized info should be defined`,

packages/vite/src/node/plugins/importAnalysisBuild.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const preloadMarker = `__VITE_PRELOAD__`
4545
export const preloadBaseMarker = `__VITE_PRELOAD_BASE__`
4646

4747
export const preloadHelperId = '\0vite/preload-helper.js'
48-
const preloadMarkerWithQuote = new RegExp(`['"]${preloadMarker}['"]`)
48+
const preloadMarkerWithQuote = new RegExp(`['"]${preloadMarker}['"]`, 'g')
4949

5050
const dynamicImportPrefixRE = /import\s*\(/
5151

@@ -63,13 +63,9 @@ function indexOfMatchInSlice(
6363
reg: RegExp,
6464
pos: number = 0,
6565
): number {
66-
if (pos !== 0) {
67-
str = str.slice(pos)
68-
}
69-
70-
const matcher = str.match(reg)
71-
72-
return matcher?.index !== undefined ? matcher.index + pos : -1
66+
reg.lastIndex = pos
67+
const result = reg.exec(str)
68+
return result?.index ?? -1
7369
}
7470

7571
/**
@@ -351,7 +347,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
351347
if (url !== specifier) {
352348
if (
353349
depsOptimizer.isOptimizedDepFile(resolvedId) &&
354-
!resolvedId.match(optimizedDepChunkRE)
350+
!optimizedDepChunkRE.test(resolvedId)
355351
) {
356352
const file = cleanUrl(resolvedId) // Remove ?v={hash}
357353

@@ -368,7 +364,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
368364
// Non-entry dynamic imports from dependencies will reach here as there isn't
369365
// optimize info for them, but they don't need es interop. If the request isn't
370366
// a dynamic import, then it is an internal Vite error
371-
if (!file.match(optimizedDepDynamicRE)) {
367+
if (!optimizedDepDynamicRE.test(file)) {
372368
config.logger.error(
373369
colors.red(
374370
`Vite Error, ${url} optimized info should be defined`,

packages/vite/src/node/plugins/resolve.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
263263
// Inject the current browserHash version if the path doesn't have one
264264
if (
265265
!resolveOptions.isBuild &&
266-
!normalizedFsPath.match(DEP_VERSION_RE)
266+
!DEP_VERSION_RE.test(normalizedFsPath)
267267
) {
268268
const browserHash = optimizedDepInfoFromFile(
269269
depsOptimizer.metadata,
@@ -501,7 +501,7 @@ function ensureVersionQuery(
501501
// file path after symlinks resolution
502502
const isNodeModule = isInNodeModules(id) || isInNodeModules(resolved)
503503

504-
if (isNodeModule && !resolved.match(DEP_VERSION_RE)) {
504+
if (isNodeModule && !DEP_VERSION_RE.test(resolved)) {
505505
const versionHash = depsOptimizer.metadata.browserHash
506506
if (versionHash && isOptimizable(resolved, depsOptimizer.options)) {
507507
resolved = injectQuery(resolved, `v=${versionHash}`)

packages/vite/src/node/plugins/worker.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,8 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
379379
}
380380
)
381381
}
382-
if (code.match(workerAssetUrlRE)) {
382+
workerAssetUrlRE.lastIndex = 0
383+
if (workerAssetUrlRE.test(code)) {
383384
const toRelativeRuntime = createToImportMetaURLBasedRelativeRuntime(
384385
outputOptions.format,
385386
config.isWorker,

packages/vite/src/node/plugins/workerImportMetaUrl.ts

+8-13
Original file line numberDiff line numberDiff line change
@@ -137,31 +137,26 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
137137
let s: MagicString | undefined
138138
const cleanString = stripLiteral(code)
139139
const workerImportMetaUrlRE =
140-
/\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/g
140+
// eslint-disable-next-line regexp/no-unused-capturing-group -- https://git.1-hub.cnota-meshi/eslint-plugin-regexp/issues/675
141+
/\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/dg
141142

142143
let match: RegExpExecArray | null
143144
while ((match = workerImportMetaUrlRE.exec(cleanString))) {
144-
const { 0: allExp, 1: exp, 2: emptyUrl, index } = match
145-
const urlIndex = allExp.indexOf(exp) + index
145+
const [[, endIndex], [expStart, expEnd], [urlStart, urlEnd]] =
146+
match.indices!
146147

147-
const urlStart = cleanString.indexOf(emptyUrl, index)
148-
const urlEnd = urlStart + emptyUrl.length
149148
const rawUrl = code.slice(urlStart, urlEnd)
150149

151150
// potential dynamic template string
152151
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
153152
this.error(
154153
`\`new URL(url, import.meta.url)\` is not supported in dynamic template string.`,
155-
urlIndex,
154+
expStart,
156155
)
157156
}
158157

159158
s ||= new MagicString(code)
160-
const workerType = getWorkerType(
161-
code,
162-
cleanString,
163-
index + allExp.length,
164-
)
159+
const workerType = getWorkerType(code, cleanString, endIndex)
165160
const url = rawUrl.slice(1, -1)
166161
let file: string | undefined
167162
if (url[0] === '.') {
@@ -190,8 +185,8 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
190185
builtUrl = injectQuery(builtUrl, `type=${workerType}`)
191186
}
192187
s.update(
193-
urlIndex,
194-
urlIndex + exp.length,
188+
expStart,
189+
expEnd,
195190
// add `'' +` to skip vite:asset-import-meta-url plugin
196191
`new URL('' + ${JSON.stringify(builtUrl)}, import.meta.url)`,
197192
)

packages/vite/src/node/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ export function fsPathFromId(id: string): string {
235235
const fsPath = normalizePath(
236236
id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id,
237237
)
238-
return fsPath[0] === '/' || fsPath.match(VOLUME_RE) ? fsPath : `/${fsPath}`
238+
return fsPath[0] === '/' || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`
239239
}
240240

241241
export function fsPathFromUrl(url: string): string {

packages/vite/src/shared/hmr.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ export class HMRClient {
200200
}
201201

202202
protected warnFailedUpdate(err: Error, path: string | string[]): void {
203-
if (!err.message.match('fetch')) {
203+
if (!err.message.includes('fetch')) {
204204
this.logger.error(err)
205205
}
206206
this.logger.error(

playground/hmr/__tests__/hmr.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ test('should render', async () => {
2323
if (!isBuild) {
2424
test('should connect', async () => {
2525
expect(browserLogs.length).toBe(3)
26-
expect(browserLogs.some((msg) => msg.match('connected'))).toBe(true)
26+
expect(browserLogs.some((msg) => msg.includes('connected'))).toBe(true)
2727
browserLogs.length = 0
2828
})
2929

playground/hmr/hmr.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ if (import.meta.hot) {
6666

6767
const cssUpdate = event.updates.find(
6868
(update) =>
69-
update.type === 'css-update' && update.path.match('global.css'),
69+
update.type === 'css-update' && update.path.includes('global.css'),
7070
)
7171
if (cssUpdate) {
7272
text(

playground/vitestGlobalSetup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function setup(): Promise<void> {
3535
return !hasWindowsUnicodeFsBug
3636
}
3737
file = file.replace(/\\/g, '/')
38-
return !file.includes('__tests__') && !file.match(/dist(\/|$)/)
38+
return !file.includes('__tests__') && !/dist(?:\/|$)/.test(file)
3939
},
4040
})
4141
.catch(async (error) => {

0 commit comments

Comments
 (0)