terser 5.17.3 → 5.17.4

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,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.17.4
4
+
5
+ - Fix crash when trying to negate a class (`!class{}`)
6
+ - Avoid outputting comments between `yield`/`await` and its argument
7
+ - Fix detection of left-hand-side of assignment, to avoid optimizing it like any other expression in some edge cases
8
+
3
9
  ## v5.17.3
4
10
 
5
11
  - Fix issue with trimming a static class property's contents accessing the class as `this`.
@@ -9345,14 +9345,17 @@ function OutputStream(options) {
9345
9345
  if (!start) return;
9346
9346
  var printed_comments = self.printed_comments;
9347
9347
 
9348
- // There cannot be a newline between return and its value.
9349
- const return_with_value = node instanceof AST_Exit && node.value;
9348
+ // There cannot be a newline between return/yield and its value.
9349
+ const keyword_with_value =
9350
+ node instanceof AST_Exit && node.value
9351
+ || (node instanceof AST_Await || node instanceof AST_Yield)
9352
+ && node.expression;
9350
9353
 
9351
9354
  if (
9352
9355
  start.comments_before
9353
9356
  && printed_comments.has(start.comments_before)
9354
9357
  ) {
9355
- if (return_with_value) {
9358
+ if (keyword_with_value) {
9356
9359
  start.comments_before = [];
9357
9360
  } else {
9358
9361
  return;
@@ -9365,10 +9368,12 @@ function OutputStream(options) {
9365
9368
  }
9366
9369
  printed_comments.add(comments);
9367
9370
 
9368
- if (return_with_value) {
9371
+ if (keyword_with_value) {
9369
9372
  var tw = new TreeWalker(function(node) {
9370
9373
  var parent = tw.parent();
9371
9374
  if (parent instanceof AST_Exit
9375
+ || parent instanceof AST_Await
9376
+ || parent instanceof AST_Yield
9372
9377
  || parent instanceof AST_Binary && parent.left === node
9373
9378
  || parent.TYPE == "Call" && parent.expression === node
9374
9379
  || parent instanceof AST_Conditional && parent.condition === node
@@ -9387,7 +9392,7 @@ function OutputStream(options) {
9387
9392
  }
9388
9393
  });
9389
9394
  tw.push(node);
9390
- node.value.walk(tw);
9395
+ keyword_with_value.walk(tw);
9391
9396
  }
9392
9397
 
9393
9398
  if (current_pos == 0) {
@@ -14022,6 +14027,9 @@ function is_lhs(node, parent) {
14022
14027
  def_negate(AST_Function, function() {
14023
14028
  return basic_negation(this);
14024
14029
  });
14030
+ def_negate(AST_Class, function() {
14031
+ return basic_negation(this);
14032
+ });
14025
14033
  def_negate(AST_Arrow, function() {
14026
14034
  return basic_negation(this);
14027
14035
  });
@@ -18335,6 +18343,13 @@ class Compressor extends TreeWalker {
18335
18343
  if (opt === node) set_flag(opt, SQUEEZED);
18336
18344
  return opt;
18337
18345
  }
18346
+
18347
+ /** Alternative to plain is_lhs() which doesn't work within .optimize() */
18348
+ is_lhs() {
18349
+ const self = this.stack[this.stack.length - 1];
18350
+ const parent = this.stack[this.stack.length - 2];
18351
+ return is_lhs(self, parent);
18352
+ }
18338
18353
  }
18339
18354
 
18340
18355
  function def_optimize(node, optimizer) {
@@ -20492,8 +20507,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
20492
20507
  }
20493
20508
  }
20494
20509
 
20495
- const parent = compressor.parent();
20496
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
20510
+ if (compressor.option("reduce_vars") && !compressor.is_lhs()) {
20497
20511
  return inline_into_symbolref(self, compressor);
20498
20512
  } else {
20499
20513
  return self;
@@ -20517,7 +20531,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
20517
20531
  return ref;
20518
20532
  }
20519
20533
  }
20520
- var lhs = is_lhs(compressor.self(), compressor.parent());
20534
+ var lhs = compressor.is_lhs();
20521
20535
  if (lhs && is_atomic(lhs, self)) return self;
20522
20536
  return make_node(AST_UnaryPrefix, self, {
20523
20537
  operator: "void",
@@ -20528,7 +20542,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
20528
20542
  });
20529
20543
 
20530
20544
  def_optimize(AST_Infinity, function(self, compressor) {
20531
- var lhs = is_lhs(compressor.self(), compressor.parent());
20545
+ var lhs = compressor.is_lhs();
20532
20546
  if (lhs && is_atomic(lhs, self)) return self;
20533
20547
  if (
20534
20548
  compressor.option("keep_infinity")
@@ -20549,7 +20563,7 @@ def_optimize(AST_Infinity, function(self, compressor) {
20549
20563
  });
20550
20564
 
20551
20565
  def_optimize(AST_NaN, function(self, compressor) {
20552
- var lhs = is_lhs(compressor.self(), compressor.parent());
20566
+ var lhs = compressor.is_lhs();
20553
20567
  if (lhs && !is_atomic(lhs, self)
20554
20568
  || find_variable(compressor, "NaN")) {
20555
20569
  return make_node(AST_Binary, self, {
@@ -21125,7 +21139,10 @@ def_optimize(AST_Sub, function(self, compressor) {
21125
21139
  }
21126
21140
  }
21127
21141
  }
21128
- prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
21142
+ prop = self.property = best_of_expression(
21143
+ prop,
21144
+ make_node_from_constant(key, prop).transform(compressor)
21145
+ );
21129
21146
  var property = "" + key;
21130
21147
  if (is_basic_identifier_string(property)
21131
21148
  && property.length <= prop.size() + 1) {
@@ -21183,7 +21200,7 @@ def_optimize(AST_Sub, function(self, compressor) {
21183
21200
  return sym;
21184
21201
  }
21185
21202
  }
21186
- if (is_lhs(self, compressor.parent())) return self;
21203
+ if (compressor.is_lhs()) return self;
21187
21204
  if (key !== prop) {
21188
21205
  var sub = self.flatten_object(property, compressor);
21189
21206
  if (sub) {
@@ -21253,7 +21270,7 @@ def_optimize(AST_Chain, function (self, compressor) {
21253
21270
 
21254
21271
  def_optimize(AST_Dot, function(self, compressor) {
21255
21272
  const parent = compressor.parent();
21256
- if (is_lhs(self, parent)) return self;
21273
+ if (compressor.is_lhs()) return self;
21257
21274
  if (compressor.option("unsafe_proto")
21258
21275
  && self.expression instanceof AST_Dot
21259
21276
  && self.expression.property == "prototype") {
@@ -442,6 +442,13 @@ class Compressor extends TreeWalker {
442
442
  if (opt === node) set_flag(opt, SQUEEZED);
443
443
  return opt;
444
444
  }
445
+
446
+ /** Alternative to plain is_lhs() which doesn't work within .optimize() */
447
+ is_lhs() {
448
+ const self = this.stack[this.stack.length - 1];
449
+ const parent = this.stack[this.stack.length - 2];
450
+ return is_lhs(self, parent);
451
+ }
445
452
  }
446
453
 
447
454
  function def_optimize(node, optimizer) {
@@ -2599,8 +2606,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
2599
2606
  }
2600
2607
  }
2601
2608
 
2602
- const parent = compressor.parent();
2603
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
2609
+ if (compressor.option("reduce_vars") && !compressor.is_lhs()) {
2604
2610
  return inline_into_symbolref(self, compressor);
2605
2611
  } else {
2606
2612
  return self;
@@ -2624,7 +2630,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
2624
2630
  return ref;
2625
2631
  }
2626
2632
  }
2627
- var lhs = is_lhs(compressor.self(), compressor.parent());
2633
+ var lhs = compressor.is_lhs();
2628
2634
  if (lhs && is_atomic(lhs, self)) return self;
2629
2635
  return make_node(AST_UnaryPrefix, self, {
2630
2636
  operator: "void",
@@ -2635,7 +2641,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
2635
2641
  });
2636
2642
 
2637
2643
  def_optimize(AST_Infinity, function(self, compressor) {
2638
- var lhs = is_lhs(compressor.self(), compressor.parent());
2644
+ var lhs = compressor.is_lhs();
2639
2645
  if (lhs && is_atomic(lhs, self)) return self;
2640
2646
  if (
2641
2647
  compressor.option("keep_infinity")
@@ -2656,7 +2662,7 @@ def_optimize(AST_Infinity, function(self, compressor) {
2656
2662
  });
2657
2663
 
2658
2664
  def_optimize(AST_NaN, function(self, compressor) {
2659
- var lhs = is_lhs(compressor.self(), compressor.parent());
2665
+ var lhs = compressor.is_lhs();
2660
2666
  if (lhs && !is_atomic(lhs, self)
2661
2667
  || find_variable(compressor, "NaN")) {
2662
2668
  return make_node(AST_Binary, self, {
@@ -3232,7 +3238,10 @@ def_optimize(AST_Sub, function(self, compressor) {
3232
3238
  }
3233
3239
  }
3234
3240
  }
3235
- prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
3241
+ prop = self.property = best_of_expression(
3242
+ prop,
3243
+ make_node_from_constant(key, prop).transform(compressor)
3244
+ );
3236
3245
  var property = "" + key;
3237
3246
  if (is_basic_identifier_string(property)
3238
3247
  && property.length <= prop.size() + 1) {
@@ -3290,7 +3299,7 @@ def_optimize(AST_Sub, function(self, compressor) {
3290
3299
  return sym;
3291
3300
  }
3292
3301
  }
3293
- if (is_lhs(self, compressor.parent())) return self;
3302
+ if (compressor.is_lhs()) return self;
3294
3303
  if (key !== prop) {
3295
3304
  var sub = self.flatten_object(property, compressor);
3296
3305
  if (sub) {
@@ -3360,7 +3369,7 @@ def_optimize(AST_Chain, function (self, compressor) {
3360
3369
 
3361
3370
  def_optimize(AST_Dot, function(self, compressor) {
3362
3371
  const parent = compressor.parent();
3363
- if (is_lhs(self, parent)) return self;
3372
+ if (compressor.is_lhs()) return self;
3364
3373
  if (compressor.option("unsafe_proto")
3365
3374
  && self.expression instanceof AST_Dot
3366
3375
  && self.expression.property == "prototype") {
@@ -818,6 +818,9 @@ export function is_lhs(node, parent) {
818
818
  def_negate(AST_Function, function() {
819
819
  return basic_negation(this);
820
820
  });
821
+ def_negate(AST_Class, function() {
822
+ return basic_negation(this);
823
+ });
821
824
  def_negate(AST_Arrow, function() {
822
825
  return basic_negation(this);
823
826
  });
package/lib/output.js CHANGED
@@ -662,14 +662,17 @@ function OutputStream(options) {
662
662
  if (!start) return;
663
663
  var printed_comments = self.printed_comments;
664
664
 
665
- // There cannot be a newline between return and its value.
666
- const return_with_value = node instanceof AST_Exit && node.value;
665
+ // There cannot be a newline between return/yield and its value.
666
+ const keyword_with_value =
667
+ node instanceof AST_Exit && node.value
668
+ || (node instanceof AST_Await || node instanceof AST_Yield)
669
+ && node.expression;
667
670
 
668
671
  if (
669
672
  start.comments_before
670
673
  && printed_comments.has(start.comments_before)
671
674
  ) {
672
- if (return_with_value) {
675
+ if (keyword_with_value) {
673
676
  start.comments_before = [];
674
677
  } else {
675
678
  return;
@@ -682,10 +685,12 @@ function OutputStream(options) {
682
685
  }
683
686
  printed_comments.add(comments);
684
687
 
685
- if (return_with_value) {
688
+ if (keyword_with_value) {
686
689
  var tw = new TreeWalker(function(node) {
687
690
  var parent = tw.parent();
688
691
  if (parent instanceof AST_Exit
692
+ || parent instanceof AST_Await
693
+ || parent instanceof AST_Yield
689
694
  || parent instanceof AST_Binary && parent.left === node
690
695
  || parent.TYPE == "Call" && parent.expression === node
691
696
  || parent instanceof AST_Conditional && parent.condition === node
@@ -704,7 +709,7 @@ function OutputStream(options) {
704
709
  }
705
710
  });
706
711
  tw.push(node);
707
- node.value.walk(tw);
712
+ keyword_with_value.walk(tw);
708
713
  }
709
714
 
710
715
  if (current_pos == 0) {
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.17.3",
7
+ "version": "5.17.4",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },