terser 5.7.0 → 5.9.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.
@@ -18,6 +18,7 @@ import {
18
18
  AST_Directive,
19
19
  AST_Do,
20
20
  AST_Dot,
21
+ AST_DotHash,
21
22
  AST_EmptyStatement,
22
23
  AST_Expansion,
23
24
  AST_Export,
@@ -233,6 +234,10 @@ AST_Dot.prototype.shallow_cmp = mkshallow({
233
234
  property: "eq"
234
235
  });
235
236
 
237
+ AST_DotHash.prototype.shallow_cmp = mkshallow({
238
+ property: "eq"
239
+ });
240
+
236
241
  AST_Unary.prototype.shallow_cmp = mkshallow({
237
242
  operator: "eq"
238
243
  });
package/lib/minify.js CHANGED
@@ -15,6 +15,7 @@ import { base54 } from "./scope.js";
15
15
  import { SourceMap } from "./sourcemap.js";
16
16
  import {
17
17
  mangle_properties,
18
+ mangle_private_properties,
18
19
  reserve_quoted_keys,
19
20
  } from "./propmangle.js";
20
21
 
@@ -113,6 +114,7 @@ async function minify(files, options) {
113
114
  keep_classnames: false,
114
115
  keep_fnames: false,
115
116
  module: false,
117
+ nth_identifier: base54,
116
118
  properties: false,
117
119
  reserved: [],
118
120
  safari10: false,
@@ -203,9 +205,9 @@ async function minify(files, options) {
203
205
  if (options.mangle) toplevel.figure_out_scope(options.mangle);
204
206
  if (timings) timings.mangle = Date.now();
205
207
  if (options.mangle) {
206
- base54.reset();
207
208
  toplevel.compute_char_frequency(options.mangle);
208
209
  toplevel.mangle_names(options.mangle);
210
+ toplevel = mangle_private_properties(toplevel, options.mangle);
209
211
  }
210
212
  if (timings) timings.properties = Date.now();
211
213
  if (options.mangle && options.mangle.properties) {
package/lib/output.js CHANGED
@@ -159,7 +159,7 @@ import {
159
159
  is_basic_identifier_string,
160
160
  is_identifier_string,
161
161
  PRECEDENCE,
162
- RESERVED_WORDS,
162
+ ALL_RESERVED_WORDS,
163
163
  } from "./parse.js";
164
164
 
165
165
  const EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
@@ -349,11 +349,17 @@ function OutputStream(options) {
349
349
  var do_add_mapping = mappings ? function() {
350
350
  mappings.forEach(function(mapping) {
351
351
  try {
352
+ let { name, token } = mapping;
353
+ if (token.type == "name" || token.type === "privatename") {
354
+ name = token.value;
355
+ } else if (name instanceof AST_Symbol) {
356
+ name = token.type === "string" ? token.value : name.name;
357
+ }
352
358
  options.source_map.add(
353
359
  mapping.token.file,
354
360
  mapping.line, mapping.col,
355
361
  mapping.token.line, mapping.token.col,
356
- !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
362
+ is_basic_identifier_string(name) ? name : undefined
357
363
  );
358
364
  } catch(ex) {
359
365
  // Ignore bad mapping
@@ -1713,7 +1719,11 @@ function OutputStream(options) {
1713
1719
  // https://github.com/mishoo/UglifyJS2/issues/60
1714
1720
  if (noin) {
1715
1721
  parens = walk(node, node => {
1716
- if (node instanceof AST_Scope) return true;
1722
+ // Don't go into scopes -- except arrow functions:
1723
+ // https://github.com/terser/terser/issues/1019#issuecomment-877642607
1724
+ if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
1725
+ return true;
1726
+ }
1717
1727
  if (node instanceof AST_Binary && node.operator == "in") {
1718
1728
  return walk_abort; // makes walk() return true
1719
1729
  }
@@ -1783,7 +1793,7 @@ function OutputStream(options) {
1783
1793
  var expr = self.expression;
1784
1794
  expr.print(output);
1785
1795
  var prop = self.property;
1786
- var print_computed = RESERVED_WORDS.has(prop)
1796
+ var print_computed = ALL_RESERVED_WORDS.has(prop)
1787
1797
  ? output.option("ie8")
1788
1798
  : !is_identifier_string(
1789
1799
  prop,
@@ -1816,6 +1826,7 @@ function OutputStream(options) {
1816
1826
 
1817
1827
  if (self.optional) output.print("?");
1818
1828
  output.print(".#");
1829
+ output.add_mapping(self.end);
1819
1830
  output.print_name(prop);
1820
1831
  });
1821
1832
  DEFPRINT(AST_Sub, function(self, output) {
@@ -1964,7 +1975,7 @@ function OutputStream(options) {
1964
1975
  }
1965
1976
  return output.print(make_num(key));
1966
1977
  }
1967
- var print_string = RESERVED_WORDS.has(key)
1978
+ var print_string = ALL_RESERVED_WORDS.has(key)
1968
1979
  ? output.option("ie8")
1969
1980
  : (
1970
1981
  output.option("ecma") < 2015 || output.option("safari10")
@@ -1991,7 +2002,7 @@ function OutputStream(options) {
1991
2002
  output.option("ecma") >= 2015 || output.option("safari10")
1992
2003
  ) &&
1993
2004
  get_name(self.value) === self.key &&
1994
- !RESERVED_WORDS.has(self.key)
2005
+ !ALL_RESERVED_WORDS.has(self.key)
1995
2006
  ) {
1996
2007
  print_property_name(self.key, self.quote, output);
1997
2008
 
@@ -2269,8 +2280,10 @@ function OutputStream(options) {
2269
2280
  DEFMAP([
2270
2281
  AST_ObjectGetter,
2271
2282
  AST_ObjectSetter,
2283
+ AST_PrivateGetter,
2284
+ AST_PrivateSetter,
2272
2285
  ], function(output) {
2273
- output.add_mapping(this.start, this.key.name);
2286
+ output.add_mapping(this.key.end, this.key.name);
2274
2287
  });
2275
2288
 
2276
2289
  DEFMAP([ AST_ObjectProperty ], function(output) {
package/lib/parse.js CHANGED
@@ -166,13 +166,15 @@ var LATEST_TEMPLATE_END = true;
166
166
 
167
167
  var KEYWORDS = "break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with";
168
168
  var KEYWORDS_ATOM = "false null true";
169
- var RESERVED_WORDS = "enum implements import interface package private protected public static super this " + KEYWORDS_ATOM + " " + KEYWORDS;
169
+ var RESERVED_WORDS = "enum import super this " + KEYWORDS_ATOM + " " + KEYWORDS;
170
+ var ALL_RESERVED_WORDS = "implements interface package private protected public static " + RESERVED_WORDS;
170
171
  var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case yield await";
171
172
 
172
173
  KEYWORDS = makePredicate(KEYWORDS);
173
174
  RESERVED_WORDS = makePredicate(RESERVED_WORDS);
174
175
  KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
175
176
  KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
177
+ ALL_RESERVED_WORDS = makePredicate(ALL_RESERVED_WORDS);
176
178
 
177
179
  var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
178
180
 
@@ -3339,6 +3341,6 @@ export {
3339
3341
  JS_Parse_Error,
3340
3342
  parse,
3341
3343
  PRECEDENCE,
3342
- RESERVED_WORDS,
3344
+ ALL_RESERVED_WORDS,
3343
3345
  tokenizer,
3344
3346
  };
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,33 +142,61 @@ 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
- cache.forEach(function(mangled_name) {
168
- reserved.add(mangled_name);
169
- });
170
200
  } else {
171
201
  cache = new Map();
172
202
  }
@@ -184,27 +214,29 @@ function mangle_properties(ast, options) {
184
214
 
185
215
  var names_to_mangle = new Set();
186
216
  var unmangleable = new Set();
187
- var private_properties = new Set();
217
+ // Track each already-mangled name to prevent nth_identifier from generating
218
+ // the same name.
219
+ cache.forEach((mangled_name) => unmangleable.add(mangled_name));
188
220
 
189
- var keep_quoted_strict = options.keep_quoted === "strict";
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
- private_properties.add(node.key.name);
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 (!keep_quoted_strict || !node.key.end.quote) {
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
- (!keep_quoted_strict || !node.quote)) {
252
+ (!keep_quoted || !node.quote)) {
221
253
  add(node.property);
222
254
  }
223
255
  } else if (node instanceof AST_Sub) {
224
- if (!keep_quoted_strict) {
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
- node.key.name = mangle_private(node.key.name);
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 (!keep_quoted_strict || !node.key.end.quote) {
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 (!keep_quoted_strict || !node.quote) {
287
+ if (!keep_quoted || !node.quote) {
256
288
  node.property = mangle(node.property);
257
289
  }
258
- } else if (!options.keep_quoted && node instanceof AST_Sub) {
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 = base54(++cname);
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
@@ -107,7 +107,7 @@ import {
107
107
  walk
108
108
  } from "./ast.js";
109
109
  import {
110
- RESERVED_WORDS,
110
+ ALL_RESERVED_WORDS,
111
111
  js_error,
112
112
  } from "./parse.js";
113
113
 
@@ -299,7 +299,14 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
299
299
  // scope when we encounter the AST_Defun node (which is
300
300
  // instanceof AST_Scope) but we get to the symbol a bit
301
301
  // later.
302
- mark_export((node.scope = defun.parent_scope.get_defun_scope()).def_function(node, defun), 1);
302
+ const closest_scope = defun.parent_scope;
303
+
304
+ // In strict mode, function definitions are block-scoped
305
+ node.scope = tw.directives["use strict"]
306
+ ? closest_scope
307
+ : closest_scope.get_defun_scope();
308
+
309
+ mark_export(node.scope.def_function(node, defun), 1);
303
310
  } else if (node instanceof AST_SymbolClass) {
304
311
  mark_export(defun.def_variable(node, defun), 1);
305
312
  } else if (node instanceof AST_SymbolImport) {
@@ -478,7 +485,6 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
478
485
 
479
486
  AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
480
487
  this.variables = new Map(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
481
- this.functions = new Map(); // map name to AST_SymbolDefun (functions defined in this scope)
482
488
  this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
483
489
  this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
484
490
  this.parent_scope = parent_scope; // the parent scope
@@ -641,7 +647,6 @@ AST_Scope.DEFMETHOD("find_variable", function(name) {
641
647
  AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
642
648
  var def = this.def_variable(symbol, init);
643
649
  if (!def.init || def.init instanceof AST_Defun) def.init = init;
644
- this.functions.set(symbol.name, def);
645
650
  return def;
646
651
  });
647
652
 
@@ -662,9 +667,10 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
662
667
 
663
668
  function next_mangled(scope, options) {
664
669
  var ext = scope.enclosed;
670
+ var nth_identifier = options.nth_identifier;
665
671
  out: while (true) {
666
- var m = base54(++scope.cname);
667
- if (RESERVED_WORDS.has(m)) continue; // skip over "do"
672
+ var m = nth_identifier.get(++scope.cname);
673
+ if (ALL_RESERVED_WORDS.has(m)) continue; // skip over "do"
668
674
 
669
675
  // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
670
676
  // shadow a name reserved from mangling.
@@ -739,6 +745,7 @@ AST_Symbol.DEFMETHOD("global", function() {
739
745
  AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
740
746
  options = defaults(options, {
741
747
  eval : false,
748
+ nth_identifier : base54,
742
749
  ie8 : false,
743
750
  keep_classnames: false,
744
751
  keep_fnames : false,
@@ -760,6 +767,7 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
760
767
 
761
768
  AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
762
769
  options = this._default_mangler_options(options);
770
+ var nth_identifier = options.nth_identifier;
763
771
 
764
772
  // We only need to mangle declaration nodes. Special logic wired
765
773
  // into the code generator will display the mangled name if it's
@@ -811,8 +819,8 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
811
819
  if (node instanceof AST_Label) {
812
820
  let name;
813
821
  do {
814
- name = base54(++lname);
815
- } while (RESERVED_WORDS.has(name));
822
+ name = nth_identifier.get(++lname);
823
+ } while (ALL_RESERVED_WORDS.has(name));
816
824
  node.mangled_name = name;
817
825
  return true;
818
826
  }
@@ -873,9 +881,12 @@ AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
873
881
  });
874
882
 
875
883
  AST_Toplevel.DEFMETHOD("expand_names", function(options) {
876
- base54.reset();
877
- base54.sort();
878
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
+ }
879
890
  var avoid = this.find_colliding_names(options);
880
891
  var cname = 0;
881
892
  this.globals.forEach(rename);
@@ -887,8 +898,8 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
887
898
  function next_name() {
888
899
  var name;
889
900
  do {
890
- name = base54(cname++);
891
- } while (avoid.has(name) || RESERVED_WORDS.has(name));
901
+ name = nth_identifier.get(cname++);
902
+ } while (avoid.has(name) || ALL_RESERVED_WORDS.has(name));
892
903
  return name;
893
904
  }
894
905
 
@@ -914,30 +925,37 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
914
925
 
915
926
  AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
916
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
+
917
935
  try {
918
936
  AST_Node.prototype.print = function(stream, force_parens) {
919
937
  this._print(stream, force_parens);
920
938
  if (this instanceof AST_Symbol && !this.unmangleable(options)) {
921
- base54.consider(this.name, -1);
939
+ nth_identifier.consider(this.name, -1);
922
940
  } else if (options.properties) {
923
941
  if (this instanceof AST_DotHash) {
924
- base54.consider("#" + this.property, -1);
942
+ nth_identifier.consider("#" + this.property, -1);
925
943
  } else if (this instanceof AST_Dot) {
926
- base54.consider(this.property, -1);
944
+ nth_identifier.consider(this.property, -1);
927
945
  } else if (this instanceof AST_Sub) {
928
946
  skip_string(this.property);
929
947
  }
930
948
  }
931
949
  };
932
- base54.consider(this.print_to_string(), 1);
950
+ nth_identifier.consider(this.print_to_string(), 1);
933
951
  } finally {
934
952
  AST_Node.prototype.print = AST_Node.prototype._print;
935
953
  }
936
- base54.sort();
954
+ nth_identifier.sort();
937
955
 
938
956
  function skip_string(node) {
939
957
  if (node instanceof AST_String) {
940
- base54.consider(node.value, -1);
958
+ nth_identifier.consider(node.value, -1);
941
959
  } else if (node instanceof AST_Conditional) {
942
960
  skip_string(node.consequent);
943
961
  skip_string(node.alternative);
@@ -961,19 +979,20 @@ const base54 = (() => {
961
979
  frequency.set(ch, 0);
962
980
  });
963
981
  }
964
- base54.consider = function(str, delta) {
982
+ function consider(str, delta) {
965
983
  for (var i = str.length; --i >= 0;) {
966
984
  frequency.set(str[i], frequency.get(str[i]) + delta);
967
985
  }
968
- };
986
+ }
969
987
  function compare(a, b) {
970
988
  return frequency.get(b) - frequency.get(a);
971
989
  }
972
- base54.sort = function() {
990
+ function sort() {
973
991
  chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
974
- };
975
- base54.reset = reset;
992
+ }
993
+ // Ensure this is in a usable initial state.
976
994
  reset();
995
+ sort();
977
996
  function base54(num) {
978
997
  var ret = "", base = 54;
979
998
  num++;
@@ -985,7 +1004,13 @@ const base54 = (() => {
985
1004
  } while (num > 0);
986
1005
  return ret;
987
1006
  }
988
- return base54;
1007
+
1008
+ return {
1009
+ get: base54,
1010
+ consider,
1011
+ reset,
1012
+ sort
1013
+ };
989
1014
  })();
990
1015
 
991
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(AST_Dot, function(self, tw) {
231
+ def_transform(AST_PropAccess, function(self, tw) {
232
232
  self.expression = self.expression.transform(tw);
233
233
  });
234
234
 
@@ -64,10 +64,8 @@ class DefaultsError extends Error {
64
64
  function defaults(args, defs, croak) {
65
65
  if (args === true) {
66
66
  args = {};
67
- }
68
-
69
- if (args != null && typeof args === "object") {
70
- args = Object.assign({}, args);
67
+ } else if (args != null && typeof args === "object") {
68
+ args = {...args};
71
69
  }
72
70
 
73
71
  const ret = args || {};
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.0",
7
+ "version": "5.9.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.19"
48
+ "source-map-support": "~0.5.20"
49
49
  },
50
50
  "devDependencies": {
51
- "@ls-lint/ls-lint": "^1.9.2",
52
- "acorn": "^8.0.5",
53
- "astring": "^1.6.2",
54
- "eslint": "^7.19.0",
55
- "eslump": "^2.0.0",
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": "^8.2.1",
57
+ "mocha": "^9.1.1",
58
58
  "pre-commit": "^1.2.2",
59
59
  "rimraf": "^3.0.2",
60
- "rollup": "2.38.4",
60
+ "rollup": "2.56.3",
61
61
  "semver": "^7.3.4"
62
62
  },
63
63
  "scripts": {
@@ -93,7 +93,7 @@
93
93
  "eslintConfig": {
94
94
  "parserOptions": {
95
95
  "sourceType": "module",
96
- "ecmaVersion": "2020"
96
+ "ecmaVersion": 2020
97
97
  },
98
98
  "env": {
99
99
  "node": true,
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
  }
@@ -138,6 +174,7 @@ export enum OutputQuoteStyle {
138
174
  export interface MinifyOptions {
139
175
  compress?: boolean | CompressOptions;
140
176
  ecma?: ECMA;
177
+ enclose?: boolean | string;
141
178
  ie8?: boolean;
142
179
  keep_classnames?: boolean | RegExp;
143
180
  keep_fnames?: boolean | RegExp;