From 8a7d752448a504883a183bee034a93df7b561317 Mon Sep 17 00:00:00 2001 From: Matthias Le Brun Date: Sun, 4 May 2025 17:18:02 +0200 Subject: [PATCH 1/2] make fromFloat error-safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #7089 ⚠️ breaking change --- CHANGELOG.md | 1 + lib/es6/Stdlib_BigInt.js | 9 +++++++++ lib/js/Stdlib_BigInt.js | 9 +++++++++ runtime/Stdlib_BigInt.res | 8 +++++++- tests/tests/src/core/Core_TempTests.mjs | 2 +- tests/tests/src/core/Core_TempTests.res | 2 +- tests/tests/src/core/Core_TestTests.mjs | 4 +++- tests/tests/src/core/Core_TestTests.res | 2 +- 8 files changed, 32 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1587e0c0c5..225b60bfe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ #### :boom: Breaking Change - Rename `JsError` to `JsExn` and error modules cleanup. https://github.com/rescript-lang/rescript/pull/7408 +- Make `BigInt.fromFloat` return an option rather than throwing an error in case it's passed a value with a decimal value. https://github.com/rescript-lang/rescript/pull/7419 #### :rocket: New Feature diff --git a/lib/es6/Stdlib_BigInt.js b/lib/es6/Stdlib_BigInt.js index 45827fdb18..6a45c334ef 100644 --- a/lib/es6/Stdlib_BigInt.js +++ b/lib/es6/Stdlib_BigInt.js @@ -1,6 +1,14 @@ +function fromFloat(value) { + try { + return BigInt(value); + } catch (exn) { + return; + } +} + function toInt(t) { return Number(t) | 0; } @@ -10,6 +18,7 @@ function bitwiseNot(x) { } export { + fromFloat, toInt, bitwiseNot, } diff --git a/lib/js/Stdlib_BigInt.js b/lib/js/Stdlib_BigInt.js index f4dad6af37..88012bc1b6 100644 --- a/lib/js/Stdlib_BigInt.js +++ b/lib/js/Stdlib_BigInt.js @@ -1,6 +1,14 @@ 'use strict'; +function fromFloat(value) { + try { + return BigInt(value); + } catch (exn) { + return; + } +} + function toInt(t) { return Number(t) | 0; } @@ -9,6 +17,7 @@ function bitwiseNot(x) { return x ^ -1n; } +exports.fromFloat = fromFloat; exports.toInt = toInt; exports.bitwiseNot = bitwiseNot; /* No side effect */ diff --git a/runtime/Stdlib_BigInt.res b/runtime/Stdlib_BigInt.res index db860210dd..d7895b8c29 100644 --- a/runtime/Stdlib_BigInt.res +++ b/runtime/Stdlib_BigInt.res @@ -35,7 +35,13 @@ switch BigInt.fromStringExn("a") { */ external fromStringExn: string => bigint = "BigInt" @val external fromInt: int => bigint = "BigInt" -@val external fromFloat: float => bigint = "BigInt" +@val external _fromFloat: float => bigint = "BigInt" + +let fromFloat = (value: float) => { + try Some(_fromFloat(value)) catch { + | _ => None + } +} @send /** diff --git a/tests/tests/src/core/Core_TempTests.mjs b/tests/tests/src/core/Core_TempTests.mjs index 7b189a747f..b2e214b011 100644 --- a/tests/tests/src/core/Core_TempTests.mjs +++ b/tests/tests/src/core/Core_TempTests.mjs @@ -140,7 +140,7 @@ console.info("BigInt"); console.info("---"); -console.log(Primitive_bigint.div(BigInt(1), BigInt(12.0))); +console.log(Primitive_bigint.div(BigInt(1), Stdlib_Option.getOr(Stdlib_BigInt.fromFloat(12.0), 0n))); console.info(""); diff --git a/tests/tests/src/core/Core_TempTests.res b/tests/tests/src/core/Core_TempTests.res index a3fe866caa..982ea21f73 100644 --- a/tests/tests/src/core/Core_TempTests.res +++ b/tests/tests/src/core/Core_TempTests.res @@ -77,7 +77,7 @@ Console.info("---") @warning("-44") Console.log({ open BigInt - fromInt(1) / fromFloat(12.0) + fromInt(1) / fromFloat(12.0)->Option.getOr(0n) }) Console.info("") diff --git a/tests/tests/src/core/Core_TestTests.mjs b/tests/tests/src/core/Core_TestTests.mjs index f39a4dce04..df93ae7d4c 100644 --- a/tests/tests/src/core/Core_TestTests.mjs +++ b/tests/tests/src/core/Core_TestTests.mjs @@ -2,11 +2,13 @@ import * as Test from "./Test.mjs"; import * as Pervasives from "rescript/lib/es6/Pervasives.js"; +import * as Stdlib_BigInt from "rescript/lib/es6/Stdlib_BigInt.js"; +import * as Stdlib_Option from "rescript/lib/es6/Stdlib_Option.js"; import * as Primitive_object from "rescript/lib/es6/Primitive_object.js"; let eq = Primitive_object.equal; -let bign = BigInt(Number.MAX_VALUE); +let bign = Stdlib_Option.getOr(Stdlib_BigInt.fromFloat(Number.MAX_VALUE), 0n); let bign$1 = bign + bign; diff --git a/tests/tests/src/core/Core_TestTests.res b/tests/tests/src/core/Core_TestTests.res index f2f0dcad99..1bf71d566a 100644 --- a/tests/tests/src/core/Core_TestTests.res +++ b/tests/tests/src/core/Core_TestTests.res @@ -1,6 +1,6 @@ let eq = (a, b) => a == b -let bign = BigInt.fromFloat(Float.Constants.maxValue) +let bign = BigInt.fromFloat(Float.Constants.maxValue)->Option.getOr(0n) let bign = BigInt.add(bign, bign) Test.run(__POS_OF__("print null"), Test.print(null), eq, "null") From 9ba80818770646bf05f01a8a35fea224ad676b0a Mon Sep 17 00:00:00 2001 From: Matthias Le Brun Date: Sun, 4 May 2025 17:30:00 +0200 Subject: [PATCH 2/2] shadow rather than prefix with underscore --- runtime/Stdlib_BigInt.res | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/Stdlib_BigInt.res b/runtime/Stdlib_BigInt.res index d7895b8c29..6ba756aa4e 100644 --- a/runtime/Stdlib_BigInt.res +++ b/runtime/Stdlib_BigInt.res @@ -35,10 +35,10 @@ switch BigInt.fromStringExn("a") { */ external fromStringExn: string => bigint = "BigInt" @val external fromInt: int => bigint = "BigInt" -@val external _fromFloat: float => bigint = "BigInt" +@val external fromFloat: float => bigint = "BigInt" let fromFloat = (value: float) => { - try Some(_fromFloat(value)) catch { + try Some(fromFloat(value)) catch { | _ => None } }