terser 5.15.1 → 5.16.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.
@@ -56,7 +56,6 @@ import {
56
56
  AST_Catch,
57
57
  AST_Chain,
58
58
  AST_Class,
59
- AST_ClassExpression,
60
59
  AST_ClassProperty,
61
60
  AST_ClassStaticBlock,
62
61
  AST_ConciseMethod,
@@ -66,7 +65,6 @@ import {
66
65
  AST_Debugger,
67
66
  AST_Default,
68
67
  AST_DefaultAssign,
69
- AST_DefClass,
70
68
  AST_Definitions,
71
69
  AST_Defun,
72
70
  AST_Destructuring,
@@ -110,8 +108,6 @@ import {
110
108
  AST_Switch,
111
109
  AST_SwitchBranch,
112
110
  AST_Symbol,
113
- AST_SymbolBlockDeclaration,
114
- AST_SymbolCatch,
115
111
  AST_SymbolClassProperty,
116
112
  AST_SymbolDeclaration,
117
113
  AST_SymbolDefun,
@@ -121,7 +117,6 @@ import {
121
117
  AST_SymbolLet,
122
118
  AST_SymbolMethod,
123
119
  AST_SymbolRef,
124
- AST_SymbolVar,
125
120
  AST_TemplateString,
126
121
  AST_This,
127
122
  AST_Toplevel,
@@ -149,10 +144,8 @@ import {
149
144
  import {
150
145
  defaults,
151
146
  HOP,
152
- keep_name,
153
147
  make_node,
154
148
  makePredicate,
155
- map_add,
156
149
  MAP,
157
150
  remove,
158
151
  return_false,
@@ -170,14 +163,12 @@ import {
170
163
  PRECEDENCE,
171
164
  } from "../parse.js";
172
165
  import { OutputStream } from "../output.js";
173
- import {
174
- base54,
175
- SymbolDef,
176
- } from "../scope.js";
166
+ import { base54, format_mangler_options } from "../scope.js";
177
167
  import "../size.js";
178
168
 
179
169
  import "./evaluate.js";
180
170
  import "./drop-side-effect-free.js";
171
+ import "./drop-unused.js";
181
172
  import "./reduce-vars.js";
182
173
  import {
183
174
  is_undeclared_ref,
@@ -192,7 +183,6 @@ import {
192
183
  OPTIMIZED,
193
184
  CLEAR_BETWEEN_PASSES,
194
185
  TOP,
195
- WRITE_ONLY,
196
186
  UNDEFINED,
197
187
  UNUSED,
198
188
  TRUTHY,
@@ -214,7 +204,6 @@ import {
214
204
  is_empty,
215
205
  is_identifier_atom,
216
206
  is_reachable,
217
- is_ref_of,
218
207
  can_be_evicted_from_block,
219
208
  as_statement_array,
220
209
  retain_top_func,
@@ -332,7 +321,9 @@ class Compressor extends TreeWalker {
332
321
  this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
333
322
  this.evaluated_regexps = new Map();
334
323
  this._toplevel = undefined;
335
- this.mangle_options = mangle_options;
324
+ this.mangle_options = mangle_options
325
+ ? format_mangler_options(mangle_options)
326
+ : mangle_options;
336
327
  }
337
328
 
338
329
  option(key) {
@@ -653,382 +644,6 @@ function opt_AST_Lambda(self, compressor) {
653
644
  }
654
645
  def_optimize(AST_Lambda, opt_AST_Lambda);
655
646
 
656
- const r_keep_assign = /keep_assign/;
657
- AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
658
- if (!compressor.option("unused")) return;
659
- if (compressor.has_directive("use asm")) return;
660
- var self = this;
661
- if (self.pinned()) return;
662
- var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
663
- var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
664
- const assign_as_unused = r_keep_assign.test(compressor.option("unused")) ? return_false : function(node) {
665
- if (node instanceof AST_Assign
666
- && !node.logical
667
- && (has_flag(node, WRITE_ONLY) || node.operator == "=")
668
- ) {
669
- return node.left;
670
- }
671
- if (node instanceof AST_Unary && has_flag(node, WRITE_ONLY)) {
672
- return node.expression;
673
- }
674
- };
675
- var in_use_ids = new Map();
676
- var fixed_ids = new Map();
677
- if (self instanceof AST_Toplevel && compressor.top_retain) {
678
- self.variables.forEach(function(def) {
679
- if (compressor.top_retain(def) && !in_use_ids.has(def.id)) {
680
- in_use_ids.set(def.id, def);
681
- }
682
- });
683
- }
684
- var var_defs_by_id = new Map();
685
- var initializations = new Map();
686
- // pass 1: find out which symbols are directly used in
687
- // this scope (not in nested scopes).
688
- var scope = this;
689
- var tw = new TreeWalker(function(node, descend) {
690
- if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive("use strict")) {
691
- node.argnames.forEach(function(argname) {
692
- if (!(argname instanceof AST_SymbolDeclaration)) return;
693
- var def = argname.definition();
694
- if (!in_use_ids.has(def.id)) {
695
- in_use_ids.set(def.id, def);
696
- }
697
- });
698
- }
699
- if (node === self) return;
700
- if (node instanceof AST_Defun || node instanceof AST_DefClass) {
701
- var node_def = node.name.definition();
702
- const in_export = tw.parent() instanceof AST_Export;
703
- if (in_export || !drop_funcs && scope === self) {
704
- if (node_def.global && !in_use_ids.has(node_def.id)) {
705
- in_use_ids.set(node_def.id, node_def);
706
- }
707
- }
708
- if (node instanceof AST_DefClass) {
709
- if (
710
- node.extends
711
- && (node.extends.has_side_effects(compressor)
712
- || node.extends.may_throw(compressor))
713
- ) {
714
- node.extends.walk(tw);
715
- }
716
- for (const prop of node.properties) {
717
- if (
718
- prop.has_side_effects(compressor) ||
719
- prop.may_throw(compressor)
720
- ) {
721
- prop.walk(tw);
722
- }
723
- }
724
- }
725
- map_add(initializations, node_def.id, node);
726
- return true; // don't go in nested scopes
727
- }
728
- if (node instanceof AST_SymbolFunarg && scope === self) {
729
- map_add(var_defs_by_id, node.definition().id, node);
730
- }
731
- if (node instanceof AST_Definitions && scope === self) {
732
- const in_export = tw.parent() instanceof AST_Export;
733
- node.definitions.forEach(function(def) {
734
- if (def.name instanceof AST_SymbolVar) {
735
- map_add(var_defs_by_id, def.name.definition().id, def);
736
- }
737
- if (in_export || !drop_vars) {
738
- walk(def.name, node => {
739
- if (node instanceof AST_SymbolDeclaration) {
740
- const def = node.definition();
741
- if (
742
- (in_export || def.global)
743
- && !in_use_ids.has(def.id)
744
- ) {
745
- in_use_ids.set(def.id, def);
746
- }
747
- }
748
- });
749
- }
750
- if (def.value) {
751
- if (def.name instanceof AST_Destructuring) {
752
- def.walk(tw);
753
- } else {
754
- var node_def = def.name.definition();
755
- map_add(initializations, node_def.id, def.value);
756
- if (!node_def.chained && def.name.fixed_value() === def.value) {
757
- fixed_ids.set(node_def.id, def);
758
- }
759
- }
760
- if (def.value.has_side_effects(compressor)) {
761
- def.value.walk(tw);
762
- }
763
- }
764
- });
765
- return true;
766
- }
767
- return scan_ref_scoped(node, descend);
768
- });
769
- self.walk(tw);
770
- // pass 2: for every used symbol we need to walk its
771
- // initialization code to figure out if it uses other
772
- // symbols (that may not be in_use).
773
- tw = new TreeWalker(scan_ref_scoped);
774
- in_use_ids.forEach(function (def) {
775
- var init = initializations.get(def.id);
776
- if (init) init.forEach(function(init) {
777
- init.walk(tw);
778
- });
779
- });
780
- // pass 3: we should drop declarations not in_use
781
- var tt = new TreeTransformer(
782
- function before(node, descend, in_list) {
783
- var parent = tt.parent();
784
- if (drop_vars) {
785
- const sym = assign_as_unused(node);
786
- if (sym instanceof AST_SymbolRef) {
787
- var def = sym.definition();
788
- var in_use = in_use_ids.has(def.id);
789
- if (node instanceof AST_Assign) {
790
- if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
791
- return maintain_this_binding(parent, node, node.right.transform(tt));
792
- }
793
- } else if (!in_use) return in_list ? MAP.skip : make_node(AST_Number, node, {
794
- value: 0
795
- });
796
- }
797
- }
798
- if (scope !== self) return;
799
- var def;
800
- if (node.name
801
- && (node instanceof AST_ClassExpression
802
- && !keep_name(compressor.option("keep_classnames"), (def = node.name.definition()).name)
803
- || node instanceof AST_Function
804
- && !keep_name(compressor.option("keep_fnames"), (def = node.name.definition()).name))) {
805
- // any declarations with same name will overshadow
806
- // name of this anonymous function and can therefore
807
- // never be used anywhere
808
- if (!in_use_ids.has(def.id) || def.orig.length > 1) node.name = null;
809
- }
810
- if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
811
- var trim = !compressor.option("keep_fargs");
812
- for (var a = node.argnames, i = a.length; --i >= 0;) {
813
- var sym = a[i];
814
- if (sym instanceof AST_Expansion) {
815
- sym = sym.expression;
816
- }
817
- if (sym instanceof AST_DefaultAssign) {
818
- sym = sym.left;
819
- }
820
- // Do not drop destructuring arguments.
821
- // They constitute a type assertion, so dropping
822
- // them would stop that TypeError which would happen
823
- // if someone called it with an incorrectly formatted
824
- // parameter.
825
- if (!(sym instanceof AST_Destructuring) && !in_use_ids.has(sym.definition().id)) {
826
- set_flag(sym, UNUSED);
827
- if (trim) {
828
- a.pop();
829
- }
830
- } else {
831
- trim = false;
832
- }
833
- }
834
- }
835
- if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
836
- const def = node.name.definition();
837
- const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
838
- // Class "extends" and static blocks may have side effects
839
- const has_side_effects = !keep
840
- && node instanceof AST_Class
841
- && node.has_side_effects(compressor);
842
- if (!keep && !has_side_effects) {
843
- def.eliminated++;
844
- return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
845
- }
846
- }
847
- if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
848
- var drop_block = !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var);
849
- // place uninitialized names at the start
850
- var body = [], head = [], tail = [];
851
- // for unused names whose initialization has
852
- // side effects, we can cascade the init. code
853
- // into the next one, or next statement.
854
- var side_effects = [];
855
- node.definitions.forEach(function(def) {
856
- if (def.value) def.value = def.value.transform(tt);
857
- var is_destructure = def.name instanceof AST_Destructuring;
858
- var sym = is_destructure
859
- ? new SymbolDef(null, { name: "<destructure>" }) /* fake SymbolDef */
860
- : def.name.definition();
861
- if (drop_block && sym.global) return tail.push(def);
862
- if (!(drop_vars || drop_block)
863
- || is_destructure
864
- && (def.name.names.length
865
- || def.name.is_array
866
- || compressor.option("pure_getters") != true)
867
- || in_use_ids.has(sym.id)
868
- ) {
869
- if (def.value && fixed_ids.has(sym.id) && fixed_ids.get(sym.id) !== def) {
870
- def.value = def.value.drop_side_effect_free(compressor);
871
- }
872
- if (def.name instanceof AST_SymbolVar) {
873
- var var_defs = var_defs_by_id.get(sym.id);
874
- if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
875
- if (def.value) {
876
- var ref = make_node(AST_SymbolRef, def.name, def.name);
877
- sym.references.push(ref);
878
- var assign = make_node(AST_Assign, def, {
879
- operator: "=",
880
- logical: false,
881
- left: ref,
882
- right: def.value
883
- });
884
- if (fixed_ids.get(sym.id) === def) {
885
- fixed_ids.set(sym.id, assign);
886
- }
887
- side_effects.push(assign.transform(tt));
888
- }
889
- remove(var_defs, def);
890
- sym.eliminated++;
891
- return;
892
- }
893
- }
894
- if (def.value) {
895
- if (side_effects.length > 0) {
896
- if (tail.length > 0) {
897
- side_effects.push(def.value);
898
- def.value = make_sequence(def.value, side_effects);
899
- } else {
900
- body.push(make_node(AST_SimpleStatement, node, {
901
- body: make_sequence(node, side_effects)
902
- }));
903
- }
904
- side_effects = [];
905
- }
906
- tail.push(def);
907
- } else {
908
- head.push(def);
909
- }
910
- } else if (sym.orig[0] instanceof AST_SymbolCatch) {
911
- var value = def.value && def.value.drop_side_effect_free(compressor);
912
- if (value) side_effects.push(value);
913
- def.value = null;
914
- head.push(def);
915
- } else {
916
- var value = def.value && def.value.drop_side_effect_free(compressor);
917
- if (value) {
918
- side_effects.push(value);
919
- }
920
- sym.eliminated++;
921
- }
922
- });
923
- if (head.length > 0 || tail.length > 0) {
924
- node.definitions = head.concat(tail);
925
- body.push(node);
926
- }
927
- if (side_effects.length > 0) {
928
- body.push(make_node(AST_SimpleStatement, node, {
929
- body: make_sequence(node, side_effects)
930
- }));
931
- }
932
- switch (body.length) {
933
- case 0:
934
- return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
935
- case 1:
936
- return body[0];
937
- default:
938
- return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
939
- body: body
940
- });
941
- }
942
- }
943
- // certain combination of unused name + side effect leads to:
944
- // https://github.com/mishoo/UglifyJS2/issues/44
945
- // https://github.com/mishoo/UglifyJS2/issues/1830
946
- // https://github.com/mishoo/UglifyJS2/issues/1838
947
- // that's an invalid AST.
948
- // We fix it at this stage by moving the `var` outside the `for`.
949
- if (node instanceof AST_For) {
950
- descend(node, this);
951
- var block;
952
- if (node.init instanceof AST_BlockStatement) {
953
- block = node.init;
954
- node.init = block.body.pop();
955
- block.body.push(node);
956
- }
957
- if (node.init instanceof AST_SimpleStatement) {
958
- node.init = node.init.body;
959
- } else if (is_empty(node.init)) {
960
- node.init = null;
961
- }
962
- return !block ? node : in_list ? MAP.splice(block.body) : block;
963
- }
964
- if (node instanceof AST_LabeledStatement
965
- && node.body instanceof AST_For
966
- ) {
967
- descend(node, this);
968
- if (node.body instanceof AST_BlockStatement) {
969
- var block = node.body;
970
- node.body = block.body.pop();
971
- block.body.push(node);
972
- return in_list ? MAP.splice(block.body) : block;
973
- }
974
- return node;
975
- }
976
- if (node instanceof AST_BlockStatement) {
977
- descend(node, this);
978
- if (in_list && node.body.every(can_be_evicted_from_block)) {
979
- return MAP.splice(node.body);
980
- }
981
- return node;
982
- }
983
- if (node instanceof AST_Scope) {
984
- const save_scope = scope;
985
- scope = node;
986
- descend(node, this);
987
- scope = save_scope;
988
- return node;
989
- }
990
- }
991
- );
992
-
993
- self.transform(tt);
994
-
995
- function scan_ref_scoped(node, descend) {
996
- var node_def;
997
- const sym = assign_as_unused(node);
998
- if (sym instanceof AST_SymbolRef
999
- && !is_ref_of(node.left, AST_SymbolBlockDeclaration)
1000
- && self.variables.get(sym.name) === (node_def = sym.definition())
1001
- ) {
1002
- if (node instanceof AST_Assign) {
1003
- node.right.walk(tw);
1004
- if (!node_def.chained && node.left.fixed_value() === node.right) {
1005
- fixed_ids.set(node_def.id, node);
1006
- }
1007
- }
1008
- return true;
1009
- }
1010
- if (node instanceof AST_SymbolRef) {
1011
- node_def = node.definition();
1012
- if (!in_use_ids.has(node_def.id)) {
1013
- in_use_ids.set(node_def.id, node_def);
1014
- if (node_def.orig[0] instanceof AST_SymbolCatch) {
1015
- const redef = node_def.scope.is_block_scope()
1016
- && node_def.scope.get_defun_scope().variables.get(node_def.name);
1017
- if (redef) in_use_ids.set(redef.id, redef);
1018
- }
1019
- }
1020
- return true;
1021
- }
1022
- if (node instanceof AST_Scope) {
1023
- var save_scope = scope;
1024
- scope = node;
1025
- descend();
1026
- scope = save_scope;
1027
- return true;
1028
- }
1029
- }
1030
- });
1031
-
1032
647
  AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
