terser 5.16.8 → 5.16.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.16.9
4
+ - Fix parentheses in output of optional chains (`a?.b`) (#1374)
5
+ - More documentation on source maps (#1368)
6
+ - New `lhs_constants` option, allowing to stop Terser from swapping comparison operands (#1361)
7
+
3
8
  ## v5.16.8
4
9
 
5
10
  - Become even less conservative around function definitions for `reduce_vars`
6
11
  - Fix parsing context of `import.meta` expressions such that method calls are allowed
7
12
 
8
- ## v5.16.7
13
+ ## v5.16.6
9
14
 
10
15
  - Become less conservative with analyzing function definitions for `reduce_vars`
11
16
  - Parse `import.meta` as a real AST node and not an `object.property`
package/README.md CHANGED
@@ -708,7 +708,8 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
708
708
 
709
709
  - `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
710
710
  e.g. `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
711
- nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
711
+ nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. Note: `comparisons`
712
+ works best with `lhs_constants` enabled.
712
713
 
713
714
  - `computed_props` (default: `true`) -- Transforms constant computed properties
714
715
  into regular ones: `{["computed"]: 1}` is converted to `{computed: 1}`.
@@ -775,6 +776,9 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
775
776
  - `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
776
777
  being compressed into `1/0`, which may cause performance issues on Chrome.
777
778
 
779
+ - `lhs_constants` (default: `true`) -- Moves constant values to the left-hand side
780
+ of binary nodes. `foo == 42 → 42 == foo`
781
+
778
782
  - `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
779
783
  when we can statically determine the condition.
780
784
 
@@ -1267,6 +1271,12 @@ expected as code is optimized and mappings are often simply not possible as
1267
1271
  some code no longer exists. For highest fidelity in source map debugging
1268
1272
  disable the `compress` option and just use `mangle`.
1269
1273
 
1274
+ When debugging, make sure you enable the **"map scopes"** feature to map mangled variable names back to their original names.
1275
+ Without this, all variable values will be `undefined`. See https://github.com/terser/terser/issues/1367 for more details.
1276
+ <br/><br/>
1277
+
1278
+ ![image](https://user-images.githubusercontent.com/27283110/230441652-ac5cf6b0-5dc5-4ffc-9d8b-bd02875484f4.png)
1279
+
1270
1280
  ### Compiler assumptions
1271
1281
 
1272
1282
  To allow for better optimizations, the compiler makes various assumptions:
@@ -9742,6 +9742,12 @@ function OutputStream(options) {
9742
9742
  return true;
9743
9743
  });
9744
9744
 
9745
+ PARENS(AST_Chain, function(output) {
9746
+ var p = output.parent();
9747
+ if (!(p instanceof AST_Call || p instanceof AST_PropAccess)) return false;
9748
+ return p.expression === this;
9749
+ });
9750
+
9745
9751
  PARENS(AST_PropAccess, function(output) {
9746
9752
  var p = output.parent();
9747
9753
  if (p instanceof AST_New && p.expression === this) {
@@ -12939,7 +12945,8 @@ function maintain_this_binding(parent, orig, val) {
12939
12945
  parent instanceof AST_UnaryPrefix && parent.operator == "delete"
12940
12946
  || parent instanceof AST_Call && parent.expression === orig
12941
12947
  && (
12942
- val instanceof AST_PropAccess
12948
+ val instanceof AST_Chain
12949
+ || val instanceof AST_PropAccess
12943
12950
  || val instanceof AST_SymbolRef && val.name == "eval"
12944
12951
  )
12945
12952
  ) {
@@ -18028,6 +18035,7 @@ class Compressor extends TreeWalker {
18028
18035
  keep_fargs : true,
18029
18036
  keep_fnames : false,
18030
18037
  keep_infinity : false,
18038
+ lhs_constants : !false_by_default,
18031
18039
  loops : !false_by_default,
18032
18040
  module : false,
18033
18041
  negate_iife : !false_by_default,
@@ -19914,7 +19922,7 @@ def_optimize(AST_Binary, function(self, compressor) {
19914
19922
  self.right = tmp;
19915
19923
  }
19916
19924
  }
19917
- if (commutativeOperators.has(self.operator)) {
19925
+ if (compressor.option("lhs_constants") && commutativeOperators.has(self.operator)) {
19918
19926
  if (self.right.is_constant()
19919
19927
  && !self.left.is_constant()) {
19920
19928
  // if right is a constant, whatever side effects the
@@ -19944,6 +19952,9 @@ def_optimize(AST_Binary, function(self, compressor) {
19944
19952
  // void 0 == x => null == x
19945
19953
  if (!is_strict_comparison && is_undefined(self.left, compressor)) {
19946
19954
  self.left = make_node(AST_Null, self.left);
19955
+ // x == void 0 => x == null
19956
+ } else if (!is_strict_comparison && is_undefined(self.right, compressor)) {
19957
+ self.right = make_node(AST_Null, self.right);
19947
19958
  } else if (compressor.option("typeofs")
19948
19959
  // "undefined" == typeof x => undefined === x
19949
19960
  && self.left instanceof AST_String
@@ -19957,6 +19968,19 @@ def_optimize(AST_Binary, function(self, compressor) {
19957
19968
  self.left = make_node(AST_Undefined, self.left).optimize(compressor);
19958
19969
  if (self.operator.length == 2) self.operator += "=";
19959
19970
  }
19971
+ } else if (compressor.option("typeofs")
19972
+ // typeof x === "undefined" => x === undefined
19973
+ && self.left instanceof AST_UnaryPrefix
19974
+ && self.left.operator == "typeof"
19975
+ && self.right instanceof AST_String
19976
+ && self.right.value == "undefined") {
19977
+ var expr = self.left.expression;
19978
+ if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
19979
+ : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
19980
+ self.left = expr;
19981
+ self.right = make_node(AST_Undefined, self.right).optimize(compressor);
19982
+ if (self.operator.length == 2) self.operator += "=";
19983
+ }
19960
19984
  } else if (self.left instanceof AST_SymbolRef
19961
19985
  // obj !== obj => false
19962
19986
  && self.right instanceof AST_SymbolRef
@@ -46,6 +46,7 @@ import {
46
46
  AST_Arrow,
47
47
  AST_BlockStatement,
48
48
  AST_Call,
49
+ AST_Chain,
49
50
  AST_Class,
50
51
  AST_Const,
51
52
  AST_Constant,
@@ -226,7 +227,8 @@ export function maintain_this_binding(parent, orig, val) {
226
227
  parent instanceof AST_UnaryPrefix && parent.operator == "delete"
227
228
  || parent instanceof AST_Call && parent.expression === orig
228
229
  && (
229
- val instanceof AST_PropAccess
230
+ val instanceof AST_Chain
231
+ || val instanceof AST_PropAccess
230
232
  || val instanceof AST_SymbolRef && val.name == "eval"
231
233
  )
232
234
  ) {
@@ -245,6 +245,7 @@ class Compressor extends TreeWalker {
245
245
  keep_fargs : true,
246
246
  keep_fnames : false,
247
247
  keep_infinity : false,
248
+ lhs_constants : !false_by_default,
248
249
  loops : !false_by_default,
249
250
  module : false,
250
251
  negate_iife : !false_by_default,
@@ -2131,7 +2132,7 @@ def_optimize(AST_Binary, function(self, compressor) {
2131
2132
  self.right = tmp;
2132
2133
  }
2133
2134
  }
2134
- if (commutativeOperators.has(self.operator)) {
2135
+ if (compressor.option("lhs_constants") && commutativeOperators.has(self.operator)) {
2135
2136
  if (self.right.is_constant()
2136
2137
  && !self.left.is_constant()) {
2137
2138
  // if right is a constant, whatever side effects the
@@ -2161,6 +2162,9 @@ def_optimize(AST_Binary, function(self, compressor) {
2161
2162
  // void 0 == x => null == x
2162
2163
  if (!is_strict_comparison && is_undefined(self.left, compressor)) {
2163
2164
  self.left = make_node(AST_Null, self.left);
2165
+ // x == void 0 => x == null
2166
+ } else if (!is_strict_comparison && is_undefined(self.right, compressor)) {
2167
+ self.right = make_node(AST_Null, self.right);
2164
2168
  } else if (compressor.option("typeofs")
2165
2169
  // "undefined" == typeof x => undefined === x
2166
2170
  && self.left instanceof AST_String
@@ -2174,6 +2178,19 @@ def_optimize(AST_Binary, function(self, compressor) {
2174
2178
  self.left = make_node(AST_Undefined, self.left).optimize(compressor);
2175
2179
  if (self.operator.length == 2) self.operator += "=";
2176
2180
  }
2181
+ } else if (compressor.option("typeofs")
2182
+ // typeof x === "undefined" => x === undefined
2183
+ && self.left instanceof AST_UnaryPrefix
2184
+ && self.left.operator == "typeof"
2185
+ && self.right instanceof AST_String
2186
+ && self.right.value == "undefined") {
2187
+ var expr = self.left.expression;
2188
+ if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
2189
+ : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
2190
+ self.left = expr;
2191
+ self.right = make_node(AST_Undefined, self.right).optimize(compressor);
2192
+ if (self.operator.length == 2) self.operator += "=";
2193
+ }
2177
2194
  } else if (self.left instanceof AST_SymbolRef
2178
2195
  // obj !== obj => false
2179
2196
  && self.right instanceof AST_SymbolRef
package/lib/output.js CHANGED
@@ -1080,6 +1080,12 @@ function OutputStream(options) {
1080
1080
  return true;
1081
1081
  });
1082
1082
 
1083
+ PARENS(AST_Chain, function(output) {
1084
+ var p = output.parent();
1085
+ if (!(p instanceof AST_Call || p instanceof AST_PropAccess)) return false;
1086
+ return p.expression === this;
1087
+ });
1088
+
1083
1089
  PARENS(AST_PropAccess, function(output) {
1084
1090
  var p = output.parent();
1085
1091
  if (p instanceof AST_New && p.expression === this) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "homepage": "https://terser.org",
5
5
  "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
6
6
  "license": "BSD-2-Clause",
7
- "version": "5.16.8",
7
+ "version": "5.16.9",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
package/bin/terser.mjs DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- "use strict";
4
-
5
- import "../tools/exit.cjs";
6
-
7
- import fs from "fs";
8
- import path from "path";
9
- import program from "commander";
10
-
11
- import { run_cli } from "../lib/cli.js";
12
-
13
- const packageJson = {
14
- name: "terser",
15
- version: "experimental module CLI"
16
- };
17
-
18
- run_cli({ program, packageJson, fs, path }).catch((error) => {
19
- console.error(error);
20
- process.exitCode = 1;
21
- });