diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3c59682e..fff4a2eeb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ # 12.0.0-beta.3 (Unreleased) +#### :boom: Breaking Change + +- `Result.getOrThrow` now throws a JS error instead of a `Not_found` ReScript exception. https://github.com/rescript-lang/rescript/pull/7630 + +#### :rocket: New Feature + +- Add optional `message` argument to `Result.getOrThrow` and improve default error message. https://github.com/rescript-lang/rescript/pull/7630 + #### :nail_care: Polish - Configuration fields `bs-dependencies`, `bs-dev-dependencies` and `bsc-flags` are now deprecated in favor of `dependencies`, `dev-dependencies` and `compiler-flags`. https://github.com/rescript-lang/rescript/pull/7658 diff --git a/lib/es6/Stdlib_Option.js b/lib/es6/Stdlib_Option.js index 24bbf4929c..228dc804ae 100644 --- a/lib/es6/Stdlib_Option.js +++ b/lib/es6/Stdlib_Option.js @@ -1,6 +1,6 @@ -import * as Stdlib_Error from "./Stdlib_Error.js"; +import * as Stdlib_JsError from "./Stdlib_JsError.js"; import * as Primitive_option from "./Primitive_option.js"; function filter(opt, p) { @@ -21,7 +21,7 @@ function getOrThrow(x, message) { if (x !== undefined) { return Primitive_option.valFromOption(x); } else { - return Stdlib_Error.panic(message !== undefined ? message : "Option.getOrThrow called for None value"); + return Stdlib_JsError.panic(message !== undefined ? message : "Option.getOrThrow called for None value"); } } diff --git a/lib/es6/Stdlib_Result.js b/lib/es6/Stdlib_Result.js index f896fc897d..191540fa71 100644 --- a/lib/es6/Stdlib_Result.js +++ b/lib/es6/Stdlib_Result.js @@ -1,14 +1,13 @@ +import * as Stdlib_JsError from "./Stdlib_JsError.js"; -function getOrThrow(x) { +function getOrThrow(x, message) { if (x.TAG === "Ok") { return x._0; + } else { + return Stdlib_JsError.panic(message !== undefined ? message : "Result.getOrThrow called for Error value"); } - throw { - RE_EXN_ID: "Not_found", - Error: new Error() - }; } function mapOr(opt, $$default, f) { diff --git a/lib/js/Stdlib_Option.js b/lib/js/Stdlib_Option.js index 6e5ed229c2..e6664fe90a 100644 --- a/lib/js/Stdlib_Option.js +++ b/lib/js/Stdlib_Option.js @@ -1,6 +1,6 @@ 'use strict'; -let Stdlib_Error = require("./Stdlib_Error.js"); +let Stdlib_JsError = require("./Stdlib_JsError.js"); let Primitive_option = require("./Primitive_option.js"); function filter(opt, p) { @@ -21,7 +21,7 @@ function getOrThrow(x, message) { if (x !== undefined) { return Primitive_option.valFromOption(x); } else { - return Stdlib_Error.panic(message !== undefined ? message : "Option.getOrThrow called for None value"); + return Stdlib_JsError.panic(message !== undefined ? message : "Option.getOrThrow called for None value"); } } diff --git a/lib/js/Stdlib_Result.js b/lib/js/Stdlib_Result.js index dcd2561cd5..0205dd16fb 100644 --- a/lib/js/Stdlib_Result.js +++ b/lib/js/Stdlib_Result.js @@ -1,14 +1,13 @@ 'use strict'; +let Stdlib_JsError = require("./Stdlib_JsError.js"); -function getOrThrow(x) { +function getOrThrow(x, message) { if (x.TAG === "Ok") { return x._0; + } else { + return Stdlib_JsError.panic(message !== undefined ? message : "Result.getOrThrow called for Error value"); } - throw { - RE_EXN_ID: "Not_found", - Error: new Error() - }; } function mapOr(opt, $$default, f) { diff --git a/runtime/Stdlib_Option.res b/runtime/Stdlib_Option.res index f6a3800aba..038e26dc42 100644 --- a/runtime/Stdlib_Option.res +++ b/runtime/Stdlib_Option.res @@ -39,7 +39,7 @@ let getOrThrow = (x, ~message=?) => switch x { | Some(x) => x | None => - Stdlib_Error.panic( + Stdlib_JsError.panic( switch message { | None => "Option.getOrThrow called for None value" | Some(message) => message diff --git a/runtime/Stdlib_Option.resi b/runtime/Stdlib_Option.resi index aa121dd618..7a964bf19a 100644 --- a/runtime/Stdlib_Option.resi +++ b/runtime/Stdlib_Option.resi @@ -71,7 +71,7 @@ Option.forEach(None, x => Console.log(x)) // returns () let forEach: (option<'a>, 'a => unit) => unit /** -`getExn(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise raises an exception with the message provided, or a generic message if no message was provided. +`getExn(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise throws an exception with the message provided, or a generic message if no message was provided. ```rescript Option.getExn(Some(3)) == 3 @@ -82,20 +82,20 @@ switch Option.getExn(None) { } switch Option.getExn(None, ~message="was None!") { -| exception _ => assert(true) // Raises an Error with the message "was None!" +| exception _ => assert(true) // Throws a JsError with the message "was None!" | _ => assert(false) } ``` ## Exceptions -- Raises an error if `opt` is `None` +- Throws an error if `opt` is `None` */ @deprecated("Use `getOrThrow` instead") let getExn: (option<'a>, ~message: string=?) => 'a /** -`getOrThrow(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise raises an exception with the message provided, or a generic message if no message was provided. +`getOrThrow(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise throws an exception with the message provided, or a generic message if no message was provided. ```rescript Option.getOrThrow(Some(3)) == 3 @@ -106,14 +106,14 @@ switch Option.getOrThrow(None) { } switch Option.getOrThrow(None, ~message="was None!") { -| exception _ => assert(true) // Raises an Error with the message "was None!" +| exception _ => assert(true) // Throws a JsError with the message "was None!" | _ => assert(false) } ``` ## Exceptions -- Raises an error if `opt` is `None` +- Throws an error if `opt` is `None` */ let getOrThrow: (option<'a>, ~message: string=?) => 'a diff --git a/runtime/Stdlib_Result.res b/runtime/Stdlib_Result.res index 8db2c6b985..47654d231a 100644 --- a/runtime/Stdlib_Result.res +++ b/runtime/Stdlib_Result.res @@ -23,10 +23,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ type t<'res, 'err> = result<'res, 'err> = Ok('res) | Error('err) -let getOrThrow = x => +let getOrThrow = (x, ~message=?) => switch x { | Ok(x) => x - | Error(_) => throw(Not_found) + | Error(_) => + Stdlib_JsError.panic( + switch message { + | None => "Result.getOrThrow called for Error value" + | Some(message) => message + }, + ) } let getExn = getOrThrow diff --git a/runtime/Stdlib_Result.resi b/runtime/Stdlib_Result.resi index 603ecaeddd..3096cf72be 100644 --- a/runtime/Stdlib_Result.resi +++ b/runtime/Stdlib_Result.resi @@ -48,33 +48,43 @@ query operation: type t<'res, 'err> = result<'res, 'err> = Ok('res) | Error('err) /** - `getExn(res)`: when `res` is `Ok(n)`, returns `n` when `res` is `Error(m)`, raise an exception + `getExn(res, ~message=?)` returns `n` if `res` is `Ok(n)`, otherwise throws an exception with the message provided, or a generic message if no message was provided. ```res example Result.getExn(Result.Ok(42)) == 42 switch Result.getExn(Error("Invalid data")) { - | exception Not_found => assert(true) + | exception _ => assert(true) + | _ => assert(false) + } + + switch Result.getExn(Error("Invalid data"), ~message="was Error!") { + | exception _ => assert(true) // Throws a JsError with the message "was Error!" | _ => assert(false) } ``` */ @deprecated("Use 'getOrThrow' instead") -let getExn: result<'a, 'b> => 'a +let getExn: (result<'a, 'b>, ~message: string=?) => 'a /** - `getOrThrow(res)`: when `res` is `Ok(n)`, returns `n` when `res` is `Error(m)`, raise an exception + `getOrThrow(res, ~message=?)` returns `n` if `res` is `Ok(n)`, otherwise throws an exception with the message provided, or a generic message if no message was provided. ```res example Result.getOrThrow(Result.Ok(42)) == 42 switch Result.getOrThrow(Error("Invalid data")) { - | exception Not_found => assert(true) + | exception _ => assert(true) + | _ => assert(false) + } + + switch Result.getOrThrow(Error("Invalid data"), ~message="was Error!") { + | exception _ => assert(true) // Throws a JsError with the message "was Error!" | _ => assert(false) } ``` */ -let getOrThrow: result<'a, 'b> => 'a +let getOrThrow: (result<'a, 'b>, ~message: string=?) => 'a /** `mapOr(res, default, f)`: When res is `Ok(n)`, returns `f(n)`, otherwise `default`. diff --git a/tests/analysis_tests/tests/src/expected/Completion.res.txt b/tests/analysis_tests/tests/src/expected/Completion.res.txt index dbfc94944f..0663346ce6 100644 --- a/tests/analysis_tests/tests/src/expected/Completion.res.txt +++ b/tests/analysis_tests/tests/src/expected/Completion.res.txt @@ -2597,14 +2597,14 @@ Path g "label": "Result.getExn", "kind": 12, "tags": [1], - "detail": "result<'a, 'b> => 'a", - "documentation": {"kind": "markdown", "value": "Deprecated: Use 'getOrThrow' instead\n\n\n `getExn(res)`: when `res` is `Ok(n)`, returns `n` when `res` is `Error(m)`, raise an exception\n\n ```res example\n Result.getExn(Result.Ok(42)) == 42\n \n switch Result.getExn(Error(\"Invalid data\")) {\n | exception Not_found => assert(true)\n | _ => assert(false)\n }\n ```\n"} + "detail": "(result<'a, 'b>, ~message: string=?) => 'a", + "documentation": {"kind": "markdown", "value": "Deprecated: Use 'getOrThrow' instead\n\n\n `getExn(res, ~message=?)` returns `n` if `res` is `Ok(n)`, otherwise throws an exception with the message provided, or a generic message if no message was provided.\n\n ```res example\n Result.getExn(Result.Ok(42)) == 42\n \n switch Result.getExn(Error(\"Invalid data\")) {\n | exception _ => assert(true)\n | _ => assert(false)\n }\n\n switch Result.getExn(Error(\"Invalid data\"), ~message=\"was Error!\") {\n | exception _ => assert(true) // Throws a JsError with the message \"was Error!\"\n | _ => assert(false)\n }\n ```\n"} }, { "label": "Result.getOrThrow", "kind": 12, "tags": [], - "detail": "result<'a, 'b> => 'a", - "documentation": {"kind": "markdown", "value": "\n `getOrThrow(res)`: when `res` is `Ok(n)`, returns `n` when `res` is `Error(m)`, raise an exception\n\n ```res example\n Result.getOrThrow(Result.Ok(42)) == 42\n \n switch Result.getOrThrow(Error(\"Invalid data\")) {\n | exception Not_found => assert(true)\n | _ => assert(false)\n }\n ```\n"} + "detail": "(result<'a, 'b>, ~message: string=?) => 'a", + "documentation": {"kind": "markdown", "value": "\n `getOrThrow(res, ~message=?)` returns `n` if `res` is `Ok(n)`, otherwise throws an exception with the message provided, or a generic message if no message was provided.\n\n ```res example\n Result.getOrThrow(Result.Ok(42)) == 42\n \n switch Result.getOrThrow(Error(\"Invalid data\")) {\n | exception _ => assert(true)\n | _ => assert(false)\n }\n\n switch Result.getOrThrow(Error(\"Invalid data\"), ~message=\"was Error!\") {\n | exception _ => assert(true) // Throws a JsError with the message \"was Error!\"\n | _ => assert(false)\n }\n ```\n"} }, { "label": "Result.getOr", "kind": 12,