terser 5.44.1 → 5.46.0

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.
@@ -87,7 +87,7 @@ import {
87
87
  walk_abort,
88
88
  walk_parent,
89
89
  } from "../ast.js";
90
- import { make_node, regexp_source_fix, string_template, makePredicate } from "../utils/index.js";
90
+ import { make_node, make_void_0, regexp_source_fix, string_template, makePredicate } from "../utils/index.js";
91
91
  import { first_in_statement } from "../utils/first_in_statement.js";
92
92
  import { has_flag, TOP } from "./compressor-flags.js";
93
93
 
@@ -148,7 +148,7 @@ export function make_node_from_constant(val, orig) {
148
148
  case "boolean":
149
149
  return make_node(val ? AST_True : AST_False, orig);
150
150
  case "undefined":
151
- return make_node(AST_Undefined, orig);
151
+ return make_void_0(orig);
152
152
  default:
153
153
  if (val === null) {
154
154
  return make_node(AST_Null, orig, { value: null });
@@ -146,6 +146,7 @@ import {
146
146
  defaults,
147
147
  HOP,
148
148
  make_node,
149
+ make_void_0,
149
150
  makePredicate,
150
151
  MAP,
151
152
  remove,
@@ -562,7 +563,7 @@ AST_Toplevel.DEFMETHOD("drop_console", function(options) {
562
563
  set_flag(exp.expression, SQUEEZED);
563
564
  self.args = [];
564
565
  } else {
565
- return make_node(AST_Undefined, self);
566
+ return make_void_0(self);
566
567
  }
567
568
  }
568
569
  });
@@ -590,12 +591,7 @@ AST_Scope.DEFMETHOD("process_expression", function(insert, compressor) {
590
591
  : make_node(AST_EmptyStatement, node);
591
592
  }
592
593
  return make_node(AST_SimpleStatement, node, {
593
- body: node.value || make_node(AST_UnaryPrefix, node, {
594
- operator: "void",
595
- expression: make_node(AST_Number, node, {
596
- value: 0
597
- })
598
- })
594
+ body: node.value || make_void_0(node)
599
595
  });
600
596
  }
601
597
  if (node instanceof AST_Class || node instanceof AST_Lambda && node !== self) {
@@ -1198,8 +1194,8 @@ def_optimize(AST_If, function(self, compressor) {
1198
1194
  return make_node(self.body.CTOR, self, {
1199
1195
  value: make_node(AST_Conditional, self, {
1200
1196
  condition : self.condition,
1201
- consequent : self.body.value || make_node(AST_Undefined, self.body),
1202
- alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
1197
+ consequent : self.body.value || make_void_0(self.body),
1198
+ alternative : self.alternative.value || make_void_0(self.alternative),
1203
1199
  }).transform(compressor)
1204
1200
  }).optimize(compressor);
1205
1201
  }
@@ -1752,7 +1748,7 @@ def_optimize(AST_Call, function(self, compressor) {
1752
1748
  const value = condition.evaluate(compressor);
1753
1749
 
1754
1750
  if (value === 1 || value === true) {
1755
- return make_node(AST_Undefined, self);
1751
+ return make_void_0(self).optimize(compressor);
1756
1752
  }
1757
1753
  }
1758
1754
  }
@@ -2114,6 +2110,10 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
2114
2110
  ) {
2115
2111
  return make_sequence(self, [e, make_node(AST_True, self)]).optimize(compressor);
2116
2112
  }
2113
+ // Short-circuit common `void 0`
2114
+ if (self.operator === "void" && e instanceof AST_Number && e.value === 0) {
2115
+ return unsafe_undefined_ref(self, compressor) || self;
2116
+ }
2117
2117
  var seq = self.lift_sequences(compressor);
2118
2118
  if (seq !== self) {
2119
2119
  return seq;
@@ -2124,7 +2124,7 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
2124
2124
  self.expression = e;
2125
2125
  return self;
2126
2126
  } else {
2127
- return make_node(AST_Undefined, self).optimize(compressor);
2127
+ return make_void_0(self).optimize(compressor);
2128
2128
  }
2129
2129
  }
2130
2130
  if (compressor.in_boolean_context()) {
@@ -2310,7 +2310,7 @@ def_optimize(AST_Binary, function(self, compressor) {
2310
2310
  if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
2311
2311
  : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
2312
2312
  self.right = expr;
2313
- self.left = make_node(AST_Undefined, self.left).optimize(compressor);
2313
+ self.left = make_void_0(self.left).optimize(compressor);
2314
2314
  if (self.operator.length == 2) self.operator += "=";
2315
2315
  }
2316
2316
  } else if (compressor.option("typeofs")
@@ -2323,7 +2323,7 @@ def_optimize(AST_Binary, function(self, compressor) {
2323
2323
  if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
2324
2324
  : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
2325
2325
  self.left = expr;
2326
- self.right = make_node(AST_Undefined, self.right).optimize(compressor);
2326
+ self.right = make_void_0(self.right).optimize(compressor);
2327
2327
  if (self.operator.length == 2) self.operator += "=";
2328
2328
  }
2329
2329
  } else if (self.left instanceof AST_SymbolRef
@@ -2964,7 +2964,8 @@ function is_atomic(lhs, self) {
2964
2964
  return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
2965
2965
  }
2966
2966
 
2967
- def_optimize(AST_Undefined, function(self, compressor) {
2967
+ /** Apply the `unsafe_undefined` option: find a variable called `undefined` and turn `self` into a reference to it. */
2968
+ function unsafe_undefined_ref(self, compressor) {
2968
2969
  if (compressor.option("unsafe_undefined")) {
2969
2970
  var undef = find_variable(compressor, "undefined");
2970
2971
  if (undef) {
@@ -2977,14 +2978,15 @@ def_optimize(AST_Undefined, function(self, compressor) {
2977
2978
  return ref;
2978
2979
  }
2979
2980
  }
2981
+ return null;
2982
+ }
2983
+
2984
+ def_optimize(AST_Undefined, function(self, compressor) {
2985
+ var symbolref = unsafe_undefined_ref(self, compressor);
2986
+ if (symbolref) return symbolref;
2980
2987
  var lhs = compressor.is_lhs();
2981
2988
  if (lhs && is_atomic(lhs, self)) return self;
2982
- return make_node(AST_UnaryPrefix, self, {
2983
- operator: "void",
2984
- expression: make_node(AST_Number, self, {
2985
- value: 0
2986
- })
2987
- });
2989
+ return make_void_0(self);
2988
2990
  });
2989
2991
 
2990
2992
  def_optimize(AST_Infinity, function(self, compressor) {
@@ -3671,7 +3673,7 @@ def_optimize(AST_Sub, function(self, compressor) {
3671
3673
  }
3672
3674
  }
3673
3675
  if (retValue instanceof AST_Expansion) break FLATTEN;
3674
- retValue = retValue instanceof AST_Hole ? make_node(AST_Undefined, retValue) : retValue;
3676
+ retValue = retValue instanceof AST_Hole ? make_void_0(retValue) : retValue;
3675
3677
  if (!flatten) values.unshift(retValue);
3676
3678
  while (--i >= 0) {
3677
3679
  var value = elements[i];
@@ -3710,7 +3712,7 @@ def_optimize(AST_Chain, function (self, compressor) {
3710
3712
  if (parent instanceof AST_UnaryPrefix && parent.operator === "delete") {
3711
3713
  return make_node_from_constant(0, self);
3712
3714
  }
3713
- return make_node(AST_Undefined, self);
3715
+ return make_void_0(self).optimize(compressor);
3714
3716
  }
3715
3717
  if (
3716
3718
  self.expression instanceof AST_PropAccess
@@ -76,7 +76,6 @@ import {
76
76
  AST_This,
77
77
  AST_Toplevel,
78
78
  AST_UnaryPrefix,
79
- AST_Undefined,
80
79
  AST_Var,
81
80
  AST_VarDef,
82
81
 
@@ -86,7 +85,7 @@ import {
86
85
  _NOINLINE,
87
86
  _PURE,
88
87
  } from "../ast.js";
89
- import { make_node, has_annotation } from "../utils/index.js";
88
+ import { make_node, make_void_0, has_annotation } from "../utils/index.js";
90
89
  import "../size.js";
91
90
 
92
91
  import "./evaluate.js";
@@ -358,7 +357,7 @@ export function inline_into_call(self, compressor) {
358
357
  if (returned) {
359
358
  returned = returned.clone(true);
360
359
  } else {
361
- returned = make_node(AST_Undefined, self);
360
+ returned = make_void_0(self);
362
361
  }
363
362
  const args = self.args.concat(returned);
364
363
  return make_sequence(self, args).optimize(compressor);
@@ -374,7 +373,7 @@ export function inline_into_call(self, compressor) {
374
373
  && returned.name === fn.argnames[0].name
375
374
  ) {
376
375
  const replacement =
377
- (self.args[0] || make_node(AST_Undefined)).optimize(compressor);
376
+ (self.args[0] || make_void_0()).optimize(compressor);
378
377
 
379
378
  let parent;
380
379
  if (
@@ -456,7 +455,7 @@ export function inline_into_call(self, compressor) {
456
455
 
457
456
  const can_drop_this_call = is_regular_func && compressor.option("side_effects") && fn.body.every(is_empty);
458
457
  if (can_drop_this_call) {
459
- var args = self.args.concat(make_node(AST_Undefined, self));
458
+ var args = self.args.concat(make_void_0(self));
460
459
  return make_sequence(self, args).optimize(compressor);
461
460
  }
462
461
 
@@ -475,9 +474,9 @@ export function inline_into_call(self, compressor) {
475
474
  return self;
476
475
 
477
476
  function return_value(stat) {
478
- if (!stat) return make_node(AST_Undefined, self);
477
+ if (!stat) return make_void_0(self);
479
478
  if (stat instanceof AST_Return) {
480
- if (!stat.value) return make_node(AST_Undefined, self);
479
+ if (!stat.value) return make_void_0(self);
481
480
  return stat.value.clone(true);
482
481
  }
483
482
  if (stat instanceof AST_SimpleStatement) {
@@ -623,7 +622,7 @@ export function inline_into_call(self, compressor) {
623
622
  } else {
624
623
  var symbol = make_node(AST_SymbolVar, name, name);
625
624
  name.definition().orig.push(symbol);
626
- if (!value && in_loop) value = make_node(AST_Undefined, self);
625
+ if (!value && in_loop) value = make_void_0(self);
627
626
  append_var(decls, expressions, symbol, value);
628
627
  }
629
628
  }
@@ -650,7 +649,7 @@ export function inline_into_call(self, compressor) {
650
649
  operator: "=",
651
650
  logical: false,
652
651
  left: sym,
653
- right: make_node(AST_Undefined, name)
652
+ right: make_void_0(name),
654
653
  }));
655
654
  }
656
655
  }
@@ -87,7 +87,6 @@ import {
87
87
  AST_Try,
88
88
  AST_Unary,
89
89
  AST_UnaryPrefix,
90
- AST_Undefined,
91
90
  AST_UsingDef,
92
91
  AST_VarDef,
93
92
  AST_VarDefLike,
@@ -98,7 +97,7 @@ import {
98
97
  walk_body,
99
98
  walk_parent,
100
99
  } from "../ast.js";
101
- import { HOP, make_node, noop } from "../utils/index.js";
100
+ import { HOP, make_node, make_void_0, noop } from "../utils/index.js";
102
101
 
103
102
  import { lazy_op, is_modified, is_lhs } from "./inference.js";
104
103
  import { INLINED, clear_flag } from "./compressor-flags.js";
@@ -172,7 +171,7 @@ function safe_to_read(tw, def) {
172
171
  if (def.fixed == null) {
173
172
  var orig = def.orig[0];
174
173
  if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
175
- def.fixed = make_node(AST_Undefined, orig);
174
+ def.fixed = make_void_0(orig);
176
175
  }
177
176
  return true;
178
177
  }
@@ -470,7 +469,7 @@ function mark_lambda(tw, descend, compressor) {
470
469
  if (d.orig.length > 1) return;
471
470
  if (d.fixed === undefined && (!this.uses_arguments || tw.has_directive("use strict"))) {
472
471
  d.fixed = function() {
473
- return iife.args[i] || make_node(AST_Undefined, iife);
472
+ return iife.args[i] || make_void_0(iife);
474
473
  };
475
474
  tw.loop_ids.set(d.id, tw.in_loop);
476
475
  mark(tw, d, true);
@@ -106,7 +106,6 @@ import {
106
106
  AST_Unary,
107
107
  AST_UnaryPostfix,
108
108
  AST_UnaryPrefix,
109
- AST_Undefined,
110
109
  AST_Using,
111
110
  AST_Var,
112
111
  AST_VarDef,
@@ -122,6 +121,7 @@ import {
122
121
  } from "../ast.js";
123
122
  import {
124
123
  make_node,
124
+ make_void_0,
125
125
  MAP,
126
126
  member,
127
127
  remove,
@@ -635,7 +635,7 @@ export function tighten_body(statements, compressor) {
635
635
  }
636
636
  } else {
637
637
  if (!arg) {
638
- arg = make_node(AST_Undefined, sym).transform(compressor);
638
+ arg = make_void_0(sym).transform(compressor);
639
639
  } else if (arg instanceof AST_Lambda && arg.pinned()
640
640
  || has_overlapping_symbol(fn, arg, fn_strict)) {
641
641
  arg = null;
@@ -875,7 +875,7 @@ export function tighten_body(statements, compressor) {
875
875
  found = true;
876
876
  if (node instanceof AST_VarDef) {
877
877
  node.value = node.name instanceof AST_SymbolConst
878
- ? make_node(AST_Undefined, node.value) // `const` always needs value.
878
+ ? make_void_0(node.value) // `const` always needs value.
879
879
  : null;
880
880
  return node;
881
881
  }
@@ -1314,7 +1314,7 @@ export function tighten_body(statements, compressor) {
1314
1314
  var stat = statements[i];
1315
1315
  if (prev) {
1316
1316
  if (stat instanceof AST_Exit) {
1317
- stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat).transform(compressor));
1317
+ stat.value = cons_seq(stat.value || make_void_0(stat).transform(compressor));
1318
1318
  } else if (stat instanceof AST_For) {
1319
1319
  if (!(stat.init instanceof AST_DefinitionsLike)) {
1320
1320
  const abort = walk(prev.body, node => {
@@ -43,7 +43,7 @@
43
43
 
44
44
  "use strict";
45
45
 
46
- import { AST_Node } from "../ast.js";
46
+ import { AST_Node, AST_Number, AST_UnaryPrefix } from "../ast.js";
47
47
 
48
48
  function characters(str) {
49
49
  return str.split("");
@@ -130,6 +130,15 @@ function make_node(ctor, orig, props) {
130
130
  return new ctor(props);
131
131
  }
132
132
 
133
+ /** Makes a `void 0` expression. Use instead of AST_Undefined which may conflict
134
+ * with an existing variable called `undefined` */
135
+ function make_void_0(orig) {
136
+ return make_node(AST_UnaryPrefix, orig, {
137
+ operator: "void",
138
+ expression: make_node(AST_Number, orig, { value: 0 })
139
+ });
140
+ }
141
+
133
142
  function push_uniq(array, el) {
134
143
  if (!array.includes(el))
135
144
  array.push(el);
@@ -272,6 +281,7 @@ export {
272
281
  HOP,
273
282
  keep_name,
274
283
  make_node,
284
+ make_void_0,
275
285
  makePredicate,
276
286
  map_add,
277
287
  map_from_object,
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.44.1",
7
+ "version": "5.46.0",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
@@ -61,6 +61,10 @@
61
61
  "semver": "^7.5.1",
62
62
  "source-map": "~0.8.0-beta.0"
63
63
  },
64
+ "overrides": {
65
+ "serialize-javascript": "6.0.2",
66
+ "js-yaml": "4.1.1"
67
+ },
64
68
  "scripts": {
65
69
  "test": "node test/compress.js && mocha test/mocha",
66
70
  "test:compress": "node test/compress.js",