terser 5.16.5 → 5.16.8

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.16.8
4
+
5
+ - Become even less conservative around function definitions for `reduce_vars`
6
+ - Fix parsing context of `import.meta` expressions such that method calls are allowed
7
+
8
+ ## v5.16.7
9
+
10
+ - Become less conservative with analyzing function definitions for `reduce_vars`
11
+ - Parse `import.meta` as a real AST node and not an `object.property`
12
+
3
13
  ## v5.16.5
4
14
 
5
15
  - Correctly handle AST transform functions that mutate children arrays
@@ -2450,8 +2450,8 @@ function parse($TEXT, options) {
2450
2450
  if (is("operator", "new")) {
2451
2451
  return new_(allow_calls);
2452
2452
  }
2453
- if (is("operator", "import")) {
2454
- return import_meta();
2453
+ if (is("name", "import") && is_token(peek(), "punc", ".")) {
2454
+ return import_meta(allow_calls);
2455
2455
  }
2456
2456
  var start = S.token;
2457
2457
  var peeked;
@@ -2944,15 +2944,15 @@ function parse($TEXT, options) {
2944
2944
  });
2945
2945
  }
2946
2946
 
2947
- function import_meta() {
2947
+ function import_meta(allow_calls) {
2948
2948
  var start = S.token;
2949
- expect_token("operator", "import");
2949
+ expect_token("name", "import");
2950
2950
  expect_token("punc", ".");
2951
2951
  expect_token("name", "meta");
2952
2952
  return subscripts(new AST_ImportMeta({
2953
2953
  start: start,
2954
2954
  end: prev()
2955
- }), false);
2955
+ }), allow_calls);
2956
2956
  }
2957
2957
 
2958
2958
  function map_name(is_import) {
@@ -13489,6 +13489,7 @@ function is_nullish(node, compressor) {
13489
13489
  || this.body && this.body.has_side_effects(compressor)
13490
13490
  || this.alternative && this.alternative.has_side_effects(compressor);
13491
13491
  });
13492
+ def_has_side_effects(AST_ImportMeta, return_false);
13492
13493
  def_has_side_effects(AST_LabeledStatement, function(compressor) {
13493
13494
  return this.body.has_side_effects(compressor);
13494
13495
  });
@@ -13592,6 +13593,7 @@ function is_nullish(node, compressor) {
13592
13593
  def_may_throw(AST_Lambda, return_false);
13593
13594
  def_may_throw(AST_SymbolDeclaration, return_false);
13594
13595
  def_may_throw(AST_This, return_false);
13596
+ def_may_throw(AST_ImportMeta, return_false);
13595
13597
 
13596
13598
  function any(list, compressor) {
13597
13599
  for (var i = list.length; --i >= 0;)
@@ -13955,6 +13957,11 @@ function is_lhs(node, parent) {
13955
13957
  var name = this.name + suffix;
13956
13958
  if (HOP(defines, name)) return to_node(defines[name], this);
13957
13959
  });
13960
+ def_find_defs(AST_ImportMeta, function(compressor, suffix) {
13961
+ var defines = compressor.option("global_defs");
13962
+ var name = "import.meta" + suffix;
13963
+ if (HOP(defines, name)) return to_node(defines[name], this);
13964
+ });
13958
13965
  })(function(node, func) {
13959
13966
  node.DEFMETHOD("_find_defs", func);
13960
13967
  });
@@ -15702,17 +15709,7 @@ def_reduce_vars(AST_Default, function(tw, descend) {
15702
15709
 
15703
15710
  function mark_lambda(tw, descend, compressor) {
15704
15711
  clear_flag(this, INLINED);
15705
-
15706
- // Sometimes we detach the lambda for safety, and instead of push()
15707
- // we go to an entirely fresh lineage of safe_ids.
15708
- let previous_safe_ids;
15709
- if (this instanceof AST_Defun || this.uses_arguments || this.pinned()) {
15710
- previous_safe_ids = tw.safe_ids;
15711
- tw.safe_ids = Object.create(null);
15712
- } else {
15713
- push(tw);
15714
- }
15715
-
15712
+ push(tw);
15716
15713
  reset_variables(tw, compressor, this);
15717
15714
 
15718
15715
  var iife;
@@ -15743,17 +15740,90 @@ function mark_lambda(tw, descend, compressor) {
15743
15740
  }
15744
15741
  });
15745
15742
  }
15743
+
15746
15744
  descend();
15745
+ pop(tw);
15747
15746
 
15748
- if (previous_safe_ids) {
15749
- tw.safe_ids = previous_safe_ids;
15750
- } else {
15751
- pop(tw);
15752
- }
15747
+ handle_defined_after_hoist(this);
15753
15748
 
15754
15749
  return true;
15755
15750
  }
15756
15751
 
15752
+ /**
15753
+ * It's possible for a hoisted function to use something that's not defined yet. Example:
15754
+ *
15755
+ * hoisted();
15756
+ * var defined_after = true;
15757
+ * function hoisted() {
15758
+ * // use defined_after
15759
+ * }
15760
+ *
15761
+ * This function is called on the parent to handle this issue.
15762
+ */
15763
+ function handle_defined_after_hoist(parent) {
15764
+ const defuns = [];
15765
+ walk(parent, node => {
15766
+ if (node === parent) return;
15767
+ if (node instanceof AST_Defun) defuns.push(node);
15768
+ if (
15769
+ node instanceof AST_Scope
15770
+ || node instanceof AST_SimpleStatement
15771
+ ) return true;
15772
+ });
15773
+
15774
+ for (const defun of defuns) {
15775
+ const fname_def = defun.name.definition();
15776
+ const found_self_ref_in_other_defuns = defuns.some(
15777
+ d => d !== defun && d.enclosed.indexOf(fname_def) !== -1
15778
+ );
15779
+
15780
+ for (const def of defun.enclosed) {
15781
+ if (
15782
+ def.fixed === false
15783
+ || def === fname_def
15784
+ || def.scope.get_defun_scope() !== parent
15785
+ ) {
15786
+ continue;
15787
+ }
15788
+
15789
+ // defun is hoisted, so always safe
15790
+ if (
15791
+ def.assignments === 0
15792
+ && def.orig.length === 1
15793
+ && def.orig[0] instanceof AST_SymbolDefun
15794
+ ) {
15795
+ continue;
15796
+ }
15797
+
15798
+ if (found_self_ref_in_other_defuns) {
15799
+ def.fixed = false;
15800
+ continue;
15801
+ }
15802
+
15803
+ // Detect `call_defun(); var used_in_defun = ...`
15804
+ // Because `used_in_defun` can no longer be fixed
15805
+ let found_defun = false;
15806
+ let found_def_after_defun = false;
15807
+ walk(parent, node => {
15808
+ if (node === defun) return true;
15809
+
15810
+ if (node instanceof AST_Symbol) {
15811
+ if (!found_defun && node.thedef === fname_def) {
15812
+ found_defun = true;
15813
+ } else if (found_defun && node.thedef === def) {
15814
+ found_def_after_defun = true;
15815
+ return walk_abort;
15816
+ }
15817
+ }
15818
+ });
15819
+
15820
+ if (found_def_after_defun) {
15821
+ def.fixed = false;
15822
+ }
15823
+ }
15824
+ }
15825
+ }
15826
+
15757
15827
  def_reduce_vars(AST_Lambda, mark_lambda);
15758
15828
 
15759
15829
  def_reduce_vars(AST_Do, function(tw, descend, compressor) {
@@ -15874,6 +15944,9 @@ def_reduce_vars(AST_Toplevel, function(tw, descend, compressor) {
15874
15944
  reset_def(compressor, def);
15875
15945
  });
15876
15946
  reset_variables(tw, compressor, this);
15947
+ descend();
15948
+ handle_defined_after_hoist(this);
15949
+ return true;
15877
15950
  });
15878
15951
 
