Skip to content

Commit 5ab1cb9

Browse files
committed
[Belt] Stricter parse for Int and Float
The actual implementation of Belt.Int.fromString relies on the Javascript `parseInt` function [0]. That function parses strings in a permissive manner. For instance, if the function encounters an alphabetical character, it returns the value up to that character: parseInt("123a456") // output: 123 The same applies for Belt.Float.fromString that relies on `parseFloat` [1] and have a similar interpretation. This commit proposes a stricter implementation of Int and Float parsing using the Javascript `Number` constructor [2]. The Belt.Int.fromString uses the more specific `Math.trunc` function [3], that parses string similarly to `Number` and then returns the Int part of that number. Relying only on the `Number` constructor keeps the implementation simple. However, there exists one last quirk while using it with an empty string. It returns the `0` value: Number("") // ouptput: 0 Consequently, Belt.Int.fromString("") will return `0`. Tests for Belt.(Int/Float).fromString have been updated in order to reflect that. Fix rescript-lang#3732 [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat [2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/Number [3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc Signed-Off-By: Ronan-A. Cherrueau <[email protected]>
1 parent bf887f1 commit 5ab1cb9

File tree

4 files changed

+22
-4
lines changed

4 files changed

+22
-4
lines changed

jscomp/others/belt_Float.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ external toInt: float -> int = "%intoffloat"
3232

3333
external fromInt: int -> float = "%identity"
3434

35-
external fromString: string -> float = "parseFloat" [@@bs.val]
35+
external fromString: string -> float = "Number" [@@bs.val]
3636

3737
let fromString i =
3838
match (fromString i) with

jscomp/others/belt_Int.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ external toFloat: int -> float = "%identity"
3232

3333
external fromFloat: float -> int = "%intoffloat"
3434

35-
external fromString: string -> (_ [@bs.as 10]) -> int = "parseInt" [@@bs.val]
35+
external fromString: string -> (_ [@bs.as 10]) -> int = "Math.trunc" [@@bs.val]
3636

3737
let fromString i =
3838
match fromString i with

jscomp/test/bs_float_test.ml

+10-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ let () =
2929
eq __LOC__ (F.fromString "-1.0") (Some (-1.0));
3030
eq __LOC__ (F.fromString "-1.5") (Some (-1.5));
3131
eq __LOC__ (F.fromString "-1.7") (Some (-1.7));
32-
eq __LOC__ (F.fromString "not a float") None
32+
eq __LOC__ (F.fromString "17e-1") (Some (1.7));
33+
eq __LOC__ (F.fromString "-17e-1") (Some (-1.7));
34+
eq __LOC__ (F.fromString " -17e-1 ") (Some (-1.7));
35+
eq __LOC__ (F.fromString "0x11") (Some (17.));
36+
eq __LOC__ (F.fromString "0b11") (Some (3.));
37+
eq __LOC__ (F.fromString "0o11") (Some (9.));
38+
eq __LOC__ (F.fromString "") (Some (0.));
39+
eq __LOC__ (F.fromString "not a float") None;
40+
eq __LOC__ (F.fromString "100.0abcdef") None;
41+
eq __LOC__ (F.fromString "123_456.7") None
3342

3443
let () =
3544
eq __LOC__ (F.toString 1.0) "1";

jscomp/test/bs_int_test.ml

+10-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ let () =
2929
eq __LOC__ (I.fromString "-1.0") (Some (-1));
3030
eq __LOC__ (I.fromString "-1.5") (Some (-1));
3131
eq __LOC__ (I.fromString "-1.7") (Some (-1));
32-
eq __LOC__ (I.fromString "not an int") None
32+
eq __LOC__ (I.fromString "17e-1") (Some (1));
33+
eq __LOC__ (I.fromString "-17e-1") (Some (-1));
34+
eq __LOC__ (I.fromString " -17e-1 ") (Some (-1));
35+
eq __LOC__ (I.fromString "0x11") (Some (17));
36+
eq __LOC__ (I.fromString "0b11") (Some (3));
37+
eq __LOC__ (I.fromString "0o11") (Some (9));
38+
eq __LOC__ (I.fromString "") (Some (0));
39+
eq __LOC__ (I.fromString "not an int") None;
40+
eq __LOC__ (I.fromString "100abcdef") None;
41+
eq __LOC__ (I.fromString "123_456") None
3342

3443
let () =
3544
eq __LOC__ (I.toString 1) "1";

0 commit comments

Comments
 (0)