terser 5.16.1 → 5.17.7

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.
@@ -151,6 +151,7 @@ import {
151
151
  AST_Toplevel,
152
152
  AST_True,
153
153
  AST_Try,
154
+ AST_TryBlock,
154
155
  AST_Unary,
155
156
  AST_UnaryPostfix,
156
157
  AST_UnaryPrefix,
@@ -344,7 +345,7 @@ import { is_basic_identifier_string } from "./parse.js";
344
345
  return new AST_Try({
345
346
  start : my_start_token(M),
346
347
  end : my_end_token(M),
347
- body : from_moz(M.block).body,
348
+ body : new AST_TryBlock(from_moz(M.block)),
348
349
  bcatch : from_moz(handlers[0]),
349
350
  bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
350
351
  });
@@ -394,22 +395,25 @@ import { is_basic_identifier_string } from "./parse.js";
394
395
  },
395
396
 
396
397
  MethodDefinition: function(M) {
398
+ const is_private = M.key.type === "PrivateIdentifier";
399
+ const key = M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value });
400
+
397
401
  var args = {
398
402
  start : my_start_token(M),
399
403
  end : my_end_token(M),
400
- key : M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value }),
404
+ key,
401
405
  value : from_moz(M.value),
402
406
  static : M.static,
403
407
  };
404
408
  if (M.kind == "get") {
405
- return new AST_ObjectGetter(args);
409
+ return new (is_private ? AST_PrivateGetter : AST_ObjectGetter)(args);
406
410
  }
407
411
  if (M.kind == "set") {
408
- return new AST_ObjectSetter(args);
412
+ return new (is_private ? AST_PrivateSetter : AST_ObjectSetter)(args);
409
413
  }
410
414
  args.is_generator = M.value.generator;
411
415
  args.async = M.value.async;
412
- return new AST_ConciseMethod(args);
416
+ return new (is_private ? AST_PrivateMethod : AST_ConciseMethod)(args);
413
417
  },
414
418
 
415
419
  FieldDefinition: function(M) {
@@ -433,8 +437,16 @@ import { is_basic_identifier_string } from "./parse.js";
433
437
  let key;
434
438
  if (M.computed) {
435
439
  key = from_moz(M.key);
440
+ } else if (M.key.type === "PrivateIdentifier") {
441
+ return new AST_ClassPrivateProperty({
442
+ start : my_start_token(M),
443
+ end : my_end_token(M),
444
+ key : from_moz(M.key),
445
+ value : from_moz(M.value),
446
+ static : M.static,
447
+ });
436
448
  } else {
437
- if (M.key.type !== "Identifier" && M.key.type !== "PrivateIdentifier") {
449
+ if (M.key.type !== "Identifier") {
438
450
  throw new Error("Non-Identifier key in PropertyDefinition");
439
451
  }
440
452
  key = from_moz(M.key);
@@ -449,6 +461,14 @@ import { is_basic_identifier_string } from "./parse.js";
449
461
  });
450
462
  },
451
463
 
