Skip to content

Commit

Permalink
fix #2347: strip "use strict" when targeting ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jun 24, 2022
1 parent 8b0da1d commit 5d7ac55
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 16 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@
* `.woff` => `font/woff`
* `.woff2` => `font/woff2`

* Remove `"use strict";` when targeting ESM ([#2347](https://github.com/evanw/esbuild/issues/2347))

All ES module code is automatically in strict mode, so a `"use strict";` directive is unnecessary. With this release, esbuild will now remove the `"use strict";` directive if the output format is ESM. This change makes the generated output file a few bytes smaller:

```js
// Original code
'use strict'
export let foo = 123

// Old output (with --format=esm --minify)
"use strict";let t=123;export{t as foo};

// New output (with --format=esm --minify)
let t=123;export{t as foo};
```

## 0.14.47

* Make global names more compact when `||=` is available ([#2331](https://github.com/evanw/esbuild/issues/2331))
Expand Down
36 changes: 35 additions & 1 deletion internal/bundler/bundler_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2788,7 +2788,41 @@ func TestUseStrictDirectiveBundleIssue1837(t *testing.T) {
})
}

func TestUseStrictDirectiveBundleIssue2264(t *testing.T) {
func TestUseStrictDirectiveBundleIIFEIssue2264(t *testing.T) {
default_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
'use strict'
export let a = 1
`,
},
entryPaths: []string{"/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
OutputFormat: config.FormatIIFE,
},
})
}

func TestUseStrictDirectiveBundleCJSIssue2264(t *testing.T) {
default_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
'use strict'
export let a = 1
`,
},
entryPaths: []string{"/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
OutputFormat: config.FormatCommonJS,
},
})
}

func TestUseStrictDirectiveBundleESMIssue2264(t *testing.T) {
default_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
Expand Down
59 changes: 58 additions & 1 deletion internal/bundler/bundler_tsconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1837,7 +1837,7 @@ func TestTsConfigAlwaysStrictTrueEmitDirectiveFormat(t *testing.T) {
})
}

func TestTsConfigAlwaysStrictTrueEmitDirectiveBundle(t *testing.T) {
func TestTsConfigAlwaysStrictTrueEmitDirectiveBundleIIFE(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/implicit.ts": `
Expand All @@ -1860,6 +1860,63 @@ func TestTsConfigAlwaysStrictTrueEmitDirectiveBundle(t *testing.T) {
options: config.Options{
Mode: config.ModeBundle,
AbsOutputDir: "/Users/user/project/out",
OutputFormat: config.FormatIIFE,
},
})
}

func TestTsConfigAlwaysStrictTrueEmitDirectiveBundleCJS(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/implicit.ts": `
console.log('this file should start with "use strict"')
`,
"/Users/user/project/src/explicit.ts": `
'use strict'
console.log('this file should start with "use strict"')
`,
"/Users/user/project/tsconfig.json": `{
"compilerOptions": {
"alwaysStrict": true
}
}`,
},
entryPaths: []string{
"/Users/user/project/src/implicit.ts",
"/Users/user/project/src/explicit.ts",
},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputDir: "/Users/user/project/out",
OutputFormat: config.FormatCommonJS,
},
})
}

func TestTsConfigAlwaysStrictTrueEmitDirectiveBundleESM(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/implicit.ts": `
console.log('this file should not start with "use strict"')
`,
"/Users/user/project/src/explicit.ts": `
'use strict'
console.log('this file should not start with "use strict"')
`,
"/Users/user/project/tsconfig.json": `{
"compilerOptions": {
"alwaysStrict": true
}
}`,
},
entryPaths: []string{
"/Users/user/project/src/implicit.ts",
"/Users/user/project/src/explicit.ts",
},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputDir: "/Users/user/project/out",
OutputFormat: config.FormatESModule,
},
})
}
5 changes: 3 additions & 2 deletions internal/bundler/linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4871,8 +4871,9 @@ func (c *linkerContext) generateChunkJS(chunks []chunkInfo, chunkIndex int, chun
isExecutable = true
}

// Add the top-level directive if present
if repr.AST.Directive != "" {
// Add the top-level directive if present (but omit "use strict" in ES
// modules because all ES modules are automatically in strict mode)
if repr.AST.Directive != "" && (repr.AST.Directive != "use strict" || c.options.OutputFormat != config.FormatESModule) {
quoted := string(js_printer.QuoteForJSON(repr.AST.Directive, c.options.ASCIIOnly)) + ";" + newline
prevOffset.AdvanceString(quoted)
j.AddString(quoted)
Expand Down
42 changes: 31 additions & 11 deletions internal/bundler/snapshots/snapshots_default.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3927,6 +3927,37 @@ await foo;
for await (foo of bar)
;

================================================================================
TestUseStrictDirectiveBundleCJSIssue2264
---------- /out.js ----------
"use strict";

// entry.js
var entry_exports = {};
__export(entry_exports, {
a: () => a
});
module.exports = __toCommonJS(entry_exports);
var a = 1;

================================================================================
TestUseStrictDirectiveBundleESMIssue2264
---------- /out.js ----------
// entry.js
var a = 1;
export {
a
};

================================================================================
TestUseStrictDirectiveBundleIIFEIssue2264
---------- /out.js ----------
"use strict";
(() => {
// entry.js
var a = 1;
})();

================================================================================
TestUseStrictDirectiveBundleIssue1837
---------- /out.js ----------
Expand All @@ -3953,17 +3984,6 @@ TestUseStrictDirectiveBundleIssue1837
console.log(require_cjs());
})();

================================================================================
TestUseStrictDirectiveBundleIssue2264
---------- /out.js ----------
"use strict";

// entry.js
var a = 1;
export {
a
};

================================================================================
TestUseStrictDirectiveMinifyNoBundle
---------- /out.js ----------
Expand Down
28 changes: 27 additions & 1 deletion internal/bundler/snapshots/snapshots_tsconfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var import_util = __toESM(require_util());
console.log((0, import_util.default)());

================================================================================
TestTsConfigAlwaysStrictTrueEmitDirectiveBundle
TestTsConfigAlwaysStrictTrueEmitDirectiveBundleCJS
---------- /Users/user/project/out/implicit.js ----------
"use strict";

Expand All @@ -27,6 +27,32 @@ console.log('this file should start with "use strict"');
// Users/user/project/src/explicit.ts
console.log('this file should start with "use strict"');

================================================================================
TestTsConfigAlwaysStrictTrueEmitDirectiveBundleESM
---------- /Users/user/project/out/implicit.js ----------
// Users/user/project/src/implicit.ts
console.log('this file should not start with "use strict"');

---------- /Users/user/project/out/explicit.js ----------
// Users/user/project/src/explicit.ts
console.log('this file should not start with "use strict"');

================================================================================
TestTsConfigAlwaysStrictTrueEmitDirectiveBundleIIFE
---------- /Users/user/project/out/implicit.js ----------
"use strict";
(() => {
// Users/user/project/src/implicit.ts
console.log('this file should start with "use strict"');
})();

---------- /Users/user/project/out/explicit.js ----------
"use strict";
(() => {
// Users/user/project/src/explicit.ts
console.log('this file should start with "use strict"');
})();

================================================================================
TestTsConfigAlwaysStrictTrueEmitDirectiveFormat
---------- /Users/user/project/out/implicit.js ----------
Expand Down

0 comments on commit 5d7ac55

Please sign in to comment.