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.
- package/CHANGELOG.md +80 -0
- package/README.md +19 -5
- package/dist/bundle.min.js +931 -459
- package/lib/ast.js +82 -9
- package/lib/compress/common.js +6 -3
- package/lib/compress/drop-side-effect-free.js +32 -20
- package/lib/compress/drop-unused.js +29 -30
- package/lib/compress/evaluate.js +20 -1
- package/lib/compress/index.js +63 -54
- package/lib/compress/inference.js +31 -3
- package/lib/compress/inline.js +119 -114
- package/lib/compress/native-objects.js +22 -0
- package/lib/compress/reduce-vars.js +111 -11
- package/lib/compress/tighten-body.js +61 -21
- package/lib/equivalent-to.js +1 -1
- package/lib/minify.js +23 -17
- package/lib/mozilla-ast.js +119 -41
- package/lib/output.js +98 -44
- package/lib/parse.js +78 -19
- package/lib/propmangle.js +11 -0
- package/lib/scope.js +5 -9
- package/lib/size.js +1 -3
- package/lib/transform.js +4 -10
- package/lib/utils/index.js +24 -39
- package/package.json +8 -9
- package/tools/domprops.js +3 -0
- package/tools/terser.d.ts +1 -0
- package/bin/terser.mjs +0 -21
package/lib/compress/index.js
CHANGED
@@ -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
|
-
|
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
|
-
|
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 =
|
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 =
|
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 =
|
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
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
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++)) !==
|
2752
|
+
while ((parent = compressor.parent(level++)) !== stop_at) {
|
2747
2753
|
if (parent instanceof AST_Try) {
|
2748
2754
|
if (parent.bfinally) return true;
|
2749
|
-
if (
|
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
|
-
|
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(
|
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 (
|
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(
|
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
|
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) :
|
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);
|
package/lib/compress/inline.js
CHANGED
@@ -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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
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
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
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
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
-
|
233
|
-
&&
|
262
|
+
ev !== fixed
|
263
|
+
&& (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
|
234
264
|
) {
|
235
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
269
|
+
if (replace) {
|
270
|
+
const name_length = self.size(compressor);
|
271
|
+
const replace_size = replace.size(compressor);
|
245
272
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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 (
|
264
|
-
|
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
|
});
|