terser 5.30.4 → 5.31.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 +8 -0
- package/dist/bundle.min.js +781 -18
- package/lib/compress/common.js +12 -7
- package/lib/compress/drop-unused.js +53 -1
- package/lib/compress/index.js +8 -9
- package/package.json +1 -1
- package/tools/domprops.js +709 -1
- package/tools/props.html +11 -0
package/lib/compress/common.js
CHANGED
@@ -226,7 +226,17 @@ export function has_break_or_continue(loop, parent) {
|
|
226
226
|
// func(something) because that changes the meaning of
|
227
227
|
// the func (becomes lexical instead of global).
|
228
228
|
export function maintain_this_binding(parent, orig, val) {
|
229
|
-
if (
|
229
|
+
if (requires_sequence_to_maintain_binding(parent, orig, val)) {
|
230
|
+
const zero = make_node(AST_Number, orig, { value: 0 });
|
231
|
+
return make_sequence(orig, [ zero, val ]);
|
232
|
+
} else {
|
233
|
+
return val;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
/** Detect (1, x.noThis)(), (0, eval)(), which need sequences */
|
238
|
+
export function requires_sequence_to_maintain_binding(parent, orig, val) {
|
239
|
+
return (
|
230
240
|
parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
231
241
|
|| parent instanceof AST_Call && parent.expression === orig
|
232
242
|
&& (
|
@@ -234,12 +244,7 @@ export function maintain_this_binding(parent, orig, val) {
|
|
234
244
|
|| val instanceof AST_PropAccess
|
235
245
|
|| val instanceof AST_SymbolRef && val.name == "eval"
|
236
246
|
)
|
237
|
-
)
|
238
|
-
const zero = make_node(AST_Number, orig, { value: 0 });
|
239
|
-
return make_sequence(orig, [ zero, val ]);
|
240
|
-
} else {
|
241
|
-
return val;
|
242
|
-
}
|
247
|
+
);
|
243
248
|
}
|
244
249
|
|
245
250
|
export function is_func_expr(node) {
|
@@ -63,6 +63,7 @@ import {
|
|
63
63
|
AST_Lambda,
|
64
64
|
AST_Number,
|
65
65
|
AST_Scope,
|
66
|
+
AST_Sequence,
|
66
67
|
AST_SimpleStatement,
|
67
68
|
AST_SymbolBlockDeclaration,
|
68
69
|
AST_SymbolCatch,
|
@@ -101,6 +102,7 @@ import {
|
|
101
102
|
is_empty,
|
102
103
|
is_ref_of,
|
103
104
|
can_be_evicted_from_block,
|
105
|
+
requires_sequence_to_maintain_binding,
|
104
106
|
} from "./common.js";
|
105
107
|
|
106
108
|
const r_keep_assign = /keep_assign/;
|
@@ -231,7 +233,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
231
233
|
var in_use = in_use_ids.has(def.id);
|
232
234
|
if (node instanceof AST_Assign) {
|
233
235
|
if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
|
234
|
-
|
236
|
+
const assignee = node.right.transform(tt);
|
237
|
+
if (!in_use && !assignee.has_side_effects(compressor) && !is_used_in_expression(tt)) {
|
238
|
+
return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
239
|
+
}
|
240
|
+
return maintain_this_binding(parent, node, assignee);
|
235
241
|
}
|
236
242
|
} else if (!in_use) {
|
237
243
|
return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
@@ -438,6 +444,14 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
438
444
|
scope = save_scope;
|
439
445
|
return node;
|
440
446
|
}
|
447
|
+
},
|
448
|
+
function after(node, in_list) {
|
449
|
+
if (node instanceof AST_Sequence) {
|
450
|
+
switch (node.expressions.length) {
|
451
|
+
case 0: return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
452
|
+
case 1: return node.expressions[0];
|
453
|
+
}
|
454
|
+
}
|
441
455
|
}
|
442
456
|
);
|
443
457
|
|
@@ -484,3 +498,41 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
484
498
|
}
|
485
499
|
});
|
486
500
|
|
501
|
+
/**
|
502
|
+
* Check if a node may be used by the expression it's in
|
503
|
+
* void (0, 1, {node}, 2) -> false
|
504
|
+
* console.log(0, {node}) -> true
|
505
|
+
*/
|
506
|
+
function is_used_in_expression(tw) {
|
507
|
+
for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
|
508
|
+
if (parent instanceof AST_Sequence) {
|
509
|
+
const nth_expression = parent.expressions.indexOf(node);
|
510
|
+
if (nth_expression !== parent.expressions.length - 1) {
|
511
|
+
// Detect (0, x.noThis)() constructs
|
512
|
+
const grandparent = tw.parent(p + 2);
|
513
|
+
if (
|
514
|
+
parent.expressions.length > 2
|
515
|
+
|| parent.expressions.length === 1
|
516
|
+
|| !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
|
517
|
+
) {
|
518
|
+
return false;
|
519
|
+
}
|
520
|
+
return true;
|
521
|
+
} else {
|
522
|
+
continue;
|
523
|
+
}
|
524
|
+
}
|
525
|
+
if (parent instanceof AST_Unary) {
|
526
|
+
const op = parent.operator;
|
527
|
+
if (op === "void") {
|
528
|
+
return false;
|
529
|
+
}
|
530
|
+
if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
|
531
|
+
continue;
|
532
|
+
}
|
533
|
+
}
|
534
|
+
return true;
|
535
|
+
}
|
536
|
+
|
537
|
+
return true;
|
538
|
+
}
|
package/lib/compress/index.js
CHANGED
@@ -3758,7 +3758,7 @@ def_optimize(AST_Array, function(self, compressor) {
|
|
3758
3758
|
return self;
|
3759
3759
|
});
|
3760
3760
|
|
3761
|
-
function inline_object_prop_spread(props
|
3761
|
+
function inline_object_prop_spread(props) {
|
3762
3762
|
for (var i = 0; i < props.length; i++) {
|
3763
3763
|
var prop = props[i];
|
3764
3764
|
if (prop instanceof AST_Expansion) {
|
@@ -3770,15 +3770,14 @@ function inline_object_prop_spread(props, compressor) {
|
|
3770
3770
|
props.splice(i, 1, ...expr.properties);
|
3771
3771
|
// Step back one, as the property at i is now new.
|
3772
3772
|
i--;
|
3773
|
-
} else if (
|
3774
|
-
|
3773
|
+
} else if ((
|
3774
|
+
// `expr.is_constant()` returns `false` for `AST_RegExp`, so need both.
|
3775
|
+
expr instanceof AST_Constant
|
3776
|
+
|| expr.is_constant()
|
3777
|
+
) && !(expr instanceof AST_String)) {
|
3775
3778
|
// Unlike array-like spread, in object spread, spreading a
|
3776
3779
|
// non-iterable value silently does nothing; it is thus safe
|
3777
|
-
// to remove. AST_String is the only iterable
|
3778
|
-
props.splice(i, 1);
|
3779
|
-
i--;
|
3780
|
-
} else if (is_nullish(expr, compressor)) {
|
3781
|
-
// Likewise, null and undefined can be silently removed.
|
3780
|
+
// to remove. AST_String is the only iterable constant.
|
3782
3781
|
props.splice(i, 1);
|
3783
3782
|
i--;
|
3784
3783
|
}
|
@@ -3791,7 +3790,7 @@ def_optimize(AST_Object, function(self, compressor) {
|
|
3791
3790
|
if (optimized !== self) {
|
3792
3791
|
return optimized;
|
3793
3792
|
}
|
3794
|
-
inline_object_prop_spread(self.properties
|
3793
|
+
inline_object_prop_spread(self.properties);
|
3795
3794
|
return self;
|
3796
3795
|
});
|
3797
3796
|
|