Skip to content

Commit

Permalink
Evaluate some BigInt operations (#1390)
Browse files Browse the repository at this point in the history
* Evaluate some BigInt operations. Closes #1388

* Prevent division by zero
  • Loading branch information
fabiosantoscode committed Feb 19, 2024
1 parent 3d199c1 commit cf27499
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
3 changes: 3 additions & 0 deletions lib/compress/common.js
Expand Up @@ -44,6 +44,7 @@
import {
AST_Array,
AST_Arrow,
AST_BigInt,
AST_BlockStatement,
AST_Call,
AST_Chain,
Expand Down Expand Up @@ -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":
Expand Down
25 changes: 21 additions & 4 deletions lib/compress/evaluate.js
Expand Up @@ -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);
Expand Down Expand Up @@ -257,7 +264,6 @@ def_eval(AST_Binary, function (compressor, depth) {
var right = this.right._eval(compressor, depth);
if (right === this.right)
return this;
var result;

if (left != null
&& right != null
Expand All @@ -269,6 +275,17 @@ def_eval(AST_Binary, function (compressor, depth) {
return this;
}

// Do not mix BigInt and Number; Don't use `>>>` on BigInt or `/ 0n`
if (
(typeof left === "bigint") !== (typeof right === "bigint")
|| typeof left === "bigint"
&& (this.operator === ">>>"
|| this.operator === "/" && Number(right) === 0)
) {
return this;
}

var result;
switch (this.operator) {
case "&&": result = left && right; break;
case "||": result = left || right; break;
Expand All @@ -278,7 +295,7 @@ def_eval(AST_Binary, function (compressor, depth) {
case "^": result = left ^ right; break;
case "+": result = left + right; break;
case "*": result = left * right; break;
case "**": result = Math.pow(left, right); break;
case "**": result = left ** right; break;
case "/": result = left / right; break;
case "%": result = left % right; break;
case "-": result = left - right; break;
Expand All @@ -296,7 +313,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;
}
Expand Down
32 changes: 25 additions & 7 deletions test/compress/big_int.js
Expand Up @@ -62,12 +62,30 @@ big_int_math: {
defaults: true
}
input: {
const sum = 10n + 15n;
const exp = 5n ** 10n;
const sub = 1n - 3n;
const mul = 5n * 5n;
const div = 15n / 5n;
const regular_number = 1 * 10;
console.log({
sum: 10n + 15n,
exp: 2n ** 3n,
sub: 1n - 3n,
mul: 5n * 5n,
div: 15n / 5n,
});
}
expect_exact: "const sum=10n+15n,exp=5n**10n,sub=1n-3n,mul=5n*5n,div=15n/5n,regular_number=10;"
expect_exact: "console.log({sum:25n,exp:8n,sub:-2n,mul:25n,div:3n});"
expect_stdout: true
}

big_int_math_counter_examples: {
node_version = ">= 12"
options = {
defaults: true
}
input: {
console.log({
mixing_types: 1 * 10n,
bad_shift: 1n >>> 0n,
bad_div: 1n / 0n,
});
}
expect_exact: "console.log({mixing_types:1*10n,bad_shift:1n>>>0n,bad_div:1n/0n});"
expect_stdout: true
}

0 comments on commit cf27499

Please sign in to comment.