Explorar o código

fix(compiler-vapor): prevent duplicate processing of member expressions in expression analysis (#14105)

edison hai 5 meses
pai
achega
35d135ee14

+ 15 - 0
packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap

@@ -57,6 +57,21 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`cache multiple access > dynamic property access with parentheses 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div></div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _foo_bar = _ctx.foo[_ctx.bar]
+    _setProp(n0, "x", (_foo_bar).x)
+    _setProp(n0, "bar", (_foo_bar))
+  })
+  return n0
+}"
+`;
+
 exports[`cache multiple access > function calls with arguments 1`] = `
 "import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>")

+ 10 - 0
packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

@@ -801,6 +801,16 @@ describe('cache multiple access', () => {
     expect(code).contains('_setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)')
   })
 
+  test('dynamic property access with parentheses', () => {
+    const { code } = compileWithVBind(`
+        <div :x="(foo[bar]).x" :bar="(foo[bar])"></div>
+      `)
+    expect(code).matchSnapshot()
+    expect(code).contains('const _foo_bar = _ctx.foo[_ctx.bar]')
+    expect(code).contains('_setProp(n0, "x", (_foo_bar).x)')
+    expect(code).contains('_setProp(n0, "bar", (_foo_bar))')
+  })
+
   test('variable name substring edge cases', () => {
     const { code } = compileWithVBind(
       `<div :id="title + titles + title"></div>`,

+ 3 - 1
packages/compiler-vapor/src/generators/expression.ts

@@ -327,8 +327,10 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
       continue
     }
 
+    const seenParents = new Set<Node>()
     walkIdentifiers(exp.ast, (currentNode, parent, parentStack) => {
-      if (parent && isMemberExpression(parent)) {
+      if (parent && isMemberExpression(parent) && !seenParents.has(parent)) {
+        seenParents.add(parent)
         const memberExp = extractMemberExpression(parent, id => {
           registerVariable(id.name, exp, true, {
             start: id.start!,