1033
648
  var self = this;
1034
649
  if (compressor.has_directive("use asm")) return self;
@@ -1173,8 +788,6 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
1173
788
  var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
1174
789
  var defs_by_id = new Map();
1175
790
  var hoister = new TreeTransformer(function(node, descend) {
1176
- if (node instanceof AST_Definitions
1177
- && hoister.parent() instanceof AST_Export) return node;
1178
791
  if (node instanceof AST_VarDef) {
1179
792
  const sym = node.name;
1180
793
  let def;
@@ -1965,16 +1578,6 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1965
1578
  right : def.value
1966
1579
  }));
1967
1580
  if (reduce_vars) name.definition().fixed = false;
1968
- } else if (def.value) {
1969
- // Because it's a destructuring, do not turn into an assignment.
1970
- var varDef = make_node(AST_VarDef, def, {
1971
- name: def.name,
1972
- value: def.value
1973
- });
1974
- var var_ = make_node(AST_Var, def, {
1975
- definitions: [ varDef ]
1976
- });
1977
- assignments.push(var_);
1978
1581
  }
1979
1582
  const thedef = def.name.definition();
1980
1583
  thedef.eliminated++;
@@ -1986,8 +1589,9 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1986
1589
  });
1987
1590
 
1988
1591
  def_optimize(AST_Definitions, function(self) {
1989
- if (self.definitions.length == 0)
1592
+ if (self.definitions.length == 0) {
1990
1593
  return make_node(AST_EmptyStatement, self);
1594
+ }
1991
1595
  return self;
1992
1596
  });