464
+ PrivateIdentifier: function (M) {
465
+ return new AST_SymbolPrivateProperty({
466
+ start: my_start_token(M),
467
+ end: my_end_token(M),
468
+ name: M.name
469
+ });
470
+ },
471
+
452
472
  StaticBlock: function(M) {
453
473
  return new AST_ClassStaticBlock({
454
474
  start : my_start_token(M),
@@ -490,6 +510,15 @@ import { is_basic_identifier_string } from "./parse.js";
490
510
  },
491
511
 
492
512
  MemberExpression: function(M) {
513
+ if (M.property.type === "PrivateIdentifier") {
514
+ return new AST_DotHash({
515
+ start : my_start_token(M),
516
+ end : my_end_token(M),
517
+ property : M.property.name,
518
+ expression : from_moz(M.object),
519
+ optional : M.optional || false
520
+ });
521
+ }
493
522
  return new (M.computed ? AST_Sub : AST_Dot)({
494
523
  start : my_start_token(M),
495
524
  end : my_end_token(M),
@@ -529,24 +558,11 @@ import { is_basic_identifier_string } from "./parse.js";
529
558
  var imported_name = null;
530
559
  var imported_names = null;
531
560
  M.specifiers.forEach(function (specifier) {
532
- if (specifier.type === "ImportSpecifier") {
561
+ if (specifier.type === "ImportSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
533
562
  if (!imported_names) { imported_names = []; }
534
- imported_names.push(new AST_NameMapping({
535
- start: my_start_token(specifier),
536
- end: my_end_token(specifier),
537
- foreign_name: from_moz(specifier.imported),
538
- name: from_moz(specifier.local)
539
- }));
563
+ imported_names.push(from_moz(specifier));
540
564
  } else if (specifier.type === "ImportDefaultSpecifier") {
541
- imported_name = from_moz(specifier.local);
542
- } else if (specifier.type === "ImportNamespaceSpecifier") {
543
- if (!imported_names) { imported_names = []; }
544
- imported_names.push(new AST_NameMapping({
545
- start: my_start_token(specifier),
546
- end: my_end_token(specifier),
547
- foreign_name: new AST_SymbolImportForeign({ name: "*" }),
548
- name: from_moz(specifier.local)
549
- }));
565
+ imported_name = from_moz(specifier);
550
566
  }
551
567
  });
552
568
  return new AST_Import({
@@ -559,14 +575,39 @@ import { is_basic_identifier_string } from "./parse.js";
559
575
  });
560
576
  },
561
577
 
578
+ ImportSpecifier: function(M) {
579
+ return new AST_NameMapping({
580
+ start: my_start_token(M),
581
+ end: my_end_token(M),
582
+ foreign_name: from_moz(M.imported),
583
+ name: from_moz(M.local)
584
+ });
585
+ },
586
+
587
+ ImportDefaultSpecifier: function(M) {
588
+ return from_moz(M.local);
589
+ },
590
+
591
+ ImportNamespaceSpecifier: function(M) {
592
+ return new AST_NameMapping({
593
+ start: my_start_token(M),
594
+ end: my_end_token(M),
595
+ foreign_name: new AST_SymbolImportForeign({ name: "*" }),
596
+ name: from_moz(M.local)
597
+ });
598
+ },
599
+
562
600
  ExportAllDeclaration: function(M) {
601
+ var foreign_name = M.exported == null ?
602
+ new AST_SymbolExportForeign({ name: "*" }) :
603
+ from_moz(M.exported);
563
604
  return new AST_Export({
564
605
  start: my_start_token(M),
565
606
  end: my_end_token(M),
566
607
  exported_names: [
567
608
  new AST_NameMapping({
568
609
  name: new AST_SymbolExportForeign({ name: "*" }),
569
- foreign_name: new AST_SymbolExportForeign({ name: "*" })
610
+ foreign_name: foreign_name
570
611
  })
571
612
  ],
572
613
  module_name: from_moz(M.source),
@@ -580,10 +621,7 @@ import { is_basic_identifier_string } from "./parse.js";
580
621
  end: my_end_token(M),
581
622
  exported_definition: from_moz(M.declaration),
582
623
  exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
583
- return new AST_NameMapping({
584
- foreign_name: from_moz(specifier.exported),
585
- name: from_moz(specifier.local)
586
- });
624
+ return from_moz(specifier);
587
625
  }) : null,
588
626
  module_name: from_moz(M.source),
589
627
  assert_clause: assert_clause_from_moz(M.assertions)
@@ -599,6 +637,13 @@ import { is_basic_identifier_string } from "./parse.js";
599
637
  });
600
638
  },
601
639
 
640
+ ExportSpecifier: function(M) {
641
+ return new AST_NameMapping({
642
+ foreign_name: from_moz(M.exported),
643
+ name: from_moz(M.local)
644
+ });
645
+ },
646
+
602
647
  Literal: function(M) {
603
648
  var val = M.value, args = {
604
649
  start : my_start_token(M),
@@ -624,6 +669,22 @@ import { is_basic_identifier_string } from "./parse.js";
624
669
  if (val === null) return new AST_Null(args);
625
670
  switch (typeof val) {
626
671
  case "string":
672
+ args.quote = "\"";
673
+ var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
674
+ if (p.type == "ImportSpecifier") {
675
+ args.name = val;
676
+ return new AST_SymbolImportForeign(args);
677
+ } else if (p.type == "ExportSpecifier") {
678
+ args.name = val;
679
+ if (M == p.exported) {
680
+ return new AST_SymbolExportForeign(args);
681
+ } else {
682
+ return new AST_SymbolExport(args);
683
+ }
684
+ } else if (p.type == "ExportAllDeclaration" && M == p.exported) {
685
+ args.name = val;
686
+ return new AST_SymbolExportForeign(args);
687
+ }
627
688
  args.value = val;
628
689
  return new AST_String(args);
629
690
  case "number":
@@ -1283,7 +1344,7 @@ import { is_basic_identifier_string } from "./parse.js";
1283
1344
  def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
1284
1345
  return {
1285
1346
  type: "TryStatement",
1286
- block: to_moz_block(M),
1347
+ block: to_moz_block(M.body),
1287
1348
  handler: to_moz(M.bcatch),
1288
1349
  guardedHandlers: [],
1289
1350
  finalizer: to_moz(M.bfinally)
@@ -1328,10 +1389,17 @@ import { is_basic_identifier_string } from "./parse.js";
1328
1389
 
1329
1390
  def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
1330
1391
  if (M.exported_names) {
1331
- if (M.exported_names[0].name.name === "*") {
1392
+ var first_exported = M.exported_names[0];
1393
+ var first_exported_name = first_exported.name;
1394
+ if (first_exported_name.name === "*" && !first_exported_name.quote) {
1395
+ var foreign_name = first_exported.foreign_name;
1396
+ var exported = foreign_name.name === "*" && !foreign_name.quote
1397
+ ? null
1398
+ : to_moz(foreign_name);
1332
1399
  return {
1333
1400
  type: "ExportAllDeclaration",
1334
1401
  source: to_moz(M.module_name),
1402
+ exported: exported,
1335
1403
  assertions: assert_clause_to_moz(M.assert_clause)
1336
1404
  };
1337
1405
  }
@@ -1363,19 +1431,22 @@ import { is_basic_identifier_string } from "./parse.js";
1363
1431
  local: to_moz(M.imported_name)
1364
1432
  });
1365
1433
  }
1366
- if (M.imported_names && M.imported_names[0].foreign_name.name === "*") {
1367
- specifiers.push({
1368
- type: "ImportNamespaceSpecifier",
1369
- local: to_moz(M.imported_names[0].name)
1370
- });
1371
- } else if (M.imported_names) {
1372
- M.imported_names.forEach(function(name_mapping) {
1434
+ if (M.imported_names) {
1435
+ var first_imported_foreign_name = M.imported_names[0].foreign_name;
1436
+ if (first_imported_foreign_name.name === "*" && !first_imported_foreign_name.quote) {
1373
1437
  specifiers.push({
1374
- type: "ImportSpecifier",
1375
- local: to_moz(name_mapping.name),
1376
- imported: to_moz(name_mapping.foreign_name)
1438
+ type: "ImportNamespaceSpecifier",
1439
+ local: to_moz(M.imported_names[0].name)
1377
1440
  });
1378
- });
1441
+ } else {
1442
+ M.imported_names.forEach(function(name_mapping) {
1443
+ specifiers.push({
1444
+ type: "ImportSpecifier",
1445
+ local: to_moz(name_mapping.name),
1446
+ imported: to_moz(name_mapping.foreign_name)
1447
+ });
1448
+ });
1449
+ }
1379
1450
  }
1380
1451
  return {
1381
1452
  type: "ImportDeclaration",
@@ -1639,7 +1710,14 @@ import { is_basic_identifier_string } from "./parse.js";
1639
1710
  });
1640
1711
 
1641
1712
  def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
1642
- if (M instanceof AST_SymbolMethod && parent.quote) {
1713
+ if (
1714
+ (M instanceof AST_SymbolMethod && parent.quote) ||
1715
+ ((
1716
+ M instanceof AST_SymbolImportForeign ||
1717
+ M instanceof AST_SymbolExportForeign ||
1718
+ M instanceof AST_SymbolExport
1719
+ ) && M.quote)
1720
+ ) {
1643
1721
  return {
1644
1722
  type: "Literal",
1645
1723
  value: M.name
package/lib/output.js CHANGED
@@ -143,6 +143,7 @@ import {
143
143
  AST_Throw,
144
144
  AST_Toplevel,
145
145
  AST_Try,
146
+ AST_TryBlock,
146
147
  AST_Unary,
147
148
  AST_UnaryPostfix,
148
149
  AST_UnaryPrefix,
@@ -661,14 +662,17 @@ function OutputStream(options) {
661
662
  if (!start) return;
662
663
  var printed_comments = self.printed_comments;
663
664
 
664
- // There cannot be a newline between return and its value.
665
- const return_with_value = node instanceof AST_Exit && node.value;
665
+ // There cannot be a newline between return/yield and its value.
666
+ const keyword_with_value =
667
+ node instanceof AST_Exit && node.value
668
+ || (node instanceof AST_Await || node instanceof AST_Yield)
669
+ && node.expression;
666
670
 
667
671
  if (
668
672
  start.comments_before
669
673
  && printed_comments.has(start.comments_before)
670
674
  ) {
671
- if (return_with_value) {
675
+ if (keyword_with_value) {
672
676
  start.comments_before = [];
673
677
  } else {
674
678
  return;
@@ -681,10 +685,12 @@ function OutputStream(options) {
681
685
  }
682
686
  printed_comments.add(comments);
683
687
 
684
- if (return_with_value) {
688
+ if (keyword_with_value) {
685
689
  var tw = new TreeWalker(function(node) {
686
690
  var parent = tw.parent();
687
691
  if (parent instanceof AST_Exit
692
+ || parent instanceof AST_Await
693
+ || parent instanceof AST_Yield
688
694
  || parent instanceof AST_Binary && parent.left === node
689
695
  || parent.TYPE == "Call" && parent.expression === node
690
696
  || parent instanceof AST_Conditional && parent.condition === node
@@ -703,7 +709,7 @@ function OutputStream(options) {
703
709
  }
704
710
  });
705
711
  tw.push(node);
706
- node.value.walk(tw);
712
+ keyword_with_value.walk(tw);
707
713
  }
708
714
 
709
715
  if (current_pos == 0) {
@@ -1079,6 +1085,12 @@ function OutputStream(options) {
1079
1085
  return true;
1080
1086
  });
1081
1087
 
1088
+ PARENS(AST_Chain, function(output) {
1089
+ var p = output.parent();
1090
+ if (!(p instanceof AST_Call || p instanceof AST_PropAccess)) return false;
1091
+ return p.expression === this;
1092
+ });
1093
+
1082
1094
  PARENS(AST_PropAccess, function(output) {
1083
1095
  var p = output.parent();
1084
1096
  if (p instanceof AST_New && p.expression === this) {
@@ -1225,7 +1237,7 @@ function OutputStream(options) {
1225
1237
  }
1226
1238
 
1227
1239
  AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
1228
- force_statement(this.body, output);
1240
+ print_maybe_braced_body(this.body, output);
1229
1241
  });
1230
1242
 
1231
1243
  DEFPRINT(AST_Statement, function(self, output) {
@@ -1554,7 +1566,7 @@ function OutputStream(options) {
1554
1566
  b = b.body;
1555
1567
  } else break;
1556
1568
  }
1557
- force_statement(self.body, output);
1569
+ print_maybe_braced_body(self.body, output);
1558
1570
  }
1559
1571
  DEFPRINT(AST_If, function(self, output) {
1560
1572
  output.print("if");
@@ -1571,7 +1583,7 @@ function OutputStream(options) {
1571
1583
  if (self.alternative instanceof AST_If)
1572
1584
  self.alternative.print(output);
1573
1585
  else
1574
- force_statement(self.alternative, output);
1586
+ print_maybe_braced_body(self.alternative, output);
1575
1587
  } else {
1576
1588
  self._do_print_body(output);
1577
1589
  }
@@ -1620,7 +1632,7 @@ function OutputStream(options) {
1620
1632
  DEFPRINT(AST_Try, function(self, output) {
1621
1633
  output.print("try");
1622
1634
  output.space();
1623
- print_braced(self, output);
1635
+ self.body.print(output);
1624
1636
  if (self.bcatch) {
1625
1637
  output.space();
1626
1638
  self.bcatch.print(output);
@@ -1630,6 +1642,9 @@ function OutputStream(options) {
1630
1642
  self.bfinally.print(output);
1631
1643
  }
1632
1644
  });
1645
+ DEFPRINT(AST_TryBlock, function(self, output) {
1646
+ print_braced(self, output);
1647
+ });
1633
1648
  DEFPRINT(AST_Catch, function(self, output) {
1634
1649
  output.print("catch");
1635
1650
  if (self.argname) {
@@ -1681,7 +1696,9 @@ function OutputStream(options) {
1681
1696
  output.space();
1682
1697
  }
1683
1698
  if (self.imported_names) {
1684
- if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
1699
+ if (self.imported_names.length === 1 &&
1700
+ self.imported_names[0].foreign_name.name === "*" &&
1701
+ !self.imported_names[0].foreign_name.quote) {
1685
1702
  self.imported_names[0].print(output);
1686
1703
  } else {
1687
1704
  output.print("{");
@@ -1715,14 +1732,31 @@ function OutputStream(options) {
1715
1732
  DEFPRINT(AST_NameMapping, function(self, output) {
1716
1733
  var is_import = output.parent() instanceof AST_Import;
1717
1734
  var definition = self.name.definition();
1735
+ var foreign_name = self.foreign_name;
1718
1736
  var names_are_different =
1719
1737
  (definition && definition.mangled_name || self.name.name) !==
1720
- self.foreign_name.name;
1738
+ foreign_name.name;
1739
+ if (!names_are_different &&
1740
+ foreign_name.name === "*" &&
1741
+ foreign_name.quote != self.name.quote) {
1742
+ // export * as "*"
1743
+ names_are_different = true;
1744
+ }
1745
+ var foreign_name_is_name = foreign_name.quote == null;
1721
1746
  if (names_are_different) {
1722
1747
  if (is_import) {
1723
- output.print(self.foreign_name.name);
1748
+ if (foreign_name_is_name) {
1749
+ output.print(foreign_name.name);
1750
+ } else {
1751
+ output.print_string(foreign_name.name, foreign_name.quote);
1752
+ }
1724
1753
  } else {
1725
- self.name.print(output);
1754
+ if (self.name.quote == null) {
1755
+ self.name.print(output);
1756
+ } else {
1757
+ output.print_string(self.name.name, self.name.quote);
1758
+ }
1759
+
1726
1760
  }
1727
1761
  output.space();
1728
1762
  output.print("as");
@@ -1730,10 +1764,18 @@ function OutputStream(options) {
1730
1764
  if (is_import) {
1731
1765
  self.name.print(output);
1732
1766
  } else {
1733
- output.print(self.foreign_name.name);
1767
+ if (foreign_name_is_name) {
1768
+ output.print(foreign_name.name);
1769
+ } else {
1770
+ output.print_string(foreign_name.name, foreign_name.quote);
1771
+ }
1734
1772
  }
1735
1773
  } else {
1736
- self.name.print(output);
1774
+ if (self.name.quote == null) {
1775
+ self.name.print(output);
1776
+ } else {
1777
+ output.print_string(self.name.name, self.name.quote);
1778
+ }
1737
1779
  }
1738
1780
  });
1739
1781
 
@@ -1745,8 +1787,10 @@ function OutputStream(options) {
1745
1787
  output.space();
1746
1788
  }
1747
1789
  if (self.exported_names) {
1748
- if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
1749
- self.exported_names[0].print(output);
1790
+ if (self.exported_names.length === 1 &&
1791
+ self.exported_names[0].name.name === "*" &&
1792
+ !self.exported_names[0].name.quote) {
1793
+ self.exported_names[0].print(output);
1750
1794
  } else {
1751
1795
  output.print("{");
1752
1796
  self.exported_names.forEach(function(name_export, i) {
@@ -1873,7 +1917,7 @@ function OutputStream(options) {
1873
1917
  ? output.option("ie8")
1874
1918
  : !is_identifier_string(
1875
1919
  prop,
1876
- output.option("ecma") >= 2015 || output.option("safari10")
1920
+ output.option("ecma") >= 2015 && !output.option("safari10")
1877
1921
  );
1878
1922
 
1879
1923
  if (self.optional) output.print("?.");
@@ -2041,15 +2085,19 @@ function OutputStream(options) {
2041
2085
  output.print("new.target");
2042
2086
  });
2043
2087
 
2088
+ /** Prints a prop name. Returns whether it can be used as a shorthand. */
2044
2089
  function print_property_name(key, quote, output) {
2045
2090
  if (output.option("quote_keys")) {
2046
- return output.print_string(key);
2091
+ output.print_string(key);
2092
+ return false;
2047
2093
  }
2048
2094
  if ("" + +key == key && key >= 0) {
2049
2095
  if (output.option("keep_numbers")) {
2050
- return output.print(key);
2096
+ output.print(key);
2097
+ return false;
2051
2098
  }
2052
- return output.print(make_num(key));
2099
+ output.print(make_num(key));
2100
+ return false;
2053
2101
  }
2054
2102
  var print_string = ALL_RESERVED_WORDS.has(key)
2055
2103
  ? output.option("ie8")
@@ -2059,9 +2107,11 @@ function OutputStream(options) {
2059
2107
  : !is_identifier_string(key, true)
2060
2108
  );
2061
2109
  if (print_string || (quote && output.option("keep_quoted_props"))) {
2062
- return output.print_string(key, quote);
2110
+ output.print_string(key, quote);
2111
+ return false;
2063
2112
  }
2064
- return output.print_name(key);
2113
+ output.print_name(key);
2114
+ return true;
2065
2115
  }
2066
2116
 
2067
2117
  DEFPRINT(AST_ObjectKeyVal, function(self, output) {
@@ -2070,28 +2120,29 @@ function OutputStream(options) {
2070
2120
  return def ? def.mangled_name || def.name : self.name;
2071
2121
  }
2072
2122
 
2073
- var allowShortHand = output.option("shorthand");
2074
- if (allowShortHand &&
2075
- self.value instanceof AST_Symbol &&
2076
- is_identifier_string(
2077
- self.key,
2078
- output.option("ecma") >= 2015 || output.option("safari10")
2079
- ) &&
2080
- get_name(self.value) === self.key &&
2081
- !ALL_RESERVED_WORDS.has(self.key)
2123
+ const try_shorthand = output.option("shorthand") && !(self.key instanceof AST_Node);
2124
+ if (
2125
+ try_shorthand
2126
+ && self.value instanceof AST_Symbol
2127
+ && get_name(self.value) === self.key
2128
+ && !ALL_RESERVED_WORDS.has(self.key)
2082
2129
  ) {
2083
- print_property_name(self.key, self.quote, output);
2084
-
2085
- } else if (allowShortHand &&
2086
- self.value instanceof AST_DefaultAssign &&
2087
- self.value.left instanceof AST_Symbol &&
2088
- is_identifier_string(
2089
- self.key,
2090
- output.option("ecma") >= 2015 || output.option("safari10")
2091
- ) &&
2092
- get_name(self.value.left) === self.key
2130
+ const was_shorthand = print_property_name(self.key, self.quote, output);
2131
+ if (!was_shorthand) {
2132
+ output.colon();
2133
+ self.value.print(output);
2134
+ }
2135
+ } else if (
2136
+ try_shorthand
2137
+ && self.value instanceof AST_DefaultAssign
2138
+ && self.value.left instanceof AST_Symbol
2139
+ && get_name(self.value.left) === self.key
2093
2140
  ) {
2094
- print_property_name(self.key, self.quote, output);
2141
+ const was_shorthand = print_property_name(self.key, self.quote, output);
2142
+ if (!was_shorthand) {
2143
+ output.colon();
2144
+ self.value.left.print(output);
2145
+ }
2095
2146
  output.space();
2096
2147
  output.print("=");
2097
2148
  output.space();
@@ -2266,12 +2317,15 @@ function OutputStream(options) {
2266
2317
  }
2267
2318
  });
2268
2319
 
2269
- function force_statement(stat, output) {
2320
+ /** if, for, while, may or may not have braces surrounding its body */
2321
+ function print_maybe_braced_body(stat, output) {
2270
2322
  if (output.option("braces")) {
2271
2323
  make_block(stat, output);
2272
2324
  } else {
2273
2325
  if (!stat || stat instanceof AST_EmptyStatement)
2274
2326
  output.force_semicolon();
2327
+ else if (stat instanceof AST_Let || stat instanceof AST_Const || stat instanceof AST_Class)
2328
+ make_block(stat, output);
2275
2329
  else
2276
2330
  stat.print(output);
2277
2331
  }