refactor: regexps (#20254)

This commit is contained in:
Alexander Akait 2025-12-19 16:17:52 +03:00 committed by GitHub
parent 24e3c2d2c9
commit 89888bc949
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 94 additions and 98 deletions

View File

@ -125,7 +125,7 @@ const doCompileAndReplace = (args, prefix, callback) => {
stdout
.replace(/[\r?\n]*$/, "")
.replace(
/\d\d\d\d-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[0-1])/g,
/\d\d\d\d-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])/g,
"XXXX-XX-XX"
)
.replace(/([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/g, "XXXX:XX:XX")

View File

@ -14,7 +14,7 @@ const path = require("path");
function lessStrict(regExpStr) {
regExpStr = regExpStr
.replace(/node_modules/g, "(node_modules|~)")
.replace(/(\\\/|\\\\)/g, "[\\/\\\\]");
.replace(/\\\/|\\\\/g, "[\\/\\\\]");
return regExpStr;
}

View File

@ -416,7 +416,7 @@ class CleanPlugin {
const currentAssets = new Map();
const now = Date.now();
for (const asset of Object.keys(compilation.assets)) {
if (/^[A-Za-z]:\\|^\/|^\\\\/.test(asset)) continue;
if (/^[a-z]:\\|^\/|^\\\\/i.test(asset)) continue;
let normalizedAsset;
let newNormalizedAsset = asset.replace(/\\/g, "/");
do {

View File

@ -509,7 +509,7 @@ class ContextModule extends Module {
for (const dep of dependencies) {
let chunkName = this.options.chunkName;
if (chunkName) {
if (!/\[(index|request)\]/.test(chunkName)) {
if (!/\[(?:index|request)\]/.test(chunkName)) {
chunkName += "[index]";
}
chunkName = chunkName.replace(/\[index\]/g, `${index++}`);

View File

@ -165,7 +165,7 @@ class ContextModuleFactory extends ModuleFactory {
loadersRequest = loadersRequest
.slice(i)
.replace(/!+$/, "")
.replace(/!!+/g, "!");
.replace(/!{2,}/g, "!");
loaders = loadersRequest === "" ? [] : loadersRequest.split("!");
resource = request.slice(idx + 1);
} else {

View File

@ -25,9 +25,9 @@ const DEFAULT_OPTIONS = {
};
// Regex for parsing .env files
// ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L32
// ported from https://github.com/motdotla/dotenv/blob/master/lib/main.js#L49
const LINE =
/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
/^\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?$/gm;
const PLUGIN_NAME = "DotenvPlugin";
@ -60,7 +60,7 @@ function parse(src) {
let lines = src.toString();
// Convert line breaks to same format
lines = lines.replace(/\r\n?/gm, "\n");
lines = lines.replace(/\r\n?/g, "\n");
let match;
while ((match = LINE.exec(lines)) !== null) {
@ -112,7 +112,7 @@ function _resolveEscapeSequences(value) {
function expandValue(value, processEnv, runningParsed) {
const env = { ...runningParsed, ...processEnv }; // process.env wins
const regex = /(?<!\\)\$\{([^{}]+)\}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
const regex = /(?<!\\)\$\{([^{}]+)\}|(?<!\\)\$([a-z_]\w*)/gi;
let result = value;
let match;

View File

@ -1889,7 +1889,7 @@ class FileSystemInfo {
for (const modulePath of module.paths) {
if (childPath.startsWith(modulePath)) {
const subPath = childPath.slice(modulePath.length + 1);
const packageMatch = /^(@[^\\/]+[\\/])[^\\/]+/.exec(
const packageMatch = /^@[^\\/]+[\\/][^\\/]+/.exec(
subPath
);
if (packageMatch) {

View File

@ -42,7 +42,9 @@ const extname = (filename) => {
const split = replaced.split(".");
const last = split.pop();
if (!last) return "";
return last && /^(gz|br|map)$/i.test(last) ? `${split.pop()}.${last}` : last;
return last && /^(?:gz|br|map)$/i.test(last)
? `${split.pop()}.${last}`
: last;
};
class ManifestPlugin {

View File

@ -115,7 +115,7 @@ const lazyObject = (obj) => {
return newObj;
};
const SQUARE_BRACKET_TAG_REGEXP = /\[\\*([\w-]+)\\*\]/gi;
const SQUARE_BRACKET_TAG_REGEXP = /\[\\*([\w-]+)\\*\]/g;
/**
* @typedef {object} ModuleFilenameTemplateContext
* @property {string} identifier the identifier of the module

View File

@ -123,7 +123,7 @@ const getExtractSourceMap = memoize(() => require("./util/extractSourceMap"));
const getValidate = memoize(() => require("schema-utils").validate);
const ABSOLUTE_PATH_REGEX = /^([a-zA-Z]:\\|\\\\|\/)/;
const ABSOLUTE_PATH_REGEX = /^(?:[a-z]:\\|\\\\|\/)/i;
/**
* @typedef {object} LoaderItem
@ -360,7 +360,7 @@ class NormalModule extends Module {
/** @type {NormalModuleCreateData['rawRequest']} */
this.rawRequest = rawRequest;
/** @type {boolean} */
this.binary = /^(asset|webassembly)\b/.test(type);
this.binary = /^(?:asset|webassembly)\b/.test(type);
/** @type {NormalModuleCreateData['parser'] | undefined} */
this.parser = parser;
/** @type {NormalModuleCreateData['parserOptions']} */

View File

@ -853,7 +853,7 @@ class NormalModuleFactory extends ModuleFactory {
* @param {string} context context
*/
const defaultResolve = (context) => {
if (/^($|\?)/.test(unresolvedResource)) {
if (/^(?:$|\?)/.test(unresolvedResource)) {
resourceData = {
...cacheParseResource(unresolvedResource),
resource: unresolvedResource,
@ -1185,7 +1185,7 @@ Add the extension to the request.`
(err, resolvedResource) => {
if (!err && resolvedResource) {
let hint = "";
const match = /(\.[^.]+)(\?|$)/.exec(unresolvedResource);
const match = /\.[^.]+(?:\?|$)/.exec(unresolvedResource);
if (match) {
const fixedRequest = unresolvedResource.replace(
/(\.[^.]+)(\?|$)/,

View File

@ -111,6 +111,8 @@ const TREE_DEPENDENCIES = {
[RuntimeGlobals.shareScopeMap]: [RuntimeGlobals.hasOwnProperty]
};
const FULLHASH_REGEXP = /\[(?:full)?hash(?::\d+)?\]/;
const PLUGIN_NAME = "RuntimePlugin";
class RuntimePlugin {
@ -266,7 +268,7 @@ class RuntimePlugin {
if (
typeof publicPath !== "string" ||
/\[(full)?hash\]/.test(publicPath)
/\[(?:full)?hash\]/.test(publicPath)
) {
module.fullHash = true;
}
@ -314,9 +316,7 @@ class RuntimePlugin {
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
if (
typeof compilation.outputOptions.chunkFilename === "string" &&
/\[(full)?hash(:\d+)?\]/.test(
compilation.outputOptions.chunkFilename
)
FULLHASH_REGEXP.test(compilation.outputOptions.chunkFilename)
) {
set.add(RuntimeGlobals.getFullHash);
}
@ -342,9 +342,7 @@ class RuntimePlugin {
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
if (
typeof compilation.outputOptions.cssChunkFilename === "string" &&
/\[(full)?hash(:\d+)?\]/.test(
compilation.outputOptions.cssChunkFilename
)
FULLHASH_REGEXP.test(compilation.outputOptions.cssChunkFilename)
) {
set.add(RuntimeGlobals.getFullHash);
}
@ -374,7 +372,7 @@ class RuntimePlugin {
.for(RuntimeGlobals.getChunkUpdateScriptFilename)
.tap(PLUGIN_NAME, (chunk, set) => {
if (
/\[(full)?hash(:\d+)?\]/.test(
FULLHASH_REGEXP.test(
compilation.outputOptions.hotUpdateChunkFilename
)
) {
@ -396,7 +394,7 @@ class RuntimePlugin {
.for(RuntimeGlobals.getUpdateManifestFilename)
.tap(PLUGIN_NAME, (chunk, set) => {
if (
/\[(full)?hash(:\d+)?\]/.test(
FULLHASH_REGEXP.test(
compilation.outputOptions.hotUpdateMainFilename
)
) {

View File

@ -84,7 +84,7 @@ function getGlobalObject(definition) {
// iife
// call expression
// expression in parentheses
/^([_\p{L}][_0-9\p{L}]*)?\(.*\)$/iu.test(trimmed)
/^(?:[_\p{L}][_0-9\p{L}]*)?\(.*\)$/iu.test(trimmed)
) {
return trimmed;
}

View File

@ -51,9 +51,9 @@ const validate = createSchemaValidation(
*/
const METACHARACTERS_REGEXP = /[-[\]\\/{}()*+?.^$|]/g;
const CONTENT_HASH_DETECT_REGEXP = /\[contenthash(:\w+)?\]/;
const CONTENT_HASH_DETECT_REGEXP = /\[contenthash(?::\w+)?\]/;
const CSS_AND_JS_MODULE_EXTENSIONS_REGEXP = /\.((c|m)?js|css)($|\?)/i;
const CSS_EXTENSION_DETECT_REGEXP = /\.css($|\?)/i;
const CSS_EXTENSION_DETECT_REGEXP = /\.css(?:$|\?)/i;
const MAP_URL_COMMENT_REGEXP = /\[map\]/g;
const URL_COMMENT_REGEXP = /\[url\]/g;
const URL_FORMATTING_REGEXP = /^\n\/\/(.*)$/;
@ -310,7 +310,7 @@ class SourceMapDevToolPlugin {
if (
typeof module === "string" &&
/^(data|https?):/.test(module)
/^(?:data|https?):/.test(module)
) {
moduleToSourceNameMapping.set(module, module);
continue;

View File

@ -36,10 +36,10 @@ const NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS =
const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g;
const INDENT_MULTILINE_REGEX = /^\t/gm;
const LINE_SEPARATOR_REGEX = /\r?\n/g;
const IDENTIFIER_NAME_REPLACE_REGEX = /^([^a-zA-Z$_])/;
const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$]+/g;
const IDENTIFIER_NAME_REPLACE_REGEX = /^([^a-z$_])/i;
const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-z0-9$]+/gi;
const COMMENT_END_REGEX = /\*\//g;
const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g;
const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-z0-9_!§$()=\-^°]+/gi;
const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
/**

View File

@ -18,7 +18,7 @@ const { parseResource } = require("./util/identifier");
/** @typedef {import("./Compilation").PathData} PathData */
/** @typedef {import("./Compiler")} Compiler */
const REGEXP = /\[\\*([\w:]+)\\*\]/gi;
const REGEXP = /\[\\*([\w:]+)\\*\]/g;
/** @type {PathData["prepareId"]} */
const prepareId = (id) => {
@ -32,7 +32,7 @@ const prepareId = (id) => {
} + "").replace(/(^[.-]|[^a-zA-Z0-9_-])+/g, "_") + "`;
}
return id.replace(/(^[.-]|[^a-zA-Z0-9_-])+/g, "_");
return id.replace(/(^[.-]|[^a-z0-9_-])+/gi, "_");
};
/**

View File

@ -129,8 +129,8 @@ class WebpackOptionsApply extends OptionsApply {
"module",
({ request, dependencyType, contextInfo }, callback) => {
if (
/\.css(\?|$)/.test(contextInfo.issuer) &&
/^(\/\/|https?:\/\/|#)/.test(request)
/\.css(?:\?|$)/.test(contextInfo.issuer) &&
/^(?:\/\/|https?:\/\/|#)/.test(request)
) {
if (dependencyType === "url") {
return callback(null, `asset ${request}`);
@ -156,7 +156,7 @@ class WebpackOptionsApply extends OptionsApply {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin(type, ({ request, dependencyType }, callback) => {
if (/^(\/\/|https?:\/\/|#|std:|jsr:|npm:)/.test(request)) {
if (/^(?:\/\/|https?:\/\/|#|std:|jsr:|npm:)/.test(request)) {
if (dependencyType === "url") {
return callback(null, `asset ${request}`);
} else if (
@ -166,7 +166,7 @@ class WebpackOptionsApply extends OptionsApply {
options.experiments.css
) {
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:|jsr:|npm:)/.test(request)) {
} else if (/^(?:\/\/|https?:\/\/|std:|jsr:|npm:)/.test(request)) {
return callback(null, `${type} ${request}`);
}
}

View File

@ -621,7 +621,7 @@ const parseValueForArgumentConfig = (argConfig, value) => {
break;
case "number":
if (typeof value === "number") return value;
if (typeof value === "string" && /^[+-]?\d*(\.\d*)[eE]\d+$/) {
if (typeof value === "string" && /^[+-]?\d*(\.\d*)e\d+$/i) {
const n = Number(value);
if (!Number.isNaN(n)) return n;
}

View File

@ -1588,7 +1588,7 @@ const applyOutputDefaults = (
"policyName",
() =>
/** @type {NonNullable<Output["uniqueName"]>} */
(output.uniqueName).replace(/[^a-zA-Z0-9\-#=_/@.%]+/g, "_") || "webpack"
(output.uniqueName).replace(/[^a-z0-9\-#=_/@.%]+/gi, "_") || "webpack"
);
D(trustedTypes, "onPolicyCreationFailure", "stop");
}

View File

@ -56,11 +56,11 @@ const CC_EQUAL = "=".charCodeAt(0);
const STRING_MULTILINE = /\\[\n\r\f]/g;
// https://www.w3.org/TR/css-syntax-3/#whitespace
const TRIM_WHITE_SPACES = /(^[ \t\n\r\f]*|[ \t\n\r\f]*$)/g;
const UNESCAPE = /\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g;
const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
const COMPOSES_PROPERTY = /^(composes|compose-with)$/i;
const IS_MODULES = /\.module(s)?\.[^.]+$/i;
const UNESCAPE = /\\([0-9a-f]{1,6}[ \t\n\r\f]?|[\s\S])/gi;
const IMAGE_SET_FUNCTION = /^(?:-\w+-)?image-set$/i;
const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(?:-\w+-)?keyframes$/;
const COMPOSES_PROPERTY = /^(?:composes|compose-with)$/i;
const IS_MODULES = /\.modules?\.[^.]+$/i;
const CSS_COMMENT = /\/\*((?!\*\/).*?)\*\//g;
/**
@ -123,8 +123,7 @@ const normalizeUrl = (str, isString) => {
return str;
};
// eslint-disable-next-line no-useless-escape
const regexSingleEscape = /[ -,.\/:-@[\]\^`{-~]/;
const regexSingleEscape = /[ -,./:-@[\]^`{-~]/;
const regexExcessiveSpaces =
/(^|\\+)?(\\[A-F0-9]{1,6})\u0020(?![a-fA-F0-9\u0020])/g;
@ -141,8 +140,7 @@ const escapeIdentifier = (str) => {
let value;
// eslint-disable-next-line no-control-regex
if (/[\t\n\f\r\u000B]/.test(character)) {
if (/[\t\n\f\r\v]/.test(character)) {
const codePoint = character.charCodeAt(0);
value = `\\${codePoint.toString(16).toUpperCase()} `;

View File

@ -60,7 +60,7 @@ const getLocalIdent = (local, module, chunkGraph, runtimeTemplate) => {
let localIdentHash = "";
if (/\[(fullhash|hash)\]/.test(localIdentName)) {
if (/\[(?:fullhash|hash)\]/.test(localIdentName)) {
const hashSalt = generator.options.localIdentHashSalt;
const hashDigest =
/** @type {string} */
@ -113,8 +113,8 @@ const getLocalIdent = (local, module, chunkGraph, runtimeTemplate) => {
if (typeof id !== "string") return id;
return id
.replace(/^([.-]|[^a-zA-Z0-9_-])+/, "")
.replace(/[^a-zA-Z0-9_-]+/g, "_");
.replace(/^([.-]|[^a-z0-9_-])+/i, "")
.replace(/[^a-z0-9_-]+/gi, "_");
},
filename: relativeResourcePath,
hash: localIdentHash,
@ -135,7 +135,7 @@ const getLocalIdent = (local, module, chunkGraph, runtimeTemplate) => {
}
// Protect the first character from unsupported values
return localIdent.replace(/^((-?[0-9])|--)/, "_$1");
return localIdent.replace(/^((-?\d)|--)/, "_$1");
};
// 0 - replace, 1 - replace, 2 - append, 2 - once

View File

@ -56,7 +56,7 @@ const avoidNumber = (str) => {
* @returns {string} id representation
*/
const requestToId = (request) =>
request.replace(/^(\.\.?\/)+/, "").replace(/(^[.-]|[^a-zA-Z0-9_-])+/g, "_");
request.replace(/^(\.\.?\/)+/, "").replace(/(^[.-]|[^a-z0-9_-])+/gi, "_");
/**
* @param {string} string the string

View File

@ -4891,7 +4891,7 @@ class JavascriptParser extends Parser {
]).some(
(comment) =>
comment.type === "Block" &&
/^\s*(#|@)__PURE__\s*$/.test(comment.value)
/^\s*(?:#|@)__PURE__\s*$/.test(comment.value)
);
if (!pureFlag) return false;
commentsStartPos = /** @type {Range} */ (expr.callee.range)[1];

View File

@ -33,7 +33,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
*/
const KEYWORD_REGEX =
/^(await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|super|switch|static|this|throw|try|true|typeof|var|void|while|with|yield)$/;
/^(?:await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|super|switch|static|this|throw|try|true|typeof|var|void|while|with|yield)$/;
const IDENTIFIER_REGEX =
/^[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*$/iu;

View File

@ -69,11 +69,11 @@ const mangleExportsInfo = (deterministic, exportsInfo, isNamespace) => {
// Can the export be mangled?
exportInfo.canMangle !== true ||
// Never rename 1 char exports
(name.length === 1 && /^[a-zA-Z0-9_$]/.test(name)) ||
(name.length === 1 && /^[a-z0-9_$]/i.test(name)) ||
// Don't rename 2 char exports in deterministic mode
(deterministic &&
name.length === 2 &&
/^[a-zA-Z_$][a-zA-Z0-9_$]|^[1-9][0-9]/.test(name)) ||
/^[a-z_$][a-z0-9_$]|^[1-9][0-9]/i.test(name)) ||
// Don't rename exports that are not provided
(avoidMangleNonProvided && exportInfo.provided !== true)
) {

View File

@ -104,9 +104,7 @@ const validate = createSchemaValidation(
* @returns {string} safe path
*/
const toSafePath = (str) =>
str
.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")
.replace(/[^a-zA-Z0-9._-]+/g, "_");
str.replace(/^[^a-z0-9]+|[^a-z0-9]+$/gi, "").replace(/[^a-z0-9._-]+/gi, "_");
/**
* @param {Buffer} content content

View File

@ -159,7 +159,7 @@ class ConsumeSharedPlugin {
};
const directFallback =
config.import &&
/^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/.test(config.import);
/^(?:\.\.?(?:\/|$)|\/|[A-Z]:|\\\\)/i.test(config.import);
return Promise.all([
new Promise(
/**
@ -215,13 +215,13 @@ class ConsumeSharedPlugin {
}
let packageName = config.packageName;
if (packageName === undefined) {
if (/^(\/|[A-Za-z]:|\\\\)/.test(request)) {
if (/^(?:\/|[A-Z]:|\\\\)/i.test(request)) {
// For relative or absolute requests we don't automatically use a packageName.
// If wished one can specify one with the packageName option.
resolve();
return;
}
const match = /^((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(request);
const match = /^(?:@[^\\/]+[\\/])?[^\\/]+/.exec(request);
if (!match) {
requiredVersionWarning(
"Unable to extract the package name from request."

View File

@ -95,13 +95,13 @@ class ProvideSharedPlugin {
/** @type {Map<string, ProvideOptions>} */
const prefixMatchProvides = new Map();
for (const [request, config] of this._provides) {
if (/^(\/|[A-Za-z]:\\|\\\\|\.\.?(\/|$))/.test(request)) {
if (/^(?:\/|[A-Z]:\\|\\\\|\.\.?(?:\/|$))/i.test(request)) {
// relative request
resolvedProvideMap.set(request, {
config,
version: config.version
});
} else if (/^(\/|[A-Za-z]:\\|\\\\)/.test(request)) {
} else if (/^(?:\/|[A-Z]:\\|\\\\)/i.test(request)) {
// absolute path
resolvedProvideMap.set(request, {
config,

View File

@ -54,7 +54,7 @@ module.exports.resolveMatchedConfigs = (compilation, configs) => {
return Promise.all(
// eslint-disable-next-line array-callback-return
configs.map(([request, config]) => {
if (/^\.\.?(\/|$)/.test(request)) {
if (/^\.\.?(?:\/|$)/.test(request)) {
// relative request
return new Promise((resolve) => {
resolver.resolve(
@ -77,7 +77,7 @@ module.exports.resolveMatchedConfigs = (compilation, configs) => {
}
);
});
} else if (/^(\/|[A-Za-z]:\\|\\\\)/.test(request)) {
} else if (/^(?:\/|[a-z]:\\|\\\\)/i.test(request)) {
// absolute path
resolved.set(request, config);
} else if (request.endsWith("/")) {

View File

@ -15,30 +15,30 @@ const { dirname, join, readJson } = require("../util/fs");
const RE_URL_GITHUB_EXTREME_SHORT = /^[^/@:.\s][^/@:\s]*\/[^@:\s]*[^/@:\s]#\S+/;
// Short url with specific protocol. eg: github:foo/bar
const RE_GIT_URL_SHORT = /^(github|gitlab|bitbucket|gist):\/?[^/.]+\/?/i;
const RE_GIT_URL_SHORT = /^(?:github|gitlab|bitbucket|gist):\/?[^/.]+\/?/i;
// Currently supported protocols
const RE_PROTOCOL =
/^((git\+)?(ssh|https?|file)|git|github|gitlab|bitbucket|gist):$/i;
/^(?:(?:git\+)?(?:ssh|https?|file)|git|github|gitlab|bitbucket|gist):$/i;
// Has custom protocol
const RE_CUSTOM_PROTOCOL = /^((git\+)?(ssh|https?|file)|git):\/\//i;
const RE_CUSTOM_PROTOCOL = /^(?:(?:git\+)?(?:ssh|https?|file)|git):\/\//i;
// Valid hash format for npm / yarn ...
const RE_URL_HASH_VERSION = /#(?:semver:)?(.+)/;
// Simple hostname validate
const RE_HOSTNAME = /^(?:[^/.]+(\.[^/]+)+|localhost)$/;
const RE_HOSTNAME = /^(?:[^/.]+(?:\.[^/]+)+|localhost)$/;
// For hostname with colon. eg: ssh://user@github.com:foo/bar
const RE_HOSTNAME_WITH_COLON =
/([^/@#:.]+(?:\.[^/@#:.]+)+|localhost):([^#/0-9]+)/;
// Reg for url without protocol
const RE_NO_PROTOCOL = /^([^/@#:.]+(?:\.[^/@#:.]+)+)/;
const RE_NO_PROTOCOL = /^[^/@#:.]+(?:\.[^/@#:.]+)+/;
// RegExp for version string
const VERSION_PATTERN_REGEXP = /^([\d^=v<>~]|[*xX]$)/;
const VERSION_PATTERN_REGEXP = /^(?:[\d^=v<>~]|[*xX]$)/;
// Specific protocol for short url without normal hostname
const PROTOCOLS_FOR_SHORT = [

View File

@ -799,7 +799,7 @@ const ERROR_PRINTERS = {
"error.file": (file, { bold }) => bold(file),
"error.moduleName": (moduleName, { bold }) =>
moduleName.includes("!")
? `${bold(moduleName.replace(/^(\s|\S)*!/, ""))} (${moduleName})`
? `${bold(moduleName.replace(/^([\s\S])*!/, ""))} (${moduleName})`
: `${bold(moduleName)}`,
"error.loc": (loc, { green }) => green(loc),
"error.message": (message, { bold, formatError }) =>

View File

@ -110,7 +110,7 @@ function findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
// Remove uncool stuff
extraInfo = extraInfo.replace(
/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g,
/\.+\/|(?:\/index)?\.[a-zA-Z0-9]{1,4}(?:$|\s|\?)|\s*\+\s*\d+\s*modules/g,
""
);

View File

@ -20,7 +20,7 @@ const preserveCamelCase = (string) => {
for (let i = 0; i < result.length; i++) {
const character = result[i];
if (isLastCharLower && /[\p{Lu}]/u.test(character)) {
if (isLastCharLower && /\p{Lu}/u.test(character)) {
result = `${result.slice(0, i)}-${result.slice(i)}`;
isLastCharLower = false;
isLastLastCharUpper = isLastCharUpper;
@ -29,7 +29,7 @@ const preserveCamelCase = (string) => {
} else if (
isLastCharUpper &&
isLastLastCharUpper &&
/[\p{Ll}]/u.test(character)
/\p{Ll}/u.test(character)
) {
result = `${result.slice(0, i - 1)}-${result.slice(i - 1)}`;
isLastLastCharUpper = isLastCharUpper;

View File

@ -6,7 +6,7 @@
const path = require("path");
const WINDOWS_ABS_PATH_REGEXP = /^[a-zA-Z]:[\\/]/;
const WINDOWS_ABS_PATH_REGEXP = /^[a-z]:[\\/]/i;
const SEGMENTS_SPLIT_REGEXP = /([|!])/;
const WINDOWS_PATH_SEPARATOR_REGEXP = /\\/g;

View File

@ -16,7 +16,7 @@ module.exports.createMagicCommentContext = () =>
codeGeneration: { strings: false, wasm: false }
});
module.exports.webpackCommentRegExp = new RegExp(
/(^|\W)webpack[A-Z]{1,}[A-Za-z]{1,}:/
/(^|\W)webpack[A-Z][A-Za-z]+:/
);
// regexp to match at least one "magic comment"

View File

@ -5,7 +5,7 @@
"use strict";
const SAFE_IDENTIFIER = /^[_a-zA-Z$][_a-zA-Z$0-9]*$/;
const SAFE_IDENTIFIER = /^[_a-z$][_a-z$0-9]*$/i;
const RESERVED_IDENTIFIER = new Set([
"break",
"case",

View File

@ -61,7 +61,7 @@ function checkSymlinkExistsAsync() {
*/
async function ensureYarnInstalledAsync() {
const semverPattern =
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/;
/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-z-][0-9a-z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-z-][0-9a-z-]*))*)?(?:\+[0-9a-z-]+(?:\.[0-9a-z-]+)*)?$/i;
let hasYarn = false;
try {
const stdout = await execGetOutput("yarn", ["-v"], "Check yarn version");

View File

@ -277,7 +277,7 @@ function buildConfiguration(
? path.resolve(
testDirectory,
config.entry
? /\.(c|m)?js$/.test(config.entry)
? /\.(?:c|m)?js$/.test(config.entry)
? config.entry
: `${config.entry}.js`
: "./index.js"

View File

@ -45,7 +45,7 @@ const exec = (n, options = {}) =>
const rawStdout = chunks.join("");
const stdout = rawStdout.replace(
// This warning is expected
/<([ew])> \[.+\n(?:<([ew])> [^[].+\n)*/g,
/<([ew])> \[.+\n(?:<[ew]> [^[].+\n)*/g,
(message, type) => {
(type === "e" ? errors : warnings).push(message);
return "";

View File

@ -8,7 +8,7 @@ const prettyFormat = require("pretty-format").default;
const webpack = require("..");
const CWD_PATTERN = new RegExp(process.cwd().replace(/\\/g, "/"), "gm");
const ERROR_STACK_PATTERN = /(?:\n\s+at\s.*)+/gm;
const ERROR_STACK_PATTERN = /(?:\n\s+at\s.*)+/g;
/**
* @param {unknown} err an err
@ -51,9 +51,9 @@ const prettyFormatOptions = {
},
print(val) {
return `"${val
.replace(/\\/gm, "/")
.replace(/"/gm, '\\"')
.replace(/\r?\n/gm, "\\n")}"`;
.replace(/\\/g, "/")
.replace(/"/g, '\\"')
.replace(/\r?\n/g, "\\n")}"`;
}
}
]

View File

@ -103,7 +103,7 @@ describe("MemoryLimitTestCases", () => {
...args,
(err, result) => {
if (err) return callback(err);
if (!/\.(js|json|txt)$/.test(args[0])) {
if (!/\.(?:js|json|txt)$/.test(args[0])) {
return callback(null, result);
}
callback(null, result.toString("utf8").replace(/\r/g, ""));

View File

@ -111,7 +111,7 @@ describe("StatsTestCases", () => {
...args,
(err, result) => {
if (err) return callback(err);
if (!/\.(js|json|txt)$/.test(args[0])) {
if (!/\.(?:js|json|txt)$/.test(args[0])) {
return callback(null, result);
}
callback(null, result.toString("utf8").replace(/\r/g, ""));
@ -215,7 +215,7 @@ describe("StatsTestCases", () => {
.replace(/Unexpected identifier '.+?'/g, "Unexpected identifier")
.replace(/[.0-9]+(\s?(bytes|KiB|MiB|GiB))/g, "X$1")
.replace(
/ms\s\([0-9a-f]{6,32}\)|(?![0-9]+-)[0-9a-f-]{6,32}\./g,
/ms\s\([0-9a-f]{6,32}\)|(?!\d+-)[0-9a-f-]{6,32}\./g,
(match) => `${match.replace(/[0-9a-f]/g, "X")}`
)
// Normalize stack traces between Jest v27 and v30

View File

@ -1,3 +1,3 @@
"use strict";
module.exports = () => /^v(1[6-9]|21)/.test(process.version);
module.exports = () => /^v(?:1[6-9]|21)/.test(process.version);

View File

@ -1,3 +1,3 @@
"use strict";
module.exports = () => /^v(2[2-9])/.test(process.version);
module.exports = () => /^v2[2-9]/.test(process.version);

View File

@ -17,7 +17,7 @@ module.exports = {
switch (file) {
case "resource-with-bom.ext": {
if (!/[\uFEFF]/.test(source)) {
if (!/\uFEFF/.test(source)) {
throw new Error(`Not found BOM in ${filename}.`);
}
break;

View File

@ -150,7 +150,7 @@ class HtmlInlinePlugin {
/** @type {{ start: number, length: number, asset: Asset }[]} */
const matches = [];
const regExp =
/<script\s+src\s*=\s*"([^"]+)"(?:\s+[^"=\s]+(?:\s*=\s*(?:"[^"]*"|[^\s]+))?)*\s*><\/script>/g;
/<script\s+src\s*=\s*"([^"]+)"(?:\s+[^"=\s]+(?:\s*=\s*(?:"[^"]*"|\S+))?)*\s*><\/script>/g;
let match = regExp.exec(content);
while (match) {
let url = match[1];

View File

@ -264,7 +264,7 @@ class FakeSheet {
css = css
// Remove comments
// @ts-expect-error we use es2018 for such tests
.replace(/\/\*.*?\*\//gms, "")
.replace(/\/\*.*?\*\//gs, "")
.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
if (!/^https:\/\/test\.cases\/path\//.test(url)) {
return url;
@ -376,7 +376,7 @@ class CSSStyleSheet {
// Remove comments
const cleanCss = cssText
// @ts-expect-error we use es2018 for such tests
.replace(/\/\*.*?\*\//gms, "");
.replace(/\/\*.*?\*\//gs, "");
let ruleStart = 0;

View File

@ -21,7 +21,7 @@ const files = ["lib/util/hash/xxhash64.js", "lib/util/hash/md4.js"];
const content = fs.readFileSync(filePath, "utf8");
const regexp =
/\n\/\/[\s]*#region wasm code: (.+) \((.+)\)(.*)\n[\s\S]+?\/\/[\s+]*#endregion\n/g;
/\n\/\/\s*#region wasm code: (.+) \((.+)\)(.*)\n[\s\S]+?\/\/[\s+]*#endregion\n/g;
const replaces = new Map();