terser 5.30.4 → 5.31.1

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.
@@ -226,7 +226,17 @@ export function has_break_or_continue(loop, parent) {
226
226
  // func(something) because that changes the meaning of
227
227
  // the func (becomes lexical instead of global).
228
228
  export function maintain_this_binding(parent, orig, val) {
229
- if (
229
+ if (requires_sequence_to_maintain_binding(parent, orig, val)) {
230
+ const zero = make_node(AST_Number, orig, { value: 0 });
231
+ return make_sequence(orig, [ zero, val ]);
232
+ } else {
233
+ return val;
234
+ }
235
+ }
236
+
237
+ /** Detect (1, x.noThis)(), (0, eval)(), which need sequences */
238
+ export function requires_sequence_to_maintain_binding(parent, orig, val) {
239
+ return (
230
240
  parent instanceof AST_UnaryPrefix && parent.operator == "delete"
231
241
  || parent instanceof AST_Call && parent.expression === orig
232
242
  && (
@@ -234,12 +244,7 @@ export function maintain_this_binding(parent, orig, val) {
234
244
  || val instanceof AST_PropAccess
235
245
  || val instanceof AST_SymbolRef && val.name == "eval"
236
246
  )
237
- ) {
238
- const zero = make_node(AST_Number, orig, { value: 0 });
239
- return make_sequence(orig, [ zero, val ]);
240
- } else {
241
- return val;
242
- }
247
+ );
243
248
  }
244
249
 
245
250
  export function is_func_expr(node) {
@@ -63,6 +63,7 @@ import {
63
63
  AST_Lambda,
64
64
  AST_Number,
65
65
  AST_Scope,
66
+ AST_Sequence,
66
67
  AST_SimpleStatement,
67
68
  AST_SymbolBlockDeclaration,
68
69
  AST_SymbolCatch,
@@ -101,6 +102,7 @@ import {
101
102
  is_empty,
102
103
  is_ref_of,
103
104
  can_be_evicted_from_block,
105
+ requires_sequence_to_maintain_binding,
104
106
  } from "./common.js";
105
107
 
106
108
  const r_keep_assign = /keep_assign/;
@@ -231,7 +233,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
231
233
  var in_use = in_use_ids.has(def.id);
232
234
  if (node instanceof AST_Assign) {
233
235
  if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
234
- return maintain_this_binding(parent, node, node.right.transform(tt));
236
+ const assignee = node.right.transform(tt);
237
+ if (!in_use && !assignee.has_side_effects(compressor) && !is_used_in_expression(tt)) {
238
+ return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
239
+ }
240
+ return maintain_this_binding(parent, node, assignee);
235
241
  }
236
242
  } else if (!in_use) {
237
243
  return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
@@ -438,6 +444,14 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
438
444
  scope = save_scope;
439
445
  return node;
440
446
  }
447
+ },
448
+ function after(node, in_list) {
449
+ if (node instanceof AST_Sequence) {
450
+ switch (node.expressions.length) {
451
+ case 0: return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
452
+ case 1: return node.expressions[0];
453
+ }
454
+ }
441
455
  }
442
456
  );
443
457
 
@@ -484,3 +498,41 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
484
498
  }
485
499
  });
486
500
 
501
+ /**
502
+ * Check if a node may be used by the expression it's in
503
+ * void (0, 1, {node}, 2) -> false
504
+ * console.log(0, {node}) -> true
505
+ */
506
+ function is_used_in_expression(tw) {
507
+ for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
508
+ if (parent instanceof AST_Sequence) {
509
+ const nth_expression = parent.expressions.indexOf(node);
510
+ if (nth_expression !== parent.expressions.length - 1) {
511
+ // Detect (0, x.noThis)() constructs
512
+ const grandparent = tw.parent(p + 2);
513
+ if (
514
+ parent.expressions.length > 2
515
+ || parent.expressions.length === 1
516
+ || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
517
+ ) {
518
+ return false;
519
+ }
520
+ return true;
521
+ } else {
522
+ continue;
523
+ }
524
+ }
525
+ if (parent instanceof AST_Unary) {
526
+ const op = parent.operator;
527
+ if (op === "void") {
528
+ return false;
529
+ }
530
+ if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
531
+ continue;
532
+ }
533
+ }
534
+ return true;
535
+ }
536
+
537
+ return true;
538
+ }
@@ -3758,7 +3758,7 @@ def_optimize(AST_Array, function(self, compressor) {
3758
3758
  return self;
3759
3759
  });
3760
3760
 
3761
- function inline_object_prop_spread(props, compressor) {
3761
+ function inline_object_prop_spread(props) {
3762
3762
  for (var i = 0; i < props.length; i++) {
3763
3763
  var prop = props[i];
3764
3764
  if (prop instanceof AST_Expansion) {
@@ -3770,15 +3770,14 @@ function inline_object_prop_spread(props, compressor) {
3770
3770
  props.splice(i, 1, ...expr.properties);
3771
3771
  // Step back one, as the property at i is now new.
3772
3772
  i--;
3773
- } else if (expr instanceof AST_Constant
3774
- && !(expr instanceof AST_String)) {
3773
+ } else if ((
3774
+ // `expr.is_constant()` returns `false` for `AST_RegExp`, so need both.
3775
+ expr instanceof AST_Constant
3776
+ || expr.is_constant()
3777
+ ) && !(expr instanceof AST_String)) {
3775
3778
  // Unlike array-like spread, in object spread, spreading a
3776
3779
  // non-iterable value silently does nothing; it is thus safe
3777
- // to remove. AST_String is the only iterable AST_Constant.
3778
- props.splice(i, 1);
3779
- i--;
3780
- } else if (is_nullish(expr, compressor)) {
3781
- // Likewise, null and undefined can be silently removed.
3780
+ // to remove. AST_String is the only iterable constant.
3782
3781
  props.splice(i, 1);
3783
3782
  i--;
3784
3783
  }
@@ -3791,7 +3790,7 @@ def_optimize(AST_Object, function(self, compressor) {
3791
3790
  if (optimized !== self) {
3792
3791
  return optimized;
3793
3792
  }
3794
- inline_object_prop_spread(self.properties, compressor);
3793
+ inline_object_prop_spread(self.properties);
3795
3794
  return self;
3796
3795
  });
3797
3796
 
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.30.4",
7
+ "version": "5.31.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },