Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: improve regex performance #17789

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -285,4 +296,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