Skip to content

fix(compiler-sfc): add resolution trying for .mts/.cts files#14402

Merged
edison1105 merged 6 commits intovuejs:mainfrom
Gehbt:feat/resolve-cmts
Feb 9, 2026
Merged

fix(compiler-sfc): add resolution trying for .mts/.cts files#14402
edison1105 merged 6 commits intovuejs:mainfrom
Gehbt:feat/resolve-cmts

Conversation

@Gehbt
Copy link
Copy Markdown
Contributor

@Gehbt Gehbt commented Feb 2, 2026

Closes vuejs/router#2611

Summary by CodeRabbit

  • Bug Fixes

    • Improved module-aware import resolution to better recognize ESM/CJS variants and additional TypeScript extensions (.mts/.cts and declaration variants), improving import precedence and reliability in mixed JS/TS projects.
    • Extended parser recognition to include new TypeScript language variants for correct parsing behavior.
  • Tests

    • Added tests covering modular JS/TS extension combinations to validate type resolution and runtime prop mapping.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 2, 2026

📝 Walkthrough

Walkthrough

Detects module type from filename suffix and expands TypeScript resolution candidates: adds .mts/.d.mts for ESM and .cts/.d.cts for CJS, updates parser language set to include cts, and adds tests for modular JS extensions. No public API changes.

Changes

Cohort / File(s) Summary
Module resolution logic
packages/compiler-sfc/src/script/resolveType.ts
Add module-type-aware extension resolution: detect .mjs/.cjs, strip JS-family suffix with unified regex, and prepend .mts/.d.mts (ESM) or .cts/.d.cts (CJS) candidates ahead of existing .ts/.d.ts and index fallbacks.
Parser context
packages/compiler-sfc/src/script/context.ts
Include cts in the set of TypeScript-like languages so TypeScript parser plugins are enabled for cts files.
Parsing/extension handling
packages/compiler-sfc/src/script/...
Recognize additional TS-related extensions (.cts, .mtsx) and adjust runtime declaration-detection regex to /\.d\.[cm]?ts$/.
Tests
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts
Add tests exercising modular JS extension resolution and precedence (.mjs/.cjs imports preferring .mts/.cts and .d.mts/.d.cts over .d.ts), asserting correct runtime prop mappings.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

ready to merge, :hammer: p3-minor-bug

Suggested reviewers

  • LittleSound

Poem

🐰 I sniffed through extensions, small and spry,
Found .mts and .cts waiting nearby.
I hopped in the resolver, nudged them in place,
Now types cross the modules with confident grace.
🥕✨

🚥 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 title clearly and specifically describes the main change: adding resolution support for .mts/.cts file extensions in the compiler-sfc package.
Linked Issues check ✅ Passed The changes implement module-type aware extension resolution for .mts and .cts files, enabling the SFC compiler to resolve types from modules using these extensions, directly addressing issue #2611's requirement to resolve RouterLinkProps and similar types.
Out of Scope Changes check ✅ Passed All changes are focused on adding resolution for .mts/.cts extensions and treating cts as a TypeScript variant, remaining within scope of the stated objectives.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


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.

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: 0

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)

988-1011: ⚠️ Potential issue | 🟠 Major

Extensionless imports won't resolve .mts/.cts files.

When moduleType is u (unknown, as with extensionless imports like ./foo), the code skips the .mts/.d.mts and .cts/.d.cts resolution branches and goes directly to trying .ts/.tsx/.d.ts. This means foo.mts and foo.cts will never be found for extensionless imports, breaking TypeScript's ESM/CJS module-kind-by-extension detection.

Add fallback resolution for .mts/.d.mts and .cts/.d.cts when moduleType === 'u' (and consider .mtsx/.ctsx JSX variants for consistency with the existing .tsx fallback):

