Skip to content

Commit

Permalink
fix #1332: ignore tsconfig.json if target is set
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jun 2, 2021
1 parent 35c263f commit 65127d2
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 18 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

* Only respect `target` in `tsconfig.json` when esbuild's target is not configured ([#1332](https://github.com/evanw/esbuild/issues/1332))

In version 0.12.4, esbuild began respecting the `target` setting in `tsconfig.json`. However, sometimes `tsconfig.json` contains target values that should not be used. With this release, esbuild will now only use the `target` value in `tsconfig.json` as the language level when esbuild's `target` setting is not configured. If esbuild's `target` setting is configured then the `target` value in `tsconfig.json` is now ignored.

## 0.12.5

* Add support for lowering tagged template literals to ES5 ([#297](https://github.com/evanw/esbuild/issues/297))
Expand Down
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,8 @@ demo/esprima: | github/esprima
cd demo/esprima && npm ci

test-esprima: esbuild | demo/esprima
echo {} > demo/esprima/ts.json # Avoid "target: ES5" in "tsconfig.json"
cd demo/esprima && ../../esbuild --bundle src/esprima.ts --outfile=dist/esprima.js --target=es6 --platform=node --tsconfig=ts.json && npm run all-tests
cd demo/esprima && ../../esbuild --bundle src/esprima.ts --outfile=dist/esprima.js --target=es6 --platform=node --tsconfig=ts.json --minify && npm run all-tests
cd demo/esprima && ../../esbuild --bundle src/esprima.ts --outfile=dist/esprima.js --target=es6 --platform=node && npm run all-tests
cd demo/esprima && ../../esbuild --bundle src/esprima.ts --outfile=dist/esprima.js --target=es6 --platform=node --minify && npm run all-tests

################################################################################
# This runs terser's test suite through esbuild
Expand Down
32 changes: 27 additions & 5 deletions internal/bundler/bundler_tsconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1147,8 +1147,9 @@ func TestTsconfigTarget(t *testing.T) {
},
entryPaths: []string{"/Users/user/project/src/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
IsTargetUnconfigured: true,
},
expectedScanLog: `Users/user/project/src/es4/tsconfig.json: warning: Unrecognized target environment "ES4"
`,
Expand All @@ -1169,16 +1170,37 @@ func TestTsconfigTargetError(t *testing.T) {
},
entryPaths: []string{"/Users/user/project/src/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
OriginalTargetEnv: "\"esnext\"", // This should not be reported as the cause of the error
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
IsTargetUnconfigured: true,
},
expectedScanLog: `Users/user/project/src/entry.ts: error: Big integer literals are not available in the configured target environment ("ES2019")
Users/user/project/src/tsconfig.json: note: The target environment was set to "ES2019" here
`,
})
}

