Skip to content

Commit 6e6f15f

Browse files
committed
fix #3767: tsconfig.json files inside symlinks
1 parent b7dcb95 commit 6e6f15f

File tree

7 files changed

+53
-0
lines changed

7 files changed

+53
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* Fix `tsconfig.json` files inside symlinked directories ([#3767](https://github.com/evanw/esbuild/issues/3767))
6+
7+
This release fixes an issue with a scenario involving a `tsconfig.json` file that `extends` another file from within a symlinked directory that uses the `paths` feature. In that case, the implicit `baseURL` value should be based on the real path (i.e. after expanding all symbolic links) instead of the original path. This was already done for other files that esbuild resolves but was not yet done for `tsconfig.json` because it's special-cased (the regular path resolver can't be used because the information inside `tsconfig.json` is involved in path resolution). Note that this fix no longer applies if the `--preserve-symlinks` setting is enabled.
8+
39
## 0.21.2
410

511
* Correct `this` in field and accessor decorators ([#3761](https://github.com/evanw/esbuild/issues/3761))

internal/fs/fs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ type FS interface {
201201
Join(parts ...string) string
202202
Cwd() string
203203
Rel(base string, target string) (string, bool)
204+
EvalSymlinks(path string) (string, bool)
204205

205206
// This is used in the implementation of "Entry"
206207
kind(dir string, base string) (symlink string, kind EntryKind)

internal/fs/fs_mock.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ func (fs *mockFS) Rel(base string, target string) (string, bool) {
281281
return target, true
282282
}
283283

284+
func (fs *mockFS) EvalSymlinks(path string) (string, bool) {
285+
return "", false
286+
}
287+
284288
func (fs *mockFS) kind(dir string, base string) (symlink string, kind EntryKind) {
285289
panic("This should never be called")
286290
}

internal/fs/fs_real.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@ func (fs *realFS) Rel(base string, target string) (string, bool) {
340340
return "", false
341341
}
342342

343+
func (fs *realFS) EvalSymlinks(path string) (string, bool) {
344+
if path, err := fs.fp.evalSymlinks(path); err == nil {
345+
return path, true
346+
}
347+
return "", false
348+
}
349+
343350
func (fs *realFS) readdir(dirname string) (entries []string, canonicalError error, originalError error) {
344351
BeforeFileOpen()
345352
defer AfterFileClose()

internal/fs/fs_zip.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ func (fs *zipFS) Rel(base string, target string) (string, bool) {
322322
return fs.inner.Rel(base, target)
323323
}
324324

325+
func (fs *zipFS) EvalSymlinks(path string) (string, bool) {
326+
return fs.inner.EvalSymlinks(path)
327+
}
328+
325329
func (fs *zipFS) kind(dir string, base string) (symlink string, kind EntryKind) {
326330
return fs.inner.kind(dir, base)
327331
}

internal/resolver/resolver.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,13 @@ var errParseErrorAlreadyLogged = errors.New("(error already logged)")
11651165
// Nested calls may also return "parseErrorImportCycle". In that case the
11661166
// caller is responsible for logging an appropriate error message.
11671167
func (r resolverQuery) parseTSConfig(file string, visited map[string]bool) (*TSConfigJSON, error) {
1168+
// Resolve any symlinks first before parsing the file
1169+
if !r.options.PreserveSymlinks {
1170+
if real, ok := r.fs.EvalSymlinks(file); ok {
1171+
file = real
1172+
}
1173+
}
1174+
11681175
// Don't infinite loop if a series of "extends" links forms a cycle
11691176
if visited[file] {
11701177
return nil, errParseErrorImportCycle

scripts/end-to-end-tests.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,30 @@ tests.push(
218218
export let bar = 'bar'
219219
`,
220220
}),
221+
222+
// See: https://github.com/evanw/esbuild/issues/3767
223+
test(['apps/client/src/index.ts', '--bundle', '--outfile=node.js'], {
224+
'apps/client/src/index.ts': `
225+
import { foo } from '~/foo'
226+
if (foo !== 'foo') throw 'fail'
227+
`,
228+
'apps/client/src/foo.ts': `
229+
export const foo = 'foo'
230+
`,
231+
'apps/client/tsconfig.json': `{
232+
"extends": "@repo/tsconfig/base"
233+
}`,
234+
'apps/client/node_modules/@repo/tsconfig': {
235+
symlink: `../../../../tooling/typescript`,
236+
},
237+
'tooling/typescript/base.json': `{
238+
"compilerOptions": {
239+
"paths": {
240+
"~/*": ["../../apps/client/src/*"]
241+
}
242+
}
243+
}`,
244+
}),
221245
)
222246

223247
// Test coverage for a special JSX error message

0 commit comments

Comments
 (0)