terser 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/terser/version.rb +1 -1
- data/lib/terser.js +280 -165
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74a43961686b1bf08bcaec1a1395f6f9bb4fd07ca66b6d154abed2e8b62c8e58
|
4
|
+
data.tar.gz: 2dea98bbf908aba6591e3aa2d2cce8edbed21cfee7b140a8377179c0821856a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3c6a287cd2101c155ea721e06615576d2328d63358ce7c1f5c4a13e81235a8baf59ac41d59e19e045956d9212baae2dbf2a10a7d9397cbd4272d3bd8ff2e4f9
|
7
|
+
data.tar.gz: f1f18ac66b8ea18431048e751355684c909bc919602a8f08747da95c31a6a59b8d98c220301ec14f97ec1cd2e2ec67219514bfe70c27a5ee6cb67bd208731574
|
data/CHANGELOG.md
CHANGED
data/lib/terser/version.rb
CHANGED
data/lib/terser.js
CHANGED
@@ -7571,6 +7571,19 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
7571
7571
|
});
|
7572
7572
|
},
|
7573
7573
|
|
7574
|
+
ImportExpression: function(M) {
|
7575
|
+
return new AST_Call({
|
7576
|
+
start: my_start_token(M),
|
7577
|
+
end: my_end_token(M),
|
7578
|
+
expression: from_moz({
|
7579
|
+
type: "Identifier",
|
7580
|
+
name: "import"
|
7581
|
+
}),
|
7582
|
+
optional: false,
|
7583
|
+
args: [from_moz(M.source)]
|
7584
|
+
});
|
7585
|
+
},
|
7586
|
+
|
7574
7587
|
ExportAllDeclaration: function(M) {
|
7575
7588
|
var foreign_name = M.exported == null ?
|
7576
7589
|
new AST_SymbolExportForeign({ name: "*" }) :
|
@@ -7638,6 +7651,11 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
7638
7651
|
args.value = { source, flags };
|
7639
7652
|
return new AST_RegExp(args);
|
7640
7653
|
}
|
7654
|
+
const bi = typeof M.value === "bigint" ? M.value.toString() : M.bigint;
|
7655
|
+
if (typeof bi === "string") {
|
7656
|
+
args.value = bi;
|
7657
|
+
return new AST_BigInt(args);
|
7658
|
+
}
|
7641
7659
|
if (val === null) return new AST_Null(args);
|
7642
7660
|
switch (typeof val) {
|
7643
7661
|
case "string":
|
@@ -7705,14 +7723,6 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
7705
7723
|
});
|
7706
7724
|
},
|
7707
7725
|
|
7708
|
-
BigIntLiteral(M) {
|
7709
|
-
return new AST_BigInt({
|
7710
|
-
start : my_start_token(M),
|
7711
|
-
end : my_end_token(M),
|
7712
|
-
value : M.value
|
7713
|
-
});
|
7714
|
-
},
|
7715
|
-
|
7716
7726
|
EmptyStatement: function(M) {
|
7717
7727
|
return new AST_EmptyStatement({
|
7718
7728
|
start: my_start_token(M),
|
@@ -8185,6 +8195,14 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
8185
8195
|
};
|
8186
8196
|
});
|
8187
8197
|
def_to_moz(AST_Call, function To_Moz_CallExpression(M) {
|
8198
|
+
if (M.expression instanceof AST_SymbolRef && M.expression.name === "import") {
|
8199
|
+
const [source] = M.args.map(to_moz);
|
8200
|
+
return {
|
8201
|
+
type: "ImportExpression",
|
8202
|
+
source,
|
8203
|
+
};
|
8204
|
+
}
|
8205
|
+
|
8188
8206
|
return {
|
8189
8207
|
type: "CallExpression",
|
8190
8208
|
callee: to_moz(M.expression),
|
@@ -8730,8 +8748,13 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
8730
8748
|
});
|
8731
8749
|
|
8732
8750
|
def_to_moz(AST_BigInt, M => ({
|
8733
|
-
type: "
|
8734
|
-
value
|
8751
|
+
type: "Literal",
|
8752
|
+
// value cannot be represented natively
|
8753
|
+
// see: https://github.com/estree/estree/blob/master/es2020.md#bigintliteral
|
8754
|
+
value: null,
|
8755
|
+
// `M.value` is a string that may be a hex number representation.
|
8756
|
+
// but "bigint" property should have only decimal digits
|
8757
|
+
bigint: typeof BigInt === "function" ? BigInt(M.value).toString() : M.value,
|
8735
8758
|
}));
|
8736
8759
|
|
8737
8760
|
AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
|
@@ -10276,7 +10299,9 @@ function OutputStream(options) {
|
|
10276
10299
|
AST_Arrow.DEFMETHOD("_do_print", function(output) {
|
10277
10300
|
var self = this;
|
10278
10301
|
var parent = output.parent();
|
10279
|
-
var needs_parens = (parent instanceof AST_Binary &&
|
10302
|
+
var needs_parens = (parent instanceof AST_Binary &&
|
10303
|
+
!(parent instanceof AST_Assign) &&
|
10304
|
+
!(parent instanceof AST_DefaultAssign)) ||
|
10280
10305
|
parent instanceof AST_Unary ||
|
10281
10306
|
(parent instanceof AST_Call && self === parent.expression);
|
10282
10307
|
if (needs_parens) { output.print("("); }
|
@@ -11649,7 +11674,7 @@ function redefined_catch_def(def) {
|
|
11649
11674
|
}
|
11650
11675
|
}
|
11651
11676
|
|
11652
|
-
AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope =
|
11677
|
+
AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = undefined, toplevel = this } = {}) {
|
11653
11678
|
options = defaults(options, {
|
11654
11679
|
cache: null,
|
11655
11680
|
ie8: false,
|
@@ -11973,7 +11998,7 @@ AST_Scope.DEFMETHOD("add_child_scope", function (scope) {
|
|
11973
11998
|
scope.parent_scope = this;
|
11974
11999
|
|
11975
12000
|
// Propagate to this.uses_arguments from arrow functions
|
11976
|
-
if ((scope instanceof AST_Arrow) && !this.uses_arguments) {
|
12001
|
+
if ((scope instanceof AST_Arrow) && (this instanceof AST_Lambda && !this.uses_arguments)) {
|
11977
12002
|
this.uses_arguments = walk(scope, node => {
|
11978
12003
|
if (
|
11979
12004
|
node instanceof AST_SymbolRef
|
@@ -13040,6 +13065,23 @@ function make_sequence(orig, expressions) {
|
|
13040
13065
|
});
|
13041
13066
|
}
|
13042
13067
|
|
13068
|
+
function make_empty_function(self) {
|
13069
|
+
return make_node(AST_Function, self, {
|
13070
|
+
uses_arguments: false,
|
13071
|
+
argnames: [],
|
13072
|
+
body: [],
|
13073
|
+
is_generator: false,
|
13074
|
+
async: false,
|
13075
|
+
variables: new Map(),
|
13076
|
+
uses_with: false,
|
13077
|
+
uses_eval: false,
|
13078
|
+
parent_scope: null,
|
13079
|
+
enclosed: [],
|
13080
|
+
cname: 0,
|
13081
|
+
block_scope: undefined,
|
13082
|
+
});
|
13083
|
+
}
|
13084
|
+
|
13043
13085
|
function make_node_from_constant(val, orig) {
|
13044
13086
|
switch (typeof val) {
|
13045
13087
|
case "string":
|
@@ -13266,9 +13308,9 @@ function is_reachable(scope_node, defs) {
|
|
13266
13308
|
}
|
13267
13309
|
|
13268
13310
|
/** Check if a ref refers to the name of a function/class it's defined within */
|
13269
|
-
function is_recursive_ref(
|
13311
|
+
function is_recursive_ref(tw, def) {
|
13270
13312
|
var node;
|
13271
|
-
for (var i = 0; node =
|
13313
|
+
for (var i = 0; node = tw.parent(i); i++) {
|
13272
13314
|
if (node instanceof AST_Lambda || node instanceof AST_Class) {
|
13273
13315
|
var name = node.name;
|
13274
13316
|
if (name && name.definition() === def) {
|
@@ -13834,7 +13876,7 @@ function is_nullish(node, compressor) {
|
|
13834
13876
|
return any(this.definitions, compressor);
|
13835
13877
|
});
|
13836
13878
|
def_has_side_effects(AST_VarDef, function() {
|
13837
|
-
return this.value;
|
13879
|
+
return this.value != null;
|
13838
13880
|
});
|
13839
13881
|
def_has_side_effects(AST_TemplateSegment, return_false);
|
13840
13882
|
def_has_side_effects(AST_TemplateString, function(compressor) {
|
@@ -14393,6 +14435,54 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
14393
14435
|
}
|
14394
14436
|
}
|
14395
14437
|
|
14438
|
+
/**
|
14439
|
+
* Check if a node may be used by the expression it's in
|
14440
|
+
* void (0, 1, {node}, 2) -> false
|
14441
|
+
* console.log(0, {node}) -> true
|
14442
|
+
*/
|
14443
|
+
function is_used_in_expression(tw) {
|
14444
|
+
for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
|
14445
|
+
if (parent instanceof AST_Sequence) {
|
14446
|
+
const nth_expression = parent.expressions.indexOf(node);
|
14447
|
+
if (nth_expression !== parent.expressions.length - 1) {
|
14448
|
+
// Detect (0, x.noThis)() constructs
|
14449
|
+
const grandparent = tw.parent(p + 2);
|
14450
|
+
if (
|
14451
|
+
parent.expressions.length > 2
|
14452
|
+
|| parent.expressions.length === 1
|
14453
|
+
|| !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
|
14454
|
+
) {
|
14455
|
+
return false;
|
14456
|
+
}
|
14457
|
+
return true;
|
14458
|
+
} else {
|
14459
|
+
continue;
|
14460
|
+
}
|
14461
|
+
}
|
14462
|
+
if (parent instanceof AST_Unary) {
|
14463
|
+
const op = parent.operator;
|
14464
|
+
if (op === "void") {
|
14465
|
+
return false;
|
14466
|
+
}
|
14467
|
+
if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
|
14468
|
+
continue;
|
14469
|
+
}
|
14470
|
+
}
|
14471
|
+
if (
|
14472
|
+
parent instanceof AST_SimpleStatement
|
14473
|
+
|| parent instanceof AST_LabeledStatement
|
14474
|
+
) {
|
14475
|
+
return false;
|
14476
|
+
}
|
14477
|
+
if (parent instanceof AST_Scope) {
|
14478
|
+
return false;
|
14479
|
+
}
|
14480
|
+
return true;
|
14481
|
+
}
|
14482
|
+
|
14483
|
+
return true;
|
14484
|
+
}
|
14485
|
+
|
14396
14486
|
/***********************************************************************
|
14397
14487
|
|
14398
14488
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
@@ -14577,14 +14667,25 @@ def_eval(AST_Object, function (compressor, depth) {
|
|
14577
14667
|
var non_converting_unary = makePredicate("! typeof void");
|
14578
14668
|
def_eval(AST_UnaryPrefix, function (compressor, depth) {
|
14579
14669
|
var e = this.expression;
|
14580
|
-
// Function would be evaluated to an array and so typeof would
|
14581
|
-
// incorrectly return 'object'. Hence making is a special case.
|
14582
14670
|
if (compressor.option("typeofs")
|
14583
|
-
&& this.operator == "typeof"
|
14584
|
-
|
14671
|
+
&& this.operator == "typeof") {
|
14672
|
+
// Function would be evaluated to an array and so typeof would
|
14673
|
+
// incorrectly return 'object'. Hence making is a special case.
|
14674
|
+
if (e instanceof AST_Lambda
|
14585
14675
|
|| e instanceof AST_SymbolRef
|
14586
|
-
&& e.fixed_value() instanceof AST_Lambda)
|
14587
|
-
|
14676
|
+
&& e.fixed_value() instanceof AST_Lambda) {
|
14677
|
+
return typeof function () { };
|
14678
|
+
}
|
14679
|
+
if (
|
14680
|
+
(e instanceof AST_Object
|
14681
|
+
|| e instanceof AST_Array
|
14682
|
+
|| (e instanceof AST_SymbolRef
|
14683
|
+
&& (e.fixed_value() instanceof AST_Object
|
14684
|
+
|| e.fixed_value() instanceof AST_Array)))
|
14685
|
+
&& !e.has_side_effects(compressor)
|
14686
|
+
) {
|
14687
|
+
return typeof {};
|
14688
|
+
}
|
14588
14689
|
}
|
14589
14690
|
if (!non_converting_unary.has(this.operator))
|
14590
14691
|
depth++;
|
@@ -15272,7 +15373,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15272
15373
|
}
|
15273
15374
|
var var_defs_by_id = new Map();
|
15274
15375
|
var initializations = new Map();
|
15275
|
-
var self_referential_classes = new Set();
|
15276
15376
|
|
15277
15377
|
// pass 1: find out which symbols are directly used in
|
15278
15378
|
// this scope (not in nested scopes).
|
@@ -15287,8 +15387,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15287
15387
|
}
|
15288
15388
|
if (node === self) return;
|
15289
15389
|
if (node instanceof AST_Class && node.has_side_effects(compressor)) {
|
15290
|
-
if (node.is_self_referential())
|
15291
|
-
|
15390
|
+
if (node.is_self_referential()) {
|
15391
|
+
descend();
|
15392
|
+
} else {
|
15393
|
+
node.visit_nondeferred_class_parts(tw);
|
15394
|
+
}
|
15292
15395
|
}
|
15293
15396
|
if (node instanceof AST_Defun || node instanceof AST_DefClass) {
|
15294
15397
|
var node_def = node.name.definition();
|
@@ -15352,9 +15455,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15352
15455
|
init.walk(tw);
|
15353
15456
|
});
|
15354
15457
|
});
|
15355
|
-
self_referential_classes.forEach(function (cls) {
|
15356
|
-
cls.walk(tw);
|
15357
|
-
});
|
15358
15458
|
// pass 3: we should drop declarations not in_use
|
15359
15459
|
var tt = new TreeTransformer(
|
15360
15460
|
function before(node, descend, in_list) {
|
@@ -15390,7 +15490,13 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15390
15490
|
if (!in_use_ids.has(def.id) || def.orig.length > 1) node.name = null;
|
15391
15491
|
}
|
15392
15492
|
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
15393
|
-
var trim =
|
15493
|
+
var trim =
|
15494
|
+
!compressor.option("keep_fargs")
|
15495
|
+
// Is this an IIFE that won't refer to its name?
|
15496
|
+
|| parent instanceof AST_Call
|
15497
|
+
&& parent.expression === node
|
15498
|
+
&& !node.pinned()
|
15499
|
+
&& (!node.name || node.name.unreferenced());
|
15394
15500
|
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
15395
15501
|
var sym = a[i];
|
15396
15502
|
if (sym instanceof AST_Expansion) {
|
@@ -15631,45 +15737,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15631
15737
|
}
|
15632
15738
|
});
|
15633
15739
|
|
15634
|
-
/**
|
15635
|
-
* Check if a node may be used by the expression it's in
|
15636
|
-
* void (0, 1, {node}, 2) -> false
|
15637
|
-
* console.log(0, {node}) -> true
|
15638
|
-
*/
|
15639
|
-
function is_used_in_expression(tw) {
|
15640
|
-
for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
|
15641
|
-
if (parent instanceof AST_Sequence) {
|
15642
|
-
const nth_expression = parent.expressions.indexOf(node);
|
15643
|
-
if (nth_expression !== parent.expressions.length - 1) {
|
15644
|
-
// Detect (0, x.noThis)() constructs
|
15645
|
-
const grandparent = tw.parent(p + 2);
|
15646
|
-
if (
|
15647
|
-
parent.expressions.length > 2
|
15648
|
-
|| parent.expressions.length === 1
|
15649
|
-
|| !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
|
15650
|
-
) {
|
15651
|
-
return false;
|
15652
|
-
}
|
15653
|
-
return true;
|
15654
|
-
} else {
|
15655
|
-
continue;
|
15656
|
-
}
|
15657
|
-
}
|
15658
|
-
if (parent instanceof AST_Unary) {
|
15659
|
-
const op = parent.operator;
|
15660
|
-
if (op === "void") {
|
15661
|
-
return false;
|
15662
|
-
}
|
15663
|
-
if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
|
15664
|
-
continue;
|
15665
|
-
}
|
15666
|
-
}
|
15667
|
-
return true;
|
15668
|
-
}
|
15669
|
-
|
15670
|
-
return true;
|
15671
|
-
}
|
15672
|
-
|
15673
15740
|
/***********************************************************************
|
15674
15741
|
|
15675
15742
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
@@ -16106,28 +16173,50 @@ function mark_lambda(tw, descend, compressor) {
|
|
16106
16173
|
* // use defined_after
|
16107
16174
|
* }
|
16108
16175
|
*
|
16109
|
-
*
|
16176
|
+
* Or even indirectly:
|
16177
|
+
*
|
16178
|
+
* B();
|
16179
|
+
* var defined_after = true;
|
16180
|
+
* function A() {
|
16181
|
+
* // use defined_after
|
16182
|
+
* }
|
16183
|
+
* function B() {
|
16184
|
+
* A();
|
16185
|
+
* }
|
16186
|
+
*
|
16187
|
+
* Access a variable before declaration will either throw a ReferenceError
|
16188
|
+
* (if the variable is declared with `let` or `const`),
|
16189
|
+
* or get an `undefined` (if the variable is declared with `var`).
|
16190
|
+
*
|
16191
|
+
* If the variable is inlined into the function, the behavior will change.
|
16192
|
+
*
|
16193
|
+
* This function is called on the parent to disallow inlining of such variables,
|
16110
16194
|
*/
|
16111
16195
|
function handle_defined_after_hoist(parent) {
|
16112
16196
|
const defuns = [];
|
16113
16197
|
walk(parent, node => {
|
16114
16198
|
if (node === parent) return;
|
16115
|
-
if (node instanceof AST_Defun)
|
16199
|
+
if (node instanceof AST_Defun) {
|
16200
|
+
defuns.push(node);
|
16201
|
+
return true;
|
16202
|
+
}
|
16116
16203
|
if (
|
16117
16204
|
node instanceof AST_Scope
|
16118
16205
|
|| node instanceof AST_SimpleStatement
|
16119
16206
|
) return true;
|
16120
16207
|
});
|
16121
16208
|
|
16209
|
+
// `defun` id to array of `defun` it uses
|
16210
|
+
const defun_dependencies_map = new Map();
|
16211
|
+
// `defun` id to array of enclosing `def` that are used by the function
|
16212
|
+
const dependencies_map = new Map();
|
16213
|
+
// all symbol ids that will be tracked for read/write
|
16122
16214
|
const symbols_of_interest = new Set();
|
16123
16215
|
const defuns_of_interest = new Set();
|
16124
|
-
const potential_conflicts = [];
|
16125
16216
|
|
16126
16217
|
for (const defun of defuns) {
|
16127
16218
|
const fname_def = defun.name.definition();
|
16128
|
-
const
|
16129
|
-
d => d !== defun && d.enclosed.indexOf(fname_def) !== -1
|
16130
|
-
);
|
16219
|
+
const enclosing_defs = [];
|
16131
16220
|
|
16132
16221
|
for (const def of defun.enclosed) {
|
16133
16222
|
if (
|
@@ -16138,93 +16227,107 @@ function handle_defined_after_hoist(parent) {
|
|
16138
16227
|
continue;
|
16139
16228
|
}
|
16140
16229
|
|
16141
|
-
|
16230
|
+
symbols_of_interest.add(def.id);
|
16231
|
+
|
16232
|
+
// found a reference to another function
|
16142
16233
|
if (
|
16143
16234
|
def.assignments === 0
|
16144
16235
|
&& def.orig.length === 1
|
16145
16236
|
&& def.orig[0] instanceof AST_SymbolDefun
|
16146
16237
|
) {
|
16147
|
-
|
16148
|
-
|
16238
|
+
defuns_of_interest.add(def.id);
|
16239
|
+
symbols_of_interest.add(def.id);
|
16240
|
+
|
16241
|
+
defuns_of_interest.add(fname_def.id);
|
16242
|
+
symbols_of_interest.add(fname_def.id);
|
16243
|
+
|
16244
|
+
if (!defun_dependencies_map.has(fname_def.id)) {
|
16245
|
+
defun_dependencies_map.set(fname_def.id, []);
|
16246
|
+
}
|
16247
|
+
defun_dependencies_map.get(fname_def.id).push(def.id);
|
16149
16248
|
|
16150
|
-
if (found_self_ref_in_other_defuns) {
|
16151
|
-
def.fixed = false;
|
16152
16249
|
continue;
|
16153
16250
|
}
|
16154
16251
|
|
16155
|
-
|
16156
|
-
|
16157
|
-
|
16252
|
+
enclosing_defs.push(def);
|
16253
|
+
}
|
16254
|
+
|
16255
|
+
if (enclosing_defs.length) {
|
16256
|
+
dependencies_map.set(fname_def.id, enclosing_defs);
|
16257
|
+
defuns_of_interest.add(fname_def.id);
|
16158
16258
|
symbols_of_interest.add(fname_def.id);
|
16159
|
-
defuns_of_interest.add(defun);
|
16160
16259
|
}
|
16161
16260
|
}
|
16162
16261
|
|
16163
|
-
//
|
16164
|
-
if (
|
16165
|
-
|
16166
|
-
|
16167
|
-
const found_symbols = [];
|
16168
|
-
// Indices of `found_symbols` which are writes
|
16169
|
-
const found_symbol_writes = new Set();
|
16170
|
-
// Defun ranges are recorded because we don't care if a function uses the def internally
|
16171
|
-
const defun_ranges = new Map();
|
16262
|
+
// No defuns use outside constants
|
16263
|
+
if (!dependencies_map.size) {
|
16264
|
+
return;
|
16265
|
+
}
|
16172
16266
|
|
16173
|
-
|
16174
|
-
|
16175
|
-
|
16176
|
-
|
16177
|
-
|
16178
|
-
|
16267
|
+
// Increment to count "symbols of interest" (defuns or defs) that we found.
|
16268
|
+
// These are tracked in AST order so we can check which is after which.
|
16269
|
+
let symbol_index = 1;
|
16270
|
+
// Map a defun ID to its first read (a `symbol_index`)
|
16271
|
+
const defun_first_read_map = new Map();
|
16272
|
+
// Map a symbol ID to its last write (a `symbol_index`)
|
16273
|
+
const symbol_last_write_map = new Map();
|
16179
16274
|
|
16180
|
-
|
16181
|
-
|
16182
|
-
|
16183
|
-
// if we found a defun on the list, mark IN_DEFUN=id and descend
|
16275
|
+
walk_parent(parent, (node, walk_info) => {
|
16276
|
+
if (node instanceof AST_Symbol && node.thedef) {
|
16277
|
+
const id = node.definition().id;
|
16184
16278
|
|
16185
|
-
|
16186
|
-
|
16187
|
-
|
16188
|
-
|
16189
|
-
|
16190
|
-
|
16191
|
-
found_symbols.push(id);
|
16279
|
+
symbol_index++;
|
16280
|
+
|
16281
|
+
// Track last-writes to symbols
|
16282
|
+
if (symbols_of_interest.has(id)) {
|
16283
|
+
if (node instanceof AST_SymbolDeclaration || is_lhs(node, walk_info.parent())) {
|
16284
|
+
symbol_last_write_map.set(id, symbol_index);
|
16192
16285
|
}
|
16193
16286
|
}
|
16194
|
-
})));
|
16195
16287
|
|
16196
|
-
|
16197
|
-
|
16288
|
+
// Track first-reads of defuns (refined later)
|
16289
|
+
if (defuns_of_interest.has(id)) {
|
16290
|
+
if (!defun_first_read_map.has(id) && !is_recursive_ref(walk_info, id)) {
|
16291
|
+
defun_first_read_map.set(id, symbol_index);
|
16292
|
+
}
|
16293
|
+
}
|
16294
|
+
}
|
16295
|
+
});
|
16198
16296
|
|
16199
|
-
|
16200
|
-
|
16201
|
-
|
16297
|
+
// Refine `defun_first_read_map` to be as high as possible
|
16298
|
+
for (const [defun, defun_first_read] of defun_first_read_map) {
|
16299
|
+
// Update all depdencies of `defun`
|
16300
|
+
const queue = new Set(defun_dependencies_map.get(defun));
|
16301
|
+
for (const enclosed_defun of queue) {
|
16302
|
+
let enclosed_defun_first_read = defun_first_read_map.get(enclosed_defun);
|
16303
|
+
if (enclosed_defun_first_read != null && enclosed_defun_first_read < defun_first_read) {
|
16304
|
+
continue;
|
16305
|
+
}
|
16202
16306
|
|
16203
|
-
|
16204
|
-
index = found_symbols.indexOf(sym_id, index);
|
16307
|
+
defun_first_read_map.set(enclosed_defun, defun_first_read);
|
16205
16308
|
|
16206
|
-
|
16207
|
-
|
16208
|
-
|
16209
|
-
|
16210
|
-
|
16211
|
-
} else if (must_be_write && !found_symbol_writes.has(index)) {
|
16212
|
-
index++;
|
16213
|
-
continue;
|
16214
|
-
} else {
|
16215
|
-
break;
|
16216
|
-
}
|
16217
|
-
}
|
16309
|
+
for (const enclosed_enclosed_defun of defun_dependencies_map.get(enclosed_defun) || []) {
|
16310
|
+
queue.add(enclosed_enclosed_defun);
|
16311
|
+
}
|
16312
|
+
}
|
16313
|
+
}
|
16218
16314
|
|
16219
|
-
|
16220
|
-
|
16315
|
+
// ensure write-then-read order, otherwise clear `fixed`
|
16316
|
+
// This is safe because last-writes (found_symbol_writes) are assumed to be as late as possible, and first-reads (defun_first_read_map) are assumed to be as early as possible.
|
16317
|
+
for (const [defun, defs] of dependencies_map) {
|
16318
|
+
const defun_first_read = defun_first_read_map.get(defun);
|
16319
|
+
if (defun_first_read === undefined) {
|
16320
|
+
continue;
|
16321
|
+
}
|
16221
16322
|
|
16222
|
-
|
16223
|
-
|
16323
|
+
for (const def of defs) {
|
16324
|
+
if (def.fixed === false) {
|
16325
|
+
continue;
|
16326
|
+
}
|
16224
16327
|
|
16225
|
-
|
16328
|
+
let def_last_write = symbol_last_write_map.get(def.id) || 0;
|
16226
16329
|
|
16227
|
-
if (
|
16330
|
+
if (defun_first_read < def_last_write) {
|
16228
16331
|
def.fixed = false;
|
16229
16332
|
}
|
16230
16333
|
}
|
@@ -18858,9 +18961,8 @@ def_optimize(AST_Node, function(self) {
|
|
18858
18961
|
});
|
18859
18962
|
|
18860
18963
|
AST_Toplevel.DEFMETHOD("drop_console", function(options) {
|
18861
|
-
|
18862
|
-
|
18863
|
-
return this.transform(new TreeTransformer(function(self) {
|
18964
|
+
const isArray = Array.isArray(options);
|
18965
|
+
const tt = new TreeTransformer(function(self) {
|
18864
18966
|
if (self.TYPE !== "Call") {
|
18865
18967
|
return;
|
18866
18968
|
}
|
@@ -18871,18 +18973,35 @@ AST_Toplevel.DEFMETHOD("drop_console", function(options) {
|
|
18871
18973
|
return;
|
18872
18974
|
}
|
18873
18975
|
|
18874
|
-
if (isArray && options.
|
18976
|
+
if (isArray && !options.includes(exp.property)) {
|
18875
18977
|
return;
|
18876
18978
|
}
|
18877
18979
|
|
18878
18980
|
var name = exp.expression;
|
18981
|
+
var depth = 2;
|
18879
18982
|
while (name.expression) {
|
18880
18983
|
name = name.expression;
|
18984
|
+
depth++;
|
18881
18985
|
}
|
18986
|
+
|
18882
18987
|
if (is_undeclared_ref(name) && name.name == "console") {
|
18883
|
-
|
18988
|
+
if (
|
18989
|
+
depth === 3
|
18990
|
+
&& !["call", "apply"].includes(exp.property)
|
18991
|
+
&& is_used_in_expression(tt)
|
18992
|
+
) {
|
18993
|
+
// a (used) call to Function.prototype methods (eg: console.log.bind(console))
|
18994
|
+
// but not .call and .apply which would also return undefined.
|
18995
|
+
exp.expression = make_empty_function(self);
|
18996
|
+
set_flag(exp.expression, SQUEEZED);
|
18997
|
+
self.args = [];
|
18998
|
+
} else {
|
18999
|
+
return make_node(AST_Undefined, self);
|
19000
|
+
}
|
18884
19001
|
}
|
18885
|
-
})
|
19002
|
+
});
|
19003
|
+
|
19004
|
+
return this.transform(tt);
|
18886
19005
|
});
|
18887
19006
|
|
18888
19007
|
AST_Node.DEFMETHOD("equivalent_to", function(node) {
|
@@ -19581,7 +19700,9 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
19581
19700
|
eliminate_branch(branch, body[body.length - 1]);
|
19582
19701
|
continue;
|
19583
19702
|
}
|
19584
|
-
if (exp instanceof AST_Node
|
19703
|
+
if (exp instanceof AST_Node && !exp.has_side_effects(compressor)) {
|
19704
|
+
exp = branch.expression.tail_node().evaluate(compressor);
|
19705
|
+
}
|
19585
19706
|
if (exp === value) {
|
19586
19707
|
exact_match = branch;
|
19587
19708
|
if (default_branch) {
|
@@ -19763,12 +19884,9 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
19763
19884
|
break DEFAULT;
|
19764
19885
|
}
|
19765
19886
|
|
19766
|
-
let sideEffect = body.find(
|
19767
|
-
|
19768
|
-
|
19769
|
-
&& branch.expression.has_side_effects(compressor)
|
19770
|
-
);
|
19771
|
-
});
|
19887
|
+
let sideEffect = body.find(
|
19888
|
+
branch => branch !== default_or_exact && branch.expression.has_side_effects(compressor)
|
19889
|
+
);
|
19772
19890
|
// If no cases cause a side-effect, we can eliminate the switch entirely.
|
19773
19891
|
if (!sideEffect) {
|
19774
19892
|
return make_node(AST_BlockStatement, self, {
|
@@ -19876,9 +19994,10 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
19876
19994
|
right: branch.expression,
|
19877
19995
|
}),
|
19878
19996
|
body: consequent,
|
19879
|
-
alternative: null
|
19880
|
-
})
|
19881
|
-
|
19997
|
+
alternative: null,
|
19998
|
+
}),
|
19999
|
+
always,
|
20000
|
+
],
|
19882
20001
|
}).optimize(compressor);
|
19883
20002
|
}
|
19884
20003
|
return self;
|
@@ -19901,13 +20020,12 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
19901
20020
|
let pblock = make_node(AST_BlockStatement, prev, { body: pbody });
|
19902
20021
|
return bblock.equivalent_to(pblock);
|
19903
20022
|
}
|
19904
|
-
function statement(
|
19905
|
-
return make_node(AST_SimpleStatement,
|
19906
|
-
body: expression
|
19907
|
-
});
|
20023
|
+
function statement(body) {
|
20024
|
+
return make_node(AST_SimpleStatement, body, { body });
|
19908
20025
|
}
|
19909
20026
|
function has_nested_break(root) {
|
19910
20027
|
let has_break = false;
|
20028
|
+
|
19911
20029
|
let tw = new TreeWalker(node => {
|
19912
20030
|
if (has_break) return true;
|
19913
20031
|
if (node instanceof AST_Lambda) return true;
|
@@ -20260,10 +20378,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
20260
20378
|
&& is_undeclared_ref(exp)
|
20261
20379
|
&& exp.name == "Function") {
|
20262
20380
|
// new Function() => function(){}
|
20263
|
-
if (self.args.length == 0) return
|
20264
|
-
argnames: [],
|
20265
|
-
body: []
|
20266
|
-
}).optimize(compressor);
|
20381
|
+
if (self.args.length == 0) return make_empty_function(self).optimize(compressor);
|
20267
20382
|
if (self.args.every((x) => x instanceof AST_String)) {
|
20268
20383
|
// quite a corner-case, but we can handle it:
|
20269
20384
|
// https://github.com/mishoo/UglifyJS2/issues/203
|
@@ -22023,10 +22138,7 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
22023
22138
|
});
|
22024
22139
|
break;
|
22025
22140
|
case "Function":
|
22026
|
-
self.expression =
|
22027
|
-
argnames: [],
|
22028
|
-
body: []
|
22029
|
-
});
|
22141
|
+
self.expression = make_empty_function(self.expression);
|
22030
22142
|
break;
|
22031
22143
|
case "Number":
|
22032
22144
|
self.expression = make_node(AST_Number, self.expression, {
|
@@ -30779,6 +30891,7 @@ var domprops = [
|
|
30779
30891
|
"uint32",
|
30780
30892
|
"uint8",
|
30781
30893
|
"uint8Clamped",
|
30894
|
+
"unadjustedMovement",
|
30782
30895
|
"unclippedDepth",
|
30783
30896
|
"unconfigure",
|
30784
30897
|
"undefined",
|
@@ -31570,7 +31683,9 @@ function mangle_properties(ast, options, annotated_props = find_annotated_props(
|
|
31570
31683
|
} else if (node instanceof AST_ObjectProperty) {
|
31571
31684
|
// setter, getter, method or class field
|
31572
31685
|
if (!keep_quoted || !node.quote) {
|
31573
|
-
|
31686
|
+
if (!node.computed_key()) {
|
31687
|
+
node.key.name = mangle(node.key.name);
|
31688
|
+
}
|
31574
31689
|
}
|
31575
31690
|
} else if (node instanceof AST_Dot) {
|
31576
31691
|
if (!keep_quoted || !node.quote) {
|
@@ -31947,7 +32062,7 @@ function* minify_sync_or_async(files, options, _fs_module) {
|
|
31947
32062
|
if (node.block_scope) {
|
31948
32063
|
node.block_scope.variables = undefined;
|
31949
32064
|
node.block_scope.enclosed = undefined;
|
31950
|
-
node.parent_scope = undefined;
|
32065
|
+
node.block_scope.parent_scope = undefined;
|
31951
32066
|
}
|
31952
32067
|
});
|
31953
32068
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Rosicky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
143
|
+
rubygems_version: 3.5.16
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: Ruby wrapper for Terser JavaScript compressor
|