Skip to content

Commit 48d9ee5

Browse files
committed
fix(compiler-sfc): refactor resolveTemplateVModelIdentifiers and improve template analysis caching
1 parent 7546248 commit 48d9ee5

File tree

2 files changed

+41
-38
lines changed

2 files changed

+41
-38
lines changed

packages/compiler-sfc/src/compileScript.ts

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import {
22
BindingTypes,
3-
NodeTypes,
4-
type TemplateChildNode,
53
UNREF,
64
isFunctionType,
7-
isSimpleIdentifier,
85
unwrapTSNode,
96
walkIdentifiers,
107
} from '@vue/compiler-dom'
@@ -67,7 +64,10 @@ import {
6764
isTS,
6865
} from './script/utils'
6966
import { analyzeScriptBindings } from './script/analyzeScriptBindings'
70-
import { isImportUsed } from './script/importUsageCheck'
67+
import {
68+
isImportUsed,
69+
resolveTemplateVModelIdentifiers,
70+
} from './script/importUsageCheck'
7171
import { processAwait } from './script/topLevelAwait'
7272

7373
export interface SFCScriptCompileOptions {
@@ -141,36 +141,6 @@ export interface SFCScriptCompileOptions {
141141
customElement?: boolean | ((filename: string) => boolean)
142142
}
143143

144-
function resolveTemplateVModelIdentifiers(sfc: SFCDescriptor): Set<string> {
145-
const ids = new Set<string>()
146-
const template = sfc.template
147-
if (!template?.ast) return ids
148-
149-
template.ast.children.forEach(walk)
150-
151-
function walk(node: TemplateChildNode) {
152-
switch (node.type) {
153-
case NodeTypes.ELEMENT:
154-
for (let i = 0; i < node.props.length; i++) {
155-
const prop = node.props[i]
156-
if (prop.type === NodeTypes.DIRECTIVE && prop.name === 'model') {
157-
const exp = prop.exp
158-
if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
159-
const expString = exp.content.trim()
160-
if (isSimpleIdentifier(expString) && expString !== 'undefined') {
161-
ids.add(expString)
162-
}
163-
}
164-
}
165-
}
166-
node.children.forEach(walk)
167-
break
168-
}
169-
}
170-
171-
return ids
172-
}
173-
174144
export interface ImportBinding {
175145
isType: boolean
176146
imported: string

packages/compiler-sfc/src/script/importUsageCheck.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
NodeTypes,
55
type SimpleExpressionNode,
66
type TemplateChildNode,
7+
isSimpleIdentifier,
78
parserOptions,
89
walkIdentifiers,
910
} from '@vue/compiler-dom'
@@ -19,16 +20,33 @@ export function isImportUsed(local: string, sfc: SFCDescriptor): boolean {
1920
return resolveTemplateUsedIdentifiers(sfc).has(local)
2021
}
2122

22-
const templateUsageCheckCache = createCache<Set<string>>()
23+
const templateAnalysisCache = createCache<{
24+
usedIds: Set<string>
25+
vModelIds: Set<string>
26+
}>()
27+
28+
export function resolveTemplateVModelIdentifiers(
29+
sfc: SFCDescriptor,
30+
): Set<string> {
31+
return resolveTemplateAnalysisResult(sfc).vModelIds
32+
}
2333

2434
function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {
35+
return resolveTemplateAnalysisResult(sfc).usedIds
36+
}
37+
38+
function resolveTemplateAnalysisResult(sfc: SFCDescriptor): {
39+
usedIds: Set<string>
40+
vModelIds: Set<string>
41+
} {
2542
const { content, ast } = sfc.template!
26-
const cached = templateUsageCheckCache.get(content)
43+
const cached = templateAnalysisCache.get(content)
2744
if (cached) {
2845
return cached
2946
}
3047

3148
const ids = new Set<string>()
49+
const vModelIds = new Set<string>()
3250

3351
ast!.children.forEach(walk)
3452

@@ -51,6 +69,20 @@ function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {
5169
ids.add(`v${capitalize(camelize(prop.name))}`)
5270
}
5371

72+
// collect v-model target identifiers (simple identifiers only)
73+
if (prop.name === 'model') {
74+
const exp = prop.exp
75+
if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
76+
const expString = exp.content.trim()
77+
if (
78+
isSimpleIdentifier(expString) &&
79+
expString !== 'undefined'
80+
) {
81+
vModelIds.add(expString)
82+
}
83+
}
84+
}
85+
5486
// process dynamic directive arguments
5587
if (prop.arg && !(prop.arg as SimpleExpressionNode).isStatic) {
5688
extractIdentifiers(ids, prop.arg)
@@ -81,8 +113,9 @@ function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {
81113
}
82114
}
83115

84-
templateUsageCheckCache.set(content, ids)
85-
return ids
116+
const result = { usedIds: ids, vModelIds }
117+
templateAnalysisCache.set(content, result)
118+
return result
86119
}
87120

88121
function extractIdentifiers(ids: Set<string>, node: ExpressionNode) {

0 commit comments

Comments
 (0)