terser 5.33.0 → 5.34.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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.34.1
4
+
5
+ - bump the rollup devDependency to disable CVE warnings (Terser was not affected)
6
+
7
+ ## v5.34.0
8
+
9
+ - internal: stop assigning properties to objects they don't belong in
10
+ - internal: run compress tests in parallel
11
+ - `drop_console`: emit an empty function if the return value of `console.METHOD(...)` may be called.
12
+
3
13
  ## v5.33.0
4
14
 
5
15
  - `reduce_vars` improved when dealing with hoisted function definitions (#1544)
@@ -2,7 +2,7 @@
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@jridgewell/source-map')) :
3
3
  typeof define === 'function' && define.amd ? define(['exports', '@jridgewell/source-map'], factory) :
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Terser = {}, global.sourceMap));
5
- }(this, (function (exports, sourceMap) { 'use strict';
5
+ })(this, (function (exports, sourceMap) { 'use strict';
6
6
 
7
7
  /***********************************************************************
8
8
 
@@ -11674,7 +11674,7 @@ function redefined_catch_def(def) {
11674
11674
  }
11675
11675
  }
11676
11676
 
11677
- AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null, toplevel = this } = {}) {
11677
+ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = undefined, toplevel = this } = {}) {
11678
11678
  options = defaults(options, {
11679
11679
  cache: null,
11680
11680
  ie8: false,
@@ -11998,7 +11998,7 @@ AST_Scope.DEFMETHOD("add_child_scope", function (scope) {
11998
11998
  scope.parent_scope = this;
11999
11999
 
12000
12000
  // Propagate to this.uses_arguments from arrow functions
12001
- if ((scope instanceof AST_Arrow) && !this.uses_arguments) {
12001
+ if ((scope instanceof AST_Arrow) && (this instanceof AST_Lambda && !this.uses_arguments)) {
12002
12002
  this.uses_arguments = walk(scope, node => {
12003
12003
  if (
12004
12004
  node instanceof AST_SymbolRef
@@ -13065,6 +13065,23 @@ function make_sequence(orig, expressions) {
13065
13065
  });
13066
13066
  }
13067
13067
 
13068
+ function make_empty_function(self) {
13069
+ return make_node(AST_Function, self, {
13070
+ uses_arguments: false,
13071
+ argnames: [],
13072
+ body: [],
13073
+ is_generator: false,
13074
+ async: false,
13075
+ variables: new Map(),
13076
+ uses_with: false,
13077
+ uses_eval: false,
13078
+ parent_scope: null,
13079
+ enclosed: [],
13080
+ cname: 0,
13081
+ block_scope: undefined,
13082
+ });
13083
+ }
13084
+
13068
13085
  function make_node_from_constant(val, orig) {
13069
13086
  switch (typeof val) {
13070
13087
  case "string":
@@ -14418,6 +14435,54 @@ function is_modified(compressor, tw, node, value, level, immutable) {
14418
14435
  }
14419
14436
  }
14420
14437
 
14438
+ /**
14439
+ * Check if a node may be used by the expression it's in
14440
+ * void (0, 1, {node}, 2) -> false
14441
+ * console.log(0, {node}) -> true
14442
+ */
14443
+ function is_used_in_expression(tw) {
14444
+ for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
14445
+ if (parent instanceof AST_Sequence) {
14446
+ const nth_expression = parent.expressions.indexOf(node);
14447
+ if (nth_expression !== parent.expressions.length - 1) {
14448
+ // Detect (0, x.noThis)() constructs
14449
+ const grandparent = tw.parent(p + 2);
14450
+ if (
14451
+ parent.expressions.length > 2
14452
+ || parent.expressions.length === 1
14453
+ || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
14454
+ ) {
14455
+ return false;
14456
+ }
14457
+ return true;
14458
+ } else {
14459
+ continue;
14460
+ }
14461
+ }
14462
+ if (parent instanceof AST_Unary) {
14463
+ const op = parent.operator;
14464
+ if (op === "void") {
14465
+ return false;
14466
+ }
14467
+ if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
14468
+ continue;
14469
+ }
14470
+ }
14471
+ if (
14472
+ parent instanceof AST_SimpleStatement
14473
+ || parent instanceof AST_LabeledStatement
14474
+ ) {
14475
+ return false;
14476
+ }
14477
+ if (parent instanceof AST_Scope) {
14478
+ return false;
14479
+ }
14480
+ return true;
14481
+ }
14482
+
14483
+ return true;
14484
+ }
14485
+
14421
14486
  /***********************************************************************
14422
14487
 
14423
14488
  A JavaScript tokenizer / parser / beautifier / compressor.
@@ -15672,45 +15737,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15672
15737
  }
15673
15738
  });
15674
15739
 
15675
- /**
15676
- * Check if a node may be used by the expression it's in
15677
- * void (0, 1, {node}, 2) -> false
15678
- * console.log(0, {node}) -> true
15679
- */
15680
- function is_used_in_expression(tw) {
15681
- for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
15682
- if (parent instanceof AST_Sequence) {
15683
- const nth_expression = parent.expressions.indexOf(node);
15684
- if (nth_expression !== parent.expressions.length - 1) {
15685
- // Detect (0, x.noThis)() constructs
15686
- const grandparent = tw.parent(p + 2);
15687
- if (
15688
- parent.expressions.length > 2
15689
- || parent.expressions.length === 1
15690
- || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
15691
- ) {
15692
- return false;
15693
- }
15694
- return true;
15695
- } else {
15696
- continue;
15697
- }
15698
- }
15699
- if (parent instanceof AST_Unary) {
15700
- const op = parent.operator;
15701
- if (op === "void") {
15702
- return false;
15703
- }
15704
- if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
15705
- continue;
15706
- }
15707
- }
15708
- return true;
15709
- }
15710
-
15711
- return true;
15712
- }
15713
-
15714
15740
  /***********************************************************************
15715
15741
 
15716
15742
  A JavaScript tokenizer / parser / beautifier / compressor.
@@ -18935,9 +18961,8 @@ def_optimize(AST_Node, function(self) {
18935
18961
  });
18936
18962
 
18937
18963
  AST_Toplevel.DEFMETHOD("drop_console", function(options) {
18938
- var isArray = Array.isArray(options);
18939
-
18940
- return this.transform(new TreeTransformer(function(self) {
18964
+ const isArray = Array.isArray(options);
18965
+ const tt = new TreeTransformer(function(self) {
18941
18966
  if (self.TYPE !== "Call") {
18942
18967
  return;
18943
18968
  }
@@ -18948,18 +18973,35 @@ AST_Toplevel.DEFMETHOD("drop_console", function(options) {
18948
18973
  return;
18949
18974
  }
18950
18975
 
18951
- if (isArray && options.indexOf(exp.property) === -1) {
18976
+ if (isArray && !options.includes(exp.property)) {
18952
18977
  return;
18953
18978
  }
18954
18979
 
18955
18980
  var name = exp.expression;
18981
+ var depth = 2;
18956
18982
  while (name.expression) {
18957
18983
  name = name.expression;
18984
+ depth++;
18958
18985
  }
18986
+
18959
18987
  if (is_undeclared_ref(name) && name.name == "console") {
18960
- return make_node(AST_Undefined, self);
18988
+ if (
18989
+ depth === 3
18990
+ && !["call", "apply"].includes(exp.property)
18991
+ && is_used_in_expression(tt)
18992
+ ) {
18993
+ // a (used) call to Function.prototype methods (eg: console.log.bind(console))
18994
+ // but not .call and .apply which would also return undefined.
18995
+ exp.expression = make_empty_function(self);
18996
+ set_flag(exp.expression, SQUEEZED);
18997
+ self.args = [];
18998
+ } else {
18999
+ return make_node(AST_Undefined, self);
19000
+ }
18961
19001
  }
18962
- }));
19002
+ });
19003
+
19004
+ return this.transform(tt);
18963
19005
  });
18964
19006
 
18965
19007
  AST_Node.DEFMETHOD("equivalent_to", function(node) {
@@ -20336,10 +20378,7 @@ def_optimize(AST_Call, function(self, compressor) {
20336
20378
  && is_undeclared_ref(exp)
20337
20379
  && exp.name == "Function") {
20338
20380
  // new Function() => function(){}
20339
- if (self.args.length == 0) return make_node(AST_Function, self, {
20340
- argnames: [],
20341
- body: []
20342
- }).optimize(compressor);
20381
+ if (self.args.length == 0) return make_empty_function(self).optimize(compressor);
20343
20382
  if (self.args.every((x) => x instanceof AST_String)) {
20344
20383
  // quite a corner-case, but we can handle it:
20345
20384
  // https://github.com/mishoo/UglifyJS2/issues/203
@@ -22099,10 +22138,7 @@ def_optimize(AST_Dot, function(self, compressor) {
22099
22138
  });
22100
22139
  break;
22101
22140
  case "Function":
22102
- self.expression = make_node(AST_Function, self.expression, {
22103
- argnames: [],
22104
- body: []
22105
- });
22141
+ self.expression = make_empty_function(self.expression);
22106
22142
  break;
22107
22143
  case "Number":
22108
22144
  self.expression = make_node(AST_Number, self.expression, {
@@ -31647,7 +31683,9 @@ function mangle_properties(ast, options, annotated_props = find_annotated_props(
31647
31683
  } else if (node instanceof AST_ObjectProperty) {
31648
31684
  // setter, getter, method or class field
31649
31685
  if (!keep_quoted || !node.quote) {
31650
- node.key.name = mangle(node.key.name);
31686
+ if (!node.computed_key()) {
31687
+ node.key.name = mangle(node.key.name);
31688
+ }
31651
31689
  }
31652
31690
  } else if (node instanceof AST_Dot) {
31653
31691
  if (!keep_quoted || !node.quote) {
@@ -32024,7 +32062,7 @@ function* minify_sync_or_async(files, options, _fs_module) {
32024
32062
  if (node.block_scope) {
32025
32063
  node.block_scope.variables = undefined;
32026
32064
  node.block_scope.enclosed = undefined;
32027
- node.parent_scope = undefined;
32065
+ node.block_scope.parent_scope = undefined;
32028
32066
  }
32029
32067
  });
32030
32068
  }
@@ -32616,4 +32654,4 @@ exports._run_cli = run_cli;
32616
32654
  exports.minify = minify;
32617
32655
  exports.minify_sync = minify_sync;
32618
32656
 
32619
- })));
32657
+ }));
@@ -107,6 +107,23 @@ export function make_sequence(orig, expressions) {
107
107
  });
108
108
  }
109
109
 
110
+ export function make_empty_function(self) {
111
+ return make_node(AST_Function, self, {
112
+ uses_arguments: false,
113
+ argnames: [],
114
+ body: [],
115
+ is_generator: false,
116
+ async: false,
117
+ variables: new Map(),
118
+ uses_with: false,
119
+ uses_eval: false,
120
+ parent_scope: null,
121
+ enclosed: [],
122
+ cname: 0,
123
+ block_scope: undefined,
124
+ });
125
+ }
126
+
110
127
  export function make_node_from_constant(val, orig) {
111
128
  switch (typeof val) {
112
129
  case "string":
@@ -103,8 +103,8 @@ import {
103
103
  is_empty,
104
104
  is_ref_of,
105
105
  can_be_evicted_from_block,
106
- requires_sequence_to_maintain_binding,
107
106
  } from "./common.js";
107
+ import { is_used_in_expression } from "./inference.js";
108
108
 
109
109
  const r_keep_assign = /keep_assign/;
110
110
 
@@ -503,42 +503,3 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
503
503
  }
504
504
  }
505
505
  });
506
-
507
- /**
508
- * Check if a node may be used by the expression it's in
509
- * void (0, 1, {node}, 2) -> false
510
- * console.log(0, {node}) -> true
511
- */
512
- function is_used_in_expression(tw) {
513
- for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
514
- if (parent instanceof AST_Sequence) {
515
- const nth_expression = parent.expressions.indexOf(node);
516
- if (nth_expression !== parent.expressions.length - 1) {
517
- // Detect (0, x.noThis)() constructs
518
- const grandparent = tw.parent(p + 2);
519
- if (
520
- parent.expressions.length > 2
521
- || parent.expressions.length === 1
522
- || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
523
- ) {
524
- return false;
525
- }
526
- return true;
527
- } else {
528
- continue;
529
- }
530
- }
531
- if (parent instanceof AST_Unary) {
532
- const op = parent.operator;
533
- if (op === "void") {
534
- return false;
535
- }
536
- if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
537
- continue;
538
- }
539
- }
540
- return true;
541
- }
542
-
543
- return true;
544
- }
@@ -176,6 +176,7 @@ import {
176
176
  is_undefined,
177
177
  is_lhs,
178
178
  aborts,
179
+ is_used_in_expression,
179
180
  } from "./inference.js";
