terser 5.19.4 → 5.21.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 +10 -0
- package/README.md +3 -4
- package/dist/bundle.min.js +364 -122
- package/lib/compress/common.js +1 -1
- package/lib/compress/drop-unused.js +8 -8
- package/lib/compress/global-defs.js +92 -0
- package/lib/compress/index.js +33 -30
- package/lib/compress/inference.js +1 -79
- package/lib/compress/inline.js +10 -3
- package/lib/minify.js +3 -0
- package/lib/mozilla-ast.js +3 -5
- package/lib/output.js +2 -1
- package/package.json +1 -1
- package/tools/domprops.js +231 -1
- package/tools/terser.d.ts +4 -1
- package/bin/terser.mjs +0 -18
package/lib/compress/common.js
CHANGED
@@ -128,7 +128,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
128
128
|
var fixed_ids = new Map();
|
129
129
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
130
130
|
self.variables.forEach(function(def) {
|
131
|
-
if (compressor.top_retain(def)
|
131
|
+
if (compressor.top_retain(def)) {
|
132
132
|
in_use_ids.set(def.id, def);
|
133
133
|
}
|
134
134
|
});
|
@@ -143,9 +143,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
143
143
|
node.argnames.forEach(function(argname) {
|
144
144
|
if (!(argname instanceof AST_SymbolDeclaration)) return;
|
145
145
|
var def = argname.definition();
|
146
|
-
|
147
|
-
in_use_ids.set(def.id, def);
|
148
|
-
}
|
146
|
+
in_use_ids.set(def.id, def);
|
149
147
|
});
|
150
148
|
}
|
151
149
|
if (node === self) return;
|
@@ -158,7 +156,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
158
156
|
var node_def = node.name.definition();
|
159
157
|
const in_export = tw.parent() instanceof AST_Export;
|
160
158
|
if (in_export || !drop_funcs && scope === self) {
|
161
|
-
if (node_def.global
|
159
|
+
if (node_def.global) {
|
162
160
|
in_use_ids.set(node_def.id, node_def);
|
163
161
|
}
|
164
162
|
}
|
@@ -166,10 +164,12 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
166
164
|
map_add(initializations, node_def.id, node);
|
167
165
|
return true; // don't go in nested scopes
|
168
166
|
}
|
169
|
-
|
167
|
+
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
168
|
+
const in_root_scope = scope === self;
|
169
|
+
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
170
170
|
map_add(var_defs_by_id, node.definition().id, node);
|
171
171
|
}
|
172
|
-
if (node instanceof AST_Definitions &&
|
172
|
+
if (node instanceof AST_Definitions && in_root_scope) {
|
173
173
|
const in_export = tw.parent() instanceof AST_Export;
|
174
174
|
node.definitions.forEach(function(def) {
|
175
175
|
if (def.name instanceof AST_SymbolVar) {
|
@@ -179,7 +179,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
179
179
|
walk(def.name, node => {
|
180
180
|
if (node instanceof AST_SymbolDeclaration) {
|
181
181
|
const def = node.definition();
|
182
|
-
if (def.global
|
182
|
+
if (def.global) {
|
183
183
|
in_use_ids.set(def.id, def);
|
184
184
|
}
|
185
185
|
}
|
@@ -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 }) {
|
@@ -385,7 +385,7 @@ class Compressor extends TreeWalker {
|
|
385
385
|
this._toplevel.figure_out_scope(mangle);
|
386
386
|
if (pass === 0 && this.option("drop_console")) {
|
387
387
|
// must be run before reduce_vars and compress pass
|
388
|
-
this._toplevel = this._toplevel.drop_console();
|
388
|
+
this._toplevel = this._toplevel.drop_console(this.option("drop_console"));
|
389
389
|
}
|
390
390
|
if (pass > 0 || this.option("reduce_vars")) {
|
391
391
|
this._toplevel.reset_opt_flags(this);
|
@@ -464,19 +464,30 @@ def_optimize(AST_Node, function(self) {
|
|
464
464
|
return self;
|
465
465
|
});
|
466
466
|
|
467
|
-
AST_Toplevel.DEFMETHOD("drop_console", function() {
|
467
|
+
AST_Toplevel.DEFMETHOD("drop_console", function(options) {
|
468
|
+
var isArray = Array.isArray(options);
|
469
|
+
|
468
470
|
return this.transform(new TreeTransformer(function(self) {
|
469
|
-
if (self.TYPE
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
471
|
+
if (self.TYPE !== "Call") {
|
472
|
+
return;
|
473
|
+
}
|
474
|
+
|
475
|
+
var exp = self.expression;
|
476
|
+
|
477
|
+
if (!(exp instanceof AST_PropAccess)) {
|
478
|
+
return;
|
479
|
+
}
|
480
|
+
|
481
|
+
if (isArray && options.indexOf(exp.property) === -1) {
|
482
|
+
return;
|
483
|
+
}
|
484
|
+
|
485
|
+
var name = exp.expression;
|
486
|
+
while (name.expression) {
|
487
|
+
name = name.expression;
|
488
|
+
}
|
489
|
+
if (is_undeclared_ref(name) && name.name == "console") {
|
490
|
+
return make_node(AST_Undefined, self);
|
480
491
|
}
|
481
492
|
}));
|
482
493
|
});
|
@@ -1598,18 +1609,10 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1598
1609
|
var exp = self.expression;
|
1599
1610
|
var fn = exp;
|
1600
1611
|
inline_array_like_spread(self.args);
|
1601
|
-
var simple_args = self.args.every((arg) =>
|
1602
|
-
!(arg instanceof AST_Expansion)
|
1603
|
-
);
|
1612
|
+
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
1604
1613
|
|
1605
|
-
if (compressor.option("reduce_vars")
|
1606
|
-
|
1607
|
-
&& !has_annotation(self, _NOINLINE)
|
1608
|
-
) {
|
1609
|
-
const fixed = fn.fixed_value();
|
1610
|
-
if (!retain_top_func(fixed, compressor)) {
|
1611
|
-
fn = fixed;
|
1612
|
-
}
|
1614
|
+
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
1615
|
+
fn = fn.fixed_value();
|
1613
1616
|
}
|
1614
1617
|
|
1615
1618
|
var is_func = fn instanceof AST_Lambda;
|
@@ -1917,7 +1920,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
1917
1920
|
}
|
1918
1921
|
}
|
1919
1922
|
|
1920
|
-
return inline_into_call(self,
|
1923
|
+
return inline_into_call(self, compressor);
|
1921
1924
|
});
|
1922
1925
|
|
1923
1926
|
def_optimize(AST_New, function(self, compressor) {
|
@@ -3750,10 +3753,10 @@ def_optimize(AST_Destructuring, function(self, compressor) {
|
|
3750
3753
|
if (def.references.length) return true;
|
3751
3754
|
if (!def.global) return false;
|
3752
3755
|
if (compressor.toplevel.vars) {
|
3753
|
-
|
3754
|
-
|
3755
|
-
|
3756
|
-
|
3756
|
+
if (compressor.top_retain) {
|
3757
|
+
return compressor.top_retain(def);
|
3758
|
+
}
|
3759
|
+
return false;
|
3757
3760
|
}
|
3758
3761
|
return true;
|
3759
3762
|
}
|
@@ -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/minify.js
CHANGED
package/lib/mozilla-ast.js
CHANGED
@@ -166,17 +166,15 @@ import { is_basic_identifier_string } from "./parse.js";
|
|
166
166
|
(function() {
|
167
167
|
|
168
168
|
var normalize_directives = function(body) {
|
169
|
-
var in_directive = true;
|
170
|
-
|
171
169
|
for (var i = 0; i < body.length; i++) {
|
172
|
-
if (
|
170
|
+
if (body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
|
173
171
|
body[i] = new AST_Directive({
|
174
172
|
start: body[i].start,
|
175
173
|
end: body[i].end,
|
176
174
|
value: body[i].body.value
|
177
175
|
});
|
178
|
-
} else
|
179
|
-
|
176
|
+
} else {
|
177
|
+
return body;
|
180
178
|
}
|
181
179
|
}
|
182
180
|
|
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
|