terser 5.46.0 → 5.46.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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.46.1
4
+
5
+ - Fix extremely slow (seemed like a freeze) `evaluate` of method chains
6
+ - Parse extremely large floating-point number literals as `Infinity`
7
+ - Remove parens from comma expressions in computed property access (`foo[(1, 2)]`)
8
+
3
9
  ## v5.46.0
4
10
 
5
11
  - Add "observedAttributes" domprop (#1652)
@@ -2464,12 +2464,20 @@ function parse($TEXT, options) {
2464
2464
  ret = _make_symbol(AST_SymbolRef);
2465
2465
  break;
2466
2466
  case "num":
2467
- ret = new AST_Number({
2468
- start: tok,
2469
- end: tok,
2470
- value: tok.value,
2471
- raw: LATEST_RAW
2472
- });
2467
+ if (tok.value === Infinity) {
2468
+ // very large float values are parsed as Infinity
2469
+ ret = new AST_Infinity({
2470
+ start: tok,
2471
+ end: tok,
2472
+ });
2473
+ } else {
2474
+ ret = new AST_Number({
2475
+ start: tok,
2476
+ end: tok,
2477
+ value: tok.value,
2478
+ raw: LATEST_RAW
2479
+ });
2480
+ }
2473
2481
  break;
2474
2482
  case "big_int":
2475
2483
  ret = new AST_BigInt({
@@ -10272,21 +10280,21 @@ function OutputStream(options) {
10272
10280
 
10273
10281
  PARENS(AST_Sequence, function(output) {
10274
10282
  var p = output.parent();
10275
- return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
10276
- || p instanceof AST_Unary // !(foo, bar, baz)
10277
- || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
10278
- || p instanceof AST_VarDefLike // var a = (1, 2), b = a + a; ==> b == 4
10279
- || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
10280
- || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
10281
- || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
10282
- || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
10283
- * ==> 20 (side effect, set a := 10 and b := 20) */
10284
- || p instanceof AST_Arrow // x => (x, x)
10285
- || p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
10286
- || p instanceof AST_Expansion // [...(a, b)]
10287
- || p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
10288
- || p instanceof AST_Yield // yield (foo, bar)
10289
- || p instanceof AST_Export // export default (foo, bar)
10283
+ return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
10284
+ || p instanceof AST_Unary // !(foo, bar, baz)
10285
+ || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
10286
+ || p instanceof AST_VarDefLike // var a = (1, 2), b = a + a; ==> b == 4
10287
+ || p instanceof AST_PropAccess && this !== p.property // (1, {foo:2}).foo, (1, {foo:2})["foo"], not foo[1, 2]
10288
+ || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
10289
+ || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
10290
+ || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
10291
+ * ==> 20 (side effect, set a := 10 and b := 20) */
10292
+ || p instanceof AST_Arrow // x => (x, x)
10293
+ || p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
10294
+ || p instanceof AST_Expansion // [...(a, b)]
10295
+ || p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
10296
+ || p instanceof AST_Yield // yield (foo, bar)
10297
+ || p instanceof AST_Export // export default (foo, bar)
10290
10298
  ;
10291
10299
  });
10292
10300
 
@@ -14869,10 +14877,13 @@ var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date e
14869
14877
  AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
14870
14878
  if (compressor.option("unsafe")) {
14871
14879
  var expr = this.expression;
14872
- var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
14880
+ var first_arg;
14873
14881
  if (
14874
14882
  expr.expression && expr.expression.name === "hasOwnProperty" &&
14875
- (first_arg == null || first_arg.thedef && first_arg.thedef.undeclared)
14883
+ (
14884
+ (first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor))) == null
14885
+ || first_arg.thedef && first_arg.thedef.undeclared
14886
+ )
14876
14887
  ) {
14877
14888
  return false;
14878
14889
  }
@@ -15375,6 +15386,15 @@ def_eval(AST_SymbolRef, function (compressor, depth) {
15375
15386
  return value;
15376
15387
  });
15377
15388
 
15389
+ def_eval(AST_Chain, function (compressor, depth) {
15390
+ const evaluated = this.expression._eval(compressor, depth, /*ast_chain=*/true);
15391
+ return evaluated === nullish
15392
+ ? undefined
15393
+ : evaluated === this.expression
15394
+ ? this
15395
+ : evaluated;
15396
+ });
15397
+
15378
15398
  const global_objs = { Array, Math, Number, Object, String };
15379
15399
 
15380
15400
  const regexp_flags = new Set([
@@ -15386,9 +15406,13 @@ const regexp_flags = new Set([
15386
15406
  "unicode",
15387
15407
  ]);
15388
15408
 
15389
- def_eval(AST_PropAccess, function (compressor, depth) {
15390
- let obj = this.expression._eval(compressor, depth + 1);
15391
- if (obj === nullish || (this.optional && obj == null)) return nullish;
15409
+ def_eval(AST_PropAccess, function (compressor, depth, ast_chain) {
15410
+ let obj = (ast_chain || this.property === "length" || compressor.option("unsafe"))
15411
+ && this.expression._eval(compressor, depth + 1, ast_chain);
15412
+
15413
+ if (ast_chain) {
15414
+ if (obj === nullish || (this.optional && obj == null)) return nullish;
15415
+ }
15392
15416
 
15393
15417
  // `.length` of strings and arrays is always safe
15394
15418
  if (this.property === "length") {
@@ -15459,26 +15483,19 @@ def_eval(AST_PropAccess, function (compressor, depth) {
15459
15483
  return this;
15460
15484
  });
15461
15485
 
15462
- def_eval(AST_Chain, function (compressor, depth) {
15463
- const evaluated = this.expression._eval(compressor, depth);
15464
- return evaluated === nullish
15465
- ? undefined
15466
- : evaluated === this.expression
15467
- ? this
15468
- : evaluated;
15469
- });
15470
-
15471
- def_eval(AST_Call, function (compressor, depth) {
15486
+ def_eval(AST_Call, function (compressor, depth, ast_chain) {
15472
15487
  var exp = this.expression;
15473
15488
 
15474
- const callee = exp._eval(compressor, depth);
15475
- if (callee === nullish || (this.optional && callee == null)) return nullish;
15489
+ if (ast_chain) {
15490
+ const callee = exp._eval(compressor, depth, ast_chain);
15491
+ if (callee === nullish || (this.optional && callee == null)) return nullish;
15492
+ }
15476
15493
 
15477
15494
  if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
15478
15495
  var key = exp.property;
15479
15496
  if (key instanceof AST_Node) {
15480
15497
  key = key._eval(compressor, depth);
15481
- if (key === exp.property)
15498
+ if (typeof key !== "string" && typeof key !== "number")
15482
15499
  return this;
15483
15500
  }
15484
15501
  var val;
@@ -15496,7 +15513,8 @@ def_eval(AST_Call, function (compressor, depth) {
15496
15513
  if (!is_pure_native_fn(e.name, key)) return this;
15497
15514
  val = global_objs[e.name];
15498
15515
  } else {
15499
- val = e._eval(compressor, depth + 1);
15516
+ val = e._eval(compressor, depth + 1, /* don't pass ast_chain (exponential work) */);
15517
+
15500
15518
  if (val === e || !val)
15501
15519
  return this;
15502
15520
  if (!is_pure_native_method(val.constructor.name, key))
@@ -371,6 +371,15 @@ def_eval(AST_SymbolRef, function (compressor, depth) {
371
371
  return value;
372
372
  });
373
373
 
374
+ def_eval(AST_Chain, function (compressor, depth) {
375
+ const evaluated = this.expression._eval(compressor, depth, /*ast_chain=*/true);
376
+ return evaluated === nullish
377
+ ? undefined
378
+ : evaluated === this.expression
379
+ ? this
380
+ : evaluated;
381
+ });
382
+
374
383
  const global_objs = { Array, Math, Number, Object, String };
375
384
 
376
385
  const regexp_flags = new Set([
@@ -382,9 +391,13 @@ const regexp_flags = new Set([
382
391
  "unicode",
383
392
  ]);
384
393
 
385
- def_eval(AST_PropAccess, function (compressor, depth) {
386
- let obj = this.expression._eval(compressor, depth + 1);
387
- if (obj === nullish || (this.optional && obj == null)) return nullish;
394
+ def_eval(AST_PropAccess, function (compressor, depth, ast_chain) {
395
+ let obj = (ast_chain || this.property === "length" || compressor.option("unsafe"))
396
+ && this.expression._eval(compressor, depth + 1, ast_chain);
397
+
398
+ if (ast_chain) {
399
+ if (obj === nullish || (this.optional && obj == null)) return nullish;
400
+ }
388
401
 
389
402
  // `.length` of strings and arrays is always safe
390
403
  if (this.property === "length") {
@@ -455,26 +468,19 @@ def_eval(AST_PropAccess, function (compressor, depth) {
455
468
  return this;
456
469
  });
457
470
 
458
- def_eval(AST_Chain, function (compressor, depth) {
459
- const evaluated = this.expression._eval(compressor, depth);
460
- return evaluated === nullish
461
- ? undefined
462
- : evaluated === this.expression
463
- ? this
464
- : evaluated;
465
- });
466
-
467
- def_eval(AST_Call, function (compressor, depth) {
471
+ def_eval(AST_Call, function (compressor, depth, ast_chain) {
468
472
  var exp = this.expression;
469
473
 
470
- const callee = exp._eval(compressor, depth);
471
- if (callee === nullish || (this.optional && callee == null)) return nullish;
474
+ if (ast_chain) {
475
+ const callee = exp._eval(compressor, depth, ast_chain);
476
+ if (callee === nullish || (this.optional && callee == null)) return nullish;
477
+ }
472
478
 
473
479
  if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
474
480
  var key = exp.property;
475
481
  if (key instanceof AST_Node) {
476
482
  key = key._eval(compressor, depth);
477
- if (key === exp.property)
483
+ if (typeof key !== "string" && typeof key !== "number")
478
484
  return this;
479
485
  }
480
486
  var val;
@@ -492,7 +498,8 @@ def_eval(AST_Call, function (compressor, depth) {
492
498
  if (!is_pure_native_fn(e.name, key)) return this;
493
499
  val = global_objs[e.name];
494
500
  } else {
495
- val = e._eval(compressor, depth + 1);
501
+ val = e._eval(compressor, depth + 1, /* don't pass ast_chain (exponential work) */);
502
+
496
503
  if (val === e || !val)
497
504
  return this;
498
505
  if (!is_pure_native_method(val.constructor.name, key))
@@ -958,10 +958,13 @@ var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date e
958
958
  AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
959
959
  if (compressor.option("unsafe")) {
960
960
  var expr = this.expression;
961
- var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
961
+ var first_arg;
962
962
  if (
963
963
  expr.expression && expr.expression.name === "hasOwnProperty" &&
964
- (first_arg == null || first_arg.thedef && first_arg.thedef.undeclared)
964
+ (
965
+ (first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor))) == null
966
+ || first_arg.thedef && first_arg.thedef.undeclared
967
+ )
965
968
  ) {
966
969
  return false;
967
970
  }
package/lib/output.js CHANGED
@@ -1043,21 +1043,21 @@ function OutputStream(options) {
1043
1043
 
1044
1044
  PARENS(AST_Sequence, function(output) {
1045
1045
  var p = output.parent();
1046
- return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
1047
- || p instanceof AST_Unary // !(foo, bar, baz)
1048
- || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
1049
- || p instanceof AST_VarDefLike // var a = (1, 2), b = a + a; ==> b == 4
1050
- || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
1051
- || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
1052
- || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
1053
- || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
1054
- * ==> 20 (side effect, set a := 10 and b := 20) */
1055
- || p instanceof AST_Arrow // x => (x, x)
1056
- || p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
1057
- || p instanceof AST_Expansion // [...(a, b)]
1058
- || p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
1059
- || p instanceof AST_Yield // yield (foo, bar)
1060
- || p instanceof AST_Export // export default (foo, bar)
1046
+ return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
1047
+ || p instanceof AST_Unary // !(foo, bar, baz)
1048
+ || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
1049
+ || p instanceof AST_VarDefLike // var a = (1, 2), b = a + a; ==> b == 4
1050
+ || p instanceof AST_PropAccess && this !== p.property // (1, {foo:2}).foo, (1, {foo:2})["foo"], not foo[1, 2]
1051
+ || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
1052
+ || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
1053
+ || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
1054
+ * ==> 20 (side effect, set a := 10 and b := 20) */
1055
+ || p instanceof AST_Arrow // x => (x, x)
1056
+ || p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
1057
+ || p instanceof AST_Expansion // [...(a, b)]
1058
+ || p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
1059
+ || p instanceof AST_Yield // yield (foo, bar)
1060
+ || p instanceof AST_Export // export default (foo, bar)
1061
1061
  ;
1062
1062
  });
1063
1063
 
package/lib/parse.js CHANGED
@@ -101,6 +101,7 @@ import {
101
101
  AST_If,
102
102
  AST_Import,
103
103
  AST_ImportMeta,
104
+ AST_Infinity,
104
105
  AST_IterationStatement,
105
106
  AST_Label,
106
107
  AST_LabeledStatement,
@@ -2313,12 +2314,20 @@ function parse($TEXT, options) {
2313
2314
  ret = _make_symbol(AST_SymbolRef);
2314
2315
  break;
2315
2316
  case "num":
2316
- ret = new AST_Number({
2317
- start: tok,
2318
- end: tok,
2319
- value: tok.value,
2320
- raw: LATEST_RAW
2321
- });
2317
+ if (tok.value === Infinity) {
2318
+ // very large float values are parsed as Infinity
2319
+ ret = new AST_Infinity({
2320
+ start: tok,
2321
+ end: tok,
2322
+ });
2323
+ } else {
2324
+ ret = new AST_Number({
2325
+ start: tok,
2326
+ end: tok,
2327
+ value: tok.value,
2328
+ raw: LATEST_RAW
2329
+ });
2330
+ }
2322
2331
  break;
2323
2332
  case "big_int":
2324
2333
  ret = new AST_BigInt({
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.46.0",
7
+ "version": "5.46.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },