terser 1.2.3 → 1.2.4
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.
- 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
|