Skip to content

Commit

Permalink
fix #792: resolve absolute paths in tsconfig.json
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 12, 2021
1 parent 1650459 commit f60ebf0
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

This change is similar to the one from the previous release for disabled files, but it applies to package paths instead of relative paths. It's relevant when using packages that override dependencies with alternative packages using the `browser` field in their `package.json` file. Using relative paths instead of absolute paths fixes a determinism issue where build output was different on different systems. This fix was contributed by [@eelco](https://github.com/eelco).

* Handle absolute paths in `tsconfig.json` ([#792](https://github.com/evanw/esbuild/issues/792))

Some automatically-generated `tsconfig.json` paths can have absolute paths in them. This is allowed by the TypeScript compiler (specifically in the `paths` and `extends` fields). With this release, esbuild now supports absolute paths in `paths` and `extends` too.

## 0.8.44

* Create a logo for esbuild ([#61](https://github.com/evanw/esbuild/issues/61))
Expand Down
87 changes: 77 additions & 10 deletions internal/bundler/bundler_tsconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,21 @@ func TestTsConfigPaths(t *testing.T) {
import test3 from 'test3/foo'
import test4 from 'test4/foo'
import test5 from 'test5/foo'
import absolute from './absolute'
import absoluteIn from './absolute-in'
import absoluteInStar from './absolute-in-star'
import absoluteOut from './absolute-out'
import absoluteOutStar from './absolute-out-star'
export default {
test0,
test1,
test2,
test3,
test4,
test5,
absolute,
absoluteIn,
absoluteInStar,
absoluteOut,
absoluteOutStar,
}
`,
"/Users/user/project/baseurl_dot/tsconfig.json": `
Expand All @@ -49,7 +55,10 @@ func TestTsConfigPaths(t *testing.T) {
"t*t3/foo": ["./test3-succ*s.ts"],
"test4/*": ["./test4-first/*", "./test4-second/*"],
"test5/*": ["./test5-first/*", "./test5-second/*"],
"/virtual/*": ["./actual/*"],
"/virtual-in/test": ["./actual/test"],
"/virtual-in-star/*": ["./actual/*"],
"/virtual-out/test": ["/Users/user/project/baseurl_dot/actual/test"],
"/virtual-out-star/*": ["/Users/user/project/baseurl_dot/actual/*"],
}
}
}
Expand All @@ -72,8 +81,17 @@ func TestTsConfigPaths(t *testing.T) {
"/Users/user/project/baseurl_dot/test5-second/foo.ts": `
export default 'test5-success'
`,
"/Users/user/project/baseurl_dot/absolute.ts": `
export {default} from '/virtual/test'
"/Users/user/project/baseurl_dot/absolute-in.ts": `
export {default} from '/virtual-in/test'
`,
"/Users/user/project/baseurl_dot/absolute-in-star.ts": `
export {default} from '/virtual-in-star/test'
`,
"/Users/user/project/baseurl_dot/absolute-out.ts": `
export {default} from '/virtual-out/test'
`,
"/Users/user/project/baseurl_dot/absolute-out-star.ts": `
export {default} from '/virtual-out-star/test'
`,
"/Users/user/project/baseurl_dot/actual/test.ts": `
export default 'absolute-success'
Expand All @@ -87,15 +105,21 @@ func TestTsConfigPaths(t *testing.T) {
import test3 from 'test3/foo'
import test4 from 'test4/foo'
import test5 from 'test5/foo'
import absolute from './absolute'
import absoluteIn from './absolute-in'
import absoluteInStar from './absolute-in-star'
import absoluteOut from './absolute-out'
import absoluteOutStar from './absolute-out-star'
export default {
test0,
test1,
test2,
test3,
test4,
test5,
absolute,
absoluteIn,
absoluteInStar,
absoluteOut,
absoluteOutStar,
}
`,
"/Users/user/project/baseurl_nested/tsconfig.json": `
Expand All @@ -109,7 +133,10 @@ func TestTsConfigPaths(t *testing.T) {
"t*t3/foo": ["./test3-succ*s.ts"],
"test4/*": ["./test4-first/*", "./test4-second/*"],
"test5/*": ["./test5-first/*", "./test5-second/*"],
"/virtual/*": ["./actual/*"],
"/virtual-in/test": ["./actual/test"],
"/virtual-in-star/*": ["./actual/*"],
"/virtual-out/test": ["/Users/user/project/baseurl_nested/nested/actual/test"],
"/virtual-out-star/*": ["/Users/user/project/baseurl_nested/nested/actual/*"],
}
}
}
Expand All @@ -132,8 +159,17 @@ func TestTsConfigPaths(t *testing.T) {
"/Users/user/project/baseurl_nested/nested/test5-second/foo.ts": `
export default 'test5-success'
`,
"/Users/user/project/baseurl_nested/absolute.ts": `
export {default} from '/virtual/test'
"/Users/user/project/baseurl_nested/absolute-in.ts": `
export {default} from '/virtual-in/test'
`,
"/Users/user/project/baseurl_nested/absolute-in-star.ts": `
export {default} from '/virtual-in/test'
`,
"/Users/user/project/baseurl_nested/absolute-out.ts": `
export {default} from '/virtual-out/test'
`,
"/Users/user/project/baseurl_nested/absolute-out-star.ts": `
export {default} from '/virtual-out-star/test'
`,
"/Users/user/project/baseurl_nested/nested/actual/test.ts": `
export default 'absolute-success'
Expand Down Expand Up @@ -588,6 +624,37 @@ func TestTsconfigJsonExtends(t *testing.T) {
})
}

func TestTsconfigJsonExtendsAbsolute(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/entry.jsx": `
console.log(<div/>, <></>)
`,
"/Users/user/project/tsconfig.json": `
{
"extends": "/Users/user/project/base.json",
"compilerOptions": {
"jsxFragmentFactory": "derivedFragment"
}
}
`,
"/Users/user/project/base.json": `
{
"compilerOptions": {
"jsxFactory": "baseFactory",
"jsxFragmentFactory": "baseFragment"
}
}
`,
},
entryPaths: []string{"/Users/user/project/entry.jsx"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
},
})
}

func TestTsconfigJsonExtendsThreeLevels(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
Expand Down
16 changes: 14 additions & 2 deletions internal/bundler/snapshots/snapshots_tsconfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ var baseurl_dot_default = {
test3: test3_success_default,
test4: foo_default2,
test5: foo_default3,
absolute: test_default
absoluteIn: test_default,
absoluteInStar: test_default,
absoluteOut: test_default,
absoluteOutStar: test_default
};

// Users/user/project/baseurl_nested/nested/test0-success.ts
Expand Down Expand Up @@ -96,7 +99,10 @@ var baseurl_nested_default = {
test3: test3_success_default2,
test4: foo_default5,
test5: foo_default6,
absolute: test_default2
absoluteIn: test_default2,
absoluteInStar: test_default2,
absoluteOut: test_default2,
absoluteOutStar: test_default2
};

// Users/user/project/entry.ts
Expand Down Expand Up @@ -220,6 +226,12 @@ TestTsconfigJsonExtends
// entry.jsx
console.log(/* @__PURE__ */ baseFactory("div", null), /* @__PURE__ */ baseFactory(derivedFragment, null));

================================================================================
TestTsconfigJsonExtendsAbsolute
---------- /out.js ----------
// Users/user/project/entry.jsx
console.log(/* @__PURE__ */ baseFactory("div", null), /* @__PURE__ */ baseFactory(derivedFragment, null));

================================================================================
TestTsconfigJsonExtendsLoop
---------- /out.js ----------
Expand Down
15 changes: 12 additions & 3 deletions internal/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,10 @@ func (r *resolver) parseTSConfig(file string, visited map[string]bool) (*TSConfi
}
} else {
// If this is a regular path, search relative to the enclosing directory
extendsFile := r.fs.Join(fileDir, extends)
extendsFile := extends
if !r.fs.IsAbs(extends) {
extendsFile = r.fs.Join(fileDir, extends)
}
for _, fileToCheck := range []string{extendsFile, extendsFile + ".json"} {
base, err := r.parseTSConfig(fileToCheck, visited)
if err == nil {
Expand Down Expand Up @@ -1200,7 +1203,10 @@ func (r *resolver) matchTSConfigPaths(tsConfigJSON *TSConfigJSON, path string, k
if key == path {
for _, originalPath := range originalPaths {
// Load the original path relative to the "baseUrl" from tsconfig.json
absoluteOriginalPath := r.fs.Join(tsConfigJSON.BaseURLForPaths, originalPath)
absoluteOriginalPath := originalPath
if !r.fs.IsAbs(originalPath) {
absoluteOriginalPath = r.fs.Join(tsConfigJSON.BaseURLForPaths, originalPath)
}
if absolute, ok := r.loadAsFileOrDirectory(absoluteOriginalPath, kind); ok {
return absolute, true
}
Expand Down Expand Up @@ -1250,7 +1256,10 @@ func (r *resolver) matchTSConfigPaths(tsConfigJSON *TSConfigJSON, path string, k
originalPath = strings.Replace(originalPath, "*", matchedText, 1)

// Load the original path relative to the "baseUrl" from tsconfig.json
absoluteOriginalPath := r.fs.Join(tsConfigJSON.BaseURLForPaths, originalPath)
absoluteOriginalPath := originalPath
if !r.fs.IsAbs(originalPath) {
absoluteOriginalPath = r.fs.Join(tsConfigJSON.BaseURLForPaths, originalPath)
}
if absolute, ok := r.loadAsFileOrDirectory(absoluteOriginalPath, kind); ok {
return absolute, true
}
Expand Down

0 comments on commit f60ebf0

Please sign in to comment.