1993
1597
 
@@ -573,7 +573,6 @@ export function is_nullish(node, compressor) {
573
573
  return true;
574
574
  }
575
575
  if (node instanceof AST_This && this instanceof AST_Arrow) {
576
- // TODO check arguments too!
577
576
  result = false;
578
577
  return walk_abort;
579
578
  }
@@ -694,7 +693,7 @@ export function is_nullish(node, compressor) {
694
693
  return this.tail_node()._dot_throw(compressor);
695
694
  });
696
695
  def_may_throw_on_access(AST_SymbolRef, function(compressor) {
697
- if (this.name === "arguments") return false;
696
+ if (this.name === "arguments" && this.scope instanceof AST_Lambda) return false;
698
697
  if (has_flag(this, UNDEFINED)) return true;
699
698
  if (!is_strict(compressor)) return false;
700
699
  if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
@@ -57,10 +57,8 @@ import {
57
57
  AST_Expansion,
58
58
  AST_Export,
59
59
  AST_Function,
60
- AST_Infinity,
61
60
  AST_IterationStatement,
62
61
  AST_Lambda,
63
- AST_NaN,
64
62
  AST_Node,
65
63
  AST_Number,
66
64
  AST_Object,
@@ -81,7 +79,6 @@ import {
81
79
  AST_Undefined,
82
80
  AST_Var,
83
81
  AST_VarDef,
84
- AST_With,
85
82
 
86
83
  walk,
87
84
 
@@ -95,7 +92,7 @@ import "../size.js";
95
92
  import "./evaluate.js";
96
93
  import "./drop-side-effect-free.js";
97
94
  import "./reduce-vars.js";
98
- import { is_undeclared_ref, is_lhs } from "./inference.js";
95
+ import { is_lhs } from "./inference.js";
99
96
  import {
100
97
  SQUEEZED,
101
98
  INLINED,
@@ -146,21 +143,6 @@ function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
146
143
  }
147
144
 
148
145
  export function inline_into_symbolref(self, compressor) {
149
- if (
150
- !compressor.option("ie8")
151
- && is_undeclared_ref(self)
152
- && !compressor.find_parent(AST_With)
153
- ) {
154
- switch (self.name) {
155
- case "undefined":
156
- return make_node(AST_Undefined, self).optimize(compressor);
157
- case "NaN":
158
- return make_node(AST_NaN, self).optimize(compressor);
159
- case "Infinity":
160
- return make_node(AST_Infinity, self).optimize(compressor);
161
- }
162
- }
163
-
164
146
  const parent = compressor.parent();
165
147
  if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
166
148
  const def = self.definition();