From 92cc57868d6797d649f62d60cf3d3215c9ac1583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=90=B9=E8=89=B2=E5=BE=A1=E5=AE=88?= <85992002+KazariEX@users.noreply.github.com> Date: Fri, 4 Jul 2025 15:49:01 +0800 Subject: [PATCH 1/2] perf: improve regexp performance with non-capturing groups --- packages/compiler-core/src/transforms/vIf.ts | 2 +- packages/compiler-core/src/transforms/vSlot.ts | 4 ++-- packages/compiler-core/src/utils.ts | 2 +- packages/compiler-dom/src/transforms/stringifyStatic.ts | 2 +- packages/compiler-sfc/src/style/pluginScoped.ts | 4 ++-- packages/compiler-sfc/src/template/templateUtils.ts | 2 +- packages/compiler-ssr/src/transforms/ssrVIf.ts | 2 +- packages/runtime-core/src/compat/global.ts | 2 +- packages/runtime-core/src/component.ts | 2 +- packages/runtime-dom/src/components/Transition.ts | 2 +- packages/runtime-dom/src/components/TransitionGroup.ts | 2 +- packages/runtime-dom/src/index.ts | 2 +- packages/runtime-dom/src/modules/style.ts | 2 +- packages/shared/src/general.ts | 4 ++-- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts index 54c505407a3..c3bf7b149c3 100644 --- a/packages/compiler-core/src/transforms/vIf.ts +++ b/packages/compiler-core/src/transforms/vIf.ts @@ -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 diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts index 43296dcc9b6..9930ad2b10b 100644 --- a/packages/compiler-core/src/transforms/vSlot.ts +++ b/packages/compiler-core/src/transforms/vSlot.ts @@ -215,7 +215,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 @@ -226,7 +226,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[ diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index b49d70bb2fb..f0e3439abc2 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -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)) diff --git a/packages/compiler-dom/src/transforms/stringifyStatic.ts b/packages/compiler-dom/src/transforms/stringifyStatic.ts index cd8f1a9d184..0cda6f35ba4 100644 --- a/packages/compiler-dom/src/transforms/stringifyStatic.ts +++ b/packages/compiler-dom/src/transforms/stringifyStatic.ts @@ -184,7 +184,7 @@ const getCachedNode = ( } } -const dataAriaRE = /^(data|aria)-/ +const dataAriaRE = /^(?:data|aria)-/ const isStringifiableAttr = (name: string, ns: Namespaces) => { return ( (ns === Namespaces.HTML diff --git a/packages/compiler-sfc/src/style/pluginScoped.ts b/packages/compiler-sfc/src/style/pluginScoped.ts index d0aaddd7676..8eaf81a58cc 100644 --- a/packages/compiler-sfc/src/style/pluginScoped.ts +++ b/packages/compiler-sfc/src/style/pluginScoped.ts @@ -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 scopedPlugin: PluginCreator = (id = '') => { const keyframes = Object.create(null) diff --git a/packages/compiler-sfc/src/template/templateUtils.ts b/packages/compiler-sfc/src/template/templateUtils.ts index c1414d1ecbd..98941386e5c 100644 --- a/packages/compiler-sfc/src/template/templateUtils.ts +++ b/packages/compiler-sfc/src/template/templateUtils.ts @@ -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) } diff --git a/packages/compiler-ssr/src/transforms/ssrVIf.ts b/packages/compiler-ssr/src/transforms/ssrVIf.ts index 0e3880247a1..79a4e20015d 100644 --- a/packages/compiler-ssr/src/transforms/ssrVIf.ts +++ b/packages/compiler-ssr/src/transforms/ssrVIf.ts @@ -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, ) diff --git a/packages/runtime-core/src/compat/global.ts b/packages/runtime-core/src/compat/global.ts index edc57436a56..e19b3fc38f3 100644 --- a/packages/runtime-core/src/compat/global.ts +++ b/packages/runtime-core/src/compat/global.ts @@ -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 } diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 60552d736d5..57e71435ab3 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -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, '') diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index 6c6344bfcac..ebd16a12a3e 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -447,7 +447,7 @@ export function getTransitionInfo( } const hasTransform = type === TRANSITION && - /\b(transform|all)(,|$)/.test( + /\b(?:transform|all)(?:,|$)/.test( getStyleProperties(`${TRANSITION}Property`).toString(), ) return { diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index 7bb5ce0c6b1..33a1533c725 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -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) diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index c69375983d8..6abfbb52e5d 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -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, diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 383628a6ad0..679064bd709 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -9,7 +9,7 @@ import { CSS_VAR_TEXT } from '../helpers/useCssVars' type Style = string | Record | 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 diff --git a/packages/shared/src/general.ts b/packages/shared/src/general.ts index 9c6a2313240..8f190b62a14 100644 --- a/packages/shared/src/general.ts +++ b/packages/shared/src/general.ts @@ -101,13 +101,13 @@ const cacheStringFunction = 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()) }, ) From 1779b630a38f0ed0a8da945197515c5bc0361005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=90=B9=E8=89=B2=E5=BE=A1=E5=AE=88?= <85992002+KazariEX@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:50:07 +0800 Subject: [PATCH 2/2] refactor: do not use lookbehind assertion --- packages/runtime-core/src/component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 57e71435ab3..9eb9193da07 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -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, '')