🛠️ Proposed fix
  return (
    tryResolve(filename) ||
    (moduleType === 'm' &&
      (tryResolve(filename + `.mts`) || tryResolve(filename + `.d.mts`))) ||
    (moduleType === 'c' &&
      (tryResolve(filename + `.cts`) || tryResolve(filename + `.d.cts`))) ||
+   (moduleType === 'u' &&
+     (tryResolve(filename + `.mts`) ||
+       tryResolve(filename + `.mtsx`) ||
+       tryResolve(filename + `.d.mts`) ||
+       tryResolve(filename + `.cts`) ||
+       tryResolve(filename + `.ctsx`) ||
+       tryResolve(filename + `.d.cts`))) ||
    tryResolve(filename + `.ts`) ||
    tryResolve(filename + `.tsx`) ||
    tryResolve(filename + `.d.ts`) ||

@edison1105 edison1105 added need test The PR has missing test cases. scope: sfc labels Feb 3, 2026
@edison1105
Copy link
Copy Markdown
Member

Could you please add a test case?

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 4, 2026

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 103 kB 39.1 kB 35.2 kB
vue.global.prod.js 161 kB 59.1 kB 52.6 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 47 kB 18.3 kB 16.8 kB
createApp 55.1 kB 21.4 kB 19.6 kB
createSSRApp 59.4 kB 23.2 kB 21.1 kB
defineCustomElement 60.8 kB 23.1 kB 21.1 kB
overall 69.5 kB 26.7 kB 24.3 kB

@Gehbt
Copy link
Copy Markdown
Contributor Author

Gehbt commented Feb 8, 2026

Test case has been added @edison1105 .

@edison1105
Copy link
Copy Markdown
Member

edison1105 commented Feb 9, 2026

Thanks for the PR. However, there are some issues with the resolution order. For example, when both foo.ts and foo.mts (or foo.d.ts and foo.d.mts) exist, foo.mjs incorrectly resolves to .d.ts. I verified locally using typescript.resolveModuleName that under TS NodeNext, it actually prioritizes .d.mts (and .d.cts for cjs). I have made the fix: 0517575

node -e "
const ts = require('typescript');

const files = {
  '/foo.d.ts': 'export type X = number;',
  '/foo.d.mts': 'export type X = string;',
};

const host = {
  fileExists: (f) => f in files,
  readFile: (f) => files[f] || '',
  directoryExists: () => true,
  getDirectories: () => [],
  realpath: (f) => f,
};

const result = ts.resolveModuleName(
  './foo.mjs',
  '/test.mts',
  { moduleResolution: ts.ModuleResolutionKind.NodeNext },
  host
);

console.log('TS NodeNext resolves ./foo.mjs to:', result.resolvedModule?.resolvedFileName); // foo.d.mts
"

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Feb 9, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14402
npm i https://pkg.pr.new/@vue/compiler-core@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14402
npm i https://pkg.pr.new/@vue/compiler-dom@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14402
npm i https://pkg.pr.new/@vue/compiler-sfc@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14402
npm i https://pkg.pr.new/@vue/compiler-ssr@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14402
npm i https://pkg.pr.new/@vue/reactivity@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14402
npm i https://pkg.pr.new/@vue/runtime-core@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14402
npm i https://pkg.pr.new/@vue/runtime-dom@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14402
npm i https://pkg.pr.new/@vue/server-renderer@14402
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14402
npm i https://pkg.pr.new/@vue/shared@14402
yarn add https://pkg.pr.new/@vue/[email protected]

vue

pnpm add https://pkg.pr.new/vue@14402
npm i https://pkg.pr.new/vue@14402
yarn add https://pkg.pr.new/[email protected]

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14402
npm i https://pkg.pr.new/@vue/compat@14402
yarn add https://pkg.pr.new/@vue/[email protected]

commit: 0517575

@edison1105 edison1105 added ready to merge The PR is ready to be merged. and removed need test The PR has missing test cases. labels Feb 9, 2026
@edison1105
Copy link
Copy Markdown
Member

/ecosystem-ci run

@vue-bot
Copy link
Copy Markdown
Contributor

vue-bot commented Feb 9, 2026

📝 Ran ecosystem CI: Open

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

@edison1105 edison1105 merged commit c09d41f into vuejs:main Feb 9, 2026
18 of 19 checks passed
@Gehbt Gehbt deleted the feat/resolve-cmts branch February 9, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

vue-router@5 can't extend RouterLinkProps and other types

3 participants