180
181
  import {
181
182
  SQUEEZED,
@@ -195,6 +196,7 @@ import {
195
196
  make_sequence,
196
197
  best_of,
197
198
  best_of_expression,
199
+ make_empty_function,
198
200
  make_node_from_constant,
199
201
  merge_sequence,
200
202
  get_simple_key,
@@ -510,9 +512,8 @@ def_optimize(AST_Node, function(self) {
510
512
  });
511
513
 
512
514
  AST_Toplevel.DEFMETHOD("drop_console", function(options) {
513
- var isArray = Array.isArray(options);
514
-
515
- return this.transform(new TreeTransformer(function(self) {
515
+ const isArray = Array.isArray(options);
516
+ const tt = new TreeTransformer(function(self) {
516
517
  if (self.TYPE !== "Call") {
517
518
  return;
518
519
  }
@@ -523,18 +524,35 @@ AST_Toplevel.DEFMETHOD("drop_console", function(options) {
523
524
  return;
524
525
  }
525
526
 
526
- if (isArray && options.indexOf(exp.property) === -1) {
527
+ if (isArray && !options.includes(exp.property)) {
527
528
  return;
528
529
  }
529
530
 
530
531
  var name = exp.expression;
532
+ var depth = 2;
531
533
  while (name.expression) {
532
534
  name = name.expression;
535
+ depth++;
533
536
  }
537
+
534
538
  if (is_undeclared_ref(name) && name.name == "console") {
535
- return make_node(AST_Undefined, self);
539
+ if (
540
+ depth === 3
541
+ && !["call", "apply"].includes(exp.property)
542
+ && is_used_in_expression(tt)
543
+ ) {
544
+ // a (used) call to Function.prototype methods (eg: console.log.bind(console))
545
+ // but not .call and .apply which would also return undefined.
546
+ exp.expression = make_empty_function(self);
547
+ set_flag(exp.expression, SQUEEZED);
548
+ self.args = [];
549
+ } else {
550
+ return make_node(AST_Undefined, self);
551
+ }
536
552
  }
537
- }));
553
+ });
554
+
555
+ return this.transform(tt);
538
556
  });
539
557
 
540
558
  AST_Node.DEFMETHOD("equivalent_to", function(node) {
@@ -1911,10 +1929,7 @@ def_optimize(AST_Call, function(self, compressor) {
1911
1929
  && is_undeclared_ref(exp)
1912
1930
  && exp.name == "Function") {
1913
1931
  // new Function() => function(){}
1914
- if (self.args.length == 0) return make_node(AST_Function, self, {
1915
- argnames: [],
1916
- body: []
1917
- }).optimize(compressor);
1932
+ if (self.args.length == 0) return make_empty_function(self).optimize(compressor);
1918
1933
  if (self.args.every((x) => x instanceof AST_String)) {
1919
1934
  // quite a corner-case, but we can handle it:
1920
1935
  // https://github.com/mishoo/UglifyJS2/issues/203
@@ -3674,10 +3689,7 @@ def_optimize(AST_Dot, function(self, compressor) {
3674
3689
  });
3675
3690
  break;
3676
3691
  case "Function":
3677
- self.expression = make_node(AST_Function, self.expression, {
3678
- argnames: [],
3679
- body: []
3680
- });
3692
+ self.expression = make_empty_function(self.expression);
3681
3693
  break;
3682
3694
  case "Number":
3683
3695
  self.expression = make_node(AST_Number, self.expression, {
@@ -121,7 +121,7 @@ import {
121
121
  member,
122
122
  has_annotation,
123
123
  } from "../utils/index.js";
124
- import { make_sequence, best_of_expression, read_property } from "./common.js";
124
+ import { make_sequence, best_of_expression, read_property, requires_sequence_to_maintain_binding } from "./common.js";
125
125
 
126
126
  import { INLINED, UNDEFINED, has_flag } from "./compressor-flags.js";
127
127
  import { pure_prop_access_globals, is_pure_native_fn, is_pure_native_method } from "./native-objects.js";
@@ -982,3 +982,51 @@ export function is_modified(compressor, tw, node, value, level, immutable) {
982
982
  return !immutable && is_modified(compressor, tw, parent, prop, level + 1);
983
983
  }
984
984
  }
985
+
986
+ /**
987
+ * Check if a node may be used by the expression it's in
988
+ * void (0, 1, {node}, 2) -> false
989
+ * console.log(0, {node}) -> true
990
+ */
991
+ export function is_used_in_expression(tw) {
992
+ for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) {
993
+ if (parent instanceof AST_Sequence) {
994
+ const nth_expression = parent.expressions.indexOf(node);
995
+ if (nth_expression !== parent.expressions.length - 1) {
996
+ // Detect (0, x.noThis)() constructs
997
+ const grandparent = tw.parent(p + 2);
998
+ if (
999
+ parent.expressions.length > 2
1000
+ || parent.expressions.length === 1
1001
+ || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1])
1002
+ ) {
1003
+ return false;
1004
+ }
1005
+ return true;
1006
+ } else {
1007
+ continue;
1008
+ }
1009
+ }
1010
+ if (parent instanceof AST_Unary) {
1011
+ const op = parent.operator;
1012
+ if (op === "void") {
1013
+ return false;
1014
+ }
1015
+ if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") {
1016
+ continue;
1017
+ }
1018
+ }
1019
+ if (
1020
+ parent instanceof AST_SimpleStatement
1021
+ || parent instanceof AST_LabeledStatement
1022
+ ) {
1023
+ return false;
1024
+ }
1025
+ if (parent instanceof AST_Scope) {
1026
+ return false;
1027
+ }
1028
+ return true;
1029
+ }
1030
+
1031
+ return true;
1032
+ }
package/lib/minify.js CHANGED
@@ -305,7 +305,7 @@ function* minify_sync_or_async(files, options, _fs_module) {
305
305
  if (node.block_scope) {
306
306
  node.block_scope.variables = undefined;
307
307
  node.block_scope.enclosed = undefined;
308
- node.parent_scope = undefined;
308
+ node.block_scope.parent_scope = undefined;
309
309
  }
310
310
  });
311
311
  }
package/lib/propmangle.js CHANGED
@@ -326,7 +326,9 @@ function mangle_properties(ast, options, annotated_props = find_annotated_props(
326
326
  } else if (node instanceof AST_ObjectProperty) {
327
327
  // setter, getter, method or class field
328
328
  if (!keep_quoted || !node.quote) {
329
- node.key.name = mangle(node.key.name);
329
+ if (!node.computed_key()) {
330
+ node.key.name = mangle(node.key.name);
331
+ }
330
332
  }
331
333
  } else if (node instanceof AST_Dot) {
332
334
  if (!keep_quoted || !node.quote) {
package/lib/scope.js CHANGED
@@ -200,7 +200,7 @@ function redefined_catch_def(def) {
200
200
  }
201
201
  }
202
202
 
203
- AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null, toplevel = this } = {}) {
203
+ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = undefined, toplevel = this } = {}) {
204
204
  options = defaults(options, {
205
205
  cache: null,
206
206
  ie8: false,
@@ -524,7 +524,7 @@ AST_Scope.DEFMETHOD("add_child_scope", function (scope) {
524
524
  scope.parent_scope = this;
525
525
 
526
526
  // Propagate to this.uses_arguments from arrow functions
527
- if ((scope instanceof AST_Arrow) && !this.uses_arguments) {
527
+ if ((scope instanceof AST_Arrow) && (this instanceof AST_Lambda && !this.uses_arguments)) {
528
528
  this.uses_arguments = walk(scope, node => {
529
529
  if (
530
530
  node instanceof AST_SymbolRef
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.33.0",
7
+ "version": "5.34.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
@@ -57,7 +57,7 @@
57
57
  "esm": "^3.2.25",
58
58
  "mocha": "^9.2.0",
59
59
  "pre-commit": "^1.2.2",
60
- "rollup": "^2.56.3",
60
+ "rollup": "^2.79.2",
61
61
  "semver": "^7.5.1",
62
62
  "source-map": "~0.8.0-beta.0"
63
63
  },