terser 5.0.0-beta.2 → 5.2.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 +39 -3
- package/README.md +2 -5
- package/dist/bundle.min.js +449 -129
- package/dist/bundle.min.js.map +1 -1
- package/lib/ast.js +28 -4
- package/lib/cli.js +2 -1
- package/lib/compress/index.js +224 -87
- package/lib/equivalent-to.js +3 -0
- package/lib/minify.js +5 -1
- package/lib/mozilla-ast.js +40 -3
- package/lib/output.js +18 -3
- package/lib/parse.js +118 -25
- package/lib/propmangle.js +5 -0
- package/lib/size.js +16 -5
- package/package.json +6 -2
- package/tools/terser.d.ts +2 -3
package/dist/bundle.min.js
CHANGED
@@ -565,6 +565,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
565
565
|
|
566
566
|
function peek() { return get_full_char(S.text, S.pos); }
|
567
567
|
|
568
|
+
// Used because parsing ?. involves a lookahead for a digit
|
569
|
+
function is_option_chain_op() {
|
570
|
+
const must_be_dot = S.text.charCodeAt(S.pos + 1) === 46;
|
571
|
+
if (!must_be_dot) return false;
|
572
|
+
|
573
|
+
const cannot_be_digit = S.text.charCodeAt(S.pos + 2);
|
574
|
+
return cannot_be_digit < 48 || cannot_be_digit > 57;
|
575
|
+
}
|
576
|
+
|
568
577
|
function next(signal_eof, in_string) {
|
569
578
|
var ch = get_full_char(S.text, S.pos++);
|
570
579
|
if (signal_eof && !ch)
|
@@ -625,7 +634,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
625
634
|
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION.has(value)) ||
|
626
635
|
(type == "punc" && PUNC_BEFORE_EXPRESSION.has(value))) ||
|
627
636
|
(type == "arrow");
|
628
|
-
if (type == "punc" && value == ".") {
|
637
|
+
if (type == "punc" && (value == "." || value == "?.")) {
|
629
638
|
prev_was_dot = true;
|
630
639
|
} else if (!is_comment) {
|
631
640
|
prev_was_dot = false;
|
@@ -672,12 +681,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
672
681
|
}
|
673
682
|
|
674
683
|
function read_num(prefix) {
|
675
|
-
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".", is_big_int = false;
|
684
|
+
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".", is_big_int = false, numeric_separator = false;
|
676
685
|
var num = read_while(function(ch, i) {
|
677
686
|
if (is_big_int) return false;
|
678
687
|
|
679
688
|
var code = ch.charCodeAt(0);
|
680
689
|
switch (code) {
|
690
|
+
case 95: // _
|
691
|
+
return (numeric_separator = true);
|
681
692
|
case 98: case 66: // bB
|
682
693
|
return (has_x = true); // Can occur in hex sequence, don't return false yet
|
683
694
|
case 111: case 79: // oO
|
@@ -705,6 +716,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
705
716
|
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
706
717
|
parse_error("Legacy octal literals are not allowed in strict mode");
|
707
718
|
}
|
719
|
+
if (numeric_separator) {
|
720
|
+
if (num.endsWith("_")) {
|
721
|
+
parse_error("Numeric separators are not allowed at the end of numeric literals");
|
722
|
+
} else if (num.includes("__")) {
|
723
|
+
parse_error("Only one underscore is allowed as numeric separator");
|
724
|
+
}
|
725
|
+
num = num.replace(/_/g, "");
|
726
|
+
}
|
708
727
|
if (num.endsWith("n")) {
|
709
728
|
const without_n = num.slice(0, -1);
|
710
729
|
const allow_e = RE_HEX_NUMBER.test(without_n);
|
@@ -1051,6 +1070,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
1051
1070
|
return tok;
|
1052
1071
|
}
|
1053
1072
|
case 61: return handle_eq_sign();
|
1073
|
+
case 63: {
|
1074
|
+
if (!is_option_chain_op()) break; // Handled below
|
1075
|
+
|
1076
|
+
next(); // ?
|
1077
|
+
next(); // .
|
1078
|
+
|
1079
|
+
return token("punc", "?.");
|
1080
|
+
}
|
1054
1081
|
case 96: return read_template_characters(true);
|
1055
1082
|
case 123:
|
1056
1083
|
S.brace_counter++;
|
@@ -1169,7 +1196,7 @@ function parse($TEXT, options) {
|
|
1169
1196
|
|
1170
1197
|
options = defaults(options, {
|
1171
1198
|
bare_returns : false,
|
1172
|
-
ecma :
|
1199
|
+
ecma : null, // Legacy
|
1173
1200
|
expression : false,
|
1174
1201
|
filename : null,
|
1175
1202
|
html5_comments : true,
|
@@ -1277,7 +1304,7 @@ function parse($TEXT, options) {
|
|
1277
1304
|
}
|
1278
1305
|
|
1279
1306
|
function embed_tokens(parser) {
|
1280
|
-
return function(...args) {
|
1307
|
+
return function _embed_tokens_wrapper(...args) {
|
1281
1308
|
const start = S.token;
|
1282
1309
|
const expr = parser(...args);
|
1283
1310
|
expr.start = start;
|
@@ -1293,7 +1320,7 @@ function parse($TEXT, options) {
|
|
1293
1320
|
}
|
1294
1321
|
}
|
1295
1322
|
|
1296
|
-
var statement = embed_tokens(function(is_export_default, is_for_body, is_if_body) {
|
1323
|
+
var statement = embed_tokens(function statement(is_export_default, is_for_body, is_if_body) {
|
1297
1324
|
handle_regexp();
|
1298
1325
|
switch (S.token.type) {
|
1299
1326
|
case "string":
|
@@ -1328,7 +1355,7 @@ function parse($TEXT, options) {
|
|
1328
1355
|
}
|
1329
1356
|
return function_(AST_Defun, false, true, is_export_default);
|
1330
1357
|
}
|
1331
|
-
if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
|
1358
|
+
if (S.token.value == "import" && !is_token(peek(), "punc", "(") && !is_token(peek(), "punc", ".")) {
|
1332
1359
|
next();
|
1333
1360
|
var node = import_();
|
1334
1361
|
semicolon();
|
@@ -1749,7 +1776,6 @@ function parse($TEXT, options) {
|
|
1749
1776
|
|
1750
1777
|
if (!is("punc", ")")) {
|
1751
1778
|
expect(",");
|
1752
|
-
if (is("punc", ")") && options.ecma < 2017) unexpected();
|
1753
1779
|
}
|
1754
1780
|
|
1755
1781
|
if (param instanceof AST_Expansion) {
|
@@ -1994,7 +2020,6 @@ function parse($TEXT, options) {
|
|
1994
2020
|
if (!is("punc", ")")) {
|
1995
2021
|
expect(",");
|
1996
2022
|
if (is("punc", ")")) {
|
1997
|
-
if (options.ecma < 2017) unexpected();
|
1998
2023
|
trailing_comma = prev();
|
1999
2024
|
if (maybe_sequence) invalid_sequence = trailing_comma;
|
2000
2025
|
}
|
@@ -2263,7 +2288,7 @@ function parse($TEXT, options) {
|
|
2263
2288
|
var newexp = expr_atom(false), args;
|
2264
2289
|
if (is("punc", "(")) {
|
2265
2290
|
next();
|
2266
|
-
args = expr_list(")",
|
2291
|
+
args = expr_list(")", true);
|
2267
2292
|
} else {
|
2268
2293
|
args = [];
|
2269
2294
|
}
|
@@ -2376,6 +2401,9 @@ function parse($TEXT, options) {
|
|
2376
2401
|
if (is("operator", "new")) {
|
2377
2402
|
return new_(allow_calls);
|
2378
2403
|
}
|
2404
|
+
if (is("operator", "import")) {
|
2405
|
+
return import_meta();
|
2406
|
+
}
|
2379
2407
|
var start = S.token;
|
2380
2408
|
var peeked;
|
2381
2409
|
var async = is("name", "async")
|
@@ -2753,6 +2781,7 @@ function parse($TEXT, options) {
|
|
2753
2781
|
|
2754
2782
|
function import_() {
|
2755
2783
|
var start = prev();
|
2784
|
+
|
2756
2785
|
var imported_name;
|
2757
2786
|
var imported_names;
|
2758
2787
|
if (is("name")) {
|
@@ -2787,6 +2816,17 @@ function parse($TEXT, options) {
|
|
2787
2816
|
});
|
2788
2817
|
}
|
2789
2818
|
|
2819
|
+
function import_meta() {
|
2820
|
+
var start = S.token;
|
2821
|
+
expect_token("operator", "import");
|
2822
|
+
expect_token("punc", ".");
|
2823
|
+
expect_token("name", "meta");
|
2824
|
+
return subscripts(new AST_ImportMeta({
|
2825
|
+
start: start,
|
2826
|
+
end: prev()
|
2827
|
+
}), false);
|
2828
|
+
}
|
2829
|
+
|
2790
2830
|
function map_name(is_import) {
|
2791
2831
|
function make_symbol(type) {
|
2792
2832
|
return new type({
|
@@ -2967,15 +3007,6 @@ function parse($TEXT, options) {
|
|
2967
3007
|
}
|
2968
3008
|
/* falls through */
|
2969
3009
|
case "name":
|
2970
|
-
if (tmp.value == "yield") {
|
2971
|
-
if (is_in_generator()) {
|
2972
|
-
token_error(tmp, "Yield cannot be used as identifier inside generators");
|
2973
|
-
} else if (!is_token(peek(), "punc", ":")
|
2974
|
-
&& !is_token(peek(), "punc", "(")
|
2975
|
-
&& S.input.has_directive("use strict")) {
|
2976
|
-
token_error(tmp, "Unexpected yield identifier inside strict mode");
|
2977
|
-
}
|
2978
|
-
}
|
2979
3010
|
case "string":
|
2980
3011
|
case "num":
|
2981
3012
|
case "big_int":
|
@@ -3057,16 +3088,17 @@ function parse($TEXT, options) {
|
|
3057
3088
|
}
|
3058
3089
|
}
|
3059
3090
|
|
3060
|
-
var subscripts = function(expr, allow_calls) {
|
3091
|
+
var subscripts = function(expr, allow_calls, is_chain) {
|
3061
3092
|
var start = expr.start;
|
3062
3093
|
if (is("punc", ".")) {
|
3063
3094
|
next();
|
3064
3095
|
return subscripts(new AST_Dot({
|
3065
3096
|
start : start,
|
3066
3097
|
expression : expr,
|
3098
|
+
optional : false,
|
3067
3099
|
property : as_name(),
|
3068
3100
|
end : prev()
|
3069
|
-
}), allow_calls);
|
3101
|
+
}), allow_calls, is_chain);
|
3070
3102
|
}
|
3071
3103
|
if (is("punc", "[")) {
|
3072
3104
|
next();
|
@@ -3075,22 +3107,80 @@ function parse($TEXT, options) {
|
|
3075
3107
|
return subscripts(new AST_Sub({
|
3076
3108
|
start : start,
|
3077
3109
|
expression : expr,
|
3110
|
+
optional : false,
|
3078
3111
|
property : prop,
|
3079
3112
|
end : prev()
|
3080
|
-
}), allow_calls);
|
3113
|
+
}), allow_calls, is_chain);
|
3081
3114
|
}
|
3082
3115
|
if (allow_calls && is("punc", "(")) {
|
3083
3116
|
next();
|
3084
3117
|
var call = new AST_Call({
|
3085
3118
|
start : start,
|
3086
3119
|
expression : expr,
|
3120
|
+
optional : false,
|
3087
3121
|
args : call_args(),
|
3088
3122
|
end : prev()
|
3089
3123
|
});
|
3090
3124
|
annotate(call);
|
3091
|
-
return subscripts(call, true);
|
3125
|
+
return subscripts(call, true, is_chain);
|
3126
|
+
}
|
3127
|
+
|
3128
|
+
if (is("punc", "?.")) {
|
3129
|
+
next();
|
3130
|
+
|
3131
|
+
let chain_contents;
|
3132
|
+
|
3133
|
+
if (allow_calls && is("punc", "(")) {
|
3134
|
+
next();
|
3135
|
+
|
3136
|
+
const call = new AST_Call({
|
3137
|
+
start,
|
3138
|
+
optional: true,
|
3139
|
+
expression: expr,
|
3140
|
+
args: call_args(),
|
3141
|
+
end: prev()
|
3142
|
+
});
|
3143
|
+
annotate(call);
|
3144
|
+
|
3145
|
+
chain_contents = subscripts(call, true, true);
|
3146
|
+
} else if (is("name")) {
|
3147
|
+
chain_contents = subscripts(new AST_Dot({
|
3148
|
+
start,
|
3149
|
+
expression: expr,
|
3150
|
+
optional: true,
|
3151
|
+
property: as_name(),
|
3152
|
+
end: prev()
|
3153
|
+
}), allow_calls, true);
|
3154
|
+
} else if (is("punc", "[")) {
|
3155
|
+
next();
|
3156
|
+
const property = expression(true);
|
3157
|
+
expect("]");
|
3158
|
+
chain_contents = subscripts(new AST_Sub({
|
3159
|
+
start,
|
3160
|
+
expression: expr,
|
3161
|
+
optional: true,
|
3162
|
+
property,
|
3163
|
+
end: prev()
|
3164
|
+
}), allow_calls, true);
|
3165
|
+
}
|
3166
|
+
|
3167
|
+
if (!chain_contents) unexpected();
|
3168
|
+
|
3169
|
+
if (chain_contents instanceof AST_Chain) return chain_contents;
|
3170
|
+
|
3171
|
+
return new AST_Chain({
|
3172
|
+
start,
|
3173
|
+
expression: chain_contents,
|
3174
|
+
end: prev()
|
3175
|
+
});
|
3092
3176
|
}
|
3177
|
+
|
3093
3178
|
if (is("template_head")) {
|
3179
|
+
if (is_chain) {
|
3180
|
+
// a?.b`c` is a syntax error
|
3181
|
+
unexpected();
|
3182
|
+
}
|
3183
|
+
|
3094
3184
|
return subscripts(new AST_PrefixedTemplateString({
|
3095
3185
|
start: start,
|
3096
3186
|
prefix: expr,
|
@@ -3098,6 +3188,7 @@ function parse($TEXT, options) {
|
|
3098
3188
|
end: prev()
|
3099
3189
|
}), allow_calls);
|
3100
3190
|
}
|
3191
|
+
|
3101
3192
|
return expr;
|
3102
3193
|
};
|
3103
3194
|
|
@@ -3116,7 +3207,6 @@ function parse($TEXT, options) {
|
|
3116
3207
|
}
|
3117
3208
|
if (!is("punc", ")")) {
|
3118
3209
|
expect(",");
|
3119
|
-
if (is("punc", ")") && options.ecma < 2017) unexpected();
|
3120
3210
|
}
|
3121
3211
|
}
|
3122
3212
|
next();
|
@@ -3320,13 +3410,14 @@ function parse($TEXT, options) {
|
|
3320
3410
|
return expression(true);
|
3321
3411
|
}
|
3322
3412
|
|
3323
|
-
return (function() {
|
3413
|
+
return (function parse_toplevel() {
|
3324
3414
|
var start = S.token;
|
3325
3415
|
var body = [];
|
3326
3416
|
S.input.push_directives_stack();
|
3327
3417
|
if (options.module) S.input.add_directive("use strict");
|
3328
|
-
while (!is("eof"))
|
3418
|
+
while (!is("eof")) {
|
3329
3419
|
body.push(statement());
|
3420
|
+
}
|
3330
3421
|
S.input.pop_directives_stack();
|
3331
3422
|
var end = prev();
|
3332
3423
|
var toplevel = options.toplevel;
|
@@ -3861,7 +3952,7 @@ var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_str
|
|
3861
3952
|
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
|
3862
3953
|
$propdoc: {
|
3863
3954
|
template_string: "[AST_TemplateString] The template string",
|
3864
|
-
prefix: "[
|
3955
|
+
prefix: "[AST_Node] The prefix, which will get called."
|
3865
3956
|
},
|
3866
3957
|
_walk: function(visitor) {
|
3867
3958
|
return visitor._visit(this, function () {
|
@@ -4198,6 +4289,10 @@ var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
|
|
4198
4289
|
},
|
4199
4290
|
});
|
4200
4291
|
|
4292
|
+
var AST_ImportMeta = DEFNODE("ImportMeta", null, {
|
4293
|
+
$documentation: "A reference to import.meta",
|
4294
|
+
});
|
4295
|
+
|
4201
4296
|
var AST_Export = DEFNODE("Export", "exported_definition exported_value is_default exported_names module_name", {
|
4202
4297
|
$documentation: "An `export` statement",
|
4203
4298
|
$propdoc: {
|
@@ -4238,11 +4333,12 @@ var AST_Export = DEFNODE("Export", "exported_definition exported_value is_defaul
|
|
4238
4333
|
|
4239
4334
|
/* -----[ OTHER ]----- */
|
4240
4335
|
|
4241
|
-
var AST_Call = DEFNODE("Call", "expression args _annotations", {
|
4336
|
+
var AST_Call = DEFNODE("Call", "expression args optional _annotations", {
|
4242
4337
|
$documentation: "A function call expression",
|
4243
4338
|
$propdoc: {
|
4244
4339
|
expression: "[AST_Node] expression to invoke as function",
|
4245
4340
|
args: "[AST_Node*] array of arguments",
|
4341
|
+
optional: "[boolean] whether this is an optional call (IE ?.() )",
|
4246
4342
|
_annotations: "[number] bitfield containing information about the call"
|
4247
4343
|
},
|
4248
4344
|
initialize() {
|
@@ -4286,11 +4382,13 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
|
4286
4382
|
},
|
4287
4383
|
});
|
4288
4384
|
|
4289
|
-
var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
|
4385
|
+
var AST_PropAccess = DEFNODE("PropAccess", "expression property optional", {
|
4290
4386
|
$documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
|
4291
4387
|
$propdoc: {
|
4292
4388
|
expression: "[AST_Node] the “container” expression",
|
4293
|
-
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
|
4389
|
+
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
|
4390
|
+
|
4391
|
+
optional: "[boolean] whether this is an optional property access (IE ?.)"
|
4294
4392
|
}
|
4295
4393
|
});
|
4296
4394
|
|
@@ -4323,6 +4421,21 @@ var AST_Sub = DEFNODE("Sub", null, {
|
|
4323
4421
|
},
|
4324
4422
|
}, AST_PropAccess);
|
4325
4423
|
|
4424
|
+
var AST_Chain = DEFNODE("Chain", "expression", {
|
4425
|
+
$documentation: "A chain expression like a?.b?.(c)?.[d]",
|
4426
|
+
$propdoc: {
|
4427
|
+
expression: "[AST_Call|AST_Dot|AST_Sub] chain element."
|
4428
|
+
},
|
4429
|
+
_walk: function (visitor) {
|
4430
|
+
return visitor._visit(this, function() {
|
4431
|
+
this.expression._walk(visitor);
|
4432
|
+
});
|
4433
|
+
},
|
4434
|
+
_children_backwards(push) {
|
4435
|
+
push(this.expression);
|
4436
|
+
},
|
4437
|
+
});
|
4438
|
+
|
4326
4439
|
var AST_Unary = DEFNODE("Unary", "operator expression", {
|
4327
4440
|
$documentation: "Base class for unary expressions",
|
4328
4441
|
$propdoc: {
|
@@ -4945,6 +5058,7 @@ AST_Break: AST_Break,
|
|
4945
5058
|
AST_Call: AST_Call,
|
4946
5059
|
AST_Case: AST_Case,
|
4947
5060
|
AST_Catch: AST_Catch,
|
5061
|
+
AST_Chain: AST_Chain,
|
4948
5062
|
AST_Class: AST_Class,
|
4949
5063
|
AST_ClassExpression: AST_ClassExpression,
|
4950
5064
|
AST_ClassProperty: AST_ClassProperty,
|
@@ -4977,6 +5091,7 @@ AST_Function: AST_Function,
|
|
4977
5091
|
AST_Hole: AST_Hole,
|
4978
5092
|
AST_If: AST_If,
|
4979
5093
|
AST_Import: AST_Import,
|
5094
|
+
AST_ImportMeta: AST_ImportMeta,
|
4980
5095
|
AST_Infinity: AST_Infinity,
|
4981
5096
|
AST_IterationStatement: AST_IterationStatement,
|
4982
5097
|
AST_Jump: AST_Jump,
|
@@ -5632,7 +5747,15 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
5632
5747
|
start : my_start_token(M),
|
5633
5748
|
end : my_end_token(M),
|
5634
5749
|
property : M.computed ? from_moz(M.property) : M.property.name,
|
5635
|
-
expression : from_moz(M.object)
|
5750
|
+
expression : from_moz(M.object),
|
5751
|
+
optional : M.optional || false
|
5752
|
+
});
|
5753
|
+
},
|
5754
|
+
ChainExpression: function(M) {
|
5755
|
+
return new AST_Chain({
|
5756
|
+
start : my_start_token(M),
|
5757
|
+
end : my_end_token(M),
|
5758
|
+
expression : from_moz(M.expression)
|
5636
5759
|
});
|
5637
5760
|
},
|
5638
5761
|
SwitchCase: function(M) {
|
@@ -5759,6 +5882,11 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
5759
5882
|
start: my_start_token(M),
|
5760
5883
|
end: my_end_token(M)
|
5761
5884
|
});
|
5885
|
+
} else if (M.meta.name === "import" && M.property.name === "meta") {
|
5886
|
+
return new AST_ImportMeta({
|
5887
|
+
start: my_start_token(M),
|
5888
|
+
end: my_end_token(M)
|
5889
|
+
});
|
5762
5890
|
}
|
5763
5891
|
},
|
5764
5892
|
Identifier: function(M) {
|
@@ -5843,7 +5971,7 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
5843
5971
|
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
|
5844
5972
|
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
|
5845
5973
|
map("NewExpression", AST_New, "callee>expression, arguments@args");
|
5846
|
-
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
5974
|
+
map("CallExpression", AST_Call, "callee>expression, optional=optional, arguments@args");
|
5847
5975
|
|
5848
5976
|
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
5849
5977
|
return to_moz_scope("Program", M);
|
@@ -6050,6 +6178,20 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
6050
6178
|
};
|
6051
6179
|
});
|
6052
6180
|
|
6181
|
+
def_to_moz(AST_ImportMeta, function To_Moz_MetaProperty() {
|
6182
|
+
return {
|
6183
|
+
type: "MetaProperty",
|
6184
|
+
meta: {
|
6185
|
+
type: "Identifier",
|
6186
|
+
name: "import"
|
6187
|
+
},
|
6188
|
+
property: {
|
6189
|
+
type: "Identifier",
|
6190
|
+
name: "meta"
|
6191
|
+
}
|
6192
|
+
};
|
6193
|
+
});
|
6194
|
+
|
6053
6195
|
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
|
6054
6196
|
return {
|
6055
6197
|
type: "SequenceExpression",
|
@@ -6063,7 +6205,15 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
6063
6205
|
type: "MemberExpression",
|
6064
6206
|
object: to_moz(M.expression),
|
6065
6207
|
computed: isComputed,
|
6066
|
-
property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
|
6208
|
+
property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property},
|
6209
|
+
optional: M.optional
|
6210
|
+
};
|
6211
|
+
});
|
6212
|
+
|
6213
|
+
def_to_moz(AST_Chain, function To_Moz_ChainExpression(M) {
|
6214
|
+
return {
|
6215
|
+
type: "ChainExpression",
|
6216
|
+
expression: to_moz(M.expression)
|
6067
6217
|
};
|
6068
6218
|
});
|
6069
6219
|
|
@@ -7275,8 +7425,8 @@ function OutputStream(options) {
|
|
7275
7425
|
return p instanceof AST_PropAccess && p.expression === this;
|
7276
7426
|
});
|
7277
7427
|
|
7278
|
-
// same goes for an object literal
|
7279
|
-
// interpreted as a block of code.
|
7428
|
+
// same goes for an object literal (as in AST_Function), because
|
7429
|
+
// otherwise {...} would be interpreted as a block of code.
|
7280
7430
|
PARENS(AST_Object, function(output) {
|
7281
7431
|
return !output.has_parens() && first_in_statement(output);
|
7282
7432
|
});
|
@@ -7792,6 +7942,8 @@ function OutputStream(options) {
|
|
7792
7942
|
|| e instanceof AST_PropAccess
|
7793
7943
|
|| e instanceof AST_Unary
|
7794
7944
|
|| e instanceof AST_Constant
|
7945
|
+
|| e instanceof AST_Await
|
7946
|
+
|| e instanceof AST_Object
|
7795
7947
|
);
|
7796
7948
|
if (parens) output.print("(");
|
7797
7949
|
self.expression.print(output);
|
@@ -7989,6 +8141,9 @@ function OutputStream(options) {
|
|
7989
8141
|
self.module_name.print(output);
|
7990
8142
|
output.semicolon();
|
7991
8143
|
});
|
8144
|
+
DEFPRINT(AST_ImportMeta, function(self, output) {
|
8145
|
+
output.print("import.meta");
|
8146
|
+
});
|
7992
8147
|
|
7993
8148
|
DEFPRINT(AST_NameMapping, function(self, output) {
|
7994
8149
|
var is_import = output.parent() instanceof AST_Import;
|
@@ -8095,6 +8250,7 @@ function OutputStream(options) {
|
|
8095
8250
|
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
8096
8251
|
output.add_mapping(self.start);
|
8097
8252
|
}
|
8253
|
+
if (self.optional) output.print("?.");
|
8098
8254
|
output.with_parens(function() {
|
8099
8255
|
self.args.forEach(function(expr, i) {
|
8100
8256
|
if (i) output.comma();
|
@@ -8138,6 +8294,9 @@ function OutputStream(options) {
|
|
8138
8294
|
var print_computed = RESERVED_WORDS.has(prop)
|
8139
8295
|
? output.option("ie8")
|
8140
8296
|
: !is_identifier_string(prop, output.option("ecma") >= 2015);
|
8297
|
+
|
8298
|
+
if (self.optional) output.print("?.");
|
8299
|
+
|
8141
8300
|
if (print_computed) {
|
8142
8301
|
output.print("[");
|
8143
8302
|
output.add_mapping(self.end);
|
@@ -8149,7 +8308,7 @@ function OutputStream(options) {
|
|
8149
8308
|
output.print(".");
|
8150
8309
|
}
|
8151
8310
|
}
|
8152
|
-
output.print(".");
|
8311
|
+
if (!self.optional) output.print(".");
|
8153
8312
|
// the name after dot would be mapped about here.
|
8154
8313
|
output.add_mapping(self.end);
|
8155
8314
|
output.print_name(prop);
|
@@ -8157,10 +8316,14 @@ function OutputStream(options) {
|
|
8157
8316
|
});
|
8158
8317
|
DEFPRINT(AST_Sub, function(self, output) {
|
8159
8318
|
self.expression.print(output);
|
8319
|
+
if (self.optional) output.print("?.");
|
8160
8320
|
output.print("[");
|
8161
8321
|
self.property.print(output);
|
8162
8322
|
output.print("]");
|
8163
8323
|
});
|
8324
|
+
DEFPRINT(AST_Chain, function(self, output) {
|
8325
|
+
self.expression.print(output);
|
8326
|
+
});
|
8164
8327
|
DEFPRINT(AST_UnaryPrefix, function(self, output) {
|
8165
8328
|
var op = self.operator;
|
8166
8329
|
output.print(op);
|
@@ -8716,6 +8879,8 @@ AST_Import.prototype.shallow_cmp = mkshallow({
|
|
8716
8879
|
imported_names: "exist"
|
8717
8880
|
});
|
8718
8881
|
|
8882
|
+
AST_ImportMeta.prototype.shallow_cmp = pass_through;
|
8883
|
+
|
8719
8884
|
AST_Export.prototype.shallow_cmp = mkshallow({
|
8720
8885
|
exported_definition: "exist",
|
8721
8886
|
exported_value: "exist",
|
@@ -9702,7 +9867,7 @@ const base54 = (() => {
|
|
9702
9867
|
|
9703
9868
|
let mangle_options = undefined;
|
9704
9869
|
AST_Node.prototype.size = function (compressor, stack) {
|
9705
|
-
mangle_options =
|
9870
|
+
mangle_options = compressor && compressor.mangle_options;
|
9706
9871
|
|
9707
9872
|
let size = 0;
|
9708
9873
|
walk_parent(this, (node, info) => {
|
@@ -9780,7 +9945,7 @@ AST_Arrow.prototype._size = function () {
|
|
9780
9945
|
args_and_arrow += 2;
|
9781
9946
|
}
|
9782
9947
|
|
9783
|
-
return lambda_modifiers(this) + args_and_arrow + Array.isArray(this.body) ? list_overhead(this.body) : this.body._size();
|
9948
|
+
return lambda_modifiers(this) + args_and_arrow + (Array.isArray(this.body) ? list_overhead(this.body) : this.body._size());
|
9784
9949
|
};
|
9785
9950
|
|
9786
9951
|
AST_Destructuring.prototype._size = () => 2;
|
@@ -9878,6 +10043,8 @@ AST_Import.prototype._size = function () {
|
|
9878
10043
|
return size;
|
9879
10044
|
};
|
9880
10045
|
|
10046
|
+
AST_ImportMeta.prototype._size = () => 11;
|
10047
|
+
|
9881
10048
|
AST_Export.prototype._size = function () {
|
9882
10049
|
let size = 7 + (this.is_default ? 8 : 0);
|
9883
10050
|
|
@@ -9899,6 +10066,9 @@ AST_Export.prototype._size = function () {
|
|
9899
10066
|
};
|
9900
10067
|
|
9901
10068
|
AST_Call.prototype._size = function () {
|
10069
|
+
if (this.optional) {
|
10070
|
+
return 4 + list_overhead(this.args);
|
10071
|
+
}
|
9902
10072
|
return 2 + list_overhead(this.args);
|
9903
10073
|
};
|
9904
10074
|
|
@@ -9911,10 +10081,15 @@ AST_Sequence.prototype._size = function () {
|
|
9911
10081
|
};
|
9912
10082
|
|
9913
10083
|
AST_Dot.prototype._size = function () {
|
10084
|
+
if (this.optional) {
|
10085
|
+
return this.property.length + 2;
|
10086
|
+
}
|
9914
10087
|
return this.property.length + 1;
|
9915
10088
|
};
|
9916
10089
|
|
9917
|
-
AST_Sub.prototype._size = ()
|
10090
|
+
AST_Sub.prototype._size = function () {
|
10091
|
+
return this.optional ? 4 : 2;
|
10092
|
+
};
|
9918
10093
|
|
9919
10094
|
AST_Unary.prototype._size = function () {
|
9920
10095
|
if (this.operator === "typeof") return 7;
|
@@ -9997,7 +10172,7 @@ AST_ClassProperty.prototype._size = function () {
|
|
9997
10172
|
AST_Symbol.prototype._size = function () {
|
9998
10173
|
return !mangle_options || this.definition().unmangleable(mangle_options)
|
9999
10174
|
? this.name.length
|
10000
|
-
:
|
10175
|
+
: 1;
|
10001
10176
|
};
|
10002
10177
|
|
10003
10178
|
// TODO take propmangle into account
|
@@ -10012,7 +10187,7 @@ AST_SymbolRef.prototype._size = AST_SymbolDeclaration.prototype._size = function
|
|
10012
10187
|
|
10013
10188
|
if (name === "arguments") return 9;
|
10014
10189
|
|
10015
|
-
return
|
10190
|
+
return AST_Symbol.prototype._size.call(this);
|
10016
10191
|
};
|
10017
10192
|
|
10018
10193
|
AST_NewTarget.prototype._size = () => 10;
|
@@ -10134,7 +10309,7 @@ const set_flag = (node, flag) => { node.flags |= flag; };
|
|
10134
10309
|
const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
10135
10310
|
|
10136
10311
|
class Compressor extends TreeWalker {
|
10137
|
-
constructor(options, false_by_default) {
|
10312
|
+
constructor(options, { false_by_default = false, mangle_options = false }) {
|
10138
10313
|
super();
|
10139
10314
|
if (options.defaults !== undefined && !options.defaults) false_by_default = true;
|
10140
10315
|
this.options = defaults(options, {
|
@@ -10192,7 +10367,7 @@ class Compressor extends TreeWalker {
|
|
10192
10367
|
unsafe_regexp : false,
|
10193
10368
|
unsafe_undefined: false,
|
10194
10369
|
unused : !false_by_default,
|
10195
|
-
warnings : false
|
10370
|
+
warnings : false // legacy
|
10196
10371
|
}, true);
|
10197
10372
|
var global_defs = this.options["global_defs"];
|
10198
10373
|
if (typeof global_defs == "object") for (var key in global_defs) {
|
@@ -10242,6 +10417,7 @@ class Compressor extends TreeWalker {
|
|
10242
10417
|
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
10243
10418
|
this.evaluated_regexps = new Map();
|
10244
10419
|
this._toplevel = undefined;
|
10420
|
+
this.mangle_options = mangle_options;
|
10245
10421
|
}
|
10246
10422
|
|
10247
10423
|
option(key) {
|
@@ -10710,13 +10886,53 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
10710
10886
|
pop(tw);
|
10711
10887
|
return true;
|
10712
10888
|
});
|
10889
|
+
|
10890
|
+
def_reduce_vars(AST_Chain, function(tw, descend) {
|
10891
|
+
// Chains' conditions apply left-to-right, cumulatively.
|
10892
|
+
// If we walk normally we don't go in that order because we would pop before pushing again
|
10893
|
+
// Solution: AST_PropAccess and AST_Call push when they are optional, and never pop.
|
10894
|
+
// Then we pop everything when they are done being walked.
|
10895
|
+
const safe_ids = tw.safe_ids;
|
10896
|
+
|
10897
|
+
descend();
|
10898
|
+
|
10899
|
+
// Unroll back to start
|
10900
|
+
tw.safe_ids = safe_ids;
|
10901
|
+
return true;
|
10902
|
+
});
|
10903
|
+
def_reduce_vars(AST_Call, function (tw) {
|
10904
|
+
// TODO this block should just be { return } but
|
10905
|
+
// for some reason the _walk function of AST_Call walks the callee last
|
10906
|
+
|
10907
|
+
this.expression.walk(tw);
|
10908
|
+
|
10909
|
+
if (this.optional) {
|
10910
|
+
// Never pop -- it's popped at AST_Chain above
|
10911
|
+
push(tw);
|
10912
|
+
}
|
10913
|
+
|
10914
|
+
for (const arg of this.args) arg.walk(tw);
|
10915
|
+
|
10916
|
+
return true;
|
10917
|
+
});
|
10918
|
+
def_reduce_vars(AST_PropAccess, function (tw) {
|
10919
|
+
if (!this.optional) return;
|
10920
|
+
|
10921
|
+
this.expression.walk(tw);
|
10922
|
+
|
10923
|
+
// Never pop -- it's popped at AST_Chain above
|
10924
|
+
push(tw);
|
10925
|
+
|
10926
|
+
if (this.property instanceof AST_Node) this.property.walk(tw);
|
10927
|
+
|
10928
|
+
return true;
|
10929
|
+
});
|
10713
10930
|
def_reduce_vars(AST_Default, function(tw, descend) {
|
10714
10931
|
push(tw);
|
10715
10932
|
descend();
|
10716
10933
|
pop(tw);
|
10717
10934
|
return true;
|
10718
10935
|
});
|
10719
|
-
|
10720
10936
|
function mark_lambda(tw, descend, compressor) {
|
10721
10937
|
clear_flag(this, INLINED);
|
10722
10938
|
push(tw);
|
@@ -11546,8 +11762,7 @@ function tighten_body(statements, compressor) {
|
|
11546
11762
|
extract_candidates(expr.condition);
|
11547
11763
|
extract_candidates(expr.consequent);
|
11548
11764
|
extract_candidates(expr.alternative);
|
11549
|
-
} else if (expr instanceof AST_Definitions
|
11550
|
-
&& (compressor.option("unused") || !(expr instanceof AST_Const))) {
|
11765
|
+
} else if (expr instanceof AST_Definitions) {
|
11551
11766
|
var len = expr.definitions.length;
|
11552
11767
|
// limit number of trailing variable definitions for consideration
|
11553
11768
|
var i = len - 200;
|
@@ -11715,7 +11930,9 @@ function tighten_body(statements, compressor) {
|
|
11715
11930
|
if (node === expr || node.body === expr) {
|
11716
11931
|
found = true;
|
11717
11932
|
if (node instanceof AST_VarDef) {
|
11718
|
-
node.value =
|
11933
|
+
node.value = node.name instanceof AST_SymbolConst
|
11934
|
+
? make_node(AST_Undefined, node.value) // `const` always needs value.
|
11935
|
+
: null;
|
11719
11936
|
return node;
|
11720
11937
|
}
|
11721
11938
|
return in_list ? MAP.skip : null;
|
@@ -12031,7 +12248,7 @@ function tighten_body(statements, compressor) {
|
|
12031
12248
|
statements.length = n;
|
12032
12249
|
CHANGED = n != len;
|
12033
12250
|
if (has_quit) has_quit.forEach(function(stat) {
|
12034
|
-
|
12251
|
+
trim_unreachable_code(compressor, stat, statements);
|
12035
12252
|
});
|
12036
12253
|
}
|
12037
12254
|
|
@@ -12289,7 +12506,7 @@ function tighten_body(statements, compressor) {
|
|
12289
12506
|
}
|
12290
12507
|
}
|
12291
12508
|
|
12292
|
-
function
|
12509
|
+
function trim_unreachable_code(compressor, stat, target) {
|
12293
12510
|
walk(stat, node => {
|
12294
12511
|
if (node instanceof AST_Var) {
|
12295
12512
|
node.remove_initializers();
|
@@ -12310,6 +12527,10 @@ function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
|
12310
12527
|
}));
|
12311
12528
|
return true;
|
12312
12529
|
}
|
12530
|
+
if (node instanceof AST_Export || node instanceof AST_Import) {
|
12531
|
+
target.push(node);
|
12532
|
+
return true;
|
12533
|
+
}
|
12313
12534
|
if (node instanceof AST_Scope) {
|
12314
12535
|
return true;
|
12315
12536
|
}
|
@@ -12361,6 +12582,10 @@ function is_undefined(node, compressor) {
|
|
12361
12582
|
if (this.properties[i]._dot_throw(compressor)) return true;
|
12362
12583
|
return false;
|
12363
12584
|
});
|
12585
|
+
// Do not be as strict with classes as we are with objects.
|
12586
|
+
// Hopefully the community is not going to abuse static getters and setters.
|
12587
|
+
// https://github.com/terser/terser/issues/724#issuecomment-643655656
|
12588
|
+
def_may_throw_on_access(AST_Class, return_false);
|
12364
12589
|
def_may_throw_on_access(AST_ObjectProperty, return_false);
|
12365
12590
|
def_may_throw_on_access(AST_ObjectGetter, return_true);
|
12366
12591
|
def_may_throw_on_access(AST_Expansion, function(compressor) {
|
@@ -12389,11 +12614,15 @@ function is_undefined(node, compressor) {
|
|
12389
12614
|
if (this.expression instanceof AST_Function && this.property == "prototype") return false;
|
12390
12615
|
return true;
|
12391
12616
|
});
|
12617
|
+
def_may_throw_on_access(AST_Chain, function(compressor) {
|
12618
|
+
return this.expression._dot_throw(compressor);
|
12619
|
+
});
|
12392
12620
|
def_may_throw_on_access(AST_Sequence, function(compressor) {
|
12393
12621
|
return this.tail_node()._dot_throw(compressor);
|
12394
12622
|
});
|
12395
12623
|
def_may_throw_on_access(AST_SymbolRef, function(compressor) {
|
12396
|
-
if (
|
12624
|
+
if (this.name === "arguments") return false;
|
12625
|
+
if (has_flag(this, UNDEFINED)) return true;
|
12397
12626
|
if (!is_strict(compressor)) return false;
|
12398
12627
|
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
|
12399
12628
|
if (this.is_immutable()) return false;
|
@@ -12538,6 +12767,9 @@ function is_lhs(node, parent) {
|
|
12538
12767
|
}));
|
12539
12768
|
});
|
12540
12769
|
def_find_defs(AST_Node, noop);
|
12770
|
+
def_find_defs(AST_Chain, function(compressor, suffix) {
|
12771
|
+
return this.expression._find_defs(compressor, suffix);
|
12772
|
+
});
|
12541
12773
|
def_find_defs(AST_Dot, function(compressor, suffix) {
|
12542
12774
|
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
12543
12775
|
});
|
@@ -12795,13 +13027,33 @@ var static_fns = convert_to_predicate({
|
|
12795
13027
|
return this;
|
12796
13028
|
});
|
12797
13029
|
var non_converting_binary = makePredicate("&& || ?? === !==");
|
13030
|
+
const identity_comparison = makePredicate("== != === !==");
|
13031
|
+
const has_identity = value =>
|
13032
|
+
typeof value === "object"
|
13033
|
+
|| typeof value === "function"
|
13034
|
+
|| typeof value === "symbol";
|
13035
|
+
|
12798
13036
|
def_eval(AST_Binary, function(compressor, depth) {
|
12799
13037
|
if (!non_converting_binary.has(this.operator)) depth++;
|
13038
|
+
|
12800
13039
|
var left = this.left._eval(compressor, depth);
|
12801
13040
|
if (left === this.left) return this;
|
12802
13041
|
var right = this.right._eval(compressor, depth);
|
12803
13042
|
if (right === this.right) return this;
|
12804
13043
|
var result;
|
13044
|
+
|
13045
|
+
if (
|
13046
|
+
left != null
|
13047
|
+
&& right != null
|
13048
|
+
&& identity_comparison.has(this.operator)
|
13049
|
+
&& has_identity(left)
|
13050
|
+
&& has_identity(right)
|
13051
|
+
&& typeof left === typeof right
|
13052
|
+
) {
|
13053
|
+
// Do not compare by reference
|
13054
|
+
return this;
|
13055
|
+
}
|
13056
|
+
|
12805
13057
|
switch (this.operator) {
|
12806
13058
|
case "&&" : result = left && right; break;
|
12807
13059
|
case "||" : result = left || right; break;
|
@@ -12842,34 +13094,29 @@ var static_fns = convert_to_predicate({
|
|
12842
13094
|
var value = node._eval(compressor, depth);
|
12843
13095
|
return value === node ? this : value;
|
12844
13096
|
});
|
13097
|
+
|
13098
|
+
// Set of AST_SymbolRef which are currently being evaluated.
|
13099
|
+
// Avoids infinite recursion of ._eval()
|
13100
|
+
const reentrant_ref_eval = new Set();
|
12845
13101
|
def_eval(AST_SymbolRef, function(compressor, depth) {
|
13102
|
+
if (reentrant_ref_eval.has(this)) return this;
|
13103
|
+
|
12846
13104
|
var fixed = this.fixed_value();
|
12847
13105
|
if (!fixed) return this;
|
12848
|
-
|
12849
|
-
|
12850
|
-
|
12851
|
-
|
12852
|
-
|
12853
|
-
|
12854
|
-
|
12855
|
-
if (value === fixed) return this;
|
12856
|
-
fixed._eval = function() {
|
12857
|
-
return value;
|
12858
|
-
};
|
12859
|
-
}
|
13106
|
+
|
13107
|
+
reentrant_ref_eval.add(this);
|
13108
|
+
const value = fixed._eval(compressor, depth);
|
13109
|
+
reentrant_ref_eval.delete(this);
|
13110
|
+
|
13111
|
+
if (value === fixed) return this;
|
13112
|
+
|
12860
13113
|
if (value && typeof value == "object") {
|
12861
13114
|
var escaped = this.definition().escaped;
|
12862
13115
|
if (escaped && depth > escaped) return this;
|
12863
13116
|
}
|
12864
13117
|
return value;
|
12865
13118
|
});
|
12866
|
-
var global_objs = {
|
12867
|
-
Array: Array,
|
12868
|
-
Math: Math,
|
12869
|
-
Number: Number,
|
12870
|
-
Object: Object,
|
12871
|
-
String: String,
|
12872
|
-
};
|
13119
|
+
var global_objs = { Array, Math, Number, Object, String };
|
12873
13120
|
var static_values = convert_to_predicate({
|
12874
13121
|
Math: [
|
12875
13122
|
"E",
|
@@ -12890,6 +13137,10 @@ var static_fns = convert_to_predicate({
|
|
12890
13137
|
],
|
12891
13138
|
});
|
12892
13139
|
def_eval(AST_PropAccess, function(compressor, depth) {
|
13140
|
+
if (this.optional) {
|
13141
|
+
const obj = this.expression._eval(compressor, depth);
|
13142
|
+
if (obj == null) return undefined;
|
13143
|
+
}
|
12893
13144
|
if (compressor.option("unsafe")) {
|
12894
13145
|
var key = this.property;
|
12895
13146
|
if (key instanceof AST_Node) {
|
@@ -12931,8 +13182,15 @@ var static_fns = convert_to_predicate({
|
|
12931
13182
|
}
|
12932
13183
|
return this;
|
12933
13184
|
});
|
13185
|
+
def_eval(AST_Chain, function(compressor, depth) {
|
13186
|
+
return this.expression._eval(compressor, depth);
|
13187
|
+
});
|
12934
13188
|
def_eval(AST_Call, function(compressor, depth) {
|
12935
13189
|
var exp = this.expression;
|
13190
|
+
if (this.optional) {
|
13191
|
+
const callee = this.expression._eval(compressor, depth);
|
13192
|
+
if (callee == null) return undefined;
|
13193
|
+
}
|
12936
13194
|
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
12937
13195
|
var key = exp.property;
|
12938
13196
|
if (key instanceof AST_Node) {
|
@@ -13134,9 +13392,11 @@ const pure_prop_access_globals = new Set([
|
|
13134
13392
|
return any(this.body, compressor);
|
13135
13393
|
});
|
13136
13394
|
def_has_side_effects(AST_Call, function(compressor) {
|
13137
|
-
if (
|
13395
|
+
if (
|
13396
|
+
!this.is_expr_pure(compressor)
|
13138
13397
|
&& (!this.expression.is_call_pure(compressor)
|
13139
|
-
|| this.expression.has_side_effects(compressor))
|
13398
|
+
|| this.expression.has_side_effects(compressor))
|
13399
|
+
) {
|
13140
13400
|
return true;
|
13141
13401
|
}
|
13142
13402
|
return any(this.args, compressor);
|
@@ -13219,14 +13479,21 @@ const pure_prop_access_globals = new Set([
|
|
13219
13479
|
return any(this.elements, compressor);
|
13220
13480
|
});
|
13221
13481
|
def_has_side_effects(AST_Dot, function(compressor) {
|
13222
|
-
return this.expression.may_throw_on_access(compressor)
|
13482
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
13223
13483
|
|| this.expression.has_side_effects(compressor);
|
13224
13484
|
});
|
13225
13485
|
def_has_side_effects(AST_Sub, function(compressor) {
|
13226
|
-
|
13486
|
+
if (this.optional && is_nullish(this.expression)) {
|
13487
|
+
return false;
|
13488
|
+
}
|
13489
|
+
|
13490
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
13227
13491
|
|| this.expression.has_side_effects(compressor)
|
13228
13492
|
|| this.property.has_side_effects(compressor);
|
13229
13493
|
});
|
13494
|
+
def_has_side_effects(AST_Chain, function (compressor) {
|
13495
|
+
return this.expression.has_side_effects(compressor);
|
13496
|
+
});
|
13230
13497
|
def_has_side_effects(AST_Sequence, function(compressor) {
|
13231
13498
|
return any(this.expressions, compressor);
|
13232
13499
|
});
|
@@ -13286,6 +13553,7 @@ const pure_prop_access_globals = new Set([
|
|
13286
13553
|
return any(this.body, compressor);
|
13287
13554
|
});
|
13288
13555
|
def_may_throw(AST_Call, function(compressor) {
|
13556
|
+
if (this.optional && is_nullish(this.expression)) return false;
|
13289
13557
|
if (any(this.args, compressor)) return true;
|
13290
13558
|
if (this.is_expr_pure(compressor)) return false;
|
13291
13559
|
if (this.expression.may_throw(compressor)) return true;
|
@@ -13304,10 +13572,6 @@ const pure_prop_access_globals = new Set([
|
|
13304
13572
|
def_may_throw(AST_Definitions, function(compressor) {
|
13305
13573
|
return any(this.definitions, compressor);
|
13306
13574
|
});
|
13307
|
-
def_may_throw(AST_Dot, function(compressor) {
|
13308
|
-
return this.expression.may_throw_on_access(compressor)
|
13309
|
-
|| this.expression.may_throw(compressor);
|
13310
|
-
});
|
13311
13575
|
def_may_throw(AST_If, function(compressor) {
|
13312
13576
|
return this.condition.may_throw(compressor)
|
13313
13577
|
|| this.body && this.body.may_throw(compressor)
|
@@ -13347,11 +13611,20 @@ const pure_prop_access_globals = new Set([
|
|
13347
13611
|
def_may_throw(AST_SimpleStatement, function(compressor) {
|
13348
13612
|
return this.body.may_throw(compressor);
|
13349
13613
|
});
|
13614
|
+
def_may_throw(AST_Dot, function(compressor) {
|
13615
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
13616
|
+
|| this.expression.may_throw(compressor);
|
13617
|
+
});
|
13350
13618
|
def_may_throw(AST_Sub, function(compressor) {
|
13351
|
-
|
13619
|
+
if (this.optional && is_nullish(this.expression)) return false;
|
13620
|
+
|
13621
|
+
return !this.optional && this.expression.may_throw_on_access(compressor)
|
13352
13622
|
|| this.expression.may_throw(compressor)
|
13353
13623
|
|| this.property.may_throw(compressor);
|
13354
13624
|
});
|
13625
|
+
def_may_throw(AST_Chain, function(compressor) {
|
13626
|
+
return this.expression.may_throw(compressor);
|
13627
|
+
});
|
13355
13628
|
def_may_throw(AST_Switch, function(compressor) {
|
13356
13629
|
return this.expression.may_throw(compressor)
|
13357
13630
|
|| any(this.body, compressor);
|
@@ -13509,9 +13782,9 @@ def_optimize(AST_Block, function(self, compressor) {
|
|
13509
13782
|
|
13510
13783
|
function can_be_extracted_from_if_block(node) {
|
13511
13784
|
return !(
|
13512
|
-
node instanceof AST_Const
|
13513
|
-
node instanceof AST_Let
|
13514
|
-
node instanceof AST_Class
|
13785
|
+
node instanceof AST_Const
|
13786
|
+
|| node instanceof AST_Let
|
13787
|
+
|| node instanceof AST_Class
|
13515
13788
|
);
|
13516
13789
|
}
|
13517
13790
|
|
@@ -14145,6 +14418,10 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
14145
14418
|
def_drop_side_effect_free(AST_Constant, return_null);
|
14146
14419
|
def_drop_side_effect_free(AST_This, return_null);
|
14147
14420
|
def_drop_side_effect_free(AST_Call, function(compressor, first_in_statement) {
|
14421
|
+
if (this.optional && is_nullish(this.expression)) {
|
14422
|
+
return make_node(AST_Undefined, this);
|
14423
|
+
}
|
14424
|
+
|
14148
14425
|
if (!this.is_expr_pure(compressor)) {
|
14149
14426
|
if (this.expression.is_call_pure(compressor)) {
|
14150
14427
|
var exprs = this.args.slice();
|
@@ -14285,17 +14562,28 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
14285
14562
|
return values && make_sequence(this, values);
|
14286
14563
|
});
|
14287
14564
|
def_drop_side_effect_free(AST_Dot, function(compressor, first_in_statement) {
|
14565
|
+
if (this.optional) {
|
14566
|
+
return is_nullish(this.expression) ? make_node(AST_Undefined, this) : this;
|
14567
|
+
}
|
14288
14568
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
14569
|
+
|
14289
14570
|
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
14290
14571
|
});
|
14291
14572
|
def_drop_side_effect_free(AST_Sub, function(compressor, first_in_statement) {
|
14573
|
+
if (this.optional) {
|
14574
|
+
return is_nullish(this.expression) ? make_node(AST_Undefined, this): this;
|
14575
|
+
}
|
14292
14576
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
14577
|
+
|
14293
14578
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
14294
14579
|
if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement);
|
14295
14580
|
var property = this.property.drop_side_effect_free(compressor);
|
14296
14581
|
if (!property) return expression;
|
14297
14582
|
return make_sequence(this, [ expression, property ]);
|
14298
14583
|
});
|
14584
|
+
def_drop_side_effect_free(AST_Chain, function (compressor, first_in_statement) {
|
14585
|
+
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
14586
|
+
});
|
14299
14587
|
def_drop_side_effect_free(AST_Sequence, function(compressor) {
|
14300
14588
|
var last = this.tail_node();
|
14301
14589
|
var expr = last.drop_side_effect_free(compressor);
|
@@ -14395,7 +14683,7 @@ function if_break_in_loop(self, compressor) {
|
|
14395
14683
|
body: self.condition
|
14396
14684
|
}));
|
14397
14685
|
}
|
14398
|
-
|
14686
|
+
trim_unreachable_code(compressor, self.body, body);
|
14399
14687
|
return make_node(AST_BlockStatement, self, {
|
14400
14688
|
body: body
|
14401
14689
|
});
|
@@ -14466,7 +14754,7 @@ def_optimize(AST_For, function(self, compressor) {
|
|
14466
14754
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
14467
14755
|
if (!cond) {
|
14468
14756
|
var body = [];
|
14469
|
-
|
14757
|
+
trim_unreachable_code(compressor, self.body, body);
|
14470
14758
|
if (self.init instanceof AST_Statement) {
|
14471
14759
|
body.push(self.init);
|
14472
14760
|
} else if (self.init) {
|
@@ -14502,7 +14790,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
14502
14790
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
14503
14791
|
if (!cond) {
|
14504
14792
|
var body = [];
|
14505
|
-
|
14793
|
+
trim_unreachable_code(compressor, self.body, body);
|
14506
14794
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
14507
14795
|
body: self.condition
|
14508
14796
|
}));
|
@@ -14515,7 +14803,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
14515
14803
|
}));
|
14516
14804
|
body.push(self.body);
|
14517
14805
|
if (self.alternative) {
|
14518
|
-
|
14806
|
+
trim_unreachable_code(compressor, self.alternative, body);
|
14519
14807
|
}
|
14520
14808
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
14521
14809
|
}
|
@@ -14727,7 +15015,7 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
14727
15015
|
if (prev && !aborts(prev)) {
|
14728
15016
|
prev.body = prev.body.concat(branch.body);
|
14729
15017
|
} else {
|
14730
|
-
|
15018
|
+
trim_unreachable_code(compressor, branch, decl);
|
14731
15019
|
}
|
14732
15020
|
}
|
14733
15021
|
});
|
@@ -14738,7 +15026,7 @@ def_optimize(AST_Try, function(self, compressor) {
|
|
14738
15026
|
if (compressor.option("dead_code") && self.body.every(is_empty)) {
|
14739
15027
|
var body = [];
|
14740
15028
|
if (self.bcatch) {
|
14741
|
-
|
15029
|
+
trim_unreachable_code(compressor, self.bcatch, body);
|
14742
15030
|
}
|
14743
15031
|
if (self.bfinally) body.push(...self.bfinally.body);
|
14744
15032
|
return make_node(AST_BlockStatement, self, {
|
@@ -14836,6 +15124,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
14836
15124
|
}
|
14837
15125
|
}
|
14838
15126
|
|
15127
|
+
if (self.optional && is_nullish(fn)) {
|
15128
|
+
return make_node(AST_Undefined, self);
|
15129
|
+
}
|
15130
|
+
|
14839
15131
|
var is_func = fn instanceof AST_Lambda;
|
14840
15132
|
|
14841
15133
|
if (is_func && fn.pinned()) return self;
|
@@ -15047,6 +15339,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
15047
15339
|
return make_node(AST_Call, self, {
|
15048
15340
|
expression: make_node(AST_Dot, exp, {
|
15049
15341
|
expression: exp.expression,
|
15342
|
+
optional: false,
|
15050
15343
|
property: "call"
|
15051
15344
|
}),
|
15052
15345
|
args: args
|
@@ -15093,7 +15386,9 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
15093
15386
|
var ast = parse(code);
|
15094
15387
|
var mangle = { ie8: compressor.option("ie8") };
|
15095
15388
|
ast.figure_out_scope(mangle);
|
15096
|
-
var comp = new Compressor(compressor.options
|
15389
|
+
var comp = new Compressor(compressor.options, {
|
15390
|
+
mangle_options: compressor.mangle_options
|
15391
|
+
});
|
15097
15392
|
ast = ast.transform(comp);
|
15098
15393
|
ast.figure_out_scope(mangle);
|
15099
15394
|
base54.reset();
|
@@ -16276,8 +16571,8 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
16276
16571
|
}
|
16277
16572
|
|
16278
16573
|
if (replace) {
|
16279
|
-
const name_length =
|
16280
|
-
const replace_size = replace.size();
|
16574
|
+
const name_length = self.size(compressor);
|
16575
|
+
const replace_size = replace.size(compressor);
|
16281
16576
|
|
16282
16577
|
let overhead = 0;
|
16283
16578
|
if (compressor.option("unused") && !compressor.exposed(def)) {
|
@@ -16482,6 +16777,10 @@ function is_nullish(node) {
|
|
16482
16777
|
&& (fixed = node.definition().fixed) instanceof AST_Node
|
16483
16778
|
&& is_nullish(fixed)
|
16484
16779
|
)
|
16780
|
+
// Recurse into those optional chains!
|
16781
|
+
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression)
|
16782
|
+
|| node instanceof AST_Call && node.optional && is_nullish(node.expression)
|
16783
|
+
|| node instanceof AST_Chain && is_nullish(node.expression)
|
16485
16784
|
);
|
16486
16785
|
}
|
16487
16786
|
|
@@ -16864,6 +17163,41 @@ function safe_to_flatten(value, compressor) {
|
|
16864
17163
|
return compressor.parent() instanceof AST_New;
|
16865
17164
|
}
|
16866
17165
|
|
17166
|
+
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
17167
|
+
if (!compressor.option("properties")) return;
|
17168
|
+
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
17169
|
+
var expr = this.expression;
|
17170
|
+
if (expr instanceof AST_Object) {
|
17171
|
+
var props = expr.properties;
|
17172
|
+
for (var i = props.length; --i >= 0;) {
|
17173
|
+
var prop = props[i];
|
17174
|
+
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
17175
|
+
if (!props.every((prop) => {
|
17176
|
+
return prop instanceof AST_ObjectKeyVal
|
17177
|
+
|| arrows && prop instanceof AST_ConciseMethod && !prop.is_generator;
|
17178
|
+
})) break;
|
17179
|
+
if (!safe_to_flatten(prop.value, compressor)) break;
|
17180
|
+
return make_node(AST_Sub, this, {
|
17181
|
+
expression: make_node(AST_Array, expr, {
|
17182
|
+
elements: props.map(function(prop) {
|
17183
|
+
var v = prop.value;
|
17184
|
+
if (v instanceof AST_Accessor) v = make_node(AST_Function, v, v);
|
17185
|
+
var k = prop.key;
|
17186
|
+
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
17187
|
+
return make_sequence(prop, [ k, v ]);
|
17188
|
+
}
|
17189
|
+
return v;
|
17190
|
+
})
|
17191
|
+
}),
|
17192
|
+
property: make_node(AST_Number, this, {
|
17193
|
+
value: i
|
17194
|
+
})
|
17195
|
+
});
|
17196
|
+
}
|
17197
|
+
}
|
17198
|
+
}
|
17199
|
+
});
|
17200
|
+
|
16867
17201
|
def_optimize(AST_Sub, function(self, compressor) {
|
16868
17202
|
var expr = self.expression;
|
16869
17203
|
var prop = self.property;
|
@@ -16886,6 +17220,7 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
16886
17220
|
&& property.length <= prop.size() + 1) {
|
16887
17221
|
return make_node(AST_Dot, self, {
|
16888
17222
|
expression: expr,
|
17223
|
+
optional: self.optional,
|
16889
17224
|
property: property,
|
16890
17225
|
quote: prop.quote,
|
16891
17226
|
}).optimize(compressor);
|
@@ -16988,6 +17323,14 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
16988
17323
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
16989
17324
|
return best_of(compressor, ev, self);
|
16990
17325
|
}
|
17326
|
+
if (self.optional && is_nullish(self.expression)) {
|
17327
|
+
return make_node(AST_Undefined, self);
|
17328
|
+
}
|
17329
|
+
return self;
|
17330
|
+
});
|
17331
|
+
|
17332
|
+
def_optimize(AST_Chain, function (self, compressor) {
|
17333
|
+
self.expression = self.expression.optimize(compressor);
|
16991
17334
|
return self;
|
16992
17335
|
});
|
16993
17336
|
|
@@ -17004,41 +17347,6 @@ AST_Lambda.DEFMETHOD("contains_this", function() {
|
|
17004
17347
|
});
|
17005
17348
|
});
|
17006
17349
|
|
17007
|
-
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
17008
|
-
if (!compressor.option("properties")) return;
|
17009
|
-
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
17010
|
-
var expr = this.expression;
|
17011
|
-
if (expr instanceof AST_Object) {
|
17012
|
-
var props = expr.properties;
|
17013
|
-
for (var i = props.length; --i >= 0;) {
|
17014
|
-
var prop = props[i];
|
17015
|
-
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
17016
|
-
if (!props.every((prop) => {
|
17017
|
-
return prop instanceof AST_ObjectKeyVal
|
17018
|
-
|| arrows && prop instanceof AST_ConciseMethod && !prop.is_generator;
|
17019
|
-
})) break;
|
17020
|
-
if (!safe_to_flatten(prop.value, compressor)) break;
|
17021
|
-
return make_node(AST_Sub, this, {
|
17022
|
-
expression: make_node(AST_Array, expr, {
|
17023
|
-
elements: props.map(function(prop) {
|
17024
|
-
var v = prop.value;
|
17025
|
-
if (v instanceof AST_Accessor) v = make_node(AST_Function, v, v);
|
17026
|
-
var k = prop.key;
|
17027
|
-
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
17028
|
-
return make_sequence(prop, [ k, v ]);
|
17029
|
-
}
|
17030
|
-
return v;
|
17031
|
-
})
|
17032
|
-
}),
|
17033
|
-
property: make_node(AST_Number, this, {
|
17034
|
-
value: i
|
17035
|
-
})
|
17036
|
-
});
|
17037
|
-
}
|
17038
|
-
}
|
17039
|
-
}
|
17040
|
-
});
|
17041
|
-
|
17042
17350
|
def_optimize(AST_Dot, function(self, compressor) {
|
17043
17351
|
const parent = compressor.parent();
|
17044
17352
|
if (is_lhs(self, parent)) return self;
|
@@ -17089,6 +17397,9 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
17089
17397
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
17090
17398
|
return best_of(compressor, ev, self);
|
17091
17399
|
}
|
17400
|
+
if (self.optional && is_nullish(self.expression)) {
|
17401
|
+
return make_node(AST_Undefined, self);
|
17402
|
+
}
|
17092
17403
|
return self;
|
17093
17404
|
});
|
17094
17405
|
|
@@ -17172,10 +17483,10 @@ def_optimize(AST_Function, function(self, compressor) {
|
|
17172
17483
|
&& !self.is_generator
|
17173
17484
|
&& !self.uses_arguments
|
17174
17485
|
&& !self.pinned()) {
|
17175
|
-
const
|
17486
|
+
const uses_this = walk(self, node => {
|
17176
17487
|
if (node instanceof AST_This) return walk_abort;
|
17177
17488
|
});
|
17178
|
-
if (!
|
17489
|
+
if (!uses_this) return make_node(AST_Arrow, self, self).optimize(compressor);
|
17179
17490
|
}
|
17180
17491
|
return self;
|
17181
17492
|
});
|
@@ -17267,7 +17578,7 @@ function lift_key(self, compressor) {
|
|
17267
17578
|
if (!compressor.option("computed_props")) return self;
|
17268
17579
|
// save a comparison in the typical case
|
17269
17580
|
if (!(self.key instanceof AST_Constant)) return self;
|
17270
|
-
//
|
17581
|
+
// allow certain acceptable props as not all AST_Constants are true constants
|
17271
17582
|
if (self.key instanceof AST_String || self.key instanceof AST_Number) {
|
17272
17583
|
if (self.key.value === "__proto__") return self;
|
17273
17584
|
if (self.key.value == "constructor"
|
@@ -23301,6 +23612,8 @@ function mangle_properties(ast, options) {
|
|
23301
23612
|
} else if (node instanceof AST_Call
|
23302
23613
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
23303
23614
|
addStrings(node.args[1], add);
|
23615
|
+
} else if (node instanceof AST_Binary && node.operator === "in") {
|
23616
|
+
addStrings(node.left, add);
|
23304
23617
|
}
|
23305
23618
|
}));
|
23306
23619
|
|
@@ -23325,6 +23638,8 @@ function mangle_properties(ast, options) {
|
|
23325
23638
|
} else if (node instanceof AST_Call
|
23326
23639
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
23327
23640
|
node.args[1] = mangleStrings(node.args[1]);
|
23641
|
+
} else if (node instanceof AST_Binary && node.operator === "in") {
|
23642
|
+
node.left = mangleStrings(node.left);
|
23328
23643
|
}
|
23329
23644
|
}));
|
23330
23645
|
|
@@ -23557,7 +23872,11 @@ async function minify(files, options) {
|
|
23557
23872
|
}
|
23558
23873
|
if (timings) timings.rename = Date.now();
|
23559
23874
|
if (timings) timings.compress = Date.now();
|
23560
|
-
if (options.compress)
|
23875
|
+
if (options.compress) {
|
23876
|
+
toplevel = new Compressor(options.compress, {
|
23877
|
+
mangle_options: options.mangle
|
23878
|
+
}).compress(toplevel);
|
23879
|
+
}
|
23561
23880
|
if (timings) timings.scope = Date.now();
|
23562
23881
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
23563
23882
|
if (timings) timings.mangle = Date.now();
|
@@ -23704,6 +24023,7 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
23704
24023
|
options[name] = program[name];
|
23705
24024
|
}
|
23706
24025
|
});
|
24026
|
+
|
23707
24027
|
if ("ecma" in program) {
|
23708
24028
|
if (program.ecma != (program.ecma | 0)) fatal("ERROR: ecma must be an integer");
|
23709
24029
|
const ecma = program.ecma | 0;
|
@@ -23933,7 +24253,7 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
23933
24253
|
}
|
23934
24254
|
} else if (program.output) {
|
23935
24255
|
fs.writeFileSync(program.output, result.code);
|
23936
|
-
if (options.sourceMap.url !== "inline" && result.map) {
|
24256
|
+
if (options.sourceMap && options.sourceMap.url !== "inline" && result.map) {
|
23937
24257
|
fs.writeFileSync(program.output + ".map", result.map);
|
23938
24258
|
}
|
23939
24259
|
} else {
|