Skip to content

Commit

Permalink
perf: improve regex performance (#17789)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Jul 29, 2024
1 parent 796eef3 commit 952bae3
Show file tree
Hide file tree
Showing 19 changed files with 64 additions and 34 deletions.
32 changes: 32 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const require = createRequire(import.meta.url)
const pkg = require('./package.json')
const pkgVite = require('./packages/vite/package.json')

// Some rules work better with typechecking enabled, but as enabling it is slow,
// we only do so when linting in IDEs for now. If you want to lint with typechecking
// explicitly, set this to `true` manually.
const shouldTypeCheck = typeof process.env.VSCODE_PID === 'string'

export default tseslint.config(
{
ignores: [
Expand All @@ -34,6 +39,12 @@ export default tseslint.config(
parserOptions: {
sourceType: 'module',
ecmaVersion: 2022,
project: shouldTypeCheck
? [
'./packages/*/tsconfig.json',
'./packages/vite/src/*/tsconfig.json',
]
: undefined,
},
globals: {
...globals.es2021,
Expand Down Expand Up @@ -294,4 +305,25 @@ export default tseslint.config(
'@typescript-eslint/ban-ts-comment': 'off',
},
},
{
name: 'disables/typechecking',
files: [
'**/*.js',
'**/*.mjs',
'**/*.cjs',
'**/*.d.ts',
'**/*.d.cts',
'**/__tests__/**',
'docs/**',
'playground/**',
'scripts/**',
'vitest.config.ts',
'vitest.config.e2e.ts',
],
languageOptions: {
parserOptions: {
project: false,
},
},
},
)
2 changes: 1 addition & 1 deletion packages/plugin-legacy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const legacyEnvVarMarker = `__VITE_IS_LEGACY__`
const _require = createRequire(import.meta.url)

const nonLeadingHashInFileNameRE = /[^/]+\[hash(?::\d+)?\]/
const prefixedHashInFileNameRE = /\W?\[hash(:\d+)?\]/
const prefixedHashInFileNameRE = /\W?\[hash(?::\d+)?\]/

function viteLegacyPlugin(options: Options = {}): Plugin[] {
let config: ResolvedConfig
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-legacy/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"include": ["src"],
"include": ["build.config.ts", "src"],
"exclude": ["**/*.spec.ts"],
"compilerOptions": {
"outDir": "dist",
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ const __require = require;
name: 'cjs-chunk-patch',
renderChunk(code, chunk) {
if (!chunk.fileName.includes('chunks/dep-')) return
const match = code.match(/^(?:import[\s\S]*?;\s*)+/)
const match = /^(?:import[\s\S]*?;\s*)+/.exec(code)
const index = match ? match.index! + match[0].length : 0
const s = new MagicString(code)
// inject after the last `import`
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/rollupLicensePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function licensePlugin(
'\n' +
licenseText
.trim()
.replace(/(\r\n|\r)/g, '\n')
.replace(/\r\n|\r/g, '\n')
.split('\n')
.map((line) => `> ${line}`)
.join('\n') +
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/optimizer/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export function expandGlobIds(id: string, config: ResolvedConfig): string[] {
// `filePath`: "./dist/glob/foo-browser/foo.js"
// we need to revert the file path back to the export key by
// matching value regex and replacing the capture groups to the key
const matched = slash(filePath).match(exportsValueGlobRe)
const matched = exportsValueGlobRe.exec(slash(filePath))
// `matched`: [..., 'foo', 'foo']
if (matched) {
let allGlobSame = matched.length === 2
Expand Down
8 changes: 4 additions & 4 deletions packages/vite/src/node/optimizer/scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,10 @@ function esbuildScanPlugin(
let scriptId = 0
const matches = raw.matchAll(scriptRE)
for (const [, openTag, content] of matches) {
const typeMatch = openTag.match(typeRE)
const typeMatch = typeRE.exec(openTag)
const type =
typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3])
const langMatch = openTag.match(langRE)
const langMatch = langRE.exec(openTag)
const lang =
langMatch && (langMatch[1] || langMatch[2] || langMatch[3])
// skip non type module script
Expand All @@ -440,7 +440,7 @@ function esbuildScanPlugin(
} else if (p.endsWith('.astro')) {
loader = 'ts'
}
const srcMatch = openTag.match(srcRE)
const srcMatch = srcRE.exec(openTag)
if (srcMatch) {
const src = srcMatch[1] || srcMatch[2] || srcMatch[3]
js += `import ${JSON.stringify(src)}\n`
Expand Down Expand Up @@ -480,7 +480,7 @@ function esbuildScanPlugin(

const virtualModulePath = JSON.stringify(virtualModulePrefix + key)

const contextMatch = openTag.match(contextRE)
const contextMatch = contextRE.exec(openTag)
const context =
contextMatch &&
(contextMatch[1] || contextMatch[2] || contextMatch[3])
Expand Down
8 changes: 4 additions & 4 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ const inlineCSSRE = /[?&]inline-css\b/
const styleAttrRE = /[?&]style-attr\b/
const functionCallRE = /^[A-Z_][\w-]*\(/i
const transformOnlyRE = /[?&]transform-only\b/
const nonEscapedDoubleQuoteRe = /(?<!\\)(")/g
const nonEscapedDoubleQuoteRe = /(?<!\\)"/g

const cssBundleName = 'style.css'

Expand Down Expand Up @@ -1223,7 +1223,7 @@ async function compileCSS(
// crawl them in order to register watch dependencies.
const needInlineImport = code.includes('@import')
const hasUrl = cssUrlRE.test(code) || cssImageSetRE.test(code)
const lang = id.match(CSS_LANGS_RE)?.[1] as CssLang | undefined
const lang = CSS_LANGS_RE.exec(id)?.[1] as CssLang | undefined
const postcssConfig = await resolvePostcssConfig(config)

// 1. plain css that needs no processing
Expand Down Expand Up @@ -1295,7 +1295,7 @@ async function compileCSS(
},
async load(id) {
const code = await fs.promises.readFile(id, 'utf-8')
const lang = id.match(CSS_LANGS_RE)?.[1] as CssLang | undefined
const lang = CSS_LANGS_RE.exec(id)?.[1] as CssLang | undefined
if (isPreProcessor(lang)) {
const result = await compileCSSPreprocessors(
id,
Expand Down Expand Up @@ -2892,7 +2892,7 @@ export const convertTargets = (
const targets: LightningCSSOptions['targets'] = {}

const entriesWithoutES = arraify(esbuildTarget).flatMap((e) => {
const match = e.match(esRE)
const match = esRE.exec(e)
if (!match) return e
const year = Number(match[1])
if (!esMap[year]) throw new Error(`Unsupported target "${e}"`)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/dataUri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function dataURIPlugin(): Plugin {
return
}

const match = uri.pathname.match(dataUriRE)
const match = dataUriRE.exec(uri.pathname)
if (!match) {
return
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const debug = createDebugger('vite:esbuild')
// IIFE content looks like `var MyLib = function() {`.
// Spaces are removed and parameters are mangled when minified
const IIFE_BEGIN_RE =
/(const|var)\s+\S+\s*=\s*function\([^()]*\)\s*\{\s*"use strict";/
/(?:const|var)\s+\S+\s*=\s*function\([^()]*\)\s*\{\s*"use strict";/

const validExtensionRE = /\.\w+$/
const jsxExtensionsRE = /\.(?:j|t)sx\b/
Expand Down
8 changes: 4 additions & 4 deletions packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface ScriptAssetsUrl {
}

const htmlProxyRE =
/\?html-proxy=?(?:&inline-css)?(?:&style-attr)?&index=(\d+)\.(js|css)$/
/\?html-proxy=?(?:&inline-css)?(?:&style-attr)?&index=(\d+)\.(?:js|css)$/
const isHtmlProxyRE = /\?html-proxy\b/

const inlineCSSRE = /__VITE_INLINE_CSS__([a-z\d]{8}_\d+)__/g
Expand Down Expand Up @@ -99,7 +99,7 @@ export function htmlInlineProxyPlugin(config: ResolvedConfig): Plugin {
},

load(id) {
const proxyMatch = id.match(htmlProxyRE)
const proxyMatch = htmlProxyRE.exec(id)
if (proxyMatch) {
const index = Number(proxyMatch[1])
const file = cleanUrl(id)
Expand Down Expand Up @@ -237,7 +237,7 @@ export function overwriteAttrValue(
sourceCodeLocation.startOffset,
sourceCodeLocation.endOffset,
)
const valueStart = srcString.match(attrValueStartRE)
const valueStart = attrValueStartRE.exec(srcString)
if (!valueStart) {
// overwrite attr value can only be called for a well-defined value
throw new Error(
Expand Down Expand Up @@ -1354,7 +1354,7 @@ export async function applyHtmlTransforms(
return html
}

const importRE = /\bimport\s*("[^"]*[^\\]"|'[^']*[^\\]');*/g
const importRE = /\bimport\s*(?:"[^"]*[^\\]"|'[^']*[^\\]');*/g
const commentRE = /\/\*[\s\S]*?\*\/|\/\/.*$/gm
function isEntirelyImport(code: string) {
// only consider "side-effect" imports, which match <script type=module> semantics exactly
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
// (e.g. vue blocks), inherit importer's version query
// do not do this for unknown type imports, otherwise the appended
// query can break 3rd party plugin's extension checks.
const versionMatch = importer.match(DEP_VERSION_RE)
const versionMatch = DEP_VERSION_RE.exec(importer)
if (versionMatch) {
url = injectQuery(url, versionMatch[1])
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
* ^
*/
if (match[3]) {
let names = match[4].match(/\.([^.?]+)/)?.[1] || ''
let names = /\.([^.?]+)/.exec(match[4])?.[1] || ''
// avoid `default` keyword error
if (names === 'default') {
names = 'default: __vite_default__'
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/optimizedDeps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin {
if (depsOptimizer?.isOptimizedDepFile(id)) {
const metadata = depsOptimizer.metadata
const file = cleanUrl(id)
const versionMatch = id.match(DEP_VERSION_RE)
const versionMatch = DEP_VERSION_RE.exec(file)
const browserHash = versionMatch
? versionMatch[1].split('=')[1]
: undefined
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ export function tryNodeResolve(
const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options

// check for deep import, e.g. "my-lib/foo"
const deepMatch = id.match(deepImportRE)
const deepMatch = deepImportRE.exec(id)
// package name doesn't include postfixes
// trim them to support importing package with queries (e.g. `import css from 'normalize.css?inline'`)
const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : cleanUrl(id)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/middlewares/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function buildErrorMessage(

function cleanStack(stack: string) {
return stack
.split(/\n/g)
.split(/\n/)
.filter((l) => /^\s*at/.test(l))
.join('\n')
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/ssr/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ async function ssrTransformScript(
const declaredConst = new Set<string>()

// hoist at the start of the file, after the hashbang
const hoistIndex = code.match(hashbangRE)?.[0].length ?? 0
const hoistIndex = hashbangRE.exec(code)?.[0].length ?? 0

function defineImport(
index: number,
Expand Down
12 changes: 6 additions & 6 deletions packages/vite/src/node/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const createFilter = _createFilter as (

const replaceSlashOrColonRE = /[/:]/g
const replaceDotRE = /\./g
const replaceNestedIdRE = /(\s*>\s*)/g
const replaceNestedIdRE = /\s*>\s*/g
const replaceHashRE = /#/g
export const flattenId = (id: string): string => {
const flatId = limitFlattenIdLength(
Expand Down Expand Up @@ -558,7 +558,7 @@ export function emptyDir(dir: string, skip?: string[]): void {
if (skip?.length) {
for (const file of skip) {
if (path.dirname(file) !== '.') {
const matched = file.match(splitFirstDirRE)
const matched = splitFirstDirRE.exec(file)
if (matched) {
nested ??= new Map()
const [, nestedDir, skipPath] = matched
Expand Down Expand Up @@ -656,7 +656,7 @@ function windowsMappedRealpathSync(path: string) {
}
return realPath
}
const parseNetUseRE = /^(\w+)? +(\w:) +([^ ]+)\s/
const parseNetUseRE = /^\w* +(\w:) +([^ ]+)\s/
let firstSafeRealPathSyncRun = false

function windowsSafeRealPathSync(path: string): string {
Expand Down Expand Up @@ -691,8 +691,8 @@ function optimizeSafeRealPathSync() {
// OK Y: \\NETWORKA\Foo Microsoft Windows Network
// OK Z: \\NETWORKA\Bar Microsoft Windows Network
for (const line of lines) {
const m = line.match(parseNetUseRE)
if (m) windowsNetworkMap.set(m[3], m[2])
const m = parseNetUseRE.exec(line)
if (m) windowsNetworkMap.set(m[2], m[1])
}
if (windowsNetworkMap.size === 0) {
safeRealpathSync = fs.realpathSync.native
Expand Down Expand Up @@ -724,7 +724,7 @@ interface ImageCandidate {
url: string
descriptor: string
}
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
const escapedSpaceCharacters = /(?: |\\t|\\n|\\f|\\r)+/g
const imageSetUrlRE = /^(?:[\w\-]+\(.*?\)|'.*?'|".*?"|\S*)/
function joinSrcset(ret: ImageCandidate[]) {
return ret
Expand Down
4 changes: 1 addition & 3 deletions packages/vite/src/runtime/moduleCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ export class ModuleCacheMap extends Map<string, ModuleCache> {
const mod = this.get(moduleId)
if (mod.map) return mod.map
if (!mod.meta || !('code' in mod.meta)) return null
const mapString = mod.meta.code.match(
VITE_RUNTIME_SOURCEMAPPING_REGEXP,
)?.[1]
const mapString = VITE_RUNTIME_SOURCEMAPPING_REGEXP.exec(mod.meta.code)?.[1]
if (!mapString) return null
const baseFile = mod.meta.file || moduleId.split('?')[0]
mod.map = new DecodedMap(JSON.parse(decodeBase64(mapString)), baseFile)
Expand Down

0 comments on commit 952bae3

Please sign in to comment.