Skip to content

Commit

Permalink
fix for #118: replace js/jsx with ts/tsx like tsc
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Aug 10, 2020
1 parent 2961027 commit 8349c0d
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 2 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

## Unreleased

* Reduce memory usage by 30-40% ([#304](https://github.com/evanw/esbuild/issues/304))
* Reduce memory usage for large builds by 30-40% ([#304](https://github.com/evanw/esbuild/issues/304))

This release reduces memory usage. Memory is reduced by ~30% for all builds by avoiding unnecessary per-file symbol maps, and is reduced by an additional ~10% for builds with source maps by preallocating some large arrays relating to source map output.
This release reduces memory usage. These specific percentages are likely only accurate for builds with a large number of files. Memory is reduced by ~30% for all builds by avoiding unnecessary per-file symbol maps, and is reduced by an additional ~10% for builds with source maps by preallocating some large arrays relating to source map output.

* Replace `.js` and `.jsx` with `.ts` or `.tsx` when resolving ([#118](https://github.com/evanw/esbuild/issues/118))

This adds an import path resolution behavior that's specific to the TypeScript compiler where you can use an import path that ends in `.js` or `.jsx` when the correct import path actually ends in `.ts` or `.tsx` instead. See the discussion here for more historical context: https://github.com/microsoft/TypeScript/issues/4595.

## 0.6.18

Expand Down
65 changes: 65 additions & 0 deletions internal/bundler/bundler_ts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -759,3 +759,68 @@ func TestTSExportDefaultTypeIssue316(t *testing.T) {
},
})
}

func TestTSImplicitExtensions(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
import './pick-js.js'
import './pick-ts.js'
import './pick-jsx.jsx'
import './pick-tsx.jsx'
import './order-js.js'
import './order-jsx.jsx'
`,

"/pick-js.js": `console.log("correct")`,
"/pick-js.ts": `console.log("wrong")`,

"/pick-ts.jsx": `console.log("wrong")`,
"/pick-ts.ts": `console.log("correct")`,

"/pick-jsx.jsx": `console.log("correct")`,
"/pick-jsx.tsx": `console.log("wrong")`,

"/pick-tsx.js": `console.log("wrong")`,
"/pick-tsx.tsx": `console.log("correct")`,

"/order-js.ts": `console.log("correct")`,
"/order-js.tsx": `console.log("wrong")`,

"/order-jsx.ts": `console.log("correct")`,
"/order-jsx.tsx": `console.log("wrong")`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
IsBundling: true,
AbsOutputFile: "/out.js",
},
})
}

func TestTSImplicitExtensionsMissing(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
import './mjs.mjs'
import './cjs.cjs'
import './js.js'
import './jsx.jsx'
`,
"/mjs.ts": ``,
"/mjs.tsx": ``,
"/cjs.ts": ``,
"/cjs.tsx": ``,
"/js.js.ts": ``,
"/jsx.jsx.tsx": ``,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
IsBundling: true,
AbsOutputFile: "/out.js",
},
expectedScanLog: `/entry.ts: error: Could not resolve "./mjs.mjs"
/entry.ts: error: Could not resolve "./cjs.cjs"
`,
})
}
23 changes: 23 additions & 0 deletions internal/bundler/snapshots/snapshots_ts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,29 @@ class Foo {
// /a.ts
console.log(new Foo());

================================================================================
TestTSImplicitExtensions
---------- /out.js ----------
// /pick-js.js
console.log("correct");

// /pick-ts.ts
console.log("correct");

// /pick-jsx.jsx
console.log("correct");

// /pick-tsx.tsx
console.log("correct");

// /order-js.ts
console.log("correct");

// /order-jsx.ts
console.log("correct");

// /entry.ts

================================================================================
TestTSImportEmptyNamespace
---------- /out.js ----------
Expand Down
26 changes: 26 additions & 0 deletions internal/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,32 @@ func (r *resolver) loadAsFile(path string) (string, bool) {
return path + ext, true
}
}

// TypeScript-specific behavior: if the extension is ".js" or ".jsx", try
// replacing it with ".ts" or ".tsx". At the time of writing this specific
// behavior comes from the function "loadModuleFromFile()" in the file
// "moduleNameResolver.ts" in the TypeScript compiler source code. It
// contains this comment:
//
// If that didn't work, try stripping a ".js" or ".jsx" extension and
// replacing it with a TypeScript one; e.g. "./foo.js" can be matched
// by "./foo.ts" or "./foo.d.ts"
//
// We don't care about ".d.ts" files because we can't do anything with
// those, so we ignore that part of the behavior.
//
// See the discussion here for more historical context:
// https://github.com/microsoft/TypeScript/issues/4595
if strings.HasSuffix(base, ".js") || strings.HasSuffix(base, ".jsx") {
lastDot := strings.LastIndexByte(base, '.')
// Note that the official compiler code always tries ".ts" before
// ".tsx" even if the original extension was ".jsx".
for _, ext := range []string{".ts", ".tsx"} {
if entries[base[:lastDot]+ext].Kind == fs.FileEntry {
return path[:len(path)-(len(base)-lastDot)] + ext, true
}
}
}
}

return "", false
Expand Down

0 comments on commit 8349c0d

Please sign in to comment.