]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-vapor): avoid cache declarations for call expression member access ...
author山吹色御守 <85992002+KazariEX@users.noreply.github.com>
Thu, 25 Dec 2025 13:17:15 +0000 (21:17 +0800)
committerGitHub <noreply@github.com>
Thu, 25 Dec 2025 13:17:15 +0000 (21:17 +0800)
close #14244

packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
packages/compiler-vapor/src/generators/expression.ts

index 316cf92243cd63f3f1b5aaa7bf19b5588d54810e..bddf5544cc02802789e98b3652d28c20854b9d3d 100644 (file)
@@ -270,6 +270,38 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`cache multiple access > should cache method call with same arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _msg_replace_1_2 = _ctx.msg.replace('1', '2')
+    _setProp(n0, "id", _msg_replace_1_2)
+    _setProp(n1, "id", _msg_replace_1_2)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`cache multiple access > should not cache method call with different arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div></div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _msg = _ctx.msg
+    _setProp(n0, "id", _msg.replace('1', '2'))
+    _setProp(n1, "id", _msg.replace('1', '3'))
+  })
+  return [n0, n1]
+}"
+`;
+
 exports[`cache multiple access > variable name substring edge cases 1`] = `
 "import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
index ddbc125cd57ea05454f09328608779cf34f51e4b..7195e52afca6dcd6f2cbe68852e0ccefde7e451c 100644 (file)
@@ -954,4 +954,24 @@ describe('cache multiple access', () => {
     expect(code).matchSnapshot()
     expect(code).not.contains('const _bar = _ctx.bar')
   })
+
+  test('should not cache method call with different arguments', () => {
+    const { code } = compileWithVBind(`
+      <div :id="msg.replace('1', '2')"></div>
+      <div :id="msg.replace('1', '3')"></div>
+    `)
+    expect(code).matchSnapshot()
+    expect(code).contains('const _msg = _ctx.msg')
+    expect(code).not.contains('_ctx.msg.replace')
+  })
+
+  test('should cache method call with same arguments', () => {
+    const { code } = compileWithVBind(`
+      <div :id="msg.replace('1', '2')"></div>
+      <div :id="msg.replace('1', '2')"></div>
+    `)
+    expect(code).matchSnapshot()
+    expect(code).contains(`const _msg_replace_1_2 = _ctx.msg.replace('1', '2')`)
+    expect(code).not.contains('const _msg = _ctx.msg')
+  })
 })
index 9012ee1f2e145d4993d53c30c2bf5854fed8f18b..3893282d6fa07cde9ed8633789c0ef69e9d1c07f 100644 (file)
@@ -337,6 +337,12 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
             end: id.end!,
           })
         })
+
+        const parentOfMemberExp = parentStack[parentStack.length - 2]
+        if (parentOfMemberExp && isCallExpression(parentOfMemberExp)) {
+          return
+        }
+
         registerVariable(
           memberExp,
           exp,
@@ -685,6 +691,12 @@ function extractMemberExpression(
   }
 }
 
+const isCallExpression = (node: Node) => {
+  return (
+    node.type === 'CallExpression' || node.type === 'OptionalCallExpression'
+  )
+}
+
 const isMemberExpression = (node: Node) => {
   return (
     node.type === 'MemberExpression' ||