terser 5.28.0 → 5.28.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 +4 -0
- package/dist/bundle.min.js +9 -337
- package/lib/compress/common.js +0 -3
- package/lib/compress/evaluate.js +4 -21
- package/lib/compress/index.js +3 -263
- package/lib/compress/inference.js +0 -50
- package/lib/size.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/bundle.min.js
CHANGED
@@ -12778,8 +12778,8 @@ AST_Class.prototype._size = function () {
|
|
12778
12778
|
};
|
12779
12779
|
|
12780
12780
|
AST_ClassStaticBlock.prototype._size = function () {
|
12781
|
-
// "
|
12782
|
-
return
|
12781
|
+
// "class{}" + semicolons
|
12782
|
+
return 7 + list_overhead(this.body);
|
12783
12783
|
};
|
12784
12784
|
|
12785
12785
|
AST_ClassProperty.prototype._size = function () {
|
@@ -13008,8 +13008,6 @@ function make_node_from_constant(val, orig) {
|
|
13008
13008
|
operator: "-",
|
13009
13009
|
expression: make_node(AST_Infinity, orig)
|
13010
13010
|
}) : make_node(AST_Infinity, orig);
|
13011
|
-
case "bigint":
|
13012
|
-
return make_node(AST_BigInt, orig, { value: val.toString() });
|
13013
13011
|
case "boolean":
|
13014
13012
|
return make_node(val ? AST_True : AST_False, orig);
|
13015
13013
|
case "undefined":
|
@@ -13488,7 +13486,6 @@ const is_pure_native_value = make_nested_lookup({
|
|
13488
13486
|
const is_undeclared_ref = (node) =>
|
13489
13487
|
node instanceof AST_SymbolRef && node.definition().undeclared;
|
13490
13488
|
|
13491
|
-
const bitwise_binop = makePredicate("<<< >> << & | ^ ~");
|
13492
13489
|
const lazy_op = makePredicate("&& || ??");
|
13493
13490
|
const unary_side_effects = makePredicate("delete ++ --");
|
13494
13491
|
|
@@ -13549,24 +13546,6 @@ const unary_side_effects = makePredicate("delete ++ --");
|
|
13549
13546
|
node.DEFMETHOD("is_number", func);
|
13550
13547
|
});
|
13551
13548
|
|
13552
|
-
// methods to determine if an expression is a 32 bit integer (IE results from bitwise ops, or is an integer constant fitting in that size
|
13553
|
-
(function(def_is_32_bit_integer) {
|
13554
|
-
def_is_32_bit_integer(AST_Node, return_false);
|
13555
|
-
def_is_32_bit_integer(AST_Number, function() {
|
13556
|
-
return this.value === (this.value | 0);
|
13557
|
-
});
|
13558
|
-
def_is_32_bit_integer(AST_UnaryPrefix, function() {
|
13559
|
-
return this.operator == "~" ? this.expression.is_number()
|
13560
|
-
: this.operator === "+" ? this.expression.is_32_bit_integer()
|
13561
|
-
: false;
|
13562
|
-
});
|
13563
|
-
def_is_32_bit_integer(AST_Binary, function() {
|
13564
|
-
return bitwise_binop.has(this.operator);
|
13565
|
-
});
|
13566
|
-
}(function (node, func) {
|
13567
|
-
node.DEFMETHOD("is_32_bit_integer", func);
|
13568
|
-
}));
|
13569
|
-
|
13570
13549
|
// methods to determine if an expression has a string result type
|
13571
13550
|
(function(def_is_string) {
|
13572
13551
|
def_is_string(AST_Node, return_false);
|
@@ -14181,37 +14160,6 @@ function is_lhs(node, parent) {
|
|
14181
14160
|
});
|
14182
14161
|
});
|
14183
14162
|
|
14184
|
-
(function (def_bitwise_negate) {
|
14185
|
-
function basic_negation(exp) {
|
14186
|
-
return make_node(AST_UnaryPrefix, exp, {
|
14187
|
-
operator: "~",
|
14188
|
-
expression: exp
|
14189
|
-
});
|
14190
|
-
}
|
14191
|
-
|
14192
|
-
def_bitwise_negate(AST_Node, function() {
|
14193
|
-
return basic_negation(this);
|
14194
|
-
});
|
14195
|
-
|
14196
|
-
def_bitwise_negate(AST_Number, function() {
|
14197
|
-
const neg = ~this.value;
|
14198
|
-
if (neg.toString().length > this.value.toString().length) {
|
14199
|
-
return basic_negation(this);
|
14200
|
-
}
|
14201
|
-
return make_node(AST_Number, this, { value: neg });
|
14202
|
-
});
|
14203
|
-
|
14204
|
-
def_bitwise_negate(AST_UnaryPrefix, function(in_32_bit_context) {
|
14205
|
-
if (this.operator == "~" && (in_32_bit_context || this.expression.is_32_bit_integer())) {
|
14206
|
-
return this.expression;
|
14207
|
-
} else {
|
14208
|
-
return basic_negation(this);
|
14209
|
-
}
|
14210
|
-
});
|
14211
|
-
})(function (node, func) {
|
14212
|
-
node.DEFMETHOD("bitwise_negate", func);
|
14213
|
-
});
|
14214
|
-
|
14215
14163
|
// Is the callee of this function pure?
|
14216
14164
|
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");
|
14217
14165
|
AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
|
@@ -14437,14 +14385,7 @@ def_eval(AST_Constant, function () {
|
|
14437
14385
|
return this.getValue();
|
14438
14386
|
});
|
14439
14387
|
|
14440
|
-
|
14441
|
-
def_eval(AST_BigInt, function () {
|
14442
|
-
if (supports_bigint) {
|
14443
|
-
return BigInt(this.value);
|
14444
|
-
} else {
|
14445
|
-
return this;
|
14446
|
-
}
|
14447
|
-
});
|
14388
|
+
def_eval(AST_BigInt, return_this);
|
14448
14389
|
|
14449
14390
|
def_eval(AST_RegExp, function (compressor) {
|
14450
14391
|
let evaluated = compressor.evaluated_regexps.get(this.value);
|
@@ -14568,6 +14509,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
14568
14509
|
var right = this.right._eval(compressor, depth);
|
14569
14510
|
if (right === this.right)
|
14570
14511
|
return this;
|
14512
|
+
var result;
|
14571
14513
|
|
14572
14514
|
if (left != null
|
14573
14515
|
&& right != null
|
@@ -14579,17 +14521,6 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
14579
14521
|
return this;
|
14580
14522
|
}
|
14581
14523
|
|
14582
|
-
// Do not mix BigInt and Number; Don't use `>>>` on BigInt or `/ 0n`
|
14583
|
-
if (
|
14584
|
-
(typeof left === "bigint") !== (typeof right === "bigint")
|
14585
|
-
|| typeof left === "bigint"
|
14586
|
-
&& (this.operator === ">>>"
|
14587
|
-
|| this.operator === "/" && Number(right) === 0)
|
14588
|
-
) {
|
14589
|
-
return this;
|
14590
|
-
}
|
14591
|
-
|
14592
|
-
var result;
|
14593
14524
|
switch (this.operator) {
|
14594
14525
|
case "&&": result = left && right; break;
|
14595
14526
|
case "||": result = left || right; break;
|
@@ -14599,7 +14530,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
14599
14530
|
case "^": result = left ^ right; break;
|
14600
14531
|
case "+": result = left + right; break;
|
14601
14532
|
case "*": result = left * right; break;
|
14602
|
-
case "**": result = left
|
14533
|
+
case "**": result = Math.pow(left, right); break;
|
14603
14534
|
case "/": result = left / right; break;
|
14604
14535
|
case "%": result = left % right; break;
|
14605
14536
|
case "-": result = left - right; break;
|
@@ -14617,7 +14548,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
14617
14548
|
default:
|
14618
14549
|
return this;
|
14619
14550
|
}
|
14620
|
-
if (
|
14551
|
+
if (isNaN(result) && compressor.find_parent(AST_With)) {
|
14621
14552
|
// leave original expression as is
|
14622
14553
|
return this;
|
14623
14554
|
}
|
@@ -18615,33 +18546,6 @@ class Compressor extends TreeWalker {
|
|
18615
18546
|
}
|
18616
18547
|
}
|
18617
18548
|
|
18618
|
-
in_32_bit_context() {
|
18619
|
-
if (!this.option("evaluate")) return false;
|
18620
|
-
var self = this.self();
|
18621
|
-
for (var i = 0, p; p = this.parent(i); i++) {
|
18622
|
-
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
18623
|
-
return true;
|
18624
|
-
}
|
18625
|
-
if (p instanceof AST_UnaryPrefix) {
|
18626
|
-
return p.operator === "~";
|
18627
|
-
}
|
18628
|
-
if (
|
18629
|
-
p instanceof AST_Binary
|
18630
|
-
&& (
|
18631
|
-
p.operator == "&&"
|
18632
|
-
|| p.operator == "||"
|
18633
|
-
|| p.operator == "??"
|
18634
|
-
)
|
18635
|
-
|| p instanceof AST_Conditional && p.condition !== self
|
18636
|
-
|| p.tail_node() === self
|
18637
|
-
) {
|
18638
|
-
self = p;
|
18639
|
-
} else {
|
18640
|
-
return false;
|
18641
|
-
}
|
18642
|
-
}
|
18643
|
-
}
|
18644
|
-
|
18645
18549
|
get_toplevel() {
|
18646
18550
|
return this._toplevel;
|
18647
18551
|
}
|
@@ -20340,40 +20244,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
20340
20244
|
right: e.right
|
20341
20245
|
});
|
20342
20246
|
}
|
20343
|
-
|
20344
|
-
if (
|
20345
|
-
|
20346
|
-
// ~~{32 bit integer} => {32 bit integer}
|
20347
|
-
if (
|
20348
|
-
self.operator === "~"
|
20349
|
-
&& self.expression instanceof AST_UnaryPrefix
|
20350
|
-
&& self.expression.operator === "~"
|
20351
|
-
&& (compressor.in_32_bit_context() || self.expression.expression.is_32_bit_integer())
|
20352
|
-
) {
|
20353
|
-
return self.expression.expression;
|
20354
|
-
}
|
20355
|
-
|
20356
|
-
// ~(x ^ y) => x ^ ~y
|
20357
|
-
if (
|
20358
|
-
self.operator === "~"
|
20359
|
-
&& e instanceof AST_Binary
|
20360
|
-
&& e.operator === "^"
|
20361
|
-
) {
|
20362
|
-
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
20363
|
-
// ~(~x ^ y) => x ^ y
|
20364
|
-
e.left = e.left.bitwise_negate(true);
|
20365
|
-
} else {
|
20366
|
-
e.right = e.right.bitwise_negate(true);
|
20367
|
-
}
|
20368
|
-
return e;
|
20369
|
-
}
|
20370
|
-
}
|
20371
|
-
|
20372
|
-
if (
|
20373
|
-
self.operator != "-"
|
20374
|
-
// avoid infinite recursion of numerals
|
20375
|
-
|| !(e instanceof AST_Number || e instanceof AST_Infinity || e instanceof AST_BigInt)
|
20376
|
-
) {
|
20247
|
+
// avoids infinite recursion of numerals
|
20248
|
+
if (self.operator != "-"
|
20249
|
+
|| !(e instanceof AST_Number || e instanceof AST_Infinity || e instanceof AST_BigInt)) {
|
20377
20250
|
var ev = self.evaluate(compressor);
|
20378
20251
|
if (ev !== self) {
|
20379
20252
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
@@ -20464,7 +20337,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20464
20337
|
self.left.equivalent_to(self.right)) {
|
20465
20338
|
self.operator = self.operator.substr(0, 2);
|
20466
20339
|
}
|
20467
|
-
|
20468
20340
|
// XXX: intentionally falling down to the next case
|
20469
20341
|
case "==":
|
20470
20342
|
case "!=":
|
@@ -20506,55 +20378,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20506
20378
|
&& self.left.definition() === self.right.definition()
|
20507
20379
|
&& is_object(self.left.fixed_value())) {
|
20508
20380
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
20509
|
-
} else if (self.left.is_32_bit_integer() && self.right.is_32_bit_integer()) {
|
20510
|
-
const not = node => make_node(AST_UnaryPrefix, node, {
|
20511
|
-
operator: "!",
|
20512
|
-
expression: node
|
20513
|
-
});
|
20514
|
-
const booleanify = (node, truthy) => {
|
20515
|
-
if (truthy) {
|
20516
|
-
return compressor.in_boolean_context()
|
20517
|
-
? node
|
20518
|
-
: not(not(node));
|
20519
|
-
} else {
|
20520
|
-
return not(node);
|
20521
|
-
}
|
20522
|
-
};
|
20523
|
-
|
20524
|
-
// The only falsy 32-bit integer is 0
|
20525
|
-
if (self.left instanceof AST_Number && self.left.value === 0) {
|
20526
|
-
return booleanify(self.right, self.operator[0] === "!");
|
20527
|
-
}
|
20528
|
-
if (self.right instanceof AST_Number && self.right.value === 0) {
|
20529
|
-
return booleanify(self.left, self.operator[0] === "!");
|
20530
|
-
}
|
20531
|
-
|
20532
|
-
// Mask all-bits check
|
20533
|
-
// (x & 0xFF) != 0xFF => !(~x & 0xFF)
|
20534
|
-
let and_op, x, mask;
|
20535
|
-
if (
|
20536
|
-
(and_op =
|
20537
|
-
self.left instanceof AST_Binary ? self.left
|
20538
|
-
: self.right instanceof AST_Binary ? self.right : null)
|
20539
|
-
&& (mask = and_op === self.left ? self.right : self.left)
|
20540
|
-
&& and_op.operator === "&"
|
20541
|
-
&& mask instanceof AST_Number
|
20542
|
-
&& mask.is_32_bit_integer()
|
20543
|
-
&& (x =
|
20544
|
-
and_op.left.equivalent_to(mask) ? and_op.right
|
20545
|
-
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
20546
|
-
) {
|
20547
|
-
let optimized = booleanify(make_node(AST_Binary, self, {
|
20548
|
-
operator: "&",
|
20549
|
-
left: mask,
|
20550
|
-
right: make_node(AST_UnaryPrefix, self, {
|
20551
|
-
operator: "~",
|
20552
|
-
expression: x
|
20553
|
-
})
|
20554
|
-
}), self.operator[0] === "=");
|
20555
|
-
|
20556
|
-
return best_of(compressor, optimized, self);
|
20557
|
-
}
|
20558
20381
|
}
|
20559
20382
|
break;
|
20560
20383
|
case "&&":
|
@@ -20928,157 +20751,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20928
20751
|
}
|
20929
20752
|
}
|
20930
20753
|
}
|
20931
|
-
|
20932
|
-
// bitwise ops
|
20933
|
-
if (bitwise_binop.has(self.operator)) {
|
20934
|
-
// Use De Morgan's laws
|
20935
|
-
// z & (X | y)
|
20936
|
-
// => z & X (given y & z === 0)
|
20937
|
-
// => z & X | {y & z} (given y & z !== 0)
|
20938
|
-
let y, z, x_node, y_node, z_node = self.left;
|
20939
|
-
if (
|
20940
|
-
self.operator === "&"
|
20941
|
-
&& self.right instanceof AST_Binary
|
20942
|
-
&& self.right.operator === "|"
|
20943
|
-
&& typeof (z = self.left.evaluate(compressor)) === "number"
|
20944
|
-
) {
|
20945
|
-
if (typeof (y = self.right.right.evaluate(compressor)) === "number") {
|
20946
|
-
// z & (X | y)
|
20947
|
-
x_node = self.right.left;
|
20948
|
-
y_node = self.right.right;
|
20949
|
-
} else if (typeof (y = self.right.left.evaluate(compressor)) === "number") {
|
20950
|
-
// z & (y | X)
|
20951
|
-
x_node = self.right.right;
|
20952
|
-
y_node = self.right.left;
|
20953
|
-
}
|
20954
|
-
|
20955
|
-
if ((y & z) === 0) {
|
20956
|
-
self = make_node(AST_Binary, self, {
|
20957
|
-
operator: self.operator,
|
20958
|
-
left: z_node,
|
20959
|
-
right: x_node
|
20960
|
-
});
|
20961
|
-
} else {
|
20962
|
-
const reordered_ops = make_node(AST_Binary, self, {
|
20963
|
-
operator: "|",
|
20964
|
-
left: make_node(AST_Binary, self, {
|
20965
|
-
operator: "&",
|
20966
|
-
left: x_node,
|
20967
|
-
right: z_node
|
20968
|
-
}),
|
20969
|
-
right: make_node_from_constant(y & z, y_node),
|
20970
|
-
});
|
20971
|
-
|
20972
|
-
self = best_of(compressor, self, reordered_ops);
|
20973
|
-
}
|
20974
|
-
}
|
20975
|
-
|
20976
|
-
// x ^ x => 0
|
20977
|
-
// x | x => 0 | x
|
20978
|
-
// x & x => 0 | x
|
20979
|
-
const same_operands = self.left.equivalent_to(self.right) && !self.left.has_side_effects(compressor);
|
20980
|
-
if (same_operands) {
|
20981
|
-
if (self.operator === "^") {
|
20982
|
-
return make_node(AST_Number, self, { value: 0 });
|
20983
|
-
}
|
20984
|
-
if (self.operator === "|" || self.operator === "&") {
|
20985
|
-
self.left = make_node(AST_Number, self, { value: 0 });
|
20986
|
-
self.operator = "|";
|
20987
|
-
}
|
20988
|
-
}
|
20989
|
-
|
20990
|
-
|
20991
|
-
// Shifts that do nothing
|
20992
|
-
// {anything} >> 0 => {anything} | 0
|
20993
|
-
// {anything} << 0 => {anything} | 0
|
20994
|
-
if (
|
20995
|
-
(self.operator === "<<" || self.operator === ">>")
|
20996
|
-
&& self.right instanceof AST_Number && self.right.value === 0
|
20997
|
-
) {
|
20998
|
-
self.operator = "|";
|
20999
|
-
}
|
21000
|
-
|
21001
|
-
// Find useless to-bitwise conversions
|
21002
|
-
// {32 bit integer} | 0 => {32 bit integer}
|
21003
|
-
// {32 bit integer} ^ 0 => {32 bit integer}
|
21004
|
-
const zero_side = self.right instanceof AST_Number && self.right.value === 0 ? self.right
|
21005
|
-
: self.left instanceof AST_Number && self.left.value === 0 ? self.left
|
21006
|
-
: null;
|
21007
|
-
const non_zero_side = zero_side && (zero_side === self.right ? self.left : self.right);
|
21008
|
-
if (
|
21009
|
-
zero_side
|
21010
|
-
&& (self.operator === "|" || self.operator === "^")
|
21011
|
-
&& (non_zero_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21012
|
-
) {
|
21013
|
-
return non_zero_side;
|
21014
|
-
}
|
21015
|
-
|
21016
|
-
// {anything} & 0 => 0
|
21017
|
-
if (
|
21018
|
-
zero_side
|
21019
|
-
&& self.operator === "&"
|
21020
|
-
&& !non_zero_side.has_side_effects(compressor)
|
21021
|
-
) {
|
21022
|
-
return zero_side;
|
21023
|
-
}
|
21024
|
-
|
21025
|
-
const is_full_mask = (node) =>
|
21026
|
-
node instanceof AST_Number && node.value === -1
|
21027
|
-
||
|
21028
|
-
node instanceof AST_UnaryPrefix && (
|
21029
|
-
node.operator === "-"
|
21030
|
-
&& node.expression instanceof AST_Number
|
21031
|
-
&& node.expression.value === 1
|
21032
|
-
|| node.operator === "~"
|
21033
|
-
&& node.expression instanceof AST_Number
|
21034
|
-
&& node.expression.value === 0);
|
21035
|
-
|
21036
|
-
const full_mask = is_full_mask(self.right) ? self.right
|
21037
|
-
: is_full_mask(self.left) ? self.left
|
21038
|
-
: null;
|
21039
|
-
const non_full_mask_side = full_mask && (full_mask === self.right ? self.left : self.right);
|
21040
|
-
|
21041
|
-
switch (self.operator) {
|
21042
|
-
case "|":
|
21043
|
-
// {anything} | -1 => -1
|
21044
|
-
if (full_mask && !non_full_mask_side.has_side_effects(compressor)) {
|
21045
|
-
return full_mask;
|
21046
|
-
}
|
21047
|
-
|
21048
|
-
break;
|
21049
|
-
case "&":
|
21050
|
-
// {32 bit integer} & -1 => {32 bit integer}
|
21051
|
-
if (
|
21052
|
-
full_mask
|
21053
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21054
|
-
) {
|
21055
|
-
return non_full_mask_side;
|
21056
|
-
}
|
21057
|
-
|
21058
|
-
break;
|
21059
|
-
case "^":
|
21060
|
-
// {anything} ^ -1 => ~{anything}
|
21061
|
-
if (full_mask) {
|
21062
|
-
return non_full_mask_side.bitwise_negate(compressor.in_32_bit_context());
|
21063
|
-
}
|
21064
|
-
|
21065
|
-
// ~x ^ ~y => x ^ y
|
21066
|
-
if (
|
21067
|
-
self.left instanceof AST_UnaryPrefix
|
21068
|
-
&& self.left.operator === "~"
|
21069
|
-
&& self.right instanceof AST_UnaryPrefix
|
21070
|
-
&& self.right.operator === "~"
|
21071
|
-
) {
|
21072
|
-
self = make_node(AST_Binary, self, {
|
21073
|
-
operator: "^",
|
21074
|
-
left: self.left.expression,
|
21075
|
-
right: self.right.expression
|
21076
|
-
});
|
21077
|
-
}
|
21078
|
-
|
21079
|
-
break;
|
21080
|
-
}
|
21081
|
-
}
|
21082
20754
|
}
|
21083
20755
|
// x && (y && z) ==> x && y && z
|
21084
20756
|
// x || (y || z) ==> x || y || z
|
package/lib/compress/common.js
CHANGED
@@ -44,7 +44,6 @@
|
|
44
44
|
import {
|
45
45
|
AST_Array,
|
46
46
|
AST_Arrow,
|
47
|
-
AST_BigInt,
|
48
47
|
AST_BlockStatement,
|
49
48
|
AST_Call,
|
50
49
|
AST_Chain,
|
@@ -125,8 +124,6 @@ export function make_node_from_constant(val, orig) {
|
|
125
124
|
operator: "-",
|
126
125
|
expression: make_node(AST_Infinity, orig)
|
127
126
|
}) : make_node(AST_Infinity, orig);
|
128
|
-
case "bigint":
|
129
|
-
return make_node(AST_BigInt, orig, { value: val.toString() });
|
130
127
|
case "boolean":
|
131
128
|
return make_node(val ? AST_True : AST_False, orig);
|
132
129
|
case "undefined":
|
package/lib/compress/evaluate.js
CHANGED
@@ -133,14 +133,7 @@ def_eval(AST_Constant, function () {
|
|
133
133
|
return this.getValue();
|
134
134
|
});
|
135
135
|
|
136
|
-
|
137
|
-
def_eval(AST_BigInt, function () {
|
138
|
-
if (supports_bigint) {
|
139
|
-
return BigInt(this.value);
|
140
|
-
} else {
|
141
|
-
return this;
|
142
|
-
}
|
143
|
-
});
|
136
|
+
def_eval(AST_BigInt, return_this);
|
144
137
|
|
145
138
|
def_eval(AST_RegExp, function (compressor) {
|
146
139
|
let evaluated = compressor.evaluated_regexps.get(this.value);
|
@@ -264,6 +257,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
264
257
|
var right = this.right._eval(compressor, depth);
|
265
258
|
if (right === this.right)
|
266
259
|
return this;
|
260
|
+
var result;
|
267
261
|
|
268
262
|
if (left != null
|
269
263
|
&& right != null
|
@@ -275,17 +269,6 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
275
269
|
return this;
|
276
270
|
}
|
277
271
|
|
278
|
-
// Do not mix BigInt and Number; Don't use `>>>` on BigInt or `/ 0n`
|
279
|
-
if (
|
280
|
-
(typeof left === "bigint") !== (typeof right === "bigint")
|
281
|
-
|| typeof left === "bigint"
|
282
|
-
&& (this.operator === ">>>"
|
283
|
-
|| this.operator === "/" && Number(right) === 0)
|
284
|
-
) {
|
285
|
-
return this;
|
286
|
-
}
|
287
|
-
|
288
|
-
var result;
|
289
272
|
switch (this.operator) {
|
290
273
|
case "&&": result = left && right; break;
|
291
274
|
case "||": result = left || right; break;
|
@@ -295,7 +278,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
295
278
|
case "^": result = left ^ right; break;
|
296
279
|
case "+": result = left + right; break;
|
297
280
|
case "*": result = left * right; break;
|
298
|
-
case "**": result = left
|
281
|
+
case "**": result = Math.pow(left, right); break;
|
299
282
|
case "/": result = left / right; break;
|
300
283
|
case "%": result = left % right; break;
|
301
284
|
case "-": result = left - right; break;
|
@@ -313,7 +296,7 @@ def_eval(AST_Binary, function (compressor, depth) {
|
|
313
296
|
default:
|
314
297
|
return this;
|
315
298
|
}
|
316
|
-
if (
|
299
|
+
if (isNaN(result) && compressor.find_parent(AST_With)) {
|
317
300
|
// leave original expression as is
|
318
301
|
return this;
|
319
302
|
}
|
package/lib/compress/index.js
CHANGED
@@ -170,7 +170,6 @@ import "./drop-unused.js";
|
|
170
170
|
import "./reduce-vars.js";
|
171
171
|
import {
|
172
172
|
is_undeclared_ref,
|
173
|
-
bitwise_binop,
|
174
173
|
lazy_op,
|
175
174
|
is_nullish,
|
176
175
|
is_undefined,
|
@@ -374,33 +373,6 @@ class Compressor extends TreeWalker {
|
|
374
373
|
}
|
375
374
|
}
|
376
375
|
|
377
|
-
in_32_bit_context() {
|
378
|
-
if (!this.option("evaluate")) return false;
|
379
|
-
var self = this.self();
|
380
|
-
for (var i = 0, p; p = this.parent(i); i++) {
|
381
|
-
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
382
|
-
return true;
|
383
|
-
}
|
384
|
-
if (p instanceof AST_UnaryPrefix) {
|
385
|
-
return p.operator === "~";
|
386
|
-
}
|
387
|
-
if (
|
388
|
-
p instanceof AST_Binary
|
389
|
-
&& (
|
390
|
-
p.operator == "&&"
|
391
|
-
|| p.operator == "||"
|
392
|
-
|| p.operator == "??"
|
393
|
-
)
|
394
|
-
|| p instanceof AST_Conditional && p.condition !== self
|
395
|
-
|| p.tail_node() === self
|
396
|
-
) {
|
397
|
-
self = p;
|
398
|
-
} else {
|
399
|
-
return false;
|
400
|
-
}
|
401
|
-
}
|
402
|
-
}
|
403
|
-
|
404
376
|
get_toplevel() {
|
405
377
|
return this._toplevel;
|
406
378
|
}
|
@@ -2099,40 +2071,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
2099
2071
|
right: e.right
|
2100
2072
|
});
|
2101
2073
|
}
|
2102
|
-
|
2103
|
-
if (
|
2104
|
-
|
2105
|
-
// ~~{32 bit integer} => {32 bit integer}
|
2106
|
-
if (
|
2107
|
-
self.operator === "~"
|
2108
|
-
&& self.expression instanceof AST_UnaryPrefix
|
2109
|
-
&& self.expression.operator === "~"
|
2110
|
-
&& (compressor.in_32_bit_context() || self.expression.expression.is_32_bit_integer())
|
2111
|
-
) {
|
2112
|
-
return self.expression.expression;
|
2113
|
-
}
|
2114
|
-
|
2115
|
-
// ~(x ^ y) => x ^ ~y
|
2116
|
-
if (
|
2117
|
-
self.operator === "~"
|
2118
|
-
&& e instanceof AST_Binary
|
2119
|
-
&& e.operator === "^"
|
2120
|
-
) {
|
2121
|
-
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
2122
|
-
// ~(~x ^ y) => x ^ y
|
2123
|
-
e.left = e.left.bitwise_negate(true);
|
2124
|
-
} else {
|
2125
|
-
e.right = e.right.bitwise_negate(true);
|
2126
|
-
}
|
2127
|
-
return e;
|
2128
|
-
}
|
2129
|
-
}
|
2130
|
-
|
2131
|
-
if (
|
2132
|
-
self.operator != "-"
|
2133
|
-
// avoid infinite recursion of numerals
|
2134
|
-
|| !(e instanceof AST_Number || e instanceof AST_Infinity || e instanceof AST_BigInt)
|
2135
|
-
) {
|
2074
|
+
// avoids infinite recursion of numerals
|
2075
|
+
if (self.operator != "-"
|
2076
|
+
|| !(e instanceof AST_Number || e instanceof AST_Infinity || e instanceof AST_BigInt)) {
|
2136
2077
|
var ev = self.evaluate(compressor);
|
2137
2078
|
if (ev !== self) {
|
2138
2079
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
@@ -2223,7 +2164,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2223
2164
|
self.left.equivalent_to(self.right)) {
|
2224
2165
|
self.operator = self.operator.substr(0, 2);
|
2225
2166
|
}
|
2226
|
-
|
2227
2167
|
// XXX: intentionally falling down to the next case
|
2228
2168
|
case "==":
|
2229
2169
|
case "!=":
|
@@ -2265,55 +2205,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2265
2205
|
&& self.left.definition() === self.right.definition()
|
2266
2206
|
&& is_object(self.left.fixed_value())) {
|
2267
2207
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
2268
|
-
} else if (self.left.is_32_bit_integer() && self.right.is_32_bit_integer()) {
|
2269
|
-
const not = node => make_node(AST_UnaryPrefix, node, {
|
2270
|
-
operator: "!",
|
2271
|
-
expression: node
|
2272
|
-
});
|
2273
|
-
const booleanify = (node, truthy) => {
|
2274
|
-
if (truthy) {
|
2275
|
-
return compressor.in_boolean_context()
|
2276
|
-
? node
|
2277
|
-
: not(not(node));
|
2278
|
-
} else {
|
2279
|
-
return not(node);
|
2280
|
-
}
|
2281
|
-
};
|
2282
|
-
|
2283
|
-
// The only falsy 32-bit integer is 0
|
2284
|
-
if (self.left instanceof AST_Number && self.left.value === 0) {
|
2285
|
-
return booleanify(self.right, self.operator[0] === "!");
|
2286
|
-
}
|
2287
|
-
if (self.right instanceof AST_Number && self.right.value === 0) {
|
2288
|
-
return booleanify(self.left, self.operator[0] === "!");
|
2289
|
-
}
|
2290
|
-
|
2291
|
-
// Mask all-bits check
|
2292
|
-
// (x & 0xFF) != 0xFF => !(~x & 0xFF)
|
2293
|
-
let and_op, x, mask;
|
2294
|
-
if (
|
2295
|
-
(and_op =
|
2296
|
-
self.left instanceof AST_Binary ? self.left
|
2297
|
-
: self.right instanceof AST_Binary ? self.right : null)
|
2298
|
-
&& (mask = and_op === self.left ? self.right : self.left)
|
2299
|
-
&& and_op.operator === "&"
|
2300
|
-
&& mask instanceof AST_Number
|
2301
|
-
&& mask.is_32_bit_integer()
|
2302
|
-
&& (x =
|
2303
|
-
and_op.left.equivalent_to(mask) ? and_op.right
|
2304
|
-
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
2305
|
-
) {
|
2306
|
-
let optimized = booleanify(make_node(AST_Binary, self, {
|
2307
|
-
operator: "&",
|
2308
|
-
left: mask,
|
2309
|
-
right: make_node(AST_UnaryPrefix, self, {
|
2310
|
-
operator: "~",
|
2311
|
-
expression: x
|
2312
|
-
})
|
2313
|
-
}), self.operator[0] === "=");
|
2314
|
-
|
2315
|
-
return best_of(compressor, optimized, self);
|
2316
|
-
}
|
2317
2208
|
}
|
2318
2209
|
break;
|
2319
2210
|
case "&&":
|
@@ -2687,157 +2578,6 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2687
2578
|
}
|
2688
2579
|
}
|
2689
2580
|
}
|
2690
|
-
|
2691
|
-
// bitwise ops
|
2692
|
-
if (bitwise_binop.has(self.operator)) {
|
2693
|
-
// Use De Morgan's laws
|
2694
|
-
// z & (X | y)
|
2695
|
-
// => z & X (given y & z === 0)
|
2696
|
-
// => z & X | {y & z} (given y & z !== 0)
|
2697
|
-
let y, z, x_node, y_node, z_node = self.left;
|
2698
|
-
if (
|
2699
|
-
self.operator === "&"
|
2700
|
-
&& self.right instanceof AST_Binary
|
2701
|
-
&& self.right.operator === "|"
|
2702
|
-
&& typeof (z = self.left.evaluate(compressor)) === "number"
|
2703
|
-
) {
|
2704
|
-
if (typeof (y = self.right.right.evaluate(compressor)) === "number") {
|
2705
|
-
// z & (X | y)
|
2706
|
-
x_node = self.right.left;
|
2707
|
-
y_node = self.right.right;
|
2708
|
-
} else if (typeof (y = self.right.left.evaluate(compressor)) === "number") {
|
2709
|
-
// z & (y | X)
|
2710
|
-
x_node = self.right.right;
|
2711
|
-
y_node = self.right.left;
|
2712
|
-
}
|
2713
|
-
|
2714
|
-
if ((y & z) === 0) {
|
2715
|
-
self = make_node(AST_Binary, self, {
|
2716
|
-
operator: self.operator,
|
2717
|
-
left: z_node,
|
2718
|
-
right: x_node
|
2719
|
-
});
|
2720
|
-
} else {
|
2721
|
-
const reordered_ops = make_node(AST_Binary, self, {
|
2722
|
-
operator: "|",
|
2723
|
-
left: make_node(AST_Binary, self, {
|
2724
|
-
operator: "&",
|
2725
|
-
left: x_node,
|
2726
|
-
right: z_node
|
2727
|
-
}),
|
2728
|
-
right: make_node_from_constant(y & z, y_node),
|
2729
|
-
});
|
2730
|
-
|
2731
|
-
self = best_of(compressor, self, reordered_ops);
|
2732
|
-
}
|
2733
|
-
}
|
2734
|
-
|
2735
|
-
// x ^ x => 0
|
2736
|
-
// x | x => 0 | x
|
2737
|
-
// x & x => 0 | x
|
2738
|
-
const same_operands = self.left.equivalent_to(self.right) && !self.left.has_side_effects(compressor);
|
2739
|
-
if (same_operands) {
|
2740
|
-
if (self.operator === "^") {
|
2741
|
-
return make_node(AST_Number, self, { value: 0 });
|
2742
|
-
}
|
2743
|
-
if (self.operator === "|" || self.operator === "&") {
|
2744
|
-
self.left = make_node(AST_Number, self, { value: 0 });
|
2745
|
-
self.operator = "|";
|
2746
|
-
}
|
2747
|
-
}
|
2748
|
-
|
2749
|
-
|
2750
|
-
// Shifts that do nothing
|
2751
|
-
// {anything} >> 0 => {anything} | 0
|
2752
|
-
// {anything} << 0 => {anything} | 0
|
2753
|
-
if (
|
2754
|
-
(self.operator === "<<" || self.operator === ">>")
|
2755
|
-
&& self.right instanceof AST_Number && self.right.value === 0
|
2756
|
-
) {
|
2757
|
-
self.operator = "|";
|
2758
|
-
}
|
2759
|
-
|
2760
|
-
// Find useless to-bitwise conversions
|
2761
|
-
// {32 bit integer} | 0 => {32 bit integer}
|
2762
|
-
// {32 bit integer} ^ 0 => {32 bit integer}
|
2763
|
-
const zero_side = self.right instanceof AST_Number && self.right.value === 0 ? self.right
|
2764
|
-
: self.left instanceof AST_Number && self.left.value === 0 ? self.left
|
2765
|
-
: null;
|
2766
|
-
const non_zero_side = zero_side && (zero_side === self.right ? self.left : self.right);
|
2767
|
-
if (
|
2768
|
-
zero_side
|
2769
|
-
&& (self.operator === "|" || self.operator === "^")
|
2770
|
-
&& (non_zero_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
2771
|
-
) {
|
2772
|
-
return non_zero_side;
|
2773
|
-
}
|
2774
|
-
|
2775
|
-
// {anything} & 0 => 0
|
2776
|
-
if (
|
2777
|
-
zero_side
|
2778
|
-
&& self.operator === "&"
|
2779
|
-
&& !non_zero_side.has_side_effects(compressor)
|
2780
|
-
) {
|
2781
|
-
return zero_side;
|
2782
|
-
}
|
2783
|
-
|
2784
|
-
const is_full_mask = (node) =>
|
2785
|
-
node instanceof AST_Number && node.value === -1
|
2786
|
-
||
|
2787
|
-
node instanceof AST_UnaryPrefix && (
|
2788
|
-
node.operator === "-"
|
2789
|
-
&& node.expression instanceof AST_Number
|
2790
|
-
&& node.expression.value === 1
|
2791
|
-
|| node.operator === "~"
|
2792
|
-
&& node.expression instanceof AST_Number
|
2793
|
-
&& node.expression.value === 0);
|
2794
|
-
|
2795
|
-
const full_mask = is_full_mask(self.right) ? self.right
|
2796
|
-
: is_full_mask(self.left) ? self.left
|
2797
|
-
: null;
|
2798
|
-
const non_full_mask_side = full_mask && (full_mask === self.right ? self.left : self.right);
|
2799
|
-
|
2800
|
-
switch (self.operator) {
|
2801
|
-
case "|":
|
2802
|
-
// {anything} | -1 => -1
|
2803
|
-
if (full_mask && !non_full_mask_side.has_side_effects(compressor)) {
|
2804
|
-
return full_mask;
|
2805
|
-
}
|
2806
|
-
|
2807
|
-
break;
|
2808
|
-
case "&":
|
2809
|
-
// {32 bit integer} & -1 => {32 bit integer}
|
2810
|
-
if (
|
2811
|
-
full_mask
|
2812
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
2813
|
-
) {
|
2814
|
-
return non_full_mask_side;
|
2815
|
-
}
|
2816
|
-
|
2817
|
-
break;
|
2818
|
-
case "^":
|
2819
|
-
// {anything} ^ -1 => ~{anything}
|
2820
|
-
if (full_mask) {
|
2821
|
-
return non_full_mask_side.bitwise_negate(compressor.in_32_bit_context());
|
2822
|
-
}
|
2823
|
-
|
2824
|
-
// ~x ^ ~y => x ^ y
|
2825
|
-
if (
|
2826
|
-
self.left instanceof AST_UnaryPrefix
|
2827
|
-
&& self.left.operator === "~"
|
2828
|
-
&& self.right instanceof AST_UnaryPrefix
|
2829
|
-
&& self.right.operator === "~"
|
2830
|
-
) {
|
2831
|
-
self = make_node(AST_Binary, self, {
|
2832
|
-
operator: "^",
|
2833
|
-
left: self.left.expression,
|
2834
|
-
right: self.right.expression
|
2835
|
-
});
|
2836
|
-
}
|
2837
|
-
|
2838
|
-
break;
|
2839
|
-
}
|
2840
|
-
}
|
2841
2581
|
}
|
2842
2582
|
// x && (y && z) ==> x && y && z
|
2843
2583
|
// x || (y || z) ==> x || y || z
|
@@ -133,7 +133,6 @@ import { pure_prop_access_globals, is_pure_native_fn, is_pure_native_method } fr
|
|
133
133
|
export const is_undeclared_ref = (node) =>
|
134
134
|
node instanceof AST_SymbolRef && node.definition().undeclared;
|
135
135
|
|
136
|
-
export const bitwise_binop = makePredicate("<<< >> << & | ^ ~");
|
137
136
|
export const lazy_op = makePredicate("&& || ??");
|
138
137
|
export const unary_side_effects = makePredicate("delete ++ --");
|
139
138
|
|
@@ -194,24 +193,6 @@ export const unary_side_effects = makePredicate("delete ++ --");
|
|
194
193
|
node.DEFMETHOD("is_number", func);
|
195
194
|
});
|
196
195
|
|
197
|
-
// methods to determine if an expression is a 32 bit integer (IE results from bitwise ops, or is an integer constant fitting in that size
|
198
|
-
(function(def_is_32_bit_integer) {
|
199
|
-
def_is_32_bit_integer(AST_Node, return_false);
|
200
|
-
def_is_32_bit_integer(AST_Number, function() {
|
201
|
-
return this.value === (this.value | 0);
|
202
|
-
});
|
203
|
-
def_is_32_bit_integer(AST_UnaryPrefix, function() {
|
204
|
-
return this.operator == "~" ? this.expression.is_number()
|
205
|
-
: this.operator === "+" ? this.expression.is_32_bit_integer()
|
206
|
-
: false;
|
207
|
-
});
|
208
|
-
def_is_32_bit_integer(AST_Binary, function() {
|
209
|
-
return bitwise_binop.has(this.operator);
|
210
|
-
});
|
211
|
-
}(function (node, func) {
|
212
|
-
node.DEFMETHOD("is_32_bit_integer", func);
|
213
|
-
}));
|
214
|
-
|
215
196
|
// methods to determine if an expression has a string result type
|
216
197
|
(function(def_is_string) {
|
217
198
|
def_is_string(AST_Node, return_false);
|
@@ -826,37 +807,6 @@ export function is_lhs(node, parent) {
|
|
826
807
|
});
|
827
808
|
});
|
828
809
|
|
829
|
-
(function (def_bitwise_negate) {
|
830
|
-
function basic_negation(exp) {
|
831
|
-
return make_node(AST_UnaryPrefix, exp, {
|
832
|
-
operator: "~",
|
833
|
-
expression: exp
|
834
|
-
});
|
835
|
-
}
|
836
|
-
|
837
|
-
def_bitwise_negate(AST_Node, function() {
|
838
|
-
return basic_negation(this);
|
839
|
-
});
|
840
|
-
|
841
|
-
def_bitwise_negate(AST_Number, function() {
|
842
|
-
const neg = ~this.value;
|
843
|
-
if (neg.toString().length > this.value.toString().length) {
|
844
|
-
return basic_negation(this);
|
845
|
-
}
|
846
|
-
return make_node(AST_Number, this, { value: neg });
|
847
|
-
});
|
848
|
-
|
849
|
-
def_bitwise_negate(AST_UnaryPrefix, function(in_32_bit_context) {
|
850
|
-
if (this.operator == "~" && (in_32_bit_context || this.expression.is_32_bit_integer())) {
|
851
|
-
return this.expression;
|
852
|
-
} else {
|
853
|
-
return basic_negation(this);
|
854
|
-
}
|
855
|
-
});
|
856
|
-
})(function (node, func) {
|
857
|
-
node.DEFMETHOD("bitwise_negate", func);
|
858
|
-
});
|
859
|
-
|
860
810
|
// Is the callee of this function pure?
|
861
811
|
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");
|
862
812
|
AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
|
package/lib/size.js
CHANGED
@@ -406,8 +406,8 @@ AST_Class.prototype._size = function () {
|
|
406
406
|
};
|
407
407
|
|
408
408
|
AST_ClassStaticBlock.prototype._size = function () {
|
409
|
-
// "
|
410
|
-
return
|
409
|
+
// "class{}" + semicolons
|
410
|
+
return 7 + list_overhead(this.body);
|
411
411
|
};
|
412
412
|
|
413
413
|
AST_ClassProperty.prototype._size = function () {
|