terser 5.16.1 → 5.16.3
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/README.md +4 -4
- package/dist/bundle.min.js +372 -194
- package/lib/ast.js +4 -0
- package/lib/compress/common.js +3 -2
- package/lib/compress/inline.js +119 -114
- package/lib/compress/native-objects.js +22 -0
- package/lib/compress/reduce-vars.js +30 -11
- package/lib/compress/tighten-body.js +9 -2
- package/lib/minify.js +9 -6
- package/lib/mozilla-ast.js +83 -34
- package/lib/output.js +44 -12
- package/lib/parse.js +46 -12
- package/lib/scope.js +3 -1
- package/package.json +1 -1
- package/tools/terser.d.ts +1 -0
- package/bin/terser.mjs +0 -21
package/lib/ast.js
CHANGED
@@ -994,6 +994,7 @@ var AST_Jump = DEFNODE("Jump", null, function AST_Jump(props) {
|
|
994
994
|
$documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
|
995
995
|
}, AST_Statement);
|
996
996
|
|
997
|
+
/** Base class for “exits” (`return` and `throw`) */
|
997
998
|
var AST_Exit = DEFNODE("Exit", "value", function AST_Exit(props) {
|
998
999
|
if (props) {
|
999
1000
|
this.value = props.value;
|
@@ -2588,6 +2589,7 @@ var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, function AST_
|
|
2588
2589
|
this.scope = props.scope;
|
2589
2590
|
this.name = props.name;
|
2590
2591
|
this.thedef = props.thedef;
|
2592
|
+
this.quote = props.quote;
|
2591
2593
|
this.start = props.start;
|
2592
2594
|
this.end = props.end;
|
2593
2595
|
}
|
@@ -2639,6 +2641,7 @@ var AST_SymbolExport = DEFNODE("SymbolExport", null, function AST_SymbolExport(p
|
|
2639
2641
|
this.scope = props.scope;
|
2640
2642
|
this.name = props.name;
|
2641
2643
|
this.thedef = props.thedef;
|
2644
|
+
this.quote = props.quote;
|
2642
2645
|
this.start = props.start;
|
2643
2646
|
this.end = props.end;
|
2644
2647
|
}
|
@@ -2653,6 +2656,7 @@ var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, function AST_
|
|
2653
2656
|
this.scope = props.scope;
|
2654
2657
|
this.name = props.name;
|
2655
2658
|
this.thedef = props.thedef;
|
2659
|
+
this.quote = props.quote;
|
2656
2660
|
this.start = props.start;
|
2657
2661
|
this.end = props.end;
|
2658
2662
|
}
|
package/lib/compress/common.js
CHANGED
@@ -241,9 +241,10 @@ export function is_func_expr(node) {
|
|
241
241
|
return node instanceof AST_Arrow || node instanceof AST_Function;
|
242
242
|
}
|
243
243
|
|
244
|
+
/**
|
245
|
+
* Used to determine whether the node can benefit from negation.
|
246
|
+
* Not the case with arrow functions (you need an extra set of parens). */
|
244
247
|
export function is_iife_call(node) {
|
245
|
-
// Used to determine whether the node can benefit from negation.
|
246
|
-
// Not the case with arrow functions (you need an extra set of parens).
|
247
248
|
if (node.TYPE != "Call") return false;
|
248
249
|
return node.expression instanceof AST_Function || is_iife_call(node.expression);
|
249
250
|
}
|
package/lib/compress/inline.js
CHANGED
@@ -92,7 +92,6 @@ import "../size.js";
|
|
92
92
|
import "./evaluate.js";
|
93
93
|
import "./drop-side-effect-free.js";
|
94
94
|
import "./reduce-vars.js";
|
95
|
-
import { is_lhs } from "./inference.js";
|
96
95
|
import {
|
97
96
|
SQUEEZED,
|
98
97
|
INLINED,
|
@@ -114,6 +113,13 @@ import {
|
|
114
113
|
retain_top_func,
|
115
114
|
} from "./common.js";
|
116
115
|
|
116
|
+
/**
|
117
|
+
* Module that contains the inlining logic.
|
118
|
+
*
|
119
|
+
* @module
|
120
|
+
*
|
121
|
+
* The stars of the show are `inline_into_symbolref` and `inline_into_call`.
|
122
|
+
*/
|
117
123
|
|
118
124
|
function within_array_or_object_literal(compressor) {
|
119
125
|
var node, level = 0;
|
@@ -144,136 +150,135 @@ function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
|
|
144
150
|
|
145
151
|
export function inline_into_symbolref(self, compressor) {
|
146
152
|
const parent = compressor.parent();
|
147
|
-
if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
|
148
|
-
const def = self.definition();
|
149
|
-
const nearest_scope = compressor.find_scope();
|
150
|
-
if (compressor.top_retain && def.global && compressor.top_retain(def)) {
|
151
|
-
def.fixed = false;
|
152
|
-
def.single_use = false;
|
153
|
-
return self;
|
154
|
-
}
|
155
153
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
&& fixed.name);
|
164
|
-
|
165
|
-
if (single_use && fixed instanceof AST_Node) {
|
166
|
-
single_use =
|
167
|
-
!fixed.has_side_effects(compressor)
|
168
|
-
&& !fixed.may_throw(compressor);
|
169
|
-
}
|
154
|
+
const def = self.definition();
|
155
|
+
const nearest_scope = compressor.find_scope();
|
156
|
+
if (compressor.top_retain && def.global && compressor.top_retain(def)) {
|
157
|
+
def.fixed = false;
|
158
|
+
def.single_use = false;
|
159
|
+
return self;
|
160
|
+
}
|
170
161
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
162
|
+
let fixed = self.fixed_value();
|
163
|
+
let single_use = def.single_use
|
164
|
+
&& !(parent instanceof AST_Call
|
165
|
+
&& (parent.is_callee_pure(compressor))
|
166
|
+
|| has_annotation(parent, _NOINLINE))
|
167
|
+
&& !(parent instanceof AST_Export
|
168
|
+
&& fixed instanceof AST_Lambda
|
169
|
+
&& fixed.name);
|
170
|
+
|
171
|
+
if (single_use && fixed instanceof AST_Node) {
|
172
|
+
single_use =
|
173
|
+
!fixed.has_side_effects(compressor)
|
174
|
+
&& !fixed.may_throw(compressor);
|
175
|
+
}
|
176
|
+
|
177
|
+
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
178
|
+
if (retain_top_func(fixed, compressor)) {
|
179
|
+
single_use = false;
|
180
|
+
} else if (def.scope !== self.scope
|
181
|
+
&& (def.escaped == 1
|
182
|
+
|| has_flag(fixed, INLINED)
|
183
|
+
|| within_array_or_object_literal(compressor)
|
184
|
+
|| !compressor.option("reduce_funcs"))) {
|
185
|
+
single_use = false;
|
186
|
+
} else if (is_recursive_ref(compressor, def)) {
|
187
|
+
single_use = false;
|
188
|
+
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
189
|
+
single_use = fixed.is_constant_expression(self.scope);
|
190
|
+
if (single_use == "f") {
|
191
|
+
var scope = self.scope;
|
192
|
+
do {
|
193
|
+
if (scope instanceof AST_Defun || is_func_expr(scope)) {
|
194
|
+
set_flag(scope, INLINED);
|
195
|
+
}
|
196
|
+
} while (scope = scope.parent_scope);
|
192
197
|
}
|
193
198
|
}
|
199
|
+
}
|
194
200
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
201
|
+
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
202
|
+
single_use =
|
203
|
+
def.scope === self.scope
|
204
|
+
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
205
|
+
|| parent instanceof AST_Call
|
206
|
+
&& parent.expression === self
|
207
|
+
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
208
|
+
&& !(fixed.name && fixed.name.definition().recursive_refs > 0);
|
209
|
+
}
|
204
210
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
211
|
+
if (single_use && fixed) {
|
212
|
+
if (fixed instanceof AST_DefClass) {
|
213
|
+
set_flag(fixed, SQUEEZED);
|
214
|
+
fixed = make_node(AST_ClassExpression, fixed, fixed);
|
215
|
+
}
|
216
|
+
if (fixed instanceof AST_Defun) {
|
217
|
+
set_flag(fixed, SQUEEZED);
|
218
|
+
fixed = make_node(AST_Function, fixed, fixed);
|
219
|
+
}
|
220
|
+
if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
|
221
|
+
const defun_def = fixed.name.definition();
|
222
|
+
let lambda_def = fixed.variables.get(fixed.name.name);
|
223
|
+
let name = lambda_def && lambda_def.orig[0];
|
224
|
+
if (!(name instanceof AST_SymbolLambda)) {
|
225
|
+
name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
226
|
+
name.scope = fixed;
|
227
|
+
fixed.name = name;
|
228
|
+
lambda_def = fixed.def_function(name);
|
213
229
|
}
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
if (!(name instanceof AST_SymbolLambda)) {
|
219
|
-
name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
220
|
-
name.scope = fixed;
|
221
|
-
fixed.name = name;
|
222
|
-
lambda_def = fixed.def_function(name);
|
230
|
+
walk(fixed, node => {
|
231
|
+
if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
|
232
|
+
node.thedef = lambda_def;
|
233
|
+
lambda_def.references.push(node);
|
223
234
|
}
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
235
|
+
});
|
236
|
+
}
|
237
|
+
if (
|
238
|
+
(fixed instanceof AST_Lambda || fixed instanceof AST_Class)
|
239
|
+
&& fixed.parent_scope !== nearest_scope
|
240
|
+
) {
|
241
|
+
fixed = fixed.clone(true, compressor.get_toplevel());
|
242
|
+
|
243
|
+
nearest_scope.add_child_scope(fixed);
|
244
|
+
}
|
245
|
+
return fixed.optimize(compressor);
|
246
|
+
}
|
247
|
+
|
248
|
+
// multiple uses
|
249
|
+
if (fixed) {
|
250
|
+
let replace;
|
251
|
+
|
252
|
+
if (fixed instanceof AST_This) {
|
253
|
+
if (!(def.orig[0] instanceof AST_SymbolFunarg)
|
254
|
+
&& def.references.every((ref) =>
|
255
|
+
def.scope === ref.scope
|
256
|
+
)) {
|
257
|
+
replace = fixed;
|
230
258
|
}
|
259
|
+
} else {
|
260
|
+
var ev = fixed.evaluate(compressor);
|
231
261
|
if (
|
232
|
-
|
233
|
-
&&
|
262
|
+
ev !== fixed
|
263
|
+
&& (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
|
234
264
|
) {
|
235
|
-
|
236
|
-
|
237
|
-
nearest_scope.add_child_scope(fixed);
|
265
|
+
replace = make_node_from_constant(ev, fixed);
|
238
266
|
}
|
239
|
-
return fixed.optimize(compressor);
|
240
267
|
}
|
241
268
|
|
242
|
-
|
243
|
-
|
244
|
-
|
269
|
+
if (replace) {
|
270
|
+
const name_length = self.size(compressor);
|
271
|
+
const replace_size = replace.size(compressor);
|
245
272
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
)
|
251
|
-
replace = fixed;
|
252
|
-
}
|
253
|
-
} else {
|
254
|
-
var ev = fixed.evaluate(compressor);
|
255
|
-
if (
|
256
|
-
ev !== fixed
|
257
|
-
&& (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
|
258
|
-
) {
|
259
|
-
replace = make_node_from_constant(ev, fixed);
|
260
|
-
}
|
273
|
+
let overhead = 0;
|
274
|
+
if (compressor.option("unused") && !compressor.exposed(def)) {
|
275
|
+
overhead =
|
276
|
+
(name_length + 2 + replace_size) /
|
277
|
+
(def.references.length - def.assignments);
|
261
278
|
}
|
262
279
|
|
263
|
-
if (
|
264
|
-
|
265
|
-
const replace_size = replace.size(compressor);
|
266
|
-
|
267
|
-
let overhead = 0;
|
268
|
-
if (compressor.option("unused") && !compressor.exposed(def)) {
|
269
|
-
overhead =
|
270
|
-
(name_length + 2 + replace_size) /
|
271
|
-
(def.references.length - def.assignments);
|
272
|
-
}
|
273
|
-
|
274
|
-
if (replace_size <= name_length + overhead) {
|
275
|
-
return replace;
|
276
|
-
}
|
280
|
+
if (replace_size <= name_length + overhead) {
|
281
|
+
return replace;
|
277
282
|
}
|
278
283
|
}
|
279
284
|
}
|
@@ -79,6 +79,9 @@ const object_methods = [
|
|
79
79
|
|
80
80
|
export const is_pure_native_method = make_nested_lookup({
|
81
81
|
Array: [
|
82
|
+
"at",
|
83
|
+
"flat",
|
84
|
+
"includes",
|
82
85
|
"indexOf",
|
83
86
|
"join",
|
84
87
|
"lastIndexOf",
|
@@ -99,22 +102,41 @@ export const is_pure_native_method = make_nested_lookup({
|
|
99
102
|
...object_methods,
|
100
103
|
],
|
101
104
|
String: [
|
105
|
+
"at",
|
102
106
|
"charAt",
|
103
107
|
"charCodeAt",
|
108
|
+
"charPointAt",
|
104
109
|
"concat",
|
110
|
+
"endsWith",
|
111
|
+
"fromCharCode",
|
112
|
+
"fromCodePoint",
|
113
|
+
"includes",
|
105
114
|
"indexOf",
|
106
115
|
"italics",
|
107
116
|
"lastIndexOf",
|
117
|
+
"localeCompare",
|
108
118
|
"match",
|
119
|
+
"matchAll",
|
120
|
+
"normalize",
|
121
|
+
"padStart",
|
122
|
+
"padEnd",
|
123
|
+
"repeat",
|
109
124
|
"replace",
|
125
|
+
"replaceAll",
|
110
126
|
"search",
|
111
127
|
"slice",
|
112
128
|
"split",
|
129
|
+
"startsWith",
|
113
130
|
"substr",
|
114
131
|
"substring",
|
132
|
+
"repeat",
|
133
|
+
"toLocaleLowerCase",
|
134
|
+
"toLocaleUpperCase",
|
115
135
|
"toLowerCase",
|
116
136
|
"toUpperCase",
|
117
137
|
"trim",
|
138
|
+
"trimEnd",
|
139
|
+
"trimStart",
|
118
140
|
...object_methods,
|
119
141
|
],
|
120
142
|
});
|
@@ -103,15 +103,17 @@ import { lazy_op, is_modified } from "./inference.js";
|
|
103
103
|
import { INLINED, clear_flag } from "./compressor-flags.js";
|
104
104
|
import { read_property, has_break_or_continue, is_recursive_ref } from "./common.js";
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
/**
|
107
|
+
* Define the method AST_Node#reduce_vars, which goes through the AST in
|
108
|
+
* execution order to perform basic flow analysis
|
109
|
+
*/
|
109
110
|
function def_reduce_vars(node, func) {
|
110
111
|
node.DEFMETHOD("reduce_vars", func);
|
111
112
|
}
|
112
113
|
|
113
114
|
def_reduce_vars(AST_Node, noop);
|
114
115
|
|
116
|
+
/** Clear definition properties */
|
115
117
|
function reset_def(compressor, def) {
|
116
118
|
def.assignments = 0;
|
117
119
|
def.chained = false;
|
@@ -120,7 +122,10 @@ function reset_def(compressor, def) {
|
|
120
122
|
def.recursive_refs = 0;
|
121
123
|
def.references = [];
|
122
124
|
def.single_use = undefined;
|
123
|
-
if (
|
125
|
+
if (
|
126
|
+
def.scope.pinned()
|
127
|
+
|| (def.orig[0] instanceof AST_SymbolFunarg && def.scope.uses_arguments)
|
128
|
+
) {
|
124
129
|
def.fixed = false;
|
125
130
|
} else if (def.orig[0] instanceof AST_SymbolConst || !compressor.exposed(def)) {
|
126
131
|
def.fixed = def.init;
|
@@ -442,15 +447,23 @@ def_reduce_vars(AST_Default, function(tw, descend) {
|
|
442
447
|
|
443
448
|
function mark_lambda(tw, descend, compressor) {
|
444
449
|
clear_flag(this, INLINED);
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
450
|
+
|
451
|
+
// Sometimes we detach the lambda for safety, and instead of push()
|
452
|
+
// we go to an entirely fresh lineage of safe_ids.
|
453
|
+
let previous_safe_ids;
|
454
|
+
if (this instanceof AST_Defun || this.uses_arguments || this.pinned()) {
|
455
|
+
previous_safe_ids = tw.safe_ids;
|
456
|
+
tw.safe_ids = Object.create(null);
|
457
|
+
} else {
|
458
|
+
push(tw);
|
451
459
|
}
|
460
|
+
|
461
|
+
reset_variables(tw, compressor, this);
|
462
|
+
|
452
463
|
var iife;
|
453
464
|
if (!this.name
|
465
|
+
&& !this.uses_arguments
|
466
|
+
&& !this.pinned()
|
454
467
|
&& (iife = tw.parent()) instanceof AST_Call
|
455
468
|
&& iife.expression === this
|
456
469
|
&& !iife.args.some(arg => arg instanceof AST_Expansion)
|
@@ -476,7 +489,13 @@ function mark_lambda(tw, descend, compressor) {
|
|
476
489
|
});
|
477
490
|
}
|
478
491
|
descend();
|
479
|
-
|
492
|
+
|
493
|
+
if (previous_safe_ids) {
|
494
|
+
tw.safe_ids = previous_safe_ids;
|
495
|
+
} else {
|
496
|
+
pop(tw);
|
497
|
+
}
|
498
|
+
|
480
499
|
return true;
|
481
500
|
}
|
482
501
|
|
@@ -1404,14 +1404,21 @@ export function tighten_body(statements, compressor) {
|
|
1404
1404
|
CHANGED = true;
|
1405
1405
|
stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
|
1406
1406
|
statements[++j] = stat;
|
1407
|
-
} else if (
|
1407
|
+
} else if (
|
1408
|
+
prev instanceof AST_Var
|
1409
|
+
&& (!stat.init || stat.init.TYPE == prev.TYPE)
|
1410
|
+
) {
|
1408
1411
|
if (stat.init) {
|
1409
1412
|
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
1410
1413
|
}
|
1411
1414
|
stat.init = prev;
|
1412
1415
|
statements[j] = stat;
|
1413
1416
|
CHANGED = true;
|
1414
|
-
} else if (
|
1417
|
+
} else if (
|
1418
|
+
defs instanceof AST_Var
|
1419
|
+
&& stat.init instanceof AST_Var
|
1420
|
+
&& declarations_only(stat.init)
|
1421
|
+
) {
|
1415
1422
|
defs.definitions = defs.definitions.concat(stat.init.definitions);
|
1416
1423
|
stat.init = null;
|
1417
1424
|
statements[++j] = stat;
|
package/lib/minify.js
CHANGED
@@ -19,12 +19,15 @@ import {
|
|
19
19
|
reserve_quoted_keys,
|
20
20
|
} from "./propmangle.js";
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
var
|
26
|
-
|
27
|
-
|
22
|
+
// to/from base64 functions
|
23
|
+
// Prefer built-in Buffer, if available, then use hack
|
24
|
+
// https://developer.mozilla.org/en-US/docs/Glossary/Base64#The_Unicode_Problem
|
25
|
+
var to_ascii = typeof Buffer !== "undefined"
|
26
|
+
? (b64) => Buffer.from(b64, "base64").toString()
|
27
|
+
: (b64) => decodeURIComponent(escape(atob(b64)));
|
28
|
+
var to_base64 = typeof Buffer !== "undefined"
|
29
|
+
? (str) => Buffer.from(str).toString("base64")
|
30
|
+
: (str) => btoa(unescape(encodeURIComponent(str)));
|
28
31
|
|
29
32
|
function read_source_map(code) {
|
30
33
|
var match = /(?:^|[^.])\/\/# sourceMappingURL=data:application\/json(;[\w=-]*)?;base64,([+/0-9A-Za-z]*=*)\s*$/.exec(code);
|