terser 5.14.2 → 5.15.1

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,17 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.15.1
4
+
5
+ - Fixed missing parentheses around optional chains
6
+ - Avoid bare `let` or `const` as the bodies of `if` statements (#1253)
7
+ - Small internal fixes (#1271)
8
+ - Avoid inlining a class twice and creating two equivalent but `!==` classes.
9
+
10
+ ## v5.15.0
11
+ - Basic support for ES2022 class static initializer blocks.
12
+ - Add `AudioWorkletNode` constructor options to domprops list (#1230)
13
+ - Make identity function inliner not inline `id(...expandedArgs)`
14
+
3
15
  ## v5.14.2
4
16
 
5
17
  - Security fix for RegExps that should not be evaluated (regexp DDOS)
package/bin/terser.mjs ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+
3
+ "use strict";
4
+
5
+ import "../tools/exit.cjs";
6
+
7
+ import fs from "fs"
8
+ import path from "path"
9
+ import program from "commander"
10
+
11
+ import { run_cli } from "../lib/cli.js"
12
+
13
+ const packageJson = {
14
+ name: "terser",
15
+ version: "experimental module CLI"
16
+ }
17
+
18
+ run_cli({ program, packageJson, fs, path }).catch((error) => {
19
+ console.error(error);
20
+ process.exitCode = 1;
21
+ });
@@ -2731,6 +2731,10 @@ function parse($TEXT, options) {
2731
2731
  var accessor_type = null;
2732
2732
 
2733
2733
  if (is_class && name === "static" && is_not_method_start()) {
2734
+ const static_block = class_static_block();
2735
+ if (static_block != null) {
2736
+ return static_block;
2737
+ }
2734
2738
  is_static = true;
2735
2739
  name = as_property_name();
2736
2740
  }
@@ -2837,6 +2841,25 @@ function parse($TEXT, options) {
2837
2841
  }
2838
2842
  }
2839
2843
 
2844
+ function class_static_block() {
2845
+ if (!is("punc", "{")) {
2846
+ return null;
2847
+ }
2848
+
2849
+ const start = S.token;
2850
+ const body = [];
2851
+
2852
+ next();
2853
+
2854
+ while (!is("punc", "}")) {
2855
+ body.push(statement());
2856
+ }
2857
+
2858
+ next();
2859
+
2860
+ return new AST_ClassStaticBlock({ start, body, end: prev() });
2861
+ }
2862
+
2840
2863
  function maybe_import_assertion() {
2841
2864
  if (is("name", "assert") && !has_newline_before(S.token)) {
2842
2865
  next();
@@ -2946,14 +2969,14 @@ function parse($TEXT, options) {
2946
2969
  var end = prev();
2947
2970
 
2948
2971
  name = name || new type({
2949
- name: "*",
2950
2972
  start: start,
2973
+ name: "*",
2951
2974
  end: end,
2952
2975
  });
2953
2976
 
2954
2977
  foreign_name = new foreign_type({
2955
- name: "*",
2956
2978
  start: start,
2979
+ name: "*",
2957
2980
  end: end,
2958
2981
  });
2959
2982
 
@@ -5784,6 +5807,28 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
5784
5807
  $documentation: "A class definition",
5785
5808
  }, AST_Class);
5786
5809
 
5810
+ var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
5811
+ this.body = props.body;
5812
+ this.block_scope = props.block_scope;
5813
+ this.start = props.start;
5814
+ this.end = props.end;
5815
+ }, {
5816
+ $documentation: "A block containing statements to be executed in the context of the class",
5817
+ $propdoc: {
5818
+ body: "[AST_Statement*] an array of statements",
5819
+ },
5820
+ _walk: function(visitor) {
5821
+ return visitor._visit(this, function() {
5822
+ walk_body(this, visitor);
5823
+ });
5824
+ },
5825
+ _children_backwards(push) {
5826
+ let i = this.body.length;
5827
+ while (i--) push(this.body[i]);
5828
+ },
5829
+ clone: clone_block_scope,
5830
+ }, AST_Scope);
5831
+
5787
5832
  var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
5788
5833
  if (props) {
5789
5834
  this.name = props.name;
@@ -6800,6 +6845,10 @@ def_transform(AST_Class, function(self, tw) {
6800
6845
  self.properties = do_list(self.properties, tw);
6801
6846
  });
6802
6847
 
6848
+ def_transform(AST_ClassStaticBlock, function(self, tw) {
6849
+ self.body = do_list(self.body, tw);
6850
+ });
6851
+
6803
6852
  def_transform(AST_Expansion, function(self, tw) {
6804
6853
  self.expression = self.expression.transform(tw);
6805
6854
  });
@@ -7159,6 +7208,14 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7159
7208
  });
7160
7209
  },
