terser 5.7.2 → 5.8.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 +15 -2
- package/bin/terser.mjs +21 -0
- package/dist/bundle.min.js +422 -110
- package/lib/ast.js +1 -1
- package/lib/compress/index.js +293 -44
- package/lib/compress/tighten-body.js +29 -7
- package/lib/minify.js +2 -2
- package/lib/output.js +9 -4
- package/lib/propmangle.js +54 -31
- package/lib/scope.js +37 -17
- package/lib/transform.js +2 -2
- package/package.json +9 -9
- package/tools/terser.d.ts +36 -0
package/lib/propmangle.js
CHANGED
@@ -59,6 +59,8 @@ import {
|
|
59
59
|
AST_ObjectKeyVal,
|
60
60
|
AST_ObjectProperty,
|
61
61
|
AST_PrivateMethod,
|
62
|
+
AST_PrivateGetter,
|
63
|
+
AST_PrivateSetter,
|
62
64
|
AST_Sequence,
|
63
65
|
AST_String,
|
64
66
|
AST_Sub,
|
@@ -140,28 +142,59 @@ function addStrings(node, add) {
|
|
140
142
|
}));
|
141
143
|
}
|
142
144
|
|
145
|
+
function mangle_private_properties(ast, options) {
|
146
|
+
var cprivate = -1;
|
147
|
+
var private_cache = new Map();
|
148
|
+
var nth_identifier = options.nth_identifier || base54;
|
149
|
+
|
150
|
+
ast = ast.transform(new TreeTransformer(function(node) {
|
151
|
+
if (
|
152
|
+
node instanceof AST_ClassPrivateProperty
|
153
|
+
|| node instanceof AST_PrivateMethod
|
154
|
+
|| node instanceof AST_PrivateGetter
|
155
|
+
|| node instanceof AST_PrivateSetter
|
156
|
+
) {
|
157
|
+
node.key.name = mangle_private(node.key.name);
|
158
|
+
} else if (node instanceof AST_DotHash) {
|
159
|
+
node.property = mangle_private(node.property);
|
160
|
+
}
|
161
|
+
}));
|
162
|
+
return ast;
|
163
|
+
|
164
|
+
function mangle_private(name) {
|
165
|
+
let mangled = private_cache.get(name);
|
166
|
+
if (!mangled) {
|
167
|
+
mangled = nth_identifier.get(++cprivate);
|
168
|
+
private_cache.set(name, mangled);
|
169
|
+
}
|
170
|
+
|
171
|
+
return mangled;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
143
175
|
function mangle_properties(ast, options) {
|
144
176
|
options = defaults(options, {
|
145
177
|
builtins: false,
|
146
178
|
cache: null,
|
147
179
|
debug: false,
|
148
180
|
keep_quoted: false,
|
181
|
+
nth_identifier: base54,
|
149
182
|
only_cache: false,
|
150
183
|
regex: null,
|
151
184
|
reserved: null,
|
152
185
|
undeclared: false,
|
153
186
|
}, true);
|
154
187
|
|
188
|
+
var nth_identifier = options.nth_identifier;
|
189
|
+
|
155
190
|
var reserved_option = options.reserved;
|
156
191
|
if (!Array.isArray(reserved_option)) reserved_option = [reserved_option];
|
157
192
|
var reserved = new Set(reserved_option);
|
158
193
|
if (!options.builtins) find_builtins(reserved);
|
159
194
|
|
160
195
|
var cname = -1;
|
161
|
-
var cprivate = -1;
|
162
196
|
|
163
197
|
var cache;
|
164
|
-
var private_cache = new Map();
|
165
198
|
if (options.cache) {
|
166
199
|
cache = options.cache.props;
|
167
200
|
cache.forEach(function(mangled_name) {
|
@@ -184,27 +217,26 @@ function mangle_properties(ast, options) {
|
|
184
217
|
|
185
218
|
var names_to_mangle = new Set();
|
186
219
|
var unmangleable = new Set();
|
187
|
-
var private_properties = new Set();
|
188
220
|
|
189
|
-
var
|
221
|
+
var keep_quoted = !!options.keep_quoted;
|
190
222
|
|
191
223
|
// step 1: find candidates to mangle
|
192
224
|
ast.walk(new TreeWalker(function(node) {
|
193
225
|
if (
|
194
226
|
node instanceof AST_ClassPrivateProperty
|
195
227
|
|| node instanceof AST_PrivateMethod
|
228
|
+
|| node instanceof AST_PrivateGetter
|
229
|
+
|| node instanceof AST_PrivateSetter
|
230
|
+
|| node instanceof AST_DotHash
|
196
231
|
) {
|
197
|
-
|
198
|
-
} else if (node instanceof AST_DotHash) {
|
199
|
-
private_properties.add(node.property);
|
232
|
+
// handled by mangle_private_properties
|
200
233
|
} else if (node instanceof AST_ObjectKeyVal) {
|
201
|
-
if (typeof node.key == "string" &&
|
202
|
-
(!keep_quoted_strict || !node.quote)) {
|
234
|
+
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
|
203
235
|
add(node.key);
|
204
236
|
}
|
205
237
|
} else if (node instanceof AST_ObjectProperty) {
|
206
238
|
// setter or getter, since KeyVal is handled above
|
207
|
-
if (!
|
239
|
+
if (!keep_quoted || !node.quote) {
|
208
240
|
add(node.key.name);
|
209
241
|
}
|
210
242
|
} else if (node instanceof AST_Dot) {
|
@@ -217,11 +249,11 @@ function mangle_properties(ast, options) {
|
|
217
249
|
declared = !(root.thedef && root.thedef.undeclared);
|
218
250
|
}
|
219
251
|
if (declared &&
|
220
|
-
(!
|
252
|
+
(!keep_quoted || !node.quote)) {
|
221
253
|
add(node.property);
|
222
254
|
}
|
223
255
|
} else if (node instanceof AST_Sub) {
|
224
|
-
if (!
|
256
|
+
if (!keep_quoted) {
|
225
257
|
addStrings(node.property, add);
|
226
258
|
}
|
227
259
|
} else if (node instanceof AST_Call
|
@@ -237,25 +269,25 @@ function mangle_properties(ast, options) {
|
|
237
269
|
if (
|
238
270
|
node instanceof AST_ClassPrivateProperty
|
239
271
|
|| node instanceof AST_PrivateMethod
|
272
|
+
|| node instanceof AST_PrivateGetter
|
273
|
+
|| node instanceof AST_PrivateSetter
|
274
|
+
|| node instanceof AST_DotHash
|
240
275
|
) {
|
241
|
-
|
242
|
-
} else if (node instanceof AST_DotHash) {
|
243
|
-
node.property = mangle_private(node.property);
|
276
|
+
// handled by mangle_private_properties
|
244
277
|
} else if (node instanceof AST_ObjectKeyVal) {
|
245
|
-
if (typeof node.key == "string" &&
|
246
|
-
(!keep_quoted_strict || !node.quote)) {
|
278
|
+
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
|
247
279
|
node.key = mangle(node.key);
|
248
280
|
}
|
249
281
|
} else if (node instanceof AST_ObjectProperty) {
|
250
282
|
// setter, getter, method or class field
|
251
|
-
if (!
|
283
|
+
if (!keep_quoted || !node.quote) {
|
252
284
|
node.key.name = mangle(node.key.name);
|
253
285
|
}
|
254
286
|
} else if (node instanceof AST_Dot) {
|
255
|
-
if (!
|
287
|
+
if (!keep_quoted || !node.quote) {
|
256
288
|
node.property = mangle(node.property);
|
257
289
|
}
|
258
|
-
} else if (!
|
290
|
+
} else if (!keep_quoted && node instanceof AST_Sub) {
|
259
291
|
node.property = mangleStrings(node.property);
|
260
292
|
} else if (node instanceof AST_Call
|
261
293
|
&& node.expression.print_to_string() == "Object.defineProperty") {
|
@@ -312,7 +344,7 @@ function mangle_properties(ast, options) {
|
|
312
344
|
// either debug mode is off, or it is on and we could not use the mangled name
|
313
345
|
if (!mangled) {
|
314
346
|
do {
|
315
|
-
mangled =
|
347
|
+
mangled = nth_identifier.get(++cname);
|
316
348
|
} while (!can_mangle(mangled));
|
317
349
|
}
|
318
350
|
|
@@ -321,16 +353,6 @@ function mangle_properties(ast, options) {
|
|
321
353
|
return mangled;
|
322
354
|
}
|
323
355
|
|
324
|
-
function mangle_private(name) {
|
325
|
-
let mangled = private_cache.get(name);
|
326
|
-
if (!mangled) {
|
327
|
-
mangled = base54(++cprivate);
|
328
|
-
private_cache.set(name, mangled);
|
329
|
-
}
|
330
|
-
|
331
|
-
return mangled;
|
332
|
-
}
|
333
|
-
|
334
356
|
function mangleStrings(node) {
|
335
357
|
return node.transform(new TreeTransformer(function(node) {
|
336
358
|
if (node instanceof AST_Sequence) {
|
@@ -350,4 +372,5 @@ function mangle_properties(ast, options) {
|
|
350
372
|
export {
|
351
373
|
reserve_quoted_keys,
|
352
374
|
mangle_properties,
|
375
|
+
mangle_private_properties,
|
353
376
|
};
|
package/lib/scope.js
CHANGED
@@ -667,8 +667,9 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
|
667
667
|
|
668
668
|
function next_mangled(scope, options) {
|
669
669
|
var ext = scope.enclosed;
|
670
|
+
var nth_identifier = options.nth_identifier;
|
670
671
|
out: while (true) {
|
671
|
-
var m =
|
672
|
+
var m = nth_identifier.get(++scope.cname);
|
672
673
|
if (ALL_RESERVED_WORDS.has(m)) continue; // skip over "do"
|
673
674
|
|
674
675
|
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
@@ -744,6 +745,7 @@ AST_Symbol.DEFMETHOD("global", function() {
|
|
744
745
|
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
|
745
746
|
options = defaults(options, {
|
746
747
|
eval : false,
|
748
|
+
nth_identifier : base54,
|
747
749
|
ie8 : false,
|
748
750
|
keep_classnames: false,
|
749
751
|
keep_fnames : false,
|
@@ -765,6 +767,7 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
|
|
765
767
|
|
766
768
|
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
767
769
|
options = this._default_mangler_options(options);
|
770
|
+
var nth_identifier = options.nth_identifier;
|
768
771
|
|
769
772
|
// We only need to mangle declaration nodes. Special logic wired
|
770
773
|
// into the code generator will display the mangled name if it's
|
@@ -816,7 +819,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|
816
819
|
if (node instanceof AST_Label) {
|
817
820
|
let name;
|
818
821
|
do {
|
819
|
-
name =
|
822
|
+
name = nth_identifier.get(++lname);
|
820
823
|
} while (ALL_RESERVED_WORDS.has(name));
|
821
824
|
node.mangled_name = name;
|
822
825
|
return true;
|
@@ -878,9 +881,12 @@ AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
|
878
881
|
});
|
879
882
|
|
880
883
|
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
881
|
-
base54.reset();
|
882
|
-
base54.sort();
|
883
884
|
options = this._default_mangler_options(options);
|
885
|
+
var nth_identifier = options.nth_identifier;
|
886
|
+
if (nth_identifier.reset && nth_identifier.sort) {
|
887
|
+
nth_identifier.reset();
|
888
|
+
nth_identifier.sort();
|
889
|
+
}
|
884
890
|
var avoid = this.find_colliding_names(options);
|
885
891
|
var cname = 0;
|
886
892
|
this.globals.forEach(rename);
|
@@ -892,7 +898,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|
892
898
|
function next_name() {
|
893
899
|
var name;
|
894
900
|
do {
|
895
|
-
name =
|
901
|
+
name = nth_identifier.get(cname++);
|
896
902
|
} while (avoid.has(name) || ALL_RESERVED_WORDS.has(name));
|
897
903
|
return name;
|
898
904
|
}
|
@@ -919,30 +925,37 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
|
|
919
925
|
|
920
926
|
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
921
927
|
options = this._default_mangler_options(options);
|
928
|
+
var nth_identifier = options.nth_identifier;
|
929
|
+
if (!nth_identifier.reset || !nth_identifier.consider || !nth_identifier.sort) {
|
930
|
+
// If the identifier mangler is invariant, skip computing character frequency.
|
931
|
+
return;
|
932
|
+
}
|
933
|
+
nth_identifier.reset();
|
934
|
+
|
922
935
|
try {
|
923
936
|
AST_Node.prototype.print = function(stream, force_parens) {
|
924
937
|
this._print(stream, force_parens);
|
925
938
|
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
|
926
|
-
|
939
|
+
nth_identifier.consider(this.name, -1);
|
927
940
|
} else if (options.properties) {
|
928
941
|
if (this instanceof AST_DotHash) {
|
929
|
-
|
942
|
+
nth_identifier.consider("#" + this.property, -1);
|
930
943
|
} else if (this instanceof AST_Dot) {
|
931
|
-
|
944
|
+
nth_identifier.consider(this.property, -1);
|
932
945
|
} else if (this instanceof AST_Sub) {
|
933
946
|
skip_string(this.property);
|
934
947
|
}
|
935
948
|
}
|
936
949
|
};
|
937
|
-
|
950
|
+
nth_identifier.consider(this.print_to_string(), 1);
|
938
951
|
} finally {
|
939
952
|
AST_Node.prototype.print = AST_Node.prototype._print;
|
940
953
|
}
|
941
|
-
|
954
|
+
nth_identifier.sort();
|
942
955
|
|
943
956
|
function skip_string(node) {
|
944
957
|
if (node instanceof AST_String) {
|
945
|
-
|
958
|
+
nth_identifier.consider(node.value, -1);
|
946
959
|
} else if (node instanceof AST_Conditional) {
|
947
960
|
skip_string(node.consequent);
|
948
961
|
skip_string(node.alternative);
|
@@ -966,19 +979,20 @@ const base54 = (() => {
|
|
966
979
|
frequency.set(ch, 0);
|
967
980
|
});
|
968
981
|
}
|
969
|
-
|
982
|
+
function consider(str, delta) {
|
970
983
|
for (var i = str.length; --i >= 0;) {
|
971
984
|
frequency.set(str[i], frequency.get(str[i]) + delta);
|
972
985
|
}
|
973
|
-
}
|
986
|
+
}
|
974
987
|
function compare(a, b) {
|
975
988
|
return frequency.get(b) - frequency.get(a);
|
976
989
|
}
|
977
|
-
|
990
|
+
function sort() {
|
978
991
|
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
|
979
|
-
}
|
980
|
-
|
992
|
+
}
|
993
|
+
// Ensure this is in a usable initial state.
|
981
994
|
reset();
|
995
|
+
sort();
|
982
996
|
function base54(num) {
|
983
997
|
var ret = "", base = 54;
|
984
998
|
num++;
|
@@ -990,7 +1004,13 @@ const base54 = (() => {
|
|
990
1004
|
} while (num > 0);
|
991
1005
|
return ret;
|
992
1006
|
}
|
993
|
-
|
1007
|
+
|
1008
|
+
return {
|
1009
|
+
get: base54,
|
1010
|
+
consider,
|
1011
|
+
reset,
|
1012
|
+
sort
|
1013
|
+
};
|
994
1014
|
})();
|
995
1015
|
|
996
1016
|
export {
|
package/lib/transform.js
CHANGED
@@ -57,7 +57,6 @@ import {
|
|
57
57
|
AST_Definitions,
|
58
58
|
AST_Destructuring,
|
59
59
|
AST_Do,
|
60
|
-
AST_Dot,
|
61
60
|
AST_Exit,
|
62
61
|
AST_Expansion,
|
63
62
|
AST_Export,
|
@@ -74,6 +73,7 @@ import {
|
|
74
73
|
AST_Object,
|
75
74
|
AST_ObjectProperty,
|
76
75
|
AST_PrefixedTemplateString,
|
76
|
+
AST_PropAccess,
|
77
77
|
AST_Sequence,
|
78
78
|
AST_SimpleStatement,
|
79
79
|
AST_Sub,
|
@@ -228,7 +228,7 @@ def_transform(AST_Sequence, function(self, tw) {
|
|
228
228
|
: [new AST_Number({ value: 0 })];
|
229
229
|
});
|
230
230
|
|
231
|
-
def_transform(
|
231
|
+
def_transform(AST_PropAccess, function(self, tw) {
|
232
232
|
self.expression = self.expression.transform(tw);
|
233
233
|
});
|
234
234
|
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"homepage": "https://terser.org",
|
5
5
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
6
6
|
"license": "BSD-2-Clause",
|
7
|
-
"version": "5.
|
7
|
+
"version": "5.8.0",
|
8
8
|
"engines": {
|
9
9
|
"node": ">=10"
|
10
10
|
},
|
@@ -45,19 +45,19 @@
|
|
45
45
|
"dependencies": {
|
46
46
|
"commander": "^2.20.0",
|
47
47
|
"source-map": "~0.7.2",
|
48
|
-
"source-map-support": "~0.5.
|
48
|
+
"source-map-support": "~0.5.20"
|
49
49
|
},
|
50
50
|
"devDependencies": {
|
51
|
-
"@ls-lint/ls-lint": "^1.
|
52
|
-
"acorn": "^8.0
|
53
|
-
"astring": "^1.
|
54
|
-
"eslint": "^7.
|
55
|
-
"eslump": "^
|
51
|
+
"@ls-lint/ls-lint": "^1.10.0",
|
52
|
+
"acorn": "^8.5.0",
|
53
|
+
"astring": "^1.7.5",
|
54
|
+
"eslint": "^7.32.0",
|
55
|
+
"eslump": "^3.0.0",
|
56
56
|
"esm": "^3.2.25",
|
57
|
-
"mocha": "^
|
57
|
+
"mocha": "^9.1.1",
|
58
58
|
"pre-commit": "^1.2.2",
|
59
59
|
"rimraf": "^3.0.2",
|
60
|
-
"rollup": "2.
|
60
|
+
"rollup": "2.56.3",
|
61
61
|
"semver": "^7.3.4"
|
62
62
|
},
|
63
63
|
"scripts": {
|
package/tools/terser.d.ts
CHANGED
@@ -80,16 +80,52 @@ export interface MangleOptions {
|
|
80
80
|
keep_classnames?: boolean | RegExp;
|
81
81
|
keep_fnames?: boolean | RegExp;
|
82
82
|
module?: boolean;
|
83
|
+
nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler;
|
83
84
|
properties?: boolean | ManglePropertiesOptions;
|
84
85
|
reserved?: string[];
|
85
86
|
safari10?: boolean;
|
86
87
|
toplevel?: boolean;
|
87
88
|
}
|
88
89
|
|
90
|
+
/**
|
91
|
+
* An identifier mangler for which the output is invariant with respect to the source code.
|
92
|
+
*/
|
93
|
+
export interface SimpleIdentifierMangler {
|
94
|
+
/**
|
95
|
+
* Obtains the nth most favored (usually shortest) identifier to rename a variable to.
|
96
|
+
* The mangler will increment n and retry until the return value is not in use in scope, and is not a reserved word.
|
97
|
+
* This function is expected to be stable; Evaluating get(n) === get(n) should always return true.
|
98
|
+
* @param n The ordinal of the identifier.
|
99
|
+
*/
|
100
|
+
get(n: number): string;
|
101
|
+
}
|
102
|
+
|
103
|
+
/**
|
104
|
+
* An identifier mangler that leverages character frequency analysis to determine identifier precedence.
|
105
|
+
*/
|
106
|
+
export interface WeightedIdentifierMangler extends SimpleIdentifierMangler {
|
107
|
+
/**
|
108
|
+
* Modifies the internal weighting of the input characters by the specified delta.
|
109
|
+
* Will be invoked on the entire printed AST, and then deduct mangleable identifiers.
|
110
|
+
* @param chars The characters to modify the weighting of.
|
111
|
+
* @param delta The numeric weight to add to the characters.
|
112
|
+
*/
|
113
|
+
consider(chars: string, delta: number): number;
|
114
|
+
/**
|
115
|
+
* Resets character weights.
|
116
|
+
*/
|
117
|
+
reset(): void;
|
118
|
+
/**
|
119
|
+
* Sorts identifiers by character frequency, in preparation for calls to get(n).
|
120
|
+
*/
|
121
|
+
sort(): void;
|
122
|
+
}
|
123
|
+
|
89
124
|
export interface ManglePropertiesOptions {
|
90
125
|
builtins?: boolean;
|
91
126
|
debug?: boolean;
|
92
127
|
keep_quoted?: boolean | 'strict';
|
128
|
+
nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler;
|
93
129
|
regex?: RegExp | string;
|
94
130
|
reserved?: string[];
|
95
131
|
}
|