terser 5.39.0 → 5.39.2
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 +9 -0
- package/README.md +2 -1
- package/dist/bundle.min.js +181 -104
- package/lib/cli.js +1 -1
- package/lib/compress/index.js +76 -72
- package/lib/compress/inference.js +97 -21
- package/lib/parse.js +7 -10
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.39.2
|
4
|
+
|
5
|
+
- Fix crash when parsing bare `yield` inside a template string.
|
6
|
+
- Update internally used acorn version requirement
|
7
|
+
|
8
|
+
## v5.39.1
|
9
|
+
|
10
|
+
- Fix bitwise operations that could mix `BigInt` and `number`
|
11
|
+
|
3
12
|
## v5.39.0
|
4
13
|
|
5
14
|
- Remove unnecessary `console.assert` calls (#1590)
|
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
@@ -843,7 +843,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
843
843
|
} else if (ch == "$" && peek() == "{") {
|
844
844
|
next(true, true);
|
845
845
|
S.brace_counter++;
|
846
|
-
tok = token(begin ? "template_head" : "
|
846
|
+
tok = token(begin ? "template_head" : "template_cont", content);
|
847
847
|
TEMPLATE_RAWS.set(tok, raw);
|
848
848
|
tok.template_end = false;
|
849
849
|
return tok;
|
@@ -860,7 +860,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
860
860
|
content += ch;
|
861
861
|
}
|
862
862
|
S.template_braces.pop();
|
863
|
-
tok = token(begin ? "template_head" : "
|
863
|
+
tok = token(begin ? "template_head" : "template_cont", content);
|
864
864
|
TEMPLATE_RAWS.set(tok, raw);
|
865
865
|
tok.template_end = true;
|
866
866
|
return tok;
|
@@ -2111,11 +2111,6 @@ function parse($TEXT, options) {
|
|
2111
2111
|
}
|
2112
2112
|
|
2113
2113
|
function _yield_expression() {
|
2114
|
-
// Previous token must be keyword yield and not be interpret as an identifier
|
2115
|
-
if (!is_in_generator()) {
|
2116
|
-
croak("Unexpected yield expression outside generator function",
|
2117
|
-
S.prev.line, S.prev.col, S.prev.pos);
|
2118
|
-
}
|
2119
2114
|
var start = S.token;
|
2120
2115
|
var star = false;
|
2121
2116
|
var has_expression = true;
|
@@ -2130,10 +2125,12 @@ function parse($TEXT, options) {
|
|
2130
2125
|
// Note 1: It isn't allowed for yield* to close without an expression
|
2131
2126
|
// Note 2: If there is a nlb between yield and star, it is interpret as
|
2132
2127
|
// yield <explicit undefined> <inserted automatic semicolon> *
|
2133
|
-
if (
|
2134
|
-
(
|
2128
|
+
if (
|
2129
|
+
can_insert_semicolon()
|
2130
|
+
|| is("punc") && PUNC_AFTER_EXPRESSION.has(S.token.value)
|
2131
|
+
|| is("template_cont")
|
2132
|
+
) {
|
2135
2133
|
has_expression = false;
|
2136
|
-
|
2137
2134
|
} else if (is("operator", "*")) {
|
2138
2135
|
star = true;
|
2139
2136
|
next();
|
@@ -13676,18 +13673,24 @@ const unary_side_effects = makePredicate("delete ++ --");
|
|
13676
13673
|
def_is_number(AST_Node, return_false);
|
13677
13674
|
def_is_number(AST_Number, return_true);
|
13678
13675
|
const unary = makePredicate("+ - ~ ++ --");
|
13679
|
-
def_is_number(AST_Unary, function() {
|
13680
|
-
return unary.has(this.operator) &&
|
13676
|
+
def_is_number(AST_Unary, function(compressor) {
|
13677
|
+
return unary.has(this.operator) && this.expression.is_number(compressor);
|
13681
13678
|
});
|
13682
13679
|
const numeric_ops = makePredicate("- * / % & | ^ << >> >>>");
|
13683
13680
|
def_is_number(AST_Binary, function(compressor) {
|
13684
|
-
|
13685
|
-
|
13686
|
-
&& this.right.
|
13681
|
+
if (this.operator === "+") {
|
13682
|
+
// Both sides need to be `number`. Or one is a `number` and the other is number-ish.
|
13683
|
+
return this.left.is_number(compressor) && this.right.is_number_or_bigint(compressor)
|
13684
|
+
|| this.right.is_number(compressor) && this.left.is_number_or_bigint(compressor);
|
13685
|
+
} else if (numeric_ops.has(this.operator)) {
|
13686
|
+
return this.left.is_number(compressor) || this.right.is_number(compressor);
|
13687
|
+
} else {
|
13688
|
+
return false;
|
13689
|
+
}
|
13687
13690
|
});
|
13688
13691
|
def_is_number(AST_Assign, function(compressor) {
|
13689
|
-
return numeric_ops.has(this.operator.slice(0, -1))
|
13690
|
-
|
13692
|
+
return (this.operator === "=" || numeric_ops.has(this.operator.slice(0, -1)))
|
13693
|
+
&& this.right.is_number(compressor);
|
13691
13694
|
});
|
13692
13695
|
def_is_number(AST_Sequence, function(compressor) {
|
13693
13696
|
return this.tail_node().is_number(compressor);
|
@@ -13699,19 +13702,83 @@ const unary_side_effects = makePredicate("delete ++ --");
|
|
13699
13702
|
node.DEFMETHOD("is_number", func);
|
13700
13703
|
});
|
13701
13704
|
|
13705
|
+
// methods to determine if an expression returns a BigInt
|
13706
|
+
(function(def_is_bigint) {
|
13707
|
+
def_is_bigint(AST_Node, return_false);
|
13708
|
+
def_is_bigint(AST_BigInt, return_true);
|
13709
|
+
const unary = makePredicate("+ - ~ ++ --");
|
13710
|
+
def_is_bigint(AST_Unary, function(compressor) {
|
13711
|
+
return unary.has(this.operator) && this.expression.is_bigint(compressor);
|
13712
|
+
});
|
13713
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
13714
|
+
def_is_bigint(AST_Binary, function(compressor) {
|
13715
|
+
if (this.operator === "+") {
|
13716
|
+
return this.left.is_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
13717
|
+
|| this.right.is_bigint(compressor) && this.left.is_number_or_bigint(compressor);
|
13718
|
+
} else if (numeric_ops.has(this.operator)) {
|
13719
|
+
return this.left.is_bigint(compressor) || this.right.is_bigint(compressor);
|
13720
|
+
} else {
|
13721
|
+
return false;
|
13722
|
+
}
|
13723
|
+
});
|
13724
|
+
def_is_bigint(AST_Assign, function(compressor) {
|
13725
|
+
return (numeric_ops.has(this.operator.slice(0, -1)) || this.operator == "=")
|
13726
|
+
&& this.right.is_bigint(compressor);
|
13727
|
+
});
|
13728
|
+
def_is_bigint(AST_Sequence, function(compressor) {
|
13729
|
+
return this.tail_node().is_bigint(compressor);
|
13730
|
+
});
|
13731
|
+
def_is_bigint(AST_Conditional, function(compressor) {
|
13732
|
+
return this.consequent.is_bigint(compressor) && this.alternative.is_bigint(compressor);
|
13733
|
+
});
|
13734
|
+
})(function(node, func) {
|
13735
|
+
node.DEFMETHOD("is_bigint", func);
|
13736
|
+
});
|
13737
|
+
|
13738
|
+
// methods to determine if an expression is a number or a bigint
|
13739
|
+
(function(def_is_number_or_bigint) {
|
13740
|
+
def_is_number_or_bigint(AST_Node, return_false);
|
13741
|
+
def_is_number_or_bigint(AST_Number, return_true);
|
13742
|
+
def_is_number_or_bigint(AST_BigInt, return_true);
|
13743
|
+
const numeric_unary_ops = makePredicate("+ - ~ ++ --");
|
13744
|
+
def_is_number_or_bigint(AST_Unary, function(_compressor) {
|
13745
|
+
return numeric_unary_ops.has(this.operator);
|
13746
|
+
});
|
13747
|
+
const numeric_ops = makePredicate("- * / % & | ^ << >>");
|
13748
|
+
def_is_number_or_bigint(AST_Binary, function(compressor) {
|
13749
|
+
return this.operator === "+"
|
13750
|
+
? this.left.is_number_or_bigint(compressor) && this.right.is_number_or_bigint(compressor)
|
13751
|
+
: numeric_ops.has(this.operator);
|
13752
|
+
});
|
13753
|
+
def_is_number_or_bigint(AST_Assign, function(compressor) {
|
13754
|
+
return numeric_ops.has(this.operator.slice(0, -1))
|
13755
|
+
|| this.operator == "=" && this.right.is_number_or_bigint(compressor);
|
13756
|
+
});
|
13757
|
+
def_is_number_or_bigint(AST_Sequence, function(compressor) {
|
13758
|
+
return this.tail_node().is_number_or_bigint(compressor);
|
13759
|
+
});
|
13760
|
+
def_is_number_or_bigint(AST_Conditional, function(compressor) {
|
13761
|
+
return this.consequent.is_number_or_bigint(compressor) && this.alternative.is_number_or_bigint(compressor);
|
13762
|
+
});
|
13763
|
+
}(function (node, func) {
|
13764
|
+
node.DEFMETHOD("is_number_or_bigint", func);
|
13765
|
+
}));
|
13766
|
+
|
13767
|
+
|
13702
13768
|
// 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
|
13703
13769
|
(function(def_is_32_bit_integer) {
|
13704
13770
|
def_is_32_bit_integer(AST_Node, return_false);
|
13705
|
-
def_is_32_bit_integer(AST_Number, function() {
|
13771
|
+
def_is_32_bit_integer(AST_Number, function(_compressor) {
|
13706
13772
|
return this.value === (this.value | 0);
|
13707
13773
|
});
|
13708
|
-
def_is_32_bit_integer(AST_UnaryPrefix, function() {
|
13709
|
-
return this.operator == "~" ? this.expression.is_number()
|
13710
|
-
: this.operator === "+" ? this.expression.is_32_bit_integer()
|
13774
|
+
def_is_32_bit_integer(AST_UnaryPrefix, function(compressor) {
|
13775
|
+
return this.operator == "~" ? this.expression.is_number(compressor)
|
13776
|
+
: this.operator === "+" ? this.expression.is_32_bit_integer(compressor)
|
13711
13777
|
: false;
|
13712
13778
|
});
|
13713
|
-
def_is_32_bit_integer(AST_Binary, function() {
|
13714
|
-
return bitwise_binop.has(this.operator)
|
13779
|
+
def_is_32_bit_integer(AST_Binary, function(compressor) {
|
13780
|
+
return bitwise_binop.has(this.operator)
|
13781
|
+
&& (this.left.is_number(compressor) || this.right.is_number(compressor));
|
13715
13782
|
});
|
13716
13783
|
}(function (node, func) {
|
13717
13784
|
node.DEFMETHOD("is_32_bit_integer", func);
|
@@ -14348,30 +14415,36 @@ function is_lhs(node, parent) {
|
|
14348
14415
|
});
|
14349
14416
|
|
14350
14417
|
(function (def_bitwise_negate) {
|
14351
|
-
function
|
14418
|
+
function basic_bitwise_negation(exp) {
|
14352
14419
|
return make_node(AST_UnaryPrefix, exp, {
|
14353
14420
|
operator: "~",
|
14354
14421
|
expression: exp
|
14355
14422
|
});
|
14356
14423
|
}
|
14357
14424
|
|
14358
|
-
def_bitwise_negate(AST_Node, function() {
|
14359
|
-
return
|
14425
|
+
def_bitwise_negate(AST_Node, function(_compressor) {
|
14426
|
+
return basic_bitwise_negation(this);
|
14360
14427
|
});
|
14361
14428
|
|
14362
|
-
def_bitwise_negate(AST_Number, function() {
|
14429
|
+
def_bitwise_negate(AST_Number, function(_compressor) {
|
14363
14430
|
const neg = ~this.value;
|
14364
14431
|
if (neg.toString().length > this.value.toString().length) {
|
14365
|
-
return
|
14432
|
+
return basic_bitwise_negation(this);
|
14366
14433
|
}
|
14367
14434
|
return make_node(AST_Number, this, { value: neg });
|
14368
14435
|
});
|
14369
14436
|
|
14370
|
-
def_bitwise_negate(AST_UnaryPrefix, function(in_32_bit_context) {
|
14371
|
-
if (
|
14437
|
+
def_bitwise_negate(AST_UnaryPrefix, function(compressor, in_32_bit_context) {
|
14438
|
+
if (
|
14439
|
+
this.operator == "~"
|
14440
|
+
&& (
|
14441
|
+
this.expression.is_32_bit_integer(compressor) ||
|
14442
|
+
(in_32_bit_context != null ? in_32_bit_context : compressor.in_32_bit_context())
|
14443
|
+
)
|
14444
|
+
) {
|
14372
14445
|
return this.expression;
|
14373
14446
|
} else {
|
14374
|
-
return
|
14447
|
+
return basic_bitwise_negation(this);
|
14375
14448
|
}
|
14376
14449
|
});
|
14377
14450
|
})(function (node, func) {
|
@@ -18908,12 +18981,16 @@ class Compressor extends TreeWalker {
|
|
18908
18981
|
}
|
18909
18982
|
}
|
18910
18983
|
|
18911
|
-
in_32_bit_context() {
|
18984
|
+
in_32_bit_context(other_operand_must_be_number) {
|
18912
18985
|
if (!this.option("evaluate")) return false;
|
18913
18986
|
var self = this.self();
|
18914
18987
|
for (var i = 0, p; p = this.parent(i); i++) {
|
18915
18988
|
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
18916
|
-
|
18989
|
+
if (other_operand_must_be_number) {
|
18990
|
+
return (self === p.left ? p.right : p.left).is_number(this);
|
18991
|
+
} else {
|
18992
|
+
return true;
|
18993
|
+
}
|
18917
18994
|
}
|
18918
18995
|
if (p instanceof AST_UnaryPrefix) {
|
18919
18996
|
return p.operator === "~";
|
@@ -20684,7 +20761,7 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
20684
20761
|
self.operator === "~"
|
20685
20762
|
&& self.expression instanceof AST_UnaryPrefix
|
20686
20763
|
&& self.expression.operator === "~"
|
20687
|
-
&& (compressor.in_32_bit_context() || self.expression.expression.is_32_bit_integer())
|
20764
|
+
&& (compressor.in_32_bit_context(false) || self.expression.expression.is_32_bit_integer(compressor))
|
20688
20765
|
) {
|
20689
20766
|
return self.expression.expression;
|
20690
20767
|
}
|
@@ -20697,9 +20774,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
20697
20774
|
) {
|
20698
20775
|
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
20699
20776
|
// ~(~x ^ y) => x ^ y
|
20700
|
-
e.left = e.left.bitwise_negate(true);
|
20777
|
+
e.left = e.left.bitwise_negate(compressor, true);
|
20701
20778
|
} else {
|
20702
|
-
e.right = e.right.bitwise_negate(true);
|
20779
|
+
e.right = e.right.bitwise_negate(compressor, true);
|
20703
20780
|
}
|
20704
20781
|
return e;
|
20705
20782
|
}
|
@@ -20794,10 +20871,13 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20794
20871
|
case "===":
|
20795
20872
|
case "!==":
|
20796
20873
|
var is_strict_comparison = true;
|
20797
|
-
if (
|
20874
|
+
if (
|
20875
|
+
(self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
20798
20876
|
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
|
20877
|
+
(self.left.is_bigint(compressor) && self.right.is_bigint(compressor)) ||
|
20799
20878
|
(self.left.is_boolean() && self.right.is_boolean()) ||
|
20800
|
-
self.left.equivalent_to(self.right)
|
20879
|
+
self.left.equivalent_to(self.right)
|
20880
|
+
) {
|
20801
20881
|
self.operator = self.operator.substr(0, 2);
|
20802
20882
|
}
|
20803
20883
|
|
@@ -20842,7 +20922,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20842
20922
|
&& self.left.definition() === self.right.definition()
|
20843
20923
|
&& is_object(self.left.fixed_value())) {
|
20844
20924
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
20845
|
-
} else if (self.left.is_32_bit_integer() && self.right.is_32_bit_integer()) {
|
20925
|
+
} else if (self.left.is_32_bit_integer(compressor) && self.right.is_32_bit_integer(compressor)) {
|
20846
20926
|
const not = node => make_node(AST_UnaryPrefix, node, {
|
20847
20927
|
operator: "!",
|
20848
20928
|
expression: node
|
@@ -20875,7 +20955,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
20875
20955
|
&& (mask = and_op === self.left ? self.right : self.left)
|
20876
20956
|
&& and_op.operator === "&"
|
20877
20957
|
&& mask instanceof AST_Number
|
20878
|
-
&& mask.is_32_bit_integer()
|
20958
|
+
&& mask.is_32_bit_integer(compressor)
|
20879
20959
|
&& (x =
|
20880
20960
|
and_op.left.equivalent_to(mask) ? and_op.right
|
20881
20961
|
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
@@ -21118,7 +21198,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21118
21198
|
// a + -b => a - b
|
21119
21199
|
if (self.right instanceof AST_UnaryPrefix
|
21120
21200
|
&& self.right.operator == "-"
|
21121
|
-
&& self.left.
|
21201
|
+
&& self.left.is_number_or_bigint(compressor)) {
|
21122
21202
|
self = make_node(AST_Binary, self, {
|
21123
21203
|
operator: "-",
|
21124
21204
|
left: self.left,
|
@@ -21130,7 +21210,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21130
21210
|
if (self.left instanceof AST_UnaryPrefix
|
21131
21211
|
&& self.left.operator == "-"
|
21132
21212
|
&& reversible()
|
21133
|
-
&& self.right.
|
21213
|
+
&& self.right.is_number_or_bigint(compressor)) {
|
21134
21214
|
self = make_node(AST_Binary, self, {
|
21135
21215
|
operator: "-",
|
21136
21216
|
left: self.right,
|
@@ -21174,8 +21254,9 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21174
21254
|
case "|":
|
21175
21255
|
case "^":
|
21176
21256
|
// a + +b => +b + a
|
21177
|
-
if (
|
21178
|
-
|
21257
|
+
if (
|
21258
|
+
self.left.is_number_or_bigint(compressor)
|
21259
|
+
&& self.right.is_number_or_bigint(compressor)
|
21179
21260
|
&& reversible()
|
21180
21261
|
&& !(self.left instanceof AST_Binary
|
21181
21262
|
&& self.left.operator != self.operator
|
@@ -21192,7 +21273,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21192
21273
|
self = best_of(compressor, self, reversed);
|
21193
21274
|
}
|
21194
21275
|
}
|
21195
|
-
if (associative && self.
|
21276
|
+
if (associative && self.is_number_or_bigint(compressor)) {
|
21196
21277
|
// a + (b + c) => (a + b) + c
|
21197
21278
|
if (self.right instanceof AST_Binary
|
21198
21279
|
&& self.right.operator == self.operator) {
|
@@ -21311,18 +21392,31 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21311
21392
|
}
|
21312
21393
|
}
|
21313
21394
|
|
21314
|
-
// x ^ x => 0
|
21315
21395
|
// x | x => 0 | x
|
21316
21396
|
// x & x => 0 | x
|
21317
|
-
|
21318
|
-
|
21319
|
-
|
21320
|
-
|
21321
|
-
|
21322
|
-
|
21323
|
-
|
21324
|
-
|
21325
|
-
|
21397
|
+
if (
|
21398
|
+
(self.operator === "|" || self.operator === "&")
|
21399
|
+
&& self.left.equivalent_to(self.right)
|
21400
|
+
&& !self.left.has_side_effects(compressor)
|
21401
|
+
&& compressor.in_32_bit_context(true)
|
21402
|
+
) {
|
21403
|
+
self.left = make_node(AST_Number, self, { value: 0 });
|
21404
|
+
self.operator = "|";
|
21405
|
+
}
|
21406
|
+
|
21407
|
+
// ~x ^ ~y => x ^ y
|
21408
|
+
if (
|
21409
|
+
self.operator === "^"
|
21410
|
+
&& self.left instanceof AST_UnaryPrefix
|
21411
|
+
&& self.left.operator === "~"
|
21412
|
+
&& self.right instanceof AST_UnaryPrefix
|
21413
|
+
&& self.right.operator === "~"
|
21414
|
+
) {
|
21415
|
+
self = make_node(AST_Binary, self, {
|
21416
|
+
operator: "^",
|
21417
|
+
left: self.left.expression,
|
21418
|
+
right: self.right.expression
|
21419
|
+
});
|
21326
21420
|
}
|
21327
21421
|
|
21328
21422
|
|
@@ -21346,7 +21440,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21346
21440
|
if (
|
21347
21441
|
zero_side
|
21348
21442
|
&& (self.operator === "|" || self.operator === "^")
|
21349
|
-
&& (non_zero_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21443
|
+
&& (non_zero_side.is_32_bit_integer(compressor) || compressor.in_32_bit_context(true))
|
21350
21444
|
) {
|
21351
21445
|
return non_zero_side;
|
21352
21446
|
}
|
@@ -21356,65 +21450,48 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
21356
21450
|
zero_side
|
21357
21451
|
&& self.operator === "&"
|
21358
21452
|
&& !non_zero_side.has_side_effects(compressor)
|
21453
|
+
&& non_zero_side.is_32_bit_integer(compressor)
|
21359
21454
|
) {
|
21360
21455
|
return zero_side;
|
21361
21456
|
}
|
21362
21457
|
|
21458
|
+
// ~0 is all ones, as well as -1.
|
21459
|
+
// We can ellide some operations with it.
|
21363
21460
|
const is_full_mask = (node) =>
|
21364
21461
|
node instanceof AST_Number && node.value === -1
|
21365
21462
|
||
|
21366
|
-
node instanceof AST_UnaryPrefix
|
21367
|
-
|
21368
|
-
|
21369
|
-
|
21370
|
-
|| node.operator === "~"
|
21371
|
-
&& node.expression instanceof AST_Number
|
21372
|
-
&& node.expression.value === 0);
|
21463
|
+
node instanceof AST_UnaryPrefix
|
21464
|
+
&& node.operator === "-"
|
21465
|
+
&& node.expression instanceof AST_Number
|
21466
|
+
&& node.expression.value === 1;
|
21373
21467
|
|
21374
21468
|
const full_mask = is_full_mask(self.right) ? self.right
|
21375
21469
|
: is_full_mask(self.left) ? self.left
|
21376
21470
|
: null;
|
21377
|
-
const
|
21378
|
-
|
21379
|
-
switch (self.operator) {
|
21380
|
-
case "|":
|
21381
|
-
// {anything} | -1 => -1
|
21382
|
-
if (full_mask && !non_full_mask_side.has_side_effects(compressor)) {
|
21383
|
-
return full_mask;
|
21384
|
-
}
|
21385
|
-
|
21386
|
-
break;
|
21387
|
-
case "&":
|
21388
|
-
// {32 bit integer} & -1 => {32 bit integer}
|
21389
|
-
if (
|
21390
|
-
full_mask
|
21391
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
21392
|
-
) {
|
21393
|
-
return non_full_mask_side;
|
21394
|
-
}
|
21395
|
-
|
21396
|
-
break;
|
21397
|
-
case "^":
|
21398
|
-
// {anything} ^ -1 => ~{anything}
|
21399
|
-
if (full_mask) {
|
21400
|
-
return non_full_mask_side.bitwise_negate(compressor.in_32_bit_context());
|
21401
|
-
}
|
21471
|
+
const other_side = (full_mask === self.right ? self.left : self.right);
|
21402
21472
|
|
21403
|
-
|
21404
|
-
|
21405
|
-
|
21406
|
-
|
21407
|
-
|
21408
|
-
|
21409
|
-
|
21410
|
-
|
21411
|
-
|
21412
|
-
|
21413
|
-
|
21414
|
-
});
|
21415
|
-
}
|
21473
|
+
// {32 bit integer} & -1 => {32 bit integer}
|
21474
|
+
if (
|
21475
|
+
full_mask
|
21476
|
+
&& self.operator === "&"
|
21477
|
+
&& (
|
21478
|
+
other_side.is_32_bit_integer(compressor)
|
21479
|
+
|| compressor.in_32_bit_context(true)
|
21480
|
+
)
|
21481
|
+
) {
|
21482
|
+
return other_side;
|
21483
|
+
}
|
21416
21484
|
|
21417
|
-
|
21485
|
+
// {anything} ^ -1 => ~{anything}
|
21486
|
+
if (
|
21487
|
+
full_mask
|
21488
|
+
&& self.operator === "^"
|
21489
|
+
&& (
|
21490
|
+
other_side.is_32_bit_integer(compressor)
|
21491
|
+
|| compressor.in_32_bit_context(true)
|
21492
|
+
)
|
21493
|
+
) {
|
21494
|
+
return other_side.bitwise_negate(compressor);
|
21418
21495
|
}
|
21419
21496
|
}
|
21420
21497
|
}
|
@@ -22465,7 +22542,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
22465
22542
|
&& segments[1] instanceof AST_Node
|
22466
22543
|
&& (
|
22467
22544
|
segments[1].is_string(compressor)
|
22468
|
-
|| segments[1].
|
22545
|
+
|| segments[1].is_number_or_bigint(compressor)
|
22469
22546
|
|| is_nullish(segments[1], compressor)
|
22470
22547
|
|| compressor.option("unsafe")
|
22471
22548
|
)
|
@@ -32757,7 +32834,7 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
32757
32834
|
if (program.parse.acorn) {
|
32758
32835
|
files = convert_ast(function(toplevel, name) {
|
32759
32836
|
return require("acorn").parse(files[name], {
|
32760
|
-
ecmaVersion:
|
32837
|
+
ecmaVersion: 2024,
|
32761
32838
|
locations: true,
|
32762
32839
|
program: toplevel,
|
32763
32840
|
sourceFile: name,
|
package/lib/cli.js
CHANGED
@@ -202,7 +202,7 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
202
202
|
if (program.parse.acorn) {
|
203
203
|
files = convert_ast(function(toplevel, name) {
|
204
204
|
return require("acorn").parse(files[name], {
|
205
|
-
ecmaVersion:
|
205
|
+
ecmaVersion: 2024,
|
206
206
|
locations: true,
|
207
207
|
program: toplevel,
|
208
208
|
sourceFile: name,
|
package/lib/compress/index.js
CHANGED
@@ -376,12 +376,16 @@ class Compressor extends TreeWalker {
|
|
376
376
|
}
|
377
377
|
}
|
378
378
|
|
379
|
-
in_32_bit_context() {
|
379
|
+
in_32_bit_context(other_operand_must_be_number) {
|
380
380
|
if (!this.option("evaluate")) return false;
|
381
381
|
var self = this.self();
|
382
382
|
for (var i = 0, p; p = this.parent(i); i++) {
|
383
383
|
if (p instanceof AST_Binary && bitwise_binop.has(p.operator)) {
|
384
|
-
|
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
|
+
}
|
385
389
|
}
|
386
390
|
if (p instanceof AST_UnaryPrefix) {
|
387
391
|
return p.operator === "~";
|
@@ -2152,7 +2156,7 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
2152
2156
|
self.operator === "~"
|
2153
2157
|
&& self.expression instanceof AST_UnaryPrefix
|
2154
2158
|
&& self.expression.operator === "~"
|
2155
|
-
&& (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))
|
2156
2160
|
) {
|
2157
2161
|
return self.expression.expression;
|
2158
2162
|
}
|
@@ -2165,9 +2169,9 @@ def_optimize(AST_UnaryPrefix, function(self, compressor) {
|
|
2165
2169
|
) {
|
2166
2170
|
if (e.left instanceof AST_UnaryPrefix && e.left.operator === "~") {
|
2167
2171
|
// ~(~x ^ y) => x ^ y
|
2168
|
-
e.left = e.left.bitwise_negate(true);
|
2172
|
+
e.left = e.left.bitwise_negate(compressor, true);
|
2169
2173
|
} else {
|
2170
|
-
e.right = e.right.bitwise_negate(true);
|
2174
|
+
e.right = e.right.bitwise_negate(compressor, true);
|
2171
2175
|
}
|
2172
2176
|
return e;
|
2173
2177
|
}
|
@@ -2262,10 +2266,13 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2262
2266
|
case "===":
|
2263
2267
|
case "!==":
|
2264
2268
|
var is_strict_comparison = true;
|
2265
|
-
if (
|
2269
|
+
if (
|
2270
|
+
(self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
2266
2271
|
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
|
2272
|
+
(self.left.is_bigint(compressor) && self.right.is_bigint(compressor)) ||
|
2267
2273
|
(self.left.is_boolean() && self.right.is_boolean()) ||
|
2268
|
-
self.left.equivalent_to(self.right)
|
2274
|
+
self.left.equivalent_to(self.right)
|
2275
|
+
) {
|
2269
2276
|
self.operator = self.operator.substr(0, 2);
|
2270
2277
|
}
|
2271
2278
|
|
@@ -2310,7 +2317,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2310
2317
|
&& self.left.definition() === self.right.definition()
|
2311
2318
|
&& is_object(self.left.fixed_value())) {
|
2312
2319
|
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
|
2313
|
-
} 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)) {
|
2314
2321
|
const not = node => make_node(AST_UnaryPrefix, node, {
|
2315
2322
|
operator: "!",
|
2316
2323
|
expression: node
|
@@ -2343,7 +2350,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2343
2350
|
&& (mask = and_op === self.left ? self.right : self.left)
|
2344
2351
|
&& and_op.operator === "&"
|
2345
2352
|
&& mask instanceof AST_Number
|
2346
|
-
&& mask.is_32_bit_integer()
|
2353
|
+
&& mask.is_32_bit_integer(compressor)
|
2347
2354
|
&& (x =
|
2348
2355
|
and_op.left.equivalent_to(mask) ? and_op.right
|
2349
2356
|
: and_op.right.equivalent_to(mask) ? and_op.left : null)
|
@@ -2586,7 +2593,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2586
2593
|
// a + -b => a - b
|
2587
2594
|
if (self.right instanceof AST_UnaryPrefix
|
2588
2595
|
&& self.right.operator == "-"
|
2589
|
-
&& self.left.
|
2596
|
+
&& self.left.is_number_or_bigint(compressor)) {
|
2590
2597
|
self = make_node(AST_Binary, self, {
|
2591
2598
|
operator: "-",
|
2592
2599
|
left: self.left,
|
@@ -2598,7 +2605,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2598
2605
|
if (self.left instanceof AST_UnaryPrefix
|
2599
2606
|
&& self.left.operator == "-"
|
2600
2607
|
&& reversible()
|
2601
|
-
&& self.right.
|
2608
|
+
&& self.right.is_number_or_bigint(compressor)) {
|
2602
2609
|
self = make_node(AST_Binary, self, {
|
2603
2610
|
operator: "-",
|
2604
2611
|
left: self.right,
|
@@ -2642,8 +2649,9 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2642
2649
|
case "|":
|
2643
2650
|
case "^":
|
2644
2651
|
// a + +b => +b + a
|
2645
|
-
if (
|
2646
|
-
|
2652
|
+
if (
|
2653
|
+
self.left.is_number_or_bigint(compressor)
|
2654
|
+
&& self.right.is_number_or_bigint(compressor)
|
2647
2655
|
&& reversible()
|
2648
2656
|
&& !(self.left instanceof AST_Binary
|
2649
2657
|
&& self.left.operator != self.operator
|
@@ -2660,7 +2668,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2660
2668
|
self = best_of(compressor, self, reversed);
|
2661
2669
|
}
|
2662
2670
|
}
|
2663
|
-
if (associative && self.
|
2671
|
+
if (associative && self.is_number_or_bigint(compressor)) {
|
2664
2672
|
// a + (b + c) => (a + b) + c
|
2665
2673
|
if (self.right instanceof AST_Binary
|
2666
2674
|
&& self.right.operator == self.operator) {
|
@@ -2779,18 +2787,31 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2779
2787
|
}
|
2780
2788
|
}
|
2781
2789
|
|
2782
|
-
// x ^ x => 0
|
2783
2790
|
// x | x => 0 | x
|
2784
2791
|
// x & x => 0 | x
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
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
|
+
});
|
2794
2815
|
}
|
2795
2816
|
|
2796
2817
|
|
@@ -2814,7 +2835,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2814
2835
|
if (
|
2815
2836
|
zero_side
|
2816
2837
|
&& (self.operator === "|" || self.operator === "^")
|
2817
|
-
&& (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))
|
2818
2839
|
) {
|
2819
2840
|
return non_zero_side;
|
2820
2841
|
}
|
@@ -2824,65 +2845,48 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
2824
2845
|
zero_side
|
2825
2846
|
&& self.operator === "&"
|
2826
2847
|
&& !non_zero_side.has_side_effects(compressor)
|
2848
|
+
&& non_zero_side.is_32_bit_integer(compressor)
|
2827
2849
|
) {
|
2828
2850
|
return zero_side;
|
2829
2851
|
}
|
2830
2852
|
|
2853
|
+
// ~0 is all ones, as well as -1.
|
2854
|
+
// We can ellide some operations with it.
|
2831
2855
|
const is_full_mask = (node) =>
|
2832
2856
|
node instanceof AST_Number && node.value === -1
|
2833
2857
|
||
|
2834
|
-
node instanceof AST_UnaryPrefix
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|| node.operator === "~"
|
2839
|
-
&& node.expression instanceof AST_Number
|
2840
|
-
&& node.expression.value === 0);
|
2858
|
+
node instanceof AST_UnaryPrefix
|
2859
|
+
&& node.operator === "-"
|
2860
|
+
&& node.expression instanceof AST_Number
|
2861
|
+
&& node.expression.value === 1;
|
2841
2862
|
|
2842
2863
|
const full_mask = is_full_mask(self.right) ? self.right
|
2843
2864
|
: is_full_mask(self.left) ? self.left
|
2844
2865
|
: null;
|
2845
|
-
const
|
2866
|
+
const other_side = (full_mask === self.right ? self.left : self.right);
|
2846
2867
|
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
full_mask
|
2859
|
-
&& (non_full_mask_side.is_32_bit_integer() || compressor.in_32_bit_context())
|
2860
|
-
) {
|
2861
|
-
return non_full_mask_side;
|
2862
|
-
}
|
2863
|
-
|
2864
|
-
break;
|
2865
|
-
case "^":
|
2866
|
-
// {anything} ^ -1 => ~{anything}
|
2867
|
-
if (full_mask) {
|
2868
|
-
return non_full_mask_side.bitwise_negate(compressor.in_32_bit_context());
|
2869
|
-
}
|
2870
|
-
|
2871
|
-
// ~x ^ ~y => x ^ y
|
2872
|
-
if (
|
2873
|
-
self.left instanceof AST_UnaryPrefix
|
2874
|
-
&& self.left.operator === "~"
|
2875
|
-
&& self.right instanceof AST_UnaryPrefix
|
2876
|
-
&& self.right.operator === "~"
|
2877
|
-
) {
|
2878
|
-
self = make_node(AST_Binary, self, {
|
2879
|
-
operator: "^",
|
2880
|
-
left: self.left.expression,
|
2881
|
-
right: self.right.expression
|
2882
|
-
});
|
2883
|
-
}
|
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
|
+
}
|
2884
2879
|
|
2885
|
-
|
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);
|
2886
2890
|
}
|
2887
2891
|
}
|
2888
2892
|
}
|
@@ -3933,7 +3937,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
3933
3937
|
&& segments[1] instanceof AST_Node
|
3934
3938
|
&& (
|
3935
3939
|
segments[1].is_string(compressor)
|
3936
|
-
|| segments[1].
|
3940
|
+
|| segments[1].is_number_or_bigint(compressor)
|
3937
3941
|
|| is_nullish(segments[1], compressor)
|
3938
3942
|
|| compressor.option("unsafe")
|
3939
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/lib/parse.js
CHANGED
@@ -698,7 +698,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
698
698
|
} else if (ch == "$" && peek() == "{") {
|
699
699
|
next(true, true);
|
700
700
|
S.brace_counter++;
|
701
|
-
tok = token(begin ? "template_head" : "
|
701
|
+
tok = token(begin ? "template_head" : "template_cont", content);
|
702
702
|
TEMPLATE_RAWS.set(tok, raw);
|
703
703
|
tok.template_end = false;
|
704
704
|
return tok;
|
@@ -715,7 +715,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
715
715
|
content += ch;
|
716
716
|
}
|
717
717
|
S.template_braces.pop();
|
718
|
-
tok = token(begin ? "template_head" : "
|
718
|
+
tok = token(begin ? "template_head" : "template_cont", content);
|
719
719
|
TEMPLATE_RAWS.set(tok, raw);
|
720
720
|
tok.template_end = true;
|
721
721
|
return tok;
|
@@ -1966,11 +1966,6 @@ function parse($TEXT, options) {
|
|
1966
1966
|
}
|
1967
1967
|
|
1968
1968
|
function _yield_expression() {
|
1969
|
-
// Previous token must be keyword yield and not be interpret as an identifier
|
1970
|
-
if (!is_in_generator()) {
|
1971
|
-
croak("Unexpected yield expression outside generator function",
|
1972
|
-
S.prev.line, S.prev.col, S.prev.pos);
|
1973
|
-
}
|
1974
1969
|
var start = S.token;
|
1975
1970
|
var star = false;
|
1976
1971
|
var has_expression = true;
|
@@ -1985,10 +1980,12 @@ function parse($TEXT, options) {
|
|
1985
1980
|
// Note 1: It isn't allowed for yield* to close without an expression
|
1986
1981
|
// Note 2: If there is a nlb between yield and star, it is interpret as
|
1987
1982
|
// yield <explicit undefined> <inserted automatic semicolon> *
|
1988
|
-
if (
|
1989
|
-
(
|
1983
|
+
if (
|
1984
|
+
can_insert_semicolon()
|
1985
|
+
|| is("punc") && PUNC_AFTER_EXPRESSION.has(S.token.value)
|
1986
|
+
|| is("template_cont")
|
1987
|
+
) {
|
1990
1988
|
has_expression = false;
|
1991
|
-
|
1992
1989
|
} else if (is("operator", "*")) {
|
1993
1990
|
star = true;
|
1994
1991
|
next();
|
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.39.
|
7
|
+
"version": "5.39.2",
|
8
8
|
"engines": {
|
9
9
|
"node": ">=10"
|
10
10
|
},
|
@@ -45,7 +45,7 @@
|
|
45
45
|
],
|
46
46
|
"dependencies": {
|
47
47
|
"@jridgewell/source-map": "^0.3.3",
|
48
|
-
"acorn": "^8.
|
48
|
+
"acorn": "^8.14.0",
|
49
49
|
"commander": "^2.20.0",
|
50
50
|
"source-map-support": "~0.5.20"
|
51
51
|
},
|
@@ -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",
|