15879
15952
  def_reduce_vars(AST_Try, function(tw, descend, compressor) {
@@ -67,6 +67,7 @@ import {
67
67
  AST_Function,
68
68
  AST_If,
69
69
  AST_Import,
70
+ AST_ImportMeta,
70
71
  AST_Jump,
71
72
  AST_LabeledStatement,
72
73
  AST_Lambda,
@@ -310,6 +311,7 @@ export function is_nullish(node, compressor) {
310
311
  || this.body && this.body.has_side_effects(compressor)
311
312
  || this.alternative && this.alternative.has_side_effects(compressor);
312
313
  });
314
+ def_has_side_effects(AST_ImportMeta, return_false);
313
315
  def_has_side_effects(AST_LabeledStatement, function(compressor) {
314
316
  return this.body.has_side_effects(compressor);
315
317
  });
@@ -413,6 +415,7 @@ export function is_nullish(node, compressor) {
413
415
  def_may_throw(AST_Lambda, return_false);
414
416
  def_may_throw(AST_SymbolDeclaration, return_false);
415
417
  def_may_throw(AST_This, return_false);
418
+ def_may_throw(AST_ImportMeta, return_false);
416
419
 
417
420
  function any(list, compressor) {
418
421
  for (var i = list.length; --i >= 0;)
@@ -776,6 +779,11 @@ export function is_lhs(node, parent) {
776
779
  var name = this.name + suffix;
777
780
  if (HOP(defines, name)) return to_node(defines[name], this);
778
781
  });
782
+ def_find_defs(AST_ImportMeta, function(compressor, suffix) {
783
+ var defines = compressor.option("global_defs");
784
+ var name = "import.meta" + suffix;
785
+ if (HOP(defines, name)) return to_node(defines[name], this);
786
+ });
779
787
  })(function(node, func) {
780
788
  node.DEFMETHOD("_find_defs", func);
781
789
  });
@@ -71,6 +71,7 @@ import {
71
71
  AST_Number,
72
72
  AST_ObjectKeyVal,
73
73
  AST_PropAccess,
74
+ AST_Scope,
74
75
  AST_Sequence,
75
76
  AST_SimpleStatement,
76
77
  AST_Symbol,
@@ -91,6 +92,7 @@ import {
91
92
  AST_Yield,
92
93
 
93
94
  walk,
95
+ walk_abort,
94
96
  walk_body,
95
97
 
96
98
  _INLINE,
@@ -447,17 +449,7 @@ def_reduce_vars(AST_Default, function(tw, descend) {
447
449
 
448
450
  function mark_lambda(tw, descend, compressor) {
449
451
  clear_flag(this, INLINED);
450
-
451
- // Sometimes we detach the lambda for safety, and instead of push()
452
- // we go to an entirely fresh lineage of safe_ids.
453
- let previous_safe_ids;
454
- if (this instanceof AST_Defun || this.uses_arguments || this.pinned()) {
455
- previous_safe_ids = tw.safe_ids;
456
- tw.safe_ids = Object.create(null);
457
- } else {
458
- push(tw);
459
- }
460
-
452
+ push(tw);
461
453
  reset_variables(tw, compressor, this);
462
454
 
463
455
  var iife;
@@ -488,17 +480,90 @@ function mark_lambda(tw, descend, compressor) {
488
480
  }
489
481
  });
490
482
  }
483
+
491
484
  descend();
485
+ pop(tw);
492
486
 
493
- if (previous_safe_ids) {
494
- tw.safe_ids = previous_safe_ids;
495
- } else {
496
- pop(tw);
497
- }
487
+ handle_defined_after_hoist(this);
498
488
 
499
489
  return true;
500
490
  }
501
491
 
492
+ /**
493
+ * It's possible for a hoisted function to use something that's not defined yet. Example:
494
+ *
495
+ * hoisted();
496
+ * var defined_after = true;
497
+ * function hoisted() {
498
+ * // use defined_after
499
+ * }
500
+ *
501
+ * This function is called on the parent to handle this issue.
502
+ */
503
+ function handle_defined_after_hoist(parent) {
504
+ const defuns = [];
505
+ walk(parent, node => {
506
+ if (node === parent) return;
507
+ if (node instanceof AST_Defun) defuns.push(node);
508
+ if (
509
+ node instanceof AST_Scope
510
+ || node instanceof AST_SimpleStatement
511
+ ) return true;
512
+ });
513
+
514
+ for (const defun of defuns) {
515
+ const fname_def = defun.name.definition();
516
+ const found_self_ref_in_other_defuns = defuns.some(
517
+ d => d !== defun && d.enclosed.indexOf(fname_def) !== -1
518
+ );
519
+
520
+ for (const def of defun.enclosed) {
521
+ if (
522
+ def.fixed === false
523
+ || def === fname_def
524
+ || def.scope.get_defun_scope() !== parent
525
+ ) {
526
+ continue;
527
+ }
528
+
529
+ // defun is hoisted, so always safe
530
+ if (
531
+ def.assignments === 0
532
+ && def.orig.length === 1
533
+ && def.orig[0] instanceof AST_SymbolDefun
534
+ ) {
535
+ continue;
536
+ }
537
+
538
+ if (found_self_ref_in_other_defuns) {
539
+ def.fixed = false;
540
+ continue;
541
+ }
542
+
543
+ // Detect `call_defun(); var used_in_defun = ...`
544
+ // Because `used_in_defun` can no longer be fixed
545
+ let found_defun = false;
546
+ let found_def_after_defun = false;
547
+ walk(parent, node => {
548
+ if (node === defun) return true;
549
+
550
+ if (node instanceof AST_Symbol) {
551
+ if (!found_defun && node.thedef === fname_def) {
552
+ found_defun = true;
553
+ } else if (found_defun && node.thedef === def) {
554
+ found_def_after_defun = true;
555
+ return walk_abort;
556
+ }
557
+ }
558
+ });
559
+
560
+ if (found_def_after_defun) {
561
+ def.fixed = false;
562
+ }
563
+ }
564
+ }
565
+ }
566
+
502
567
  def_reduce_vars(AST_Lambda, mark_lambda);
503
568
 
504
569
  def_reduce_vars(AST_Do, function(tw, descend, compressor) {
@@ -619,6 +684,9 @@ def_reduce_vars(AST_Toplevel, function(tw, descend, compressor) {
619
684
  reset_def(compressor, def);
620
685
  });
621
686
  reset_variables(tw, compressor, this);
687
+ descend();
688
+ handle_defined_after_hoist(this);
689
+ return true;
622
690
  });
623
691
 
624
692
  def_reduce_vars(AST_Try, function(tw, descend, compressor) {
package/lib/parse.js CHANGED
@@ -2307,8 +2307,8 @@ function parse($TEXT, options) {
2307
2307
  if (is("operator", "new")) {
2308
2308
  return new_(allow_calls);
2309
2309
  }
2310
- if (is("operator", "import")) {
2311
- return import_meta();
2310
+ if (is("name", "import") && is_token(peek(), "punc", ".")) {
2311
+ return import_meta(allow_calls);
2312
2312
  }
2313
2313
  var start = S.token;
2314
2314
  var peeked;
@@ -2801,15 +2801,15 @@ function parse($TEXT, options) {
2801
2801
  });
2802
2802
  }
2803
2803
 
2804
- function import_meta() {
2804
+ function import_meta(allow_calls) {
2805
2805
  var start = S.token;
2806
- expect_token("operator", "import");
2806
+ expect_token("name", "import");
2807
2807
  expect_token("punc", ".");
2808
2808
  expect_token("name", "meta");
2809
2809
  return subscripts(new AST_ImportMeta({
2810
2810
  start: start,
2811
2811
  end: prev()
2812
- }), false);
2812
+ }), allow_calls);
2813
2813
  }
2814
2814
 
2815
2815
  function map_name(is_import) {
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.5",
7
+ "version": "5.16.8",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },