Skip to content

Rename functions ending with Exn to OrThrow #7518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@

# 12.0.0-alpha.14 (Unreleased)

#### :boom: Breaking Change

- Rename functions ending with `Exn` to end with `OrThrow`. The old `Exn` functions are now deprecated:
- `Bool.fromStringExn` → `Bool.fromStringOrThrow`
- `BigInt.fromStringExn` → `BigInt.fromStringOrThrow`
- `JSON.parseExn` → `JSON.parseOrThrow`
- Changed `BigInt.fromFloat` to return an option rather than throwing an error.
- Added `BigInt.fromFloatOrThrow`
- Old functions remain available but are marked as deprecated with guidance to use the new `OrThrow` variants.

#### :rocket: New Feature

- Add `RegExp.flags`. https://github.com/rescript-lang/rescript/pull/7461
Expand Down
16 changes: 14 additions & 2 deletions analysis/reanalyze/src/ExnLib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,19 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t =
("float_of_string", [failure]);
]
in
let stdlibBigInt = [("fromStringExn", [jsExn])] in
let stdlibBool = [("fromStringExn", [invalidArgument])] in
let stdlibBigInt =
[
("fromStringExn", [jsExn]);
("fromStringOrThrow", [jsExn]);
("fromFloatOrThrow", [jsExn]);
]
in
let stdlibBool =
[
("fromStringExn", [invalidArgument]);
("fromStringOrThrow", [invalidArgument]);
]
in
let stdlibError = [("raise", [jsExn])] in
let stdlibExn =
[
Expand All @@ -68,6 +79,7 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t =
[
("parseExn", [jsExn]);
("parseExnWithReviver", [jsExn]);
("parseOrThrow", [jsExn]);
("stringifyAny", [jsExn]);
("stringifyAnyWithIndent", [jsExn]);
("stringifyAnyWithReplacer", [jsExn]);
Expand Down
9 changes: 9 additions & 0 deletions lib/es6/Stdlib_BigInt.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@



function fromString(value) {
try {
return BigInt(value);
} catch (exn) {
return;
}
}

function fromFloat(value) {
try {
return BigInt(value);
Expand All @@ -14,6 +22,7 @@ function toInt(t) {
}

export {
fromString,
fromFloat,
toInt,
}
Expand Down
7 changes: 5 additions & 2 deletions lib/es6/Stdlib_Bool.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function fromString(s) {
}
}

function fromStringExn(param) {
function fromStringOrThrow(param) {
switch (param) {
case "false" :
return false;
Expand All @@ -29,15 +29,18 @@ function fromStringExn(param) {
default:
throw {
RE_EXN_ID: "Invalid_argument",
_1: "Bool.fromStringExn: value is neither \"true\" nor \"false\"",
_1: "Bool.fromStringOrThrow: value is neither \"true\" nor \"false\"",
Error: new Error()
};
}
}

let fromStringExn = fromStringOrThrow;

export {
toString,
fromString,
fromStringOrThrow,
fromStringExn,
}
/* No side effect */
9 changes: 9 additions & 0 deletions lib/js/Stdlib_BigInt.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
'use strict';


function fromString(value) {
try {
return BigInt(value);
} catch (exn) {
return;
}
}

function fromFloat(value) {
try {
return BigInt(value);
Expand All @@ -13,6 +21,7 @@ function toInt(t) {
return Number(t) | 0;
}

exports.fromString = fromString;
exports.fromFloat = fromFloat;
exports.toInt = toInt;
/* No side effect */
7 changes: 5 additions & 2 deletions lib/js/Stdlib_Bool.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function fromString(s) {
}
}

function fromStringExn(param) {
function fromStringOrThrow(param) {
switch (param) {
case "false" :
return false;
Expand All @@ -29,13 +29,16 @@ function fromStringExn(param) {
default:
throw {
RE_EXN_ID: "Invalid_argument",
_1: "Bool.fromStringExn: value is neither \"true\" nor \"false\"",
_1: "Bool.fromStringOrThrow: value is neither \"true\" nor \"false\"",
Error: new Error()
};
}
}

let fromStringExn = fromStringOrThrow;

exports.toString = toString;
exports.fromString = fromString;
exports.fromStringOrThrow = fromStringOrThrow;
exports.fromStringExn = fromStringExn;
/* No side effect */
72 changes: 61 additions & 11 deletions runtime/Stdlib_BigInt.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,89 @@ type t = bigint
@val external asIntN: (~width: int, bigint) => bigint = "BigInt.asIntN"
@val external asUintN: (~width: int, bigint) => bigint = "BigInt.asUintN"

@val external fromString: string => bigint = "BigInt"

/**
Parses the given `string` into a `bigint` using JavaScript semantics. Return the
number as a `bigint` if successfully parsed. Uncaught syntax exception otherwise.
number as a `bigint` if successfully parsed. Throws a syntax exception otherwise.

## Examples

```rescript
BigInt.fromStringExn("123")->assertEqual(123n)
BigInt.fromStringOrThrow("123")->assertEqual(123n)

BigInt.fromStringExn("")->assertEqual(0n)
BigInt.fromStringOrThrow("")->assertEqual(0n)

BigInt.fromStringExn("0x11")->assertEqual(17n)
BigInt.fromStringOrThrow("0x11")->assertEqual(17n)

BigInt.fromStringExn("0b11")->assertEqual(3n)
BigInt.fromStringOrThrow("0b11")->assertEqual(3n)

BigInt.fromStringExn("0o11")->assertEqual(9n)
BigInt.fromStringOrThrow("0o11")->assertEqual(9n)

/* catch exception */
switch BigInt.fromStringExn("a") {
switch BigInt.fromStringOrThrow("a") {
| exception JsExn(_error) => assert(true)
| _bigInt => assert(false)
}
```
*/
@val
external fromStringOrThrow: string => bigint = "BigInt"

/**
Parses the given `string` into a `bigint` using JavaScript semantics. Returns
`Some(bigint)` if the string can be parsed, `None` otherwise.

## Examples

```rescript
BigInt.fromString("123")->assertEqual(Some(123n))

BigInt.fromString("")->assertEqual(Some(0n))

BigInt.fromString("0x11")->assertEqual(Some(17n))

BigInt.fromString("0b11")->assertEqual(Some(3n))

BigInt.fromString("0o11")->assertEqual(Some(9n))

BigInt.fromString("invalid")->assertEqual(None)
```
*/
let fromString = (value: string) => {
try Some(fromStringOrThrow(value)) catch {
| _ => None
}
}

@deprecated("Use `fromStringOrThrow` instead") @val
external fromStringExn: string => bigint = "BigInt"

@val external fromInt: int => bigint = "BigInt"
@val external fromFloat: float => bigint = "BigInt"

/**
Converts a `float` to a `bigint` using JavaScript semantics.
Throws an exception if the float is not an integer or is infinite/NaN.

## Examples

```rescript
BigInt.fromFloatOrThrow(123.0)->assertEqual(123n)

BigInt.fromFloatOrThrow(0.0)->assertEqual(0n)

BigInt.fromFloatOrThrow(-456.0)->assertEqual(-456n)

/* This will throw an exception */
switch BigInt.fromFloatOrThrow(123.5) {
| exception JsExn(_error) => assert(true)
| _bigInt => assert(false)
}
```
*/
@val
external fromFloatOrThrow: float => bigint = "BigInt"

let fromFloat = (value: float) => {
try Some(fromFloat(value)) catch {
try Some(fromFloatOrThrow(value)) catch {
| _ => None
}
}
Expand Down
7 changes: 5 additions & 2 deletions runtime/Stdlib_Bool.res
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ let fromString = s => {
}
}

let fromStringExn = param =>
let fromStringOrThrow = param =>
switch param {
| "true" => true
| "false" => false
| _ => throw(Invalid_argument(`Bool.fromStringExn: value is neither "true" nor "false"`))
| _ => throw(Invalid_argument(`Bool.fromStringOrThrow: value is neither "true" nor "false"`))
}

@deprecated("Use `fromStringOrThrow` instead")
let fromStringExn = fromStringOrThrow

external compare: (bool, bool) => Stdlib_Ordering.t = "%compare"

external equal: (bool, bool) => bool = "%equal"
17 changes: 17 additions & 0 deletions runtime/Stdlib_Bool.resi
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ Bool.fromString("notAValidBoolean")->assertEqual(None)
*/
let fromString: string => option<bool>

/**
Converts a string to a boolean.
Throws an `Invalid_argument` exception if the string is not a valid boolean.

## Examples
```rescript
Bool.fromStringOrThrow("true")->assertEqual(true)
Bool.fromStringOrThrow("false")->assertEqual(false)
switch Bool.fromStringOrThrow("notAValidBoolean") {
| exception Invalid_argument(_) => assert(true)
| _ => assert(false)
}
```
*/
let fromStringOrThrow: string => bool

/**
Converts a string to a boolean.
Beware, this function will throw an `Invalid_argument` exception
Expand All @@ -46,6 +62,7 @@ switch Bool.fromStringExn("notAValidBoolean") {
}
```
*/
@deprecated("Use `fromStringOrThrow` instead")
let fromStringExn: string => bool

external compare: (bool, bool) => Stdlib_Ordering.t = "%compare"
Expand Down
8 changes: 6 additions & 2 deletions runtime/Stdlib_JSON.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ type rec t =
@unboxed
type replacer = Keys(array<string>) | Replacer((string, t) => t)

@raises @val external parseExn: (string, ~reviver: (string, t) => t=?) => t = "JSON.parse"
@deprecated("Use `parseExn` with optional parameter instead") @raises @val
@raises @val external parseOrThrow: (string, ~reviver: (string, t) => t=?) => t = "JSON.parse"

@deprecated("Use `parseOrThrow` instead") @raises @val
external parseExn: (string, ~reviver: (string, t) => t=?) => t = "JSON.parse"

@deprecated("Use `parseOrThrow` with optional parameter instead") @raises @val
external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse"

@val external stringify: (t, ~replacer: replacer=?, ~space: int=?) => string = "JSON.stringify"
Expand Down
Loading