terser 5.16.1 → 5.17.7

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.
@@ -245,6 +245,7 @@ class Compressor extends TreeWalker {
245
245
  keep_fargs : true,
246
246
  keep_fnames : false,
247
247
  keep_infinity : false,
248
+ lhs_constants : !false_by_default,
248
249
  loops : !false_by_default,
249
250
  module : false,
250
251
  negate_iife : !false_by_default,
@@ -441,6 +442,13 @@ class Compressor extends TreeWalker {
441
442
  if (opt === node) set_flag(opt, SQUEEZED);
442
443
  return opt;
443
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
+ }
444
452
  }
445
453
 
446
454
  function def_optimize(node, optimizer) {
@@ -647,8 +655,6 @@ def_optimize(AST_Lambda, opt_AST_Lambda);
647
655
  AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
648
656
  var self = this;
649
657
  if (compressor.has_directive("use asm")) return self;
650
- // Hoisting makes no sense in an arrow func
651
- if (!Array.isArray(self.body)) return self;
652
658
 
653
659
  var hoist_funs = compressor.option("hoist_funs");
654
660
  var hoist_vars = compressor.option("hoist_vars");
@@ -1529,9 +1535,9 @@ def_optimize(AST_Switch, function(self, compressor) {
1529
1535
  });
1530
1536
 
1531
1537
  def_optimize(AST_Try, function(self, compressor) {
1532
- tighten_body(self.body, compressor);
1533
1538
  if (self.bcatch && self.bfinally && self.bfinally.body.every(is_empty)) self.bfinally = null;
1534
- if (compressor.option("dead_code") && self.body.every(is_empty)) {
1539
+
1540
+ if (compressor.option("dead_code") && self.body.body.every(is_empty)) {
1535
1541
  var body = [];
1536
1542
  if (self.bcatch) {
1537
1543
  trim_unreachable_code(compressor, self.bcatch, body);
@@ -1544,26 +1550,6 @@ def_optimize(AST_Try, function(self, compressor) {
1544
1550
  return self;
1545
1551
  });
1546
1552
 
1547
- AST_Definitions.DEFMETHOD("remove_initializers", function() {
1548
- var decls = [];
1549
- this.definitions.forEach(function(def) {
1550
- if (def.name instanceof AST_SymbolDeclaration) {
1551
- def.value = null;
1552
- decls.push(def);
1553
- } else {
1554
- walk(def.name, node => {
1555
- if (node instanceof AST_SymbolDeclaration) {
1556
- decls.push(make_node(AST_VarDef, def, {
1557
- name: node,
1558
- value: null
1559
- }));
1560
- }
1561
- });
1562
- }
1563
- });
1564
- this.definitions = decls;
1565
- });
1566
-
1567
1553
  AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1568
1554
  var reduce_vars = compressor.option("reduce_vars");
1569
1555
  var assignments = [];
@@ -2131,7 +2117,7 @@ def_optimize(AST_Binary, function(self, compressor) {
2131
2117
  self.right = tmp;
2132
2118
  }
2133
2119
  }
2134
- if (commutativeOperators.has(self.operator)) {
2120
+ if (compressor.option("lhs_constants") && commutativeOperators.has(self.operator)) {
2135
2121
  if (self.right.is_constant()
2136
2122
  && !self.left.is_constant()) {
2137
2123
  // if right is a constant, whatever side effects the
@@ -2161,6 +2147,9 @@ def_optimize(AST_Binary, function(self, compressor) {
2161
2147
  // void 0 == x => null == x
2162
2148
  if (!is_strict_comparison && is_undefined(self.left, compressor)) {
2163
2149
  self.left = make_node(AST_Null, self.left);
2150
+ // x == void 0 => x == null
2151
+ } else if (!is_strict_comparison && is_undefined(self.right, compressor)) {
2152
+ self.right = make_node(AST_Null, self.right);
2164
2153
  } else if (compressor.option("typeofs")
2165
2154
  // "undefined" == typeof x => undefined === x
2166
2155
  && self.left instanceof AST_String
@@ -2174,6 +2163,19 @@ def_optimize(AST_Binary, function(self, compressor) {
2174
2163
  self.left = make_node(AST_Undefined, self.left).optimize(compressor);
2175
2164
  if (self.operator.length == 2) self.operator += "=";
2176
2165
  }
2166
+ } else if (compressor.option("typeofs")
2167
+ // typeof x === "undefined" => x === undefined
2168
+ && self.left instanceof AST_UnaryPrefix
2169
+ && self.left.operator == "typeof"
2170
+ && self.right instanceof AST_String
2171
+ && self.right.value == "undefined") {
2172
+ var expr = self.left.expression;
2173
+ if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
2174
+ : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
2175
+ self.left = expr;
2176
+ self.right = make_node(AST_Undefined, self.right).optimize(compressor);
2177
+ if (self.operator.length == 2) self.operator += "=";
2178
+ }
2177
2179
  } else if (self.left instanceof AST_SymbolRef
2178
2180
  // obj !== obj => false
2179
2181
  && self.right instanceof AST_SymbolRef
@@ -2602,8 +2604,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
2602
2604
  }
2603
2605
  }
2604
2606
 
2605
- const parent = compressor.parent();
2606
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
2607
+ if (compressor.option("reduce_vars") && !compressor.is_lhs()) {
2607
2608
  return inline_into_symbolref(self, compressor);
2608
2609
  } else {
2609
2610
  return self;
@@ -2627,7 +2628,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
2627
2628
  return ref;
2628
2629
  }
2629
2630
  }
2630
- var lhs = is_lhs(compressor.self(), compressor.parent());
2631
+ var lhs = compressor.is_lhs();
2631
2632
  if (lhs && is_atomic(lhs, self)) return self;
2632
2633
  return make_node(AST_UnaryPrefix, self, {
2633
2634
  operator: "void",
@@ -2638,7 +2639,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
2638
2639
  });
2639
2640
 
2640
2641
  def_optimize(AST_Infinity, function(self, compressor) {
2641
- var lhs = is_lhs(compressor.self(), compressor.parent());
2642
+ var lhs = compressor.is_lhs();
2642
2643
  if (lhs && is_atomic(lhs, self)) return self;
2643
2644
  if (
2644
2645
  compressor.option("keep_infinity")
@@ -2659,7 +2660,7 @@ def_optimize(AST_Infinity, function(self, compressor) {
2659
2660
  });
2660
2661
 
2661
2662
  def_optimize(AST_NaN, function(self, compressor) {
2662
- var lhs = is_lhs(compressor.self(), compressor.parent());
2663
+ var lhs = compressor.is_lhs();
2663
2664
  if (lhs && !is_atomic(lhs, self)
2664
2665
  || find_variable(compressor, "NaN")) {
2665
2666
  return make_node(AST_Binary, self, {
@@ -2737,16 +2738,21 @@ def_optimize(AST_Assign, function(self, compressor) {
2737
2738
  return self;
2738
2739
 
2739
2740
  function in_try(level, node) {
2740
- var right = self.right;
2741
- self.right = make_node(AST_Null, right);
2742
- var may_throw = node.may_throw(compressor);
2743
- self.right = right;
2744
- var scope = self.left.definition().scope;
2741
+ function may_assignment_throw() {
2742
+ const right = self.right;
2743
+ self.right = make_node(AST_Null, right);
2744
+ const may_throw = node.may_throw(compressor);
2745
+ self.right = right;
2746
+
2747
+ return may_throw;
2748
+ }
2749
+
2750
+ var stop_at = self.left.definition().scope.get_defun_scope();
2745
2751
  var parent;
2746
- while ((parent = compressor.parent(level++)) !== scope) {
2752
+ while ((parent = compressor.parent(level++)) !== stop_at) {
2747
2753
  if (parent instanceof AST_Try) {
2748
2754
  if (parent.bfinally) return true;
2749
- if (may_throw && parent.bcatch) return true;
2755
+ if (parent.bcatch && may_assignment_throw()) return true;
2750
2756
  }
2751
2757
  }
2752
2758
  }
@@ -2759,8 +2765,21 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
2759
2765
  var evaluateRight = self.right.evaluate(compressor);
2760
2766
 
2761
2767
  // `[x = undefined] = foo` ---> `[x] = foo`
2768
+ // `(arg = undefined) => ...` ---> `(arg) => ...` (unless `keep_fargs`)
2769
+ // `((arg = undefined) => ...)()` ---> `((arg) => ...)()`
2770
+ let lambda, iife;
2762
2771
  if (evaluateRight === undefined) {
2763
- self = self.left;
2772
+ if (
2773
+ (lambda = compressor.parent()) instanceof AST_Lambda
2774
+ ? (
2775
+ compressor.option("keep_fargs") === false
2776
+ || (iife = compressor.parent(1)).TYPE === "Call"
2777
+ && iife.expression === lambda
2778
+ )
2779
+ : true
2780
+ ) {
2781
+ self = self.left;
2782
+ }
2764
2783
  } else if (evaluateRight !== self.right) {
2765
2784
  evaluateRight = make_node_from_constant(evaluateRight, self.right);
2766
2785
  self.right = best_of_expression(evaluateRight, self.right);
@@ -3217,7 +3236,10 @@ def_optimize(AST_Sub, function(self, compressor) {
3217
3236
  }
3218
3237
  }
3219
3238
  }
3220
- prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
3239
+ prop = self.property = best_of_expression(
3240
+ prop,
3241
+ make_node_from_constant(key, prop).transform(compressor)
3242
+ );
3221
3243
  var property = "" + key;
3222
3244
  if (is_basic_identifier_string(property)
3223
3245
  && property.length <= prop.size() + 1) {
@@ -3275,7 +3297,7 @@ def_optimize(AST_Sub, function(self, compressor) {
3275
3297
  return sym;
3276
3298
  }
3277
3299
  }
3278
- if (is_lhs(self, compressor.parent())) return self;
3300
+ if (compressor.is_lhs()) return self;
3279
3301
  if (key !== prop) {
3280
3302
  var sub = self.flatten_object(property, compressor);
3281
3303
  if (sub) {
@@ -3343,22 +3365,9 @@ def_optimize(AST_Chain, function (self, compressor) {
3343
3365
  return self;
3344
3366
  });
3345
3367
 
3346
- AST_Lambda.DEFMETHOD("contains_this", function() {
3347
- return walk(this, node => {
3348
- if (node instanceof AST_This) return walk_abort;
3349
- if (
3350
- node !== this
3351
- && node instanceof AST_Scope
3352
- && !(node instanceof AST_Arrow)
3353
- ) {
3354
- return true;
3355
- }
3356
- });
3357
- });
3358
-
3359
3368
  def_optimize(AST_Dot, function(self, compressor) {
3360
3369
  const parent = compressor.parent();
3361
- if (is_lhs(self, parent)) return self;
3370
+ if (compressor.is_lhs()) return self;
3362
3371
  if (compressor.option("unsafe_proto")
3363
3372
  && self.expression instanceof AST_Dot
3364
3373
  && self.expression.property == "prototype") {
@@ -45,6 +45,7 @@ import {
45
45
  AST_Array,
46
46
  AST_Arrow,
47
47
  AST_Assign,
48
+ AST_BigInt,
48
49
  AST_Binary,
49
50
  AST_Block,
50
51
  AST_BlockStatement,
@@ -63,9 +64,11 @@ import {
63
64
  AST_EmptyStatement,
64
65
  AST_Expansion,
65
66
  AST_False,
67
+ AST_ForIn,
66
68
  AST_Function,
67
69
  AST_If,
68
70
  AST_Import,
71
+ AST_ImportMeta,
69
72
  AST_Jump,
70
73
  AST_LabeledStatement,
71
74
  AST_Lambda,
@@ -81,6 +84,7 @@ import {
81
84
  AST_PropAccess,
82
85
  AST_RegExp,
83
86
  AST_Return,
87
+ AST_Scope,
84
88
  AST_Sequence,
85
89
  AST_SimpleStatement,
86
90
  AST_Statement,
@@ -171,7 +175,7 @@ export const unary_side_effects = makePredicate("delete ++ --");
171
175
  def_is_number(AST_Number, return_true);
172
176
  const unary = makePredicate("+ - ~ ++ --");
173
177
  def_is_number(AST_Unary, function() {
174
- return unary.has(this.operator);
178
+ return unary.has(this.operator) && !(this.expression instanceof AST_BigInt);
175
179
  });
176
180
  const numeric_ops = makePredicate("- * / % & | ^ << >> >>>");
177
181
  def_is_number(AST_Binary, function(compressor) {
@@ -300,7 +304,7 @@ export function is_nullish(node, compressor) {
300
304
  || any(this.body, compressor);
301
305
  });
302
306
  def_has_side_effects(AST_Try, function(compressor) {
303
- return any(this.body, compressor)
307
+ return this.body.has_side_effects(compressor)
304
308
  || this.bcatch && this.bcatch.has_side_effects(compressor)
305
309
  || this.bfinally && this.bfinally.has_side_effects(compressor);
306
310
  });
@@ -309,6 +313,7 @@ export function is_nullish(node, compressor) {
309
313
  || this.body && this.body.has_side_effects(compressor)
310
314
  || this.alternative && this.alternative.has_side_effects(compressor);
311
315
  });
316
+ def_has_side_effects(AST_ImportMeta, return_false);
312
317
  def_has_side_effects(AST_LabeledStatement, function(compressor) {
313
318
  return this.body.has_side_effects(compressor);
314
319
  });
@@ -412,6 +417,7 @@ export function is_nullish(node, compressor) {
412
417
  def_may_throw(AST_Lambda, return_false);
413
418
  def_may_throw(AST_SymbolDeclaration, return_false);
414
419
  def_may_throw(AST_This, return_false);
420
+ def_may_throw(AST_ImportMeta, return_false);
415
421
 
416
422
  function any(list, compressor) {
417
423
  for (var i = list.length; --i >= 0;)
@@ -529,7 +535,7 @@ export function is_nullish(node, compressor) {
529
535
  });
530
536
  def_may_throw(AST_SymbolClassProperty, return_false);
531
537
  def_may_throw(AST_Try, function(compressor) {
532
- return this.bcatch ? this.bcatch.may_throw(compressor) : any(this.body, compressor)
538
+ return this.bcatch ? this.bcatch.may_throw(compressor) : this.body.may_throw(compressor)
533
539
  || this.bfinally && this.bfinally.may_throw(compressor);
534
540
  });
535
541
  def_may_throw(AST_Unary, function(compressor) {
@@ -708,6 +714,7 @@ export function is_nullish(node, compressor) {
708
714
  export function is_lhs(node, parent) {
709
715
  if (parent instanceof AST_Unary && unary_side_effects.has(parent.operator)) return parent.expression;
710
716
  if (parent instanceof AST_Assign && parent.left === node) return node;
717
+ if (parent instanceof AST_ForIn && parent.init === node) return node;
711
718
  }
712
719
 
713
720
  (function(def_find_defs) {
@@ -775,6 +782,11 @@ export function is_lhs(node, parent) {
775
782
  var name = this.name + suffix;
776
783
  if (HOP(defines, name)) return to_node(defines[name], this);
777
784
  });
785
+ def_find_defs(AST_ImportMeta, function(compressor, suffix) {
786
+ var defines = compressor.option("global_defs");
787
+ var name = "import.meta" + suffix;
788
+ if (HOP(defines, name)) return to_node(defines[name], this);
789
+ });
778
790
  })(function(node, func) {
779
791
  node.DEFMETHOD("_find_defs", func);
780
792
  });
@@ -806,6 +818,9 @@ export function is_lhs(node, parent) {
806
818
  def_negate(AST_Function, function() {
807
819
  return basic_negation(this);
808
820
  });
821
+ def_negate(AST_Class, function() {
822
+ return basic_negation(this);
823
+ });
809
824
  def_negate(AST_Arrow, function() {
810
825
  return basic_negation(this);
811
826
  });
@@ -939,6 +954,19 @@ export const aborts = (thing) => thing && thing.aborts();
939
954
  node.DEFMETHOD("aborts", func);
940
955
  });
941
956
 
957
+ AST_Node.DEFMETHOD("contains_this", function() {
958
+ return walk(this, node => {
959
+ if (node instanceof AST_This) return walk_abort;
960
+ if (
961
+ node !== this
962
+ && node instanceof AST_Scope
963
+ && !(node instanceof AST_Arrow)
964
+ ) {
965
+ return true;
966
+ }
967
+ });
968
+ });
969
+
942
970
  export function is_modified(compressor, tw, node, value, level, immutable) {
943
971
  var parent = tw.parent(level);
944
972
  var lhs = is_lhs(node, parent);
@@ -92,7 +92,6 @@ import "../size.js";
92
92
  import "./evaluate.js";
93
93
  import "./drop-side-effect-free.js";
94
94
  import "./reduce-vars.js";
95
- import { is_lhs } from "./inference.js";
96
95
  import {
97
96
  SQUEEZED,
98
97
  INLINED,
@@ -114,6 +113,13 @@ import {
114
113
  retain_top_func,
115
114
  } from "./common.js";
116
115
 
116
+ /**
117
+ * Module that contains the inlining logic.
118
+ *
119
+ * @module
120
+ *
121
+ * The stars of the show are `inline_into_symbolref` and `inline_into_call`.
122
+ */
117
123
 
118
124
  function within_array_or_object_literal(compressor) {
119
125
  var node, level = 0;
@@ -144,136 +150,135 @@ function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
144
150
 
145
151
  export function inline_into_symbolref(self, compressor) {
146
152
  const parent = compressor.parent();
147
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
148
- const def = self.definition();
149
- const nearest_scope = compressor.find_scope();
150
- if (compressor.top_retain && def.global && compressor.top_retain(def)) {
151
- def.fixed = false;
152
- def.single_use = false;
153
- return self;
154
- }
155
153
 
156
- let fixed = self.fixed_value();
157
- let single_use = def.single_use
158
- && !(parent instanceof AST_Call
159
- && (parent.is_callee_pure(compressor))
160
- || has_annotation(parent, _NOINLINE))
161
- && !(parent instanceof AST_Export
162
- && fixed instanceof AST_Lambda
163
- && fixed.name);
164
-
165
- if (single_use && fixed instanceof AST_Node) {
166
- single_use =
167
- !fixed.has_side_effects(compressor)
168
- && !fixed.may_throw(compressor);
169
- }
154
+ const def = self.definition();
155
+ const nearest_scope = compressor.find_scope();
156
+ if (compressor.top_retain && def.global && compressor.top_retain(def)) {
157
+ def.fixed = false;
158
+ def.single_use = false;
159
+ return self;
160
+ }
170
161
 
171
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
172
- if (retain_top_func(fixed, compressor)) {
173
- single_use = false;
174
- } else if (def.scope !== self.scope
175
- && (def.escaped == 1
176
- || has_flag(fixed, INLINED)
177
- || within_array_or_object_literal(compressor)
178
- || !compressor.option("reduce_funcs"))) {
179
- single_use = false;
180
- } else if (is_recursive_ref(compressor, def)) {
181
- single_use = false;
182
- } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
183
- single_use = fixed.is_constant_expression(self.scope);
184
- if (single_use == "f") {
185
- var scope = self.scope;
186
- do {
187
- if (scope instanceof AST_Defun || is_func_expr(scope)) {
188
- set_flag(scope, INLINED);
189
- }
190
- } while (scope = scope.parent_scope);
191
- }
162
+ let fixed = self.fixed_value();
163
+ let single_use = def.single_use
164
+ && !(parent instanceof AST_Call
165
+ && (parent.is_callee_pure(compressor))
166
+ || has_annotation(parent, _NOINLINE))
167
+ && !(parent instanceof AST_Export
168
+ && fixed instanceof AST_Lambda
169
+ && fixed.name);
170
+
171
+ if (single_use && fixed instanceof AST_Node) {
172
+ single_use =
173
+ !fixed.has_side_effects(compressor)
174
+ && !fixed.may_throw(compressor);
175
+ }
176
+
177
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
178
+ if (retain_top_func(fixed, compressor)) {
179
+ single_use = false;
180
+ } else if (def.scope !== self.scope
181
+ && (def.escaped == 1
182
+ || has_flag(fixed, INLINED)
183
+ || within_array_or_object_literal(compressor)
184
+ || !compressor.option("reduce_funcs"))) {
185
+ single_use = false;
186
+ } else if (is_recursive_ref(compressor, def)) {
187
+ single_use = false;
188
+ } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
189
+ single_use = fixed.is_constant_expression(self.scope);
190
+ if (single_use == "f") {
191
+ var scope = self.scope;
192
+ do {
193
+ if (scope instanceof AST_Defun || is_func_expr(scope)) {
194
+ set_flag(scope, INLINED);
195
+ }
196
+ } while (scope = scope.parent_scope);
192
197
  }
193
198
  }
199
+ }
194
200
 
195
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
196
- single_use =
197
- def.scope === self.scope
198
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
199
- || parent instanceof AST_Call
200
- && parent.expression === self
201
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
202
- && !(fixed.name && fixed.name.definition().recursive_refs > 0);
203
- }
201
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
202
+ single_use =
203
+ def.scope === self.scope
204
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
205
+ || parent instanceof AST_Call
206
+ && parent.expression === self
207
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
208
+ && !(fixed.name && fixed.name.definition().recursive_refs > 0);
209
+ }
204
210
 
205
- if (single_use && fixed) {
206
- if (fixed instanceof AST_DefClass) {
207
- set_flag(fixed, SQUEEZED);
208
- fixed = make_node(AST_ClassExpression, fixed, fixed);
209
- }
210
- if (fixed instanceof AST_Defun) {
211
- set_flag(fixed, SQUEEZED);
212
- fixed = make_node(AST_Function, fixed, fixed);
211
+ if (single_use && fixed) {
212
+ if (fixed instanceof AST_DefClass) {
213
+ set_flag(fixed, SQUEEZED);
214
+ fixed = make_node(AST_ClassExpression, fixed, fixed);
215
+ }
216
+ if (fixed instanceof AST_Defun) {
217
+ set_flag(fixed, SQUEEZED);
218
+ fixed = make_node(AST_Function, fixed, fixed);
219
+ }
220
+ if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
221
+ const defun_def = fixed.name.definition();
222
+ let lambda_def = fixed.variables.get(fixed.name.name);
223
+ let name = lambda_def && lambda_def.orig[0];
224
+ if (!(name instanceof AST_SymbolLambda)) {
225
+ name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
226
+ name.scope = fixed;
227
+ fixed.name = name;
228
+ lambda_def = fixed.def_function(name);
213
229
  }
214
- if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
215
- const defun_def = fixed.name.definition();
216
- let lambda_def = fixed.variables.get(fixed.name.name);
217
- let name = lambda_def && lambda_def.orig[0];
218
- if (!(name instanceof AST_SymbolLambda)) {
219
- name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
220
- name.scope = fixed;
221
- fixed.name = name;
222
- lambda_def = fixed.def_function(name);
230
+ walk(fixed, node => {
231
+ if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
232
+ node.thedef = lambda_def;
233
+ lambda_def.references.push(node);
223
234
  }
224
- walk(fixed, node => {
225
- if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
226
- node.thedef = lambda_def;
227
- lambda_def.references.push(node);
228
- }
229
- });
235
+ });
236
+ }
237
+ if (
238
+ (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
239
+ && fixed.parent_scope !== nearest_scope
240
+ ) {
241
+ fixed = fixed.clone(true, compressor.get_toplevel());
242
+
243
+ nearest_scope.add_child_scope(fixed);
244
+ }
245
+ return fixed.optimize(compressor);
246
+ }
247
+
248
+ // multiple uses
249
+ if (fixed) {
250
+ let replace;
251
+
252
+ if (fixed instanceof AST_This) {
253
+ if (!(def.orig[0] instanceof AST_SymbolFunarg)
254
+ && def.references.every((ref) =>
255
+ def.scope === ref.scope
256
+ )) {
257
+ replace = fixed;
230
258
  }
259
+ } else {
260
+ var ev = fixed.evaluate(compressor);
231
261
  if (
232
- (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
233
- && fixed.parent_scope !== nearest_scope
262
+ ev !== fixed
263
+ && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
234
264
  ) {
235
- fixed = fixed.clone(true, compressor.get_toplevel());
236
-
237
- nearest_scope.add_child_scope(fixed);
265
+ replace = make_node_from_constant(ev, fixed);
238
266
  }
239
- return fixed.optimize(compressor);
240
267
  }
241
268
 
242
- // multiple uses
243
- if (fixed) {
244
- let replace;
269
+ if (replace) {
270
+ const name_length = self.size(compressor);
271
+ const replace_size = replace.size(compressor);
245
272
 
246
- if (fixed instanceof AST_This) {
247
- if (!(def.orig[0] instanceof AST_SymbolFunarg)
248
- && def.references.every((ref) =>
249
- def.scope === ref.scope
250
- )) {
251
- replace = fixed;
252
- }
253
- } else {
254
- var ev = fixed.evaluate(compressor);
255
- if (
256
- ev !== fixed
257
- && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
258
- ) {
259
- replace = make_node_from_constant(ev, fixed);
260
- }
273
+ let overhead = 0;
274
+ if (compressor.option("unused") && !compressor.exposed(def)) {
275
+ overhead =
276
+ (name_length + 2 + replace_size) /
277
+ (def.references.length - def.assignments);
261
278
  }
262
279
 
263
- if (replace) {
264
- const name_length = self.size(compressor);
265
- const replace_size = replace.size(compressor);
266
-
267
- let overhead = 0;
268
- if (compressor.option("unused") && !compressor.exposed(def)) {
269
- overhead =
270
- (name_length + 2 + replace_size) /
271
- (def.references.length - def.assignments);
272
- }
273
-
274
- if (replace_size <= name_length + overhead) {
275
- return replace;
276
- }
280
+ if (replace_size <= name_length + overhead) {
281
+ return replace;
277
282
  }
278
283
  }
279
284
  }
@@ -79,6 +79,9 @@ const object_methods = [
79
79
 
80
80
  export const is_pure_native_method = make_nested_lookup({
81
81
  Array: [
82
+ "at",
83
+ "flat",
84
+ "includes",
82
85
  "indexOf",
83
86
  "join",
84
87
  "lastIndexOf",
@@ -99,22 +102,41 @@ export const is_pure_native_method = make_nested_lookup({
99
102
  ...object_methods,
100
103
  ],
101
104
  String: [
105
+ "at",
102
106
  "charAt",
103
107
  "charCodeAt",
108
+ "charPointAt",
104
109
  "concat",
110
+ "endsWith",
111
+ "fromCharCode",
112
+ "fromCodePoint",
113
+ "includes",
105
114
  "indexOf",
106
115
  "italics",
107
116
  "lastIndexOf",
117
+ "localeCompare",
108
118
  "match",
119
+ "matchAll",
120
+ "normalize",
121
+ "padStart",
122
+ "padEnd",
123
+ "repeat",
109
124
  "replace",
125
+ "replaceAll",
110
126
  "search",
111
127
  "slice",
112
128
  "split",
129
+ "startsWith",
113
130
  "substr",
114
131
  "substring",
132
+ "repeat",
133
+ "toLocaleLowerCase",
134
+ "toLocaleUpperCase",
115
135
  "toLowerCase",
116
136
  "toUpperCase",
117
137
  "trim",
138
+ "trimEnd",
139
+ "trimStart",
118
140
  ...object_methods,
119
141
  ],
120
142
  });