Skip to content

fix(compiler-sfc): resolve type re-exports inside declare global#14766

Merged
edison1105 merged 6 commits intovuejs:mainfrom
danielroe:fix-global-reexports
May 6, 2026
Merged

fix(compiler-sfc): resolve type re-exports inside declare global#14766
edison1105 merged 6 commits intovuejs:mainfrom
danielroe:fix-global-reexports

Conversation

@danielroe
Copy link
Copy Markdown
Member

@danielroe danielroe commented Apr 28, 2026

resolves nuxt/nuxt#30213

this was an omission in my earlier pr #13789

this now handles both named exports and star exports

Summary by CodeRabbit

  • Bug Fixes

    • Improved resolution of re‑exported global types so runtime type inference uses the original source scope and correctly records source-file dependencies, including across cache reuse.
  • Tests

    • Added tests validating re‑exported global types, preservation of source‑module scope, dependency tracking (including after cache reuse), and resolution of re‑exports from package directories.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Adds eager resolution and re-export propagation for declarations inside ambient declare global blocks, preserves existing _ownerScope when present, and improves dependency tracking (including across cache reuse); includes new tests validating cross-module re-exports and dependency recording.

Changes

Global re-export handling & tests

Layer / File(s) Summary
Data Shape / Tests Setup
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
Adds tests that declare modules and re-export types into a declare global block (named re-exports and export *), asserting runtime inference and dependency tracking (including after cache reuse).
Core Implementation
packages/compiler-sfc/src/script/resolveType.ts
When processing declare global, handle ExportNamedDeclaration with source and ExportAllDeclaration by eagerly resolving the source scope and copying exported types/declares into the global lookup; when resolving a global symbol, add the symbol’s _ownerScope file to ctx.deps if it differs from the current global scope.
Import Resolution Control
packages/compiler-sfc/src/script/resolveType.ts
importSourceToScope gains a trackDep parameter (default true); additions to ctx.deps during import resolution are guarded by this flag.
Owner-scope Post-processing
packages/compiler-sfc/src/script/resolveType.ts
Post-processing attaches _ownerScope and nested _ns._ownerScope only when missing (avoids overwriting existing owner scopes); same for collected declares.
Tests / Verification
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
New assertions verify runtime type mapping (Number/Boolean/String) from re-exported global types, retention of source-module scope for re-exported globals, and that ctx.deps includes both the global augmentation file and the originating module (also after cache reuse).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • vuejs/core#13789 — Adjusts ambient/declare-global traversal and exported-declare handling in the same area of resolveType.ts.
  • vuejs/core#14260 — Related changes to declare global processing and traversal in resolveType.ts.
  • vuejs/core#14297 — Modifies _ownerScope propagation and related resolution behavior in resolveType.ts.

Suggested reviewers

  • edison1105
  • LittleSound

Poem

🐇 I hopped through ASTs both near and far,
Re-exported names now find their star.
Owners stay put where they belong,
Deps recorded, caches hum along.
Hooray — types resolve and tests sing strong!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: resolving type re-exports inside declare global blocks, which directly addresses the primary objective.
Linked Issues check ✅ Passed The changes add comprehensive support for resolving type re-exports in declare global blocks, both test coverage and implementation, addressing the core issue where shared folder types weren't being resolved correctly.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective of resolving type re-exports inside declare global, with no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB 40 kB 35.9 kB
vue.global.prod.js 164 kB 60 kB 53.3 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.6 kB 18.9 kB 17.3 kB
createApp 56.7 kB 21.9 kB 20.1 kB
createSSRApp 61 kB 23.7 kB 21.6 kB
defineCustomElement 62.9 kB 23.9 kB 21.8 kB
overall 71.5 kB 27.3 kB 24.9 kB

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 28, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14766
npm i https://pkg.pr.new/@vue/compiler-core@14766
yarn add https://pkg.pr.new/@vue/compiler-core@14766.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14766
npm i https://pkg.pr.new/@vue/compiler-dom@14766
yarn add https://pkg.pr.new/@vue/compiler-dom@14766.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14766
npm i https://pkg.pr.new/@vue/compiler-sfc@14766
yarn add https://pkg.pr.new/@vue/compiler-sfc@14766.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14766
npm i https://pkg.pr.new/@vue/compiler-ssr@14766
yarn add https://pkg.pr.new/@vue/compiler-ssr@14766.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14766
npm i https://pkg.pr.new/@vue/reactivity@14766
yarn add https://pkg.pr.new/@vue/reactivity@14766.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14766
npm i https://pkg.pr.new/@vue/runtime-core@14766
yarn add https://pkg.pr.new/@vue/runtime-core@14766.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14766
npm i https://pkg.pr.new/@vue/runtime-dom@14766
yarn add https://pkg.pr.new/@vue/runtime-dom@14766.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14766
npm i https://pkg.pr.new/@vue/server-renderer@14766
yarn add https://pkg.pr.new/@vue/server-renderer@14766.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14766
npm i https://pkg.pr.new/@vue/shared@14766
yarn add https://pkg.pr.new/@vue/shared@14766.tgz

