perf: improve regexp performance by using non-capturing groups (#58551)

This commit is contained in:
Anthony Fu 2025-07-01 07:12:49 +09:00 committed by GitHub
parent 5fd65f3189
commit e58dde511c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 12 additions and 12 deletions

View File

@ -9542,7 +9542,7 @@ const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question];
const commonPackageFolders: readonly string[] = ["node_modules", "bower_components", "jspm_packages"];
const implicitExcludePathRegexPattern = `(?!(${commonPackageFolders.join("|")})(/|$))`;
const implicitExcludePathRegexPattern = `(?!(?:${commonPackageFolders.join("|")})(?:/|$))`;
/** @internal */
export interface WildcardMatcher {
@ -9558,12 +9558,12 @@ const filesMatcher: WildcardMatcher = {
* [^./] # matches everything up to the first . character (excluding directory separators)
* (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
*/
singleAsteriskRegexFragment: "([^./]|(\\.(?!min\\.js$))?)*",
singleAsteriskRegexFragment: "(?:[^./]|(?:\\.(?!min\\.js$))?)*",
/**
* Regex for the ** wildcard. Matches any number of subdirectories. When used for including
* files or directories, does not match subdirectories that start with a . character
*/
doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
doubleAsteriskRegexFragment: `(?:/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
replaceWildcardCharacter: match => replaceWildcardCharacter(match, filesMatcher.singleAsteriskRegexFragment),
};
@ -9573,13 +9573,13 @@ const directoriesMatcher: WildcardMatcher = {
* Regex for the ** wildcard. Matches any number of subdirectories. When used for including
* files or directories, does not match subdirectories that start with a . character
*/
doubleAsteriskRegexFragment: `(/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
doubleAsteriskRegexFragment: `(?:/${implicitExcludePathRegexPattern}[^/.][^/]*)*?`,
replaceWildcardCharacter: match => replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment),
};
const excludeMatcher: WildcardMatcher = {
singleAsteriskRegexFragment: "[^/]*",
doubleAsteriskRegexFragment: "(/.+?)?",
doubleAsteriskRegexFragment: "(?:/.+?)?",
replaceWildcardCharacter: match => replaceWildcardCharacter(match, excludeMatcher.singleAsteriskRegexFragment),
};
@ -9596,10 +9596,10 @@ export function getRegularExpressionForWildcard(specs: readonly string[] | undef
return undefined;
}
const pattern = patterns.map(pattern => `(${pattern})`).join("|");
const pattern = patterns.map(pattern => `(?:${pattern})`).join("|");
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
const terminator = usage === "exclude" ? "($|/)" : "$";
return `^(${pattern})${terminator}`;
const terminator = usage === "exclude" ? "(?:$|/)" : "$";
return `^(?:${pattern})${terminator}`;
}
/** @internal */
@ -9624,7 +9624,7 @@ export function isImplicitGlob(lastPathComponent: string): boolean {
/** @internal */
export function getPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined {
const pattern = spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage]);
return pattern && `^(${pattern})${usage === "exclude" ? "($|/)" : "$"}`;
return pattern && `^(?:${pattern})${usage === "exclude" ? "(?:$|/)" : "$"}`;
}
/** @internal */
@ -9657,7 +9657,7 @@ export function getSubPatternFromSpec(
}
else {
if (usage === "directories") {
subpattern += "(";
subpattern += "(?:";
optionalCount++;
}
@ -9671,7 +9671,7 @@ export function getSubPatternFromSpec(
// appear first in a component. Dotted directories and files can be included explicitly
// like so: **/.*/.*
if (component.charCodeAt(0) === CharacterCodes.asterisk) {
componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?";
componentPattern += "(?:[^./]" + singleAsteriskRegexFragment + ")?";
component = component.substr(1);
}
else if (component.charCodeAt(0) === CharacterCodes.question) {

View File

@ -436,7 +436,7 @@ export function getMatchedIncludeSpec(program: Program, fileName: string): strin
const index = findIndex(configFile?.configFileSpecs?.validatedIncludeSpecs, includeSpec => {
if (isJsonFile && !endsWith(includeSpec, Extension.Json)) return false;
const pattern = getPatternFromSpec(includeSpec, basePath, "files");
return !!pattern && getRegexFromPattern(`(${pattern})$`, useCaseSensitiveFileNames).test(fileName);
return !!pattern && getRegexFromPattern(`(?:${pattern})$`, useCaseSensitiveFileNames).test(fileName);
});
return index !== -1 ? configFile.configFileSpecs.validatedIncludeSpecsBeforeSubstitution![index] : undefined;
}