Skip to content

fix(tsconfig): resolve baseUrl / paths against the canonical tsconfig path#1148

Merged
Boshen merged 1 commit into
mainfrom
test-extends-baseurl-paths-symlink
May 24, 2026
Merged

fix(tsconfig): resolve baseUrl / paths against the canonical tsconfig path#1148
Boshen merged 1 commit into
mainfrom
test-extends-baseurl-paths-symlink

Conversation

@Boshen

@Boshen Boshen commented May 24, 2026

Copy link
Copy Markdown
Member

closes #1080

…nfig path

When `extends` traverses a symlink (e.g. a pnpm workspace package), `baseUrl`
and `paths` were anchored at the symlink's parent instead of the real
tsconfig directory.

`Cache::get_tsconfig` now canonicalizes the tsconfig file path and passes it
to `TsConfig::parse` as a separate `canonical_path` parameter. `paths_base`
is computed from the canonical directory while `tsconfig.path` (cache
identity, error reporting, circular-extend detection) keeps the requested
path unchanged.
@codecov

codecov Bot commented May 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.15%. Comparing base (ef0c86b) to head (209cbea).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1148      +/-   ##
==========================================
+ Coverage   93.11%   93.15%   +0.03%     
==========================================
  Files          22       22              
  Lines        4141     4150       +9     
==========================================
+ Hits         3856     3866      +10     
+ Misses        285      284       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented May 24, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.65%

❌ 1 regressed benchmark
✅ 12 untouched benchmarks
⏩ 5 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
resolver_memory[multi-thread] 387.4 µs 406.3 µs -4.65%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing test-extends-baseurl-paths-symlink (209cbea) with main (ef0c86b)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Boshen Boshen merged commit 27a9864 into main May 24, 2026
18 checks passed
@Boshen Boshen deleted the test-extends-baseurl-paths-symlink branch May 24, 2026 05:39
@oxc-guard oxc-guard Bot mentioned this pull request May 24, 2026
Boshen added a commit that referenced this pull request May 24, 2026
…em (#1150)

## Summary

Closes #1075.

`rootDirs` entries inherited via `extends` were being normalized against
the caller tsconfig's directory at `build()` time, instead of against
the directory of the config that actually declared them. This broke the
SvelteKit pattern where `tsconfig.json` extends
`.svelte-kit/tsconfig.json` and the latter declares `rootDirs: ["..",
"./types"]` relative to itself.

## Fix

Mirror the established `paths_base` pattern: normalize non-template
`rootDirs` entries at parse time against each config's own canonical
directory (`canonical_path.parent()`). The `build()` step keeps
`${configDir}` template substitution only, so templates still resolve
against the root caller's directory as before.

After this change, `extend_tsconfig`'s existing clone-from-parent is
correct without further work — the parent's entries are already absolute
by the time the child inherits them.

## Verification

Cross-checked against TypeScript 6.0.3 via `tsc --traceResolution`:

- **SvelteKit case (no symlinks)** — TS resolves `rootDirs: ["..",
"./types"]` declared in `.svelte-kit/tsconfig.json` against
`.svelte-kit/`, exactly matching the fixed behavior.
- **Symlinked `extends`** (`node_modules/shared-config` → real-configs)
— TS anchors inherited `rootDirs` at the **canonical** path of the
parent config, matching the `paths_base` precedent landed in #1148.

Verified against typescript-go source
(`internal/tsoptions/tsconfigparsing.go`): `rootDirs` is declared
`IsFilePath: true` and `normalizeNonListOptionValue` calls
`GetNormalizedAbsolutePath(value, basePath)` at parse time per config;
`handleOptionConfigDirTemplateSubstitution` runs once afterward against
the root caller's directory.

New fixture `fixtures/tsconfig/cases/root-dirs-extends/` mirrors the
SvelteKit reproduction; new test `test_root_dirs_via_extends` fails on
`main` (`NotFound("./$types")`) and passes after the fix.
Boshen added a commit that referenced this pull request May 25, 2026
## 🤖 New release

* `oxc_resolver`: 11.19.1 -> 11.19.2
* `oxc_resolver_napi`: 11.19.1 -> 11.19.2

<details><summary><i><b>Changelog</b></i></summary><p>

## `oxc_resolver`

<blockquote>

##
[11.19.2](v11.19.1...v11.19.2)
- 2026-05-25

### <!-- 1 -->🐛 Bug Fixes

- *(tsconfig)* apply later-wins semantics for extends array
([#1156](#1156)) (by
@Boshen)
- *(tsconfig)* walk past a tsconfig that doesn't claim the file
([#1154](#1154)) (by
@Boshen)
- *(tsconfig)* let project references take priority over their parent
([#1151](#1151)) (by
@Boshen)
- *(tsconfig)* resolve `rootDirs` against the config that declared them
([#1150](#1150)) (by
@Boshen)
- *(tsconfig)* resolve `baseUrl` / `paths` against the canonical
tsconfig path
([#1148](#1148)) (by
@Boshen)
- strip query fragments when calling `find_tsconfig`
([#1147](#1147)) (by
@Boshen)
- avoid panic in resolve_file for parentless paths
([#1053](#1053)) (by
@Boshen)
- *(dts)* strip ./ prefix from package entry when matching typesVersions
([#1051](#1051)) (by
@Boshen)
- *(dts)* expand Declaration to TypeScript|Declaration for package entry
resolution
([#1050](#1050)) (by
@Boshen)
- *(dts)* prefer declaration extensions over JS in exports-resolved
paths ([#1047](#1047))
(by @Boshen)
- avoid wasm/wasi dead-code lint in NodePath
([#1043](#1043)) (by
@Boshen)
- *(napi)* replace panics with error returns to prevent WASM traps
([#1055](#1055)) (by
@Boshen)

### <!-- 2 -->🚜 Refactor

- remove clear_cache test that dynamically creates fixtures (by @Boshen)
- move resolve and misc fixtures into fixtures/integration (by @Boshen)
- replace ignored doctest with link to example (by @Boshen)
- consolidate fixture directories for better test file mapping (by
@Boshen)
- replace `url` crate with `percent-encoding`
([#1065](#1065)) (by
@Boshen)

### <!-- 4 -->⚡ Performance

- *(cache)* pack CachedPathImpl::meta into a CachedMeta byte
([#1144](#1144)) (by
@Boshen)
- *(cache)* store canonical path as Box<Path> instead of PathBuf
([#1143](#1143)) (by
@Boshen)
- *(alias)* fast-reject alias entries by cached first byte
([#1142](#1142)) (by
@Boshen)

### <!-- 6 -->🧪 Testing

- *(tsconfig)* port lookup scenarios from typescript-go
([#1155](#1155)) (by
@Boshen)
- add 28 tests to improve coverage (92% → 93%)
([#1082](#1082)) (by
@Boshen)

### Contributors

* @Boshen
* @renovate[bot]
</blockquote>



</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: oxc-guard[bot] <276638029+oxc-guard[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant