terser 5.15.1 → 5.16.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.16.1
4
+
5
+ - Disallow private fields in object bodies (#1011)
6
+ - Parse `#privatefield in object` (#1279)
7
+ - Compress `#privatefield in object`
8
+
3
9
  ## v5.15.1
4
10
 
5
11
  - Fixed missing parentheses around optional chains
package/PATRONS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Our patrons
2
2
 
3
- These are the first-tier patrons from [Patreon](https://www.patreon.com/fabiosantoscode). My appreciation goes to everyone on this list for supporting the project!
3
+ These are the first-tier patrons from Patreon (notice: **The Terser Patreon is shutting down in favor of opencollective**). My appreciation goes to everyone on this list for supporting the project!
4
4
 
5
5
  * 38elements
6
6
  * Alan Orozco
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  A JavaScript mangler/compressor toolkit for ES6+.
9
9
 
10
- *note*: You can support this project on patreon: <a target="_blank" rel="nofollow" href="https://www.patreon.com/fabiosantoscode"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="patron" width="100px" height="auto"></a>. Check out [PATRONS.md](https://github.com/terser/terser/blob/master/PATRONS.md) for our first-tier patrons.
10
+ *note*: <s>You can support this project on patreon: [link]</s> **The Terser Patreon is shutting down in favor of opencollective**. Check out [PATRONS.md](https://github.com/terser/terser/blob/master/PATRONS.md) for our first-tier patrons.
11
11
 
12
12
  Terser recommends you use RollupJS to bundle your modules, as that produces smaller code overall.
13
13
 
@@ -1336,7 +1336,7 @@ If you're not sure how to set an environment variable on your shell (the above e
1336
1336
 
1337
1337
  # README.md Patrons:
1338
1338
 
1339
- *note*: You can support this project on patreon: <a target="_blank" rel="nofollow" href="https://www.patreon.com/fabiosantoscode"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="patron" width="100px" height="auto"></a>. Check out [PATRONS.md](https://github.com/terser/terser/blob/master/PATRONS.md) for our first-tier patrons.
1339
+ *note*: <s>You can support this project on patreon: [link]</s> **The Terser Patreon is shutting down in favor of opencollective**. Check out [PATRONS.md](https://github.com/terser/terser/blob/master/PATRONS.md) for our first-tier patrons.
1340
1340
 
1341
1341
  These are the second-tier patrons. Great thanks for your support!
1342
1342
 
@@ -1209,7 +1209,7 @@ var PRECEDENCE = (function(a, ret) {
1209
1209
  {}
1210
1210
  );
1211
1211
 
1212
- var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "big_int", "string", "regexp", "name" ]);
1212
+ var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "big_int", "string", "regexp", "name"]);
1213
1213
 
1214
1214
  /* -----[ Parser ]----- */
1215
1215
 
@@ -1381,6 +1381,10 @@ function parse($TEXT, options) {
1381
1381
  return simple_statement();
1382
1382
 
1383
1383
  case "name":
1384
+ case "privatename":
1385
+ if(is("privatename") && !S.in_class)
1386
+ croak("Private field must be used in an enclosing class");
1387
+
1384
1388
  if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
1385
1389
  next();
1386
1390
  next();
@@ -2525,6 +2529,29 @@ function parse($TEXT, options) {
2525
2529
  if (is("template_head")) {
2526
2530
  return subscripts(template_string(), allow_calls);
2527
2531
  }
2532
+ if (is("privatename")) {
2533
+ if(!S.in_class) {
2534
+ croak("Private field must be used in an enclosing class");
2535
+ }
2536
+
2537
+ const start = S.token;
2538
+ const key = new AST_SymbolPrivateProperty({
2539
+ start,
2540
+ name: start.value,
2541
+ end: start
2542
+ });
2543
+ next();
2544
+ expect_token("operator", "in");
2545
+
2546
+ const private_in = new AST_PrivateIn({
2547
+ start,
2548
+ key,
2549
+ value: subscripts(as_atom_node(), allow_calls),
2550
+ end: prev()
2551
+ });
2552
+
2553
+ return subscripts(private_in, allow_calls);
2554
+ }
2528
2555
  if (ATOMIC_START_TOKEN.has(S.token.type)) {
2529
2556
  return subscripts(as_atom_node(), allow_calls);
2530
2557
  }
@@ -2610,7 +2637,9 @@ function parse($TEXT, options) {
2610
2637
  }));
2611
2638
  continue;
2612
2639
  }
2613
-
2640
+ if(is("privatename")) {
2641
+ croak("private fields are not allowed in an object");
2642
+ }
2614
2643
  var name = as_property_name();
2615
2644
  var value;
2616
2645
 
@@ -2684,7 +2713,8 @@ function parse($TEXT, options) {
2684
2713
  }
2685
2714
 
2686
2715
  expect("{");
2687
-
2716
+ // mark in class feild,
2717
+ S.in_class = true;
2688
2718
  while (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
2689
2719
  while (!is("punc", "}")) {
2690
2720
  start = S.token;
@@ -2693,6 +2723,8 @@ function parse($TEXT, options) {
2693
2723
  a.push(method);
2694
2724
  while (is("punc", ";")) { next(); }
2695
2725
  }
2726
+ // mark in class feild,
2727
+ S.in_class = false;
2696
2728
 
2697
2729
  S.input.pop_directives_stack();
2698
2730
 
@@ -3199,6 +3231,8 @@ function parse($TEXT, options) {
3199
3231
  var start = expr.start;
3200
3232
  if (is("punc", ".")) {
3201
3233
  next();
3234
+ if(is("privatename") && !S.in_class)
3235
+ croak("Private field must be used in an enclosing class");
3202
3236
  const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3203
3237
  return subscripts(new AST_DotVariant({
3204
3238
  start : start,
@@ -3252,6 +3286,8 @@ function parse($TEXT, options) {
3252
3286
 
3253
3287
  chain_contents = subscripts(call, true, true);
3254
3288
  } else if (is("name") || is("privatename")) {
3289
+ if(is("privatename") && !S.in_class)
3290
+ croak("Private field must be used in an enclosing class");
3255
3291
  const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3256
3292
  chain_contents = subscripts(new AST_DotVariant({
3257
3293
  start,
@@ -3297,7 +3333,6 @@ function parse($TEXT, options) {
3297
3333
  end: prev()
3298
3334
  }), allow_calls);
3299
3335
  }
3300
-
3301
3336
  return expr;
3302
3337
  };
3303
3338
 
@@ -5785,6 +5820,29 @@ var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", function AST_
5785
5820
  $documentation: "A class property for a private property",
5786
5821
  }, AST_ClassProperty);
5787
5822
 
5823
+ var AST_PrivateIn = DEFNODE("PrivateIn", "key value", function AST_PrivateIn(props) {
5824
+ if (props) {
5825
+ this.key = props.key;
5826
+ this.value = props.value;
5827
+ this.start = props.start;
5828
+ this.end = props.end;
5829
+ }
5830
+
5831
+ this.flags = 0;
5832
+ }, {
5833
+ $documentation: "An `in` binop when the key is private, eg #x in this",
5834
+ _walk: function(visitor) {
5835
+ return visitor._visit(this, function() {
5836
+ this.key._walk(visitor);
5837
+ this.value._walk(visitor);
5838
+ });
5839
+ },
5840
+ _children_backwards(push) {
5841
+ push(this.value);
5842
+ push(this.key);
5843
+ },
5844
+ });
5845
+
5788
5846
  var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
5789
5847
  if (props) {
5790
5848
  this.name = props.name;
@@ -6188,6 +6246,20 @@ var AST_LabelRef = DEFNODE("LabelRef", null, function AST_LabelRef(props) {
6188
6246
  $documentation: "Reference to a label symbol",
6189
6247
  }, AST_Symbol);
6190
6248
 
6249
+ var AST_SymbolPrivateProperty = DEFNODE("SymbolPrivateProperty", null, function AST_SymbolPrivateProperty(props) {
6250
+ if (props) {
6251
+ this.scope = props.scope;
6252
+ this.name = props.name;
6253
+ this.thedef = props.thedef;
6254
+ this.start = props.start;
6255
+ this.end = props.end;
6256
+ }
6257
+
6258
+ this.flags = 0;
6259
+ }, {
6260
+ $documentation: "A symbol that refers to a private property",
6261
+ }, AST_Symbol);
6262
+
6191
6263
  var AST_This = DEFNODE("This", null, function AST_This(props) {
6192
6264
  if (props) {
6193
6265
  this.scope = props.scope;
@@ -6818,6 +6890,11 @@ def_transform(AST_Binary, function(self, tw) {
6818
6890
  self.right = self.right.transform(tw);
6819
6891
  });
6820
6892
 
6893
+ def_transform(AST_PrivateIn, function(self, tw) {
6894
+ self.key = self.key.transform(tw);
6895
+ self.value = self.value.transform(tw);
6896
+ });
6897
+
6821
6898
  def_transform(AST_Conditional, function(self, tw) {
6822
6899
  self.condition = self.condition.transform(tw);
6823
6900
  self.consequent = self.consequent.transform(tw);
@@ -7195,7 +7272,9 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7195
7272
  if (M.computed) {
7196
7273
  key = from_moz(M.key);
7197
7274
  } else {
7198
- if (M.key.type !== "Identifier") throw new Error("Non-Identifier key in PropertyDefinition");
7275
+ if (M.key.type !== "Identifier" && M.key.type !== "PrivateIdentifier") {
7276
+ throw new Error("Non-Identifier key in PropertyDefinition");
7277
+ }
7199
7278
  key = from_moz(M.key);
7200
7279
  }
7201
7280
 
@@ -7630,6 +7709,18 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7630
7709
  },
7631
7710
 
7632
7711
  BinaryExpression: function(M) {
7712
+ if (M.left.type === "PrivateIdentifier") {
7713
+ return new AST_PrivateIn({
7714
+ start: my_start_token(M),
7715
+ end: my_end_token(M),
7716
+ key: new AST_SymbolPrivateProperty({
7717
+ start: my_start_token(M.left),
7718
+ end: my_end_token(M.left),
7719
+ name: M.left.name
7720
+ }),
7721
+ value: from_moz(M.right),
7722
+ });
7723
+ }
7633
7724
  return new AST_Binary({
7634
7725
  start: my_start_token(M),
7635
7726
  end: my_end_token(M),
@@ -8214,6 +8305,15 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8214
8305
  };
8215
8306
  });
8216
8307
 
8308
+ def_to_moz(AST_PrivateIn, function To_Moz_BinaryExpression_PrivateIn(M) {
8309
+ return {
8310
+ type: "BinaryExpression",
8311
+ left: { type: "PrivateIdentifier", name: M.key.name },
8312
+ operator: "in",
8313
+ right: to_moz(M.value),
8314
+ };
8315
+ });
8316
+
8217
8317
  def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
8218
8318
  return {
8219
8319
  type: "ArrayExpression",
@@ -10261,7 +10361,10 @@ function OutputStream(options) {
10261
10361
  if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
10262
10362
  return true;
10263
10363
  }
10264
- if (node instanceof AST_Binary && node.operator == "in") {
10364
+ if (
10365
+ node instanceof AST_Binary && node.operator == "in"
10366
+ || node instanceof AST_PrivateIn
10367
+ ) {
10265
10368
  return walk_abort; // makes walk() return true
10266
10369
  }
10267
10370
  });
@@ -10650,6 +10753,16 @@ function OutputStream(options) {
10650
10753
  }
10651
10754
  self._print_getter_setter(type, true, output);
10652
10755
  });
10756
+ DEFPRINT(AST_PrivateIn, function(self, output) {
10757
+ self.key.print(output);
10758
+ output.space();
10759
+ output.print("in");
10760
+ output.space();
10761
+ self.value.print(output);
10762
+ });
10763
+ DEFPRINT(AST_SymbolPrivateProperty, function(self, output) {
10764
+ output.print("#" + self.name);
10765
+ });
10653
10766
  DEFPRINT(AST_ConciseMethod, function(self, output) {
10654
10767
  var type;
10655
10768
  if (self.is_generator && self.async) {
@@ -12332,6 +12445,10 @@ AST_PrivateGetter.prototype._size = AST_PrivateSetter.prototype._size = function
12332
12445
  return AST_ConciseMethod.prototype._size.call(this) + 4;
12333
12446
  };
12334
12447
 
12448
+ AST_PrivateIn.prototype._size = function () {
12449
+ return 5; // "#", and " in "
12450
+ };
12451
+
12335
12452
  AST_Class.prototype._size = function () {
12336
12453
  return (
12337
12454
  (this.name ? 8 : 7)
@@ -18931,16 +19048,6 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
18931
19048
  right : def.value
18932
19049
  }));
18933
19050
  if (reduce_vars) name.definition().fixed = false;
18934
- } else if (def.value) {
18935
- // Because it's a destructuring, do not turn into an assignment.
18936
- var varDef = make_node(AST_VarDef, def, {
18937
- name: def.name,
18938
- value: def.value
18939
- });
18940
- var var_ = make_node(AST_Var, def, {
18941
- definitions: [ varDef ]
18942
- });
18943
- assignments.push(var_);
18944
19051
  }
18945
19052
  const thedef = def.name.definition();
18946
19053
  thedef.eliminated++;
@@ -18952,8 +19059,9 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
18952
19059
  });
18953
19060
 
18954
19061
  def_optimize(AST_Definitions, function(self) {
18955
- if (self.definitions.length == 0)
19062
+ if (self.definitions.length == 0) {
18956
19063
  return make_node(AST_EmptyStatement, self);
19064
+ }
18957
19065
  return self;
18958
19066
  });
18959
19067
 
@@ -29168,6 +29276,7 @@ function mangle_private_properties(ast, options) {
29168
29276
  || node instanceof AST_PrivateMethod
29169
29277
  || node instanceof AST_PrivateGetter
29170
29278
  || node instanceof AST_PrivateSetter
29279
+ || node instanceof AST_PrivateIn
29171
29280
  ) {
29172
29281
  node.key.name = mangle_private(node.key.name);
29173
29282
  } else if (node instanceof AST_DotHash) {
package/lib/ast.js CHANGED
@@ -2250,6 +2250,29 @@ var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", function AST_
2250
2250
  $documentation: "A class property for a private property",
2251
2251
  }, AST_ClassProperty);
2252
2252
 
2253
+ var AST_PrivateIn = DEFNODE("PrivateIn", "key value", function AST_PrivateIn(props) {
2254
+ if (props) {
2255
+ this.key = props.key;
2256
+ this.value = props.value;
2257
+ this.start = props.start;
2258
+ this.end = props.end;
2259
+ }
2260
+
2261
+ this.flags = 0;
2262
+ }, {
2263
+ $documentation: "An `in` binop when the key is private, eg #x in this",
2264
+ _walk: function(visitor) {
2265
+ return visitor._visit(this, function() {
2266
+ this.key._walk(visitor);
2267
+ this.value._walk(visitor);
2268
+ });
2269
+ },
2270
+ _children_backwards(push) {
2271
+ push(this.value);
2272
+ push(this.key);
2273
+ },
2274
+ });
2275
+
2253
2276
  var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
2254
2277
  if (props) {
2255
2278
  this.name = props.name;
@@ -2653,6 +2676,20 @@ var AST_LabelRef = DEFNODE("LabelRef", null, function AST_LabelRef(props) {
2653
2676
  $documentation: "Reference to a label symbol",
2654
2677
  }, AST_Symbol);
2655
2678
 
2679
+ var AST_SymbolPrivateProperty = DEFNODE("SymbolPrivateProperty", null, function AST_SymbolPrivateProperty(props) {
2680
+ if (props) {
2681
+ this.scope = props.scope;
2682
+ this.name = props.name;
2683
+ this.thedef = props.thedef;
2684
+ this.start = props.start;
2685
+ this.end = props.end;
2686
+ }
2687
+
2688
+ this.flags = 0;
2689
+ }, {
2690
+ $documentation: "A symbol that refers to a private property",
2691
+ }, AST_Symbol);
2692
+
2656
2693
  var AST_This = DEFNODE("This", null, function AST_This(props) {
2657
2694
  if (props) {
2658
2695
  this.scope = props.scope;
@@ -3093,6 +3130,7 @@ export {
3093
3130
  AST_Class,
3094
3131
  AST_ClassExpression,
3095
3132
  AST_ClassPrivateProperty,
3133
+ AST_PrivateIn,
3096
3134
  AST_ClassProperty,
3097
3135
  AST_ClassStaticBlock,
3098
3136
  AST_ConciseMethod,
@@ -3185,6 +3223,7 @@ export {
3185
3223
  AST_SymbolVar,
3186
3224
  AST_TemplateSegment,
3187
3225
  AST_TemplateString,
3226
+ AST_SymbolPrivateProperty,
3188
3227
  AST_This,
3189
3228
  AST_Throw,
3190
3229
  AST_Token,
@@ -1965,16 +1965,6 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1965
1965
  right : def.value
1966
1966
  }));
1967
1967
  if (reduce_vars) name.definition().fixed = false;
1968
- } else if (def.value) {
1969
- // Because it's a destructuring, do not turn into an assignment.
1970
- var varDef = make_node(AST_VarDef, def, {
1971
- name: def.name,
1972
- value: def.value
1973
- });
1974
- var var_ = make_node(AST_Var, def, {
1975
- definitions: [ varDef ]
1976
- });
1977
- assignments.push(var_);
1978
1968
  }
1979
1969
  const thedef = def.name.definition();
1980
1970
  thedef.eliminated++;
@@ -1986,8 +1976,9 @@ AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1986
1976
  });
1987
1977
 
1988
1978
  def_optimize(AST_Definitions, function(self) {
1989
- if (self.definitions.length == 0)
1979
+ if (self.definitions.length == 0) {
1990
1980
  return make_node(AST_EmptyStatement, self);
1981
+ }
1991
1982
  return self;
1992
1983
  });
1993
1984
 
@@ -113,6 +113,7 @@ import {
113
113
  AST_PrivateGetter,
114
114
  AST_PrivateMethod,
115
115
  AST_PrivateSetter,
116
+ AST_PrivateIn,
116
117
  AST_PropAccess,
117
118
  AST_RegExp,
118
119
  AST_Return,
@@ -128,6 +129,7 @@ import {
128
129
  AST_SymbolCatch,
129
130
  AST_SymbolClass,
130
131
  AST_SymbolClassProperty,
132
+ AST_SymbolPrivateProperty,
131
133
  AST_SymbolConst,
132
134
  AST_SymbolDefClass,
133
135
  AST_SymbolDefun,
@@ -432,7 +434,9 @@ import { is_basic_identifier_string } from "./parse.js";
432
434
  if (M.computed) {
433
435
  key = from_moz(M.key);
434
436
  } else {
435
- if (M.key.type !== "Identifier") throw new Error("Non-Identifier key in PropertyDefinition");
437
+ if (M.key.type !== "Identifier" && M.key.type !== "PrivateIdentifier") {
438
+ throw new Error("Non-Identifier key in PropertyDefinition");
439
+ }
436
440
  key = from_moz(M.key);
437
441
  }
438
442
 
@@ -867,6 +871,18 @@ import { is_basic_identifier_string } from "./parse.js";
867
871
  },
868
872
 
869
873
  BinaryExpression: function(M) {
874
+ if (M.left.type === "PrivateIdentifier") {
875
+ return new AST_PrivateIn({
876
+ start: my_start_token(M),
877
+ end: my_end_token(M),
878
+ key: new AST_SymbolPrivateProperty({
879
+ start: my_start_token(M.left),
880
+ end: my_end_token(M.left),
881
+ name: M.left.name
882
+ }),
883
+ value: from_moz(M.right),
884
+ });
885
+ }
870
886
  return new AST_Binary({
871
887
  start: my_start_token(M),
872
888
  end: my_end_token(M),
@@ -1451,6 +1467,15 @@ import { is_basic_identifier_string } from "./parse.js";
1451
1467
  };
1452
1468
  });
1453
1469
 
1470
+ def_to_moz(AST_PrivateIn, function To_Moz_BinaryExpression_PrivateIn(M) {
1471
+ return {
1472
+ type: "BinaryExpression",
1473
+ left: { type: "PrivateIdentifier", name: M.key.name },
1474
+ operator: "in",
1475
+ right: to_moz(M.value),
1476
+ };
1477
+ });
1478
+
1454
1479
  def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
1455
1480
  return {
1456
1481
  type: "ArrayExpression",
package/lib/output.js CHANGED
@@ -74,7 +74,9 @@ import {
74
74
  AST_ConciseMethod,
75
75
  AST_PrivateGetter,
76
76
  AST_PrivateMethod,
77
+ AST_SymbolPrivateProperty,
77
78
  AST_PrivateSetter,
79
+ AST_PrivateIn,
78
80
  AST_Conditional,
79
81
  AST_Const,
80
82
  AST_Constant,
@@ -1795,7 +1797,10 @@ function OutputStream(options) {
1795
1797
  if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
1796
1798
  return true;
1797
1799
  }
1798
- if (node instanceof AST_Binary && node.operator == "in") {
1800
+ if (
1801
+ node instanceof AST_Binary && node.operator == "in"
1802
+ || node instanceof AST_PrivateIn
1803
+ ) {
1799
1804
  return walk_abort; // makes walk() return true
1800
1805
  }
1801
1806
  });
@@ -2184,6 +2189,16 @@ function OutputStream(options) {
2184
2189
  }
2185
2190
  self._print_getter_setter(type, true, output);
2186
2191
  });
2192
+ DEFPRINT(AST_PrivateIn, function(self, output) {
2193
+ self.key.print(output);
2194
+ output.space();
2195
+ output.print("in");
2196
+ output.space();
2197
+ self.value.print(output);
2198
+ });
2199
+ DEFPRINT(AST_SymbolPrivateProperty, function(self, output) {
2200
+ output.print("#" + self.name);
2201
+ });
2187
2202
  DEFPRINT(AST_ConciseMethod, function(self, output) {
2188
2203
  var type;
2189
2204
  if (self.is_generator && self.async) {
package/lib/parse.js CHANGED
@@ -69,6 +69,7 @@ import {
69
69
  AST_ClassProperty,
70
70
  AST_ClassStaticBlock,
71
71
  AST_ConciseMethod,
72
+ AST_PrivateIn,
72
73
  AST_PrivateGetter,
73
74
  AST_PrivateMethod,
74
75
  AST_PrivateSetter,
@@ -145,6 +146,7 @@ import {
145
146
  AST_TemplateSegment,
146
147
  AST_TemplateString,
147
148
  AST_This,
149
+ AST_SymbolPrivateProperty,
148
150
  AST_Throw,
149
151
  AST_Token,
150
152
  AST_Toplevel,
@@ -1041,7 +1043,7 @@ var PRECEDENCE = (function(a, ret) {
1041
1043
  {}
1042
1044
  );
1043
1045
 
1044
- var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "big_int", "string", "regexp", "name" ]);
1046
+ var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "big_int", "string", "regexp", "name"]);
1045
1047
 
1046
1048
  /* -----[ Parser ]----- */
1047
1049
 
@@ -1213,6 +1215,10 @@ function parse($TEXT, options) {
1213
1215
  return simple_statement();
1214
1216
 
1215
1217
  case "name":
1218
+ case "privatename":
1219
+ if(is("privatename") && !S.in_class)
1220
+ croak("Private field must be used in an enclosing class");
1221
+
1216
1222
  if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
1217
1223
  next();
1218
1224
  next();
@@ -2357,6 +2363,29 @@ function parse($TEXT, options) {
2357
2363
  if (is("template_head")) {
2358
2364
  return subscripts(template_string(), allow_calls);
2359
2365
  }
2366
+ if (is("privatename")) {
2367
+ if(!S.in_class) {
2368
+ croak("Private field must be used in an enclosing class");
2369
+ }
2370
+
2371
+ const start = S.token;
2372
+ const key = new AST_SymbolPrivateProperty({
2373
+ start,
2374
+ name: start.value,
2375
+ end: start
2376
+ });
2377
+ next();
2378
+ expect_token("operator", "in");
2379
+
2380
+ const private_in = new AST_PrivateIn({
2381
+ start,
2382
+ key,
2383
+ value: subscripts(as_atom_node(), allow_calls),
2384
+ end: prev()
2385
+ });
2386
+
2387
+ return subscripts(private_in, allow_calls);
2388
+ }
2360
2389
  if (ATOMIC_START_TOKEN.has(S.token.type)) {
2361
2390
  return subscripts(as_atom_node(), allow_calls);
2362
2391
  }
@@ -2442,7 +2471,9 @@ function parse($TEXT, options) {
2442
2471
  }));
2443
2472
  continue;
2444
2473
  }
2445
-
2474
+ if(is("privatename")) {
2475
+ croak("private fields are not allowed in an object");
2476
+ }
2446
2477
  var name = as_property_name();
2447
2478
  var value;
2448
2479
 
@@ -2516,7 +2547,8 @@ function parse($TEXT, options) {
2516
2547
  }
2517
2548
 
2518
2549
  expect("{");
2519
-
2550
+ // mark in class feild,
2551
+ S.in_class = true;
2520
2552
  while (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
2521
2553
  while (!is("punc", "}")) {
2522
2554
  start = S.token;
@@ -2525,6 +2557,8 @@ function parse($TEXT, options) {
2525
2557
  a.push(method);
2526
2558
  while (is("punc", ";")) { next(); }
2527
2559
  }
2560
+ // mark in class feild,
2561
+ S.in_class = false;
2528
2562
 
2529
2563
  S.input.pop_directives_stack();
2530
2564
 
@@ -3031,6 +3065,8 @@ function parse($TEXT, options) {
3031
3065
  var start = expr.start;
3032
3066
  if (is("punc", ".")) {
3033
3067
  next();
3068
+ if(is("privatename") && !S.in_class)
3069
+ croak("Private field must be used in an enclosing class");
3034
3070
  const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3035
3071
  return subscripts(new AST_DotVariant({
3036
3072
  start : start,
@@ -3084,6 +3120,8 @@ function parse($TEXT, options) {
3084
3120
 
3085
3121
  chain_contents = subscripts(call, true, true);
3086
3122
  } else if (is("name") || is("privatename")) {
3123
+ if(is("privatename") && !S.in_class)
3124
+ croak("Private field must be used in an enclosing class");
3087
3125
  const AST_DotVariant = is("privatename") ? AST_DotHash : AST_Dot;
3088
3126
  chain_contents = subscripts(new AST_DotVariant({
3089
3127
  start,
@@ -3129,7 +3167,6 @@ function parse($TEXT, options) {
3129
3167
  end: prev()
3130
3168
  }), allow_calls);
3131
3169
  }
3132
-
3133
3170
  return expr;
3134
3171
  };
3135
3172
 
package/lib/propmangle.js CHANGED
@@ -61,6 +61,7 @@ import {
61
61
  AST_PrivateMethod,
62
62
  AST_PrivateGetter,
63
63
  AST_PrivateSetter,
64
+ AST_PrivateIn,
64
65
  AST_Sequence,
65
66
  AST_String,
66
67
  AST_Sub,
@@ -153,6 +154,7 @@ function mangle_private_properties(ast, options) {
153
154
  || node instanceof AST_PrivateMethod
154
155
  || node instanceof AST_PrivateGetter
155
156
  || node instanceof AST_PrivateSetter
157
+ || node instanceof AST_PrivateIn
156
158
  ) {
157
159
  node.key.name = mangle_private(node.key.name);
158
160
  } else if (node instanceof AST_DotHash) {
package/lib/size.js CHANGED
@@ -53,6 +53,7 @@ import {
53
53
  AST_PrivateGetter,
54
54
  AST_PrivateMethod,
55
55
  AST_PrivateSetter,
56
+ AST_PrivateIn,
56
57
  AST_RegExp,
57
58
  AST_Return,
58
59
  AST_Sequence,
@@ -395,6 +396,10 @@ AST_PrivateGetter.prototype._size = AST_PrivateSetter.prototype._size = function
395
396
  return AST_ConciseMethod.prototype._size.call(this) + 4;
396
397
  };
397
398
 
399
+ AST_PrivateIn.prototype._size = function () {
400
+ return 5; // "#", and " in "
401
+ };
402
+
398
403
  AST_Class.prototype._size = function () {
399
404
  return (
400
405
  (this.name ? 8 : 7)
package/lib/transform.js CHANGED
@@ -47,6 +47,7 @@ import {
47
47
  AST_Array,
48
48
  AST_Await,
49
49
  AST_Binary,
50
+ AST_PrivateIn,
50
51
  AST_Block,
51
52
  AST_Call,
52
53
  AST_Case,
@@ -259,6 +260,11 @@ def_transform(AST_Binary, function(self, tw) {
259
260
  self.right = self.right.transform(tw);
260
261
  });
261
262
 
263
+ def_transform(AST_PrivateIn, function(self, tw) {
264
+ self.key = self.key.transform(tw);
265
+ self.value = self.value.transform(tw);
266
+ });
267
+
262
268
  def_transform(AST_Conditional, function(self, tw) {
263
269
  self.condition = self.condition.transform(tw);
264
270
  self.consequent = self.consequent.transform(tw);
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.15.1",
7
+ "version": "5.16.0",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },