terser 5.0.0-beta.2 → 5.2.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.
- package/CHANGELOG.md +39 -3
- package/README.md +2 -5
- package/dist/bundle.min.js +449 -129
- package/dist/bundle.min.js.map +1 -1
- package/lib/ast.js +28 -4
- package/lib/cli.js +2 -1
- package/lib/compress/index.js +224 -87
- package/lib/equivalent-to.js +3 -0
- package/lib/minify.js +5 -1
- package/lib/mozilla-ast.js +40 -3
- package/lib/output.js +18 -3
- package/lib/parse.js +118 -25
- package/lib/propmangle.js +5 -0
- package/lib/size.js +16 -5
- package/package.json +6 -2
- package/tools/terser.d.ts +2 -3
package/lib/compress/index.js
CHANGED
@@ -78,6 +78,7 @@ import {
|
|
78
78
|
AST_Call,
|
79
79
|
AST_Case,
|
80
80
|
AST_Catch,
|
81
|
+
AST_Chain,
|
81
82
|
AST_Class,
|
82
83
|
AST_ClassExpression,
|
83
84
|
AST_ClassProperty,
|
@@ -216,7 +217,7 @@ const set_flag = (node, flag) => { node.flags |= flag; };
|
|
216
217
|
const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
217
218
|
|
218
219
|
class Compressor extends TreeWalker {
|
219
|
-
constructor(options, false_by_default) {
|
220
|
+
constructor(options, { false_by_default = false, mangle_options = false }) {
|
220
221
|
super();
|
221
222
|
if (options.defaults !== undefined && !options.defaults) false_by_default = true;
|
222
223
|
this.options = defaults(options, {
|
@@ -274,7 +275,7 @@ class Compressor extends TreeWalker {
|
|
274
275
|
unsafe_regexp : false,
|
275
276
|
unsafe_undefined: false,
|
276
277
|
unused : !false_by_default,
|
277
|
-
warnings : false
|
278
|
+
warnings : false // legacy
|
278
279
|
}, true);
|
279
280
|
var global_defs = this.options["global_defs"];
|
280
281
|
if (typeof global_defs == "object") for (var key in global_defs) {
|
@@ -324,6 +325,7 @@ class Compressor extends TreeWalker {
|
|
324
325
|
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
325
326
|
this.evaluated_regexps = new Map();
|
326
327
|
this._toplevel = undefined;
|
328
|
+
this.mangle_options = mangle_options;
|
327
329
|
}
|
328
330
|
|
329
331
|
option(key) {
|
@@ -792,13 +794,53 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
792
794
|
pop(tw);
|
793
795
|
return true;
|
794
796
|
});
|
797
|
+
|
798
|
+
def_reduce_vars(AST_Chain, function(tw, descend) {
|
799
|
+
// Chains' conditions apply left-to-right, cumulatively.
|
800
|
+
// If we walk normally we don't go in that order because we would pop before pushing again
|
801
|
+
// Solution: AST_PropAccess and AST_Call push when they are optional, and never pop.
|
802
|
+
// Then we pop everything when they are done being walked.
|
803
|
+
const safe_ids = tw.safe_ids;
|
804
|
+
|
805
|
+
descend();
|
806
|
+
|
807
|
+
// Unroll back to start
|
808
|
+
tw.safe_ids = safe_ids;
|
809
|
+
return true;
|
810
|
+
});
|
811
|
+
def_reduce_vars(AST_Call, function (tw) {
|
812
|
+
// TODO this block should just be { return } but
|
813
|
+
// for some reason the _walk function of AST_Call walks the callee last
|
814
|
+
|
815
|
+
this.expression.walk(tw);
|
816
|
+
|
817
|
+
if (this.optional) {
|
818
|
+
// Never pop -- it's popped at AST_Chain above
|
819
|
+
push(tw);
|
820
|
+
}
|
821
|
+
|
822
|
+
for (const arg of this.args) arg.walk(tw);
|
823
|
+
|
824
|
+
return true;
|
825
|
+
});
|
826
|
+
def_reduce_vars(AST_PropAccess, function (tw) {
|
827
|
+
if (!this.optional) return;
|
828
|
+
|
829
|
+
this.expression.walk(tw);
|
830
|
+
|
831
|
+
// Never pop -- it's popped at AST_Chain above
|
832
|
+
push(tw);
|
833
|
+
|
834
|
+
if (this.property instanceof AST_Node) this.property.walk(tw);
|
835
|
+
|
836
|
+
return true;
|
837
|
+
});
|
795
838
|
def_reduce_vars(AST_Default, function(tw, descend) {
|
796
839
|
push(tw);
|
797
840
|
descend();
|
798
841
|
pop(tw);
|
799
842
|
return true;
|
800
843
|
});
|
801
|
-
|
802
844
|
function mark_lambda(tw, descend, compressor) {
|
803
845
|
clear_flag(this, INLINED);
|
804
846
|
push(tw);
|
@@ -1628,8 +1670,7 @@ function tighten_body(statements, compressor) {
|
|
1628
1670
|
extract_candidates(expr.condition);
|
1629
1671
|
extract_candidates(expr.consequent);
|
1630
1672
|
extract_candidates(expr.alternative);
|
1631
|
-
} else if (expr instanceof AST_Definitions
|
1632
|
-
&& (compressor.option("unused") || !(expr instanceof AST_Const))) {
|
1673
|
+
} else if (expr instanceof AST_Definitions) {
|
1633
1674
|
var len = expr.definitions.length;
|
1634
1675
|
// limit number of trailing variable definitions for consideration
|
1635
1676
|
var i = len - 200;
|
@@ -1797,7 +1838,9 @@ function tighten_body(statements, compressor) {
|
|
1797
1838
|
if (node === expr || node.body === expr) {
|
1798
1839
|
found = true;
|
1799
1840
|
if (node instanceof AST_VarDef) {
|
1800
|
-
node.value =
|
1841
|
+
node.value = node.name instanceof AST_SymbolConst
|
1842
|
+
? make_node(AST_Undefined, node.value) // `const` always needs value.
|
1843
|
+
: null;
|
1801
1844
|
return node;
|
1802
1845
|
}
|
1803
1846
|
return in_list ? MAP.skip : null;
|
@@ -2113,7 +2156,7 @@ function tighten_body(statements, compressor) {
|
|
2113
2156
|
statements.length = n;
|
2114
2157
|
CHANGED = n != len;
|
2115
2158
|
if (has_quit) has_quit.forEach(function(stat) {
|
2116
|
-
|
2159
|
+
trim_unreachable_code(compressor, stat, statements);
|
2117
2160
|
});
|
2118
2161
|
}
|
2119
2162
|
|
@@ -2371,7 +2414,7 @@ function tighten_body(statements, compressor) {
|
|
2371
2414
|
}
|
2372
2415
|
}
|
2373
2416
|
|
2374
|
-
function
|
2417
|
+
function trim_unreachable_code(compressor, stat, target) {
|
2375
2418
|
walk(stat, node => {
|
2376
2419
|
if (node instanceof AST_Var) {
|
2377
2420
|
node.remove_initializers();
|
@@ -2392,6 +2435,10 @@ function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
|
2392
2435
|
}));
|
2393
2436
|
return true;
|
2394
2437
|
}
|
2438
|
+
if (node instanceof AST_Export || node instanceof AST_Import) {
|
2439
|
+
target.push(node);
|
2440
|
+
return true;
|
2441
|
+
}
|
2395
2442
|
if (node instanceof AST_Scope) {
|
2396
2443
|
return true;
|
2397
2444
|
}
|
@@ -2443,6 +2490,10 @@ function is_undefined(node, compressor) {
|
|
2443
2490
|
if (this.properties[i]._dot_throw(compressor)) return true;
|
2444
2491
|
return false;
|
2445
2492
|
});
|
2493
|
+
// Do not be as strict with classes as we are with objects.
|
2494
|
+
// Hopefully the community is not going to abuse static getters and setters.
|
2495
|
+
// https://github.com/terser/terser/issues/724#issuecomment-643655656
|
2496
|
+
def_may_throw_on_access(AST_Class, return_false);
|
2446
2497
|
def_may_throw_on_access(AST_ObjectProperty, return_false);
|
2447
2498
|
def_may_throw_on_access(AST_ObjectGetter, return_true);
|
2448
2499
|
def_may_throw_on_access(AST_Expansion, function(compressor) {
|
@@ -2471,11 +2522,15 @@ function is_undefined(node, compressor) {
|
|
2471
2522
|
if (this.expression instanceof AST_Function && this.property == "prototype") return false;
|
2472
2523
|
return true;
|
2473
2524
|
});
|
2525
|
+
def_may_throw_on_access(AST_Chain, function(compressor) {
|
2526
|
+
return this.expression._dot_throw(compressor);
|
2527
|
+
});
|
2474
2528
|
def_may_throw_on_access(AST_Sequence, function(compressor) {
|
2475
2529
|
return this.tail_node()._dot_throw(compressor);
|
2476
2530
|
});
|
2477
2531
|
def_may_throw_on_access(AST_SymbolRef, function(compressor) {
|
2478
|
-
if (
|
2532
|
+
if (this.name === "arguments") return false;
|
2533
|
+
if (has_flag(this, UNDEFINED)) return true;
|
2479
2534
|
if (!is_strict(compressor)) return false;
|
2480
2535
|
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
|
2481
2536
|
if (this.is_immutable()) return false;
|
@@ -2620,6 +2675,9 @@ function is_lhs(node, parent) {
|
|
2620
2675
|
}));
|
2621
2676
|
});
|
2622
2677
|
def_find_defs(AST_Node, noop);
|
2678
|
+
def_find_defs(AST_Chain, function(compressor, suffix) {
|
2679
|
+
return this.expression._find_defs(compressor, suffix);
|
2680
|
+
});
|
2623
2681
|
def_find_defs(AST_Dot, function(compressor, suffix) {
|
2624
2682
|
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
2625
2683
|
});
|
@@ -2877,13 +2935,33 @@ var static_fns = convert_to_predicate({
|
|
2877
2935
|
return this;
|
2878
2936
|
});
|
2879
2937
|
var non_converting_binary = makePredicate("&& || ?? === !==");
|
2938
|
+
const identity_comparison = makePredicate("== != === !==");
|
2939
|
+
const has_identity = value =>
|
2940
|
+
typeof value === "object"
|
2941
|
+
|| typeof value === "function"
|
2942
|
+
|| typeof value === "symbol";
|
2943
|
+
|
2880
2944
|
def_eval(AST_Binary, function(compressor, depth) {
|
2881
2945
|
if (!non_converting_binary.has(this.operator)) depth++;
|
2946
|
+
|
2882
2947
|
var left = this.left._eval(compressor, depth);
|
2883
2948
|
if (left === this.left) return this;
|
2884
2949
|
var right = this.right._eval(compressor, depth);
|
2885
2950
|
if (right === this.right) return this;
|
2886
2951
|
var result;
|
2952
|
+
|
2953
|
+
if (
|
2954
|
+
left != null
|
2955
|
+
&& right != null
|
2956
|
+
&& identity_comparison.has(this.operator)
|
2957
|
+
&& has_identity(left)
|
2958
|
+
&& has_identity(right)
|
2959
|
+
&& typeof left === typeof right
|
2960
|
+
) {
|
2961
|
+
// Do not compare by reference
|
2962
|
+
return this;
|
2963
|
+
}
|
2964
|
+
|
2887
2965
|
switch (this.operator) {
|
2888
2966
|
case "&&" : result = left && right; break;
|
2889
2967
|
case "||" : result = left || right; break;
|
@@ -2924,34 +3002,29 @@ var static_fns = convert_to_predicate({
|
|
2924
3002
|
var value = node._eval(compressor, depth);
|
2925
3003
|
return value === node ? this : value;
|
2926
3004
|
});
|
3005
|
+
|
3006
|
+
// Set of AST_SymbolRef which are currently being evaluated.
|
3007
|
+
// Avoids infinite recursion of ._eval()
|
3008
|
+
const reentrant_ref_eval = new Set();
|
2927
3009
|
def_eval(AST_SymbolRef, function(compressor, depth) {
|
3010
|
+
if (reentrant_ref_eval.has(this)) return this;
|
3011
|
+
|
2928
3012
|
var fixed = this.fixed_value();
|
2929
3013
|
if (!fixed) return this;
|
2930
|
-
|
2931
|
-
|
2932
|
-
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
if (value === fixed) return this;
|
2938
|
-
fixed._eval = function() {
|
2939
|
-
return value;
|
2940
|
-
};
|
2941
|
-
}
|
3014
|
+
|
3015
|
+
reentrant_ref_eval.add(this);
|
3016
|
+
const value = fixed._eval(compressor, depth);
|
3017
|
+
reentrant_ref_eval.delete(this);
|
3018
|
+
|
3019
|
+
if (value === fixed) return this;
|
3020
|
+
|
2942
3021
|
if (value && typeof value == "object") {
|
2943
3022
|
var escaped = this.definition().escaped;
|
2944
3023
|
if (escaped && depth > escaped) return this;
|
2945
3024
|
}
|
2946
3025
|
return value;
|
2947
3026
|
});
|
2948
|
-
var global_objs = {
|
2949
|
-
Array: Array,
|
2950
|
-
Math: Math,
|
2951
|
-
Number: Number,
|
2952
|
-
Object: Object,
|
2953
|
-
String: String,
|
2954
|
-
};
|
3027
|
+
var global_objs = { Array, Math, Number, Object, String };
|
2955
3028
|
var static_values = convert_to_predicate({
|
2956
3029
|
Math: [
|
2957
3030
|
"E",
|
@@ -2972,6 +3045,10 @@ var static_fns = convert_to_predicate({
|
|
2972
3045
|
],
|
2973
3046
|
});
|
2974
3047
|
def_eval(AST_PropAccess, function(compressor, depth) {
|
3048
|
+
if (this.optional) {
|
3049
|
+
const obj = this.expression._eval(compressor, depth);
|
3050
|
+
if (obj == null) return undefined;
|
3051
|
+
}
|
2975
3052
|
if (compressor.option("unsafe")) {
|
2976
3053
|
var key = this.property;
|
2977
3054
|
if (key instanceof AST_Node) {
|
@@ -3013,8 +3090,15 @@ var static_fns = convert_to_predicate({
|
|
3013
3090
|
}
|
3014
3091
|
return this;
|
3015
3092
|
});
|
3093
|
+
def_eval(AST_Chain, function(compressor, depth) {
|
3094
|
+
return this.expression._eval(compressor, depth);
|
3095
|
+
});
|
3016
3096
|
def_eval(AST_Call, function(compressor, depth) {
|
3017
3097
|
var exp = this.expression;
|
3098
|
+
if (this.optional) {
|
3099
|
+
const callee = this.expression._eval(compressor, depth);
|
3100
|
+
if (callee == null) return undefined;
|
3101
|
+
}
|
3018
3102
|
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
3019
3103
|
var key = exp.property;
|
3020
3104
|
if (key instanceof AST_Node) {
|
@@ -3216,9 +3300,11 @@ const pure_prop_access_globals = new Set([
|
|
3216
3300
|
return any(this.body, compressor);
|
3217
3301
|
});
|
3218
3302
|
def_has_side_effects(AST_Call, function(compressor) {
|
3219
|
-
if (
|
3303
|
+
if (
|
3304
|
+
!this.is_expr_pure(compressor)
|
3220
3305
|
&& (!this.expression.is_call_pure(compressor)
|
3221
|
-
|| this.expression.has_side_effects(compressor))
|
3306
|
+
|| this.expression.has_side_effects(compressor))
|
3307
|
+
) {
|
3222
3308
|
return true;
|
3223
3309
|
}
|
3224
3310
|
return any(this.args, compressor);
|
@@ -3301,14 +3387,21 @@ const pure_prop_access_globals = new Set([
|
|
3301
3387
|
return any(this.elements, compressor);
|
3302
3388
|
});
|
3303
3389
|
def_has_side_effects(AST_Dot, function(compressor) {
|
3304
|
-
return this.expression.may_throw_on_access(compressor)
|
3390
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
3305
3391
|
|| this.expression.has_side_effects(compressor);
|
3306
3392
|
});
|
3307
3393
|
def_has_side_effects(AST_Sub, function(compressor) {
|
3308
|
-
|
3394
|
+
if (this.optional && is_nullish(this.expression)) {
|
3395
|
+
return false;
|
3396
|
+
}
|
3397
|
+
|
3398
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
3309
3399
|
|| this.expression.has_side_effects(compressor)
|
3310
3400
|
|| this.property.has_side_effects(compressor);
|
3311
3401
|
});
|
3402
|
+
def_has_side_effects(AST_Chain, function (compressor) {
|
3403
|
+
return this.expression.has_side_effects(compressor);
|
3404
|
+
});
|
3312
3405
|
def_has_side_effects(AST_Sequence, function(compressor) {
|
3313
3406
|
return any(this.expressions, compressor);
|
3314
3407
|
});
|
@@ -3368,6 +3461,7 @@ const pure_prop_access_globals = new Set([
|
|
3368
3461
|
return any(this.body, compressor);
|
3369
3462
|
});
|
3370
3463
|
def_may_throw(AST_Call, function(compressor) {
|
3464
|
+
if (this.optional && is_nullish(this.expression)) return false;
|
3371
3465
|
if (any(this.args, compressor)) return true;
|
3372
3466
|
if (this.is_expr_pure(compressor)) return false;
|
3373
3467
|
if (this.expression.may_throw(compressor)) return true;
|
@@ -3386,10 +3480,6 @@ const pure_prop_access_globals = new Set([
|
|
3386
3480
|
def_may_throw(AST_Definitions, function(compressor) {
|
3387
3481
|
return any(this.definitions, compressor);
|
3388
3482
|
});
|
3389
|
-
def_may_throw(AST_Dot, function(compressor) {
|
3390
|
-
return this.expression.may_throw_on_access(compressor)
|
3391
|
-
|| this.expression.may_throw(compressor);
|
3392
|
-
});
|
3393
3483
|
def_may_throw(AST_If, function(compressor) {
|
3394
3484
|
return this.condition.may_throw(compressor)
|
3395
3485
|
|| this.body && this.body.may_throw(compressor)
|
@@ -3429,11 +3519,20 @@ const pure_prop_access_globals = new Set([
|
|
3429
3519
|
def_may_throw(AST_SimpleStatement, function(compressor) {
|
3430
3520
|
return this.body.may_throw(compressor);
|
3431
3521
|
});
|
3522
|
+
def_may_throw(AST_Dot, function(compressor) {
|
3523
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
3524
|
+
|| this.expression.may_throw(compressor);
|
3525
|
+
});
|
3432
3526
|
def_may_throw(AST_Sub, function(compressor) {
|
3433
|
-
|
3527
|
+
if (this.optional && is_nullish(this.expression)) return false;
|
3528
|
+
|
3529
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
3434
3530
|
|| this.expression.may_throw(compressor)
|
3435
3531
|
|| this.property.may_throw(compressor);
|
3436
3532
|
});
|
3533
|
+
def_may_throw(AST_Chain, function(compressor) {
|
3534
|
+
return this.expression.may_throw(compressor);
|
3535
|
+
});
|
3437
3536
|
def_may_throw(AST_Switch, function(compressor) {
|
3438
3537
|
return this.expression.may_throw(compressor)
|
3439
3538
|
|| any(this.body, compressor);
|
@@ -3591,9 +3690,9 @@ def_optimize(AST_Block, function(self, compressor) {
|
|
3591
3690
|
|
3592
3691
|
function can_be_extracted_from_if_block(node) {
|
3593
3692
|
return !(
|
3594
|
-
node instanceof AST_Const
|
3595
|
-
node instanceof AST_Let
|
3596
|
-
node instanceof AST_Class
|
3693
|
+
node instanceof AST_Const
|
3694
|
+
|| node instanceof AST_Let
|
3695
|
+
|| node instanceof AST_Class
|
3597
3696
|
);
|
3598
3697
|
}
|
3599
3698
|
|
@@ -4227,6 +4326,10 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4227
4326
|
def_drop_side_effect_free(AST_Constant, return_null);
|
4228
4327
|
def_drop_side_effect_free(AST_This, return_null);
|
4229
4328
|
def_drop_side_effect_free(AST_Call, function(compressor, first_in_statement) {
|
4329
|
+
if (this.optional && is_nullish(this.expression)) {
|
4330
|
+
return make_node(AST_Undefined, this);
|
4331
|
+
}
|
4332
|
+
|
4230
4333
|
if (!this.is_expr_pure(compressor)) {
|
4231
4334
|
if (this.expression.is_call_pure(compressor)) {
|
4232
4335
|
var exprs = this.args.slice();
|
@@ -4367,17 +4470,28 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4367
4470
|
return values && make_sequence(this, values);
|
4368
4471
|
});
|
4369
4472
|
def_drop_side_effect_free(AST_Dot, function(compressor, first_in_statement) {
|
4473
|
+
if (this.optional) {
|
4474
|
+
return is_nullish(this.expression) ? make_node(AST_Undefined, this) : this;
|
4475
|
+
}
|
4370
4476
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
4477
|
+
|
4371
4478
|
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
4372
4479
|
});
|
4373
4480
|
def_drop_side_effect_free(AST_Sub, function(compressor, first_in_statement) {
|
4481
|
+
if (this.optional) {
|
4482
|
+
return is_nullish(this.expression) ? make_node(AST_Undefined, this): this;
|
4483
|
+
}
|
4374
4484
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
4485
|
+
|
4375
4486
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
4376
4487
|
if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement);
|
4377
4488
|
var property = this.property.drop_side_effect_free(compressor);
|
4378
4489
|
if (!property) return expression;
|
4379
4490
|
return make_sequence(this, [ expression, property ]);
|
4380
4491
|
});
|
4492
|
+
def_drop_side_effect_free(AST_Chain, function (compressor, first_in_statement) {
|
4493
|
+
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
4494
|
+
});
|
4381
4495
|
def_drop_side_effect_free(AST_Sequence, function(compressor) {
|
4382
4496
|
var last = this.tail_node();
|
4383
4497
|
var expr = last.drop_side_effect_free(compressor);
|
@@ -4477,7 +4591,7 @@ function if_break_in_loop(self, compressor) {
|
|
4477
4591
|
body: self.condition
|
4478
4592
|
}));
|
4479
4593
|
}
|
4480
|
-
|
4594
|
+
trim_unreachable_code(compressor, self.body, body);
|
4481
4595
|
return make_node(AST_BlockStatement, self, {
|
4482
4596
|
body: body
|
4483
4597
|
});
|
@@ -4548,7 +4662,7 @@ def_optimize(AST_For, function(self, compressor) {
|
|
4548
4662
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
4549
4663
|
if (!cond) {
|
4550
4664
|
var body = [];
|
4551
|
-
|
4665
|
+
trim_unreachable_code(compressor, self.body, body);
|
4552
4666
|
if (self.init instanceof AST_Statement) {
|
4553
4667
|
body.push(self.init);
|
4554
4668
|
} else if (self.init) {
|
@@ -4584,7 +4698,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
4584
4698
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
4585
4699
|
if (!cond) {
|
4586
4700
|
var body = [];
|
4587
|
-
|
4701
|
+
trim_unreachable_code(compressor, self.body, body);
|
4588
4702
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
4589
4703
|
body: self.condition
|
4590
4704
|
}));
|
@@ -4597,7 +4711,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
4597
4711
|
}));
|
4598
4712
|
body.push(self.body);
|
4599
4713
|
if (self.alternative) {
|
4600
|
-
|
4714
|
+
trim_unreachable_code(compressor, self.alternative, body);
|
4601
4715
|
}
|
4602
4716
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
4603
4717
|
}
|
@@ -4809,7 +4923,7 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
4809
4923
|
if (prev && !aborts(prev)) {
|
4810
4924
|
prev.body = prev.body.concat(branch.body);
|
4811
4925
|
} else {
|
4812
|
-
|
4926
|
+
trim_unreachable_code(compressor, branch, decl);
|
4813
4927
|
}
|
4814
4928
|
}
|
4815
4929
|
});
|
@@ -4820,7 +4934,7 @@ def_optimize(AST_Try, function(self, compressor) {
|
|
4820
4934
|
if (compressor.option("dead_code") && self.body.every(is_empty)) {
|
4821
4935
|
var body = [];
|
4822
4936
|
if (self.bcatch) {
|
4823
|
-
|
4937
|
+
trim_unreachable_code(compressor, self.bcatch, body);
|
4824
4938
|
}
|
4825
4939
|
if (self.bfinally) body.push(...self.bfinally.body);
|
4826
4940
|
return make_node(AST_BlockStatement, self, {
|
@@ -4918,6 +5032,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
4918
5032
|
}
|
4919
5033
|
}
|
4920
5034
|
|
5035
|
+
if (self.optional && is_nullish(fn)) {
|
5036
|
+
return make_node(AST_Undefined, self);
|
5037
|
+
}
|
5038
|
+
|
4921
5039
|
var is_func = fn instanceof AST_Lambda;
|
4922
5040
|
|
4923
5041
|
if (is_func && fn.pinned()) return self;
|
@@ -5129,6 +5247,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
5129
5247
|
return make_node(AST_Call, self, {
|
5130
5248
|
expression: make_node(AST_Dot, exp, {
|
5131
5249
|
expression: exp.expression,
|
5250
|
+
optional: false,
|
5132
5251
|
property: "call"
|
5133
5252
|
}),
|
5134
5253
|
args: args
|
@@ -5175,7 +5294,9 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
5175
5294
|
var ast = parse(code);
|
5176
5295
|
var mangle = { ie8: compressor.option("ie8") };
|
5177
5296
|
ast.figure_out_scope(mangle);
|
5178
|
-
var comp = new Compressor(compressor.options
|
5297
|
+
var comp = new Compressor(compressor.options, {
|
5298
|
+
mangle_options: compressor.mangle_options
|
5299
|
+
});
|
5179
5300
|
ast = ast.transform(comp);
|
5180
5301
|
ast.figure_out_scope(mangle);
|
5181
5302
|
base54.reset();
|
@@ -6358,8 +6479,8 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6358
6479
|
}
|
6359
6480
|
|
6360
6481
|
if (replace) {
|
6361
|
-
const name_length =
|
6362
|
-
const replace_size = replace.size();
|
6482
|
+
const name_length = self.size(compressor);
|
6483
|
+
const replace_size = replace.size(compressor);
|
6363
6484
|
|
6364
6485
|
let overhead = 0;
|
6365
6486
|
if (compressor.option("unused") && !compressor.exposed(def)) {
|
@@ -6564,6 +6685,10 @@ function is_nullish(node) {
|
|
6564
6685
|
&& (fixed = node.definition().fixed) instanceof AST_Node
|
6565
6686
|
&& is_nullish(fixed)
|
6566
6687
|
)
|
6688
|
+
// Recurse into those optional chains!
|
6689
|
+
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression)
|
6690
|
+
|| node instanceof AST_Call && node.optional && is_nullish(node.expression)
|
6691
|
+
|| node instanceof AST_Chain && is_nullish(node.expression)
|
6567
6692
|
);
|
6568
6693
|
}
|
6569
6694
|
|
@@ -6946,6 +7071,41 @@ function safe_to_flatten(value, compressor) {
|
|
6946
7071
|
return compressor.parent() instanceof AST_New;
|
6947
7072
|
}
|
6948
7073
|
|
7074
|
+
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
7075
|
+
if (!compressor.option("properties")) return;
|
7076
|
+
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
7077
|
+
var expr = this.expression;
|
7078
|
+
if (expr instanceof AST_Object) {
|
7079
|
+
var props = expr.properties;
|
7080
|
+
for (var i = props.length; --i >= 0;) {
|
7081
|
+
var prop = props[i];
|
7082
|
+
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
7083
|
+
if (!props.every((prop) => {
|
7084
|
+
return prop instanceof AST_ObjectKeyVal
|
7085
|
+
|| arrows && prop instanceof AST_ConciseMethod && !prop.is_generator;
|
7086
|
+
})) break;
|
7087
|
+
if (!safe_to_flatten(prop.value, compressor)) break;
|
7088
|
+
return make_node(AST_Sub, this, {
|
7089
|
+
expression: make_node(AST_Array, expr, {
|
7090
|
+
elements: props.map(function(prop) {
|
7091
|
+
var v = prop.value;
|
7092
|
+
if (v instanceof AST_Accessor) v = make_node(AST_Function, v, v);
|
7093
|
+
var k = prop.key;
|
7094
|
+
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
7095
|
+
return make_sequence(prop, [ k, v ]);
|
7096
|
+
}
|
7097
|
+
return v;
|
7098
|
+
})
|
7099
|
+
}),
|
7100
|
+
property: make_node(AST_Number, this, {
|
7101
|
+
value: i
|
7102
|
+
})
|
7103
|
+
});
|
7104
|
+
}
|
7105
|
+
}
|
7106
|
+
}
|
7107
|
+
});
|
7108
|
+
|
6949
7109
|
def_optimize(AST_Sub, function(self, compressor) {
|
6950
7110
|
var expr = self.expression;
|
6951
7111
|
var prop = self.property;
|
@@ -6968,6 +7128,7 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
6968
7128
|
&& property.length <= prop.size() + 1) {
|
6969
7129
|
return make_node(AST_Dot, self, {
|
6970
7130
|
expression: expr,
|
7131
|
+
optional: self.optional,
|
6971
7132
|
property: property,
|
6972
7133
|
quote: prop.quote,
|
6973
7134
|
}).optimize(compressor);
|
@@ -7070,6 +7231,14 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
7070
7231
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
7071
7232
|
return best_of(compressor, ev, self);
|
7072
7233
|
}
|
7234
|
+
if (self.optional && is_nullish(self.expression)) {
|
7235
|
+
return make_node(AST_Undefined, self);
|
7236
|
+
}
|
7237
|
+
return self;
|
7238
|
+
});
|
7239
|
+
|
7240
|
+
def_optimize(AST_Chain, function (self, compressor) {
|
7241
|
+
self.expression = self.expression.optimize(compressor);
|
7073
7242
|
return self;
|
7074
7243
|
});
|
7075
7244
|
|
@@ -7086,41 +7255,6 @@ AST_Lambda.DEFMETHOD("contains_this", function() {
|
|
7086
7255
|
});
|
7087
7256
|
});
|
7088
7257
|
|
7089
|
-
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
7090
|
-
if (!compressor.option("properties")) return;
|
7091
|
-
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
7092
|
-
var expr = this.expression;
|
7093
|
-
if (expr instanceof AST_Object) {
|
7094
|
-
var props = expr.properties;
|
7095
|
-
for (var i = props.length; --i >= 0;) {
|
7096
|
-
var prop = props[i];
|
7097
|
-
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
7098
|
-
if (!props.every((prop) => {
|
7099
|
-
return prop instanceof AST_ObjectKeyVal
|
7100
|
-
|| arrows && prop instanceof AST_ConciseMethod && !prop.is_generator;
|
7101
|
-
})) break;
|
7102
|
-
if (!safe_to_flatten(prop.value, compressor)) break;
|
7103
|
-
return make_node(AST_Sub, this, {
|
7104
|
-
expression: make_node(AST_Array, expr, {
|
7105
|
-
elements: props.map(function(prop) {
|
7106
|
-
var v = prop.value;
|
7107
|
-
if (v instanceof AST_Accessor) v = make_node(AST_Function, v, v);
|
7108
|
-
var k = prop.key;
|
7109
|
-
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
7110
|
-
return make_sequence(prop, [ k, v ]);
|
7111
|
-
}
|
7112
|
-
return v;
|
7113
|
-
})
|
7114
|
-
}),
|
7115
|
-
property: make_node(AST_Number, this, {
|
7116
|
-
value: i
|
7117
|
-
})
|
7118
|
-
});
|
7119
|
-
}
|
7120
|
-
}
|
7121
|
-
}
|
7122
|
-
});
|
7123
|
-
|
7124
7258
|
def_optimize(AST_Dot, function(self, compressor) {
|
7125
7259
|
const parent = compressor.parent();
|
7126
7260
|
if (is_lhs(self, parent)) return self;
|
@@ -7171,6 +7305,9 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
7171
7305
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
7172
7306
|
return best_of(compressor, ev, self);
|
7173
7307
|
}
|
7308
|
+
if (self.optional && is_nullish(self.expression)) {
|
7309
|
+
return make_node(AST_Undefined, self);
|
7310
|
+
}
|
7174
7311
|
return self;
|
7175
7312
|
});
|
7176
7313
|
|
@@ -7254,10 +7391,10 @@ def_optimize(AST_Function, function(self, compressor) {
|
|
7254
7391
|
&& !self.is_generator
|
7255
7392
|
&& !self.uses_arguments
|
7256
7393
|
&& !self.pinned()) {
|
7257
|
-
const
|
7394
|
+
const uses_this = walk(self, node => {
|
7258
7395
|
if (node instanceof AST_This) return walk_abort;
|
7259
7396
|
});
|
7260
|
-
if (!
|
7397
|
+
if (!uses_this) return make_node(AST_Arrow, self, self).optimize(compressor);
|
7261
7398
|
}
|
7262
7399
|
return self;
|
7263
7400
|
});
|
@@ -7349,7 +7486,7 @@ function lift_key(self, compressor) {
|
|
7349
7486
|
if (!compressor.option("computed_props")) return self;
|
7350
7487
|
// save a comparison in the typical case
|
7351
7488
|
if (!(self.key instanceof AST_Constant)) return self;
|
7352
|
-
//
|
7489
|
+
// allow certain acceptable props as not all AST_Constants are true constants
|
7353
7490
|
if (self.key instanceof AST_String || self.key instanceof AST_Number) {
|
7354
7491
|
if (self.key.value === "__proto__") return self;
|
7355
7492
|
if (self.key.value == "constructor"
|
package/lib/equivalent-to.js
CHANGED
@@ -26,6 +26,7 @@ import {
|
|
26
26
|
AST_ForOf,
|
27
27
|
AST_If,
|
28
28
|
AST_Import,
|
29
|
+
AST_ImportMeta,
|
29
30
|
AST_Jump,
|
30
31
|
AST_LabeledStatement,
|
31
32
|
AST_Lambda,
|
@@ -209,6 +210,8 @@ AST_Import.prototype.shallow_cmp = mkshallow({
|
|
209
210
|
imported_names: "exist"
|
210
211
|
});
|
211
212
|
|
213
|
+
AST_ImportMeta.prototype.shallow_cmp = pass_through;
|
214
|
+
|
212
215
|
AST_Export.prototype.shallow_cmp = mkshallow({
|
213
216
|
exported_definition: "exist",
|
214
217
|
exported_value: "exist",
|
package/lib/minify.js
CHANGED
@@ -181,7 +181,11 @@ async function minify(files, options) {
|
|
181
181
|
toplevel.expand_names(options.mangle);
|
182
182
|
}
|
183
183
|
if (timings) timings.compress = Date.now();
|
184
|
-
if (options.compress)
|
184
|
+
if (options.compress) {
|
185
|
+
toplevel = new Compressor(options.compress, {
|
186
|
+
mangle_options: options.mangle
|
187
|
+
}).compress(toplevel);
|
188
|
+
}
|
185
189
|
if (timings) timings.scope = Date.now();
|
186
190
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
187
191
|
if (timings) timings.mangle = Date.now();
|