terser 5.0.0 → 5.3.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/output.js CHANGED
@@ -65,6 +65,7 @@ import {
65
65
  AST_Call,
66
66
  AST_Case,
67
67
  AST_Catch,
68
+ AST_Chain,
68
69
  AST_Class,
69
70
  AST_ClassExpression,
70
71
  AST_ClassProperty,
@@ -94,6 +95,7 @@ import {
94
95
  AST_Hole,
95
96
  AST_If,
96
97
  AST_Import,
98
+ AST_ImportMeta,
97
99
  AST_Jump,
98
100
  AST_LabeledStatement,
99
101
  AST_Lambda,
@@ -894,8 +896,8 @@ function OutputStream(options) {
894
896
  return p instanceof AST_PropAccess && p.expression === this;
895
897
  });
896
898
 
897
- // same goes for an object literal, because otherwise it would be
898
- // interpreted as a block of code.
899
+ // same goes for an object literal (as in AST_Function), because
900
+ // otherwise {...} would be interpreted as a block of code.
899
901
  PARENS(AST_Object, function(output) {
900
902
  return !output.has_parens() && first_in_statement(output);
901
903
  });
@@ -1411,6 +1413,8 @@ function OutputStream(options) {
1411
1413
  || e instanceof AST_PropAccess
1412
1414
  || e instanceof AST_Unary
1413
1415
  || e instanceof AST_Constant
1416
+ || e instanceof AST_Await
1417
+ || e instanceof AST_Object
1414
1418
  );
1415
1419
  if (parens) output.print("(");
1416
1420
  self.expression.print(output);
@@ -1608,6 +1612,9 @@ function OutputStream(options) {
1608
1612
  self.module_name.print(output);
1609
1613
  output.semicolon();
1610
1614
  });
1615
+ DEFPRINT(AST_ImportMeta, function(self, output) {
1616
+ output.print("import.meta");
1617
+ });
1611
1618
 
