]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): skip circular tsconfig project reference (#11680)
authorcyrilluce <cyrilluce@gmail.com>
Thu, 29 Aug 2024 03:42:35 +0000 (11:42 +0800)
committerGitHub <noreply@github.com>
Thu, 29 Aug 2024 03:42:35 +0000 (11:42 +0800)
Co-authored-by: cluezhang <cluezhang@futurefab.ai>
close #11382

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

index ff33882568e7c8eaf6c57e16a99dd0d15e4136d1..816d74bc64905a4daf1e7aa30147d261d48de4b4 100644 (file)
@@ -1185,6 +1185,49 @@ describe('resolveType', () => {
       expect(deps && [...deps]).toStrictEqual(['/user.ts'])
     })
 
+    // #11382
+    test('ts module resolve circular project reference', () => {
+      const files = {
+        '/tsconfig.json': JSON.stringify({
+          exclude: ['**/*.ts', '**/*.vue'],
+          references: [
+            {
+              path: './tsconfig.web.json',
+            },
+          ],
+        }),
+        '/tsconfig.web.json': JSON.stringify({
+          include: ['**/*.ts', '**/*.vue'],
+          compilerOptions: {
+            composite: true,
+            paths: {
+              user: ['./user.ts'],
+            },
+          },
+          references: [
+            {
+              // circular reference
+              path: './tsconfig.json',
+            },
+          ],
+        }),
+        '/user.ts': 'export type User = { bar: string }',
+      }
+
+      const { props, deps } = resolve(
+        `
+        import { User } from 'user'
+        defineProps<User>() 
+        `,
+        files,
+      )
+
+      expect(props).toStrictEqual({
+        bar: ['String'],
+      })
+      expect(deps && [...deps]).toStrictEqual(['/user.ts'])
+    })
+
     test('ts module resolve w/ path aliased vue file', () => {
       const files = {
         '/tsconfig.json': JSON.stringify({
index ee0a723991c85368c7a93ac400f8ac22a5c73ed2..6bb647f11ff2ac418827e85ac1e1cdb7ce3b2b59 100644 (file)
@@ -1070,6 +1070,7 @@ function loadTSConfig(
   configPath: string,
   ts: typeof TS,
   fs: FS,
+  visited = new Set<string>(),
 ): TS.ParsedCommandLine[] {
   // The only case where `fs` is NOT `ts.sys` is during tests.
   // parse config host requires an extra `readDirectory` method
@@ -1089,14 +1090,15 @@ function loadTSConfig(
     configPath,
   )
   const res = [config]
+  visited.add(configPath)
   if (config.projectReferences) {
     for (const ref of config.projectReferences) {
       const refPath = ts.resolveProjectReferencePath(ref)
-      if (!fs.fileExists(refPath)) {
+      if (visited.has(refPath) || !fs.fileExists(refPath)) {
         continue
       }
       tsConfigRefMap.set(refPath, configPath)
-      res.unshift(...loadTSConfig(refPath, ts, fs))
+      res.unshift(...loadTSConfig(refPath, ts, fs, visited))
     }
   }
   return res