perf: improve regexp performance with non-capturing groups (#13567)

This commit is contained in:
山吹色御守 2025-09-02 17:30:02 +08:00 committed by GitHub
parent f2699a5cb3
commit 1e8b65aa49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 17 additions and 17 deletions

View File

@ -36,7 +36,7 @@ import { findDir, findProp, getMemoedVNodeCall, injectProp } from '../utils'
import { PatchFlags } from '@vue/shared'
export const transformIf: NodeTransform = createStructuralDirectiveTransform(
/^(if|else|else-if)$/,
/^(?:if|else|else-if)$/,
(node, dir, context) => {
return processIf(node, dir, context, (ifNode, branch, isRoot) => {
// #1587: We need to dynamically increment the key based on the current

View File

@ -223,7 +223,7 @@ export function buildSlots(
),
)
} else if (
(vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))
(vElse = findDir(slotElement, /^else(?:-if)?$/, true /* allowEmpty */))
) {
// find adjacent v-if
let j = i
@ -234,7 +234,7 @@ export function buildSlots(
break
}
}
if (prev && isTemplateNode(prev) && findDir(prev, /^(else-)?if$/)) {
if (prev && isTemplateNode(prev) && findDir(prev, /^(?:else-)?if$/)) {
__TEST__ && assert(dynamicSlots.length > 0)
// attach this slot to previous conditional
let conditional = dynamicSlots[

View File

@ -189,7 +189,7 @@ export const isMemberExpression: (
) => boolean = __BROWSER__ ? isMemberExpressionBrowser : isMemberExpressionNode
const fnExpRE =
/^\s*(async\s*)?(\([^)]*?\)|[\w$_]+)\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/
/^\s*(?:async\s*)?(?:\([^)]*?\)|[\w$_]+)\s*(?::[^=]+)?=>|^\s*(?:async\s+)?function(?:\s+[\w$]+)?\s*\(/
export const isFnExpressionBrowser: (exp: ExpressionNode) => boolean = exp =>
fnExpRE.test(getExpSource(exp))

View File

@ -184,7 +184,7 @@ const getCachedNode = (
}
}
const dataAriaRE = /^(data|aria)-/
const dataAriaRE = /^(?:data|aria)-/
const isStringifiableAttr = (name: string, ns: Namespaces) => {
return (
(ns === Namespaces.HTML

View File

@ -8,8 +8,8 @@ import {
import selectorParser from 'postcss-selector-parser'
import { warn } from '../warn'
const animationNameRE = /^(-\w+-)?animation-name$/
const animationRE = /^(-\w+-)?animation$/
const animationNameRE = /^(?:-\w+-)?animation-name$/
const animationRE = /^(?:-\w+-)?animation$/
const keyframesRE = /^(?:-\w+-)?keyframes$/
const scopedPlugin: PluginCreator<string> = (id = '') => {

View File

@ -6,7 +6,7 @@ export function isRelativeUrl(url: string): boolean {
return firstChar === '.' || firstChar === '~' || firstChar === '@'
}
const externalRE = /^(https?:)?\/\//
const externalRE = /^(?:https?:)?\/\//
export function isExternalUrl(url: string): boolean {
return externalRE.test(url)
}

View File

@ -17,7 +17,7 @@ import {
// Plugin for the first transform pass, which simply constructs the AST node
export const ssrTransformIf: NodeTransform = createStructuralDirectiveTransform(
/^(if|else|else-if)$/,
/^(?:if|else|else-if)$/,
processIf,
)

View File

@ -536,7 +536,7 @@ function installCompatMount(
if (__DEV__) {
for (let i = 0; i < container.attributes.length; i++) {
const attr = container.attributes[i]
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
if (attr.name !== 'v-cloak' && /^(?:v-|:|@)/.test(attr.name)) {
warnDeprecation(DeprecationTypes.GLOBAL_MOUNT_CONTAINER, null)
break
}

View File

@ -1203,7 +1203,7 @@ export function getComponentPublicInstance(
}
}
const classifyRE = /(?:^|[-_])(\w)/g
const classifyRE = /(?:^|[-_])\w/g
const classify = (str: string): string =>
str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')

View File

@ -447,7 +447,7 @@ export function getTransitionInfo(
}
const hasTransform =
type === TRANSITION &&
/\b(transform|all)(,|$)/.test(
/\b(?:transform|all)(?:,|$)/.test(
getStyleProperties(`${TRANSITION}Property`).toString(),
)
return {

View File

@ -103,7 +103,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
if (e && e.target !== el) {
return
}
if (!e || /transform$/.test(e.propertyName)) {
if (!e || e.propertyName.endsWith('transform')) {
el.removeEventListener('transitionend', cb)
;(el as any)[moveCbKey] = null
removeTransitionClass(el, moveClass)

View File

@ -119,7 +119,7 @@ export const createApp = ((...args) => {
if (__COMPAT__ && __DEV__ && container.nodeType === 1) {
for (let i = 0; i < (container as Element).attributes.length; i++) {
const attr = (container as Element).attributes[i]
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
if (attr.name !== 'v-cloak' && /^(?:v-|:|@)/.test(attr.name)) {
compatUtils.warnDeprecation(
DeprecationTypes.GLOBAL_MOUNT_CONTAINER,
null,

View File

@ -9,7 +9,7 @@ import { CSS_VAR_TEXT } from '../helpers/useCssVars'
type Style = string | Record<string, string | string[]> | null
const displayRE = /(^|;)\s*display\s*:/
const displayRE = /(?:^|;)\s*display\s*:/
export function patchStyle(el: Element, prev: Style, next: Style): void {
const style = (el as HTMLElement).style

View File

@ -101,13 +101,13 @@ const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {
}) as T
}
const camelizeRE = /-(\w)/g
const camelizeRE = /-\w/g
/**
* @private
*/
export const camelize: (str: string) => string = cacheStringFunction(
(str: string): string => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
return str.replace(camelizeRE, c => c.slice(1).toUpperCase())
},
)