Skip to content

Commit 583b625

Browse files
committed
fix(compiler-sfc): fix usage detection for types in v-for/v-slot expressions
fix #5959
1 parent 8ba0bb8 commit 583b625

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ return { props, a, emit }
722722

723723
exports[`SFC compile <script setup> dev mode import usage check TS annotations 1`] = `
724724
"import { defineComponent as _defineComponent } from 'vue'
725-
import { Foo, Bar, Baz } from './x'
725+
import { Foo, Bar, Baz, Qux, Fred } from './x'
726726

727727
export default /*#__PURE__*/_defineComponent({
728728
setup(__props, { expose }) {

packages/compiler-sfc/__tests__/compileScript.spec.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -446,14 +446,16 @@ defineExpose({ foo: 123 })
446446
test('TS annotations', () => {
447447
const { content } = compile(`
448448
<script setup lang="ts">
449-
import { Foo, Bar, Baz } from './x'
449+
import { Foo, Bar, Baz, Qux, Fred } from './x'
450450
const a = 1
451451
function b() {}
452452
</script>
453453
<template>
454454
{{ a as Foo }}
455455
{{ b<Bar>() }}
456456
{{ Baz }}
457+
<Comp v-slot="{ data }: Qux">{{ data }}</Comp>
458+
<div v-for="{ z = x as Qux } in list as Fred"/>
457459
</template>
458460
`)
459461
expect(content).toMatch(`return { a, b, Baz }`)

packages/compiler-sfc/src/compileScript.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const WITH_DEFAULTS = 'withDefaults'
6565
const DEFAULT_VAR = `__default__`
6666

6767
const isBuiltInDir = makeMap(
68-
`once,memo,if,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
68+
`once,memo,if,for,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
6969
)
7070

7171
export interface SFCScriptCompileOptions {
@@ -2103,7 +2103,8 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
21032103
}
21042104
if (prop.exp) {
21052105
code += `,${processExp(
2106-
(prop.exp as SimpleExpressionNode).content
2106+
(prop.exp as SimpleExpressionNode).content,
2107+
prop.name
21072108
)}`
21082109
}
21092110
}
@@ -2122,8 +2123,19 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
21222123
return code
21232124
}
21242125

2125-
function processExp(exp: string) {
2126-
if (/ as \w|<.*>/.test(exp)) {
2126+
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
2127+
2128+
function processExp(exp: string, dir?: string): string {
2129+
if (/ as\s+\w|<.*>|:/.test(exp)) {
2130+
if (dir === 'slot') {
2131+
exp = `(${exp})=>{}`
2132+
} else if (dir === 'for') {
2133+
const inMatch = exp.match(forAliasRE)
2134+
if (inMatch) {
2135+
const [, LHS, RHS] = inMatch
2136+
return processExp(`(${LHS})=>{}`) + processExp(RHS)
2137+
}
2138+
}
21272139
let ret = ''
21282140
// has potential type cast or generic arguments that uses types
21292141
const ast = parseExpression(exp, { plugins: ['typescript'] })

0 commit comments

Comments
 (0)