terser 5.7.1 → 5.10.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/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) {
@@ -158,6 +158,7 @@ import {
158
158
  AST_With,
159
159
  AST_Yield,
160
160
  } from "./ast.js";
161
+ import { is_basic_identifier_string } from "./parse.js";
161
162
 
162
163
  (function() {
163
164
 
@@ -179,6 +180,24 @@ import {
179
180
  return body;
180
181
  };
181
182
 
183
+ const assert_clause_from_moz = (assertions) => {
184
+ if (assertions && assertions.length > 0) {
185
+ return new AST_Object({
186
+ start: my_start_token(assertions),
187
+ end: my_end_token(assertions),
188
+ properties: assertions.map((assertion_kv) =>
189
+ new AST_ObjectKeyVal({
190
+ start: my_start_token(assertion_kv),
191
+ end: my_end_token(assertion_kv),
192
+ key: assertion_kv.key.name || assertion_kv.key.value,
193
+ value: from_moz(assertion_kv.value)
194
+ })
195
+ )
196
+ });
197
+ }
198
+ return null;
199
+ };
200
+
182
201
  var MOZ_TO_ME = {
183
202
  Program: function(M) {
184
203
  return new AST_Toplevel({
@@ -499,7 +518,8 @@ import {
499
518
  end : my_end_token(M),
500
519
  imported_name: imported_name,
501
520
  imported_names : imported_names,
502
- module_name : from_moz(M.source)
521
+ module_name : from_moz(M.source),
522
+ assert_clause: assert_clause_from_moz(M.assertions)
503
523
  });
504
524
  },
505
525
  ExportAllDeclaration: function(M) {
@@ -512,7 +532,8 @@ import {
512
532
  foreign_name: new AST_SymbolExportForeign({ name: "*" })
513
533
  })
514
534
  ],
515
- module_name: from_moz(M.source)
535
+ module_name: from_moz(M.source),
536
+ assert_clause: assert_clause_from_moz(M.assertions)
516
537
  });
517
538
  },
518
539
  ExportNamedDeclaration: function(M) {
@@ -526,7 +547,8 @@ import {
526
547
  name: from_moz(specifier.local)
527
548
  });
528
549
  }) : null,
529
- module_name: from_moz(M.source)
550
+ module_name: from_moz(M.source),
551
+ assert_clause: assert_clause_from_moz(M.assertions)
530
552
  });
531
553
  },
532
554
  ExportDefaultDeclaration: function(M) {
@@ -818,12 +840,30 @@ import {
818
840
  };
819
841
  });
820
842
 
843
+ const assert_clause_to_moz = assert_clause => {
844
+ const assertions = [];
845
+ if (assert_clause) {
846
+ for (const { key, value } of assert_clause.properties) {
847
+ const key_moz = is_basic_identifier_string(key)
848
+ ? { type: "Identifier", name: key }
849
+ : { type: "Literal", value: key, raw: JSON.stringify(key) };
850
+ assertions.push({
851
+ type: "ImportAttribute",
852
+ key: key_moz,
853
+ value: to_moz(value)
854
+ });
855
+ }
856
+ }
857
+ return assertions;
858
+ };
859
+
821
860
  def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
822
861
  if (M.exported_names) {
823
862
  if (M.exported_names[0].name.name === "*") {
824
863
  return {
825
864
  type: "ExportAllDeclaration",
826
- source: to_moz(M.module_name)
865
+ source: to_moz(M.module_name),
866
+ assertions: assert_clause_to_moz(M.assert_clause)
827
867
  };
828
868
  }
829
869
  return {
@@ -836,7 +876,8 @@ import {
836
876
  };
837
877
  }),
838
878
  declaration: to_moz(M.exported_definition),
839
- source: to_moz(M.module_name)
879
+ source: to_moz(M.module_name),
880
+ assertions: assert_clause_to_moz(M.assert_clause)
840
881
  };
841
882
  }
