Skip to content

Commit a6c1db2

Browse files
committed
fix(compiler-core): fix hoisting logic for elements with cached handlers + other bindings
fix #4327
1 parent 5b3f1e8 commit a6c1db2

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap

+15
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,21 @@ return function render(_ctx, _cache) {
211211
}"
212212
`;
213213
214+
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist elements with cached handlers + other bindings 1`] = `
215+
"import { normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
216+
217+
export function render(_ctx, _cache) {
218+
return (_openBlock(), _createElementBlock(\\"div\\", null, [
219+
_createElementVNode(\\"div\\", null, [
220+
_createElementVNode(\\"div\\", {
221+
class: _normalizeClass({}),
222+
onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.foo && _ctx.foo(...args)))
223+
})
224+
])
225+
]))
226+
}"
227+
`;
228+
214229
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist elements with cached handlers 1`] = `
215230
"import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
216231

packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts

+19
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,25 @@ describe('compiler: hoistStatic transform', () => {
590590
).toMatchSnapshot()
591591
})
592592

593+
test('should NOT hoist elements with cached handlers + other bindings', () => {
594+
const root = transformWithHoist(
595+
`<div><div><div :class="{}" @click="foo"/></div></div>`,
596+
{
597+
prefixIdentifiers: true,
598+
cacheHandlers: true
599+
}
600+
)
601+
602+
expect(root.cached).toBe(1)
603+
expect(root.hoists.length).toBe(0)
604+
expect(
605+
generate(root, {
606+
mode: 'module',
607+
prefixIdentifiers: true
608+
}).code
609+
).toMatchSnapshot()
610+
})
611+
593612
test('should NOT hoist keyed template v-for with plain element child', () => {
594613
const root = transformWithHoist(
595614
`<div><template v-for="item in items" :key="item"><span/></template></div>`

packages/compiler-core/src/transforms/hoistStatic.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,17 @@ function getGeneratedPropsConstantType(
335335
if (keyType < returnType) {
336336
returnType = keyType
337337
}
338-
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
338+
let valueType: ConstantTypes
339+
if (value.type === NodeTypes.SIMPLE_EXPRESSION) {
340+
valueType = getConstantType(value, context)
341+
} else if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
339342
// some helper calls can be hoisted,
340343
// such as the `normalizeProps` generated by the compiler for pre-normalize class,
341344
// in this case we need to respect the ConstanType of the helper's argments
342-
if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
343-
return getConstantTypeOfHelperCall(value, context)
344-
}
345-
return ConstantTypes.NOT_CONSTANT
345+
valueType = getConstantTypeOfHelperCall(value, context)
346+
} else {
347+
valueType = ConstantTypes.NOT_CONSTANT
346348
}
347-
const valueType = getConstantType(value, context)
348349
if (valueType === ConstantTypes.NOT_CONSTANT) {
349350
return valueType
350351
}

0 commit comments

Comments
 (0)