diff --git a/pages/docs/manual/v12.0.0/async-await.mdx b/pages/docs/manual/v12.0.0/async-await.mdx index ebe40b49c..1a459ce06 100644 --- a/pages/docs/manual/v12.0.0/async-await.mdx +++ b/pages/docs/manual/v12.0.0/async-await.mdx @@ -130,15 +130,15 @@ You may use `try / catch` or `switch` to handle exceptions during async executio ```res // For simulation purposes let authenticate = async () => { - raise(Exn.raiseRangeError("Authentication failed.")) + JsError.RangeError.throwWithMessage("Authentication failed.") } let checkAuth = async () => { try { await authenticate() } catch { - | Exn.Error(e) => - switch Exn.message(e) { + | JsExn(e) => + switch JsExn.message(e) { | Some(msg) => Console.log("JS error thrown: " ++ msg) | None => Console.log("Some other exception has been thrown") } @@ -152,14 +152,14 @@ You may unify error and value handling in a single switch as well: ```res let authenticate = async () => { - raise(Exn.raiseRangeError("Authentication failed.")) + JsError.RangeError.throwWithMessage("Authentication failed.") } let checkAuth = async () => { switch await authenticate() { | _ => Console.log("ok") - | exception Exn.Error(e) => - switch Exn.message(e) { + | exception JsExn(e) => + switch JsExn.message(e) { | Some(msg) => Console.log("JS error thrown: " ++ msg) | None => Console.log("Some other exception has been thrown") } diff --git a/pages/docs/manual/v12.0.0/exception.mdx b/pages/docs/manual/v12.0.0/exception.mdx index 1fb7facb4..176c48c9e 100644 --- a/pages/docs/manual/v12.0.0/exception.mdx +++ b/pages/docs/manual/v12.0.0/exception.mdx @@ -15,18 +15,18 @@ You can create your own exceptions like you'd make a variant (exceptions need to ```res example exception InputClosed(string) // later on -raise(InputClosed("The stream has closed!")) +throw(InputClosed("The stream has closed!")) ``` ```js -import * as Caml_exceptions from "./stdlib/caml_exceptions.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; -var InputClosed = /* @__PURE__ */Caml_exceptions.create("Playground.InputClosed"); +let InputClosed = /* @__PURE__ */Primitive_exceptions.create("Playground.InputClosed"); throw { - RE_EXN_ID: InputClosed, - _1: "The stream has closed!", - Error: new Error() - }; + RE_EXN_ID: InputClosed, + _1: "The stream has closed!", + Error: new Error() +}; ``` @@ -45,7 +45,7 @@ let getItem = (item: int) => // return the found item here 1 } else { - raise(Not_found) + throw(Not_found) } let result = @@ -56,25 +56,24 @@ let result = } ``` ```js -import * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; function getItem(item) { if (item === 3) { return 1; } throw { - RE_EXN_ID: "Not_found", - Error: new Error() - }; + RE_EXN_ID: "Not_found", + Error: new Error() + }; } -var result; +let result; try { result = getItem(2); -} -catch (raw_exn){ - var exn = Caml_js_exceptions.internalToOCamlException(raw_exn); +} catch (raw_exn) { + let exn = Primitive_exceptions.internalToException(raw_exn); if (exn.RE_EXN_ID === "Not_found") { result = 0; } else { @@ -98,28 +97,27 @@ switch list{1, 2, 3}->List.getExn(4) { } ``` ```js -import * as Core__List from "./stdlib/core__List.js"; -import * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Stdlib_List from "./stdlib/Stdlib_List.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; -var exit = 0; +let exit = 0; -var item; +let item; try { - item = Core__List.getExn({ - hd: 1, - tl: { - hd: 2, - tl: { - hd: 3, - tl: /* [] */0 - } - } - }, 4); + item = Stdlib_List.getExn({ + hd: 1, + tl: { + hd: 2, + tl: { + hd: 3, + tl: /* [] */0 + } + } + }, 4); exit = 1; -} -catch (raw_exn){ - var exn = Caml_js_exceptions.internalToOCamlException(raw_exn); +} catch (raw_exn) { + let exn = Primitive_exceptions.internalToException(raw_exn); if (exn.RE_EXN_ID === "Not_found") { console.log("No such item found!"); } else { @@ -142,7 +140,7 @@ Used to check if argument is valid. This exception takes a string. ```res example let divide = (a, b) => if b == 0 { - raise(Invalid_argument("Denominator is zero")) + throw(Invalid_argument("Denominator is zero")) } else { a / b } @@ -154,25 +152,24 @@ try divide(2, 0)->Console.log catch { ``` ```js -import * as Caml_int32 from "./stdlib/caml_int32.js"; -import * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Primitive_int from "./stdlib/Primitive_int.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; function divide(a, b) { if (b === 0) { throw { - RE_EXN_ID: "Invalid_argument", - _1: "Denominator is zero", - Error: new Error() - }; + RE_EXN_ID: "Invalid_argument", + _1: "Denominator is zero", + Error: new Error() + }; } - return Caml_int32.div(a, b); + return Primitive_int.div(a, b); } try { console.log(divide(2, 0)); -} -catch (raw_msg){ - var msg = Caml_js_exceptions.internalToOCamlException(raw_msg); +} catch (raw_msg) { + let msg = Primitive_exceptions.internalToException(raw_msg); if (msg.RE_EXN_ID === "Invalid_argument") { console.log(msg._1); } else { @@ -185,7 +182,7 @@ catch (raw_msg){ ### `Assert_failure` -Raise when you use `assert(condition)` and `condition` is false. The arguments +Thrown when you use `assert(condition)` and `condition` is false. The arguments are the location of the `assert` in the source code (file name, line number, column number). @@ -208,55 +205,43 @@ try decodeUser(%raw("{}"))->Console.log catch { ``` ```js -mport * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; function decodeUser(json) { - if (!Array.isArray(json) && (json === null || typeof json !== "object") && typeof json !== "number" && typeof json !== "string" && typeof json !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "playground.res", - 8, - 9 - ], - Error: new Error() - }; - } - if (typeof json === "object" && !Array.isArray(json)) { - var match = json["name"]; - var match$1 = json["age"]; - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string" && match$1 !== undefined && !(!Array.isArray(match$1) && (match$1 === null || typeof match$1 !== "object") && typeof match$1 !== "number" && typeof match$1 !== "string" && typeof match$1 !== "boolean") && typeof match$1 === "number") { + if (typeof json === "object" && json !== null && !Array.isArray(json)) { + let match = json["name"]; + let match$1 = json["age"]; + if (typeof match === "string" && typeof match$1 === "number") { return [ - match, - match$1 | 0 - ]; + match, + match$1 | 0 + ]; } throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "playground.res", - 6, - 11 - ], - Error: new Error() - }; + RE_EXN_ID: "Assert_failure", + _1: [ + "playground.res", + 6, + 11 + ], + Error: new Error() + }; } throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "playground.res", - 8, - 9 - ], - Error: new Error() - }; + RE_EXN_ID: "Assert_failure", + _1: [ + "playground.res", + 8, + 9 + ], + Error: new Error() + }; } try { console.log(decodeUser({})); -} -catch (raw_loc){ - var loc = Caml_js_exceptions.internalToOCamlException(raw_loc); +} catch (raw_loc) { + let loc = Primitive_exceptions.internalToException(raw_loc); if (loc.RE_EXN_ID === "Assert_failure") { console.log(loc._1); } else { @@ -269,7 +254,7 @@ catch (raw_loc){ ### `Failure` -Exception raised to signal that the given arguments do not make sense. This +Exception thrown to signal that the given arguments do not make sense. This exception takes a string as an argument. @@ -279,7 +264,7 @@ let isValidEmail = email => { let hasAtSign = String.includes(email, "@") let hasDot = String.includes(email, ".") if !(hasAtSign && hasDot) { - raise(Failure("Invalid email address")) + throw(Failure("Invalid email address")) } else { true } @@ -295,28 +280,27 @@ let isValid = try isValidEmail("rescript.org") catch { ``` ```js -import * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; function isValidEmail(email) { - var hasAtSign = email.includes("@"); - var hasDot = email.includes("."); + let hasAtSign = email.includes("@"); + let hasDot = email.includes("."); if (hasAtSign && hasDot) { return true; } throw { - RE_EXN_ID: "Failure", - _1: "Invalid email address", - Error: new Error() - }; + RE_EXN_ID: "Failure", + _1: "Invalid email address", + Error: new Error() + }; } -var isValid; +let isValid; try { isValid = isValidEmail("rescript.org"); -} -catch (raw_msg){ - var msg = Caml_js_exceptions.internalToOCamlException(raw_msg); +} catch (raw_msg) { + let msg = Primitive_exceptions.internalToException(raw_msg); if (msg.RE_EXN_ID === "Failure") { console.error(msg._1); isValid = false; @@ -330,12 +314,12 @@ catch (raw_msg){ ### `Division_by_zero` -Exception raised by integer division and remainder operations when their second argument is zero. +Exception thrown by integer division and remainder operations when their second argument is zero. ```res example -// ReScript raise `Division_by_zero` if the denominator is zero +// ReScript throws `Division_by_zero` if the denominator is zero let result = try Some(10 / 0) catch { | Division_by_zero => None } @@ -344,16 +328,15 @@ Console.log(result) // None ``` ```js -import * as Caml_int32 from "./stdlib/caml_int32.js"; -import * as Caml_js_exceptions from "./stdlib/caml_js_exceptions.js"; +import * as Primitive_int from "./stdlib/Primitive_int.js"; +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; -var result; +let result; try { - result = Caml_int32.div(10, 0); -} -catch (raw_exn){ - var exn = Caml_js_exceptions.internalToOCamlException(raw_exn); + result = Primitive_int.div(10, 0); +} catch (raw_exn) { + let exn = Primitive_exceptions.internalToException(raw_exn); if (exn.RE_EXN_ID === "Division_by_zero") { result = undefined; } else { @@ -368,7 +351,7 @@ console.log(result); ## Catching JS Exceptions -To distinguish between JavaScript exceptions and ReScript exceptions, ReScript namespaces JS exceptions under the `Exn.Error(payload)` variant. To catch an exception thrown from the JS side: +To distinguish between JavaScript exceptions and ReScript exceptions, ReScript namespaces JS exceptions under the `JsExn(payload)` variant. To catch an exception thrown from the JS side: Throw an exception from JS: @@ -392,32 +375,35 @@ try { // call the external method someJSFunctionThatThrows() } catch { -| Exn.Error(obj) => - switch Exn.message(obj) { +| JsExn(exn) => + switch JsExn.message(exn) { | Some(m) => Console.log("Caught a JS exception! Message: " ++ m) | None => () } } ``` -The `obj` here is of type `Exn.t`, intentionally opaque to disallow illegal operations. To operate on `obj`, do like the code above by using the standard library's [`Exn`](api/js/exn) module's helpers. +The payload `exn` here is of type `unknown` since in JS you can throw anything. To operate on `exn`, do like the code above by using the standard library's [`JsExn`](api/core/jsexn) module's helpers +or use [`Type.Classify.classify`](api/core/type/classify#value-classify) to get more information about the runtime type of `exn`. -## Raise a JS Exception +## Throw a JS Exception -`raise(MyException)` raises a ReScript exception. To raise a JavaScript exception (whatever your purpose is), use `Exn.raiseError`: +### Throw a JS Error + +`throw(MyException)` throws a ReScript exception. To throw a JavaScript error (whatever your purpose is), use `JsError.throwWithMessage`: ```res example let myTest = () => { - Exn.raiseError("Hello!") + JsError.throwWithMessage("Hello!") } ``` ```js -var Js_exn = require("./stdlib/js_exn.js"); +import * as Stdlib_JsError from "./stdlib/Stdlib_JsError.js"; function myTest() { - return Js_exn.raiseError("Hello!"); + return Stdlib_JsError.throwWithMessage("Hello!"); } ``` @@ -434,6 +420,36 @@ try { } ``` +### Throw a value that is not an JS Error + +If you want to throw any value that is not a valid JS Error, use `JsExn.throw`: + + + +```res example +let myTest = () => { + JsExn.throw("some non-error value!") +} +``` +```js +function myTest() { + throw "some non-error value!"; +} +``` + + + +Then you can catch it from the JS side: + +```js +// after importing `myTest`... +try { + myTest() +} catch (message) { + console.log(message) // "Hello!" +} +``` + ## Catch ReScript Exceptions from JS The previous section is less useful than you think; to let your JS code work with your exception-throwing ReScript code, the latter doesn't actually need to throw a JS exception. ReScript exceptions can be used by JS code! @@ -444,13 +460,13 @@ The previous section is less useful than you think; to let your JS code work wit exception BadArgument({myMessage: string}) let myTest = () => { - raise(BadArgument({myMessage: "Oops!"})) + throw(BadArgument({myMessage: "Oops!"})) } ``` ```js -var Caml_exceptions = require("./stdlib/caml_exceptions.js"); +import * as Primitive_exceptions from "./stdlib/Primitive_exceptions.js"; -var BadArgument = Caml_exceptions.create("Playground.BadArgument"); +let BadArgument = /* @__PURE__ */Primitive_exceptions.create("Playground.BadArgument"); function myTest() { throw { @@ -491,7 +507,7 @@ try { } catch { | Not_found => ... // catch a ReScript exception | Invalid_argument(_) => ... // catch a second ReScript exception -| Exn.Error(obj) => ... // catch the JS exception +| JsExn(exn) => ... // catch the JS exception } ``` diff --git a/pages/docs/manual/v12.0.0/function.mdx b/pages/docs/manual/v12.0.0/function.mdx index 73a56051e..8138b32a7 100644 --- a/pages/docs/manual/v12.0.0/function.mdx +++ b/pages/docs/manual/v12.0.0/function.mdx @@ -446,7 +446,7 @@ Both JS exceptions and exceptions defined in ReScript can be caught. The compile ```res example exception SomeReScriptException -let somethingThatMightThrow = async () => raise(SomeReScriptException) +let somethingThatMightThrow = async () => throw(SomeReScriptException) let someAsyncFn = async () => { switch await somethingThatMightThrow() { diff --git a/pages/docs/manual/v12.0.0/lazy-values.mdx b/pages/docs/manual/v12.0.0/lazy-values.mdx index 228912bfa..9e541f608 100644 --- a/pages/docs/manual/v12.0.0/lazy-values.mdx +++ b/pages/docs/manual/v12.0.0/lazy-values.mdx @@ -62,7 +62,7 @@ The first time `Lazy.get` is called, the expensive computation happens and the r ## Exception Handling -For completeness' sake, our files read example might raise an exception because of `readdirSync`. Here's how you'd handle it: +For completeness' sake, our files read example might throw an exception because of `readdirSync`. Here's how you'd handle it: diff --git a/pages/docs/manual/v12.0.0/overview.mdx b/pages/docs/manual/v12.0.0/overview.mdx index 7f3049b73..bb2269eab 100644 --- a/pages/docs/manual/v12.0.0/overview.mdx +++ b/pages/docs/manual/v12.0.0/overview.mdx @@ -187,8 +187,8 @@ canonical: "/docs/manual/v12.0.0/overview" | JavaScript | ReScript | | ----------------------------------------- | -------------------------------------------- | -| `throw new SomeError(...)` | `raise(SomeError(...))` | -| `try {a} catch (err) {...} finally {...}` | `try a catch { \| SomeError(err) => ...}` \* | +| `throw new SomeError(...)` | `throw(SomeException(...))` | +| `try {a} catch (err) {...} finally {...}` | `try a catch { \| SomeException(err) => ...}` \* | \* No finally. diff --git a/pages/docs/manual/v12.0.0/scoped-polymorphic-types.mdx b/pages/docs/manual/v12.0.0/scoped-polymorphic-types.mdx index e0076f9c6..e0c1a3d23 100644 --- a/pages/docs/manual/v12.0.0/scoped-polymorphic-types.mdx +++ b/pages/docs/manual/v12.0.0/scoped-polymorphic-types.mdx @@ -92,9 +92,9 @@ Scoped polymorphic types work only when they are directly applied to let-binding ```res exception Abort -let testExn: 'a. unit => 'a = () => raise(Abort) // Works! +let testExn: 'a. unit => 'a = () => throw(Abort) // Works! -let testExn2 = (): 'a. 'a = raise(Abort) // Syntax error! +let testExn2 = (): 'a. 'a = throw(Abort) // Syntax error! type fn = 'a. 'a => unit // Syntax error! ```