diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
index cbe274ef9e8..757b153411d 100644
--- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
@@ -535,6 +535,23 @@ return { props, a, emit }
}"
`;
+exports[`SFC compile
+
+ {{ a as Foo }}
+ {{ b() }}
+ {{ Baz }}
+
+ `)
+ expect(content).toMatch(`return { a, b, Baz }`)
+ assertCode(content)
+ })
})
describe('inlineTemplate mode', () => {
diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts
index 9c9c7ffbf82..509934d6d91 100644
--- a/packages/compiler-sfc/src/compileScript.ts
+++ b/packages/compiler-sfc/src/compileScript.ts
@@ -12,7 +12,12 @@ import {
walkIdentifiers
} from '@vue/compiler-dom'
import { DEFAULT_FILENAME, SFCDescriptor, SFCScriptBlock } from './parse'
-import { parse as _parse, ParserOptions, ParserPlugin } from '@babel/parser'
+import {
+ parse as _parse,
+ parseExpression,
+ ParserOptions,
+ ParserPlugin
+} from '@babel/parser'
import { camelize, capitalize, generateCodeFrame, makeMap } from '@vue/shared'
import {
Node,
@@ -348,14 +353,23 @@ export function compileScript(
local: string,
imported: string | false,
isType: boolean,
- isFromSetup: boolean
+ isFromSetup: boolean,
+ needTemplateUsageCheck: boolean
) {
if (source === 'vue' && imported) {
userImportAlias[imported] = local
}
- let isUsedInTemplate = true
- if (isTS && sfc.template && !sfc.template.src && !sfc.template.lang) {
+ // template usage check is only needed in non-inline mode, so we can skip
+ // the work if inlineTemplate is true.
+ let isUsedInTemplate = needTemplateUsageCheck
+ if (
+ needTemplateUsageCheck &&
+ isTS &&
+ sfc.template &&
+ !sfc.template.src &&
+ !sfc.template.lang
+ ) {
isUsedInTemplate = isImportUsed(local, sfc)
}
@@ -813,7 +827,8 @@ export function compileScript(
node.importKind === 'type' ||
(specifier.type === 'ImportSpecifier' &&
specifier.importKind === 'type'),
- false
+ false,
+ !options.inlineTemplate
)
}
} else if (node.type === 'ExportDefaultDeclaration') {
@@ -1027,7 +1042,8 @@ export function compileScript(
node.importKind === 'type' ||
(specifier.type === 'ImportSpecifier' &&
specifier.importKind === 'type'),
- true
+ true,
+ !options.inlineTemplate
)
}
}
@@ -2051,14 +2067,14 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
code += `,v${capitalize(camelize(prop.name))}`
}
if (prop.exp) {
- code += `,${stripStrings(
+ code += `,${processExp(
(prop.exp as SimpleExpressionNode).content
)}`
}
}
}
} else if (node.type === NodeTypes.INTERPOLATION) {
- code += `,${stripStrings(
+ code += `,${processExp(
(node.content as SimpleExpressionNode).content
)}`
}
@@ -2071,6 +2087,19 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
return code
}
+function processExp(exp: string) {
+ if (/ as \w|<.*>/.test(exp)) {
+ let ret = ''
+ // has potential type cast or generic arguments that uses types
+ const ast = parseExpression(exp, { plugins: ['typescript'] })
+ walkIdentifiers(ast, node => {
+ ret += `,` + node.name
+ })
+ return ret
+ }
+ return stripStrings(exp)
+}
+
function stripStrings(exp: string) {
return exp
.replace(/'[^']*'|"[^"]*"/g, '')