terser 5.38.2 → 5.39.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/README.md +2 -1
- package/dist/bundle.min.js +191 -94
- package/lib/compress/compressor-flags.js +0 -1
- package/lib/compress/index.js +94 -73
- package/lib/compress/inference.js +97 -21
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
@@ -871,7 +871,8 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
|
|
871
871
|
allow improved compression. This might be unsafe when an at least one of two
|
872
872
|
operands is an object with computed values due the use of methods like `get`,
|
873
873
|
or `valueOf`. This could cause change in execution order after operands in the
|
874
|
-
comparison are switching.
|
874
|
+
comparison are switching. Or if one of two operands is `NaN`, the result is always
|
875
|
+
`false`. Compression only works if both `comparisons` and
|
875
876
|
`unsafe_comps` are both set to true.
|
876
877
|
|
877
878
|
- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
|
package/dist/bundle.min.js
CHANGED
@@ -13045,7 +13045,6 @@ const TRUTHY = 0b00000010;
|
|
13045
13045
|
const FALSY = 0b00000100;
|
13046
13046
|
const UNDEFINED = 0b00001000;
|
13047
13047
|
const INLINED = 0b00010000;
|
13048
|
-
|
13049
13048
|
// Nodes to which values are ever written. Used when keep_assign is part of the unused option string.
|
13050
13049
|
const WRITE_ONLY = 0b00100000;
|
13051
13050
|
|
@@ -13677,18 +13676,24 @@ const unary_side_effects = makePredicate("delete ++ --");
|
|
13677
13676
|
def_is_number(AST_Node, return_false);
|
13678
13677
|
def_is_number(AST_Number, return_true);
|
13679
13678
|
const unary = makePredicate("+ - ~ ++ --");
|
13680
|
-
def_is_number(AST_Unary, function() {
|
13681
|
-
return unary.has(this.operator) &&
|
13679
|
+
def_is_number(AST_Unary, function(compressor) {
|
13680
|
+
return unary.has(this.operator) && this.expression.is_number(compressor);
|
13682
13681
|
});
|
13683
13682
|
const numeric_ops = makePredicate("- * / % & | ^ << >> >>>");
|
13684
13683
|
def_is_number(AST_Binary, function(compressor) {
|
13685
|
-
|
13686
|
-
|
13687
|
-
&& this.right.
|
13684
|
+
if (this.operator === "+") {
|
13685
|
+
// Both sides need to be `number`. Or one is a `number` and the other is number-ish.
|
13686
|
+
return this.left.is_number(compressor) && this.right.is_number_or_bigint(compressor)
|
13687
|
+
|| this.right.is_number(compressor) && this.left.is_number_or_bigint(compressor);
|
13688
|
+
} else if (numeric_ops.has(this.operator)) {
|
13689
|
+
return this.left.is_number(compressor) || this.right.is_number(compressor);
|
13690
|
+
} else {
|
13691
|
+
return false;
|
13692
|
+
}
|
13688
13693
|
});
|
13689
13694
|
def_is_number(AST_Assign, function(compressor) {
|
13690
|
-
return numeric_ops.has(this.operator.slice(0, -1))
|
13691
|
-
|
13695
|
+
return (this.operator === "=" || numeric_ops.has(this.operator.slice(0, -1)))
|
13696
|
+
&& this.right.is_number(compressor);
|
13692
13697
|
});
|
13693
13698
|
def_is_number(AST_Sequence, function(compressor) {
|
13694
13699
|
return this.tail_node().is_number(compressor);
|
@@ -13700,19 +13705,83 @@ const unary_side_effects = makePredicate("delete ++ --");
|
|
13700
13705
|
node.DEFMETHOD("is_number", func);
|
13701
13706
|
});
|
13702
13707
|
|
13708
|
+
// methods to determine if an expression returns a BigInt
|
13709
|
+
(function(def_is_bigint) {
|
13710
|
+
def_is_bigint(AST_Node, return_false);
|
13711
|
+
def_is_bigint(AST_BigInt, return_true);
|
13712
|
+
const unary = makePredicate("+ - ~ ++ --");
|
13713
|
+
def_is_bigint(AST_Unary, function(compressor) {
|
13714
|
+
return unary.has(this.operator) && this.expression.is_bigint(compressor);
|
13715
|
+
});
|
13716
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
13717
|
+
def_is_bigint(AST_Binary, function(compressor) {
|
13718
|
+
if (this.operator === "+") {
|
13719
|
+
return this.left.is_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
13720
|
+
|| this.right.is_bigint(compressor) && this.left.is_number_or_bigint(compressor);
|
13721
|
+
} else if (numeric_ops.has(this.operator)) {
|
13722
|
+
return this.left.is_bigint(compressor) || this.right.is_bigint(compressor);
|
13723
|
+
} else {
|
13724
|
+
return false;
|
13725
|
+
}
|
13726
|
+
});
|
13727
|
+
def_is_bigint(AST_Assign, function(compressor) {
|
13728
|
+
return (numeric_ops.has(this.operator.slice(0, -1)) || this.operator == "=")
|
13729
|
+
&& this.right.is_bigint(compressor);
|
13730
|
+
});
|
13731
|
+
def_is_bigint(AST_Sequence, function(compressor) {
|
13732
|
+
return this.tail_node().is_bigint(compressor);
|
13733
|
+
});
|
13734
|
+
def_is_bigint(AST_Conditional, function(compressor) {
|
13735
|
+
return this.consequent.is_bigint(compressor) && this.alternative.is_bigint(compressor);
|
13736
|
+
});
|
13737
|
+
})(function(node, func) {
|
13738
|
+
node.DEFMETHOD("is_bigint", func);
|
13739
|
+
});
|
13740
|
+
|
13741
|
+
// methods to determine if an expression is a number or a bigint
|
13742
|
+
(function(def_is_number_or_bigint) {
|
13743
|
+
def_is_number_or_bigint(AST_Node, return_false);
|
13744
|
+
def_is_number_or_bigint(AST_Number, return_true);
|
13745
|
+
def_is_number_or_bigint(AST_BigInt, return_true);
|
13746
|
+
const numeric_unary_ops = makePredicate("+ - ~ ++ --");
|
13747
|
+
def_is_number_or_bigint(AST_Unary, function(_compressor) {
|
13748
|
+
return numeric_unary_ops.has(this.operator);
|
13749
|
+
});
|
13750
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
13751
|
+
def_is_number_or_bigint(AST_Binary, function(compressor) {
|
13752
|
+
return this.operator === "+"
|
13753
|
+
? this.left.is_number_or_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
13754
|
+
: numeric_ops.has(this.operator);
|
13755
|
+
});
|
13756
|
+
def_is_number_or_bigint(AST_Assign, function(compressor) {
|
13757
|
+
return numeric_ops.has(this.operator.slice(0, -1))
|
13758
|
+
|| this.operator == "=" && this.right.is_number_or_bigint(compressor);
|
13759
|
+
});
|
13760
|
+
def_is_number_or_bigint(AST_Sequence, function(compressor) {
|
13761
|
+
return this.tail_node().is_number_or_bigint(compressor);
|
13762
|
+
});
|
13763
|
+
def_is_number_or_bigint(AST_Conditional, function(compressor) {
|
13764
|
+
return this.consequent.is_number_or_bigint(compressor) && this.alternative.is_number_or_bigint(compressor);
|
13765
|
+
});
|
13766
|
+
}(function (node, func) {
|
13767
|
+
node.DEFMETHOD("is_number_or_bigint", func);
|
13768
|
+
}));
|
13769
|
+
|
13770
|
+
|
13703
13771
|
// 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
|
13704
13772
|
(function(def_is_32_bit_integer) {
|
13705
13773
|
def_is_32_bit_integer(AST_Node, return_false);
|
13706
|
-
def_is_32_bit_integer(AST_Number, function() {
|
13774
|
+
def_is_32_bit_integer(AST_Number, function(_compressor) {
|
13707
13775
|
return this.value === (this.value | 0);
|
13708
13776
|
});
|
13709
|
-
def_is_32_bit_integer(AST_UnaryPrefix, function() {
|
13710
|
-
return this.operator == "~" ? this.expression.is_number()
|
13711
|
-
: this.operator === "+" ? this.expression.is_32_bit_integer()
|
13777
|
+
def_is_32_bit_integer(AST_UnaryPrefix, function(compressor) {
|
13778
|
+
return this.operator == "~" ? this.expression.is_number(compressor)
|
13779
|
+
: this.operator === "+" ? this.expression.is_32_bit_integer(compressor)
|
13712
13780
|
: false;
|
13713
13781
|
});
|
13714
|
-
def_is_32_bit_integer(AST_Binary, function() {
|
13715
|
-
return bitwise_binop.has(this.operator)
|
13782
|
+
def_is_32_bit_integer(AST_Binary, function(compressor) {
|
13783
|
+
return bitwise_binop.has(this.operator)
|
13784
|
+
&& (this.left.is_number(compressor) || this.right.is_number(compressor));
|
13716
13785
|
});
|
13717
13786
|
}(function (node, func) {
|
13718
13787
|
node.DEFMETHOD("is_32_bit_integer", func);
|
@@ -14349,30 +14418,36 @@ function is_lhs(node, parent) {
|
|
14349
14418
|
});
|
14350
14419
|
|
14351
14420
|
(function (def_bitwise_negate) {
|
14352
|
-
function
|
14421
|
+
function basic_bitwise_negation(exp) {
|
14353
14422
|
return make_node(AST_UnaryPrefix, exp, {
|
14354
14423
|
operator: "~",
|
14355
14424
|
expression: exp
|
14356
14425
|
});
|
14357
14426
|
}
|
14358
14427
|
|
14359
|
-
def_bitwise_negate(AST_Node, function() {
|
14360
|
-
return
|
14428
|
+
def_bitwise_negate(AST_Node, function(_compressor) {
|
14429
|
+
return basic_bitwise_negation(this);
|
14361
14430
|
});
|
14362
14431
|
|
14363
|
-
def_bitwise_negate(AST_Number, function() {
|
14432
|
+
def_bitwise_negate(AST_Number, function(_compressor) {
|
14364
14433
|
const neg = ~this.value;
|
14365
14434
|
if (neg.toString().length > this.value.toString().length) {
|
14366
|
-
return
|
14435
|
+
return basic_bitwise_negation(this);
|
14367
14436
|
}
|
14368
14437
|
return make_node(AST_Number, this, { value: neg });
|
14369
14438
|
});
|
14370
14439
|
|
14371
|
-
def_bitwise_negate(AST_UnaryPrefix, function(in_32_bit_context) {
|
14372
|
-
if (
|
14440
|
+
def_bitwise_negate(AST_UnaryPrefix, function(compressor, in_32_bit_context) {
|
14441
|
+
if (
|
14442
|
+
this.operator == "~"
|
14443
|
+
&& (
|
14444
|
+
this.expression.is_32_bit_integer(compressor) ||
|
14445
|
+
(in_32_bit_context != null ? in_32_bit_context : compressor.in_32_bit_context())
|
14446
|
+
)
|
14447
|
+
) {
|
14373
14448
|
return this.expression;
|
14374
14449
|
} else {
|
14375
|
-
return
|
14450
|
+
return basic_bitwise_negation(this);
|
14376
14451
|
}
|
14377
14452
|
});
|
14378
14453
|
})(function (node, func) {
|
@@ -18909,12 +18984,16 @@ class Compressor extends TreeWalker {
|
|
18909
18984
|
}
|
18910
18985
|
}
|
18911
18986
|
|
18912
|
-
in_32_bit_context() {
|
18987
|
+
in_32_bit_context(other_operand_must_be_number) {
|
18913
18988
|
if (!this.option("evaluate")) return false;
|
18914
18989
|
var self = this.self();
|
18915
18990
|
for (var i = 0, p; p = this.parent(i); i++) {
|
18916
18991
|
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
18917
|
-
|
18992
|
+
if (other_operand_must_be_number) {
|
18993
|
+
return (self === p.left ? p.right : p.left).is_number(this);
|
18994
|
+
} else {
|
18995
|
+
return true;
|
18996
|
+
}
|
18918
18997
|
}
|
18919
18998
|
if (p instanceof AST_UnaryPrefix) {
|
18920
18999
|
return p.operator === "~";
|
@@ -19029,6 +19108,7 @@ class Compressor extends TreeWalker {
|
|
19029
19108
|
}
|
19030
19109
|
}
|
19031
19110
|
|
19111
|
+
|
19032
19112
|
function def_optimize(node, optimizer) {
|
19033
19113
|
node.DEFMETHOD("optimize", function(compressor) {
|
19034
19114
|
var self = this;
|
@@ -20253,6 +20333,23 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
20253
20333
|
self.args.length = last;
|
20254
20334
|
}
|
20255
20335
|
|
20336
|
+
if (
|
20337
|
+
exp instanceof AST_Dot
|
20338
|
+
&& exp.expression instanceof AST_SymbolRef
|
20339
|
+
&& exp.expression.name === "console"
|
20340
|
+
&& exp.expression.definition().undeclared
|
20341
|
+
&& exp.property === "assert"
|
20342
|
+
) {
|
20343
|
+
const condition = self.args[0];
|
20344
|
+
if (condition) {
|
20345
|
+
const value = condition.evaluate(compressor);
|
20346
|
+
|
20347
|
+
if (value === 1 || value === true) {
|
20348
|
+
return make_node(AST_Undefined, self);
|
20349
|
+
}
|
20350
|
+
}
|
20351
|
+
}
|
20352
|
+
|
20256
20353
|
if (compressor.option("unsafe") && !exp.contains_optional()) {
|
20257
20354
|
if (exp instanceof AST_Dot && exp.start.value === "Array" && exp.property === "from" && self.args.length === 1) {
|
20258
20355
|
const [argument] = self.args;
|
@@ -20667,7 +20764,7 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
20667
20764
|
self.operator === "~"
|
20668
20765
|
&& self.expression instanceof AST_UnaryPrefix
|
20669
20766
|
&& self.expression.operator === "~"
|
20670
|
-
&& (compressor.in_32_bit_context() || self.expression.expression.is_32_bit_integer())
|
20767
|
+
&& (compressor.in_32_bit_context(false) || self.expression.expression.is_32_bit_integer(compressor))
|
20671
20768
|
) {
|
20672
20769
|
return self.expression.expression;
|
20673
20770
|
}
|
@@ -20680,9 +20777,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
20680
20777
|
) {
|
20681
20778
|
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
20682
20779
|
// ~(~x ^ y) => x ^ y
|
20683
|
-
e.left = e.left.bitwise_negate(true);
|
20780
|
+
e.left = e.left.bitwise_negate(compressor, true);
|
20684
20781
|
} else {
|
20685
|
-
e.right = e.right.bitwise_negate(true);
|
20782
|
+
e.right = e.right.bitwise_negate(compressor, true);
|
20686
20783
|
}
|
20687
20784
|
return e;
|
20688
20785
|
}
|
@@ -20777,10 +20874,13 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20777
20874
|
case "===":
|
20778
20875
|
case "!==":
|
20779
20876
|
var is_strict_comparison = true;
|
20780
|
-
if (
|
20877
|
+
if (
|
20878
|
+
(self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
20781
20879
|
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
|
20880
|
+
(self.left.is_bigint(compressor) && self.right.is_bigint(compressor)) ||
|
20782
20881
|
(self.left.is_boolean() && self.right.is_boolean()) ||
|
20783
|
-
self.left.equivalent_to(self.right)
|
20882
|
+
self.left.equivalent_to(self.right)
|
20883
|
+
) {
|
20784
20884
|
self.operator = self.operator.substr(0, 2);
|
20785
20885
|
}
|
20786
20886
|
|
@@ -20825,7 +20925,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20825
20925
|
&& self.left.definition() === self.right.definition()
|
20826
20926
|
&& is_object(self.left.fixed_value())) {
|
20827
20927
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
20828
|
-
} else if (self.left.is_32_bit_integer() && self.right.is_32_bit_integer()) {
|
20928
|
+
} else if (self.left.is_32_bit_integer(compressor) && self.right.is_32_bit_integer(compressor)) {
|
20829
20929
|
const not = node => make_node(AST_UnaryPrefix, node, {
|
20830
20930
|
operator: "!",
|
20831
20931
|
expression: node
|
@@ -20858,7 +20958,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20858
20958
|
&& (mask = and_op === self.left ? self.right : self.left)
|
20859
20959
|
&& and_op.operator === "&"
|
20860
20960
|
&& mask instanceof AST_Number
|
20861
|
-
&& mask.is_32_bit_integer()
|
20961
|
+
&& mask.is_32_bit_integer(compressor)
|
20862
20962
|
&& (x =
|
20863
20963
|
and_op.left.equivalent_to(mask) ? and_op.right
|
20864
20964
|
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
@@ -21101,7 +21201,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21101
21201
|
// a + -b => a - b
|
21102
21202
|
if (self.right instanceof AST_UnaryPrefix
|
21103
21203
|
&& self.right.operator == "-"
|
21104
|
-
&& self.left.
|
21204
|
+
&& self.left.is_number_or_bigint(compressor)) {
|
21105
21205
|
self = make_node(AST_Binary, self, {
|
21106
21206
|
operator: "-",
|
21107
21207
|
left: self.left,
|
@@ -21113,7 +21213,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21113
21213
|
if (self.left instanceof AST_UnaryPrefix
|
21114
21214
|
&& self.left.operator == "-"
|
21115
21215
|
&& reversible()
|
21116
|
-
&& self.right.
|
21216
|
+
&& self.right.is_number_or_bigint(compressor)) {
|
21117
21217
|
self = make_node(AST_Binary, self, {
|
21118
21218
|
operator: "-",
|
21119
21219
|
left: self.right,
|
@@ -21157,8 +21257,9 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21157
21257
|
case "|":
|
21158
21258
|
case "^":
|
21159
21259
|
// a + +b => +b + a
|
21160
|
-
if (
|
21161
|
-
|
21260
|
+
if (
|
21261
|
+
self.left.is_number_or_bigint(compressor)
|
21262
|
+
&& self.right.is_number_or_bigint(compressor)
|
21162
21263
|
&& reversible()
|
21163
21264
|
&& !(self.left instanceof AST_Binary
|
21164
21265
|
&& self.left.operator != self.operator
|
@@ -21175,7 +21276,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21175
21276
|
self = best_of(compressor, self, reversed);
|
21176
21277
|
}
|
21177
21278
|
}
|
21178
|
-
if (associative && self.
|
21279
|
+
if (associative && self.is_number_or_bigint(compressor)) {
|
21179
21280
|
// a + (b + c) => (a + b) + c
|
21180
21281
|
if (self.right instanceof AST_Binary
|
21181
21282
|
&& self.right.operator == self.operator) {
|
@@ -21294,18 +21395,31 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21294
21395
|
}
|
21295
21396
|
}
|
21296
21397
|
|
21297
|
-
// x ^ x => 0
|
21298
21398
|
// x | x => 0 | x
|
21299
21399
|
// x & x => 0 | x
|
21300
|
-
|
21301
|
-
|
21302
|
-
|
21303
|
-
|
21304
|
-
|
21305
|
-
|
21306
|
-
|
21307
|
-
|
21308
|
-
|
21400
|
+
if (
|
21401
|
+
(self.operator === "|" || self.operator === "&")
|
21402
|
+
&& self.left.equivalent_to(self.right)
|
21403
|
+
&& !self.left.has_side_effects(compressor)
|
21404
|
+
&& compressor.in_32_bit_context(true)
|
21405
|
+
) {
|
21406
|
+
self.left = make_node(AST_Number, self, { value: 0 });
|
21407
|
+
self.operator = "|";
|
21408
|
+
}
|
21409
|
+
|
21410
|
+
// ~x ^ ~y => x ^ y
|
21411
|
+
if (
|
21412
|
+
self.operator === "^"
|
21413
|
+
&& self.left instanceof AST_UnaryPrefix
|
21414
|
+
&& self.left.operator === "~"
|
21415
|
+
&& self.right instanceof AST_UnaryPrefix
|
21416
|
+
&& self.right.operator === "~"
|
21417
|
+
) {
|
21418
|
+
self = make_node(AST_Binary, self, {
|
21419
|
+
operator: "^",
|
21420
|
+
left: self.left.expression,
|
21421
|
+
right: self.right.expression
|
21422
|
+
});
|
21309
21423
|
}
|
21310
21424
|
|
21311
21425
|
|
@@ -21329,7 +21443,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21329
21443
|
if (
|
21330
21444
|
zero_side
|
21331
21445
|
&& (self.operator === "|" || self.operator === "^")
|
21332
|
-
&& (non_zero_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21446
|
+
&& (non_zero_side.is_32_bit_integer(compressor) || compressor.in_32_bit_context(true))
|
21333
21447
|
) {
|
21334
21448
|
return non_zero_side;
|
21335
21449
|
}
|
@@ -21339,65 +21453,48 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21339
21453
|
zero_side
|
21340
21454
|
&& self.operator === "&"
|
21341
21455
|
&& !non_zero_side.has_side_effects(compressor)
|
21456
|
+
&& non_zero_side.is_32_bit_integer(compressor)
|
21342
21457
|
) {
|
21343
21458
|
return zero_side;
|
21344
21459
|
}
|
21345
21460
|
|
21461
|
+
// ~0 is all ones, as well as -1.
|
21462
|
+
// We can ellide some operations with it.
|
21346
21463
|
const is_full_mask = (node) =>
|
21347
21464
|
node instanceof AST_Number && node.value === -1
|
21348
21465
|
||
|
21349
|
-
node instanceof AST_UnaryPrefix
|
21350
|
-
|
21351
|
-
|
21352
|
-
|
21353
|
-
|| node.operator === "~"
|
21354
|
-
&& node.expression instanceof AST_Number
|
21355
|
-
&& node.expression.value === 0);
|
21466
|
+
node instanceof AST_UnaryPrefix
|
21467
|
+
&& node.operator === "-"
|
21468
|
+
&& node.expression instanceof AST_Number
|
21469
|
+
&& node.expression.value === 1;
|
21356
21470
|
|
21357
21471
|
const full_mask = is_full_mask(self.right) ? self.right
|
21358
21472
|
: is_full_mask(self.left) ? self.left
|
21359
21473
|
: null;
|
21360
|
-
const
|
21361
|
-
|
21362
|
-
switch (self.operator) {
|
21363
|
-
case "|":
|
21364
|
-
// {anything} | -1 => -1
|
21365
|
-
if (full_mask && !non_full_mask_side.has_side_effects(compressor)) {
|
21366
|
-
return full_mask;
|
21367
|
-
}
|
21368
|
-
|
21369
|
-
break;
|
21370
|
-
case "&":
|
21371
|
-
// {32 bit integer} & -1 => {32 bit integer}
|
21372
|
-
if (
|
21373
|
-
full_mask
|
21374
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21375
|
-
) {
|
21376
|
-
return non_full_mask_side;
|
21377
|
-
}
|
21474
|
+
const other_side = (full_mask === self.right ? self.left : self.right);
|
21378
21475
|
|
21379
|
-
|
21380
|
-
|
21381
|
-
|
21382
|
-
|
21383
|
-
|
21384
|
-
|
21385
|
-
|
21386
|
-
|
21387
|
-
|
21388
|
-
|
21389
|
-
|
21390
|
-
&& self.right instanceof AST_UnaryPrefix
|
21391
|
-
&& self.right.operator === "~"
|
21392
|
-
) {
|
21393
|
-
self = make_node(AST_Binary, self, {
|
21394
|
-
operator: "^",
|
21395
|
-
left: self.left.expression,
|
21396
|
-
right: self.right.expression
|
21397
|
-
});
|
21398
|
-
}
|
21476
|
+
// {32 bit integer} & -1 => {32 bit integer}
|
21477
|
+
if (
|
21478
|
+
full_mask
|
21479
|
+
&& self.operator === "&"
|
21480
|
+
&& (
|
21481
|
+
other_side.is_32_bit_integer(compressor)
|
21482
|
+
|| compressor.in_32_bit_context(true)
|
21483
|
+
)
|
21484
|
+
) {
|
21485
|
+
return other_side;
|
21486
|
+
}
|
21399
21487
|
|
21400
|
-
|
21488
|
+
// {anything} ^ -1 => ~{anything}
|
21489
|
+
if (
|
21490
|
+
full_mask
|
21491
|
+
&& self.operator === "^"
|
21492
|
+
&& (
|
21493
|
+
other_side.is_32_bit_integer(compressor)
|
21494
|
+
|| compressor.in_32_bit_context(true)
|
21495
|
+
)
|
21496
|
+
) {
|
21497
|
+
return other_side.bitwise_negate(compressor);
|
21401
21498
|
}
|
21402
21499
|
}
|
21403
21500
|
}
|
@@ -22448,7 +22545,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
22448
22545
|
&& segments[1] instanceof AST_Node
|
22449
22546
|
&& (
|
22450
22547
|
segments[1].is_string(compressor)
|
22451
|
-
|| segments[1].
|
22548
|
+
|| segments[1].is_number_or_bigint(compressor)
|
22452
22549
|
|| is_nullish(segments[1], compressor)
|
22453
22550
|
|| compressor.option("unsafe")
|
22454
22551
|
)
|
@@ -48,7 +48,6 @@ export const TRUTHY = 0b00000010;
|
|
48
48
|
export const FALSY = 0b00000100;
|
49
49
|
export const UNDEFINED = 0b00001000;
|
50
50
|
export const INLINED = 0b00010000;
|
51
|
-
|
52
51
|
// Nodes to which values are ever written. Used when keep_assign is part of the unused option string.
|
53
52
|
export const WRITE_ONLY = 0b00100000;
|
54
53
|
|
package/lib/compress/index.js
CHANGED
@@ -188,7 +188,6 @@ import {
|
|
188
188
|
UNUSED,
|
189
189
|
TRUTHY,
|
190
190
|
FALSY,
|
191
|
-
|
192
191
|
has_flag,
|
193
192
|
set_flag,
|
194
193
|
clear_flag,
|
@@ -377,12 +376,16 @@ class Compressor extends TreeWalker {
|
|
377
376
|
}
|
378
377
|
}
|
379
378
|
|
380
|
-
in_32_bit_context() {
|
379
|
+
in_32_bit_context(other_operand_must_be_number) {
|
381
380
|
if (!this.option("evaluate")) return false;
|
382
381
|
var self = this.self();
|
383
382
|
for (var i = 0, p; p = this.parent(i); i++) {
|
384
383
|
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
385
|
-
|
384
|
+
if (other_operand_must_be_number) {
|
385
|
+
return (self === p.left ? p.right : p.left).is_number(this);
|
386
|
+
} else {
|
387
|
+
return true;
|
388
|
+
}
|
386
389
|
}
|
387
390
|
if (p instanceof AST_UnaryPrefix) {
|
388
391
|
return p.operator === "~";
|
@@ -497,6 +500,7 @@ class Compressor extends TreeWalker {
|
|
497
500
|
}
|
498
501
|
}
|
499
502
|
|
503
|
+
|
500
504
|
function def_optimize(node, optimizer) {
|
501
505
|
node.DEFMETHOD("optimize", function(compressor) {
|
502
506
|
var self = this;
|
@@ -1721,6 +1725,23 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1721
1725
|
self.args.length = last;
|
1722
1726
|
}
|
1723
1727
|
|
1728
|
+
if (
|
1729
|
+
exp instanceof AST_Dot
|
1730
|
+
&& exp.expression instanceof AST_SymbolRef
|
1731
|
+
&& exp.expression.name === "console"
|
1732
|
+
&& exp.expression.definition().undeclared
|
1733
|
+
&& exp.property === "assert"
|
1734
|
+
) {
|
1735
|
+
const condition = self.args[0];
|
1736
|
+
if (condition) {
|
1737
|
+
const value = condition.evaluate(compressor);
|
1738
|
+
|
1739
|
+
if (value === 1 || value === true) {
|
1740
|
+
return make_node(AST_Undefined, self);
|
1741
|
+
}
|
1742
|
+
}
|
1743
|
+
}
|
1744
|
+
|
1724
1745
|
if (compressor.option("unsafe") && !exp.contains_optional()) {
|
1725
1746
|
if (exp instanceof AST_Dot && exp.start.value === "Array" && exp.property === "from" && self.args.length === 1) {
|
1726
1747
|
const [argument] = self.args;
|
@@ -2135,7 +2156,7 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
2135
2156
|
self.operator === "~"
|
2136
2157
|
&& self.expression instanceof AST_UnaryPrefix
|
2137
2158
|
&& self.expression.operator === "~"
|
2138
|
-
&& (compressor.in_32_bit_context() || self.expression.expression.is_32_bit_integer())
|
2159
|
+
&& (compressor.in_32_bit_context(false) || self.expression.expression.is_32_bit_integer(compressor))
|
2139
2160
|
) {
|
2140
2161
|
return self.expression.expression;
|
2141
2162
|
}
|
@@ -2148,9 +2169,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
2148
2169
|
) {
|
2149
2170
|
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
2150
2171
|
// ~(~x ^ y) => x ^ y
|
2151
|
-
e.left = e.left.bitwise_negate(true);
|
2172
|
+
e.left = e.left.bitwise_negate(compressor, true);
|
2152
2173
|
} else {
|
2153
|
-
e.right = e.right.bitwise_negate(true);
|
2174
|
+
e.right = e.right.bitwise_negate(compressor, true);
|
2154
2175
|
}
|
2155
2176
|
return e;
|
2156
2177
|
}
|
@@ -2245,10 +2266,13 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2245
2266
|
case "===":
|
2246
2267
|
case "!==":
|
2247
2268
|
var is_strict_comparison = true;
|
2248
|
-
if (
|
2269
|
+
if (
|
2270
|
+
(self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
2249
2271
|
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
|
2272
|
+
(self.left.is_bigint(compressor) && self.right.is_bigint(compressor)) ||
|
2250
2273
|
(self.left.is_boolean() && self.right.is_boolean()) ||
|
2251
|
-
self.left.equivalent_to(self.right)
|
2274
|
+
self.left.equivalent_to(self.right)
|
2275
|
+
) {
|
2252
2276
|
self.operator = self.operator.substr(0, 2);
|
2253
2277
|
}
|
2254
2278
|
|
@@ -2293,7 +2317,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2293
2317
|
&& self.left.definition() === self.right.definition()
|
2294
2318
|
&& is_object(self.left.fixed_value())) {
|
2295
2319
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
2296
|
-
} else if (self.left.is_32_bit_integer() && self.right.is_32_bit_integer()) {
|
2320
|
+
} else if (self.left.is_32_bit_integer(compressor) && self.right.is_32_bit_integer(compressor)) {
|
2297
2321
|
const not = node => make_node(AST_UnaryPrefix, node, {
|
2298
2322
|
operator: "!",
|
2299
2323
|
expression: node
|
@@ -2326,7 +2350,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2326
2350
|
&& (mask = and_op === self.left ? self.right : self.left)
|
2327
2351
|
&& and_op.operator === "&"
|
2328
2352
|
&& mask instanceof AST_Number
|
2329
|
-
&& mask.is_32_bit_integer()
|
2353
|
+
&& mask.is_32_bit_integer(compressor)
|
2330
2354
|
&& (x =
|
2331
2355
|
and_op.left.equivalent_to(mask) ? and_op.right
|
2332
2356
|
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
@@ -2569,7 +2593,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2569
2593
|
// a + -b => a - b
|
2570
2594
|
if (self.right instanceof AST_UnaryPrefix
|
2571
2595
|
&& self.right.operator == "-"
|
2572
|
-
&& self.left.
|
2596
|
+
&& self.left.is_number_or_bigint(compressor)) {
|
2573
2597
|
self = make_node(AST_Binary, self, {
|
2574
2598
|
operator: "-",
|
2575
2599
|
left: self.left,
|
@@ -2581,7 +2605,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2581
2605
|
if (self.left instanceof AST_UnaryPrefix
|
2582
2606
|
&& self.left.operator == "-"
|
2583
2607
|
&& reversible()
|
2584
|
-
&& self.right.
|
2608
|
+
&& self.right.is_number_or_bigint(compressor)) {
|
2585
2609
|
self = make_node(AST_Binary, self, {
|
2586
2610
|
operator: "-",
|
2587
2611
|
left: self.right,
|
@@ -2625,8 +2649,9 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2625
2649
|
case "|":
|
2626
2650
|
case "^":
|
2627
2651
|
// a + +b => +b + a
|
2628
|
-
if (
|
2629
|
-
|
2652
|
+
if (
|
2653
|
+
self.left.is_number_or_bigint(compressor)
|
2654
|
+
&& self.right.is_number_or_bigint(compressor)
|
2630
2655
|
&& reversible()
|
2631
2656
|
&& !(self.left instanceof AST_Binary
|
2632
2657
|
&& self.left.operator != self.operator
|
@@ -2643,7 +2668,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2643
2668
|
self = best_of(compressor, self, reversed);
|
2644
2669
|
}
|
2645
2670
|
}
|
2646
|
-
if (associative && self.
|
2671
|
+
if (associative && self.is_number_or_bigint(compressor)) {
|
2647
2672
|
// a + (b + c) => (a + b) + c
|
2648
2673
|
if (self.right instanceof AST_Binary
|
2649
2674
|
&& self.right.operator == self.operator) {
|
@@ -2762,18 +2787,31 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2762
2787
|
}
|
2763
2788
|
}
|
2764
2789
|
|
2765
|
-
// x ^ x => 0
|
2766
2790
|
// x | x => 0 | x
|
2767
2791
|
// x & x => 0 | x
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2792
|
+
if (
|
2793
|
+
(self.operator === "|" || self.operator === "&")
|
2794
|
+
&& self.left.equivalent_to(self.right)
|
2795
|
+
&& !self.left.has_side_effects(compressor)
|
2796
|
+
&& compressor.in_32_bit_context(true)
|
2797
|
+
) {
|
2798
|
+
self.left = make_node(AST_Number, self, { value: 0 });
|
2799
|
+
self.operator = "|";
|
2800
|
+
}
|
2801
|
+
|
2802
|
+
// ~x ^ ~y => x ^ y
|
2803
|
+
if (
|
2804
|
+
self.operator === "^"
|
2805
|
+
&& self.left instanceof AST_UnaryPrefix
|
2806
|
+
&& self.left.operator === "~"
|
2807
|
+
&& self.right instanceof AST_UnaryPrefix
|
2808
|
+
&& self.right.operator === "~"
|
2809
|
+
) {
|
2810
|
+
self = make_node(AST_Binary, self, {
|
2811
|
+
operator: "^",
|
2812
|
+
left: self.left.expression,
|
2813
|
+
right: self.right.expression
|
2814
|
+
});
|
2777
2815
|
}
|
2778
2816
|
|
2779
2817
|
|
@@ -2797,7 +2835,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2797
2835
|
if (
|
2798
2836
|
zero_side
|
2799
2837
|
&& (self.operator === "|" || self.operator === "^")
|
2800
|
-
&& (non_zero_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
2838
|
+
&& (non_zero_side.is_32_bit_integer(compressor) || compressor.in_32_bit_context(true))
|
2801
2839
|
) {
|
2802
2840
|
return non_zero_side;
|
2803
2841
|
}
|
@@ -2807,65 +2845,48 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2807
2845
|
zero_side
|
2808
2846
|
&& self.operator === "&"
|
2809
2847
|
&& !non_zero_side.has_side_effects(compressor)
|
2848
|
+
&& non_zero_side.is_32_bit_integer(compressor)
|
2810
2849
|
) {
|
2811
2850
|
return zero_side;
|
2812
2851
|
}
|
2813
2852
|
|
2853
|
+
// ~0 is all ones, as well as -1.
|
2854
|
+
// We can ellide some operations with it.
|
2814
2855
|
const is_full_mask = (node) =>
|
2815
2856
|
node instanceof AST_Number && node.value === -1
|
2816
2857
|
||
|
2817
|
-
node instanceof AST_UnaryPrefix
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
|| node.operator === "~"
|
2822
|
-
&& node.expression instanceof AST_Number
|
2823
|
-
&& node.expression.value === 0);
|
2858
|
+
node instanceof AST_UnaryPrefix
|
2859
|
+
&& node.operator === "-"
|
2860
|
+
&& node.expression instanceof AST_Number
|
2861
|
+
&& node.expression.value === 1;
|
2824
2862
|
|
2825
2863
|
const full_mask = is_full_mask(self.right) ? self.right
|
2826
2864
|
: is_full_mask(self.left) ? self.left
|
2827
2865
|
: null;
|
2828
|
-
const
|
2829
|
-
|
2830
|
-
switch (self.operator) {
|
2831
|
-
case "|":
|
2832
|
-
// {anything} | -1 => -1
|
2833
|
-
if (full_mask && !non_full_mask_side.has_side_effects(compressor)) {
|
2834
|
-
return full_mask;
|
2835
|
-
}
|
2836
|
-
|
2837
|
-
break;
|
2838
|
-
case "&":
|
2839
|
-
// {32 bit integer} & -1 => {32 bit integer}
|
2840
|
-
if (
|
2841
|
-
full_mask
|
2842
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
2843
|
-
) {
|
2844
|
-
return non_full_mask_side;
|
2845
|
-
}
|
2846
|
-
|
2847
|
-
break;
|
2848
|
-
case "^":
|
2849
|
-
// {anything} ^ -1 => ~{anything}
|
2850
|
-
if (full_mask) {
|
2851
|
-
return non_full_mask_side.bitwise_negate(compressor.in_32_bit_context());
|
2852
|
-
}
|
2866
|
+
const other_side = (full_mask === self.right ? self.left : self.right);
|
2853
2867
|
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
});
|
2866
|
-
}
|
2868
|
+
// {32 bit integer} & -1 => {32 bit integer}
|
2869
|
+
if (
|
2870
|
+
full_mask
|
2871
|
+
&& self.operator === "&"
|
2872
|
+
&& (
|
2873
|
+
other_side.is_32_bit_integer(compressor)
|
2874
|
+
|| compressor.in_32_bit_context(true)
|
2875
|
+
)
|
2876
|
+
) {
|
2877
|
+
return other_side;
|
2878
|
+
}
|
2867
2879
|
|
2868
|
-
|
2880
|
+
// {anything} ^ -1 => ~{anything}
|
2881
|
+
if (
|
2882
|
+
full_mask
|
2883
|
+
&& self.operator === "^"
|
2884
|
+
&& (
|
2885
|
+
other_side.is_32_bit_integer(compressor)
|
2886
|
+
|| compressor.in_32_bit_context(true)
|
2887
|
+
)
|
2888
|
+
) {
|
2889
|
+
return other_side.bitwise_negate(compressor);
|
2869
2890
|
}
|
2870
2891
|
}
|
2871
2892
|
}
|
@@ -3916,7 +3937,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
3916
3937
|
&& segments[1] instanceof AST_Node
|
3917
3938
|
&& (
|
3918
3939
|
segments[1].is_string(compressor)
|
3919
|
-
|| segments[1].
|
3940
|
+
|| segments[1].is_number_or_bigint(compressor)
|
3920
3941
|
|| is_nullish(segments[1], compressor)
|
3921
3942
|
|| compressor.option("unsafe")
|
3922
3943
|
)
|
@@ -175,18 +175,24 @@ export const unary_side_effects = makePredicate("delete ++ --");
|
|
175
175
|
def_is_number(AST_Node, return_false);
|
176
176
|
def_is_number(AST_Number, return_true);
|
177
177
|
const unary = makePredicate("+ - ~ ++ --");
|
178
|
-
def_is_number(AST_Unary, function() {
|
179
|
-
return unary.has(this.operator) &&
|
178
|
+
def_is_number(AST_Unary, function(compressor) {
|
179
|
+
return unary.has(this.operator) && this.expression.is_number(compressor);
|
180
180
|
});
|
181
181
|
const numeric_ops = makePredicate("- * / % & | ^ << >> >>>");
|
182
182
|
def_is_number(AST_Binary, function(compressor) {
|
183
|
-
|
184
|
-
|
185
|
-
&& this.right.
|
183
|
+
if (this.operator === "+") {
|
184
|
+
// Both sides need to be `number`. Or one is a `number` and the other is number-ish.
|
185
|
+
return this.left.is_number(compressor) && this.right.is_number_or_bigint(compressor)
|
186
|
+
|| this.right.is_number(compressor) && this.left.is_number_or_bigint(compressor);
|
187
|
+
} else if (numeric_ops.has(this.operator)) {
|
188
|
+
return this.left.is_number(compressor) || this.right.is_number(compressor);
|
189
|
+
} else {
|
190
|
+
return false;
|
191
|
+
}
|
186
192
|
});
|
187
193
|
def_is_number(AST_Assign, function(compressor) {
|
188
|
-
return numeric_ops.has(this.operator.slice(0, -1))
|
189
|
-
|
194
|
+
return (this.operator === "=" || numeric_ops.has(this.operator.slice(0, -1)))
|
195
|
+
&& this.right.is_number(compressor);
|
190
196
|
});
|
191
197
|
def_is_number(AST_Sequence, function(compressor) {
|
192
198
|
return this.tail_node().is_number(compressor);
|
@@ -198,19 +204,83 @@ export const unary_side_effects = makePredicate("delete ++ --");
|
|
198
204
|
node.DEFMETHOD("is_number", func);
|
199
205
|
});
|
200
206
|
|
207
|
+
// methods to determine if an expression returns a BigInt
|
208
|
+
(function(def_is_bigint) {
|
209
|
+
def_is_bigint(AST_Node, return_false);
|
210
|
+
def_is_bigint(AST_BigInt, return_true);
|
211
|
+
const unary = makePredicate("+ - ~ ++ --");
|
212
|
+
def_is_bigint(AST_Unary, function(compressor) {
|
213
|
+
return unary.has(this.operator) && this.expression.is_bigint(compressor);
|
214
|
+
});
|
215
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
216
|
+
def_is_bigint(AST_Binary, function(compressor) {
|
217
|
+
if (this.operator === "+") {
|
218
|
+
return this.left.is_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
219
|
+
|| this.right.is_bigint(compressor) && this.left.is_number_or_bigint(compressor);
|
220
|
+
} else if (numeric_ops.has(this.operator)) {
|
221
|
+
return this.left.is_bigint(compressor) || this.right.is_bigint(compressor);
|
222
|
+
} else {
|
223
|
+
return false;
|
224
|
+
}
|
225
|
+
});
|
226
|
+
def_is_bigint(AST_Assign, function(compressor) {
|
227
|
+
return (numeric_ops.has(this.operator.slice(0, -1)) || this.operator == "=")
|
228
|
+
&& this.right.is_bigint(compressor);
|
229
|
+
});
|
230
|
+
def_is_bigint(AST_Sequence, function(compressor) {
|
231
|
+
return this.tail_node().is_bigint(compressor);
|
232
|
+
});
|
233
|
+
def_is_bigint(AST_Conditional, function(compressor) {
|
234
|
+
return this.consequent.is_bigint(compressor) && this.alternative.is_bigint(compressor);
|
235
|
+
});
|
236
|
+
})(function(node, func) {
|
237
|
+
node.DEFMETHOD("is_bigint", func);
|
238
|
+
});
|
239
|
+
|
240
|
+
// methods to determine if an expression is a number or a bigint
|
241
|
+
(function(def_is_number_or_bigint) {
|
242
|
+
def_is_number_or_bigint(AST_Node, return_false);
|
243
|
+
def_is_number_or_bigint(AST_Number, return_true);
|
244
|
+
def_is_number_or_bigint(AST_BigInt, return_true);
|
245
|
+
const numeric_unary_ops = makePredicate("+ - ~ ++ --");
|
246
|
+
def_is_number_or_bigint(AST_Unary, function(_compressor) {
|
247
|
+
return numeric_unary_ops.has(this.operator);
|
248
|
+
});
|
249
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
250
|
+
def_is_number_or_bigint(AST_Binary, function(compressor) {
|
251
|
+
return this.operator === "+"
|
252
|
+
? this.left.is_number_or_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
253
|
+
: numeric_ops.has(this.operator);
|
254
|
+
});
|
255
|
+
def_is_number_or_bigint(AST_Assign, function(compressor) {
|
256
|
+
return numeric_ops.has(this.operator.slice(0, -1))
|
257
|
+
|| this.operator == "=" && this.right.is_number_or_bigint(compressor);
|
258
|
+
});
|
259
|
+
def_is_number_or_bigint(AST_Sequence, function(compressor) {
|
260
|
+
return this.tail_node().is_number_or_bigint(compressor);
|
261
|
+
});
|
262
|
+
def_is_number_or_bigint(AST_Conditional, function(compressor) {
|
263
|
+
return this.consequent.is_number_or_bigint(compressor) && this.alternative.is_number_or_bigint(compressor);
|
264
|
+
});
|
265
|
+
}(function (node, func) {
|
266
|
+
node.DEFMETHOD("is_number_or_bigint", func);
|
267
|
+
}));
|
268
|
+
|
269
|
+
|
201
270
|
// 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
|
202
271
|
(function(def_is_32_bit_integer) {
|
203
272
|
def_is_32_bit_integer(AST_Node, return_false);
|
204
|
-
def_is_32_bit_integer(AST_Number, function() {
|
273
|
+
def_is_32_bit_integer(AST_Number, function(_compressor) {
|
205
274
|
return this.value === (this.value | 0);
|
206
275
|
});
|
207
|
-
def_is_32_bit_integer(AST_UnaryPrefix, function() {
|
208
|
-
return this.operator == "~" ? this.expression.is_number()
|
209
|
-
: this.operator === "+" ? this.expression.is_32_bit_integer()
|
276
|
+
def_is_32_bit_integer(AST_UnaryPrefix, function(compressor) {
|
277
|
+
return this.operator == "~" ? this.expression.is_number(compressor)
|
278
|
+
: this.operator === "+" ? this.expression.is_32_bit_integer(compressor)
|
210
279
|
: false;
|
211
280
|
});
|
212
|
-
def_is_32_bit_integer(AST_Binary, function() {
|
213
|
-
return bitwise_binop.has(this.operator)
|
281
|
+
def_is_32_bit_integer(AST_Binary, function(compressor) {
|
282
|
+
return bitwise_binop.has(this.operator)
|
283
|
+
&& (this.left.is_number(compressor) || this.right.is_number(compressor));
|
214
284
|
});
|
215
285
|
}(function (node, func) {
|
216
286
|
node.DEFMETHOD("is_32_bit_integer", func);
|
@@ -847,30 +917,36 @@ export function is_lhs(node, parent) {
|
|
847
917
|
});
|
848
918
|
|
849
919
|
(function (def_bitwise_negate) {
|
850
|
-
function
|
920
|
+
function basic_bitwise_negation(exp) {
|
851
921
|
return make_node(AST_UnaryPrefix, exp, {
|
852
922
|
operator: "~",
|
853
923
|
expression: exp
|
854
924
|
});
|
855
925
|
}
|
856
926
|
|
857
|
-
def_bitwise_negate(AST_Node, function() {
|
858
|
-
return
|
927
|
+
def_bitwise_negate(AST_Node, function(_compressor) {
|
928
|
+
return basic_bitwise_negation(this);
|
859
929
|
});
|
860
930
|
|
861
|
-
def_bitwise_negate(AST_Number, function() {
|
931
|
+
def_bitwise_negate(AST_Number, function(_compressor) {
|
862
932
|
const neg = ~this.value;
|
863
933
|
if (neg.toString().length > this.value.toString().length) {
|
864
|
-
return
|
934
|
+
return basic_bitwise_negation(this);
|
865
935
|
}
|
866
936
|
return make_node(AST_Number, this, { value: neg });
|
867
937
|
});
|
868
938
|
|
869
|
-
def_bitwise_negate(AST_UnaryPrefix, function(in_32_bit_context) {
|
870
|
-
if (
|
939
|
+
def_bitwise_negate(AST_UnaryPrefix, function(compressor, in_32_bit_context) {
|
940
|
+
if (
|
941
|
+
this.operator == "~"
|
942
|
+
&& (
|
943
|
+
this.expression.is_32_bit_integer(compressor) ||
|
944
|
+
(in_32_bit_context != null ? in_32_bit_context : compressor.in_32_bit_context())
|
945
|
+
)
|
946
|
+
) {
|
871
947
|
return this.expression;
|
872
948
|
} else {
|
873
|
-
return
|
949
|
+
return basic_bitwise_negation(this);
|
874
950
|
}
|
875
951
|
});
|
876
952
|
})(function (node, func) {
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"homepage": "https://terser.org",
|
5
5
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
6
6
|
"license": "BSD-2-Clause",
|
7
|
-
"version": "5.
|
7
|
+
"version": "5.39.1",
|
8
8
|
"engines": {
|
9
9
|
"node": ">=10"
|
10
10
|
},
|
@@ -128,7 +128,8 @@
|
|
128
128
|
"no-unused-vars": [
|
129
129
|
"error",
|
130
130
|
{
|
131
|
-
"varsIgnorePattern": "^_"
|
131
|
+
"varsIgnorePattern": "^_",
|
132
|
+
"argsIgnorePattern": "^_"
|
132
133
|
}
|
133
134
|
],
|
134
135
|
"no-tabs": "error",
|