]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: avoid hard error when inferring runtime type
authorEvan You <yyx990803@gmail.com>
Sat, 15 Apr 2023 09:59:50 +0000 (17:59 +0800)
committerEvan You <yyx990803@gmail.com>
Sat, 15 Apr 2023 14:08:39 +0000 (22:08 +0800)
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
packages/compiler-sfc/src/parse.ts
packages/compiler-sfc/src/script/context.ts
packages/compiler-sfc/src/script/resolveType.ts

index 2f5b233091d0115f1f2b86354a5f8dc0ace90dab..6f07cfcfab4e38ecd04bb0aa617ae13343fbc784 100644 (file)
@@ -397,6 +397,11 @@ describe('resolveType', () => {
         resolve(`import { X } from './foo'; defineProps<X>()`)
       ).toThrow(`Failed to resolve import source "./foo" for type X`)
     })
+
+    test('should not error on unresolved type when inferring runtime type', () => {
+      expect(() => resolve(`defineProps<{ foo: T }>()`)).not.toThrow()
+      expect(() => resolve(`defineProps<{ foo: T['bar'] }>()`)).not.toThrow()
+    })
   })
 })
 
index b46c5ea1332ca05cf5ba2df75b67fabaf9d98b34..29c91cc1977d01a699fe8bb6b81b96f4b4cb1861 100644 (file)
@@ -47,6 +47,13 @@ export interface SFCScriptBlock extends SFCBlock {
   imports?: Record<string, ImportBinding>
   scriptAst?: import('@babel/types').Statement[]
   scriptSetupAst?: import('@babel/types').Statement[]
+  warnings?: string[]
+  /**
+   * Fully resolved dependency file paths (unix slashes) with imported types
+   * used in macros, used for HMR cache busting in @vitejs/plugin-vue and
+   * vue-loader.
+   */
+  deps?: string[]
 }
 
 export interface SFCStyleBlock extends SFCBlock {
index ec6bbe8d0f17472d230cd5f24468bb80bcc6d868..1f96584507b4cba564dad2c959ad8cb8cac30a15 100644 (file)
@@ -7,7 +7,7 @@ import { PropsDestructureBindings } from './defineProps'
 import { ModelDecl } from './defineModel'
 import { BindingMetadata } from '../../../compiler-core/src'
 import MagicString from 'magic-string'
-import { TypeScope, WithScope } from './resolveType'
+import { TypeScope } from './resolveType'
 
 export class ScriptCompileContext {
   isJS: boolean
@@ -56,13 +56,17 @@ export class ScriptCompileContext {
 
   // codegen
   bindingMetadata: BindingMetadata = {}
-
   helperImports: Set<string> = new Set()
   helper(key: string): string {
     this.helperImports.add(key)
     return `_${key}`
   }
 
+  /**
+   * to be exposed on compiled script block for HMR cache busting
+   */
+  deps?: string[]
+
   constructor(
     public descriptor: SFCDescriptor,
     public options: SFCScriptCompileOptions
@@ -125,7 +129,7 @@ export class ScriptCompileContext {
     return block.content.slice(node.start!, node.end!)
   }
 
-  error(msg: string, node: Node & WithScope, scope?: TypeScope): never {
+  error(msg: string, node: Node, scope?: TypeScope): never {
     const offset = scope ? scope.offset : this.startOffset!
     throw new Error(
       `[@vue/compiler-sfc] ${msg}\n\n${
index 9d306d7bc5c765e76326e89134c0c6fcefa0a863..bbbbd4c5bc0ba667f37223e1b94aab9a512592a7 100644 (file)
@@ -134,6 +134,7 @@ function innerResolveTypeElements(
           break
         }
       } else {
+        // TODO support `number` and `string` index type when possible
         ctx.error(
           `Unsupported index type: ${node.indexType.type}`,
           node.indexType,
@@ -320,7 +321,11 @@ function resolveStringType(
           case 'Uncapitalize':
             return getParam().map(s => s[0].toLowerCase() + s.slice(1))
           default:
-            ctx.error('Failed to resolve type reference', node, scope)
+            ctx.error(
+              'Unsupported type when resolving string type',
+              node.typeName,
+              scope
+            )
         }
       }
     }
@@ -906,7 +911,7 @@ export function inferRuntimeType(
       if (node.typeName.type === 'Identifier') {
         const resolved = resolveTypeReference(ctx, node, scope)
         if (resolved) {
-          return inferRuntimeType(ctx, resolved, scope)
+          return inferRuntimeType(ctx, resolved, resolved._ownerScope)
         }
         switch (node.typeName.name) {
           case 'Array':
@@ -988,9 +993,15 @@ export function inferRuntimeType(
         node.indexType.type === 'TSLiteralType' &&
         node.indexType.literal.type === 'StringLiteral'
       ) {
-        const resolved = resolveTypeElements(ctx, node.objectType)
-        const key = node.indexType.literal.value
-        return inferRuntimeType(ctx, resolved.props[key])
+        try {
+          const resolved = resolveTypeElements(ctx, node.objectType, scope)
+          const key = node.indexType.literal.value
+          const prop = resolved.props[key]
+          return inferRuntimeType(ctx, prop, prop._ownerScope)
+        } catch (e) {
+          // avoid hard error, fallback to unknown
+          return [UNKNOWN_TYPE]
+        }
       }
     }