Skip to content

Commit eca4d78

Browse files
Bigfish8yyx990803
authored andcommitted
chore(compiler-core): reduce unnecessary cache inside v-once (#4112)
1 parent e5a4412 commit eca4d78

File tree

7 files changed

+37
-2
lines changed

7 files changed

+37
-2
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,18 @@ describe('compiler: transform v-model', () => {
425425
).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)
426426
})
427427

428+
test('should not cache update handler if it inside v-once', () => {
429+
const root = parseWithVModel(
430+
'<div v-once><input v-model="foo" /></div>',
431+
{
432+
prefixIdentifiers: true,
433+
cacheHandlers: true
434+
}
435+
)
436+
expect(root.cached).not.toBe(2)
437+
expect(root.cached).toBe(1)
438+
})
439+
428440
test('should mark update handler dynamic if it refers slot scope variables', () => {
429441
const root = parseWithVModel(
430442
'<Comp v-slot="{ foo }"><input v-model="foo.bar"/></Comp>',

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,15 @@ describe('compiler: transform v-on', () => {
530530
expect(root.cached).toBe(0)
531531
})
532532

533+
test('should not be cached inside v-once', () => {
534+
const { root } = parseWithVOn(`<div v-once><div v-on:click="foo"/></div>`, {
535+
prefixIdentifiers: true,
536+
cacheHandlers: true
537+
})
538+
expect(root.cached).not.toBe(2)
539+
expect(root.cached).toBe(1)
540+
})
541+
533542
test('inline function expression handler', () => {
534543
const { root, node } = parseWithVOn(`<div v-on:click="() => foo()" />`, {
535544
prefixIdentifiers: true,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ describe('compiler: v-once transform', () => {
8080
expect(generate(root).code).toMatchSnapshot()
8181
})
8282

83+
// v-once inside v-once should not be cached
84+
test('inside v-once', () => {
85+
const root = transformWithOnce(`<div v-once><div v-once/></div>`)
86+
expect(root.cached).not.toBe(2)
87+
expect(root.cached).toBe(1)
88+
})
89+
8390
// cached nodes should be ignored by hoistStatic transform
8491
test('with hoistStatic: true', () => {
8592
const root = transformWithOnce(`<div><div v-once /></div>`, {

packages/compiler-core/src/transform.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export interface TransformContext
105105
parent: ParentNode | null
106106
childIndex: number
107107
currentNode: RootNode | TemplateChildNode | null
108+
inVOnce: boolean
108109
helper<T extends symbol>(name: T): T
109110
removeHelper<T extends symbol>(name: T): void
110111
helperString(name: symbol): string
@@ -192,6 +193,7 @@ export function createTransformContext(
192193
parent: null,
193194
currentNode: root,
194195
childIndex: 0,
196+
inVOnce: false,
195197

196198
// methods
197199
helper(name) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
107107
if (
108108
!__BROWSER__ &&
109109
context.prefixIdentifiers &&
110+
!context.inVOnce &&
110111
context.cacheHandlers &&
111112
!hasScopeRef(exp, context.identifiers)
112113
) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export const transformOn: DirectiveTransform = (
7070
if (exp && !exp.content.trim()) {
7171
exp = undefined
7272
}
73-
let shouldCache: boolean = context.cacheHandlers && !exp
73+
let shouldCache: boolean = context.cacheHandlers && !exp && !context.inVOnce
7474
if (exp) {
7575
const isMemberExp = isMemberExpression(exp.content)
7676
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content))
@@ -90,6 +90,8 @@ export const transformOn: DirectiveTransform = (
9090
// to scope variables.
9191
shouldCache =
9292
context.cacheHandlers &&
93+
// unnecessary to cache inside v-once
94+
!context.inVOnce &&
9395
// runtime constants don't need to be cached
9496
// (this is analyzed by compileScript in SFC <script setup>)
9597
!(exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ const seen = new WeakSet()
77

88
export const transformOnce: NodeTransform = (node, context) => {
99
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
10-
if (seen.has(node)) {
10+
if (seen.has(node) || context.inVOnce) {
1111
return
1212
}
1313
seen.add(node)
14+
context.inVOnce = true
1415
context.helper(SET_BLOCK_TRACKING)
1516
return () => {
17+
context.inVOnce = false
1618
const cur = context.currentNode as ElementNode | IfNode | ForNode
1719
if (cur.codegenNode) {
1820
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */)

0 commit comments

Comments
 (0)