]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): fix usage detection for types in v-for/v-slot expressions
authorEvan You <yyx990803@gmail.com>
Fri, 20 May 2022 16:09:15 +0000 (00:09 +0800)
committerEvan You <yyx990803@gmail.com>
Fri, 20 May 2022 16:09:15 +0000 (00:09 +0800)
fix #5959

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

index bef06904a50fbba1fcab3cf8b077123badb85bc6..e8026dc129c6be5671da743078f012895aa71d92 100644 (file)
@@ -722,7 +722,7 @@ return { props, a, emit }
 
 exports[`SFC compile <script setup> dev mode import usage check TS annotations 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
-import { Foo, Bar, Baz } from './x'
+import { Foo, Bar, Baz, Qux, Fred } from './x'
         
 export default /*#__PURE__*/_defineComponent({
   setup(__props, { expose }) {
index 1eb867601600839068611698f8daa58ab4d2c222..77a26a6f5db06928487a66d7359d7d82e4fb187b 100644 (file)
@@ -446,7 +446,7 @@ defineExpose({ foo: 123 })
     test('TS annotations', () => {
       const { content } = compile(`
         <script setup lang="ts">
-        import { Foo, Bar, Baz } from './x'
+        import { Foo, Bar, Baz, Qux, Fred } from './x'
         const a = 1
         function b() {}
         </script>
@@ -454,6 +454,8 @@ defineExpose({ foo: 123 })
           {{ a as Foo }}
           {{ b<Bar>() }}
           {{ Baz }}
+          <Comp v-slot="{ data }: Qux">{{ data }}</Comp>
+          <div v-for="{ z = x as Qux } in list as Fred"/>
         </template>
         `)
       expect(content).toMatch(`return { a, b, Baz }`)
index 74c89e88d479e205e9bb6a77b57b1e84ebc26935..ca82dc909bd83189cd32cc377647936b76379552 100644 (file)
@@ -65,7 +65,7 @@ const WITH_DEFAULTS = 'withDefaults'
 const DEFAULT_VAR = `__default__`
 
 const isBuiltInDir = makeMap(
-  `once,memo,if,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
+  `once,memo,if,for,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
 )
 
 export interface SFCScriptCompileOptions {
@@ -2103,7 +2103,8 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
               }
               if (prop.exp) {
                 code += `,${processExp(
-                  (prop.exp as SimpleExpressionNode).content
+                  (prop.exp as SimpleExpressionNode).content,
+                  prop.name
                 )}`
               }
             }
@@ -2122,8 +2123,19 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) {
   return code
 }
 
-function processExp(exp: string) {
-  if (/ as \w|<.*>/.test(exp)) {
+const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
+
+function processExp(exp: string, dir?: string): string {
+  if (/ as\s+\w|<.*>|:/.test(exp)) {
+    if (dir === 'slot') {
+      exp = `(${exp})=>{}`
+    } else if (dir === 'for') {
+      const inMatch = exp.match(forAliasRE)
+      if (inMatch) {
+        const [, LHS, RHS] = inMatch
+        return processExp(`(${LHS})=>{}`) + processExp(RHS)
+      }
+    }
     let ret = ''
     // has potential type cast or generic arguments that uses types
     const ast = parseExpression(exp, { plugins: ['typescript'] })