vue

pnpm add https://pkg.pr.new/vue@14766
npm i https://pkg.pr.new/vue@14766
yarn add https://pkg.pr.new/vue@14766.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14766
npm i https://pkg.pr.new/@vue/compat@14766
yarn add https://pkg.pr.new/@vue/compat@14766.tgz

commit: eb99300

@danielroe
Copy link
Copy Markdown
Member Author

I don't believe the test failure is related 🤔

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/compiler-sfc/src/script/resolveType.ts`:
- Around line 1340-1376: The code currently copies AST nodes by reference from
sourceScope (via sourceScope.exportedTypes/exportedDeclares) into the local
types/declares maps in the ExportNamedDeclaration re-export handling and the
ExportAllDeclaration branch, which allows later owner-scope normalization to
mutate the original sourceScope nodes; instead, clone the nodes before storing
them locally (e.g. when assigning types[exported] =
sourceScope.exportedTypes[local] and declares[exported] =
sourceScope.exportedDeclares[local], and when merging Object.assign(types,
sourceScope.exportedTypes)/declares) so the local scope gets fresh copies; use
the project’s existing node-cloning helper (or a lightweight deep/structured
clone) to produce new node instances so owner/parent normalization won’t corrupt
the cached source file state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c25b506-3292-41c5-a7e5-e4a6555cbe08

📥 Commits

Reviewing files that changed from the base of the PR and between 3310eea and 401f4ed.

📒 Files selected for processing (2)
  • packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
  • packages/compiler-sfc/src/script/resolveType.ts

Comment thread packages/compiler-sfc/src/script/resolveType.ts
@danielroe
Copy link
Copy Markdown
Member Author

thank you dear rabbit 🐇

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts (1)

1500-1534: Consider asserting transitive dependency tracking for re-exported globals.

This test validates type resolution well, but adding a deps assertion would also lock in cache/invalidation behavior for ./foo, ./bar, and ./baz loaded via /global.d.ts.

Suggested test hardening
-      expect(
-        resolve(`defineProps<Foo>()`, files, globalTypeFiles).props,
-      ).toStrictEqual({
+      const fooRes = resolve(`defineProps<Foo>()`, files, globalTypeFiles)
+      expect(fooRes.props).toStrictEqual({
         foo: ['Number'],
       })
+      expect(fooRes.deps && [...fooRes.deps]).toEqual(
+        expect.arrayContaining(['/global.d.ts', '/foo.ts']),
+      )

-      expect(
-        resolve(`defineProps<Bar>()`, files, globalTypeFiles).props,
-      ).toStrictEqual({
+      const barRes = resolve(`defineProps<Bar>()`, files, globalTypeFiles)
+      expect(barRes.props).toStrictEqual({
         bar: ['Boolean'],
       })
+      expect(barRes.deps && [...barRes.deps]).toEqual(
+        expect.arrayContaining(['/global.d.ts', '/bar.ts']),
+      )

-      expect(
-        resolve(`defineProps<Baz>()`, files, globalTypeFiles).props,
-      ).toStrictEqual({
+      const bazRes = resolve(`defineProps<Baz>()`, files, globalTypeFiles)
+      expect(bazRes.props).toStrictEqual({
         baz: ['String'],
       })
+      expect(bazRes.deps && [...bazRes.deps]).toEqual(
+        expect.arrayContaining(['/global.d.ts', '/baz.ts']),
+      )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts` around
lines 1500 - 1534, The test "global types with re-exports" verifies props but
doesn't assert dependency tracking; update the test to also assert resolve(...)
returns the expected deps so cache/invalidation is locked in: after each
resolve(...) call (or once per file), assert the returned deps includes
'/global.d.ts' plus the transitive source(s) ('/foo.ts', '/bar.ts', '/baz.ts')
as appropriate; modify the assertions around resolve in this test to check both
.props and .deps (using the resolve helper and the file names above) so
re-exported globals are tracked as dependencies.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts`:
- Around line 1500-1534: The test "global types with re-exports" verifies props
but doesn't assert dependency tracking; update the test to also assert
resolve(...) returns the expected deps so cache/invalidation is locked in: after
each resolve(...) call (or once per file), assert the returned deps includes
'/global.d.ts' plus the transitive source(s) ('/foo.ts', '/bar.ts', '/baz.ts')
as appropriate; modify the assertions around resolve in this test to check both
.props and .deps (using the resolve helper and the file names above) so
re-exported globals are tracked as dependencies.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cc9fea78-4d83-405c-9c81-dc15cfc0f0bf

📥 Commits

Reviewing files that changed from the base of the PR and between 401f4ed and 2bdd516.

📒 Files selected for processing (2)
  • packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
  • packages/compiler-sfc/src/script/resolveType.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/compiler-sfc/src/script/resolveType.ts

@edison1105 edison1105 added scope: sfc 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Apr 30, 2026
@edison1105 edison1105 added the ready to merge The PR is ready to be merged. label May 6, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/compiler-sfc/src/script/resolveType.ts`:
- Around line 1352-1380: The code calls importSourceToScope while indexing
`declare global`, which mutates ctx.deps and causes spurious dependency records;
fix this by preventing dependency tracking during those calls (either add an
options param to importSourceToScope like {recordDeps:false} and pass it from
the `ExportNamedDeclaration`/`ExportAllDeclaration` branches inside the
declare-global handling, or temporarily save/restore ctx.deps around the call),
ensuring only the real resolved source is recorded by the normal lookup path;
reference importSourceToScope, ctx.deps, and the export handling blocks that
handle ExportNamedDeclaration/ExportAllDeclaration in declare global.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 246cb6ca-752a-48d4-b8ca-22388d859fa5

