]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(compiler-vapor): generate unique helper aliases to prevent collisions with...
authordaiwei <daiwei521@126.com>
Fri, 29 Aug 2025 03:02:24 +0000 (11:02 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 29 Aug 2025 03:02:24 +0000 (11:02 +0800)
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
packages/compiler-vapor/__tests__/compile.spec.ts
packages/compiler-vapor/src/generate.ts

index 9f2183ce83ea698ac9b1fb7f3d30aca19cde8a1d..3855360c4bd0f57effd6ce2454b05e686c753e12 100644 (file)
@@ -280,6 +280,18 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compile > helper alias > should avoid conflicts with existing variable names 1`] = `
+"import { child as _child2, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div> </div>", true)
+
+export function render(_ctx, $props, $emit, $attrs, $slots) {
+  const n0 = t0()
+  const x0 = _child2(n0)
+  _renderEffect(() => _setText(x0, _toDisplayString(_ctx.foo)))
+  return n0
+}"
+`;
+
 exports[`compile > setInsertionState > next, child and nthChild should be above the setInsertionState 1`] = `
 "import { resolveComponent as _resolveComponent, child as _child, next as _next, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, nthChild as _nthChild, createIf as _createIf, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>")
index 7963a9e98c2c63a96ec47ee79a8ac1cfe0cfa413..19bb45b4879055d9738bbc561157aaf70e0edd1b 100644 (file)
@@ -268,4 +268,18 @@ describe('compile', () => {
       expect(code).matchSnapshot()
     })
   })
+
+  describe('helper alias', () => {
+    test('should avoid conflicts with existing variable names', () => {
+      const code = compile(`<div>{{ foo }}</div>`, {
+        bindingMetadata: {
+          _child: BindingTypes.LITERAL_CONST,
+          _child1: BindingTypes.SETUP_REF,
+        },
+      })
+      expect(code).matchSnapshot()
+      expect(code).contains('child as _child2')
+      expect(code).contains('const x0 = _child2(n0)')
+    })
+  })
 })
index 193a0f5da777be3f443ac9aa2480870aad6a3d34..ca26138c894f0cffa00e204edeb945f0a18aa9a7 100644 (file)
@@ -24,11 +24,31 @@ export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
 export class CodegenContext {
   options: Required<CodegenOptions>
 
-  helpers: Set<string> = new Set<string>([])
+  bindingNames: Set<string> = new Set<string>()
 
-  helper = (name: CoreHelper | VaporHelper) => {
-    this.helpers.add(name)
-    return `_${name}`
+  helpers: Map<string, string> = new Map()
+
+  helper = (name: CoreHelper | VaporHelper): string => {
+    if (this.helpers.has(name)) {
+      return this.helpers.get(name)!
+    }
+
+    const base = `_${name}`
+    if (this.bindingNames.size === 0) {
+      this.helpers.set(name, base)
+      return base
+    }
+
+    // check whether an alias is already used bindings
+    let alias = base
+    let i = 0
+    while (this.bindingNames.has(alias)) {
+      i++
+      alias = `${base}${i}`
+    }
+
+    this.helpers.set(name, alias)
+    return alias
   }
 
   delegates: Set<string> = new Set<string>()
@@ -90,6 +110,11 @@ export class CodegenContext {
     }
     this.options = extend(defaultOptions, options)
     this.block = ir.block
+    this.bindingNames = new Set<string>(
+      this.options.bindingMetadata
+        ? Object.keys(this.options.bindingMetadata)
+        : [],
+    )
   }
 }
 
@@ -105,7 +130,6 @@ export function generate(
 ): VaporCodegenResult {
   const [frag, push] = buildCodeFragment()
   const context = new CodegenContext(ir, options)
-  const { helpers } = context
   const { inline, bindingMetadata } = options
   const functionName = 'render'
 
@@ -156,7 +180,7 @@ export function generate(
     ast: ir,
     preamble,
     map: map && map.toJSON(),
-    helpers,
+    helpers: new Set<string>(Array.from(context.helpers.keys())),
   }
 }
 
@@ -169,11 +193,11 @@ function genDelegates({ delegates, helper }: CodegenContext) {
     : ''
 }
 
-function genHelperImports({ helpers, helper, options }: CodegenContext) {
+function genHelperImports({ helpers, options }: CodegenContext) {
   let imports = ''
   if (helpers.size) {
-    imports += `import { ${[...helpers]
-      .map(h => `${h} as _${h}`)
+    imports += `import { ${Array.from(helpers)
+      .map(([h, alias]) => `${h} as ${alias}`)
       .join(', ')} } from '${options.runtimeModuleName}';\n`
   }
   return imports