1612
1619
  DEFPRINT(AST_NameMapping, function(self, output) {
1613
1620
  var is_import = output.parent() instanceof AST_Import;
@@ -1714,6 +1721,7 @@ function OutputStream(options) {
1714
1721
  if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
1715
1722
  output.add_mapping(self.start);
1716
1723
  }
1724
+ if (self.optional) output.print("?.");
1717
1725
  output.with_parens(function() {
1718
1726
  self.args.forEach(function(expr, i) {
1719
1727
  if (i) output.comma();
@@ -1757,6 +1765,9 @@ function OutputStream(options) {
1757
1765
  var print_computed = RESERVED_WORDS.has(prop)
1758
1766
  ? output.option("ie8")
1759
1767
  : !is_identifier_string(prop, output.option("ecma") >= 2015);
1768
+
1769
+ if (self.optional) output.print("?.");
1770
+
1760
1771
  if (print_computed) {
1761
1772
  output.print("[");
1762
1773
  output.add_mapping(self.end);
@@ -1768,7 +1779,7 @@ function OutputStream(options) {
1768
1779
  output.print(".");
1769
1780
  }
1770
1781
  }
1771
- output.print(".");
1782
+ if (!self.optional) output.print(".");
1772
1783
  // the name after dot would be mapped about here.
1773
1784
  output.add_mapping(self.end);
1774
1785
  output.print_name(prop);
@@ -1776,10 +1787,14 @@ function OutputStream(options) {
1776
1787
  });
1777
1788
  DEFPRINT(AST_Sub, function(self, output) {
1778
1789
  self.expression.print(output);
1790
+ if (self.optional) output.print("?.");
1779
1791
  output.print("[");
1780
1792
  self.property.print(output);
1781
1793
  output.print("]");
1782
1794
  });
1795
+ DEFPRINT(AST_Chain, function(self, output) {
1796
+ self.expression.print(output);
1797
+ });
1783
1798
  DEFPRINT(AST_UnaryPrefix, function(self, output) {
1784
1799
  var op = self.operator;
1785
1800
  output.print(op);
package/lib/parse.js CHANGED
@@ -63,6 +63,7 @@ import {
63
63
  AST_Call,
64
64
  AST_Case,
65
65
  AST_Catch,
66
+ AST_Chain,
66
67
  AST_ClassExpression,
67
68
  AST_ClassProperty,
68
69
  AST_ConciseMethod,
@@ -91,6 +92,7 @@ import {
91
92
  AST_Hole,
92
93
  AST_If,
93
94
  AST_Import,
95
+ AST_ImportMeta,
94
96
  AST_IterationStatement,
95
97
  AST_Label,
96
98
  AST_LabeledStatement,
@@ -396,6 +398,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
396
398
 
397
399
  function peek() { return get_full_char(S.text, S.pos); }
398
400
 
401
+ // Used because parsing ?. involves a lookahead for a digit
402
+ function is_option_chain_op() {
403
+ const must_be_dot = S.text.charCodeAt(S.pos + 1) === 46;
404
+ if (!must_be_dot) return false;
405
+
406
+ const cannot_be_digit = S.text.charCodeAt(S.pos + 2);
407
+ return cannot_be_digit < 48 || cannot_be_digit > 57;
408
+ }
409
+
399
410
  function next(signal_eof, in_string) {
400
411
  var ch = get_full_char(S.text, S.pos++);
401
412
  if (signal_eof && !ch)
@@ -456,7 +467,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
456
467
  (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION.has(value)) ||
457
468
  (type == "punc" && PUNC_BEFORE_EXPRESSION.has(value))) ||
458
469
  (type == "arrow");
459
- if (type == "punc" && value == ".") {
470
+ if (type == "punc" && (value == "." || value == "?.")) {
460
471
  prev_was_dot = true;
461
472
  } else if (!is_comment) {
462
473
  prev_was_dot = false;
@@ -892,6 +903,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
892
903
  return tok;
893
904
  }
894
905
  case 61: return handle_eq_sign();
906
+ case 63: {
907
+ if (!is_option_chain_op()) break; // Handled below
908
+
909
+ next(); // ?
910
+ next(); // .
911
+
912
+ return token("punc", "?.");
913
+ }
895
914
  case 96: return read_template_characters(true);
896
915
  case 123:
897
916
  S.brace_counter++;
@@ -1010,7 +1029,7 @@ function parse($TEXT, options) {
1010
1029
 
1011
1030
  options = defaults(options, {
1012
1031
  bare_returns : false,
1013
- ecma : 2017,
1032
+ ecma : null, // Legacy
1014
1033
  expression : false,
1015
1034
  filename : null,
1016
1035
  html5_comments : true,
@@ -1118,7 +1137,7 @@ function parse($TEXT, options) {
1118
1137
  }
1119
1138
 
1120
1139
  function embed_tokens(parser) {
1121
- return function(...args) {
1140
+ return function _embed_tokens_wrapper(...args) {
1122
1141
  const start = S.token;
1123
1142
  const expr = parser(...args);
1124
1143
  expr.start = start;
@@ -1134,7 +1153,7 @@ function parse($TEXT, options) {
1134
1153
  }
1135
1154
  }
1136
1155
 
1137
- var statement = embed_tokens(function(is_export_default, is_for_body, is_if_body) {
1156
+ var statement = embed_tokens(function statement(is_export_default, is_for_body, is_if_body) {
1138
1157
  handle_regexp();
1139
1158
  switch (S.token.type) {
1140
1159
  case "string":
@@ -1169,7 +1188,7 @@ function parse($TEXT, options) {
1169
1188
  }
1170
1189
  return function_(AST_Defun, false, true, is_export_default);
1171
1190
  }
1172
- if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
1191
+ if (S.token.value == "import" && !is_token(peek(), "punc", "(") && !is_token(peek(), "punc", ".")) {
1173
1192
  next();
1174
1193
  var node = import_();
1175
1194
  semicolon();
@@ -1590,7 +1609,6 @@ function parse($TEXT, options) {
1590
1609
 
1591
1610
  if (!is("punc", ")")) {
1592
1611
  expect(",");
1593
- if (is("punc", ")") && options.ecma < 2017) unexpected();
1594
1612
  }
1595
1613
 
1596
1614
  if (param instanceof AST_Expansion) {
@@ -1835,7 +1853,6 @@ function parse($TEXT, options) {
1835
1853
  if (!is("punc", ")")) {
1836
1854
  expect(",");
1837
1855
  if (is("punc", ")")) {
1838
- if (options.ecma < 2017) unexpected();
1839
1856
  trailing_comma = prev();
1840
1857
  if (maybe_sequence) invalid_sequence = trailing_comma;
1841
1858
  }
@@ -2104,7 +2121,7 @@ function parse($TEXT, options) {
2104
2121
  var newexp = expr_atom(false), args;
2105
2122
  if (is("punc", "(")) {
2106
2123
  next();
2107
- args = expr_list(")", options.ecma >= 2017);
2124
+ args = expr_list(")", true);
2108
2125
  } else {
2109
2126
  args = [];
2110
2127
  }
@@ -2217,6 +2234,9 @@ function parse($TEXT, options) {
2217
2234
  if (is("operator", "new")) {
2218
2235
  return new_(allow_calls);
2219
2236
  }
2237
+ if (is("operator", "import")) {
2238
+ return import_meta();
2239
+ }
2220
2240
  var start = S.token;
2221
2241
  var peeked;
2222
2242
  var async = is("name", "async")
@@ -2594,6 +2614,7 @@ function parse($TEXT, options) {
2594
2614
 
2595
2615
  function import_() {
2596
2616
  var start = prev();
2617
+
2597
2618
  var imported_name;
2598
2619
  var imported_names;
2599
2620
  if (is("name")) {
@@ -2628,6 +2649,17 @@ function parse($TEXT, options) {
2628
2649
  });
2629
2650
  }
2630
2651
 
2652
+ function import_meta() {
2653
+ var start = S.token;
2654
+ expect_token("operator", "import");
2655
+ expect_token("punc", ".");
2656
+ expect_token("name", "meta");
2657
+ return subscripts(new AST_ImportMeta({
2658
+ start: start,
2659
+ end: prev()
2660
+ }), false);
2661
+ }
2662
+
2631
2663
  function map_name(is_import) {
2632
2664
  function make_symbol(type) {
2633
2665
  return new type({
@@ -2889,16 +2921,17 @@ function parse($TEXT, options) {
2889
2921
  }
2890
2922
  }
2891
2923
 
2892
- var subscripts = function(expr, allow_calls) {
2924
+ var subscripts = function(expr, allow_calls, is_chain) {
2893
2925
  var start = expr.start;
2894
2926
  if (is("punc", ".")) {
2895
2927
  next();
2896
2928
  return subscripts(new AST_Dot({
2897
2929
  start : start,
2898
2930
  expression : expr,
2931
+ optional : false,
2899
2932
  property : as_name(),
2900
2933
  end : prev()
2901
- }), allow_calls);
2934
+ }), allow_calls, is_chain);
2902
2935
  }
2903
2936
  if (is("punc", "[")) {
2904
2937
  next();
@@ -2907,22 +2940,80 @@ function parse($TEXT, options) {
2907
2940
  return subscripts(new AST_Sub({
2908
2941
  start : start,
2909
2942
  expression : expr,
2943
+ optional : false,
2910
2944
  property : prop,
2911
2945
  end : prev()
2912
- }), allow_calls);
2946
+ }), allow_calls, is_chain);
2913
2947
  }
2914
2948
  if (allow_calls && is("punc", "(")) {
2915
2949
  next();
2916
2950
  var call = new AST_Call({
2917
2951
  start : start,
2918
2952
  expression : expr,
2953
+ optional : false,
2919
2954
  args : call_args(),
2920
2955
  end : prev()
2921
2956
  });
2922
2957
  annotate(call);
2923
- return subscripts(call, true);
2958
+ return subscripts(call, true, is_chain);
2924
2959
  }
2960
+
2961
+ if (is("punc", "?.")) {
2962
+ next();
2963
+
2964
+ let chain_contents;
2965
+
2966
+ if (allow_calls && is("punc", "(")) {
2967
+ next();
2968
+
2969
+ const call = new AST_Call({
2970
+ start,
2971
+ optional: true,
2972
+ expression: expr,
2973
+ args: call_args(),
2974
+ end: prev()
2975
+ });
2976
+ annotate(call);
2977
+
2978
+ chain_contents = subscripts(call, true, true);
2979
+ } else if (is("name")) {
2980
+ chain_contents = subscripts(new AST_Dot({
2981
+ start,
2982
+ expression: expr,
2983
+ optional: true,
2984
+ property: as_name(),
2985
+ end: prev()
2986
+ }), allow_calls, true);
2987
+ } else if (is("punc", "[")) {
2988
+ next();
2989
+ const property = expression(true);
2990
+ expect("]");
2991
+ chain_contents = subscripts(new AST_Sub({
2992
+ start,
2993
+ expression: expr,
2994
+ optional: true,
2995
+ property,
2996
+ end: prev()
2997
+ }), allow_calls, true);
2998
+ }
2999
+
3000
+ if (!chain_contents) unexpected();
3001
+
3002
+ if (chain_contents instanceof AST_Chain) return chain_contents;
3003
+
3004
+ return new AST_Chain({
3005
+ start,
3006
+ expression: chain_contents,
3007
+ end: prev()
3008
+ });
3009
+ }
3010
+
2925
3011
  if (is("template_head")) {
3012
+ if (is_chain) {
3013
+ // a?.b`c` is a syntax error
3014
+ unexpected();
3015
+ }
3016
+
2926
3017
  return subscripts(new AST_PrefixedTemplateString({
2927
3018
  start: start,
2928
3019
  prefix: expr,
@@ -2930,6 +3021,7 @@ function parse($TEXT, options) {
2930
3021
  end: prev()
2931
3022
  }), allow_calls);
2932
3023
  }
3024
+
2933
3025
  return expr;
2934
3026
  };
2935
3027
 
@@ -2948,7 +3040,6 @@ function parse($TEXT, options) {
2948
3040
  }
2949
3041
  if (!is("punc", ")")) {
2950
3042
  expect(",");
2951
- if (is("punc", ")") && options.ecma < 2017) unexpected();
2952
3043
  }
2953
3044
  }
2954
3045
  next();
@@ -3152,13 +3243,14 @@ function parse($TEXT, options) {
3152
3243
  return expression(true);
3153
3244
  }
3154
3245
 
3155
- return (function() {
3246
+ return (function parse_toplevel() {
3156
3247
  var start = S.token;
3157
3248
  var body = [];
3158
3249
  S.input.push_directives_stack();
3159
3250
  if (options.module) S.input.add_directive("use strict");
3160
- while (!is("eof"))
3251
+ while (!is("eof")) {
3161
3252
  body.push(statement());
3253
+ }
3162
3254
  S.input.pop_directives_stack();
3163
3255
  var end = prev();
3164
3256
  var toplevel = options.toplevel;
package/lib/size.js CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  AST_Hole,
33
33
  AST_If,
34
34
  AST_Import,
35
+ AST_ImportMeta,
35
36
  AST_Infinity,
36
37
  AST_LabeledStatement,
37
38
  AST_Let,
@@ -81,7 +82,7 @@ import { first_in_statement } from "./utils/first_in_statement.js";
81
82
 
82
83
  let mangle_options = undefined;
83
84
  AST_Node.prototype.size = function (compressor, stack) {
84
- mangle_options = undefined; // TODO get mangle_options somehow
85
+ mangle_options = compressor && compressor.mangle_options;
85
86
 
86
87
  let size = 0;
87
88
  walk_parent(this, (node, info) => {
@@ -257,6 +258,8 @@ AST_Import.prototype._size = function () {
257
258
  return size;
258
259
  };
259
260
 
261
+ AST_ImportMeta.prototype._size = () => 11;
262
+
260
263
  AST_Export.prototype._size = function () {
261
264
  let size = 7 + (this.is_default ? 8 : 0);
262
265
 
@@ -278,6 +281,9 @@ AST_Export.prototype._size = function () {
278
281
  };
279
282
 
280
283
  AST_Call.prototype._size = function () {
284
+ if (this.optional) {
285
+ return 4 + list_overhead(this.args);
286
+ }
281
287
  return 2 + list_overhead(this.args);
282
288
  };
283
289
 
@@ -290,10 +296,15 @@ AST_Sequence.prototype._size = function () {
290
296
  };
291
297
 
292
298
  AST_Dot.prototype._size = function () {
299
+ if (this.optional) {
300
+ return this.property.length + 2;
301
+ }
293
302
  return this.property.length + 1;
294
303
  };
295
304
 
296
- AST_Sub.prototype._size = () => 2;
305
+ AST_Sub.prototype._size = function () {
306
+ return this.optional ? 4 : 2;
307
+ };
297
308
 
298
309
  AST_Unary.prototype._size = function () {
299
310
  if (this.operator === "typeof") return 7;
@@ -376,7 +387,7 @@ AST_ClassProperty.prototype._size = function () {
376
387
  AST_Symbol.prototype._size = function () {
377
388
  return !mangle_options || this.definition().unmangleable(mangle_options)
378
389
  ? this.name.length
379
- : 2;
390
+ : 1;
380
391
  };
381
392
 
382
393
  // TODO take propmangle into account
@@ -391,7 +402,7 @@ AST_SymbolRef.prototype._size = AST_SymbolDeclaration.prototype._size = function
391
402
 
392
403
  if (name === "arguments") return 9;
393
404
 
394
- return 2;
405
+ return AST_Symbol.prototype._size.call(this);
395
406
  };
396
407
 
397
408
  AST_NewTarget.prototype._size = () => 10;
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.0.0",
7
+ "version": "5.3.0",
8
8
  "engines": {
9
9
  "node": ">=6.0.0"
10
10
  },
@@ -14,6 +14,7 @@
14
14
  "repository": "https://github.com/terser/terser",
15
15
  "main": "dist/bundle.min.js",
16
16
  "type": "module",
17
+ "module": "./main.js",
17
18
  "exports": {
18
19
  ".": {
19
20
  "import": "./main.js",
@@ -48,7 +49,7 @@
48
49
  },
49
50
  "devDependencies": {
50
51
  "@ls-lint/ls-lint": "^1.9.2",
51
- "acorn": "^7.1.1",
52
+ "acorn": "^7.4.0",
52
53
  "astring": "^1.4.1",
53
54
  "eslint": "^7.0.0",
54
55
  "eslump": "^2.0.0",