terser 5.15.1 → 5.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/PATRONS.md +1 -1
- package/README.md +2 -2
- package/dist/bundle.min.js +3223 -3060
- package/lib/ast.js +42 -2
- package/lib/compress/drop-unused.js +482 -0
- package/lib/compress/evaluate.js +7 -0
- package/lib/compress/index.js +7 -403
- package/lib/compress/inference.js +1 -2
- package/lib/compress/inline.js +1 -19
- package/lib/compress/tighten-body.js +29 -28
- package/lib/mozilla-ast.js +26 -1
- package/lib/output.js +16 -1
- package/lib/parse.js +42 -4
- package/lib/propmangle.js +2 -0
- package/lib/scope.js +30 -8
- package/lib/size.js +11 -8
- package/lib/transform.js +6 -0
- package/package.json +1 -1
package/lib/ast.js
CHANGED
@@ -2250,6 +2250,29 @@ var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", function AST_
|
|
2250
2250
|
$documentation: "A class property for a private property",
|
2251
2251
|
}, AST_ClassProperty);
|
2252
2252
|
|
2253
|
+
var AST_PrivateIn = DEFNODE("PrivateIn", "key value", function AST_PrivateIn(props) {
|
2254
|
+
if (props) {
|
2255
|
+
this.key = props.key;
|
2256
|
+
this.value = props.value;
|
2257
|
+
this.start = props.start;
|
2258
|
+
this.end = props.end;
|
2259
|
+
}
|
2260
|
+
|
2261
|
+
this.flags = 0;
|
2262
|
+
}, {
|
2263
|
+
$documentation: "An `in` binop when the key is private, eg #x in this",
|
2264
|
+
_walk: function(visitor) {
|
2265
|
+
return visitor._visit(this, function() {
|
2266
|
+
this.key._walk(visitor);
|
2267
|
+
this.value._walk(visitor);
|
2268
|
+
});
|
2269
|
+
},
|
2270
|
+
_children_backwards(push) {
|
2271
|
+
push(this.value);
|
2272
|
+
push(this.key);
|
2273
|
+
},
|
2274
|
+
});
|
2275
|
+
|
2253
2276
|
var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
|
2254
2277
|
if (props) {
|
2255
2278
|
this.name = props.name;
|
@@ -2653,6 +2676,20 @@ var AST_LabelRef = DEFNODE("LabelRef", null, function AST_LabelRef(props) {
|
|
2653
2676
|
$documentation: "Reference to a label symbol",
|
2654
2677
|
}, AST_Symbol);
|
2655
2678
|
|
2679
|
+
var AST_SymbolPrivateProperty = DEFNODE("SymbolPrivateProperty", null, function AST_SymbolPrivateProperty(props) {
|
2680
|
+
if (props) {
|
2681
|
+
this.scope = props.scope;
|
2682
|
+
this.name = props.name;
|
2683
|
+
this.thedef = props.thedef;
|
2684
|
+
this.start = props.start;
|
2685
|
+
this.end = props.end;
|
2686
|
+
}
|
2687
|
+
|
2688
|
+
this.flags = 0;
|
2689
|
+
}, {
|
2690
|
+
$documentation: "A symbol that refers to a private property",
|
2691
|
+
}, AST_Symbol);
|
2692
|
+
|
2656
2693
|
var AST_This = DEFNODE("This", null, function AST_This(props) {
|
2657
2694
|
if (props) {
|
2658
2695
|
this.scope = props.scope;
|
@@ -3024,8 +3061,9 @@ class TreeWalker {
|
|
3024
3061
|
}
|
3025
3062
|
|
3026
3063
|
find_scope() {
|
3027
|
-
|
3028
|
-
|
3064
|
+
var stack = this.stack;
|
3065
|
+
for (var i = stack.length; --i >= 0;) {
|
3066
|
+
const p = stack[i];
|
3029
3067
|
if (p instanceof AST_Toplevel) return p;
|
3030
3068
|
if (p instanceof AST_Lambda) return p;
|
3031
3069
|
if (p.block_scope) return p.block_scope;
|
@@ -3093,6 +3131,7 @@ export {
|
|
3093
3131
|
AST_Class,
|
3094
3132
|
AST_ClassExpression,
|
3095
3133
|
AST_ClassPrivateProperty,
|
3134
|
+
AST_PrivateIn,
|
3096
3135
|
AST_ClassProperty,
|
3097
3136
|
AST_ClassStaticBlock,
|
3098
3137
|
AST_ConciseMethod,
|
@@ -3185,6 +3224,7 @@ export {
|
|
3185
3224
|
AST_SymbolVar,
|
3186
3225
|
AST_TemplateSegment,
|
3187
3226
|
AST_TemplateString,
|
3227
|
+
AST_SymbolPrivateProperty,
|
3188
3228
|
AST_This,
|
3189
3229
|
AST_Throw,
|
3190
3230
|
AST_Token,
|
@@ -0,0 +1,482 @@
|
|
1
|
+
/***********************************************************************
|
2
|
+
|
3
|
+
A JavaScript tokenizer / parser / beautifier / compressor.
|
4
|
+
https://github.com/mishoo/UglifyJS2
|
5
|
+
|
6
|
+
-------------------------------- (C) ---------------------------------
|
7
|
+
|
8
|
+
Author: Mihai Bazon
|
9
|
+
<mihai.bazon@gmail.com>
|
10
|
+
http://mihai.bazon.net/blog
|
11
|
+
|
12
|
+
Distributed under the BSD license:
|
13
|
+
|
14
|
+
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
15
|
+
|
16
|
+
Redistribution and use in source and binary forms, with or without
|
17
|
+
modification, are permitted provided that the following conditions
|
18
|
+
are met:
|
19
|
+
|
20
|
+
* Redistributions of source code must retain the above
|
21
|
+
copyright notice, this list of conditions and the following
|
22
|
+
disclaimer.
|
23
|
+
|
24
|
+
* Redistributions in binary form must reproduce the above
|
25
|
+
copyright notice, this list of conditions and the following
|
26
|
+
disclaimer in the documentation and/or other materials
|
27
|
+
provided with the distribution.
|
28
|
+
|
29
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
30
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
31
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
32
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
33
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
34
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
35
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
36
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
37
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
38
|
+
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
39
|
+
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
40
|
+
SUCH DAMAGE.
|
41
|
+
|
42
|
+
***********************************************************************/
|
43
|
+
|
44
|
+
import {
|
45
|
+
AST_Accessor,
|
46
|
+
AST_Assign,
|
47
|
+
AST_BlockStatement,
|
48
|
+
AST_Class,
|
49
|
+
AST_ClassExpression,
|
50
|
+
AST_DefaultAssign,
|
51
|
+
AST_DefClass,
|
52
|
+
AST_Definitions,
|
53
|
+
AST_Defun,
|
54
|
+
AST_Destructuring,
|
55
|
+
AST_EmptyStatement,
|
56
|
+
AST_Expansion,
|
57
|
+
AST_Export,
|
58
|
+
AST_For,
|
59
|
+
AST_ForIn,
|
60
|
+
AST_Function,
|
61
|
+
AST_LabeledStatement,
|
62
|
+
AST_Lambda,
|
63
|
+
AST_Number,
|
64
|
+
AST_Scope,
|
65
|
+
AST_SimpleStatement,
|
66
|
+
AST_SymbolBlockDeclaration,
|
67
|
+
AST_SymbolCatch,
|
68
|
+
AST_SymbolDeclaration,
|
69
|
+
AST_SymbolFunarg,
|
70
|
+
AST_SymbolRef,
|
71
|
+
AST_SymbolVar,
|
72
|
+
AST_Toplevel,
|
73
|
+
AST_Unary,
|
74
|
+
AST_Var,
|
75
|
+
|
76
|
+
TreeTransformer,
|
77
|
+
TreeWalker,
|
78
|
+
walk,
|
79
|
+
|
80
|
+
_INLINE,
|
81
|
+
_NOINLINE,
|
82
|
+
_PURE
|
83
|
+
} from "../ast.js";
|
84
|
+
import {
|
85
|
+
keep_name,
|
86
|
+
make_node,
|
87
|
+
map_add,
|
88
|
+
MAP,
|
89
|
+
remove,
|
90
|
+
return_false,
|
91
|
+
} from "../utils/index.js";
|
92
|
+
import { SymbolDef } from "../scope.js";
|
93
|
+
|
94
|
+
import {
|
95
|
+
WRITE_ONLY,
|
96
|
+
UNUSED,
|
97
|
+
|
98
|
+
has_flag,
|
99
|
+
set_flag,
|
100
|
+
} from "./compressor-flags.js";
|
101
|
+
import {
|
102
|
+
make_sequence,
|
103
|
+
maintain_this_binding,
|
104
|
+
is_empty,
|
105
|
+
is_ref_of,
|
106
|
+
can_be_evicted_from_block,
|
107
|
+
} from "./common.js";
|
108
|
+
|
109
|
+
const r_keep_assign = /keep_assign/;
|
110
|
+
|
111
|
+
/** Drop unused variables from this scope */
|
112
|
+
AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
113
|
+
if (!compressor.option("unused")) return;
|
114
|
+
if (compressor.has_directive("use asm")) return;
|
115
|
+
var self = this;
|
116
|
+
if (self.pinned()) return;
|
117
|
+
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
118
|
+
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
119
|
+
const assign_as_unused = r_keep_assign.test(compressor.option("unused")) ? return_false : function(node) {
|
120
|
+
if (node instanceof AST_Assign
|
121
|
+
&& !node.logical
|
122
|
+
&& (has_flag(node, WRITE_ONLY) || node.operator == "=")
|
123
|
+
) {
|
124
|
+
return node.left;
|
125
|
+
}
|
126
|
+
if (node instanceof AST_Unary && has_flag(node, WRITE_ONLY)) {
|
127
|
+
return node.expression;
|
128
|
+
}
|
129
|
+
};
|
130
|
+
var in_use_ids = new Map();
|
131
|
+
var fixed_ids = new Map();
|
132
|
+
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
133
|
+
self.variables.forEach(function(def) {
|
134
|
+
if (compressor.top_retain(def) && !in_use_ids.has(def.id)) {
|
135
|
+
in_use_ids.set(def.id, def);
|
136
|
+
}
|
137
|
+
});
|
138
|
+
}
|
139
|
+
var var_defs_by_id = new Map();
|
140
|
+
var initializations = new Map();
|
141
|
+
// pass 1: find out which symbols are directly used in
|
142
|
+
// this scope (not in nested scopes).
|
143
|
+
var scope = this;
|
144
|
+
var tw = new TreeWalker(function(node, descend) {
|
145
|
+
if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive("use strict")) {
|
146
|
+
node.argnames.forEach(function(argname) {
|
147
|
+
if (!(argname instanceof AST_SymbolDeclaration)) return;
|
148
|
+
var def = argname.definition();
|
149
|
+
if (!in_use_ids.has(def.id)) {
|
150
|
+
in_use_ids.set(def.id, def);
|
151
|
+
}
|
152
|
+
});
|
153
|
+
}
|
154
|
+
if (node === self) return;
|
155
|
+
if (node instanceof AST_Defun || node instanceof AST_DefClass) {
|
156
|
+
var node_def = node.name.definition();
|
157
|
+
const in_export = tw.parent() instanceof AST_Export;
|
158
|
+
if (in_export || !drop_funcs && scope === self) {
|
159
|
+
if (node_def.global && !in_use_ids.has(node_def.id)) {
|
160
|
+
in_use_ids.set(node_def.id, node_def);
|
161
|
+
}
|
162
|
+
}
|
163
|
+
if (node instanceof AST_DefClass) {
|
164
|
+
if (
|
165
|
+
node.extends
|
166
|
+
&& (node.extends.has_side_effects(compressor)
|
167
|
+
|| node.extends.may_throw(compressor))
|
168
|
+
) {
|
169
|
+
node.extends.walk(tw);
|
170
|
+
}
|
171
|
+
for (const prop of node.properties) {
|
172
|
+
if (
|
173
|
+
prop.has_side_effects(compressor) ||
|
174
|
+
prop.may_throw(compressor)
|
175
|
+
) {
|
176
|
+
prop.walk(tw);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
map_add(initializations, node_def.id, node);
|
181
|
+
return true; // don't go in nested scopes
|
182
|
+
}
|
183
|
+
if (node instanceof AST_SymbolFunarg && scope === self) {
|
184
|
+
map_add(var_defs_by_id, node.definition().id, node);
|
185
|
+
}
|
186
|
+
if (node instanceof AST_Definitions && scope === self) {
|
187
|
+
const in_export = tw.parent() instanceof AST_Export;
|
188
|
+
node.definitions.forEach(function(def) {
|
189
|
+
if (def.name instanceof AST_SymbolVar) {
|
190
|
+
map_add(var_defs_by_id, def.name.definition().id, def);
|
191
|
+
}
|
192
|
+
if (in_export || !drop_vars) {
|
193
|
+
walk(def.name, node => {
|
194
|
+
if (node instanceof AST_SymbolDeclaration) {
|
195
|
+
const def = node.definition();
|
196
|
+
if (def.global && !in_use_ids.has(def.id)) {
|
197
|
+
in_use_ids.set(def.id, def);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
});
|
201
|
+
}
|
202
|
+
if (def.name instanceof AST_Destructuring) {
|
203
|
+
def.walk(tw);
|
204
|
+
}
|
205
|
+
if (def.name instanceof AST_SymbolDeclaration && def.value) {
|
206
|
+
var node_def = def.name.definition();
|
207
|
+
map_add(initializations, node_def.id, def.value);
|
208
|
+
if (!node_def.chained && def.name.fixed_value() === def.value) {
|
209
|
+
fixed_ids.set(node_def.id, def);
|
210
|
+
}
|
211
|
+
if (def.value.has_side_effects(compressor)) {
|
212
|
+
def.value.walk(tw);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
});
|
216
|
+
return true;
|
217
|
+
}
|
218
|
+
return scan_ref_scoped(node, descend);
|
219
|
+
});
|
220
|
+
self.walk(tw);
|
221
|
+
// pass 2: for every used symbol we need to walk its
|
222
|
+
// initialization code to figure out if it uses other
|
223
|
+
// symbols (that may not be in_use).
|
224
|
+
tw = new TreeWalker(scan_ref_scoped);
|
225
|
+
in_use_ids.forEach(function (def) {
|
226
|
+
var init = initializations.get(def.id);
|
227
|
+
if (init) init.forEach(function(init) {
|
228
|
+
init.walk(tw);
|
229
|
+
});
|
230
|
+
});
|
231
|
+
// pass 3: we should drop declarations not in_use
|
232
|
+
var tt = new TreeTransformer(
|
233
|
+
function before(node, descend, in_list) {
|
234
|
+
var parent = tt.parent();
|
235
|
+
if (drop_vars) {
|
236
|
+
const sym = assign_as_unused(node);
|
237
|
+
if (sym instanceof AST_SymbolRef) {
|
238
|
+
var def = sym.definition();
|
239
|
+
var in_use = in_use_ids.has(def.id);
|
240
|
+
if (node instanceof AST_Assign) {
|
241
|
+
if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
|
242
|
+
return maintain_this_binding(parent, node, node.right.transform(tt));
|
243
|
+
}
|
244
|
+
} else if (!in_use) return in_list ? MAP.skip : make_node(AST_Number, node, {
|
245
|
+
value: 0
|
246
|
+
});
|
247
|
+
}
|
248
|
+
}
|
249
|
+
if (scope !== self) return;
|
250
|
+
var def;
|
251
|
+
if (node.name
|
252
|
+
&& (node instanceof AST_ClassExpression
|
253
|
+
&& !keep_name(compressor.option("keep_classnames"), (def = node.name.definition()).name)
|
254
|
+
|| node instanceof AST_Function
|
255
|
+
&& !keep_name(compressor.option("keep_fnames"), (def = node.name.definition()).name))) {
|
256
|
+
// any declarations with same name will overshadow
|
257
|
+
// name of this anonymous function and can therefore
|
258
|
+
// never be used anywhere
|
259
|
+
if (!in_use_ids.has(def.id) || def.orig.length > 1) node.name = null;
|
260
|
+
}
|
261
|
+
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
262
|
+
var trim = !compressor.option("keep_fargs");
|
263
|
+
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
264
|
+
var sym = a[i];
|
265
|
+
if (sym instanceof AST_Expansion) {
|
266
|
+
sym = sym.expression;
|
267
|
+
}
|
268
|
+
if (sym instanceof AST_DefaultAssign) {
|
269
|
+
sym = sym.left;
|
270
|
+
}
|
271
|
+
// Do not drop destructuring arguments.
|
272
|
+
// They constitute a type assertion of sorts
|
273
|
+
if (
|
274
|
+
!(sym instanceof AST_Destructuring)
|
275
|
+
&& !in_use_ids.has(sym.definition().id)
|
276
|
+
) {
|
277
|
+
set_flag(sym, UNUSED);
|
278
|
+
if (trim) {
|
279
|
+
a.pop();
|
280
|
+
}
|
281
|
+
} else {
|
282
|
+
trim = false;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
|
287
|
+
const def = node.name.definition();
|
288
|
+
const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
|
289
|
+
// Class "extends" and static blocks may have side effects
|
290
|
+
const has_side_effects = !keep
|
291
|
+
&& node instanceof AST_Class
|
292
|
+
&& node.has_side_effects(compressor);
|
293
|
+
if (!keep && !has_side_effects) {
|
294
|
+
def.eliminated++;
|
295
|
+
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
296
|
+
}
|
297
|
+
}
|
298
|
+
if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
|
299
|
+
var drop_block = !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var);
|
300
|
+
// place uninitialized names at the start
|
301
|
+
var body = [], head = [], tail = [];
|
302
|
+
// for unused names whose initialization has
|
303
|
+
// side effects, we can cascade the init. code
|
304
|
+
// into the next one, or next statement.
|
305
|
+
var side_effects = [];
|
306
|
+
node.definitions.forEach(function(def) {
|
307
|
+
if (def.value) def.value = def.value.transform(tt);
|
308
|
+
var is_destructure = def.name instanceof AST_Destructuring;
|
309
|
+
var sym = is_destructure
|
310
|
+
? new SymbolDef(null, { name: "<destructure>" }) /* fake SymbolDef */
|
311
|
+
: def.name.definition();
|
312
|
+
if (drop_block && sym.global) return tail.push(def);
|
313
|
+
if (!(drop_vars || drop_block)
|
314
|
+
|| is_destructure
|
315
|
+
&& (def.name.names.length
|
316
|
+
|| def.name.is_array
|
317
|
+
|| compressor.option("pure_getters") != true)
|
318
|
+
|| in_use_ids.has(sym.id)
|
319
|
+
) {
|
320
|
+
if (def.value && fixed_ids.has(sym.id) && fixed_ids.get(sym.id) !== def) {
|
321
|
+
def.value = def.value.drop_side_effect_free(compressor);
|
322
|
+
}
|
323
|
+
if (def.name instanceof AST_SymbolVar) {
|
324
|
+
var var_defs = var_defs_by_id.get(sym.id);
|
325
|
+
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
326
|
+
if (def.value) {
|
327
|
+
var ref = make_node(AST_SymbolRef, def.name, def.name);
|
328
|
+
sym.references.push(ref);
|
329
|
+
var assign = make_node(AST_Assign, def, {
|
330
|
+
operator: "=",
|
331
|
+
logical: false,
|
332
|
+
left: ref,
|
333
|
+
right: def.value
|
334
|
+
});
|
335
|
+
if (fixed_ids.get(sym.id) === def) {
|
336
|
+
fixed_ids.set(sym.id, assign);
|
337
|
+
}
|
338
|
+
side_effects.push(assign.transform(tt));
|
339
|
+
}
|
340
|
+
remove(var_defs, def);
|
341
|
+
sym.eliminated++;
|
342
|
+
return;
|
343
|
+
}
|
344
|
+
}
|
345
|
+
if (def.value) {
|
346
|
+
if (side_effects.length > 0) {
|
347
|
+
if (tail.length > 0) {
|
348
|
+
side_effects.push(def.value);
|
349
|
+
def.value = make_sequence(def.value, side_effects);
|
350
|
+
} else {
|
351
|
+
body.push(make_node(AST_SimpleStatement, node, {
|
352
|
+
body: make_sequence(node, side_effects)
|
353
|
+
}));
|
354
|
+
}
|
355
|
+
side_effects = [];
|
356
|
+
}
|
357
|
+
tail.push(def);
|
358
|
+
} else {
|
359
|
+
head.push(def);
|
360
|
+
}
|
361
|
+
} else if (sym.orig[0] instanceof AST_SymbolCatch) {
|
362
|
+
var value = def.value && def.value.drop_side_effect_free(compressor);
|
363
|
+
if (value) side_effects.push(value);
|
364
|
+
def.value = null;
|
365
|
+
head.push(def);
|
366
|
+
} else {
|
367
|
+
var value = def.value && def.value.drop_side_effect_free(compressor);
|
368
|
+
if (value) {
|
369
|
+
side_effects.push(value);
|
370
|
+
}
|
371
|
+
sym.eliminated++;
|
372
|
+
}
|
373
|
+
});
|
374
|
+
if (head.length > 0 || tail.length > 0) {
|
375
|
+
node.definitions = head.concat(tail);
|
376
|
+
body.push(node);
|
377
|
+
}
|
378
|
+
if (side_effects.length > 0) {
|
379
|
+
body.push(make_node(AST_SimpleStatement, node, {
|
380
|
+
body: make_sequence(node, side_effects)
|
381
|
+
}));
|
382
|
+
}
|
383
|
+
switch (body.length) {
|
384
|
+
case 0:
|
385
|
+
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
386
|
+
case 1:
|
387
|
+
return body[0];
|
388
|
+
default:
|
389
|
+
return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
|
390
|
+
body: body
|
391
|
+
});
|
392
|
+
}
|
393
|
+
}
|
394
|
+
// certain combination of unused name + side effect leads to:
|
395
|
+
// https://github.com/mishoo/UglifyJS2/issues/44
|
396
|
+
// https://github.com/mishoo/UglifyJS2/issues/1830
|
397
|
+
// https://github.com/mishoo/UglifyJS2/issues/1838
|
398
|
+
// that's an invalid AST.
|
399
|
+
// We fix it at this stage by moving the `var` outside the `for`.
|
400
|
+
if (node instanceof AST_For) {
|
401
|
+
descend(node, this);
|
402
|
+
var block;
|
403
|
+
if (node.init instanceof AST_BlockStatement) {
|
404
|
+
block = node.init;
|
405
|
+
node.init = block.body.pop();
|
406
|
+
block.body.push(node);
|
407
|
+
}
|
408
|
+
if (node.init instanceof AST_SimpleStatement) {
|
409
|
+
node.init = node.init.body;
|
410
|
+
} else if (is_empty(node.init)) {
|
411
|
+
node.init = null;
|
412
|
+
}
|
413
|
+
return !block ? node : in_list ? MAP.splice(block.body) : block;
|
414
|
+
}
|
415
|
+
if (node instanceof AST_LabeledStatement
|
416
|
+
&& node.body instanceof AST_For
|
417
|
+
) {
|
418
|
+
descend(node, this);
|
419
|
+
if (node.body instanceof AST_BlockStatement) {
|
420
|
+
var block = node.body;
|
421
|
+
node.body = block.body.pop();
|
422
|
+
block.body.push(node);
|
423
|
+
return in_list ? MAP.splice(block.body) : block;
|
424
|
+
}
|
425
|
+
return node;
|
426
|
+
}
|
427
|
+
if (node instanceof AST_BlockStatement) {
|
428
|
+
descend(node, this);
|
429
|
+
if (in_list && node.body.every(can_be_evicted_from_block)) {
|
430
|
+
return MAP.splice(node.body);
|
431
|
+
}
|
432
|
+
return node;
|
433
|
+
}
|
434
|
+
if (node instanceof AST_Scope) {
|
435
|
+
const save_scope = scope;
|
436
|
+
scope = node;
|
437
|
+
descend(node, this);
|
438
|
+
scope = save_scope;
|
439
|
+
return node;
|
440
|
+
}
|
441
|
+
}
|
442
|
+
);
|
443
|
+
|
444
|
+
self.transform(tt);
|
445
|
+
|
446
|
+
function scan_ref_scoped(node, descend) {
|
447
|
+
var node_def;
|
448
|
+
const sym = assign_as_unused(node);
|
449
|
+
if (sym instanceof AST_SymbolRef
|
450
|
+
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
|
451
|
+
&& self.variables.get(sym.name) === (node_def = sym.definition())
|
452
|
+
) {
|
453
|
+
if (node instanceof AST_Assign) {
|
454
|
+
node.right.walk(tw);
|
455
|
+
if (!node_def.chained && node.left.fixed_value() === node.right) {
|
456
|
+
fixed_ids.set(node_def.id, node);
|
457
|
+
}
|
458
|
+
}
|
459
|
+
return true;
|
460
|
+
}
|
461
|
+
if (node instanceof AST_SymbolRef) {
|
462
|
+
node_def = node.definition();
|
463
|
+
if (!in_use_ids.has(node_def.id)) {
|
464
|
+
in_use_ids.set(node_def.id, node_def);
|
465
|
+
if (node_def.orig[0] instanceof AST_SymbolCatch) {
|
466
|
+
const redef = node_def.scope.is_block_scope()
|
467
|
+
&& node_def.scope.get_defun_scope().variables.get(node_def.name);
|
468
|
+
if (redef) in_use_ids.set(redef.id, redef);
|
469
|
+
}
|
470
|
+
}
|
471
|
+
return true;
|
472
|
+
}
|
473
|
+
if (node instanceof AST_Scope) {
|
474
|
+
var save_scope = scope;
|
475
|
+
scope = node;
|
476
|
+
descend();
|
477
|
+
scope = save_scope;
|
478
|
+
return true;
|
479
|
+
}
|
480
|
+
}
|
481
|
+
});
|
482
|
+
|
package/lib/compress/evaluate.js
CHANGED
@@ -99,6 +99,13 @@ AST_Node.DEFMETHOD("evaluate", function (compressor) {
|
|
99
99
|
return val;
|
100
100
|
if (typeof val == "function" || typeof val == "object" || val == nullish)
|
101
101
|
return this;
|
102
|
+
|
103
|
+
// Evaluated strings can be larger than the original expression
|
104
|
+
if (typeof val === "string") {
|
105
|
+
const unevaluated_size = this.size(compressor);
|
106
|
+
if (val.length + 2 > unevaluated_size) return this;
|
107
|
+
}
|
108
|
+
|
102
109
|
return val;
|
103
110
|
});
|
104
111
|
|