842
883
  return {
@@ -870,7 +911,8 @@ import {
870
911
  return {
871
912
  type: "ImportDeclaration",
872
913
  specifiers: specifiers,
873
- source: to_moz(M.module_name)
914
+ source: to_moz(M.module_name),
915
+ assertions: assert_clause_to_moz(M.assert_clause)
874
916
  };
875
917
  });
876
918
 
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]*$/;
@@ -176,6 +176,48 @@ function is_some_comments(comment) {
176
176
  );
177
177
  }
178
178
 
179
+ class Rope {
180
+ constructor() {
181
+ this.committed = "";
182
+ this.current = "";
183
+ }
184
+
185
+ append(str) {
186
+ this.current += str;
187
+ }
188
+
189
+ insertAt(char, index) {
190
+ const { committed, current } = this;
191
+ if (index < committed.length) {
192
+ this.committed = committed.slice(0, index) + char + committed.slice(index);
193
+ } else if (index === committed.length) {
194
+ this.committed += char;
195
+ } else {
196
+ index -= committed.length;
197
+ this.committed += current.slice(0, index) + char;
198
+ this.current = current.slice(index);
199
+ }
200
+ }
201
+
202
+ charAt(index) {
203
+ const { committed } = this;
204
+ if (index < committed.length) return committed[index];
205
+ return this.current[index - committed.length];
206
+ }
207
+
208
+ curLength() {
209
+ return this.current.length;
210
+ }
211
+
212
+ length() {
213
+ return this.committed.length + this.current.length;
214
+ }
215
+
216
+ toString() {
217
+ return this.committed + this.current;
218
+ }
219
+ }
220
+
179
221
  function OutputStream(options) {
180
222
 
181
223
  var readonly = !options;
@@ -240,7 +282,7 @@ function OutputStream(options) {
240
282
  var current_col = 0;
241
283
  var current_line = 1;
242
284
  var current_pos = 0;
243
- var OUTPUT = "";
285
+ var OUTPUT = new Rope();
244
286
  let printed_comments = new Set();
245
287
 
246
288
  var to_utf8 = options.ascii_only ? function(str, identifier) {
@@ -349,9 +391,11 @@ function OutputStream(options) {
349
391
  var do_add_mapping = mappings ? function() {
350
392
  mappings.forEach(function(mapping) {
351
393
  try {
352
- let name = !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name;
353
- if (name instanceof AST_Symbol) {
354
- name = name.name;
394
+ let { name, token } = mapping;
395
+ if (token.type == "name" || token.type === "privatename") {
396
+ name = token.value;
397
+ } else if (name instanceof AST_Symbol) {
398
+ name = token.type === "string" ? token.value : name.name;
355
399
  }
356
400
  options.source_map.add(
357
401
  mapping.token.file,
@@ -369,19 +413,18 @@ function OutputStream(options) {
369
413
  var ensure_line_len = options.max_line_len ? function() {
370
414
  if (current_col > options.max_line_len) {
371
415
  if (might_add_newline) {
372
- var left = OUTPUT.slice(0, might_add_newline);
373
- var right = OUTPUT.slice(might_add_newline);
416
+ OUTPUT.insertAt("\n", might_add_newline);
417
+ const curLength = OUTPUT.curLength();
374
418
  if (mappings) {
375
- var delta = right.length - current_col;
419
+ var delta = curLength - current_col;
376
420
  mappings.forEach(function(mapping) {
377
421
  mapping.line++;
378
422
  mapping.col += delta;
379
423
  });
380
424
  }
381
- OUTPUT = left + "\n" + right;
382
425
  current_line++;
383
426
  current_pos++;
384
- current_col = right.length;
427
+ current_col = curLength;
385
428
  }
386
429
  }
387
430
  if (might_add_newline) {
@@ -415,13 +458,13 @@ function OutputStream(options) {
415
458
 
416
459
  if (prev === ":" && ch === "}" || (!ch || !";}".includes(ch)) && prev !== ";") {
417
460
  if (options.semicolons || requireSemicolonChars.has(ch)) {
418
- OUTPUT += ";";
461
+ OUTPUT.append(";");
419
462
  current_col++;
420
463
  current_pos++;
421
464
  } else {
422
465
  ensure_line_len();
423
466
  if (current_col > 0) {
424
- OUTPUT += "\n";
467
+ OUTPUT.append("\n");
425
468
  current_pos++;
426
469
  current_line++;
427
470
  current_col = 0;
@@ -445,7 +488,7 @@ function OutputStream(options) {
445
488
  || (ch == "/" && ch == prev)
446
489
  || ((ch == "+" || ch == "-") && ch == last)
447
490
  ) {
448
- OUTPUT += " ";
491
+ OUTPUT.append(" ");
449
492
  current_col++;
450
493
  current_pos++;
451
494
  }
@@ -463,7 +506,7 @@ function OutputStream(options) {
463
506
  if (!might_add_newline) do_add_mapping();
464
507
  }
465
508
 
466
- OUTPUT += str;
509
+ OUTPUT.append(str);
467
510
  has_parens = str[str.length - 1] == "(";
468
511
  current_pos += str.length;
469
512
  var a = str.split(/\r?\n/), n = a.length - 1;
@@ -503,15 +546,15 @@ function OutputStream(options) {
503
546
 
504
547
  var newline = options.beautify ? function() {
505
548
  if (newline_insert < 0) return print("\n");
506
- if (OUTPUT[newline_insert] != "\n") {
507
- OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
549
+ if (OUTPUT.charAt(newline_insert) != "\n") {
550
+ OUTPUT.insertAt("\n", newline_insert);
508
551
  current_pos++;
509
552
  current_line++;
510
553
  }
511
554
  newline_insert++;
512
555
  } : options.max_line_len ? function() {
513
556
  ensure_line_len();
514
- might_add_newline = OUTPUT.length;
557
+ might_add_newline = OUTPUT.length();
515
558
  } : noop;
516
559
 
517
560
  var semicolon = options.beautify ? function() {
@@ -577,13 +620,14 @@ function OutputStream(options) {
577
620
  if (might_add_newline) {
578
621
  ensure_line_len();
579
622
  }
580
- return OUTPUT;
623
+ return OUTPUT.toString();
581
624
  }
582
625
 
583
626
  function has_nlb() {
584
- let n = OUTPUT.length - 1;
627
+ const output = OUTPUT.toString();
628
+ let n = output.length - 1;
585
629
  while (n >= 0) {
586
- const code = OUTPUT.charCodeAt(n);
630
+ const code = output.charCodeAt(n);
587
631
  if (code === CODE_LINE_BREAK) {
588
632
  return true;
589
633
  }
@@ -720,7 +764,7 @@ function OutputStream(options) {
720
764
  !/comment[134]/.test(c.type)
721
765
  ))) return;
722
766
  printed_comments.add(comments);
723
- var insert = OUTPUT.length;
767
+ var insert = OUTPUT.length();
724
768
  comments.filter(comment_filter, node).forEach(function(c, i) {
725
769
  if (printed_comments.has(c)) return;
726
770
  printed_comments.add(c);
@@ -749,7 +793,7 @@ function OutputStream(options) {
749
793
  need_space = true;
750
794
  }
751
795
  });
752
- if (OUTPUT.length > insert) newline_insert = insert;
796
+ if (OUTPUT.length() > insert) newline_insert = insert;
753
797
  }
754
798
 
755
799
  var stack = [];
@@ -779,7 +823,7 @@ function OutputStream(options) {
779
823
  var encoded = encode_string(str, quote);
780
824
  if (escape_directive === true && !encoded.includes("\\")) {
781
825
  // Insert semicolons to break directive prologue
782
- if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
826
+ if (!EXPECT_DIRECTIVE.test(OUTPUT.toString())) {
783
827
  force_semicolon();
784
828
  }
785
829
  force_semicolon();
@@ -1635,6 +1679,10 @@ function OutputStream(options) {
1635
1679
  output.space();
1636
1680
  }
1637
1681
  self.module_name.print(output);
1682
+ if (self.assert_clause) {
1683
+ output.print("assert");
1684
+ self.assert_clause.print(output);
1685
+ }
1638
1686
  output.semicolon();
1639
1687
  });
1640
1688
  DEFPRINT(AST_ImportMeta, function(self, output) {
@@ -1700,6 +1748,10 @@ function OutputStream(options) {
1700
1748
  output.space();
1701
1749
  self.module_name.print(output);
1702
1750
  }
1751
+ if (self.assert_clause) {
1752
+ output.print("assert");
1753
+ self.assert_clause.print(output);
1754
+ }
1703
1755
  if (self.exported_value
1704
1756
  && !(self.exported_value instanceof AST_Defun ||
1705
1757
  self.exported_value instanceof AST_Function ||
@@ -1717,7 +1769,11 @@ function OutputStream(options) {
1717
1769
  // https://github.com/mishoo/UglifyJS2/issues/60
1718
1770
  if (noin) {
1719
1771
  parens = walk(node, node => {
1720
- if (node instanceof AST_Scope) return true;
1772
+ // Don't go into scopes -- except arrow functions:
1773
+ // https://github.com/terser/terser/issues/1019#issuecomment-877642607
1774
+ if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
1775
+ return true;
1776
+ }
1721
1777
  if (node instanceof AST_Binary && node.operator == "in") {
1722
1778
  return walk_abort; // makes walk() return true
1723
1779
  }
@@ -1787,7 +1843,7 @@ function OutputStream(options) {
1787
1843
  var expr = self.expression;
1788
1844
  expr.print(output);
1789
1845
  var prop = self.property;
1790
- var print_computed = RESERVED_WORDS.has(prop)
1846
+ var print_computed = ALL_RESERVED_WORDS.has(prop)
1791
1847
  ? output.option("ie8")
1792
1848
  : !is_identifier_string(
1793
1849
  prop,
@@ -1820,6 +1876,7 @@ function OutputStream(options) {
1820
1876
 
1821
1877
  if (self.optional) output.print("?");
1822
1878
  output.print(".#");
1879
+ output.add_mapping(self.end);
1823
1880
  output.print_name(prop);
1824
1881
  });
1825
1882
  DEFPRINT(AST_Sub, function(self, output) {
@@ -1968,7 +2025,7 @@ function OutputStream(options) {
1968
2025
  }
1969
2026
  return output.print(make_num(key));
1970
2027
  }
1971
- var print_string = RESERVED_WORDS.has(key)
2028
+ var print_string = ALL_RESERVED_WORDS.has(key)
1972
2029
  ? output.option("ie8")
1973
2030
  : (
1974
2031
  output.option("ecma") < 2015 || output.option("safari10")
@@ -1995,7 +2052,7 @@ function OutputStream(options) {
1995
2052
  output.option("ecma") >= 2015 || output.option("safari10")
1996
2053
  ) &&
1997
2054
  get_name(self.value) === self.key &&
1998
- !RESERVED_WORDS.has(self.key)
2055
+ !ALL_RESERVED_WORDS.has(self.key)
1999
2056
  ) {
2000
2057
  print_property_name(self.key, self.quote, output);
2001
2058
 
@@ -2273,8 +2330,10 @@ function OutputStream(options) {
2273
2330
  DEFMAP([
2274
2331
  AST_ObjectGetter,
2275
2332
  AST_ObjectSetter,
2333
+ AST_PrivateGetter,
2334
+ AST_PrivateSetter,
2276
2335
  ], function(output) {
2277
- output.add_mapping(this.start, this.key.name);
2336
+ output.add_mapping(this.key.end, this.key.name);
2278
2337
  });
2279
2338
 
2280
2339
  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
 
@@ -1220,7 +1222,7 @@ function parse($TEXT, options) {
1220
1222
  }
1221
1223
  if (S.token.value == "import" && !is_token(peek(), "punc", "(") && !is_token(peek(), "punc", ".")) {
1222
1224
  next();
1223
- var node = import_();
1225
+ var node = import_statement();
1224
1226
  semicolon();
1225
1227
  return node;
1226
1228
  }
@@ -1372,7 +1374,7 @@ function parse($TEXT, options) {
1372
1374
  case "export":
1373
1375
  if (!is_token(peek(), "punc", "(")) {
1374
1376
  next();
1375
- var node = export_();
1377
+ var node = export_statement();
1376
1378
  if (is("punc", ";")) semicolon();
1377
1379
  return node;
1378
1380
  }
@@ -2549,7 +2551,7 @@ function parse($TEXT, options) {
2549
2551
  };
2550
2552
 
2551
2553
  const is_not_method_start = () =>
2552
- !is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("operator", "=");
2554
+ !is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("punc", ";") && !is("operator", "=");
2553
2555
 
2554
2556
  var is_async = false;
2555
2557
  var is_static = false;
@@ -2664,7 +2666,15 @@ function parse($TEXT, options) {
2664
2666
  }
2665
2667
  }
2666
2668
 
2667
- function import_() {
2669
+ function maybe_import_assertion() {
2670
+ if (is("name", "assert") && !has_newline_before(S.token)) {
2671
+ next();
2672
+ return object_or_destructuring_();
2673
+ }
2674
+ return null;
2675
+ }
2676
+
2677
+ function import_statement() {
2668
2678
  var start = prev();
2669
2679
 
2670
2680
  var imported_name;
@@ -2687,16 +2697,20 @@ function parse($TEXT, options) {
2687
2697
  unexpected();
2688
2698
  }
2689
2699
  next();
2700
+
2701
+ const assert_clause = maybe_import_assertion();
2702
+
2690
2703
  return new AST_Import({
2691
- start: start,
2692
- imported_name: imported_name,
2693
- imported_names: imported_names,
2704
+ start,
2705
+ imported_name,
2706
+ imported_names,
2694
2707
  module_name: new AST_String({
2695
2708
  start: mod_str,
2696
2709
  value: mod_str.value,
2697
2710
  quote: mod_str.quote,
2698
2711
  end: mod_str,
2699
2712
  }),
2713
+ assert_clause,
2700
2714
  end: S.token,
2701
2715
  });
2702
2716
  }
@@ -2804,7 +2818,7 @@ function parse($TEXT, options) {
2804
2818
  return names;
2805
2819
  }
2806
2820
 
2807
- function export_() {
2821
+ function export_statement() {
2808
2822
  var start = S.token;
2809
2823
  var is_default;
2810
2824
  var exported_names;
@@ -2822,6 +2836,8 @@ function parse($TEXT, options) {
2822
2836
  }
2823
2837
  next();
2824
2838
 
2839
+ const assert_clause = maybe_import_assertion();
2840
+
2825
2841
  return new AST_Export({
2826
2842
  start: start,
2827
2843
  is_default: is_default,
@@ -2833,6 +2849,7 @@ function parse($TEXT, options) {
2833
2849
  end: mod_str,
2834
2850
  }),
2835
2851
  end: prev(),
2852
+ assert_clause
2836
2853
  });
2837
2854
  } else {
2838
2855
  return new AST_Export({
@@ -2878,6 +2895,7 @@ function parse($TEXT, options) {
2878
2895
  exported_value: exported_value,
2879
2896
  exported_definition: exported_definition,
2880
2897
  end: prev(),
2898
+ assert_clause: null
2881
2899
  });
2882
2900
  }
2883
2901
 
@@ -3339,6 +3357,6 @@ export {
3339
3357
  JS_Parse_Error,
3340
3358
  parse,
3341
3359
  PRECEDENCE,
3342
- RESERVED_WORDS,
3360
+ ALL_RESERVED_WORDS,
3343
3361
  tokenizer,
3344
3362
  };