Skip to content

Commit 99482a4

Browse files
authored
fix(compiler-vapor): prevent caching variables in function expression (#13244)
1 parent e5a5957 commit 99482a4

File tree

5 files changed

+81
-28
lines changed

5 files changed

+81
-28
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ export function render(_ctx) {
1313
}"
1414
`;
1515

16+
exports[`compiler: template ref transform > function ref 1`] = `
17+
"import { createTemplateRefSetter as _createTemplateRefSetter, renderEffect as _renderEffect, template as _template } from 'vue';
18+
const t0 = _template("<div></div>", true)
19+
20+
export function render(_ctx) {
21+
const _setTemplateRef = _createTemplateRefSetter()
22+
const n0 = t0()
23+
let r0
24+
_renderEffect(() => r0 = _setTemplateRef(n0, bar => _ctx.foo = bar, r0))
25+
return n0
26+
}"
27+
`;
28+
1629
exports[`compiler: template ref transform > ref + v-for 1`] = `
1730
"import { createTemplateRefSetter as _createTemplateRefSetter, createFor as _createFor, template as _template } from 'vue';
1831
const t0 = _template("<div></div>", true)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ export function render(_ctx) {
7575
}"
7676
`;
7777

78+
exports[`cache multiple access > not cache variable in function expression 1`] = `
79+
"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
80+
const t0 = _template("<div></div>", true)
81+
82+
export function render(_ctx) {
83+
const n0 = t0()
84+
_renderEffect(() => _setDynamicProps(n0, [{ foo: bar => _ctx.foo = bar }], true))
85+
return n0
86+
}"
87+
`;
88+
7889
exports[`cache multiple access > not cache variable only used in property shorthand 1`] = `
7990
"import { setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue';
8091
const t0 = _template("<div></div>", true)

packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,40 @@ describe('compiler: template ref transform', () => {
8181
expect(code).contains('_setTemplateRef(n0, _ctx.foo, r0)')
8282
})
8383

84+
test('function ref', () => {
85+
const { ir, code } = compileWithTransformRef(
86+
`<div :ref="bar => foo = bar" />`,
87+
)
88+
expect(ir.block.dynamic.children[0]).toMatchObject({
89+
id: 0,
90+
flags: DynamicFlag.REFERENCED,
91+
})
92+
expect(ir.template).toEqual(['<div></div>'])
93+
expect(ir.block.operation).toMatchObject([
94+
{
95+
type: IRNodeTypes.DECLARE_OLD_REF,
96+
id: 0,
97+
},
98+
])
99+
expect(ir.block.effect).toMatchObject([
100+
{
101+
operations: [
102+
{
103+
type: IRNodeTypes.SET_TEMPLATE_REF,
104+
element: 0,
105+
value: {
106+
content: 'bar => foo = bar',
107+
isStatic: false,
108+
},
109+
},
110+
],
111+
},
112+
])
113+
expect(code).toMatchSnapshot()
114+
expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
115+
expect(code).contains('_setTemplateRef(n0, bar => _ctx.foo = bar, r0)')
116+
})
117+
84118
test('ref + v-if', () => {
85119
const { ir, code } = compileWithTransformRef(
86120
`<div ref="foo" v-if="true" />`,

packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,4 +809,12 @@ describe('cache multiple access', () => {
809809
expect(code).matchSnapshot()
810810
expect(code).not.contains('const _bar = _ctx.bar')
811811
})
812+
813+
test('not cache variable in function expression', () => {
814+
const { code } = compileWithVBind(`
815+
<div v-bind="{ foo: bar => foo = bar }"></div>
816+
`)
817+
expect(code).matchSnapshot()
818+
expect(code).not.contains('const _bar = _ctx.bar')
819+
})
812820
})

packages/compiler-vapor/src/generators/expression.ts

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import type { Identifier, Node } from '@babel/types'
2020
import type { CodegenContext } from '../generate'
2121
import { isConstantExpression } from '../utils'
2222
import { type CodeFragment, NEWLINE, buildCodeFragment } from './utils'
23-
import { walk } from 'estree-walker'
2423
import { type ParserOptions, parseExpression } from '@babel/parser'
2524

2625
export function genExpression(
@@ -295,33 +294,15 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
295294
continue
296295
}
297296

298-
walk(exp.ast, {
299-
enter(currentNode: Node, parent: Node | null) {
300-
if (currentNode.type === 'MemberExpression') {
301-
const memberExp = extractMemberExpression(
302-
currentNode,
303-
(name: string) => {
304-
registerVariable(name, exp, true)
305-
},
306-
)
307-
registerVariable(memberExp, exp, false)
308-
return this.skip()
309-
}
310-
311-
// skip shorthand or non-computed property keys
312-
if (
313-
parent &&
314-
parent.type === 'ObjectProperty' &&
315-
parent.key === currentNode &&
316-
(parent.shorthand || !parent.computed)
317-
) {
318-
return this.skip()
319-
}
320-
321-
if (currentNode.type === 'Identifier') {
322-
registerVariable(currentNode.name, exp, true)
323-
}
324-
},
297+
walkIdentifiers(exp.ast, (currentNode, parent, parentStack) => {
298+
if (parent && isMemberExpression(parent)) {
299+
const memberExp = extractMemberExpression(parent, name => {
300+
registerVariable(name, exp, true)
301+
})
302+
registerVariable(memberExp, exp, false)
303+
} else if (!parentStack.some(isMemberExpression)) {
304+
registerVariable(currentNode.name, exp, true)
305+
}
325306
})
326307
}
327308

@@ -580,3 +561,9 @@ function extractMemberExpression(
580561
return ''
581562
}
582563
}
564+
565+
const isMemberExpression = (node: Node) => {
566+
return (
567+
node.type === 'MemberExpression' || node.type === 'OptionalMemberExpression'
568+
)
569+
}

0 commit comments

Comments
 (0)