terser 5.20.0 → 5.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +3 -2
- package/dist/bundle.min.js +140 -111
- package/lib/compress/common.js +1 -1
- package/lib/compress/drop-unused.js +10 -8
- package/lib/compress/global-defs.js +92 -0
- package/lib/compress/index.js +37 -24
- package/lib/compress/inference.js +1 -79
- package/lib/compress/inline.js +10 -3
- package/lib/output.js +2 -1
- package/lib/scope.js +6 -0
- package/lib/size.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.22.0
|
4
|
+
- Do not `unsafe`ly shorten expressions like a?.toString() when they're conditional.
|
5
|
+
- Avoid running drop_unused in nodes that aren't scopes. Fixes a rare crash.
|
6
|
+
- When 'module' is enabled, assume strict mode when figuring out scopes.
|
7
|
+
|
8
|
+
## v5.21.0
|
9
|
+
- Do not inline functions that would be retained in the toplevel (as this would cause code duplication).
|
10
|
+
- Fix precedence of arrow function and ternary operator when formatting output.
|
11
|
+
|
3
12
|
## v5.20.0
|
4
13
|
- Passing `minify()` zero files will now throw a clean exception (#1450)
|
5
14
|
- `drop_console` supports passing in an array of `console.*` method names (#1445)
|
package/README.md
CHANGED
@@ -154,7 +154,8 @@ a double dash to prevent input files being used as option arguments:
|
|
154
154
|
--keep-fnames Do not mangle/drop function names. Useful for
|
155
155
|
code relying on Function.prototype.name.
|
156
156
|
--module Input is an ES6 module. If `compress` or `mangle` is
|
157
|
-
enabled then the `toplevel` option
|
157
|
+
enabled then the `toplevel` option, as well as strict mode,
|
158
|
+
will be enabled.
|
158
159
|
--name-cache <file> File to hold mangled name mappings.
|
159
160
|
--safari10 Support non-standard Safari 10/11.
|
160
161
|
Equivalent to setting `safari10: true` in `minify()`
|
@@ -912,7 +913,7 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
|
|
912
913
|
[compress option](#compress-options).
|
913
914
|
|
914
915
|
- `module` (default `false`) -- Pass `true` an ES6 modules, where the toplevel
|
915
|
-
scope is not the global scope. Implies `toplevel
|
916
|
+
scope is not the global scope. Implies `toplevel` and assumes input code is strict mode JS.
|
916
917
|
|
917
918
|
- `nth_identifier` (default: an internal mangler that weights based on character
|
918
919
|
frequency analysis) -- Pass an object with a `get(n)` function that converts an
|
package/dist/bundle.min.js
CHANGED
@@ -9742,7 +9742,8 @@ function OutputStream(options) {
|
|
9742
9742
|
) {
|
9743
9743
|
return true;
|
9744
9744
|
}
|
9745
|
-
return p instanceof AST_PropAccess && p.expression === this
|
9745
|
+
return p instanceof AST_PropAccess && p.expression === this
|
9746
|
+
|| p instanceof AST_Conditional && p.condition === this;
|
9746
9747
|
});
|
9747
9748
|
|
9748
9749
|
// same goes for an object literal (as in AST_Function), because
|
@@ -11572,6 +11573,7 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
11572
11573
|
cache: null,
|
11573
11574
|
ie8: false,
|
11574
11575
|
safari10: false,
|
11576
|
+
module: false,
|
11575
11577
|
});
|
11576
11578
|
|
11577
11579
|
if (!(toplevel instanceof AST_Toplevel)) {
|
@@ -11739,6 +11741,11 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
11739
11741
|
);
|
11740
11742
|
}
|
11741
11743
|
});
|
11744
|
+
|
11745
|
+
if (options.module) {
|
11746
|
+
tw.directives["use strict"] = true;
|
11747
|
+
}
|
11748
|
+
|
11742
11749
|
this.walk(tw);
|
11743
11750
|
|
11744
11751
|
function mark_export(def, level) {
|
@@ -12423,7 +12430,7 @@ const base54 = (() => {
|
|
12423
12430
|
|
12424
12431
|
let mangle_options = undefined;
|
12425
12432
|
AST_Node.prototype.size = function (compressor, stack) {
|
12426
|
-
mangle_options = compressor && compressor.
|
12433
|
+
mangle_options = compressor && compressor._mangle_options;
|
12427
12434
|
|
12428
12435
|
let size = 0;
|
12429
12436
|
walk_parent(this, (node, info) => {
|
@@ -13190,7 +13197,7 @@ function retain_top_func(fn, compressor) {
|
|
13190
13197
|
&& fn instanceof AST_Defun
|
13191
13198
|
&& has_flag(fn, TOP)
|
13192
13199
|
&& fn.name
|
13193
|
-
&& compressor.top_retain(fn.name);
|
13200
|
+
&& compressor.top_retain(fn.name.definition());
|
13194
13201
|
}
|
13195
13202
|
|
13196
13203
|
/***********************************************************************
|
@@ -14039,80 +14046,6 @@ function is_lhs(node, parent) {
|
|
14039
14046
|
if (parent instanceof AST_ForIn && parent.init === node) return node;
|
14040
14047
|
}
|
14041
14048
|
|
14042
|
-
(function(def_find_defs) {
|
14043
|
-
function to_node(value, orig) {
|
14044
|
-
if (value instanceof AST_Node) {
|
14045
|
-
if (!(value instanceof AST_Constant)) {
|
14046
|
-
// Value may be a function, an array including functions and even a complex assign / block expression,
|
14047
|
-
// so it should never be shared in different places.
|
14048
|
-
// Otherwise wrong information may be used in the compression phase
|
14049
|
-
value = value.clone(true);
|
14050
|
-
}
|
14051
|
-
return make_node(value.CTOR, orig, value);
|
14052
|
-
}
|
14053
|
-
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
14054
|
-
elements: value.map(function(value) {
|
14055
|
-
return to_node(value, orig);
|
14056
|
-
})
|
14057
|
-
});
|
14058
|
-
if (value && typeof value == "object") {
|
14059
|
-
var props = [];
|
14060
|
-
for (var key in value) if (HOP(value, key)) {
|
14061
|
-
props.push(make_node(AST_ObjectKeyVal, orig, {
|
14062
|
-
key: key,
|
14063
|
-
value: to_node(value[key], orig)
|
14064
|
-
}));
|
14065
|
-
}
|
14066
|
-
return make_node(AST_Object, orig, {
|
14067
|
-
properties: props
|
14068
|
-
});
|
14069
|
-
}
|
14070
|
-
return make_node_from_constant(value, orig);
|
14071
|
-
}
|
14072
|
-
|
14073
|
-
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
|
14074
|
-
if (!compressor.option("global_defs")) return this;
|
14075
|
-
this.figure_out_scope({ ie8: compressor.option("ie8") });
|
14076
|
-
return this.transform(new TreeTransformer(function(node) {
|
14077
|
-
var def = node._find_defs(compressor, "");
|
14078
|
-
if (!def) return;
|
14079
|
-
var level = 0, child = node, parent;
|
14080
|
-
while (parent = this.parent(level++)) {
|
14081
|
-
if (!(parent instanceof AST_PropAccess)) break;
|
14082
|
-
if (parent.expression !== child) break;
|
14083
|
-
child = parent;
|
14084
|
-
}
|
14085
|
-
if (is_lhs(child, parent)) {
|
14086
|
-
return;
|
14087
|
-
}
|
14088
|
-
return def;
|
14089
|
-
}));
|
14090
|
-
});
|
14091
|
-
def_find_defs(AST_Node, noop);
|
14092
|
-
def_find_defs(AST_Chain, function(compressor, suffix) {
|
14093
|
-
return this.expression._find_defs(compressor, suffix);
|
14094
|
-
});
|
14095
|
-
def_find_defs(AST_Dot, function(compressor, suffix) {
|
14096
|
-
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
14097
|
-
});
|
14098
|
-
def_find_defs(AST_SymbolDeclaration, function() {
|
14099
|
-
if (!this.global()) return;
|
14100
|
-
});
|
14101
|
-
def_find_defs(AST_SymbolRef, function(compressor, suffix) {
|
14102
|
-
if (!this.global()) return;
|
14103
|
-
var defines = compressor.option("global_defs");
|
14104
|
-
var name = this.name + suffix;
|
14105
|
-
if (HOP(defines, name)) return to_node(defines[name], this);
|
14106
|
-
});
|
14107
|
-
def_find_defs(AST_ImportMeta, function(compressor, suffix) {
|
14108
|
-
var defines = compressor.option("global_defs");
|
14109
|
-
var name = "import.meta" + suffix;
|
14110
|
-
if (HOP(defines, name)) return to_node(defines[name], this);
|
14111
|
-
});
|
14112
|
-
})(function(node, func) {
|
14113
|
-
node.DEFMETHOD("_find_defs", func);
|
14114
|
-
});
|
14115
|
-
|
14116
14049
|
// method to negate an expression
|
14117
14050
|
(function(def_negate) {
|
14118
14051
|
function basic_negation(exp) {
|
@@ -15150,6 +15083,8 @@ const r_keep_assign = /keep_assign/;
|
|
15150
15083
|
AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
15151
15084
|
if (!compressor.option("unused")) return;
|
15152
15085
|
if (compressor.has_directive("use asm")) return;
|
15086
|
+
if (!this.variables) return; // not really a scope (eg: AST_Class)
|
15087
|
+
|
15153
15088
|
var self = this;
|
15154
15089
|
if (self.pinned()) return;
|
15155
15090
|
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
@@ -15169,7 +15104,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15169
15104
|
var fixed_ids = new Map();
|
15170
15105
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
15171
15106
|
self.variables.forEach(function(def) {
|
15172
|
-
if (compressor.top_retain(def)
|
15107
|
+
if (compressor.top_retain(def)) {
|
15173
15108
|
in_use_ids.set(def.id, def);
|
15174
15109
|
}
|
15175
15110
|
});
|
@@ -15184,9 +15119,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15184
15119
|
node.argnames.forEach(function(argname) {
|
15185
15120
|
if (!(argname instanceof AST_SymbolDeclaration)) return;
|
15186
15121
|
var def = argname.definition();
|
15187
|
-
|
15188
|
-
in_use_ids.set(def.id, def);
|
15189
|
-
}
|
15122
|
+
in_use_ids.set(def.id, def);
|
15190
15123
|
});
|
15191
15124
|
}
|
15192
15125
|
if (node === self) return;
|
@@ -15199,7 +15132,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15199
15132
|
var node_def = node.name.definition();
|
15200
15133
|
const in_export = tw.parent() instanceof AST_Export;
|
15201
15134
|
if (in_export || !drop_funcs && scope === self) {
|
15202
|
-
if (node_def.global
|
15135
|
+
if (node_def.global) {
|
15203
15136
|
in_use_ids.set(node_def.id, node_def);
|
15204
15137
|
}
|
15205
15138
|
}
|
@@ -15207,10 +15140,12 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15207
15140
|
map_add(initializations, node_def.id, node);
|
15208
15141
|
return true; // don't go in nested scopes
|
15209
15142
|
}
|
15210
|
-
|
15143
|
+
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
15144
|
+
const in_root_scope = scope === self;
|
15145
|
+
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
15211
15146
|
map_add(var_defs_by_id, node.definition().id, node);
|
15212
15147
|
}
|
15213
|
-
if (node instanceof AST_Definitions &&
|
15148
|
+
if (node instanceof AST_Definitions && in_root_scope) {
|
15214
15149
|
const in_export = tw.parent() instanceof AST_Export;
|
15215
15150
|
node.definitions.forEach(function(def) {
|
15216
15151
|
if (def.name instanceof AST_SymbolVar) {
|
@@ -15220,7 +15155,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15220
15155
|
walk(def.name, node => {
|
15221
15156
|
if (node instanceof AST_SymbolDeclaration) {
|
15222
15157
|
const def = node.definition();
|
15223
|
-
if (def.global
|
15158
|
+
if (def.global) {
|
15224
15159
|
in_use_ids.set(def.id, def);
|
15225
15160
|
}
|
15226
15161
|
}
|
@@ -17903,8 +17838,9 @@ function inline_into_symbolref(self, compressor) {
|
|
17903
17838
|
return self;
|
17904
17839
|
}
|
17905
17840
|
|
17906
|
-
function inline_into_call(self,
|
17841
|
+
function inline_into_call(self, compressor) {
|
17907
17842
|
var exp = self.expression;
|
17843
|
+
var fn = exp;
|
17908
17844
|
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
17909
17845
|
|
17910
17846
|
if (compressor.option("reduce_vars")
|
@@ -17912,9 +17848,15 @@ function inline_into_call(self, fn, compressor) {
|
|
17912
17848
|
&& !has_annotation(self, _NOINLINE)
|
17913
17849
|
) {
|
17914
17850
|
const fixed = fn.fixed_value();
|
17915
|
-
|
17916
|
-
|
17851
|
+
|
17852
|
+
if (
|
17853
|
+
retain_top_func(fixed, compressor)
|
17854
|
+
|| !compressor.toplevel.funcs && exp.definition().global
|
17855
|
+
) {
|
17856
|
+
return self;
|
17917
17857
|
}
|
17858
|
+
|
17859
|
+
fn = fixed;
|
17918
17860
|
}
|
17919
17861
|
|
17920
17862
|
var is_func = fn instanceof AST_Lambda;
|
@@ -18245,6 +18187,80 @@ function inline_into_call(self, fn, compressor) {
|
|
18245
18187
|
}
|
18246
18188
|
}
|
18247
18189
|
|
18190
|
+
(function(def_find_defs) {
|
18191
|
+
function to_node(value, orig) {
|
18192
|
+
if (value instanceof AST_Node) {
|
18193
|
+
if (!(value instanceof AST_Constant)) {
|
18194
|
+
// Value may be a function, an array including functions and even a complex assign / block expression,
|
18195
|
+
// so it should never be shared in different places.
|
18196
|
+
// Otherwise wrong information may be used in the compression phase
|
18197
|
+
value = value.clone(true);
|
18198
|
+
}
|
18199
|
+
return make_node(value.CTOR, orig, value);
|
18200
|
+
}
|
18201
|
+
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
18202
|
+
elements: value.map(function(value) {
|
18203
|
+
return to_node(value, orig);
|
18204
|
+
})
|
18205
|
+
});
|
18206
|
+
if (value && typeof value == "object") {
|
18207
|
+
var props = [];
|
18208
|
+
for (var key in value) if (HOP(value, key)) {
|
18209
|
+
props.push(make_node(AST_ObjectKeyVal, orig, {
|
18210
|
+
key: key,
|
18211
|
+
value: to_node(value[key], orig)
|
18212
|
+
}));
|
18213
|
+
}
|
18214
|
+
return make_node(AST_Object, orig, {
|
18215
|
+
properties: props
|
18216
|
+
});
|
18217
|
+
}
|
18218
|
+
return make_node_from_constant(value, orig);
|
18219
|
+
}
|
18220
|
+
|
18221
|
+
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
|
18222
|
+
if (!compressor.option("global_defs")) return this;
|
18223
|
+
this.figure_out_scope({ ie8: compressor.option("ie8") });
|
18224
|
+
return this.transform(new TreeTransformer(function(node) {
|
18225
|
+
var def = node._find_defs(compressor, "");
|
18226
|
+
if (!def) return;
|
18227
|
+
var level = 0, child = node, parent;
|
18228
|
+
while (parent = this.parent(level++)) {
|
18229
|
+
if (!(parent instanceof AST_PropAccess)) break;
|
18230
|
+
if (parent.expression !== child) break;
|
18231
|
+
child = parent;
|
18232
|
+
}
|
18233
|
+
if (is_lhs(child, parent)) {
|
18234
|
+
return;
|
18235
|
+
}
|
18236
|
+
return def;
|
18237
|
+
}));
|
18238
|
+
});
|
18239
|
+
def_find_defs(AST_Node, noop);
|
18240
|
+
def_find_defs(AST_Chain, function(compressor, suffix) {
|
18241
|
+
return this.expression._find_defs(compressor, suffix);
|
18242
|
+
});
|
18243
|
+
def_find_defs(AST_Dot, function(compressor, suffix) {
|
18244
|
+
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
18245
|
+
});
|
18246
|
+
def_find_defs(AST_SymbolDeclaration, function() {
|
18247
|
+
if (!this.global()) return;
|
18248
|
+
});
|
18249
|
+
def_find_defs(AST_SymbolRef, function(compressor, suffix) {
|
18250
|
+
if (!this.global()) return;
|
18251
|
+
var defines = compressor.option("global_defs");
|
18252
|
+
var name = this.name + suffix;
|
18253
|
+
if (HOP(defines, name)) return to_node(defines[name], this);
|
18254
|
+
});
|
18255
|
+
def_find_defs(AST_ImportMeta, function(compressor, suffix) {
|
18256
|
+
var defines = compressor.option("global_defs");
|
18257
|
+
var name = "import.meta" + suffix;
|
18258
|
+
if (HOP(defines, name)) return to_node(defines[name], this);
|
18259
|
+
});
|
18260
|
+
})(function(node, func) {
|
18261
|
+
node.DEFMETHOD("_find_defs", func);
|
18262
|
+
});
|
18263
|
+
|
18248
18264
|
/***********************************************************************
|
18249
18265
|
|
18250
18266
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
@@ -18398,11 +18414,17 @@ class Compressor extends TreeWalker {
|
|
18398
18414
|
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
18399
18415
|
this.evaluated_regexps = new Map();
|
18400
18416
|
this._toplevel = undefined;
|
18401
|
-
this.
|
18417
|
+
this._mangle_options = mangle_options
|
18402
18418
|
? format_mangler_options(mangle_options)
|
18403
18419
|
: mangle_options;
|
18404
18420
|
}
|
18405
18421
|
|
18422
|
+
mangle_options() {
|
18423
|
+
var nth_identifier = this._mangle_options && this._mangle_options.nth_identifier || base54;
|
18424
|
+
var module = this._mangle_options && this._mangle_options.module || this.option("module");
|
18425
|
+
return { ie8: this.option("ie8"), nth_identifier, module };
|
18426
|
+
}
|
18427
|
+
|
18406
18428
|
option(key) {
|
18407
18429
|
return this.options[key];
|
18408
18430
|
}
|
@@ -18457,8 +18479,7 @@ class Compressor extends TreeWalker {
|
|
18457
18479
|
var passes = +this.options.passes || 1;
|
18458
18480
|
var min_count = 1 / 0;
|
18459
18481
|
var stopping = false;
|
18460
|
-
var
|
18461
|
-
var mangle = { ie8: this.option("ie8"), nth_identifier: nth_identifier };
|
18482
|
+
var mangle = this.mangle_options();
|
18462
18483
|
for (var pass = 0; pass < passes; pass++) {
|
18463
18484
|
this._toplevel.figure_out_scope(mangle);
|
18464
18485
|
if (pass === 0 && this.option("drop_console")) {
|
@@ -19687,18 +19708,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
19687
19708
|
var exp = self.expression;
|
19688
19709
|
var fn = exp;
|
19689
19710
|
inline_array_like_spread(self.args);
|
19690
|
-
var simple_args = self.args.every((arg) =>
|
19691
|
-
!(arg instanceof AST_Expansion)
|
19692
|
-
);
|
19711
|
+
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
19693
19712
|
|
19694
|
-
if (compressor.option("reduce_vars")
|
19695
|
-
|
19696
|
-
&& !has_annotation(self, _NOINLINE)
|
19697
|
-
) {
|
19698
|
-
const fixed = fn.fixed_value();
|
19699
|
-
if (!retain_top_func(fixed, compressor)) {
|
19700
|
-
fn = fixed;
|
19701
|
-
}
|
19713
|
+
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
19714
|
+
fn = fn.fixed_value();
|
19702
19715
|
}
|
19703
19716
|
|
19704
19717
|
var is_func = fn instanceof AST_Lambda;
|
@@ -19742,7 +19755,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
19742
19755
|
self.args.length = last;
|
19743
19756
|
}
|
19744
19757
|
|
19745
|
-
if (compressor.option("unsafe")) {
|
19758
|
+
if (compressor.option("unsafe") && !exp.contains_optional()) {
|
19746
19759
|
if (exp instanceof AST_Dot && exp.start.value === "Array" && exp.property === "from" && self.args.length === 1) {
|
19747
19760
|
const [argument] = self.args;
|
19748
19761
|
if (argument instanceof AST_Array) {
|
@@ -19957,7 +19970,6 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
19957
19970
|
argnames: [],
|
19958
19971
|
body: []
|
19959
19972
|
}).optimize(compressor);
|
19960
|
-
var nth_identifier = compressor.mangle_options && compressor.mangle_options.nth_identifier || base54;
|
19961
19973
|
if (self.args.every((x) => x instanceof AST_String)) {
|
19962
19974
|
// quite a corner-case, but we can handle it:
|
19963
19975
|
// https://github.com/mishoo/UglifyJS2/issues/203
|
@@ -19967,10 +19979,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
19967
19979
|
return arg.value;
|
19968
19980
|
}).join(",") + "){" + self.args[self.args.length - 1].value + "})";
|
19969
19981
|
var ast = parse(code);
|
19970
|
-
var mangle =
|
19982
|
+
var mangle = compressor.mangle_options();
|
19971
19983
|
ast.figure_out_scope(mangle);
|
19972
19984
|
var comp = new Compressor(compressor.options, {
|
19973
|
-
mangle_options: compressor.
|
19985
|
+
mangle_options: compressor._mangle_options
|
19974
19986
|
});
|
19975
19987
|
ast = ast.transform(comp);
|
19976
19988
|
ast.figure_out_scope(mangle);
|
@@ -20006,7 +20018,24 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
20006
20018
|
}
|
20007
20019
|
}
|
20008
20020
|
|
20009
|
-
return inline_into_call(self,
|
20021
|
+
return inline_into_call(self, compressor);
|
20022
|
+
});
|
20023
|
+
|
20024
|
+
/** Does this node contain optional property access or optional call? */
|
20025
|
+
AST_Node.DEFMETHOD("contains_optional", function() {
|
20026
|
+
if (
|
20027
|
+
this instanceof AST_PropAccess
|
20028
|
+
|| this instanceof AST_Call
|
20029
|
+
|| this instanceof AST_Chain
|
20030
|
+
) {
|
20031
|
+
if (this.optional) {
|
20032
|
+
return true;
|
20033
|
+
} else {
|
20034
|
+
return this.expression.contains_optional();
|
20035
|
+
}
|
20036
|
+
} else {
|
20037
|
+
return false;
|
20038
|
+
}
|
20010
20039
|
});
|
20011
20040
|
|
20012
20041
|
def_optimize(AST_New, function(self, compressor) {
|
@@ -21839,10 +21868,10 @@ def_optimize(AST_Destructuring, function(self, compressor) {
|
|
21839
21868
|
if (def.references.length) return true;
|
21840
21869
|
if (!def.global) return false;
|
21841
21870
|
if (compressor.toplevel.vars) {
|
21842
|
-
|
21843
|
-
|
21844
|
-
|
21845
|
-
|
21871
|
+
if (compressor.top_retain) {
|
21872
|
+
return compressor.top_retain(def);
|
21873
|
+
}
|
21874
|
+
return false;
|
21846
21875
|
}
|
21847
21876
|
return true;
|
21848
21877
|
}
|
package/lib/compress/common.js
CHANGED
@@ -109,6 +109,8 @@ const r_keep_assign = /keep_assign/;
|
|
109
109
|
AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
110
110
|
if (!compressor.option("unused")) return;
|
111
111
|
if (compressor.has_directive("use asm")) return;
|
112
|
+
if (!this.variables) return; // not really a scope (eg: AST_Class)
|
113
|
+
|
112
114
|
var self = this;
|
113
115
|
if (self.pinned()) return;
|
114
116
|
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
@@ -128,7 +130,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
128
130
|
var fixed_ids = new Map();
|
129
131
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
130
132
|
self.variables.forEach(function(def) {
|
131
|
-
if (compressor.top_retain(def)
|
133
|
+
if (compressor.top_retain(def)) {
|
132
134
|
in_use_ids.set(def.id, def);
|
133
135
|
}
|
134
136
|
});
|
@@ -143,9 +145,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
143
145
|
node.argnames.forEach(function(argname) {
|
144
146
|
if (!(argname instanceof AST_SymbolDeclaration)) return;
|
145
147
|
var def = argname.definition();
|
146
|
-
|
147
|
-
in_use_ids.set(def.id, def);
|
148
|
-
}
|
148
|
+
in_use_ids.set(def.id, def);
|
149
149
|
});
|
150
150
|
}
|
151
151
|
if (node === self) return;
|
@@ -158,7 +158,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
158
158
|
var node_def = node.name.definition();
|
159
159
|
const in_export = tw.parent() instanceof AST_Export;
|
160
160
|
if (in_export || !drop_funcs && scope === self) {
|
161
|
-
if (node_def.global
|
161
|
+
if (node_def.global) {
|
162
162
|
in_use_ids.set(node_def.id, node_def);
|
163
163
|
}
|
164
164
|
}
|
@@ -166,10 +166,12 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
166
166
|
map_add(initializations, node_def.id, node);
|
167
167
|
return true; // don't go in nested scopes
|
168
168
|
}
|
169
|
-
|
169
|
+
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
170
|
+
const in_root_scope = scope === self;
|
171
|
+
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
170
172
|
map_add(var_defs_by_id, node.definition().id, node);
|
171
173
|
}
|
172
|
-
if (node instanceof AST_Definitions &&
|
174
|
+
if (node instanceof AST_Definitions && in_root_scope) {
|
173
175
|
const in_export = tw.parent() instanceof AST_Export;
|
174
176
|
node.definitions.forEach(function(def) {
|
175
177
|
if (def.name instanceof AST_SymbolVar) {
|
@@ -179,7 +181,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
179
181
|
walk(def.name, node => {
|
180
182
|
if (node instanceof AST_SymbolDeclaration) {
|
181
183
|
const def = node.definition();
|
182
|
-
if (def.global
|
184
|
+
if (def.global) {
|
183
185
|
in_use_ids.set(def.id, def);
|
184
186
|
}
|
185
187
|
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import {
|
2
|
+
AST_Array,
|
3
|
+
AST_Chain,
|
4
|
+
AST_Constant,
|
5
|
+
AST_Dot,
|
6
|
+
AST_ImportMeta,
|
7
|
+
AST_Node,
|
8
|
+
AST_Object,
|
9
|
+
AST_ObjectKeyVal,
|
10
|
+
AST_PropAccess,
|
11
|
+
AST_SymbolDeclaration,
|
12
|
+
AST_SymbolRef,
|
13
|
+
AST_Toplevel,
|
14
|
+
TreeTransformer,
|
15
|
+
} from "../ast.js";
|
16
|
+
import { make_node, noop, HOP } from "../utils/index.js";
|
17
|
+
import { make_node_from_constant } from "./common.js";
|
18
|
+
import { is_lhs } from "./inference.js";
|
19
|
+
|
20
|
+
(function(def_find_defs) {
|
21
|
+
function to_node(value, orig) {
|
22
|
+
if (value instanceof AST_Node) {
|
23
|
+
if (!(value instanceof AST_Constant)) {
|
24
|
+
// Value may be a function, an array including functions and even a complex assign / block expression,
|
25
|
+
// so it should never be shared in different places.
|
26
|
+
// Otherwise wrong information may be used in the compression phase
|
27
|
+
value = value.clone(true);
|
28
|
+
}
|
29
|
+
return make_node(value.CTOR, orig, value);
|
30
|
+
}
|
31
|
+
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
32
|
+
elements: value.map(function(value) {
|
33
|
+
return to_node(value, orig);
|
34
|
+
})
|
35
|
+
});
|
36
|
+
if (value && typeof value == "object") {
|
37
|
+
var props = [];
|
38
|
+
for (var key in value) if (HOP(value, key)) {
|
39
|
+
props.push(make_node(AST_ObjectKeyVal, orig, {
|
40
|
+
key: key,
|
41
|
+
value: to_node(value[key], orig)
|
42
|
+
}));
|
43
|
+
}
|
44
|
+
return make_node(AST_Object, orig, {
|
45
|
+
properties: props
|
46
|
+
});
|
47
|
+
}
|
48
|
+
return make_node_from_constant(value, orig);
|
49
|
+
}
|
50
|
+
|
51
|
+
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
|
52
|
+
if (!compressor.option("global_defs")) return this;
|
53
|
+
this.figure_out_scope({ ie8: compressor.option("ie8") });
|
54
|
+
return this.transform(new TreeTransformer(function(node) {
|
55
|
+
var def = node._find_defs(compressor, "");
|
56
|
+
if (!def) return;
|
57
|
+
var level = 0, child = node, parent;
|
58
|
+
while (parent = this.parent(level++)) {
|
59
|
+
if (!(parent instanceof AST_PropAccess)) break;
|
60
|
+
if (parent.expression !== child) break;
|
61
|
+
child = parent;
|
62
|
+
}
|
63
|
+
if (is_lhs(child, parent)) {
|
64
|
+
return;
|
65
|
+
}
|
66
|
+
return def;
|
67
|
+
}));
|
68
|
+
});
|
69
|
+
def_find_defs(AST_Node, noop);
|
70
|
+
def_find_defs(AST_Chain, function(compressor, suffix) {
|
71
|
+
return this.expression._find_defs(compressor, suffix);
|
72
|
+
});
|
73
|
+
def_find_defs(AST_Dot, function(compressor, suffix) {
|
74
|
+
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
75
|
+
});
|
76
|
+
def_find_defs(AST_SymbolDeclaration, function() {
|
77
|
+
if (!this.global()) return;
|
78
|
+
});
|
79
|
+
def_find_defs(AST_SymbolRef, function(compressor, suffix) {
|
80
|
+
if (!this.global()) return;
|
81
|
+
var defines = compressor.option("global_defs");
|
82
|
+
var name = this.name + suffix;
|
83
|
+
if (HOP(defines, name)) return to_node(defines[name], this);
|
84
|
+
});
|
85
|
+
def_find_defs(AST_ImportMeta, function(compressor, suffix) {
|
86
|
+
var defines = compressor.option("global_defs");
|
87
|
+
var name = "import.meta" + suffix;
|
88
|
+
if (HOP(defines, name)) return to_node(defines[name], this);
|
89
|
+
});
|
90
|
+
})(function(node, func) {
|
91
|
+
node.DEFMETHOD("_find_defs", func);
|
92
|
+
});
|
package/lib/compress/index.js
CHANGED
@@ -204,11 +204,11 @@ import {
|
|
204
204
|
is_reachable,
|
205
205
|
can_be_evicted_from_block,
|
206
206
|
as_statement_array,
|
207
|
-
retain_top_func,
|
208
207
|
is_func_expr,
|
209
208
|
} from "./common.js";
|
210
209
|
import { tighten_body, trim_unreachable_code } from "./tighten-body.js";
|
211
210
|
import { inline_into_symbolref, inline_into_call } from "./inline.js";
|
211
|
+
import "./global-defs.js";
|
212
212
|
|
213
213
|
class Compressor extends TreeWalker {
|
214
214
|
constructor(options, { false_by_default = false, mangle_options = false }) {
|
@@ -320,11 +320,17 @@ class Compressor extends TreeWalker {
|
|
320
320
|
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
321
321
|
this.evaluated_regexps = new Map();
|
322
322
|
this._toplevel = undefined;
|
323
|
-
this.
|
323
|
+
this._mangle_options = mangle_options
|
324
324
|
? format_mangler_options(mangle_options)
|
325
325
|
: mangle_options;
|
326
326
|
}
|
327
327
|
|
328
|
+
mangle_options() {
|
329
|
+
var nth_identifier = this._mangle_options && this._mangle_options.nth_identifier || base54;
|
330
|
+
var module = this._mangle_options && this._mangle_options.module || this.option("module");
|
331
|
+
return { ie8: this.option("ie8"), nth_identifier, module };
|
332
|
+
}
|
333
|
+
|
328
334
|
option(key) {
|
329
335
|
return this.options[key];
|
330
336
|
}
|
@@ -379,8 +385,7 @@ class Compressor extends TreeWalker {
|
|
379
385
|
var passes = +this.options.passes || 1;
|
380
386
|
var min_count = 1 / 0;
|
381
387
|
var stopping = false;
|
382
|
-
var
|
383
|
-
var mangle = { ie8: this.option("ie8"), nth_identifier: nth_identifier };
|
388
|
+
var mangle = this.mangle_options();
|
384
389
|
for (var pass = 0; pass < passes; pass++) {
|
385
390
|
this._toplevel.figure_out_scope(mangle);
|
386
391
|
if (pass === 0 && this.option("drop_console")) {
|
@@ -1609,18 +1614,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1609
1614
|
var exp = self.expression;
|
1610
1615
|
var fn = exp;
|
1611
1616
|
inline_array_like_spread(self.args);
|
1612
|
-
var simple_args = self.args.every((arg) =>
|
1613
|
-
!(arg instanceof AST_Expansion)
|
1614
|
-
);
|
1617
|
+
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
1615
1618
|
|
1616
|
-
if (compressor.option("reduce_vars")
|
1617
|
-
|
1618
|
-
&& !has_annotation(self, _NOINLINE)
|
1619
|
-
) {
|
1620
|
-
const fixed = fn.fixed_value();
|
1621
|
-
if (!retain_top_func(fixed, compressor)) {
|
1622
|
-
fn = fixed;
|
1623
|
-
}
|
1619
|
+
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
1620
|
+
fn = fn.fixed_value();
|
1624
1621
|
}
|
1625
1622
|
|
1626
1623
|
var is_func = fn instanceof AST_Lambda;
|
@@ -1664,7 +1661,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1664
1661
|
self.args.length = last;
|
1665
1662
|
}
|
1666
1663
|
|
1667
|
-
if (compressor.option("unsafe")) {
|
1664
|
+
if (compressor.option("unsafe") && !exp.contains_optional()) {
|
1668
1665
|
if (exp instanceof AST_Dot && exp.start.value === "Array" && exp.property === "from" && self.args.length === 1) {
|
1669
1666
|
const [argument] = self.args;
|
1670
1667
|
if (argument instanceof AST_Array) {
|
@@ -1879,7 +1876,6 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1879
1876
|
argnames: [],
|
1880
1877
|
body: []
|
1881
1878
|
}).optimize(compressor);
|
1882
|
-
var nth_identifier = compressor.mangle_options && compressor.mangle_options.nth_identifier || base54;
|
1883
1879
|
if (self.args.every((x) => x instanceof AST_String)) {
|
1884
1880
|
// quite a corner-case, but we can handle it:
|
1885
1881
|
// https://github.com/mishoo/UglifyJS2/issues/203
|
@@ -1889,10 +1885,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1889
1885
|
return arg.value;
|
1890
1886
|
}).join(",") + "){" + self.args[self.args.length - 1].value + "})";
|
1891
1887
|
var ast = parse(code);
|
1892
|
-
var mangle =
|
1888
|
+
var mangle = compressor.mangle_options();
|
1893
1889
|
ast.figure_out_scope(mangle);
|
1894
1890
|
var comp = new Compressor(compressor.options, {
|
1895
|
-
mangle_options: compressor.
|
1891
|
+
mangle_options: compressor._mangle_options
|
1896
1892
|
});
|
1897
1893
|
ast = ast.transform(comp);
|
1898
1894
|
ast.figure_out_scope(mangle);
|
@@ -1928,7 +1924,24 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1928
1924
|
}
|
1929
1925
|
}
|
1930
1926
|
|
1931
|
-
return inline_into_call(self,
|
1927
|
+
return inline_into_call(self, compressor);
|
1928
|
+
});
|
1929
|
+
|
1930
|
+
/** Does this node contain optional property access or optional call? */
|
1931
|
+
AST_Node.DEFMETHOD("contains_optional", function() {
|
1932
|
+
if (
|
1933
|
+
this instanceof AST_PropAccess
|
1934
|
+
|| this instanceof AST_Call
|
1935
|
+
|| this instanceof AST_Chain
|
1936
|
+
) {
|
1937
|
+
if (this.optional) {
|
1938
|
+
return true;
|
1939
|
+
} else {
|
1940
|
+
return this.expression.contains_optional();
|
1941
|
+
}
|
1942
|
+
} else {
|
1943
|
+
return false;
|
1944
|
+
}
|
1932
1945
|
});
|
1933
1946
|
|
1934
1947
|
def_optimize(AST_New, function(self, compressor) {
|
@@ -3761,10 +3774,10 @@ def_optimize(AST_Destructuring, function(self, compressor) {
|
|
3761
3774
|
if (def.references.length) return true;
|
3762
3775
|
if (!def.global) return false;
|
3763
3776
|
if (compressor.toplevel.vars) {
|
3764
|
-
|
3765
|
-
|
3766
|
-
|
3767
|
-
|
3777
|
+
if (compressor.top_retain) {
|
3778
|
+
return compressor.top_retain(def);
|
3779
|
+
}
|
3780
|
+
return false;
|
3768
3781
|
}
|
3769
3782
|
return true;
|
3770
3783
|
}
|
@@ -98,7 +98,6 @@ import {
|
|
98
98
|
AST_TemplateSegment,
|
99
99
|
AST_TemplateString,
|
100
100
|
AST_This,
|
101
|
-
AST_Toplevel,
|
102
101
|
AST_True,
|
103
102
|
AST_Try,
|
104
103
|
AST_Unary,
|
@@ -107,7 +106,6 @@ import {
|
|
107
106
|
AST_Undefined,
|
108
107
|
AST_VarDef,
|
109
108
|
|
110
|
-
TreeTransformer,
|
111
109
|
walk,
|
112
110
|
walk_abort,
|
113
111
|
|
@@ -121,11 +119,9 @@ import {
|
|
121
119
|
return_this,
|
122
120
|
make_node,
|
123
121
|
member,
|
124
|
-
noop,
|
125
122
|
has_annotation,
|
126
|
-
HOP
|
127
123
|
} from "../utils/index.js";
|
128
|
-
import {
|
124
|
+
import { make_sequence, best_of_expression, read_property } from "./common.js";
|
129
125
|
|
130
126
|
import { INLINED, UNDEFINED, has_flag } from "./compressor-flags.js";
|
131
127
|
import { pure_prop_access_globals, is_pure_native_fn, is_pure_native_method } from "./native-objects.js";
|
@@ -728,80 +724,6 @@ export function is_lhs(node, parent) {
|
|
728
724
|
if (parent instanceof AST_ForIn && parent.init === node) return node;
|
729
725
|
}
|
730
726
|
|
731
|
-
(function(def_find_defs) {
|
732
|
-
function to_node(value, orig) {
|
733
|
-
if (value instanceof AST_Node) {
|
734
|
-
if (!(value instanceof AST_Constant)) {
|
735
|
-
// Value may be a function, an array including functions and even a complex assign / block expression,
|
736
|
-
// so it should never be shared in different places.
|
737
|
-
// Otherwise wrong information may be used in the compression phase
|
738
|
-
value = value.clone(true);
|
739
|
-
}
|
740
|
-
return make_node(value.CTOR, orig, value);
|
741
|
-
}
|
742
|
-
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
743
|
-
elements: value.map(function(value) {
|
744
|
-
return to_node(value, orig);
|
745
|
-
})
|
746
|
-
});
|
747
|
-
if (value && typeof value == "object") {
|
748
|
-
var props = [];
|
749
|
-
for (var key in value) if (HOP(value, key)) {
|
750
|
-
props.push(make_node(AST_ObjectKeyVal, orig, {
|
751
|
-
key: key,
|
752
|
-
value: to_node(value[key], orig)
|
753
|
-
}));
|
754
|
-
}
|
755
|
-
return make_node(AST_Object, orig, {
|
756
|
-
properties: props
|
757
|
-
});
|
758
|
-
}
|
759
|
-
return make_node_from_constant(value, orig);
|
760
|
-
}
|
761
|
-
|
762
|
-
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
|
763
|
-
if (!compressor.option("global_defs")) return this;
|
764
|
-
this.figure_out_scope({ ie8: compressor.option("ie8") });
|
765
|
-
return this.transform(new TreeTransformer(function(node) {
|
766
|
-
var def = node._find_defs(compressor, "");
|
767
|
-
if (!def) return;
|
768
|
-
var level = 0, child = node, parent;
|
769
|
-
while (parent = this.parent(level++)) {
|
770
|
-
if (!(parent instanceof AST_PropAccess)) break;
|
771
|
-
if (parent.expression !== child) break;
|
772
|
-
child = parent;
|
773
|
-
}
|
774
|
-
if (is_lhs(child, parent)) {
|
775
|
-
return;
|
776
|
-
}
|
777
|
-
return def;
|
778
|
-
}));
|
779
|
-
});
|
780
|
-
def_find_defs(AST_Node, noop);
|
781
|
-
def_find_defs(AST_Chain, function(compressor, suffix) {
|
782
|
-
return this.expression._find_defs(compressor, suffix);
|
783
|
-
});
|
784
|
-
def_find_defs(AST_Dot, function(compressor, suffix) {
|
785
|
-
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
786
|
-
});
|
787
|
-
def_find_defs(AST_SymbolDeclaration, function() {
|
788
|
-
if (!this.global()) return;
|
789
|
-
});
|
790
|
-
def_find_defs(AST_SymbolRef, function(compressor, suffix) {
|
791
|
-
if (!this.global()) return;
|
792
|
-
var defines = compressor.option("global_defs");
|
793
|
-
var name = this.name + suffix;
|
794
|
-
if (HOP(defines, name)) return to_node(defines[name], this);
|
795
|
-
});
|
796
|
-
def_find_defs(AST_ImportMeta, function(compressor, suffix) {
|
797
|
-
var defines = compressor.option("global_defs");
|
798
|
-
var name = "import.meta" + suffix;
|
799
|
-
if (HOP(defines, name)) return to_node(defines[name], this);
|
800
|
-
});
|
801
|
-
})(function(node, func) {
|
802
|
-
node.DEFMETHOD("_find_defs", func);
|
803
|
-
});
|
804
|
-
|
805
727
|
// method to negate an expression
|
806
728
|
(function(def_negate) {
|
807
729
|
function basic_negation(exp) {
|
package/lib/compress/inline.js
CHANGED
@@ -290,8 +290,9 @@ export function inline_into_symbolref(self, compressor) {
|
|
290
290
|
return self;
|
291
291
|
}
|
292
292
|
|
293
|
-
export function inline_into_call(self,
|
293
|
+
export function inline_into_call(self, compressor) {
|
294
294
|
var exp = self.expression;
|
295
|
+
var fn = exp;
|
295
296
|
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
296
297
|
|
297
298
|
if (compressor.option("reduce_vars")
|
@@ -299,9 +300,15 @@ export function inline_into_call(self, fn, compressor) {
|
|
299
300
|
&& !has_annotation(self, _NOINLINE)
|
300
301
|
) {
|
301
302
|
const fixed = fn.fixed_value();
|
302
|
-
|
303
|
-
|
303
|
+
|
304
|
+
if (
|
305
|
+
retain_top_func(fixed, compressor)
|
306
|
+
|| !compressor.toplevel.funcs && exp.definition().global
|
307
|
+
) {
|
308
|
+
return self;
|
304
309
|
}
|
310
|
+
|
311
|
+
fn = fixed;
|
305
312
|
}
|
306
313
|
|
307
314
|
var is_func = fn instanceof AST_Lambda;
|
package/lib/output.js
CHANGED
@@ -980,7 +980,8 @@ function OutputStream(options) {
|
|
980
980
|
) {
|
981
981
|
return true;
|
982
982
|
}
|
983
|
-
return p instanceof AST_PropAccess && p.expression === this
|
983
|
+
return p instanceof AST_PropAccess && p.expression === this
|
984
|
+
|| p instanceof AST_Conditional && p.condition === this;
|
984
985
|
});
|
985
986
|
|
986
987
|
// same goes for an object literal (as in AST_Function), because
|
package/lib/scope.js
CHANGED
@@ -205,6 +205,7 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
205
205
|
cache: null,
|
206
206
|
ie8: false,
|
207
207
|
safari10: false,
|
208
|
+
module: false,
|
208
209
|
});
|
209
210
|
|
210
211
|
if (!(toplevel instanceof AST_Toplevel)) {
|
@@ -372,6 +373,11 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
372
373
|
);
|
373
374
|
}
|
374
375
|
});
|
376
|
+
|
377
|
+
if (options.module) {
|
378
|
+
tw.directives["use strict"] = true;
|
379
|
+
}
|
380
|
+
|
375
381
|
this.walk(tw);
|
376
382
|
|
377
383
|
function mark_export(def, level) {
|
package/lib/size.js
CHANGED
@@ -89,7 +89,7 @@ import { first_in_statement } from "./utils/first_in_statement.js";
|
|
89
89
|
|
90
90
|
let mangle_options = undefined;
|
91
91
|
AST_Node.prototype.size = function (compressor, stack) {
|
92
|
-
mangle_options = compressor && compressor.
|
92
|
+
mangle_options = compressor && compressor._mangle_options;
|
93
93
|
|
94
94
|
let size = 0;
|
95
95
|
walk_parent(this, (node, info) => {
|