7161
7210
 
7211
+ StaticBlock: function(M) {
7212
+ return new AST_ClassStaticBlock({
7213
+ start : my_start_token(M),
7214
+ end : my_end_token(M),
7215
+ body : M.body.map(from_moz),
7216
+ });
7217
+ },
7218
+
7162
7219
  ArrayExpression: function(M) {
7163
7220
  return new AST_Array({
7164
7221
  start : my_start_token(M),
@@ -8298,6 +8355,13 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8298
8355
  };
8299
8356
  });
8300
8357
 
8358
+ def_to_moz(AST_ClassStaticBlock, function To_Moz_StaticBlock(M) {
8359
+ return {
8360
+ type: "StaticBlock",
8361
+ body: M.body.map(to_moz),
8362
+ };
8363
+ });
8364
+
8301
8365
  def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
8302
8366
  return {
8303
8367
  type: "MetaProperty",
@@ -8496,6 +8560,7 @@ function first_in_statement(stack) {
8496
8560
  (p instanceof AST_PrefixedTemplateString && p.prefix === node) ||
8497
8561
  (p instanceof AST_Dot && p.expression === node) ||
8498
8562
  (p instanceof AST_Sub && p.expression === node) ||
8563
+ (p instanceof AST_Chain && p.expression === node) ||
8499
8564
  (p instanceof AST_Conditional && p.condition === node) ||
8500
8565
  (p instanceof AST_Binary && p.left === node) ||
8501
8566
  (p instanceof AST_UnaryPostfix && p.expression === node)
@@ -8514,6 +8579,7 @@ function left_is_object(node) {
8514
8579
  if (node.TYPE === "Call") return left_is_object(node.expression);
8515
8580
  if (node instanceof AST_PrefixedTemplateString) return left_is_object(node.prefix);
8516
8581
  if (node instanceof AST_Dot || node instanceof AST_Sub) return left_is_object(node.expression);
8582
+ if (node instanceof AST_Chain) return left_is_object(node.expression);
8517
8583
  if (node instanceof AST_Conditional) return left_is_object(node.condition);
8518
8584
  if (node instanceof AST_Binary) return left_is_object(node.left);
8519
8585
  if (node instanceof AST_UnaryPostfix) return left_is_object(node.expression);
@@ -8655,7 +8721,7 @@ function OutputStream(options) {
8655
8721
  if (options.shorthand === undefined)
8656
8722
  options.shorthand = options.ecma > 5;
8657
8723
 
8658
- // Convert comment option to RegExp if neccessary and set up comments filter
8724
+ // Convert comment option to RegExp if necessary and set up comments filter
8659
8725
  var comment_filter = return_false; // Default case, throw all comments away
8660
8726
  if (options.comments) {
8661
8727
  let comments = options.comments;
@@ -10595,6 +10661,11 @@ function OutputStream(options) {
10595
10661
  }
10596
10662
  self._print_getter_setter(type, false, output);
10597
10663
  });
10664
+ DEFPRINT(AST_ClassStaticBlock, function (self, output) {
10665
+ output.print("static");
10666
+ output.space();
10667
+ print_braced(self, output);
10668
+ });
10598
10669
  AST_Symbol.DEFMETHOD("_do_print", function(output) {
10599
10670
  var def = this.definition();
10600
10671
  output.print_name(def ? def.mangled_name || def.name : this.name);
@@ -12268,6 +12339,11 @@ AST_Class.prototype._size = function () {
12268
12339
  );
12269
12340
  };
12270
12341
 
12342
+ AST_ClassStaticBlock.prototype._size = function () {
12343
+ // "class{}" + semicolons
12344
+ return 7 + list_overhead(this.body);
12345
+ };
12346
+
12271
12347
  AST_ClassProperty.prototype._size = function () {
12272
12348
  return (
12273
12349
  static_size(this.static)
@@ -12644,8 +12720,9 @@ function is_ref_of(ref, type) {
12644
12720
  }
12645
12721
  }
12646
12722
 
12647
- // Can we turn { block contents... } into just the block contents ?
12648
- // Not if one of these is inside.
12723
+ /**Can we turn { block contents... } into just the block contents ?
12724
+ * Not if one of these is inside.
12725
+ **/
12649
12726
  function can_be_evicted_from_block(node) {
12650
12727
  return !(
12651
12728
  node instanceof AST_DefClass ||
@@ -13138,6 +13215,9 @@ function is_nullish(node, compressor) {
13138
13215
  }
13139
13216
  return any(this.properties, compressor);
13140
13217
  });
13218
+ def_has_side_effects(AST_ClassStaticBlock, function(compressor) {
13219
+ return any(this.body, compressor);
13220
+ });
13141
13221
  def_has_side_effects(AST_Binary, function(compressor) {
13142
13222
  return this.left.has_side_effects(compressor)
13143
13223
  || this.right.has_side_effects(compressor);
@@ -13237,6 +13317,9 @@ function is_nullish(node, compressor) {
13237
13317
  if (this.extends && this.extends.may_throw(compressor)) return true;
13238
13318
  return any(this.properties, compressor);
13239
13319
  });
13320
+ def_may_throw(AST_ClassStaticBlock, function (compressor) {
13321
+ return any(this.body, compressor);
13322
+ });
13240
13323
 
13241
13324
  def_may_throw(AST_Array, function(compressor) {
13242
13325
  return any(this.elements, compressor);
@@ -13405,6 +13488,9 @@ function is_nullish(node, compressor) {
13405
13488
  if (prop.static && prop.value && !prop.value.is_constant_expression(scope)) {
13406
13489
  return false;
13407
13490
  }
13491
+ if (prop instanceof AST_ClassStaticBlock) {
13492
+ return false;
13493
+ }
13408
13494
  }
13409
13495
 
13410
13496
  return all_refs_local.call(this, scope);
@@ -13728,9 +13814,18 @@ const aborts = (thing) => thing && thing.aborts();
13728
13814
  }
13729
13815
  return null;
13730
13816
  }
13731
- def_aborts(AST_Import, function() { return null; });
13817
+ def_aborts(AST_Import, return_null);
13732
13818
  def_aborts(AST_BlockStatement, block_aborts);
13733
13819
  def_aborts(AST_SwitchBranch, block_aborts);
13820
+ def_aborts(AST_DefClass, function () {
13821
+ for (const prop of this.properties) {
13822
+ if (prop instanceof AST_ClassStaticBlock) {
13823
+ if (prop.aborts()) return prop;
13824
+ }
13825
+ }
13826
+ return null;
13827
+ });
13828
+ def_aborts(AST_ClassStaticBlock, block_aborts);
13734
13829
  def_aborts(AST_If, function() {
13735
13830
  return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
13736
13831
  });
@@ -14309,6 +14404,14 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
14309
14404
  if (trimmed_extends)
14310
14405
  with_effects.push(trimmed_extends);
14311
14406
  for (const prop of this.properties) {
14407
+ if (prop instanceof AST_ClassStaticBlock) {
14408
+ if (prop.body.some(stat => stat.has_side_effects(compressor))) {
14409
+ return this;
14410
+ } else {
14411
+ continue;
14412
+ }
14413
+ }
14414
+
14312
14415
  const trimmed_prop = prop.drop_side_effect_free(compressor);
14313
14416
  if (trimmed_prop)
14314
14417
  with_effects.push(trimmed_prop);
@@ -14820,6 +14923,10 @@ def_reduce_vars(AST_Class, function(tw, descend) {
14820
14923
  return true;
14821
14924
  });
14822
14925
 
14926
+ def_reduce_vars(AST_ClassStaticBlock, function(tw, descend, compressor) {
14927
+ reset_block_variables(compressor, this);
14928
+ });
14929
+
14823
14930
  def_reduce_vars(AST_Conditional, function(tw) {
14824
14931
  this.condition.walk(tw);
14825
14932
  push(tw);
@@ -16202,8 +16309,7 @@ function tighten_body(statements, compressor) {
16202
16309
  }
16203
16310
 
16204
16311
  function declarations_only(node) {
16205
- return node.definitions.every((var_def) => !var_def.value
16206
- );
16312
+ return node.definitions.every((var_def) => !var_def.value);
16207
16313
  }
16208
16314
 
16209
16315
  function sequencesize(statements, compressor) {
@@ -16249,7 +16355,7 @@ function tighten_body(statements, compressor) {
16249
16355
  var line = block.body[i];
16250
16356
  if (line instanceof AST_Var && declarations_only(line)) {
16251
16357
  decls.push(line);
16252
- } else if (stat) {
16358
+ } else if (stat || line instanceof AST_Const || line instanceof AST_Let) {
16253
16359
  return false;
16254
16360
  } else {
16255
16361
  stat = line;
@@ -16609,7 +16715,7 @@ function inline_into_symbolref(self, compressor) {
16609
16715
  }
16610
16716
  }
16611
16717
 
16612
- if (single_use && fixed instanceof AST_Lambda) {
16718
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
16613
16719
  single_use =
16614
16720
  def.scope === self.scope
16615
16721
  && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
@@ -16734,6 +16840,7 @@ function inline_into_call(self, fn, compressor) {
16734
16840
  fn.argnames.length === 1
16735
16841
  && (fn.argnames[0] instanceof AST_SymbolFunarg)
16736
16842
  && self.args.length < 2
16843
+ && !(self.args[0] instanceof AST_Expansion)
16737
16844
  && returned instanceof AST_SymbolRef
16738
16845
  && returned.name === fn.argnames[0].name
16739
16846
  ) {
@@ -17693,18 +17800,13 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
17693
17800
  }
17694
17801
  if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
17695
17802
  const def = node.name.definition();
17696
- let keep = def.global && !drop_funcs || in_use_ids.has(def.id);
17697
- if (!keep) {
17803
+ const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
17804
+ // Class "extends" and static blocks may have side effects
17805
+ const has_side_effects = !keep
17806
+ && node instanceof AST_Class
17807
+ && node.has_side_effects(compressor);
17808
+ if (!keep && !has_side_effects) {
17698
17809
  def.eliminated++;
17699
- if (node instanceof AST_DefClass) {
17700
- // Classes might have extends with side effects
17701
- const side_effects = node.drop_side_effect_free(compressor);
17702
- if (side_effects) {
17703
- return make_node(AST_SimpleStatement, node, {
17704
- body: side_effects
17705
- });
17706
- }
17707
- }
17708
17810
  return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
17709
17811
  }
17710
17812
  }
@@ -20783,6 +20885,11 @@ def_optimize(AST_Class, function(self) {
20783
20885
  return self;
20784
20886
  });
20785
20887
 
20888
+ def_optimize(AST_ClassStaticBlock, function(self, compressor) {
20889
+ tighten_body(self.body, compressor);
20890
+ return self;
20891
+ });
20892
+
20786
20893
  def_optimize(AST_Yield, function(self, compressor) {
20787
20894
  if (self.expression && !self.is_star && is_undefined(self.expression, compressor)) {
20788
20895
  self.expression = null;
@@ -27170,6 +27277,7 @@ var domprops = [
27170
27277
  "outlineStyle",
27171
27278
  "outlineWidth",
27172
27279
  "outputBuffer",
27280
+ "outputChannelCount",
27173
27281
  "outputLatency",
27174
27282
  "outputs",
27175
27283
  "overflow",
@@ -27257,6 +27365,7 @@ var domprops = [
27257
27365
  "palette",
27258
27366
  "pan",
27259
27367
  "panningModel",
27368
+ "parameterData",
27260
27369
  "parameters",
27261
27370
  "parent",
27262
27371
  "parentElement",
@@ -27432,6 +27541,7 @@ var domprops = [
27432
27541
  "processIceMessage",
27433
27542
  "processingEnd",
27434
27543
  "processingStart",
27544
+ "processorOptions",
27435
27545
  "product",
27436
27546
  "productId",
27437
27547
  "productName",
@@ -29872,7 +29982,9 @@ async function run_cli({ program, packageJson, fs, path }) {
29872
29982
  result.enclosed = value.block_scope.enclosed;
29873
29983
  }
29874
29984
  value.CTOR.PROPS.forEach(function(prop) {
29875
- result[prop] = value[prop];
29985
+ if (prop !== "block_scope") {
29986
+ result[prop] = value[prop];
29987
+ }
29876
29988
  });
29877
29989
  return result;
29878
29990
  }
package/lib/ast.js CHANGED
@@ -2272,6 +2272,28 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
2272
2272
  $documentation: "A class definition",
2273
2273
  }, AST_Class);
2274
2274
 
2275
+ var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
2276
+ this.body = props.body;
2277
+ this.block_scope = props.block_scope;
2278
+ this.start = props.start;
2279
+ this.end = props.end;
2280
+ }, {
2281
+ $documentation: "A block containing statements to be executed in the context of the class",
2282
+ $propdoc: {
2283
+ body: "[AST_Statement*] an array of statements",
2284
+ },
2285
+ _walk: function(visitor) {
2286
+ return visitor._visit(this, function() {
2287
+ walk_body(this, visitor);
2288
+ });
2289
+ },
2290
+ _children_backwards(push) {
2291
+ let i = this.body.length;
2292
+ while (i--) push(this.body[i]);
2293
+ },
2294
+ clone: clone_block_scope,
2295
+ }, AST_Scope);
2296
+
2275
2297
  var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
2276
2298
  if (props) {
2277
2299
  this.name = props.name;
@@ -3072,6 +3094,7 @@ export {
3072
3094
  AST_ClassExpression,
3073
3095
  AST_ClassPrivateProperty,
3074
3096
  AST_ClassProperty,
3097
+ AST_ClassStaticBlock,
3075
3098
  AST_ConciseMethod,
3076
3099
  AST_Conditional,
3077
3100
  AST_Const,
package/lib/cli.js CHANGED
@@ -279,7 +279,9 @@ export async function run_cli({ program, packageJson, fs, path }) {
279
279
  result.enclosed = value.block_scope.enclosed;
280
280
  }
281
281
  value.CTOR.PROPS.forEach(function(prop) {
282
- result[prop] = value[prop];
282
+ if (prop !== "block_scope") {
283
+ result[prop] = value[prop];
284
+ }
283
285
  });
284
286
  return result;
285
287
  }
@@ -271,8 +271,9 @@ export function is_ref_of(ref, type) {
271
271
  }
272
272
  }
273
273
 
274
- // Can we turn { block contents... } into just the block contents ?
275
- // Not if one of these is inside.
274
+ /**Can we turn { block contents... } into just the block contents ?
275
+ * Not if one of these is inside.
276
+ **/
276
277
  export function can_be_evicted_from_block(node) {
277
278
  return !(
278
279
  node instanceof AST_DefClass ||
@@ -50,6 +50,7 @@ import {
50
50
  AST_Call,
51
51
  AST_Chain,
52
52
  AST_Class,
53
+ AST_ClassStaticBlock,
53
54
  AST_ClassProperty,
54
55
  AST_ConciseMethod,
55
56
  AST_Conditional,
@@ -156,6 +157,14 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
156
157
  if (trimmed_extends)
157
158
  with_effects.push(trimmed_extends);
158
159
  for (const prop of this.properties) {
160
+ if (prop instanceof AST_ClassStaticBlock) {
161
+ if (prop.body.some(stat => stat.has_side_effects(compressor))) {
162
+ return this;
163
+ } else {
164
+ continue;
165
+ }
166
+ }
167
+
159
168
  const trimmed_prop = prop.drop_side_effect_free(compressor);
160
169
  if (trimmed_prop)
161
170
  with_effects.push(trimmed_prop);
@@ -58,6 +58,7 @@ import {
58
58
  AST_Class,
59
59
  AST_ClassExpression,
60
60
  AST_ClassProperty,
61
+ AST_ClassStaticBlock,
61
62
  AST_ConciseMethod,
62
63
  AST_Conditional,
63
64
  AST_Const,
@@ -833,18 +834,13 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
833
834
  }
834
835
  if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
835
836
  const def = node.name.definition();
836
- let keep = def.global && !drop_funcs || in_use_ids.has(def.id);
837
- if (!keep) {
837
+ const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
838
+ // Class "extends" and static blocks may have side effects
839
+ const has_side_effects = !keep
840
+ && node instanceof AST_Class
841
+ && node.has_side_effects(compressor);
842
+ if (!keep && !has_side_effects) {
838
843
  def.eliminated++;
839
- if (node instanceof AST_DefClass) {
840
- // Classes might have extends with side effects
841
- const side_effects = node.drop_side_effect_free(compressor);
842
- if (side_effects) {
843
- return make_node(AST_SimpleStatement, node, {
844
- body: side_effects
845
- });
846
- }
847
- }
848
844
  return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
849
845
  }
850
846
  }
@@ -3923,6 +3919,11 @@ def_optimize(AST_Class, function(self) {
3923
3919
  return self;
3924
3920
  });
3925
3921
 
3922
+ def_optimize(AST_ClassStaticBlock, function(self, compressor) {
3923
+ tighten_body(self.body, compressor);
3924
+ return self;
3925
+ });
3926
+
3926
3927
  def_optimize(AST_Yield, function(self, compressor) {
3927
3928
  if (self.expression && !self.is_star && is_undefined(self.expression, compressor)) {
3928
3929
  self.expression = null;
@@ -52,6 +52,8 @@ import {
52
52
  AST_Case,
53
53
  AST_Chain,
54
54
  AST_Class,
55
+ AST_DefClass,
56
+ AST_ClassStaticBlock,
55
57
  AST_ClassProperty,
56
58
  AST_ConciseMethod,
57
59
  AST_Conditional,
@@ -320,6 +322,9 @@ export function is_nullish(node, compressor) {
320
322
  }
321
323
  return any(this.properties, compressor);
322
324
  });
325
+ def_has_side_effects(AST_ClassStaticBlock, function(compressor) {
326
+ return any(this.body, compressor);
327
+ });
323
328
  def_has_side_effects(AST_Binary, function(compressor) {
324
329
  return this.left.has_side_effects(compressor)
325
330
  || this.right.has_side_effects(compressor);
@@ -419,6 +424,9 @@ export function is_nullish(node, compressor) {
419
424
  if (this.extends && this.extends.may_throw(compressor)) return true;
420
425
  return any(this.properties, compressor);
421
426
  });
427
+ def_may_throw(AST_ClassStaticBlock, function (compressor) {
428
+ return any(this.body, compressor);
429
+ });
422
430
 
423
431
  def_may_throw(AST_Array, function(compressor) {
424
432
  return any(this.elements, compressor);
@@ -587,6 +595,9 @@ export function is_nullish(node, compressor) {
587
595
  if (prop.static && prop.value && !prop.value.is_constant_expression(scope)) {
588
596
  return false;
589
597
  }
598
+ if (prop instanceof AST_ClassStaticBlock) {
599
+ return false;
600
+ }
590
601
  }
591
602
 
592
603
  return all_refs_local.call(this, scope);
@@ -910,9 +921,18 @@ export const aborts = (thing) => thing && thing.aborts();
910
921
  }
911
922
  return null;
912
923
  }
913
- def_aborts(AST_Import, function() { return null; });
924
+ def_aborts(AST_Import, return_null);
914
925
  def_aborts(AST_BlockStatement, block_aborts);
915
926
  def_aborts(AST_SwitchBranch, block_aborts);
927
+ def_aborts(AST_DefClass, function () {
928
+ for (const prop of this.properties) {
929
+ if (prop instanceof AST_ClassStaticBlock) {
930
+ if (prop.aborts()) return prop;
931
+ }
932
+ }
933
+ return null;
934
+ });
935
+ def_aborts(AST_ClassStaticBlock, block_aborts);
916
936
  def_aborts(AST_If, function() {
917
937
  return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
918
938
  });
@@ -210,7 +210,7 @@ export function inline_into_symbolref(self, compressor) {
210
210
  }
211
211
  }
212
212
 
213
- if (single_use && fixed instanceof AST_Lambda) {
213
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
214
214
  single_use =
215
215
  def.scope === self.scope
216
216
  && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
@@ -335,6 +335,7 @@ export function inline_into_call(self, fn, compressor) {
335
335
  fn.argnames.length === 1
336
336
  && (fn.argnames[0] instanceof AST_SymbolFunarg)
337
337
  && self.args.length < 2
338
+ && !(self.args[0] instanceof AST_Expansion)
338
339
  && returned instanceof AST_SymbolRef
339
340
  && returned.name === fn.argnames[0].name
340
341
  ) {
@@ -52,6 +52,7 @@ import {
52
52
  AST_Case,
53
53
  AST_Chain,
54
54
  AST_Class,
55
+ AST_ClassStaticBlock,
55
56
  AST_ClassExpression,
56
57
  AST_Conditional,
57
58
  AST_Default,
@@ -377,6 +378,10 @@ def_reduce_vars(AST_Class, function(tw, descend) {
377
378
  return true;
378
379
  });
379
380
 
381
+ def_reduce_vars(AST_ClassStaticBlock, function(tw, descend, compressor) {
382
+ reset_block_variables(compressor, this);
383
+ });
384
+
380
385
  def_reduce_vars(AST_Conditional, function(tw) {
381
386
  this.condition.walk(tw);
382
387
  push(tw);
@@ -1189,8 +1189,7 @@ export function tighten_body(statements, compressor) {
1189
1189
  }
1190
1190
 
1191
1191
  function declarations_only(node) {
1192
- return node.definitions.every((var_def) => !var_def.value
1193
- );
1192
+ return node.definitions.every((var_def) => !var_def.value);
1194
1193
  }
1195
1194
 
1196
1195
  function sequencesize(statements, compressor) {
@@ -1236,7 +1235,7 @@ export function tighten_body(statements, compressor) {
1236
1235
  var line = block.body[i];
1237
1236
  if (line instanceof AST_Var && declarations_only(line)) {
1238
1237
  decls.push(line);
1239
- } else if (stat) {
1238
+ } else if (stat || line instanceof AST_Const || line instanceof AST_Let) {
1240
1239
  return false;
1241
1240
  } else {
1242
1241
  stat = line;
@@ -60,6 +60,7 @@ import {
60
60
  AST_Catch,
61
61
  AST_Chain,
62
62
  AST_Class,
63
+ AST_ClassStaticBlock,
63
64
  AST_ClassExpression,
64
65
  AST_ClassProperty,
65
66
  AST_ClassPrivateProperty,
@@ -444,6 +445,14 @@ import { is_basic_identifier_string } from "./parse.js";
444
445
  });
445
446
  },
446
447
 
448
+ StaticBlock: function(M) {
449
+ return new AST_ClassStaticBlock({
450
+ start : my_start_token(M),
451
+ end : my_end_token(M),
452
+ body : M.body.map(from_moz),
453
+ });
454
+ },
455
+
447
456
  ArrayExpression: function(M) {
448
457
  return new AST_Array({
449
458
  start : my_start_token(M),
@@ -1583,6 +1592,13 @@ import { is_basic_identifier_string } from "./parse.js";
1583
1592
  };
1584
1593
  });
1585
1594
 
1595
+ def_to_moz(AST_ClassStaticBlock, function To_Moz_StaticBlock(M) {
1596
+ return {
1597
+ type: "StaticBlock",
1598
+ body: M.body.map(to_moz),
1599
+ };
1600
+ });
1601
+
1586
1602
  def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
1587
1603
  return {
1588
1604
  type: "MetaProperty",
package/lib/output.js CHANGED
@@ -70,6 +70,7 @@ import {
70
70
  AST_ClassExpression,
71
71
  AST_ClassPrivateProperty,
72
72
  AST_ClassProperty,
73
+ AST_ClassStaticBlock,
73
74
  AST_ConciseMethod,
74
75
  AST_PrivateGetter,
75
76
  AST_PrivateMethod,
@@ -254,7 +255,7 @@ function OutputStream(options) {
254
255
  if (options.shorthand === undefined)
255
256
  options.shorthand = options.ecma > 5;
256
257
 
257
- // Convert comment option to RegExp if neccessary and set up comments filter
258
+ // Convert comment option to RegExp if necessary and set up comments filter
258
259
  var comment_filter = return_false; // Default case, throw all comments away
259
260
  if (options.comments) {
260
261
  let comments = options.comments;
@@ -2194,6 +2195,11 @@ function OutputStream(options) {
2194
2195
  }
2195
2196
  self._print_getter_setter(type, false, output);
2196
2197
  });
2198
+ DEFPRINT(AST_ClassStaticBlock, function (self, output) {
2199
+ output.print("static");
2200
+ output.space();
2201
+ print_braced(self, output);
2202
+ });
2197
2203
  AST_Symbol.DEFMETHOD("_do_print", function(output) {
2198
2204
  var def = this.definition();
2199
2205
  output.print_name(def ? def.mangled_name || def.name : this.name);
package/lib/parse.js CHANGED
@@ -67,6 +67,7 @@ import {
67
67
  AST_ClassExpression,
68
68
  AST_ClassPrivateProperty,
69
69
  AST_ClassProperty,
70
+ AST_ClassStaticBlock,
70
71
  AST_ConciseMethod,
71
72
  AST_PrivateGetter,
72
73
  AST_PrivateMethod,
@@ -2562,6 +2563,10 @@ function parse($TEXT, options) {
2562
2563
  var accessor_type = null;
2563
2564
 
2564
2565
  if (is_class && name === "static" && is_not_method_start()) {
2566
+ const static_block = class_static_block();
2567
+ if (static_block != null) {
2568
+ return static_block;
2569
+ }
2565
2570
  is_static = true;
2566
2571
  name = as_property_name();
2567
2572
  }
@@ -2668,6 +2673,25 @@ function parse($TEXT, options) {
2668
2673
  }
2669
2674
  }
2670
2675
 
2676
+ function class_static_block() {
2677
+ if (!is("punc", "{")) {
2678
+ return null;
2679
+ }
2680
+
2681
+ const start = S.token;
2682
+ const body = [];
2683
+
2684
+ next();
2685
+
2686
+ while (!is("punc", "}")) {
2687
+ body.push(statement());
2688
+ }
2689
+
2690
+ next();
2691
+
2692
+ return new AST_ClassStaticBlock({ start, body, end: prev() });
2693
+ }
2694
+
2671
2695
  function maybe_import_assertion() {
2672
2696
  if (is("name", "assert") && !has_newline_before(S.token)) {
2673
2697
  next();
@@ -2777,14 +2801,14 @@ function parse($TEXT, options) {
2777
2801
  var end = prev();
2778
2802
 
2779
2803
  name = name || new type({
2780
- name: "*",
2781
2804
  start: start,
2805
+ name: "*",
2782
2806
  end: end,
2783
2807
  });
2784
2808
 
2785
2809
  foreign_name = new foreign_type({
2786
- name: "*",
2787
2810
  start: start,
2811
+ name: "*",
2788
2812
  end: end,
2789
2813
  });
2790
2814
 
package/lib/size.js CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  AST_Call,
11
11
  AST_Case,
12
12
  AST_Class,
13
+ AST_ClassStaticBlock,
13
14
  AST_ClassPrivateProperty,
14
15
  AST_ClassProperty,
15
16
  AST_ConciseMethod,
@@ -401,6 +402,11 @@ AST_Class.prototype._size = function () {
401
402
  );
402
403
  };
403
404
 
405
+ AST_ClassStaticBlock.prototype._size = function () {
406
+ // "class{}" + semicolons
407
+ return 7 + list_overhead(this.body);
408
+ };
409
+
404
410
  AST_ClassProperty.prototype._size = function () {
405
411
  return (
406
412
  static_size(this.static)
package/lib/transform.js CHANGED
@@ -53,6 +53,7 @@ import {
53
53
  AST_Catch,
54
54
  AST_Chain,
55
55
  AST_Class,
56
+ AST_ClassStaticBlock,
56
57
  AST_Conditional,
57
58
  AST_Definitions,
58
59
  AST_Destructuring,
@@ -285,6 +286,10 @@ def_transform(AST_Class, function(self, tw) {
285
286
  self.properties = do_list(self.properties, tw);
286
287
  });
287
288
 
289
+ def_transform(AST_ClassStaticBlock, function(self, tw) {
290
+ self.body = do_list(self.body, tw);
291
+ });
292
+
288
293
  def_transform(AST_Expansion, function(self, tw) {
289
294
  self.expression = self.expression.transform(tw);
290
295
  });
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AST_Binary,
3
3
  AST_Conditional,
4
+ AST_Chain,
4
5
  AST_Dot,
5
6
  AST_Object,
6
7
  AST_Sequence,
@@ -23,6 +24,7 @@ function first_in_statement(stack) {
23
24
  (p instanceof AST_PrefixedTemplateString && p.prefix === node) ||
24
25
  (p instanceof AST_Dot && p.expression === node) ||
25
26
  (p instanceof AST_Sub && p.expression === node) ||
27
+ (p instanceof AST_Chain && p.expression === node) ||
26
28
  (p instanceof AST_Conditional && p.condition === node) ||
27
29
  (p instanceof AST_Binary && p.left === node) ||
28
30
  (p instanceof AST_UnaryPostfix && p.expression === node)
@@ -41,6 +43,7 @@ function left_is_object(node) {
41
43
  if (node.TYPE === "Call") return left_is_object(node.expression);
42
44
  if (node instanceof AST_PrefixedTemplateString) return left_is_object(node.prefix);
43
45
  if (node instanceof AST_Dot || node instanceof AST_Sub) return left_is_object(node.expression);
46
+ if (node instanceof AST_Chain) return left_is_object(node.expression);
44
47
  if (node instanceof AST_Conditional) return left_is_object(node.condition);
45
48
  if (node instanceof AST_Binary) return left_is_object(node.left);
46
49
  if (node instanceof AST_UnaryPostfix) return left_is_object(node.expression);
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.14.2",
7
+ "version": "5.15.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
package/tools/domprops.js CHANGED
@@ -6021,6 +6021,7 @@ export var domprops = [
6021
6021
  "outlineStyle",
6022
6022
  "outlineWidth",
6023
6023
  "outputBuffer",
6024
+ "outputChannelCount",
6024
6025
  "outputLatency",
6025
6026
  "outputs",
6026
6027
  "overflow",
@@ -6108,6 +6109,7 @@ export var domprops = [
6108
6109
  "palette",
6109
6110
  "pan",
6110
6111
  "panningModel",
6112
+ "parameterData",
6111
6113
  "parameters",
6112
6114
  "parent",
6113
6115
  "parentElement",
@@ -6283,6 +6285,7 @@ export var domprops = [
6283
6285
  "processIceMessage",
6284
6286
  "processingEnd",
6285
6287
  "processingStart",
6288
+ "processorOptions",
6286
6289
  "product",
6287
6290
  "productId",
6288
6291
  "productName",