Skip to content

Commit fb13930

Browse files
committedOct 11, 2022
fix(sfc): prune returned bindings for non-TS as well
In Vue 3, pruning is only done for TS to produce valid code and tree-shaking is done by inlining the template for production. In Vue 2 we do not inline the template in production, so return binding pruning is needed in all cases. fix #12765
1 parent 87f69aa commit fb13930

File tree

2 files changed

+19
-19
lines changed

2 files changed

+19
-19
lines changed
 

‎packages/compiler-sfc/src/compileScript.ts

+18-18
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,9 @@ export function compileScript(
284284
userImportAlias[imported] = local
285285
}
286286

287-
// template usage check is only needed in non-inline mode, so we can skip
288-
// the work if inlineTemplate is true.
289287
let isUsedInTemplate = true
290-
if (isTS && sfc.template && !sfc.template.src && !sfc.template.lang) {
291-
isUsedInTemplate = isImportUsed(local, sfc)
288+
if (sfc.template && !sfc.template.src && !sfc.template.lang) {
289+
isUsedInTemplate = isImportUsed(local, sfc, isTS)
292290
}
293291

294292
userImports[local] = {
@@ -1782,7 +1780,7 @@ function getObjectOrArrayExpressionKeys(value: Node): string[] {
17821780

17831781
const templateUsageCheckCache = new LRU<string, string>(512)
17841782

1785-
function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
1783+
function resolveTemplateUsageCheckString(sfc: SFCDescriptor, isTS: boolean) {
17861784
const { content } = sfc.template!
17871785
const cached = templateUsageCheckCache.get(content)
17881786
if (cached) {
@@ -1809,15 +1807,15 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
18091807
code += `,v${capitalize(camelize(baseName))}`
18101808
}
18111809
if (value) {
1812-
code += `,${processExp(value, baseName)}`
1810+
code += `,${processExp(value, isTS, baseName)}`
18131811
}
18141812
}
18151813
}
18161814
},
18171815
chars(text) {
18181816
const res = parseText(text)
18191817
if (res) {
1820-
code += `,${processExp(res.expression)}`
1818+
code += `,${processExp(res.expression, isTS)}`
18211819
}
18221820
}
18231821
})
@@ -1829,8 +1827,8 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
18291827

18301828
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
18311829

1832-
function processExp(exp: string, dir?: string): string {
1833-
if (/ as\s+\w|<.*>|:/.test(exp)) {
1830+
function processExp(exp: string, isTS: boolean, dir?: string): string {
1831+
if (isTS && / as\s+\w|<.*>|:/.test(exp)) {
18341832
if (dir === 'slot') {
18351833
exp = `(${exp})=>{}`
18361834
} else if (dir === 'on') {
@@ -1839,7 +1837,7 @@ function processExp(exp: string, dir?: string): string {
18391837
const inMatch = exp.match(forAliasRE)
18401838
if (inMatch) {
18411839
const [, LHS, RHS] = inMatch
1842-
return processExp(`(${LHS})=>{}`) + processExp(RHS)
1840+
return processExp(`(${LHS})=>{}`, true) + processExp(RHS, true)
18431841
}
18441842
}
18451843
let ret = ''
@@ -1867,36 +1865,38 @@ function stripTemplateString(str: string): string {
18671865
return ''
18681866
}
18691867

1870-
function isImportUsed(local: string, sfc: SFCDescriptor): boolean {
1868+
function isImportUsed(
1869+
local: string,
1870+
sfc: SFCDescriptor,
1871+
isTS: boolean
1872+
): boolean {
18711873
return new RegExp(
18721874
// #4274 escape $ since it's a special char in regex
18731875
// (and is the only regex special char that is valid in identifiers)
18741876
`[^\\w$_]${local.replace(/\$/g, '\\$')}[^\\w$_]`
1875-
).test(resolveTemplateUsageCheckString(sfc))
1877+
).test(resolveTemplateUsageCheckString(sfc, isTS))
18761878
}
18771879

18781880
/**
18791881
* Note: this comparison assumes the prev/next script are already identical,
1880-
* and only checks the special case where <script setup lang="ts"> unused import
1882+
* and only checks the special case where <script setup> unused import
18811883
* pruning result changes due to template changes.
18821884
*/
18831885
export function hmrShouldReload(
18841886
prevImports: Record<string, ImportBinding>,
18851887
next: SFCDescriptor
18861888
): boolean {
1887-
if (
1888-
!next.scriptSetup ||
1889-
(next.scriptSetup.lang !== 'ts' && next.scriptSetup.lang !== 'tsx')
1890-
) {
1889+
if (!next.scriptSetup) {
18911890
return false
18921891
}
18931892

1893+
const isTS = next.scriptSetup.lang === 'ts' || next.scriptSetup.lang === 'tsx'
18941894
// for each previous import, check if its used status remain the same based on
18951895
// the next descriptor's template
18961896
for (const key in prevImports) {
18971897
// if an import was previous unused, but now is used, we need to force
18981898
// reload so that the script now includes that import.
1899-
if (!prevImports[key].isUsedInTemplate && isImportUsed(key, next)) {
1899+
if (!prevImports[key].isUsedInTemplate && isImportUsed(key, next, isTS)) {
19001900
return true
19011901
}
19021902
}

‎packages/compiler-sfc/test/__snapshots__/compileScript.spec.ts.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ exports[`SFC analyze <script> bindings > auto name inference > do not overwrite
2020
export default /*#__PURE__*/Object.assign(__default__, {
2121
setup(__props) {
2222
const a = 1
23-
return { a, defineComponent }
23+
return { a }
2424
}
2525
2626
})"

0 commit comments

Comments
 (0)