terser 5.19.0 → 5.19.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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.19.1
4
+ - Better avoid outputting `</script>` and HTML comments.
5
+ - Fix unused variables in class static blocks not being dropped correctly.
6
+ - Fix sourcemap names of methods that are `async` or `static`
7
+
3
8
  ## v5.19.0
4
9
  - Allow `/*@__MANGLE_PROP__*/` annotation in `object.property`, in addition to property declarations.
5
10
 
@@ -8954,6 +8954,18 @@ class Rope {
8954
8954
  this.current += str;
8955
8955
  }
8956
8956
 
8957
+ endsWith(str) {
8958
+ const { committed, current } = this;
8959
+ const len = str.length;
8960
+ if (committed.length >= len) {
8961
+ return committed.slice(committed.length - str.length) === str;
8962
+ } else {
8963
+ // `str` is small and this is a rare case so keep it simple
8964
+ const last_bit = committed.slice(-len) + current;
8965
+ return last_bit.endsWith(str);
8966
+ }
8967
+ }
8968
+
8957
8969
  insertAt(char, index) {
8958
8970
  const { committed, current } = this;
8959
8971
  if (index < committed.length) {
@@ -9162,10 +9174,12 @@ function OutputStream(options) {
9162
9174
  mappings.forEach(function(mapping) {
9163
9175
  try {
9164
9176
  let { name, token } = mapping;
9165
- if (token.type == "name" || token.type === "privatename") {
9166
- name = token.value;
9167
- } else if (name instanceof AST_Symbol) {
9168
- name = token.type === "string" ? token.value : name.name;
9177
+ if (name !== false) {
9178
+ if (token.type == "name" || token.type === "privatename") {
9179
+ name = token.value;
9180
+ } else if (name instanceof AST_Symbol) {
9181
+ name = token.type === "string" ? token.value : name.name;
9182
+ }
9169
9183
  }
9170
9184
  options.source_map.add(
9171
9185
  mapping.token.file,
@@ -9333,6 +9347,10 @@ function OutputStream(options) {
9333
9347
  might_need_semicolon = true;
9334
9348
  };
9335
9349
 
9350
+ function ends_with(str) {
9351
+ return OUTPUT.endsWith(str);
9352
+ }
9353
+
9336
9354
  function force_semicolon() {
9337
9355
  might_need_semicolon = false;
9338
9356
  print(";");
@@ -9602,6 +9620,7 @@ function OutputStream(options) {
9602
9620
  comma : comma,
9603
9621
  colon : colon,
9604
9622
  last : function() { return last; },
9623
+ ends_with : ends_with,
9605
9624
  semicolon : semicolon,
9606
9625
  force_semicolon : force_semicolon,
9607
9626
  to_utf8 : to_utf8,
@@ -10725,6 +10744,9 @@ function OutputStream(options) {
10725
10744
  });
10726
10745
  DEFPRINT(AST_UnaryPrefix, function(self, output) {
10727
10746
  var op = self.operator;
10747
+ if (op === "--" && output.ends_with("<!")) {
10748
+ output.print(" ");
10749
+ }
10728
10750
  output.print(op);
10729
10751
  if (/^[a-z]/i.test(op)
10730
10752
  || (/[+-]$/.test(op)
@@ -10742,8 +10764,7 @@ function OutputStream(options) {
10742
10764
  var op = self.operator;
10743
10765
  self.left.print(output);
10744
10766
  if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
10745
- && self.left instanceof AST_UnaryPostfix
10746
- && self.left.operator == "--") {
10767
+ && output.ends_with("--")) {
10747
10768
  // space is mandatory to avoid outputting -->
10748
10769
  output.print(" ");
10749
10770
  } else {
@@ -10751,17 +10772,7 @@ function OutputStream(options) {
10751
10772
  output.space();
10752
10773
  }
10753
10774
  output.print(op);
10754
- if ((op == "<" || op == "<<")
10755
- && self.right instanceof AST_UnaryPrefix
10756
- && self.right.operator == "!"
10757
- && self.right.expression instanceof AST_UnaryPrefix
10758
- && self.right.expression.operator == "--") {
10759
- // space is mandatory to avoid outputting <!--
10760
- output.print(" ");
10761
- } else {
10762
- // the space is optional depending on "beautify"
10763
- output.space();
10764
- }
10775
+ output.space();
10765
10776
  self.right.print(output);
10766
10777
  });
10767
10778
  DEFPRINT(AST_Conditional, function(self, output) {
@@ -10974,6 +10985,7 @@ function OutputStream(options) {
10974
10985
  if (self.key instanceof AST_SymbolMethod) {
10975
10986
  if (is_private) output.print("#");
10976
10987
  print_property_name(self.key.name, self.quote, output);
10988
+ self.key.add_source_map(output);
10977
10989
  } else {
10978
10990
  output.with_square(function() {
10979
10991
  self.key.print(output);
@@ -11062,12 +11074,18 @@ function OutputStream(options) {
11062
11074
  });
11063
11075
 
11064
11076
  const r_slash_script = /(<\s*\/\s*script)/i;
11077
+ const r_starts_with_script = /^\s*script/i;
11065
11078
  const slash_script_replace = (_, $1) => $1.replace("/", "\\/");
11066
11079
  DEFPRINT(AST_RegExp, function(self, output) {
11067
11080
  let { source, flags } = self.getValue();
11068
11081
  source = regexp_source_fix(source);
11069
11082
  flags = flags ? sort_regexp_flags(flags) : "";
11083
+
11084
+ // Avoid outputting end of script tag
11070
11085
  source = source.replace(r_slash_script, slash_script_replace);
11086
+ if (r_starts_with_script.test(source) && output.ends_with("<")) {
11087
+ output.print(" ");
11088
+ }
11071
11089
 
11072
11090
  output.print(output.to_utf8(`/${source}/${flags}`, false, true));
11073
11091
 
@@ -11191,8 +11209,22 @@ function OutputStream(options) {
11191
11209
  AST_ObjectSetter,
11192
11210
  AST_PrivateGetter,
11193
11211
  AST_PrivateSetter,
11212
+ AST_ConciseMethod,
11213
+ AST_PrivateMethod,
11194
11214
  ], function(output) {
11195
- output.add_mapping(this.key.end, this.key.name);
11215
+ output.add_mapping(this.start, false /*name handled below*/);
11216
+ });
11217
+
11218
+ DEFMAP([
11219
+ AST_SymbolMethod,
11220
+ AST_SymbolPrivateProperty
11221
+ ], function(output) {
11222
+ const tok_type = this.end && this.end.type;
11223
+ if (tok_type === "name" || tok_type === "privatename") {
11224
+ output.add_mapping(this.end, this.name);
11225
+ } else {
11226
+ output.add_mapping(this.end);
11227
+ }
11196
11228
  });
11197
11229
 
11198
11230
  DEFMAP([ AST_ObjectProperty ], function(output) {
@@ -15281,21 +15313,24 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15281
15313
  }
15282
15314
  }
15283
15315
  }
15284
- if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
15316
+ if (node instanceof AST_DefClass && node !== self) {
15317
+ const def = node.name.definition();
15318
+ descend(node, this);
15319
+ const keep_class = def.global && !drop_funcs || in_use_ids.has(def.id);
15320
+ if (!keep_class) {
15321
+ const kept = node.drop_side_effect_free(compressor);
15322
+ if (kept == null) {
15323
+ def.eliminated++;
15324
+ return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
15325
+ }
15326
+ return kept;
15327
+ }
15328
+ return node;
15329
+ }
15330
+ if (node instanceof AST_Defun && node !== self) {
15285
15331
  const def = node.name.definition();
15286
15332
  const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
15287
15333
  if (!keep) {
15288
- // Class "extends" and static blocks may have side effects
15289
- if (node instanceof AST_Class) {
15290
- const kept = node.drop_side_effect_free(compressor);
15291
- if (kept !== node) {
15292
- def.eliminated++;
15293
- if (kept) return kept;
15294
- return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
15295
- } else {
15296
- return kept;
15297
- }
15298
- }
15299
15334
  def.eliminated++;
15300
15335
  return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
15301
15336
  }
@@ -273,21 +273,24 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
273
273
  }
274
274
  }
275
275
  }
276
- if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
276
+ if (node instanceof AST_DefClass && node !== self) {
277
+ const def = node.name.definition();
278
+ descend(node, this);
279
+ const keep_class = def.global && !drop_funcs || in_use_ids.has(def.id);
280
+ if (!keep_class) {
281
+ const kept = node.drop_side_effect_free(compressor);
282
+ if (kept == null) {
283
+ def.eliminated++;
284
+ return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
285
+ }
286
+ return kept;
287
+ }
288
+ return node;
289
+ }
290
+ if (node instanceof AST_Defun && node !== self) {
277
291
  const def = node.name.definition();
278
292
  const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
279
293
  if (!keep) {
280
- // Class "extends" and static blocks may have side effects
281
- if (node instanceof AST_Class) {
282
- const kept = node.drop_side_effect_free(compressor);
283
- if (kept !== node) {
284
- def.eliminated++;
285
- if (kept) return kept;
286
- return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
287
- } else {
288
- return kept;
289
- }
290
- }
291
294
  def.eliminated++;
292
295
  return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
293
296
  }
package/lib/output.js CHANGED
@@ -190,6 +190,18 @@ class Rope {
190
190
  this.current += str;
191
191
  }
192
192
 
193
+ endsWith(str) {
194
+ const { committed, current } = this;
195
+ const len = str.length;
196
+ if (committed.length >= len) {
197
+ return committed.slice(committed.length - str.length) === str;
198
+ } else {
199
+ // `str` is small and this is a rare case so keep it simple
200
+ const last_bit = committed.slice(-len) + current;
201
+ return last_bit.endsWith(str);
202
+ }
203
+ }
204
+
193
205
  insertAt(char, index) {
194
206
  const { committed, current } = this;
195
207
  if (index < committed.length) {
@@ -398,10 +410,12 @@ function OutputStream(options) {
398
410
  mappings.forEach(function(mapping) {
399
411
  try {
400
412
  let { name, token } = mapping;
401
- if (token.type == "name" || token.type === "privatename") {
402
- name = token.value;
403
- } else if (name instanceof AST_Symbol) {
404
- name = token.type === "string" ? token.value : name.name;
413
+ if (name !== false) {
414
+ if (token.type == "name" || token.type === "privatename") {
415
+ name = token.value;
416
+ } else if (name instanceof AST_Symbol) {
417
+ name = token.type === "string" ? token.value : name.name;
418
+ }
405
419
  }
406
420
  options.source_map.add(
407
421
  mapping.token.file,
@@ -569,6 +583,10 @@ function OutputStream(options) {
569
583
  might_need_semicolon = true;
570
584
  };
571
585
 
586
+ function ends_with(str) {
587
+ return OUTPUT.endsWith(str);
588
+ }
589
+
572
590
  function force_semicolon() {
573
591
  might_need_semicolon = false;
574
592
  print(";");
@@ -838,6 +856,7 @@ function OutputStream(options) {
838
856
  comma : comma,
839
857
  colon : colon,
840
858
  last : function() { return last; },
859
+ ends_with : ends_with,
841
860
  semicolon : semicolon,
842
861
  force_semicolon : force_semicolon,
843
862
  to_utf8 : to_utf8,
@@ -1961,6 +1980,9 @@ function OutputStream(options) {
1961
1980
  });
1962
1981
  DEFPRINT(AST_UnaryPrefix, function(self, output) {
1963
1982
  var op = self.operator;
1983
+ if (op === "--" && output.ends_with("<!")) {
1984
+ output.print(" ");
1985
+ }
1964
1986
  output.print(op);
1965
1987
  if (/^[a-z]/i.test(op)
1966
1988
  || (/[+-]$/.test(op)
@@ -1978,8 +2000,7 @@ function OutputStream(options) {
1978
2000
  var op = self.operator;
1979
2001
  self.left.print(output);
1980
2002
  if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
1981
- && self.left instanceof AST_UnaryPostfix
1982
- && self.left.operator == "--") {
2003
+ && output.ends_with("--")) {
1983
2004
  // space is mandatory to avoid outputting -->
1984
2005
  output.print(" ");
1985
2006
  } else {
@@ -1987,17 +2008,7 @@ function OutputStream(options) {
1987
2008
  output.space();
1988
2009
  }
1989
2010
  output.print(op);
1990
- if ((op == "<" || op == "<<")
1991
- && self.right instanceof AST_UnaryPrefix
1992
- && self.right.operator == "!"
1993
- && self.right.expression instanceof AST_UnaryPrefix
1994
- && self.right.expression.operator == "--") {
1995
- // space is mandatory to avoid outputting <!--
1996
- output.print(" ");
1997
- } else {
1998
- // the space is optional depending on "beautify"
1999
- output.space();
2000
- }
2011
+ output.space();
2001
2012
  self.right.print(output);
2002
2013
  });
2003
2014
  DEFPRINT(AST_Conditional, function(self, output) {
@@ -2210,6 +2221,7 @@ function OutputStream(options) {
2210
2221
  if (self.key instanceof AST_SymbolMethod) {
2211
2222
  if (is_private) output.print("#");
2212
2223
  print_property_name(self.key.name, self.quote, output);
2224
+ self.key.add_source_map(output);
2213
2225
  } else {
2214
2226
  output.with_square(function() {
2215
2227
  self.key.print(output);
@@ -2298,12 +2310,18 @@ function OutputStream(options) {
2298
2310
  });
2299
2311
 
2300
2312
  const r_slash_script = /(<\s*\/\s*script)/i;
2313
+ const r_starts_with_script = /^\s*script/i;
2301
2314
  const slash_script_replace = (_, $1) => $1.replace("/", "\\/");
2302
2315
  DEFPRINT(AST_RegExp, function(self, output) {
2303
2316
  let { source, flags } = self.getValue();
2304
2317
  source = regexp_source_fix(source);
2305
2318
  flags = flags ? sort_regexp_flags(flags) : "";
2319
+
2320
+ // Avoid outputting end of script tag
2306
2321
  source = source.replace(r_slash_script, slash_script_replace);
2322
+ if (r_starts_with_script.test(source) && output.ends_with("<")) {
2323
+ output.print(" ");
2324
+ }
2307
2325
 
2308
2326
  output.print(output.to_utf8(`/${source}/${flags}`, false, true));
2309
2327
 
@@ -2427,8 +2445,22 @@ function OutputStream(options) {
2427
2445
  AST_ObjectSetter,
2428
2446
  AST_PrivateGetter,
2429
2447
  AST_PrivateSetter,
2448
+ AST_ConciseMethod,
2449
+ AST_PrivateMethod,
2430
2450
  ], function(output) {
2431
- output.add_mapping(this.key.end, this.key.name);
2451
+ output.add_mapping(this.start, false /*name handled below*/);
2452
+ });
2453
+
2454
+ DEFMAP([
2455
+ AST_SymbolMethod,
2456
+ AST_SymbolPrivateProperty
2457
+ ], function(output) {
2458
+ const tok_type = this.end && this.end.type;
2459
+ if (tok_type === "name" || tok_type === "privatename") {
2460
+ output.add_mapping(this.end, this.name);
2461
+ } else {
2462
+ output.add_mapping(this.end);
2463
+ }
2432
2464
  });
2433
2465
 
2434
2466
  DEFMAP([ AST_ObjectProperty ], function(output) {
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.19.0",
7
+ "version": "5.19.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },