terser 5.5.1 → 5.7.0
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 +26 -0
- package/README.md +27 -21
- package/dist/bundle.min.js +467 -160
- package/lib/ast.js +62 -2
- package/lib/cli.js +4 -14
- package/lib/compress/index.js +71 -41
- package/lib/minify.js +26 -9
- package/lib/mozilla-ast.js +75 -6
- package/lib/output.js +56 -4
- package/lib/parse.js +117 -75
- package/lib/propmangle.js +33 -2
- package/lib/scope.js +4 -1
- package/lib/size.js +33 -2
- package/lib/utils/index.js +4 -2
- package/package.json +11 -10
- package/tools/domprops.js +1 -0
- package/tools/terser.d.ts +1 -0
package/lib/ast.js
CHANGED
@@ -522,6 +522,21 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator as
|
|
522
522
|
|
523
523
|
if (this.name) push(this.name);
|
524
524
|
},
|
525
|
+
is_braceless() {
|
526
|
+
return this.body[0] instanceof AST_Return && this.body[0].value;
|
527
|
+
},
|
528
|
+
// Default args and expansion don't count, so .argnames.length doesn't cut it
|
529
|
+
length_property() {
|
530
|
+
let length = 0;
|
531
|
+
|
532
|
+
for (const arg of this.argnames) {
|
533
|
+
if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
|
534
|
+
length++;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
return length;
|
539
|
+
}
|
525
540
|
}, AST_Scope);
|
526
541
|
|
527
542
|
var AST_Accessor = DEFNODE("Accessor", null, {
|
@@ -1007,7 +1022,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property optional", {
|
|
1007
1022
|
$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
|
1008
1023
|
$propdoc: {
|
1009
1024
|
expression: "[AST_Node] the “container” expression",
|
1010
|
-
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
|
1025
|
+
property: "[AST_Node|string] the property to access. For AST_Dot & AST_DotHash this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
|
1011
1026
|
|
1012
1027
|
optional: "[boolean] whether this is an optional property access (IE ?.)"
|
1013
1028
|
}
|
@@ -1028,6 +1043,18 @@ var AST_Dot = DEFNODE("Dot", "quote", {
|
|
1028
1043
|
},
|
1029
1044
|
}, AST_PropAccess);
|
1030
1045
|
|
1046
|
+
var AST_DotHash = DEFNODE("DotHash", "", {
|
1047
|
+
$documentation: "A dotted property access to a private property",
|
1048
|
+
_walk: function(visitor) {
|
1049
|
+
return visitor._visit(this, function() {
|
1050
|
+
this.expression._walk(visitor);
|
1051
|
+
});
|
1052
|
+
},
|
1053
|
+
_children_backwards(push) {
|
1054
|
+
push(this.expression);
|
1055
|
+
},
|
1056
|
+
}, AST_PropAccess);
|
1057
|
+
|
1031
1058
|
var AST_Sub = DEFNODE("Sub", null, {
|
1032
1059
|
$documentation: "Index-style property access, i.e. `a[\"foo\"]`",
|
1033
1060
|
_walk: function(visitor) {
|
@@ -1045,7 +1072,7 @@ var AST_Sub = DEFNODE("Sub", null, {
|
|
1045
1072
|
var AST_Chain = DEFNODE("Chain", "expression", {
|
1046
1073
|
$documentation: "A chain expression like a?.b?.(c)?.[d]",
|
1047
1074
|
$propdoc: {
|
1048
|
-
expression: "[AST_Call|AST_Dot|AST_Sub] chain element."
|
1075
|
+
expression: "[AST_Call|AST_Dot|AST_DotHash|AST_Sub] chain element."
|
1049
1076
|
},
|
1050
1077
|
_walk: function (visitor) {
|
1051
1078
|
return visitor._visit(this, function() {
|
@@ -1201,6 +1228,26 @@ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
|
|
1201
1228
|
}
|
1202
1229
|
}, AST_ObjectProperty);
|
1203
1230
|
|
1231
|
+
var AST_PrivateSetter = DEFNODE("PrivateSetter", "static", {
|
1232
|
+
$propdoc: {
|
1233
|
+
static: "[boolean] whether this is a static private setter"
|
1234
|
+
},
|
1235
|
+
$documentation: "A private setter property",
|
1236
|
+
computed_key() {
|
1237
|
+
return false;
|
1238
|
+
}
|
1239
|
+
}, AST_ObjectProperty);
|
1240
|
+
|
1241
|
+
var AST_PrivateGetter = DEFNODE("PrivateGetter", "static", {
|
1242
|
+
$propdoc: {
|
1243
|
+
static: "[boolean] whether this is a static private getter"
|
1244
|
+
},
|
1245
|
+
$documentation: "A private getter property",
|
1246
|
+
computed_key() {
|
1247
|
+
return false;
|
1248
|
+
}
|
1249
|
+
}, AST_ObjectProperty);
|
1250
|
+
|
1204
1251
|
var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", {
|
1205
1252
|
$propdoc: {
|
1206
1253
|
quote: "[string|undefined] the original quote character, if any",
|
@@ -1236,6 +1283,10 @@ var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator asyn
|
|
1236
1283
|
}
|
1237
1284
|
}, AST_ObjectProperty);
|
1238
1285
|
|
1286
|
+
var AST_PrivateMethod = DEFNODE("PrivateMethod", "", {
|
1287
|
+
$documentation: "A private class method inside a class",
|
1288
|
+
}, AST_ConciseMethod);
|
1289
|
+
|
1239
1290
|
var AST_Class = DEFNODE("Class", "name extends properties", {
|
1240
1291
|
$propdoc: {
|
1241
1292
|
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
|
@@ -1285,6 +1336,10 @@ var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", {
|
|
1285
1336
|
}
|
1286
1337
|
}, AST_ObjectProperty);
|
1287
1338
|
|
1339
|
+
var AST_ClassPrivateProperty = DEFNODE("ClassProperty", "", {
|
1340
|
+
$documentation: "A class property for a private property",
|
1341
|
+
}, AST_ClassProperty);
|
1342
|
+
|
1288
1343
|
var AST_DefClass = DEFNODE("DefClass", null, {
|
1289
1344
|
$documentation: "A class definition",
|
1290
1345
|
}, AST_Class);
|
@@ -1684,6 +1739,7 @@ export {
|
|
1684
1739
|
AST_Chain,
|
1685
1740
|
AST_Class,
|
1686
1741
|
AST_ClassExpression,
|
1742
|
+
AST_ClassPrivateProperty,
|
1687
1743
|
AST_ClassProperty,
|
1688
1744
|
AST_ConciseMethod,
|
1689
1745
|
AST_Conditional,
|
@@ -1700,6 +1756,7 @@ export {
|
|
1700
1756
|
AST_Directive,
|
1701
1757
|
AST_Do,
|
1702
1758
|
AST_Dot,
|
1759
|
+
AST_DotHash,
|
1703
1760
|
AST_DWLoop,
|
1704
1761
|
AST_EmptyStatement,
|
1705
1762
|
AST_Exit,
|
@@ -1737,6 +1794,9 @@ export {
|
|
1737
1794
|
AST_ObjectProperty,
|
1738
1795
|
AST_ObjectSetter,
|
1739
1796
|
AST_PrefixedTemplateString,
|
1797
|
+
AST_PrivateGetter,
|
1798
|
+
AST_PrivateMethod,
|
1799
|
+
AST_PrivateSetter,
|
1740
1800
|
AST_PropAccess,
|
1741
1801
|
AST_RegExp,
|
1742
1802
|
AST_Return,
|
package/lib/cli.js
CHANGED
@@ -42,7 +42,7 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
42
42
|
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
43
43
|
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
44
44
|
program.option("-f, --format [options]", "Format options.", parse_js());
|
45
|
-
program.option("-b, --beautify [options]", "Alias for --format
|
45
|
+
program.option("-b, --beautify [options]", "Alias for --format.", parse_js());
|
46
46
|
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
47
47
|
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
48
48
|
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
@@ -93,19 +93,9 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
93
93
|
else
|
94
94
|
options.ecma = ecma;
|
95
95
|
}
|
96
|
-
if (program.
|
97
|
-
|
98
|
-
|
99
|
-
}
|
100
|
-
if (program.beautify) {
|
101
|
-
options.format = typeof program.beautify == "object" ? program.beautify : {};
|
102
|
-
if (!("beautify" in options.format)) {
|
103
|
-
options.format.beautify = true;
|
104
|
-
}
|
105
|
-
}
|
106
|
-
if (program.format) {
|
107
|
-
options.format = typeof program.format == "object" ? program.format : {};
|
108
|
-
}
|
96
|
+
if (program.format || program.beautify) {
|
97
|
+
const chosenOption = program.format || program.beautify;
|
98
|
+
options.format = typeof chosenOption === "object" ? chosenOption : {};
|
109
99
|
}
|
110
100
|
if (program.comments) {
|
111
101
|
if (typeof options.format != "object") options.format = {};
|
package/lib/compress/index.js
CHANGED
@@ -209,11 +209,8 @@ const TOP = 0b0000010000000000;
|
|
209
209
|
|
210
210
|
const CLEAR_BETWEEN_PASSES = SQUEEZED | OPTIMIZED | TOP;
|
211
211
|
|
212
|
-
/*@__INLINE__*/
|
213
212
|
const has_flag = (node, flag) => node.flags & flag;
|
214
|
-
/*@__INLINE__*/
|
215
213
|
const set_flag = (node, flag) => { node.flags |= flag; };
|
216
|
-
/*@__INLINE__*/
|
217
214
|
const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
218
215
|
|
219
216
|
class Compressor extends TreeWalker {
|
@@ -256,7 +253,7 @@ class Compressor extends TreeWalker {
|
|
256
253
|
properties : !false_by_default,
|
257
254
|
pure_getters : !false_by_default && "strict",
|
258
255
|
pure_funcs : null,
|
259
|
-
reduce_funcs :
|
256
|
+
reduce_funcs : !false_by_default,
|
260
257
|
reduce_vars : !false_by_default,
|
261
258
|
sequences : !false_by_default,
|
262
259
|
side_effects : !false_by_default,
|
@@ -556,7 +553,7 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
556
553
|
&& parent.expression === node
|
557
554
|
&& !(value instanceof AST_Arrow)
|
558
555
|
&& !(value instanceof AST_Class)
|
559
|
-
&& !parent.
|
556
|
+
&& !parent.is_callee_pure(compressor)
|
560
557
|
&& (!(value instanceof AST_Function)
|
561
558
|
|| !(parent instanceof AST_New) && value.contains_this())) {
|
562
559
|
return true;
|
@@ -861,9 +858,6 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
861
858
|
return true;
|
862
859
|
});
|
863
860
|
def_reduce_vars(AST_Call, function (tw) {
|
864
|
-
// TODO this block should just be { return } but
|
865
|
-
// for some reason the _walk function of AST_Call walks the callee last
|
866
|
-
|
867
861
|
this.expression.walk(tw);
|
868
862
|
|
869
863
|
if (this.optional) {
|
@@ -1416,8 +1410,11 @@ function tighten_body(statements, compressor) {
|
|
1416
1410
|
|| node instanceof AST_Debugger
|
1417
1411
|
|| node instanceof AST_Destructuring
|
1418
1412
|
|| node instanceof AST_Expansion
|
1419
|
-
|
1420
|
-
|
1413
|
+
&& node.expression instanceof AST_Symbol
|
1414
|
+
&& (
|
1415
|
+
node.expression instanceof AST_This
|
1416
|
+
|| node.expression.definition().references.length > 1
|
1417
|
+
)
|
1421
1418
|
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
1422
1419
|
|| node instanceof AST_LoopControl
|
1423
1420
|
|| node instanceof AST_Try
|
@@ -2586,7 +2583,13 @@ function is_undefined(node, compressor) {
|
|
2586
2583
|
});
|
2587
2584
|
def_may_throw_on_access(AST_Dot, function(compressor) {
|
2588
2585
|
if (!is_strict(compressor)) return false;
|
2589
|
-
|
2586
|
+
|
2587
|
+
if (this.property == "prototype") {
|
2588
|
+
return !(
|
2589
|
+
this.expression instanceof AST_Function
|
2590
|
+
|| this.expression instanceof AST_Class
|
2591
|
+
);
|
2592
|
+
}
|
2590
2593
|
return true;
|
2591
2594
|
});
|
2592
2595
|
def_may_throw_on_access(AST_Chain, function(compressor) {
|
@@ -2928,9 +2931,7 @@ var static_fns = convert_to_predicate({
|
|
2928
2931
|
if (compressor.option("unsafe")) {
|
2929
2932
|
var fn = function() {};
|
2930
2933
|
fn.node = this;
|
2931
|
-
fn.toString =
|
2932
|
-
return this.node.print_to_string();
|
2933
|
-
};
|
2934
|
+
fn.toString = () => this.print_to_string();
|
2934
2935
|
return fn;
|
2935
2936
|
}
|
2936
2937
|
return this;
|
@@ -3111,6 +3112,14 @@ var static_fns = convert_to_predicate({
|
|
3111
3112
|
"POSITIVE_INFINITY",
|
3112
3113
|
],
|
3113
3114
|
});
|
3115
|
+
const regexp_flags = new Set([
|
3116
|
+
"dotAll",
|
3117
|
+
"global",
|
3118
|
+
"ignoreCase",
|
3119
|
+
"multiline",
|
3120
|
+
"sticky",
|
3121
|
+
"unicode",
|
3122
|
+
]);
|
3114
3123
|
def_eval(AST_PropAccess, function(compressor, depth) {
|
3115
3124
|
if (this.optional) {
|
3116
3125
|
const obj = this.expression._eval(compressor, depth);
|
@@ -3143,12 +3152,19 @@ var static_fns = convert_to_predicate({
|
|
3143
3152
|
val = global_objs[exp.name];
|
3144
3153
|
} else {
|
3145
3154
|
val = exp._eval(compressor, depth + 1);
|
3155
|
+
if (val instanceof RegExp) {
|
3156
|
+
if (key == "source") {
|
3157
|
+
return regexp_source_fix(val.source);
|
3158
|
+
} else if (key == "flags" || regexp_flags.has(key)) {
|
3159
|
+
return val[key];
|
3160
|
+
}
|
3161
|
+
}
|
3146
3162
|
if (!val || val === exp || !HOP(val, key)) return this;
|
3147
3163
|
if (typeof val == "function") switch (key) {
|
3148
3164
|
case "name":
|
3149
3165
|
return val.node.name ? val.node.name.name : "";
|
3150
3166
|
case "length":
|
3151
|
-
return val.node.
|
3167
|
+
return val.node.length_property();
|
3152
3168
|
default:
|
3153
3169
|
return this;
|
3154
3170
|
}
|
@@ -3200,6 +3216,7 @@ var static_fns = convert_to_predicate({
|
|
3200
3216
|
var arg = this.args[i];
|
3201
3217
|
var value = arg._eval(compressor, depth);
|
3202
3218
|
if (arg === value) return this;
|
3219
|
+
if (arg instanceof AST_Lambda) return this;
|
3203
3220
|
args.push(value);
|
3204
3221
|
}
|
3205
3222
|
try {
|
@@ -3299,7 +3316,7 @@ var static_fns = convert_to_predicate({
|
|
3299
3316
|
});
|
3300
3317
|
|
3301
3318
|
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
|
3302
|
-
AST_Call.DEFMETHOD("
|
3319
|
+
AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
|
3303
3320
|
if (compressor.option("unsafe")) {
|
3304
3321
|
var expr = this.expression;
|
3305
3322
|
var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
|
@@ -3369,7 +3386,7 @@ const pure_prop_access_globals = new Set([
|
|
3369
3386
|
});
|
3370
3387
|
def_has_side_effects(AST_Call, function(compressor) {
|
3371
3388
|
if (
|
3372
|
-
!this.
|
3389
|
+
!this.is_callee_pure(compressor)
|
3373
3390
|
&& (!this.expression.is_call_pure(compressor)
|
3374
3391
|
|| this.expression.has_side_effects(compressor))
|
3375
3392
|
) {
|
@@ -3433,7 +3450,7 @@ const pure_prop_access_globals = new Set([
|
|
3433
3450
|
def_has_side_effects(AST_ObjectProperty, function(compressor) {
|
3434
3451
|
return (
|
3435
3452
|
this.computed_key() && this.key.has_side_effects(compressor)
|
3436
|
-
|| this.value.has_side_effects(compressor)
|
3453
|
+
|| this.value && this.value.has_side_effects(compressor)
|
3437
3454
|
);
|
3438
3455
|
});
|
3439
3456
|
def_has_side_effects(AST_ClassProperty, function(compressor) {
|
@@ -3531,7 +3548,7 @@ const pure_prop_access_globals = new Set([
|
|
3531
3548
|
def_may_throw(AST_Call, function(compressor) {
|
3532
3549
|
if (this.optional && is_nullish(this.expression)) return false;
|
3533
3550
|
if (any(this.args, compressor)) return true;
|
3534
|
-
if (this.
|
3551
|
+
if (this.is_callee_pure(compressor)) return false;
|
3535
3552
|
if (this.expression.may_throw(compressor)) return true;
|
3536
3553
|
return !(this.expression instanceof AST_Lambda)
|
3537
3554
|
|| any(this.expression.body, compressor);
|
@@ -3561,7 +3578,7 @@ const pure_prop_access_globals = new Set([
|
|
3561
3578
|
});
|
3562
3579
|
def_may_throw(AST_ObjectProperty, function(compressor) {
|
3563
3580
|
// TODO key may throw too
|
3564
|
-
return this.value.may_throw(compressor);
|
3581
|
+
return this.value ? this.value.may_throw(compressor) : false;
|
3565
3582
|
});
|
3566
3583
|
def_may_throw(AST_ClassProperty, function(compressor) {
|
3567
3584
|
return (
|
@@ -3695,7 +3712,7 @@ const pure_prop_access_globals = new Set([
|
|
3695
3712
|
return this.properties.every((l) => l.is_constant_expression());
|
3696
3713
|
});
|
3697
3714
|
def_is_constant_expression(AST_ObjectProperty, function() {
|
3698
|
-
return !(this.key instanceof AST_Node) && this.value.is_constant_expression();
|
3715
|
+
return !!(!(this.key instanceof AST_Node) && this.value && this.value.is_constant_expression());
|
3699
3716
|
});
|
3700
3717
|
})(function(node, func) {
|
3701
3718
|
node.DEFMETHOD("is_constant_expression", func);
|
@@ -4409,7 +4426,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4409
4426
|
return make_node(AST_Undefined, this);
|
4410
4427
|
}
|
4411
4428
|
|
4412
|
-
if (!this.
|
4429
|
+
if (!this.is_callee_pure(compressor)) {
|
4413
4430
|
if (this.expression.is_call_pure(compressor)) {
|
4414
4431
|
var exprs = this.args.slice();
|
4415
4432
|
exprs.unshift(this.expression.expression);
|
@@ -4522,7 +4539,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4522
4539
|
def_drop_side_effect_free(AST_ObjectProperty, function(compressor, first_in_statement) {
|
4523
4540
|
const computed_key = this instanceof AST_ObjectKeyVal && this.key instanceof AST_Node;
|
4524
4541
|
const key = computed_key && this.key.drop_side_effect_free(compressor, first_in_statement);
|
4525
|
-
const value = this.value.drop_side_effect_free(compressor, first_in_statement);
|
4542
|
+
const value = this.value && this.value.drop_side_effect_free(compressor, first_in_statement);
|
4526
4543
|
if (key && value) {
|
4527
4544
|
return make_sequence(this, [key, value]);
|
4528
4545
|
}
|
@@ -5429,7 +5446,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
5429
5446
|
|
5430
5447
|
var stat = is_func && fn.body[0];
|
5431
5448
|
var is_regular_func = is_func && !fn.is_generator && !fn.async;
|
5432
|
-
var can_inline = is_regular_func && compressor.option("inline") && !self.
|
5449
|
+
var can_inline = is_regular_func && compressor.option("inline") && !self.is_callee_pure(compressor);
|
5433
5450
|
if (can_inline && stat instanceof AST_Return) {
|
5434
5451
|
let returned = stat.value;
|
5435
5452
|
if (!returned || returned.is_constant_expression()) {
|
@@ -6455,19 +6472,26 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6455
6472
|
let fixed = self.fixed_value();
|
6456
6473
|
let single_use = def.single_use
|
6457
6474
|
&& !(parent instanceof AST_Call
|
6458
|
-
&& (parent.
|
6475
|
+
&& (parent.is_callee_pure(compressor))
|
6459
6476
|
|| has_annotation(parent, _NOINLINE))
|
6460
6477
|
&& !(parent instanceof AST_Export
|
6461
6478
|
&& fixed instanceof AST_Lambda
|
6462
6479
|
&& fixed.name);
|
6463
6480
|
|
6481
|
+
if (single_use && fixed instanceof AST_Node) {
|
6482
|
+
single_use =
|
6483
|
+
!fixed.has_side_effects(compressor)
|
6484
|
+
&& !fixed.may_throw(compressor);
|
6485
|
+
}
|
6486
|
+
|
6464
6487
|
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
6465
6488
|
if (retain_top_func(fixed, compressor)) {
|
6466
6489
|
single_use = false;
|
6467
6490
|
} else if (def.scope !== self.scope
|
6468
6491
|
&& (def.escaped == 1
|
6469
6492
|
|| has_flag(fixed, INLINED)
|
6470
|
-
|| within_array_or_object_literal(compressor)
|
6493
|
+
|| within_array_or_object_literal(compressor)
|
6494
|
+
|| !compressor.option("reduce_funcs"))) {
|
6471
6495
|
single_use = false;
|
6472
6496
|
} else if (recursive_ref(compressor, def)) {
|
6473
6497
|
single_use = false;
|
@@ -6483,6 +6507,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6483
6507
|
}
|
6484
6508
|
}
|
6485
6509
|
}
|
6510
|
+
|
6486
6511
|
if (single_use && fixed instanceof AST_Lambda) {
|
6487
6512
|
single_use =
|
6488
6513
|
def.scope === self.scope
|
@@ -6492,15 +6517,6 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6492
6517
|
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
6493
6518
|
&& !(fixed.name && fixed.name.definition().recursive_refs > 0);
|
6494
6519
|
}
|
6495
|
-
if (single_use && fixed instanceof AST_Class) {
|
6496
|
-
const extends_inert = !fixed.extends
|
6497
|
-
|| !fixed.extends.may_throw(compressor)
|
6498
|
-
&& !fixed.extends.has_side_effects(compressor);
|
6499
|
-
single_use = extends_inert
|
6500
|
-
&& !fixed.properties.some(prop =>
|
6501
|
-
prop.may_throw(compressor) || prop.has_side_effects(compressor)
|
6502
|
-
);
|
6503
|
-
}
|
6504
6520
|
|
6505
6521
|
if (single_use && fixed) {
|
6506
6522
|
if (fixed instanceof AST_DefClass) {
|
@@ -6577,6 +6593,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6577
6593
|
}
|
6578
6594
|
}
|
6579
6595
|
}
|
6596
|
+
|
6580
6597
|
return self;
|
6581
6598
|
});
|
6582
6599
|
|
@@ -7163,27 +7180,40 @@ function safe_to_flatten(value, compressor) {
|
|
7163
7180
|
|
7164
7181
|
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
7165
7182
|
if (!compressor.option("properties")) return;
|
7183
|
+
if (key === "__proto__") return;
|
7184
|
+
|
7166
7185
|
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
7167
7186
|
var expr = this.expression;
|
7168
7187
|
if (expr instanceof AST_Object) {
|
7169
7188
|
var props = expr.properties;
|
7189
|
+
|
7170
7190
|
for (var i = props.length; --i >= 0;) {
|
7171
7191
|
var prop = props[i];
|
7192
|
+
|
7172
7193
|
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
7173
|
-
|
7174
|
-
|
7175
|
-
|| arrows &&
|
7176
|
-
|
7177
|
-
|
7194
|
+
const all_props_flattenable = props.every((p) =>
|
7195
|
+
(p instanceof AST_ObjectKeyVal
|
7196
|
+
|| arrows && p instanceof AST_ConciseMethod && !p.is_generator
|
7197
|
+
)
|
7198
|
+
&& !p.computed_key()
|
7199
|
+
);
|
7200
|
+
|
7201
|
+
if (!all_props_flattenable) return;
|
7202
|
+
if (!safe_to_flatten(prop.value, compressor)) return;
|
7203
|
+
|
7178
7204
|
return make_node(AST_Sub, this, {
|
7179
7205
|
expression: make_node(AST_Array, expr, {
|
7180
7206
|
elements: props.map(function(prop) {
|
7181
7207
|
var v = prop.value;
|
7182
|
-
if (v instanceof AST_Accessor)
|
7208
|
+
if (v instanceof AST_Accessor) {
|
7209
|
+
v = make_node(AST_Function, v, v);
|
7210
|
+
}
|
7211
|
+
|
7183
7212
|
var k = prop.key;
|
7184
7213
|
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
7185
7214
|
return make_sequence(prop, [ k, v ]);
|
7186
7215
|
}
|
7216
|
+
|
7187
7217
|
return v;
|
7188
7218
|
})
|
7189
7219
|
}),
|
package/lib/minify.js
CHANGED
@@ -7,7 +7,7 @@ import {
|
|
7
7
|
map_to_object,
|
8
8
|
HOP,
|
9
9
|
} from "./utils/index.js";
|
10
|
-
import { AST_Toplevel } from "./ast.js";
|
10
|
+
import { AST_Toplevel, AST_Node } from "./ast.js";
|
11
11
|
import { parse } from "./parse.js";
|
12
12
|
import { OutputStream } from "./output.js";
|
13
13
|
import { Compressor } from "./compress/index.js";
|
@@ -77,6 +77,7 @@ async function minify(files, options) {
|
|
77
77
|
rename: undefined,
|
78
78
|
safari10: false,
|
79
79
|
sourceMap: false,
|
80
|
+
spidermonkey: false,
|
80
81
|
timings: false,
|
81
82
|
toplevel: false,
|
82
83
|
warnings: false,
|
@@ -148,20 +149,32 @@ async function minify(files, options) {
|
|
148
149
|
if (files instanceof AST_Toplevel) {
|
149
150
|
toplevel = files;
|
150
151
|
} else {
|
151
|
-
if (typeof files == "string") {
|
152
|
+
if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
|
152
153
|
files = [ files ];
|
153
154
|
}
|
154
155
|
options.parse = options.parse || {};
|
155
156
|
options.parse.toplevel = null;
|
156
|
-
|
157
|
-
|
158
|
-
options.parse.toplevel =
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
157
|
+
|
158
|
+
if (options.parse.spidermonkey) {
|
159
|
+
options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
|
160
|
+
if (!toplevel) return files[name];
|
161
|
+
toplevel.body = toplevel.body.concat(files[name].body);
|
162
|
+
return toplevel;
|
163
|
+
}, null));
|
164
|
+
} else {
|
165
|
+
delete options.parse.spidermonkey;
|
166
|
+
|
167
|
+
for (var name in files) if (HOP(files, name)) {
|
168
|
+
options.parse.filename = name;
|
169
|
+
options.parse.toplevel = parse(files[name], options.parse);
|
170
|
+
if (options.sourceMap && options.sourceMap.content == "inline") {
|
171
|
+
if (Object.keys(files).length > 1)
|
172
|
+
throw new Error("inline source map only works with singular input");
|
173
|
+
options.sourceMap.content = read_source_map(files[name]);
|
174
|
+
}
|
163
175
|
}
|
164
176
|
}
|
177
|
+
|
165
178
|
toplevel = options.parse.toplevel;
|
166
179
|
}
|
167
180
|
if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
|
@@ -203,6 +216,9 @@ async function minify(files, options) {
|
|
203
216
|
if (options.format.ast) {
|
204
217
|
result.ast = toplevel;
|
205
218
|
}
|
219
|
+
if (options.format.spidermonkey) {
|
220
|
+
result.ast = toplevel.to_mozilla_ast();
|
221
|
+
}
|
206
222
|
if (!HOP(options.format, "code") || options.format.code) {
|
207
223
|
if (options.sourceMap) {
|
208
224
|
options.format.source_map = await SourceMap({
|
@@ -220,6 +236,7 @@ async function minify(files, options) {
|
|
220
236
|
}
|
221
237
|
delete options.format.ast;
|
222
238
|
delete options.format.code;
|
239
|
+
delete options.format.spidermonkey;
|
223
240
|
var stream = OutputStream(options.format);
|
224
241
|
toplevel.print(stream);
|
225
242
|
result.code = stream.get();
|