From 97a79a6924215d0b9b7e2f79e23ae24a6e51f80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Mon, 15 May 2023 17:41:03 +0100 Subject: [PATCH] Evaluate some BigInt operations. Closes #1388 --- lib/compress/common.js | 3 +++ lib/compress/evaluate.js | 20 ++++++++++++++++++-- test/compress/big_int.js | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/compress/common.js b/lib/compress/common.js index 8263522c8..2350c1ea8 100644 --- a/lib/compress/common.js +++ b/lib/compress/common.js @@ -44,6 +44,7 @@ import { AST_Array, AST_Arrow, + AST_BigInt, AST_BlockStatement, AST_Call, AST_Chain, @@ -124,6 +125,8 @@ export function make_node_from_constant(val, orig) { operator: "-", expression: make_node(AST_Infinity, orig) }) : make_node(AST_Infinity, orig); + case "bigint": + return make_node(AST_BigInt, orig, { value: val.toString() }); case "boolean": return make_node(val ? AST_True : AST_False, orig); case "undefined": diff --git a/lib/compress/evaluate.js b/lib/compress/evaluate.js index d249ee355..3add88758 100644 --- a/lib/compress/evaluate.js +++ b/lib/compress/evaluate.js @@ -133,7 +133,14 @@ def_eval(AST_Constant, function () { return this.getValue(); }); -def_eval(AST_BigInt, return_this); +const supports_bigint = typeof BigInt === "function"; +def_eval(AST_BigInt, function () { + if (supports_bigint) { + return BigInt(this.value); + } else { + return this; + } +}); def_eval(AST_RegExp, function (compressor) { let evaluated = compressor.evaluated_regexps.get(this.value); @@ -246,6 +253,7 @@ const identity_comparison = makePredicate("== != === !=="); const has_identity = value => typeof value === "object" || typeof value === "function" || typeof value === "symbol"; +const no_bigint_ops = new Set(['**', ">>>"]); def_eval(AST_Binary, function (compressor, depth) { if (!non_converting_binary.has(this.operator)) @@ -269,6 +277,14 @@ def_eval(AST_Binary, function (compressor, depth) { return this; } + // Do not mix BigInt and Number; Don't use Math.pow() on BigInt + if ( + (typeof left === "bigint") !== (typeof right === "bigint") + || typeof left === "bigint" && no_bigint_ops.has(this.operator) + ) { + return this; + } + switch (this.operator) { case "&&": result = left && right; break; case "||": result = left || right; break; @@ -296,7 +312,7 @@ def_eval(AST_Binary, function (compressor, depth) { default: return this; } - if (isNaN(result) && compressor.find_parent(AST_With)) { + if (typeof result === "number" && isNaN(result) && compressor.find_parent(AST_With)) { // leave original expression as is return this; } diff --git a/test/compress/big_int.js b/test/compress/big_int.js index 2f3501c04..cf28dceb5 100644 --- a/test/compress/big_int.js +++ b/test/compress/big_int.js @@ -70,5 +70,5 @@ big_int_math: { const div = 15n / 5n; const regular_number = 1 * 10; } - expect_exact: "const sum=10n+15n,exp=5n**10n,sub=1n-3n,mul=5n*5n,div=15n/5n,regular_number=10;" + expect_exact: "const sum=25n,exp=5n**10n,sub=-2n,mul=25n,div=3n,regular_number=10;" }