]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): raise specific warning for failed extends and allow ignoring extends
authorEvan You <yyx990803@gmail.com>
Fri, 12 May 2023 12:17:55 +0000 (13:17 +0100)
committerEvan You <yyx990803@gmail.com>
Fri, 12 May 2023 12:17:55 +0000 (13:17 +0100)
ref #8286

packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
packages/compiler-sfc/src/script/resolveType.ts

index 240497310ee21fa68162212e73372efbddb0ccfc..dd47ae269c6ff0cfd961995c38a2a888a3b993d7 100644 (file)
@@ -755,6 +755,35 @@ describe('resolveType', () => {
       `)
       ).not.toThrow()
     })
+
+    test('error against failed extends', () => {
+      expect(() =>
+        resolve(`
+        import type Base from 'unknown'
+        interface Props extends Base {}
+        defineProps<Props>()
+      `)
+      ).toThrow(`@vue-ignore`)
+    })
+
+    test('allow ignoring failed extends', () => {
+      let res: any
+
+      expect(
+        () =>
+          (res = resolve(`
+        import type Base from 'unknown'
+        interface Props extends /*@vue-ignore*/ Base {
+          foo: string
+        }
+        defineProps<Props>()
+      `))
+      ).not.toThrow(`@vue-ignore`)
+
+      expect(res.props).toStrictEqual({
+        foo: ['String']
+      })
+    })
   })
 })
 
index 6b43be582d590464ab69a0842b31fba0cf6f8986..e79d21f8419607f2de6fdc9ecf5bc60294aee800 100644 (file)
@@ -322,11 +322,29 @@ function resolveInterfaceMembers(
   const base = typeElementsToMap(ctx, node.body.body, node._ownerScope)
   if (node.extends) {
     for (const ext of node.extends) {
-      const { props } = resolveTypeElements(ctx, ext, scope)
-      for (const key in props) {
-        if (!hasOwn(base.props, key)) {
-          base.props[key] = props[key]
+      if (
+        ext.leadingComments &&
+        ext.leadingComments.some(c => c.value.includes('@vue-ignore'))
+      ) {
+        continue
+      }
+      try {
+        const { props } = resolveTypeElements(ctx, ext, scope)
+        for (const key in props) {
+          if (!hasOwn(base.props, key)) {
+            base.props[key] = props[key]
+          }
         }
+      } catch (e) {
+        ctx.error(
+          `Failed to resolve extends base type.\nIf this previously worked in 3.2, ` +
+            `you can instruct the compiler to ignore this extend by adding ` +
+            `/* @vue-ignore */ before it, for example:\n\n` +
+            `interface Props extends /* @vue-ignore */ Base {}\n\n` +
+            `Note: both in 3.2 or with the ignore, the properties in the base ` +
+            `type are treated as fallthrough attrs at runtime.`,
+          ext
+        )
       }
     }
   }