📥 Commits

Reviewing files that changed from the base of the PR and between 2bdd516 and 28c5912.

📒 Files selected for processing (2)
  • packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
  • packages/compiler-sfc/src/script/resolveType.ts

Comment thread packages/compiler-sfc/src/script/resolveType.ts
@vuejs vuejs deleted a comment from edison1105 May 6, 2026
@edison1105
Copy link
Copy Markdown
Member

/ecosystem-ci run

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/compiler-sfc/src/script/resolveType.ts`:
- Around line 782-785: Cache reuse short-circuits by returning previously
resolved entries (via _resolvedElements / _resolvedReference) but only adds the
immediate owner (resolved._ownerScope) to ctx.deps, so transitive source deps
(e.g., global.d.ts -> foo.ts -> bar.ts or foo.ts -> types.ts) are lost; update
the resolution path in resolveType.ts to walk the chain of owner scopes for a
resolved entry (starting from resolved and following resolved._ownerScope links
until null or s) and add each ownerScope.filename into ctx.deps (in addition to
the current immediate-owner logic that checks resolved._ownerScope !== s),
ensuring you also handle cached _resolvedElements / _resolvedReference cases by
collecting and merging their transitive owner filenames into ctx.deps so deeper
files aren’t dropped on subsequent compiles.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30c9d70f-ede7-4406-abaf-95d77c8eb757

📥 Commits

Reviewing files that changed from the base of the PR and between ffec9c0 and cc2e2a0.

📒 Files selected for processing (2)
  • packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
  • packages/compiler-sfc/src/script/resolveType.ts

Comment thread packages/compiler-sfc/src/script/resolveType.ts
@vuejs vuejs deleted a comment from edison1105 May 6, 2026
@vue-bot
Copy link
Copy Markdown
Contributor

vue-bot commented May 6, 2026

📝 Ran ecosystem CI: Open

suite result latest scheduled
pinia success success
radix-vue success success
nuxt success failure
test-utils success success
vant success success
vitepress success success
language-tools success success
vue-simple-compiler success success
quasar success success
vue-i18n success success
primevue success success
vuetify success success
vueuse success success
vue-macros success success
router success success
vite-plugin-vue success success

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/compiler-sfc/src/script/resolveType.ts (1)

155-176: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replay cached call-signature deps too.

ResolvedElements also backs defineEmits(), but recordResolvedElementDeps() only re-adds prop owners. On a cache hit, an imported interface that contributes only calls via extends will lose its transitive source files from ctx.deps, so emit-type edits can stop invalidating HMR correctly.

Possible fix
 interface ResolvedElements {
   props: Record<
     string,
     (TSPropertySignature | TSMethodSignature) & {
       // resolved props always has ownerScope attached
       _ownerScope: TypeScope
     }
   >
-  calls?: (TSCallSignatureDeclaration | TSFunctionType)[]
+  calls?: ((TSCallSignatureDeclaration | TSFunctionType) & MaybeWithScope)[]
 }

 function recordResolvedElementDeps(
   ctx: TypeResolveContext,
-  { props }: ResolvedElements,
+  { props, calls }: ResolvedElements,
 ): void {
   for (const key in props) {
     recordScopeDep(ctx, props[key]._ownerScope)
   }
+  for (const call of calls || []) {
+    recordScopeDep(ctx, call._ownerScope)
+  }
 }
     case 'TSFunctionType': {
+      ;(node as MaybeWithScope)._ownerScope ??= scope
       return { props: {}, calls: [node] }
     }
     } else if (e.type === 'TSCallSignatureDeclaration') {
+      ;(e as MaybeWithScope)._ownerScope = scope
       ;(res.calls || (res.calls = [])).push(e)
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/compiler-sfc/src/script/resolveType.ts` around lines 155 - 176, The
cache hit path in resolveTypeElements only replays deps for props via
recordResolvedElementDeps, which ignores call-signature contributors, causing
their _ownerScope to not be re-recorded; update recordResolvedElementDeps (or
the cache-hit handling in resolveTypeElements) to also iterate over
ResolvedElements.calls and call recordScopeDep(ctx, call._ownerScope) for each
call entry (in addition to props) so imported interfaces that only contribute
call signatures still have their transitive source files added to ctx.deps.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/compiler-sfc/src/script/resolveType.ts`:
- Around line 155-176: The cache hit path in resolveTypeElements only replays
deps for props via recordResolvedElementDeps, which ignores call-signature
contributors, causing their _ownerScope to not be re-recorded; update
recordResolvedElementDeps (or the cache-hit handling in resolveTypeElements) to
also iterate over ResolvedElements.calls and call recordScopeDep(ctx,
call._ownerScope) for each call entry (in addition to props) so imported
interfaces that only contribute call signatures still have their transitive
source files added to ctx.deps.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4dbfd0c7-e63e-4fe8-b310-2c22cfb2211b

📥 Commits

Reviewing files that changed from the base of the PR and between ffec9c0 and eb99300.

📒 Files selected for processing (2)
  • packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
  • packages/compiler-sfc/src/script/resolveType.ts

@edison1105 edison1105 merged commit acfffe3 into vuejs:main May 6, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged. scope: sfc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shared folder types and extending interface in Vue component setup error

3 participants