func TestTsconfigTargetIgnored(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.ts": `
x = 123n
`,
"/Users/user/project/src/tsconfig.json": `{
"compilerOptions": {
"target": "ES2019"
}
}`,
},
entryPaths: []string{"/Users/user/project/src/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
IsTargetUnconfigured: false,
},
})
}

func TestTsconfigUseDefineForClassFieldsES2020(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
Expand Down
6 changes: 6 additions & 0 deletions internal/bundler/snapshots/snapshots_tsconfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,12 @@ try {
}
x3?.y();

================================================================================
TestTsconfigTargetIgnored
---------- /Users/user/project/out.js ----------
// Users/user/project/src/entry.ts
x = 123n;

================================================================================
TestTsconfigUseDefineForClassFieldsES2020
---------- /Users/user/project/out.js ----------
Expand Down
3 changes: 1 addition & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
"github.com/evanw/esbuild/internal/logger"
)

type LanguageTarget int8

type JSXOptions struct {
Factory JSXExpr
Fragment JSXExpr
Expand Down Expand Up @@ -224,6 +222,7 @@ type Options struct {
JSX JSXOptions
Platform Platform

IsTargetUnconfigured bool // If true, TypeScript's "target" setting is respected
UnsupportedJSFeatures compat.JSFeature
UnsupportedCSSFeatures compat.CSSFeature
TSTarget *TSTarget
Expand Down
8 changes: 6 additions & 2 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ type optionsThatSupportStructuralEquality struct {
platform config.Platform
outputFormat config.Format
moduleType config.ModuleType
isTargetUnconfigured bool
asciiOnly bool
keepNames bool
mangleSyntax bool
Expand All @@ -351,6 +352,7 @@ func OptionsFromConfig(options *config.Options) Options {
platform: options.Platform,
outputFormat: options.OutputFormat,
moduleType: options.ModuleType,
isTargetUnconfigured: options.IsTargetUnconfigured,
asciiOnly: options.ASCIIOnly,
keepNames: options.KeepNames,
mangleSyntax: options.MangleSyntax,
Expand Down Expand Up @@ -13650,8 +13652,10 @@ func Parse(log logger.Log, source logger.Source, options Options) (result js_ast
}
}

// Include unsupported JavaScript features from the TypeScript "target" setting
if options.tsTarget != nil {
// If there is no top-level esbuild "target" setting, include unsupported
// JavaScript features from the TypeScript "target" setting. Otherwise the
// TypeScript "target" setting is ignored.
if options.isTargetUnconfigured && options.tsTarget != nil {
options.unsupportedJSFeatures |= options.tsTarget.UnsupportedJSFeatures
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ const (
type Target uint8

const (
ESNext Target = iota
DefaultTarget Target = iota
ESNext
ES5
ES2015
ES2016
Expand Down
16 changes: 11 additions & 5 deletions pkg/api/api_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,11 @@ func validateEngine(value EngineName) compat.Engine {

var versionRegex = regexp.MustCompile(`^([0-9]+)(?:\.([0-9]+))?(?:\.([0-9]+))?$`)

func validateFeatures(log logger.Log, target Target, engines []Engine) (compat.JSFeature, compat.CSSFeature, string) {
func validateFeatures(log logger.Log, target Target, engines []Engine) (bool, compat.JSFeature, compat.CSSFeature, string) {
if target == DefaultTarget && len(engines) == 0 {
return true, 0, 0, ""
}

constraints := make(map[compat.Engine][]int)
targets := make([]string, 0, 1+len(engines))

Expand All @@ -286,7 +290,7 @@ func validateFeatures(log logger.Log, target Target, engines []Engine) (compat.J
constraints[compat.ES] = []int{2019}
case ES2020:
constraints[compat.ES] = []int{2020}
case ESNext:
case ESNext, DefaultTarget:
default:
panic("Invalid target")
}
Expand Down Expand Up @@ -340,7 +344,7 @@ func validateFeatures(log logger.Log, target Target, engines []Engine) (compat.J
sort.Strings(targets)
targetEnv := strings.Join(targets, ", ")

return compat.UnsupportedJSFeatures(constraints), compat.UnsupportedCSSFeatures(constraints), targetEnv
return false, compat.UnsupportedJSFeatures(constraints), compat.UnsupportedCSSFeatures(constraints), targetEnv
}

func validateGlobalName(log logger.Log, text string) []string {
Expand Down Expand Up @@ -788,13 +792,14 @@ func rebuildImpl(
// This should already have been checked above
panic(err.Error())
}
jsFeatures, cssFeatures, targetEnv := validateFeatures(log, buildOpts.Target, buildOpts.Engines)
isTargetUnconfigured, jsFeatures, cssFeatures, targetEnv := validateFeatures(log, buildOpts.Target, buildOpts.Engines)
outJS, outCSS := validateOutputExtensions(log, buildOpts.OutExtensions)
bannerJS, bannerCSS := validateBannerOrFooter(log, "banner", buildOpts.Banner)
footerJS, footerCSS := validateBannerOrFooter(log, "footer", buildOpts.Footer)
minify := buildOpts.MinifyWhitespace && buildOpts.MinifyIdentifiers && buildOpts.MinifySyntax
defines, injectedDefines := validateDefines(log, buildOpts.Define, buildOpts.Pure, buildOpts.Platform, minify)
options := config.Options{
IsTargetUnconfigured: isTargetUnconfigured,
UnsupportedJSFeatures: jsFeatures,
UnsupportedCSSFeatures: cssFeatures,
OriginalTargetEnv: targetEnv,
Expand Down Expand Up @@ -1276,9 +1281,10 @@ func transformImpl(input string, transformOpts TransformOptions) TransformResult
}

// Convert and validate the transformOpts
jsFeatures, cssFeatures, targetEnv := validateFeatures(log, transformOpts.Target, transformOpts.Engines)
isTargetUnconfigured, jsFeatures, cssFeatures, targetEnv := validateFeatures(log, transformOpts.Target, transformOpts.Engines)
defines, injectedDefines := validateDefines(log, transformOpts.Define, transformOpts.Pure, PlatformNeutral, false /* minify */)
options := config.Options{
IsTargetUnconfigured: isTargetUnconfigured,
UnsupportedJSFeatures: jsFeatures,
UnsupportedCSSFeatures: cssFeatures,
OriginalTargetEnv: targetEnv,
Expand Down

0 comments on commit 65127d2

Please sign in to comment.