From 1f7f2551ae4ae7223a3245176dde181ae8be2d3e Mon Sep 17 00:00:00 2001 From: tsnobip Date: Sat, 26 Apr 2025 16:47:20 +0200 Subject: [PATCH 1/2] rename JsError to JsExn and create JsError and JsExn modules --- CHANGELOG.md | 4 + .../myplugin/src/Promise.res | 2 +- analysis/reanalyze/src/Exn.ml | 2 +- analysis/reanalyze/src/Exn.mli | 2 +- analysis/reanalyze/src/ExnLib.ml | 42 +-- compiler/core/design.md | 4 +- compiler/frontend/ast_exp_extension.ml | 2 +- compiler/ml/predef.ml | 8 +- lib/es6/Primitive_exceptions.js | 4 +- lib/es6/Stdlib.js | 12 +- lib/es6/Stdlib_Exn.js | 2 +- lib/es6/Stdlib_JsError.js | 70 +++++ lib/es6/Stdlib_JsExn.js | 15 ++ lib/js/Primitive_exceptions.js | 4 +- lib/js/Stdlib.js | 12 +- lib/js/Stdlib_Exn.js | 2 +- lib/js/Stdlib_JsError.js | 68 +++++ lib/js/Stdlib_JsExn.js | 13 + packages/artifacts.txt | 16 ++ runtime/Primitive_exceptions.res | 4 +- runtime/Primitive_exceptions.resi | 2 +- runtime/Stdlib.res | 4 +- runtime/Stdlib_BigInt.res | 2 +- runtime/Stdlib_Error.resi | 19 +- runtime/Stdlib_Exn.res | 2 +- runtime/Stdlib_Exn.resi | 19 +- runtime/Stdlib_JSON.resi | 6 +- runtime/Stdlib_JsError.res | 51 ++++ runtime/Stdlib_JsError.resi | 245 ++++++++++++++++++ runtime/Stdlib_JsExn.res | 18 ++ runtime/Stdlib_JsExn.resi | 97 +++++++ runtime/Stdlib_Object.res | 6 +- runtime/Stdlib_Promise.resi | 4 +- .../deadcode/expected/exception.txt | 2 +- .../deadcode/src/exception/Exn.res | 2 +- .../deadcode/src/exception/ExternalTest.res | 4 +- .../deadcode/src/exception/StdlibTest.res | 6 +- tests/docstring_tests/DocTest.res | 2 +- tests/docstring_tests/DocTest.res.js | 7 +- .../src/DynamicallyLoadedComponent.res.js | 13 - .../src/ExportWithRename.gen.tsx | 10 - .../src/ExportWithRename.res.js | 13 - .../src/Hooks.gen.tsx | 141 ---------- .../typescript-react-example/src/Hooks.res.js | 231 ----------------- .../src/ImportHookDefault.gen.tsx | 54 ---- .../src/ImportHookDefault.res.js | 18 -- .../src/ImportHooks.gen.tsx | 41 --- .../src/ImportHooks.res.js | 15 -- .../src/ImportIndex.gen.tsx | 16 -- .../src/ImportIndex.res.js | 10 - .../src/JSXV4.gen.tsx | 43 --- .../typescript-react-example/src/JSXV4.res.js | 19 -- .../src/MyInput.gen.tsx | 20 -- .../src/MyInput.res.js | 10 - .../src/OnClick2.gen.tsx | 12 - .../src/OnClick2.res.js | 16 -- .../parsing/grammar/expressions/await.res | 2 +- .../expressions/expected/await.res.txt | 2 +- .../data/printer/expr/asyncAwait.res | 2 +- .../printer/expr/expected/asyncAwait.res.txt | 2 +- tests/tests/src/core/Core_ErrorTests.mjs | 3 +- tests/tests/src/core/Core_ErrorTests.res | 2 +- tests/tests/src/core/Core_IntTests.mjs | 7 +- tests/tests/src/core/Core_IntTests.res | 8 +- tests/tests/src/core/Core_PromiseTest.mjs | 4 +- tests/tests/src/core/Core_PromiseTest.res | 4 +- tests/tests/src/core/intl/Core_IntlTests.mjs | 11 +- tests/tests/src/core/intl/Core_IntlTests.res | 14 +- 68 files changed, 741 insertions(+), 788 deletions(-) create mode 100644 lib/es6/Stdlib_JsError.js create mode 100644 lib/es6/Stdlib_JsExn.js create mode 100644 lib/js/Stdlib_JsError.js create mode 100644 lib/js/Stdlib_JsExn.js create mode 100644 runtime/Stdlib_JsError.res create mode 100644 runtime/Stdlib_JsError.resi create mode 100644 runtime/Stdlib_JsExn.res create mode 100644 runtime/Stdlib_JsExn.resi delete mode 100644 tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/Hooks.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportHooks.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/ImportIndex.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/JSXV4.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/MyInput.res.js delete mode 100644 tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/OnClick2.res.js diff --git a/CHANGELOG.md b/CHANGELOG.md index e2d215b786..7180aab912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ # 12.0.0-alpha.13 (Unreleased) +#### :boom: Breaking Change + +- Rename `JsError` to `JsExn` and error modules cleanup. https://github.com/rescript-lang/rescript/pull/7408 + #### :rocket: New Feature - Add shift (`<<`, `>>`, `>>>`) operators for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7183 diff --git a/analysis/examples/workspace-project/myplugin/src/Promise.res b/analysis/examples/workspace-project/myplugin/src/Promise.res index 6a72bfffd9..854789e433 100644 --- a/analysis/examples/workspace-project/myplugin/src/Promise.res +++ b/analysis/examples/workspace-project/myplugin/src/Promise.res @@ -1,6 +1,6 @@ type t<+'a> = Js.Promise.t<'a> -exception JsError(Js.Exn.t) +exception JsExn(Js.Exn.t) external unsafeToJsExn: exn => Js.Exn.t = "%identity" @new diff --git a/analysis/reanalyze/src/Exn.ml b/analysis/reanalyze/src/Exn.ml index c715c7f9aa..1970d035b1 100644 --- a/analysis/reanalyze/src/Exn.ml +++ b/analysis/reanalyze/src/Exn.ml @@ -8,7 +8,7 @@ let endOfFile = "End_of_file" let exit = "exit" let failure = "Failure" let invalidArgument = "Invalid_argument" -let jsExnError = "Exn.Error" +let jsExn = "JsExn" let matchFailure = "Match_failure" let notFound = "Not_found" let sysError = "Sys_error" diff --git a/analysis/reanalyze/src/Exn.mli b/analysis/reanalyze/src/Exn.mli index f591177819..c9c991847d 100644 --- a/analysis/reanalyze/src/Exn.mli +++ b/analysis/reanalyze/src/Exn.mli @@ -10,7 +10,7 @@ val failure : t val fromLid : Longident.t -> t val fromString : string -> t val invalidArgument : t -val jsExnError : t +val jsExn : t val matchFailure : t val notFound : t val sysError : t diff --git a/analysis/reanalyze/src/ExnLib.ml b/analysis/reanalyze/src/ExnLib.ml index c9e7393779..16798d7c36 100644 --- a/analysis/reanalyze/src/ExnLib.ml +++ b/analysis/reanalyze/src/ExnLib.ml @@ -38,8 +38,8 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t = in let stdlib = [ - ("panic", [jsExnError]); - ("assertEqual", [jsExnError]); + ("panic", [jsExn]); + ("assertEqual", [jsExn]); ("invalid_arg", [invalidArgument]); ("failwith", [failure]); ("/", [divisionByZero]); @@ -50,30 +50,30 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t = ("float_of_string", [failure]); ] in - let stdlibBigInt = [("fromStringExn", [jsExnError])] in + let stdlibBigInt = [("fromStringExn", [jsExn])] in let stdlibBool = [("fromStringExn", [invalidArgument])] in - let stdlibError = [("raise", [jsExnError])] in + let stdlibError = [("raise", [jsExn])] in let stdlibExn = [ - ("raiseError", [jsExnError]); - ("raiseEvalError", [jsExnError]); - ("raiseRangeError", [jsExnError]); - ("raiseReferenceError", [jsExnError]); - ("raiseSyntaxError", [jsExnError]); - ("raiseTypeError", [jsExnError]); - ("raiseUriError", [jsExnError]); + ("raiseError", [jsExn]); + ("raiseEvalError", [jsExn]); + ("raiseRangeError", [jsExn]); + ("raiseReferenceError", [jsExn]); + ("raiseSyntaxError", [jsExn]); + ("raiseTypeError", [jsExn]); + ("raiseUriError", [jsExn]); ] in let stdlibJson = [ - ("parseExn", [jsExnError]); - ("parseExnWithReviver", [jsExnError]); - ("stringifyAny", [jsExnError]); - ("stringifyAnyWithIndent", [jsExnError]); - ("stringifyAnyWithReplacer", [jsExnError]); - ("stringifyAnyWithReplacerAndIndent", [jsExnError]); - ("stringifyAnyWithFilter", [jsExnError]); - ("stringifyAnyWithFilterAndIndent", [jsExnError]); + ("parseExn", [jsExn]); + ("parseExnWithReviver", [jsExn]); + ("stringifyAny", [jsExn]); + ("stringifyAnyWithIndent", [jsExn]); + ("stringifyAnyWithReplacer", [jsExn]); + ("stringifyAnyWithReplacerAndIndent", [jsExn]); + ("stringifyAnyWithFilter", [jsExn]); + ("stringifyAnyWithFilterAndIndent", [jsExn]); ] in let stdlibList = @@ -81,7 +81,7 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t = in let stdlibNull = [("getExn", [invalidArgument])] in let stdlibNullable = [("getExn", [invalidArgument])] in - let stdlibOption = [("getExn", [jsExnError])] in + let stdlibOption = [("getExn", [jsExn])] in let stdlibResult = [("getExn", [notFound])] in let yojsonBasic = [("from_string", [yojsonJsonError])] in let yojsonBasicUtil = @@ -144,7 +144,7 @@ let raisesLibTable : (Name.t, Exceptions.t) Hashtbl.t = ("Bool", stdlibBool); ("Error", stdlibError); ("Exn", stdlibExn); - ("Js.Json", [("parseExn", [jsExnError])]); + ("Js.Json", [("parseExn", [jsExn])]); ("JSON", stdlibJson); ("Json_decode", bsJson); ("Json.Decode", bsJson); diff --git a/compiler/core/design.md b/compiler/core/design.md index 50ab484a13..567a8dce77 100644 --- a/compiler/core/design.md +++ b/compiler/core/design.md @@ -372,7 +372,7 @@ function packError(exn){ } } ``` -So whenever we raise an OCaml exception, we always wrapped it as a JS error. +So whenever we raise an OCaml exception, we always wrapped it as a JS exception. Now we unpack it, it could be OCaml exception or JS exception, so we did a runtime dispatch. @@ -381,7 +381,7 @@ Some potential optimization ```ocaml try f x with Not_found -> .. -JsError e +JsExn e ``` currently it would be transalted as diff --git a/compiler/frontend/ast_exp_extension.ml b/compiler/frontend/ast_exp_extension.ml index 47405da03d..0ef83dcfa1 100644 --- a/compiler/frontend/ast_exp_extension.ml +++ b/compiler/frontend/ast_exp_extension.ml @@ -43,7 +43,7 @@ let handle_extension e (self : Bs_ast_mapper.mapper) in Exp.apply ~loc - (Exp.ident ~loc {txt = Longident.parse "Js.Exn.raiseError"; loc}) + (Exp.ident ~loc {txt = Longident.parse "JsError.throwWithMessage"; loc}) [ ( Nolabel, Exp.constant ~loc diff --git a/compiler/ml/predef.ml b/compiler/ml/predef.ml index 6deed6ffa3..f94a939d27 100644 --- a/compiler/ml/predef.ml +++ b/compiler/ml/predef.ml @@ -158,7 +158,7 @@ and ident_error = ident_create_predef_exn "Error" and ident_dict_magic_field_name = ident_create Dict_type_helpers.dict_magic_field_name -and ident_js_error = ident_create_predef_exn "JsError" +and ident_js_exn = ident_create_predef_exn "JsExn" and ident_not_found = ident_create_predef_exn "Not_found" @@ -176,7 +176,7 @@ let all_predef_exns = ident_match_failure; ident_invalid_argument; ident_failure; - ident_js_error; + ident_js_exn; ident_not_found; ident_end_of_file; ident_division_by_zero; @@ -412,7 +412,7 @@ let common_initial_env add_type add_extension empty_env = |> add_exception ident_end_of_file [] |> add_exception ident_not_found [] |> add_exception ident_failure [type_string] - |> add_exception ident_js_error [type_unknown] + |> add_exception ident_js_exn [type_unknown] |> add_exception ident_invalid_argument [type_string] |> add_exception ident_match_failure [newgenty (Ttuple [type_string; type_int; type_int])] @@ -433,7 +433,7 @@ let builtin_values = ident_match_failure; ident_invalid_argument; ident_failure; - ident_js_error; + ident_js_exn; ident_not_found; ident_end_of_file; ident_division_by_zero; diff --git a/lib/es6/Primitive_exceptions.js b/lib/es6/Primitive_exceptions.js index f4fefef083..cadedefca2 100644 --- a/lib/es6/Primitive_exceptions.js +++ b/lib/es6/Primitive_exceptions.js @@ -14,7 +14,7 @@ function internalToException(e) { return e; } else { return { - RE_EXN_ID: "JsError", + RE_EXN_ID: "JsExn", _1: e }; } @@ -33,7 +33,7 @@ function create(str) { return str; } -let $$Error = "JsError"; +let $$Error = "JsExn"; export { $$Error, diff --git a/lib/es6/Stdlib.js b/lib/es6/Stdlib.js index 3f545e797e..bbb1fc648d 100644 --- a/lib/es6/Stdlib.js +++ b/lib/es6/Stdlib.js @@ -1,7 +1,7 @@ -import * as Stdlib_Error from "./Stdlib_Error.js"; import * as Stdlib_Global from "./Stdlib_Global.js"; +import * as Stdlib_JsError from "./Stdlib_JsError.js"; import * as Primitive_object from "./Primitive_object.js"; function assertEqual(a, b) { @@ -12,7 +12,7 @@ function assertEqual(a, b) { RE_EXN_ID: "Assert_failure", _1: [ "Stdlib.res", - 120, + 122, 4 ], Error: new Error() @@ -47,6 +47,10 @@ let Int; let $$Intl; +let JsError; + +let JsExn; + let $$JSON; let Lazy; @@ -117,7 +121,7 @@ let $$BigInt64Array; let $$BigUint64Array; -let panic = Stdlib_Error.panic; +let panic = Stdlib_JsError.panic; export { TimeoutId, @@ -134,6 +138,8 @@ export { Float, Int, $$Intl, + JsError, + JsExn, $$JSON, Lazy, List, diff --git a/lib/es6/Stdlib_Exn.js b/lib/es6/Stdlib_Exn.js index 359ad673e8..548a32b106 100644 --- a/lib/es6/Stdlib_Exn.js +++ b/lib/es6/Stdlib_Exn.js @@ -2,7 +2,7 @@ import * as Primitive_option from "./Primitive_option.js"; -let $$Error = "JsError"; +let $$Error = "JsExn"; function asJsExn(exn) { if (exn.RE_EXN_ID === $$Error) { diff --git a/lib/es6/Stdlib_JsError.js b/lib/es6/Stdlib_JsError.js new file mode 100644 index 0000000000..04fb5fa4d2 --- /dev/null +++ b/lib/es6/Stdlib_JsError.js @@ -0,0 +1,70 @@ + + + +function throwWithMessage(str) { + throw new Error(str); +} + +function throwWithMessage$1(s) { + throw new EvalError(s); +} + +let $$EvalError$1 = { + throwWithMessage: throwWithMessage$1 +}; + +function throwWithMessage$2(s) { + throw new RangeError(s); +} + +let $$RangeError$1 = { + throwWithMessage: throwWithMessage$2 +}; + +function throwWithMessage$3(s) { + throw new ReferenceError(s); +} + +let $$ReferenceError$1 = { + throwWithMessage: throwWithMessage$3 +}; + +function throwWithMessage$4(s) { + throw new SyntaxError(s); +} + +let $$SyntaxError$1 = { + throwWithMessage: throwWithMessage$4 +}; + +function throwWithMessage$5(s) { + throw new TypeError(s); +} + +let $$TypeError$1 = { + throwWithMessage: throwWithMessage$5 +}; + +function throwWithMessage$6(s) { + throw new URIError(s); +} + +let $$URIError$1 = { + throwWithMessage: throwWithMessage$6 +}; + +function panic(msg) { + throw new Error("Panic! " + msg); +} + +export { + $$EvalError$1 as $$EvalError, + $$RangeError$1 as $$RangeError, + $$ReferenceError$1 as $$ReferenceError, + $$SyntaxError$1 as $$SyntaxError, + $$TypeError$1 as $$TypeError, + $$URIError$1 as $$URIError, + throwWithMessage, + panic, +} +/* No side effect */ diff --git a/lib/es6/Stdlib_JsExn.js b/lib/es6/Stdlib_JsExn.js new file mode 100644 index 0000000000..f392e96434 --- /dev/null +++ b/lib/es6/Stdlib_JsExn.js @@ -0,0 +1,15 @@ + + +import * as Primitive_option from "./Primitive_option.js"; + +function fromException(exn) { + if (exn.RE_EXN_ID === "JsExn") { + return Primitive_option.some(exn._1); + } + +} + +export { + fromException, +} +/* No side effect */ diff --git a/lib/js/Primitive_exceptions.js b/lib/js/Primitive_exceptions.js index 49bf58ee20..64ad6fdaa7 100644 --- a/lib/js/Primitive_exceptions.js +++ b/lib/js/Primitive_exceptions.js @@ -14,7 +14,7 @@ function internalToException(e) { return e; } else { return { - RE_EXN_ID: "JsError", + RE_EXN_ID: "JsExn", _1: e }; } @@ -33,7 +33,7 @@ function create(str) { return str; } -let $$Error = "JsError"; +let $$Error = "JsExn"; exports.$$Error = $$Error; exports.create = create; diff --git a/lib/js/Stdlib.js b/lib/js/Stdlib.js index 05e4d91e25..283c1d3303 100644 --- a/lib/js/Stdlib.js +++ b/lib/js/Stdlib.js @@ -1,7 +1,7 @@ 'use strict'; -let Stdlib_Error = require("./Stdlib_Error.js"); let Stdlib_Global = require("./Stdlib_Global.js"); +let Stdlib_JsError = require("./Stdlib_JsError.js"); let Primitive_object = require("./Primitive_object.js"); function assertEqual(a, b) { @@ -12,7 +12,7 @@ function assertEqual(a, b) { RE_EXN_ID: "Assert_failure", _1: [ "Stdlib.res", - 120, + 122, 4 ], Error: new Error() @@ -47,6 +47,10 @@ let Int; let $$Intl; +let JsError; + +let JsExn; + let $$JSON; let Lazy; @@ -117,7 +121,7 @@ let $$BigInt64Array; let $$BigUint64Array; -let panic = Stdlib_Error.panic; +let panic = Stdlib_JsError.panic; exports.TimeoutId = TimeoutId; exports.IntervalId = IntervalId; @@ -133,6 +137,8 @@ exports.$$Error = $$Error; exports.Float = Float; exports.Int = Int; exports.$$Intl = $$Intl; +exports.JsError = JsError; +exports.JsExn = JsExn; exports.$$JSON = $$JSON; exports.Lazy = Lazy; exports.List = List; diff --git a/lib/js/Stdlib_Exn.js b/lib/js/Stdlib_Exn.js index 4c3f4fa255..80dd97cc96 100644 --- a/lib/js/Stdlib_Exn.js +++ b/lib/js/Stdlib_Exn.js @@ -2,7 +2,7 @@ let Primitive_option = require("./Primitive_option.js"); -let $$Error = "JsError"; +let $$Error = "JsExn"; function asJsExn(exn) { if (exn.RE_EXN_ID === $$Error) { diff --git a/lib/js/Stdlib_JsError.js b/lib/js/Stdlib_JsError.js new file mode 100644 index 0000000000..3e6a4d822c --- /dev/null +++ b/lib/js/Stdlib_JsError.js @@ -0,0 +1,68 @@ +'use strict'; + + +function throwWithMessage(str) { + throw new Error(str); +} + +function throwWithMessage$1(s) { + throw new EvalError(s); +} + +let $$EvalError$1 = { + throwWithMessage: throwWithMessage$1 +}; + +function throwWithMessage$2(s) { + throw new RangeError(s); +} + +let $$RangeError$1 = { + throwWithMessage: throwWithMessage$2 +}; + +function throwWithMessage$3(s) { + throw new ReferenceError(s); +} + +let $$ReferenceError$1 = { + throwWithMessage: throwWithMessage$3 +}; + +function throwWithMessage$4(s) { + throw new SyntaxError(s); +} + +let $$SyntaxError$1 = { + throwWithMessage: throwWithMessage$4 +}; + +function throwWithMessage$5(s) { + throw new TypeError(s); +} + +let $$TypeError$1 = { + throwWithMessage: throwWithMessage$5 +}; + +function throwWithMessage$6(s) { + throw new URIError(s); +} + +let $$URIError$1 = { + throwWithMessage: throwWithMessage$6 +}; + +function panic(msg) { + throw new Error("Panic! " + msg); +} + +exports.$$EvalError = $$EvalError$1; +exports.$$RangeError = $$RangeError$1; +exports.$$ReferenceError = $$ReferenceError$1; +exports.$$SyntaxError = $$SyntaxError$1; +exports.$$TypeError = $$TypeError$1; +exports.$$URIError = $$URIError$1; +exports.throwWithMessage = throwWithMessage; +exports.panic = panic; +/* No side effect */ diff --git a/lib/js/Stdlib_JsExn.js b/lib/js/Stdlib_JsExn.js new file mode 100644 index 0000000000..6e0dc49505 --- /dev/null +++ b/lib/js/Stdlib_JsExn.js @@ -0,0 +1,13 @@ +'use strict'; + +let Primitive_option = require("./Primitive_option.js"); + +function fromException(exn) { + if (exn.RE_EXN_ID === "JsExn") { + return Primitive_option.some(exn._1); + } + +} + +exports.fromException = fromException; +/* No side effect */ diff --git a/packages/artifacts.txt b/packages/artifacts.txt index adfa893f3b..97400097da 100644 --- a/packages/artifacts.txt +++ b/packages/artifacts.txt @@ -177,6 +177,8 @@ lib/es6/Stdlib_Intl_Segmenter.js lib/es6/Stdlib_Intl_Segments.js lib/es6/Stdlib_Iterator.js lib/es6/Stdlib_JSON.js +lib/es6/Stdlib_JsError.js +lib/es6/Stdlib_JsExn.js lib/es6/Stdlib_Lazy.js lib/es6/Stdlib_List.js lib/es6/Stdlib_Map.js @@ -350,6 +352,8 @@ lib/js/Stdlib_Intl_Segmenter.js lib/js/Stdlib_Intl_Segments.js lib/js/Stdlib_Iterator.js lib/js/Stdlib_JSON.js +lib/js/Stdlib_JsError.js +lib/js/Stdlib_JsExn.js lib/js/Stdlib_Lazy.js lib/js/Stdlib_List.js lib/js/Stdlib_Map.js @@ -1103,6 +1107,18 @@ lib/ocaml/Stdlib_JSON.cmt lib/ocaml/Stdlib_JSON.cmti lib/ocaml/Stdlib_JSON.res lib/ocaml/Stdlib_JSON.resi +lib/ocaml/Stdlib_JsError.cmi +lib/ocaml/Stdlib_JsError.cmj +lib/ocaml/Stdlib_JsError.cmt +lib/ocaml/Stdlib_JsError.cmti +lib/ocaml/Stdlib_JsError.res +lib/ocaml/Stdlib_JsError.resi +lib/ocaml/Stdlib_JsExn.cmi +lib/ocaml/Stdlib_JsExn.cmj +lib/ocaml/Stdlib_JsExn.cmt +lib/ocaml/Stdlib_JsExn.cmti +lib/ocaml/Stdlib_JsExn.res +lib/ocaml/Stdlib_JsExn.resi lib/ocaml/Stdlib_Lazy.cmi lib/ocaml/Stdlib_Lazy.cmj lib/ocaml/Stdlib_Lazy.cmt diff --git a/runtime/Primitive_exceptions.res b/runtime/Primitive_exceptions.res index dae327dff3..d36281d2a1 100644 --- a/runtime/Primitive_exceptions.res +++ b/runtime/Primitive_exceptions.res @@ -27,7 +27,7 @@ module Js = Primitive_js_extern type t = {@as("RE_EXN_ID") id: string} -exception Error = JsError +exception Error = JsExn type js_error = {cause: exn} /** @@ -76,7 +76,7 @@ let internalToException = (e: unknown) => if isExtension(e) { (Obj.magic(e): exn) } else { - JsError(e) + JsExn(e) } module Dict = { diff --git a/runtime/Primitive_exceptions.resi b/runtime/Primitive_exceptions.resi index 9662bedfcf..9632c3c2ca 100644 --- a/runtime/Primitive_exceptions.resi +++ b/runtime/Primitive_exceptions.resi @@ -1,4 +1,4 @@ -exception Error = JsError +exception Error = JsExn type js_error = {cause: exn} // TODO: remove legacy exn representation diff --git a/runtime/Stdlib.res b/runtime/Stdlib.res index 6c72f2b12d..f020f0d5aa 100644 --- a/runtime/Stdlib.res +++ b/runtime/Stdlib.res @@ -12,6 +12,8 @@ module Error = Stdlib_Error module Float = Stdlib_Float module Int = Stdlib_Int module Intl = Stdlib_Intl +module JsError = Stdlib_JsError +module JsExn = Stdlib_JsExn module JSON = Stdlib_JSON module Lazy = Stdlib_Lazy module List = Stdlib_List @@ -102,7 +104,7 @@ async function main() { */ external import: 'a => promise<'a> = "%import" -let panic = Error.panic +let panic = JsError.panic /** `assertEqual(a, b)` check if `a` is equal `b`. If not raise a panic exception diff --git a/runtime/Stdlib_BigInt.res b/runtime/Stdlib_BigInt.res index dddd46180b..db860210dd 100644 --- a/runtime/Stdlib_BigInt.res +++ b/runtime/Stdlib_BigInt.res @@ -28,7 +28,7 @@ BigInt.fromStringExn("0o11")->assertEqual(9n) /* catch exception */ switch BigInt.fromStringExn("a") { -| exception Exn.Error(_error) => assert(true) +| exception JsExn(_error) => assert(true) | _bigInt => assert(false) } ``` diff --git a/runtime/Stdlib_Error.resi b/runtime/Stdlib_Error.resi index 45cbed665d..87c095eb37 100644 --- a/runtime/Stdlib_Error.resi +++ b/runtime/Stdlib_Error.resi @@ -5,8 +5,10 @@ See [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ */ /** Represents a JavaScript exception. */ +@deprecated("Use `JsError.t` instead") type t = Stdlib_Exn.t +@deprecated("Use `JsExn.fromException` instead") let fromException: exn => option /** @@ -19,6 +21,7 @@ let error = Error.make("Something went wrong.") let asExn = error->Error.toException // `asExn` is now type `exn` ``` */ +@deprecated("Use functions from `JsExn` instead") external toException: t => exn = "%identity" /** @@ -32,6 +35,7 @@ let error = Error.make("error") Console.log(error->Error.stack) // Logs `stack` if it exists on `someError` ``` */ +@deprecated("Use `JsError.stack` instead") @get external stack: t => option = "stack" @@ -46,6 +50,7 @@ let error = Error.SyntaxError.make("Some message here") Console.log(error->Error.message) // Logs "Some message here" to the console ``` */ +@deprecated("Use `JsError.message` instead") @get external message: t => option = "message" @@ -60,6 +65,7 @@ let error = Error.SyntaxError.make("Some message here") Console.log(error->Error.name) // Logs "SyntaxError" to the console ``` */ +@deprecated("Use `JsError.name` instead") @get external name: t => option = "name" @@ -68,6 +74,7 @@ external name: t => option = "name" See [`Error.prototype.fileName`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName) on MDN. */ +@deprecated("Use `JsError.fileName` instead") @get external fileName: t => option = "fileName" @@ -83,6 +90,7 @@ Console.log(error->Error.message) // Logs "Some message here" to the console Console.log(error->Error.name) // Logs "Error" to the console, because this is a regular error ``` */ +@deprecated("Use `JsError.make` instead") @new external make: string => t = "Error" @@ -92,6 +100,7 @@ module EvalError: { See [`EvalError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError) on MDN. */ + @deprecated("Use `JsError.EvalError.make` instead") @new external make: string => t = "EvalError" } @@ -101,6 +110,7 @@ module RangeError: { See [`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) on MDN. */ + @deprecated("Use `JsError.RangeError.make` instead") @new external make: string => t = "RangeError" } @@ -110,6 +120,7 @@ module ReferenceError: { See [`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) on MDN. */ + @deprecated("Use `JsError.ReferenceError.make` instead") @new external make: string => t = "ReferenceError" } @@ -119,6 +130,7 @@ module SyntaxError: { See [`SyntaxError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError) on MDN. */ + @deprecated("Use `JsError.SyntaxError.make` instead") @new external make: string => t = "SyntaxError" } @@ -128,6 +140,7 @@ module TypeError: { See [`TypeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) on MDN. */ + @deprecated("Use `JsError.TypeError.make` instead") @new external make: string => t = "TypeError" } @@ -137,6 +150,7 @@ module URIError: { See [`URIError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError) on MDN. */ + @deprecated("Use `JsError.URIError.make` instead") @new external make: string => t = "URIError" } @@ -156,7 +170,7 @@ if 5 > 10 { ``` */ @deprecated( - "`raise` has been renamed to `throw` to align with JavaScript vocabulary. Please use `throw` instead" + "`raise` has been renamed to `throw` to align with JavaScript vocabulary. Please use `JsError.throw` instead" ) external raise: t => 'a = "%raise" @@ -175,6 +189,7 @@ if 5 > 10 { } ``` */ +@deprecated("Use `JsError.throw` instead") external throw: t => 'a = "%raise" /** @@ -199,6 +214,7 @@ try { } ``` */ +@deprecated("Use `JsError.panic` instead") let panic: string => 'a /** @@ -207,4 +223,5 @@ let panic: string => 'a This helper is useful when you want to discard a value (for example, the result of an operation with side effects) without having to store or process it further. */ +@deprecated("Use `JsError.ignore` instead") external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_Exn.res b/runtime/Stdlib_Exn.res index 20e6753680..ecb78572b3 100644 --- a/runtime/Stdlib_Exn.res +++ b/runtime/Stdlib_Exn.res @@ -25,7 +25,7 @@ type t = unknown @@warning("-38") /* unused extension constructor */ -exception Error = JsError +exception Error = JsExn let asJsExn: exn => option = exn => switch Obj.magic(exn) { diff --git a/runtime/Stdlib_Exn.resi b/runtime/Stdlib_Exn.resi index 9f66de23c2..5842b83694 100644 --- a/runtime/Stdlib_Exn.resi +++ b/runtime/Stdlib_Exn.resi @@ -27,16 +27,18 @@ Provide utilities for dealing with JS exceptions. */ /** Represents a JS exception */ +@deprecated("Use `JsExn.t` instead") type t type exn += private Error(t) +@deprecated("Use `JsExn.fromException` instead") let asJsExn: exn => option -@get external stack: t => option = "stack" -@get external message: t => option = "message" -@get external name: t => option = "name" -@get external fileName: t => option = "fileName" +@deprecated("Use `JsExn.stack` instead") @get external stack: t => option = "stack" +@deprecated("Use `JsExn.message` instead") @get external message: t => option = "message" +@deprecated("Use `JsExn.name` instead") @get external name: t => option = "name" +@deprecated("Use `JsExn.fileName` instead") @get external fileName: t => option = "fileName" /** `anyToExnInternal(obj)` will take any value `obj` and wrap it @@ -49,15 +51,23 @@ a value passed to a Promise.catch callback) **IMPORTANT**: This is an internal API and may be changed / removed any time in the future. */ +@deprecated("Use `JsExn.anyToExnInternal` instead") external anyToExnInternal: 'a => exn = "%wrap_exn" /** Raise Js exception Error object with stacktrace */ +@deprecated("Use `JsError.throwWithMessage` instead") let raiseError: string => 'a +@deprecated("Use `JsError.EvalError.throwWithMessage` instead") let raiseEvalError: string => 'a +@deprecated("Use `JsError.RangeError.throwWithMessage` instead") let raiseRangeError: string => 'a +@deprecated("Use `JsError.ReferenceError.throwWithMessage` instead") let raiseReferenceError: string => 'a +@deprecated("Use `JsError.SyntaxError.throwWithMessage` instead") let raiseSyntaxError: string => 'a +@deprecated("Use `JsError.TypeError.throwWithMessage` instead") let raiseTypeError: string => 'a +@deprecated("Use `JsError.URIError.throwWithMessage` instead") let raiseUriError: string => 'a /** @@ -66,4 +76,5 @@ let raiseUriError: string => 'a This helper is useful when you want to discard a value (for example, the result of an operation with side effects) without having to store or process it further. */ +@deprecated("Use `JsExn.ignore` instead") external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_JSON.resi b/runtime/Stdlib_JSON.resi index d0218ac3d0..9b816feb02 100644 --- a/runtime/Stdlib_JSON.resi +++ b/runtime/Stdlib_JSON.resi @@ -33,7 +33,7 @@ try { let _ = JSON.parseExn("") // error } catch { -| Exn.Error(_) => Console.log("error") +| JsExn(_) => Console.log("error") } let reviver = (_, value: JSON.t) => @@ -52,7 +52,7 @@ try { JSON.parseExn("", ~reviver)->Console.log // error } catch { -| Exn.Error(_) => Console.log("error") +| JsExn(_) => Console.log("error") } ``` @@ -89,7 +89,7 @@ try { JSON.parseExnWithReviver("", reviver)->Console.log // error } catch { -| Exn.Error(_) => Console.log("error") +| JsExn(_) => Console.log("error") } ``` diff --git a/runtime/Stdlib_JsError.res b/runtime/Stdlib_JsError.res new file mode 100644 index 0000000000..17ff192439 --- /dev/null +++ b/runtime/Stdlib_JsError.res @@ -0,0 +1,51 @@ +type t + +@get external stack: t => option = "stack" +@get external message: t => string = "message" +@get external name: t => string = "name" +@get external fileName: t => option = "fileName" + +@new external make: string => t = "Error" + +external throw: t => 'a = "%raise" + +let throwWithMessage = str => { + let error = make(str) + throw(error) +} + +module EvalError = { + @new external make: string => t = "EvalError" + let throwWithMessage = s => make(s)->throw +} + +module RangeError = { + @new external make: string => t = "RangeError" + let throwWithMessage = s => make(s)->throw +} + +module ReferenceError = { + @new external make: string => t = "ReferenceError" + let throwWithMessage = s => make(s)->throw +} + +module SyntaxError = { + @new external make: string => t = "SyntaxError" + let throwWithMessage = s => make(s)->throw +} + +module TypeError = { + @new external make: string => t = "TypeError" + let throwWithMessage = s => make(s)->throw +} + +module URIError = { + @new external make: string => t = "URIError" + let throwWithMessage = s => make(s)->throw +} + +let panic = msg => make(`Panic! ${msg}`)->throw + +external toJsExn: t => Stdlib_JsExn.t = "%identity" + +external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_JsError.resi b/runtime/Stdlib_JsError.resi new file mode 100644 index 0000000000..9f55fd7a82 --- /dev/null +++ b/runtime/Stdlib_JsError.resi @@ -0,0 +1,245 @@ +/*** +Functions for working with JavaScript errors. + +See [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) on MDN. +*/ + +/** Represents a JavaScript error. */ +type t + +/** +`stack(error)` retrieves the `stack` property of the error, if it exists. The stack is a list of what functions were called, and what files they are defined in, prior to the error happening. + +See [`Error.prototype.stack`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack) on MDN. + +## Example +```rescript +let error = JsError.make("error") +Console.log(error->JsError.stack) // Logs `stack` if it exists on `someError` +``` +*/ +@get +external stack: t => option = "stack" + +/** +`message(error)` retrieves the `message` property of the error. + +See [`Error.prototype.message`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message) on MDN. + +## Example +```rescript +let error = JsError.SyntaxError.make("Some message here") +error->JsError.message->assertEqual("Some message here") +``` +*/ +@get +external message: t => string = "message" + +/** +`name(error)` retrieves the `name` property of the error. + +See [`Error.prototype.name`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name) on MDN. + +## Example +```rescript +let error = JsError.SyntaxError.make("Some message here") +error->JsError.name->assertEqual("SyntaxError") +``` +*/ +@get +external name: t => string = "name" + +/** +`fileName(error)` retrieves the `fileName` property of the error, if it exists. + +See [`Error.prototype.fileName`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName) on MDN. +*/ +@get +external fileName: t => option = "fileName" + +/** +`make(message)` creates a new error, setting its `message` to the provided value. + +See [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error) on MDN. + +## Example +```rescript +let error = JsError.make("Some message here") +error->JsError.message->assertEqual("Some message here") +error->JsError.name->assertEqual("Error") +```` +*/ +@new +external make: string => t = "Error" + +module EvalError: { + /** + Creates a new `EvalError` with the provided `message`. + + See [`EvalError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError) on MDN. + */ + @new + external make: string => t = "EvalError" + + /** + Creates a new `EvalError` with the provided `message` and throws it. + + `JsError.EvalError.throwWithMessage("message")` is equivalent to `JsError.EvalError.make("message")->JsError.throw`. + + See [`EvalError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError) on MDN. + */ + let throwWithMessage: string => 'a +} +module RangeError: { + /** + Creates a new `RangeError` with the provided `message`. + + See [`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) on MDN. + */ + @new + external make: string => t = "RangeError" + + /** + Creates a new `RangeError` with the provided `message` and throws it. + + `JsError.RangeError.throwWithMessage("message")` is equivalent to `JsError.RangeError.make("message")->JsError.throw`. + + See [`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) on MDN. + */ + let throwWithMessage: string => 'a +} +module ReferenceError: { + /** + Creates a new `ReferenceError` with the provided `message`. + + See [`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) on MDN. + */ + @new + external make: string => t = "ReferenceError" + + /** + Creates a new `ReferenceError` with the provided `message` and throws it. + + `JsError.ReferenceError.throwWithMessage("message")` is equivalent to `JsError.ReferenceError.make("message")->JsError.throw`. + + See [`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) on MDN. + */ + let throwWithMessage: string => 'a +} +module SyntaxError: { + /** + Creates a new `SyntaxError` with the provided `message`. + + See [`SyntaxError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError) on MDN. + */ + @new + external make: string => t = "SyntaxError" + + /** + Creates a new `SyntaxError` with the provided `message` and throws it. + + `JsError.SyntaxError.throwWithMessage("message")` is equivalent to `JsError.SyntaxError.make("message")->JsError.throw`. + + See [`SyntaxError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError) on MDN. + */ + let throwWithMessage: string => 'a +} +module TypeError: { + /** + Creates a new `TypeError` with the provided `message`. + + See [`TypeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) on MDN. + */ + @new + external make: string => t = "TypeError" + + /** + Creates a new `TypeError` with the provided `message` and throws it. + + `JsError.TypeError.throwWithMessage("message")` is equivalent to `JsError.TypeError.make("message")->JsError.throw`. + + See [`TypeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) on MDN. + */ + let throwWithMessage: string => 'a +} +module URIError: { + /** + Creates a new `URIError` with the provided `message`. + + See [`URIError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError) on MDN. + */ + @new + external make: string => t = "URIError" + + /** + Creates a new `URIError` with the provided `message` and throws it. + + `JsError.URIError.throwWithMessage("message")` is equivalent to `JsError.URIError.make("message")->JsError.throw`. + + See [`URIError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError) on MDN. + */ + let throwWithMessage: string => 'a +} + +/** +Throws the given error, terminating execution unless caught by a surrounding try/catch block. + +## Examples + +```rescript +let error = JsError.make("Everything is upside down.") + +if 5 > 10 { + JsError.throw(error) +} else { + Console.log("Phew, sanity still rules.") +} +``` +*/ +external throw: t => 'a = "%raise" + +/** +Creates a new `Error` with the provided `message` and throws it. + +`JsError.throwWithMessage("message")` is equivalent to `JsError.make("message")->JsError.throw`. +*/ +let throwWithMessage: string => 'a + +/** +Throws a panic exception with the given message. + +A panic exception is a native JavaScript exception that is not intended to be caught and +handled. Compared to a ReScript exception this will give a better stack trace and +debugging experience. + +## Examples + +```rescript +try { + JsError.panic("Uh oh. This was unexpected!") +} catch { +| JsExn(obj) => + switch JsExn.message(obj) { + | Some(m) => assert(m == "Panic! Uh oh. This was unexpected!") + | None => assert(false) + } +| _ => assert(false) +} +``` +*/ +let panic: string => 'a + +/** +Casts a `JsError.t` to a `JsExn.t`. + +This is useful when you want to compare a JS exception and a JS error. +*/ +external toJsExn: t => Stdlib_JsExn.t = "%identity" + +/** + `ignore(error)` ignores the provided error and returns unit. + + This helper is useful when you want to discard a value (for example, the result of an operation with side effects) + without having to store or process it further. +*/ +external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_JsExn.res b/runtime/Stdlib_JsExn.res new file mode 100644 index 0000000000..92cd620710 --- /dev/null +++ b/runtime/Stdlib_JsExn.res @@ -0,0 +1,18 @@ +type t = unknown + +let fromException: exn => option = exn => + switch exn { + | JsExn(t) => Some(t) + | _ => None + } + +external anyToExnInternal: 'a => exn = "%wrap_exn" + +@get external stack: t => option = "stack" +@get external message: t => option = "message" +@get external name: t => option = "name" +@get external fileName: t => option = "fileName" + +external throw: 'a => 'b = "%raise" + +external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_JsExn.resi b/runtime/Stdlib_JsExn.resi new file mode 100644 index 0000000000..917b355ac6 --- /dev/null +++ b/runtime/Stdlib_JsExn.resi @@ -0,0 +1,97 @@ +/*** +Provide utilities for dealing with JS exceptions. + +JS exceptions can be of any type, even though they *should* be of type `Error` of one of its subclasses. + +See [`throw`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw) on MDN. + +*/ + +/** Represents a JS exception */ +type t = unknown + +let fromException: exn => option + +/** +`anyToExnInternal(obj)` will take any value `obj` and wrap it +in a JsExn if given value is not an exn already. If +`obj` is an exn, it will return `obj` without any changes. + +This function is mostly useful for cases where you want to unify a type of a value +that potentially is either exn, a JS error, or any other JS value really (e.g. for +a value passed to a Promise.catch callback) + +**IMPORTANT**: This is an internal API and may be changed / removed any time in the future. +*/ +external anyToExnInternal: 'a => exn = "%wrap_exn" + +/** +`stack(jsExn)` retrieves the `stack` property of the exception, if it exists. The stack is a list of what functions were called, and what files they are defined in, prior to the error happening. + +See [`Error.prototype.stack`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack) on MDN. + +## Example +```rescript +try {JsError.make("error")->JsError.throw} catch { +| JsExn(e) => Console.log(JsExn.stack(e)) // Logs `stack` +| _ => assert(false) +} +``` +*/ +@get +external stack: t => option = "stack" + +/** +`message(error)` retrieves the `message` property of the error, if it exists. + +See [`Error.prototype.message`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message) on MDN. + +## Example +```rescript +try {JsError.SyntaxError.throwWithMessage("Some message here")} catch { +| JsExn(e) => e->JsExn.message->Option.getExn->assertEqual("Some message here") +| _ => assert(false) +} +``` +*/ +@get +external message: t => option = "message" + +/** +`name(error)` retrieves the `name` property of the error, if it exists. + +See [`Error.prototype.name`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name) on MDN. + +## Example +```rescript +try {JsError.SyntaxError.throwWithMessage("Some message here")} catch { +| JsExn(e) => e->JsExn.name->Option.getExn->assertEqual("SyntaxError") +| _ => assert(false) +} +``` +*/ +@get +external name: t => option = "name" + +/** +`fileName(error)` retrieves the `fileName` property of the error, if it exists. + +See [`Error.prototype.fileName`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName) on MDN. +*/ +@get +external fileName: t => option = "fileName" + +/** +Throws the given value, terminating execution unless caught by a surrounding try/catch block. + +This is meant to be used when a JS API is based on throwing values that are not of type `Error` or its subclasses. +*/ +external throw: 'a => 'b = "%raise" + +/** + `ignore(jsExn)` ignores the provided JS exception and returns unit. + + This helper is useful when you want to discard a value (for example, the result of an operation with side effects) + without having to store or process it further. +*/ +external ignore: t => unit = "%ignore" diff --git a/runtime/Stdlib_Object.res b/runtime/Stdlib_Object.res index 84ec1220e9..f2304cf1ef 100644 --- a/runtime/Stdlib_Object.res +++ b/runtime/Stdlib_Object.res @@ -190,7 +190,7 @@ point->Object.seal->ignore try { point->Object.set("z", 9) // fails } catch { -| Exn.Error(_) => assert(true) +| JsExn(_) => assert(true) | _ => assert(false) } @@ -214,7 +214,7 @@ obj->Object.preventExtensions->ignore try { obj->Object.set("c", 3) // fails } catch { -| Exn.Error(_) => assert(true) +| JsExn(_) => assert(true) | _ => assert(false) } ``` @@ -239,7 +239,7 @@ obj->Object.freeze->ignore try { obj->Object.set("a", 3) // fails } catch { -| Exn.Error(_) => assert(true) +| JsExn(_) => assert(true) | _ => assert(false) } ``` diff --git a/runtime/Stdlib_Promise.resi b/runtime/Stdlib_Promise.resi index 6de24738c5..a1fd1def74 100644 --- a/runtime/Stdlib_Promise.resi +++ b/runtime/Stdlib_Promise.resi @@ -135,8 +135,8 @@ reject(SomeError("this is an error")) ->catch(e => { let msg = switch(e) { | SomeError(msg) => "ReScript error occurred: " ++ msg - | Exn.Error(obj) => - switch Exn.message(obj) { + | JsExn(obj) => + switch JsExn.message(obj) { | Some(msg) => "JS exception occurred: " ++ msg | None => "Some other JS value has been thrown" } diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt b/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt index 9d087d9e01..9bd59a72cc 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt +++ b/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt @@ -94,6 +94,6 @@ Exception Analysis ExternalTest.res:7:5-24 - bigIntFromStringExn2 might raise Exn.Error (ExternalTest.res:7:35) and is not annotated with @raises(Exn.Error) + bigIntFromStringExn2 might raise JsExn (ExternalTest.res:7:35) and is not annotated with @raises(JsExn) Analysis reported 24 issues (Exception Analysis:24) diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/Exn.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/Exn.res index 1a51cda096..79fd0f55f9 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/Exn.res +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/Exn.res @@ -115,7 +115,7 @@ let raisePipe = raise(Not_found) @raises(Not_found) let raiseArrow = Not_found->raise -@raises(Exn.Error) +@raises(JsExn) let bar = () => Js.Json.parseExn("!!!") let severalCases = cases => diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExternalTest.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExternalTest.res index b5a0134c5c..acd09217a3 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExternalTest.res +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExternalTest.res @@ -1,7 +1,7 @@ -@raises(Exn.Error) +@raises(JsExn) external bigIntFromStringExn: string => bigint = "BigInt" -@raises(Exn.Error) +@raises(JsExn) let bigIntFromStringExn = s => s->bigIntFromStringExn let bigIntFromStringExn2 = s => s->bigIntFromStringExn diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/StdlibTest.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/StdlibTest.res index 2a74754966..13b1136e82 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/StdlibTest.res +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/StdlibTest.res @@ -1,4 +1,4 @@ -@raises(Exn.Error) +@raises(JsExn) let optionGetExn = o => o->Option.getExn @raises(Not_found) @@ -7,8 +7,8 @@ let resultGetExn = r => r->Result.getExn @raises(Invalid_argument) let nullGetExn = n => n->Null.getExn -@raises(Exn.Error) +@raises(JsExn) let bigIntFromStringExn = s => s->BigInt.fromStringExn -@raises(Exn.Error) +@raises(JsExn) let jsonParseExn = s => s->JSON.parseExn diff --git a/tests/docstring_tests/DocTest.res b/tests/docstring_tests/DocTest.res index f974435984..305b2ced66 100644 --- a/tests/docstring_tests/DocTest.res +++ b/tests/docstring_tests/DocTest.res @@ -57,7 +57,7 @@ let extractDocFromFile = async file => { ->JSON.parseExn ->Docgen.decodeFromJson } catch { - | Exn.Error(_) => Error.panic(`Failed to generate docstrings from ${file}`) + | JsExn(_) => JsError.panic(`Failed to generate docstrings from ${file}`) | _ => assert(false) } } diff --git a/tests/docstring_tests/DocTest.res.js b/tests/docstring_tests/DocTest.res.js index 2c75b3a9ad..7fda54793a 100644 --- a/tests/docstring_tests/DocTest.res.js +++ b/tests/docstring_tests/DocTest.res.js @@ -9,13 +9,12 @@ import * as Nodepath from "node:path"; import * as ArrayUtils from "./ArrayUtils.res.js"; import * as Belt_Array from "rescript/lib/es6/Belt_Array.js"; import * as SpawnAsync from "./SpawnAsync.res.js"; -import * as Stdlib_Exn from "rescript/lib/es6/Stdlib_Exn.js"; import * as Stdlib_Int from "rescript/lib/es6/Stdlib_Int.js"; import * as Stdlib_Dict from "rescript/lib/es6/Stdlib_Dict.js"; import * as Stdlib_List from "rescript/lib/es6/Stdlib_List.js"; import * as Stdlib_Array from "rescript/lib/es6/Stdlib_Array.js"; -import * as Stdlib_Error from "rescript/lib/es6/Stdlib_Error.js"; import * as Stdlib_Option from "rescript/lib/es6/Stdlib_Option.js"; +import * as Stdlib_JsError from "rescript/lib/es6/Stdlib_JsError.js"; import * as Primitive_string from "rescript/lib/es6/Primitive_string.js"; import * as Promises from "node:fs/promises"; import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js"; @@ -60,8 +59,8 @@ async function extractDocFromFile(file) { return RescriptTools_Docgen.decodeFromJson(JSON.parse(getOutput(match.stdout))); } catch (raw_exn) { let exn = Primitive_exceptions.internalToException(raw_exn); - if (exn.RE_EXN_ID === Stdlib_Exn.$$Error) { - return Stdlib_Error.panic("Failed to generate docstrings from " + file); + if (exn.RE_EXN_ID === "JsExn") { + return Stdlib_JsError.panic("Failed to generate docstrings from " + file); } throw { RE_EXN_ID: "Assert_failure", diff --git a/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js b/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js deleted file mode 100644 index 80bc599ff9..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js +++ /dev/null @@ -1,13 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - - -function DynamicallyLoadedComponent(props) { - return props.s; -} - -let make = DynamicallyLoadedComponent; - -export { - make, -} -/* No side effect */ diff --git a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx deleted file mode 100644 index 6e8cb207cc..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx +++ /dev/null @@ -1,10 +0,0 @@ -/* TypeScript file generated from ExportWithRename.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import * as ExportWithRenameJS from './ExportWithRename.res.js'; - -export type props = { readonly s: s }; - -export const Renamed: React.ComponentType<{ readonly s: string }> = ExportWithRenameJS.make as any; diff --git a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js deleted file mode 100644 index 3d13c84a2f..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js +++ /dev/null @@ -1,13 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - - -function ExportWithRename(props) { - return props.s; -} - -let make = ExportWithRename; - -export { - make, -} -/* No side effect */ diff --git a/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx b/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx deleted file mode 100644 index 1d9a1e530f..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* TypeScript file generated from Hooks.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import * as HooksJS from './Hooks.res.js'; - -import type {TypedArray2_Uint8Array_t as Js_TypedArray2_Uint8Array_t} from '../src/shims/Js.shim'; - -export type vehicle = { readonly name: string }; - -export type props = { readonly vehicle: vehicle }; - -export type Another_props = { readonly vehicle: vehicle; readonly callback: callback }; - -export type Inner_props = { readonly vehicle: vehicle }; - -export type Inner_Another_props = { readonly vehicle: vehicle }; - -export type Inner_Inner2_props = { readonly vehicle: vehicle }; - -export type Inner_Inner2_Another_props = { readonly vehicle: vehicle }; - -export type NoProps_props = {}; - -export type cb = (_to:vehicle) => void; - -export type WithRename_props = { - readonly _to: T_to; - readonly _Type: T_Type; - readonly cb: cb -}; - -export type WithRef_props = { readonly vehicle: vehicle }; - -export type r = { readonly x: string }; - -export type callback = (_1:input) => output; - -export type testReactContext = React.Context; - -export type testReactRef = { current: (null | number) }; - -export type testDomRef = React.Ref; - -export type testDomRef2 = React.Ref; - -export type Poly_props

= { readonly p: p }; - -export type Fun_props = { readonly name: name }; - -export type RenderPropRequiresConversion_props = { readonly renderVehicle: renderVehicle }; - -export type WithChildren_props = { readonly vehicle: vehicle; readonly children: children }; - -export type DD_props = { readonly array: array; readonly name: name }; - -export const $$default: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.default as any; - -export default $$default; - -export const Another_anotherComponent: React.ComponentType<{ readonly vehicle: vehicle; readonly callback: () => void }> = HooksJS.Another.anotherComponent as any; - -export const Inner_make: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.make as any; - -export const Inner_Another_anotherComponent: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Another.anotherComponent as any; - -export const Inner_Inner2_make: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Inner2.make as any; - -export const Inner_Inner2_Another_anotherComponent: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Inner2.Another.anotherComponent as any; - -export const NoProps_make: React.ComponentType<{}> = HooksJS.NoProps.make as any; - -export const functionWithRenamedArgs: (_to:vehicle, _Type:vehicle, cb:cb) => string = HooksJS.functionWithRenamedArgs as any; - -export const WithRename_componentWithRenamedArgs: React.ComponentType<{ - readonly _to: vehicle; - readonly _Type: vehicle; - readonly cb: cb -}> = HooksJS.WithRename.componentWithRenamedArgs as any; - -export const WithRef_makeWithRef: (_1:WithRef_props) => (_1:(null | undefined | any)) => JSX.Element = HooksJS.WithRef.makeWithRef as any; - -export const testForwardRef: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.testForwardRef as any; - -export const ForwardRef_input: (_1:r) => JSX.Element = HooksJS.ForwardRef.input as any; - -export const Poly_polymorphicComponent: React.ComponentType<{ readonly p: [vehicle, any] }> = HooksJS.Poly.polymorphicComponent as any; - -export const Fun_functionReturningReactElement: React.ComponentType<{ readonly name: string }> = HooksJS.Fun.functionReturningReactElement as any; - -export const RenderPropRequiresConversion_make: React.ComponentType<{ readonly renderVehicle: React.ComponentType<{ readonly number: number; readonly vehicle: vehicle }> }> = HooksJS.RenderPropRequiresConversion.make as any; - -export const WithChildren_aComponentWithChildren: React.ComponentType<{ readonly vehicle: vehicle; readonly children: React.ReactNode }> = HooksJS.WithChildren.aComponentWithChildren as any; - -export const DD_make: React.ComponentType<{ readonly array: Js_TypedArray2_Uint8Array_t; readonly name: string }> = HooksJS.DD.make as any; - -export const NoProps: { make: React.ComponentType<{}> } = HooksJS.NoProps as any; - -export const Inner: { - Inner2: { - Another: { - anotherComponent: React.ComponentType<{ - readonly vehicle: vehicle - }> - }; - make: React.ComponentType<{ - readonly vehicle: vehicle - }> - }; - Another: { - anotherComponent: React.ComponentType<{ - readonly vehicle: vehicle - }> - }; - make: React.ComponentType<{ - readonly vehicle: vehicle - }> -} = HooksJS.Inner as any; - -export const RenderPropRequiresConversion: { make: React.ComponentType<{ readonly renderVehicle: React.ComponentType<{ readonly number: number; readonly vehicle: vehicle }> }> } = HooksJS.RenderPropRequiresConversion as any; - -export const WithRename: { componentWithRenamedArgs: React.ComponentType<{ - readonly _to: vehicle; - readonly _Type: vehicle; - readonly cb: cb -}> } = HooksJS.WithRename as any; - -export const ForwardRef: { input: (_1:r) => JSX.Element } = HooksJS.ForwardRef as any; - -export const Fun: { functionReturningReactElement: React.ComponentType<{ readonly name: string }> } = HooksJS.Fun as any; - -export const WithRef: { makeWithRef: (_1:WithRef_props) => (_1:(null | undefined | any)) => JSX.Element } = HooksJS.WithRef as any; - -export const WithChildren: { aComponentWithChildren: React.ComponentType<{ readonly vehicle: vehicle; readonly children: React.ReactNode }> } = HooksJS.WithChildren as any; - -export const DD: { make: React.ComponentType<{ readonly array: Js_TypedArray2_Uint8Array_t; readonly name: string }> } = HooksJS.DD as any; - -export const Another: { anotherComponent: React.ComponentType<{ readonly vehicle: vehicle; readonly callback: () => void }> } = HooksJS.Another as any; - -export const Poly: { polymorphicComponent: React.ComponentType<{ readonly p: [vehicle, any] }> } = HooksJS.Poly as any; diff --git a/tests/gentype_tests/typescript-react-example/src/Hooks.res.js b/tests/gentype_tests/typescript-react-example/src/Hooks.res.js deleted file mode 100644 index 8d6972ea24..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/Hooks.res.js +++ /dev/null @@ -1,231 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as React from "react"; -import * as ImportHooks from "./ImportHooks.res.js"; -import * as Primitive_option from "rescript/lib/es6/Primitive_option.js"; -import * as ImportHookDefault from "./ImportHookDefault.res.js"; -import * as JsxRuntime from "react/jsx-runtime"; - -function Hooks(props) { - let match = React.useState(() => 0); - let setCount = match[1]; - let count = match[0]; - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("p", { - children: "Hooks example " + (props.vehicle.name + (" clicked " + (String(count) + " times"))) - }), - JsxRuntime.jsx("button", { - children: "Click me", - onClick: param => setCount(param => count + 1 | 0) - }), - JsxRuntime.jsxs(ImportHooks.make, { - person: { - name: "Mary", - age: 71 - }, - children: [ - "child1", - "child2" - ], - renderMe: x => x.randomString - }), - JsxRuntime.jsxs(ImportHookDefault.make, { - person: { - name: "DefaultImport", - age: 42 - }, - children: [ - "child1", - "child2" - ], - renderMe: x => x.randomString - }) - ] - }); -} - -function Hooks$Another$anotherComponent(props) { - props.callback(); - return JsxRuntime.jsx("div", { - children: "Another Hook " + props.vehicle.name - }); -} - -let Another = { - anotherComponent: Hooks$Another$anotherComponent -}; - -function Hooks$Inner(props) { - return JsxRuntime.jsx("div", { - children: "Another Hook " + props.vehicle.name - }); -} - -function Hooks$Inner$Another$anotherComponent(props) { - return JsxRuntime.jsx("div", { - children: "Another Hook " + props.vehicle.name - }); -} - -let Another$1 = { - anotherComponent: Hooks$Inner$Another$anotherComponent -}; - -function Hooks$Inner$Inner2(props) { - return JsxRuntime.jsx("div", { - children: "Another Hook " + props.vehicle.name - }); -} - -function Hooks$Inner$Inner2$Another$anotherComponent(props) { - return JsxRuntime.jsx("div", { - children: "Another Hook " + props.vehicle.name - }); -} - -let Another$2 = { - anotherComponent: Hooks$Inner$Inner2$Another$anotherComponent -}; - -let Inner2 = { - make: Hooks$Inner$Inner2, - Another: Another$2 -}; - -let Inner = { - make: Hooks$Inner, - Another: Another$1, - Inner2: Inner2 -}; - -function Hooks$NoProps(props) { - return JsxRuntime.jsx("div", { - children: null - }); -} - -let NoProps = { - make: Hooks$NoProps -}; - -function functionWithRenamedArgs(_to, _Type, cb) { - cb(_to); - return _to.name + _Type.name; -} - -function Hooks$WithRename$componentWithRenamedArgs(props) { - let _to = props._to; - props.cb(_to); - return _to.name + props._Type.name; -} - -let WithRename = { - componentWithRenamedArgs: Hooks$WithRename$componentWithRenamedArgs -}; - -function makeWithRef(param) { - let vehicle = param.vehicle; - return ref => { - if (ref == null) { - return null; - } else { - return JsxRuntime.jsx("button", { - children: vehicle.name, - ref: Primitive_option.some(ref) - }); - } - }; -} - -let Hooks$WithRef$makeWithRef = makeWithRef; - -let WithRef = { - makeWithRef: Hooks$WithRef$makeWithRef -}; - -let testForwardRef = React.forwardRef((x, y) => makeWithRef(x)(y)); - -let input = React.forwardRef((r, ref) => JsxRuntime.jsx("div", { - children: r.x, - ref: Primitive_option.some(ref) -})); - -let ForwardRef = { - input: input -}; - -function Hooks$Poly$polymorphicComponent(props) { - return props.p[0].name; -} - -let Poly = { - polymorphicComponent: Hooks$Poly$polymorphicComponent -}; - -function Hooks$Fun$functionReturningReactElement(props) { - return props.name; -} - -let Fun = { - functionReturningReactElement: Hooks$Fun$functionReturningReactElement -}; - -function Hooks$RenderPropRequiresConversion(props) { - return props.renderVehicle({ - vehicle: { - name: "Car" - }, - number: 42 - }); -} - -let RenderPropRequiresConversion = { - make: Hooks$RenderPropRequiresConversion -}; - -function Hooks$WithChildren$aComponentWithChildren(props) { - return JsxRuntime.jsxs("div", { - children: [ - "Another Hook " + props.vehicle.name, - JsxRuntime.jsx("div", { - children: props.children - }) - ] - }); -} - -let WithChildren = { - aComponentWithChildren: Hooks$WithChildren$aComponentWithChildren -}; - -function Hooks$DD(props) { - return props.name; -} - -let DD = { - make: Hooks$DD -}; - -let make = Hooks; - -let $$default = Hooks; - -export { - make, - $$default as default, - Another, - Inner, - NoProps, - functionWithRenamedArgs, - WithRename, - WithRef, - testForwardRef, - ForwardRef, - Poly, - Fun, - RenderPropRequiresConversion, - WithChildren, - DD, -} -/* testForwardRef Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx deleted file mode 100644 index 8552188b0e..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* TypeScript file generated from ImportHookDefault.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import {default as makeNotChecked} from './hookExample'; - -import {default as defaultNotChecked} from './hookExample'; - -// In case of type error, check the type of 'make' in 'ImportHookDefault.res' and './hookExample'. -export const makeTypeChecked: React.ComponentType<{ - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: ImportHooks_renderMe -}> = makeNotChecked as any; - -// Export 'make' early to allow circular import from the '.bs.js' file. -export const make: unknown = makeTypeChecked as React.ComponentType<{ - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: ImportHooks_renderMe -}> as any; - -// In case of type error, check the type of 'default' in 'ImportHookDefault.res' and './hookExample'. -export const defaultTypeChecked: React.ComponentType<{ - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: ImportHooks_renderMe -}> = defaultNotChecked as any; - -// Export '$$default' early to allow circular import from the '.bs.js' file. -export const $$default: unknown = defaultTypeChecked as React.ComponentType<{ - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: ImportHooks_renderMe -}> as any; - -import type {renderMe as ImportHooks_renderMe} from './ImportHooks.gen'; - -export type person = { readonly name: string; readonly age: number }; - -export type props = { - readonly person: person; - readonly children: children; - readonly renderMe: renderMe -}; - -export type MM_props = { - readonly person: person; - readonly children: children; - readonly renderMe: renderMe -}; - -export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js deleted file mode 100644 index 8b5cb1e464..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js +++ /dev/null @@ -1,18 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import ImportHookDefaultGen from "./ImportHookDefault.gen"; -import * as ImportHookDefaultGen$1 from "./ImportHookDefault.gen"; - -let make = ImportHookDefaultGen$1.make; - -let make2 = ImportHookDefaultGen; - -let MM = { - make2: make2 -}; - -export { - make, - MM, -} -/* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx deleted file mode 100644 index fc7dd23a2e..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* TypeScript file generated from ImportHooks.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import {makeRenamed as makeRenamedNotChecked} from './hookExample'; - -import {foo as fooNotChecked} from './hookExample'; - -// In case of type error, check the type of 'makeRenamed' in 'ImportHooks.res' and './hookExample'. -export const makeRenamedTypeChecked: React.ComponentType<{ - readonly actions?: JSX.Element; - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: renderMe -}> = makeRenamedNotChecked as any; - -// Export 'makeRenamed' early to allow circular import from the '.bs.js' file. -export const makeRenamed: unknown = makeRenamedTypeChecked as React.ComponentType<{ - readonly actions?: JSX.Element; - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: renderMe -}> as any; - -// In case of type error, check the type of 'foo' in 'ImportHooks.res' and './hookExample'. -export const fooTypeChecked: (person:person) => string = fooNotChecked as any; - -// Export 'foo' early to allow circular import from the '.bs.js' file. -export const foo: unknown = fooTypeChecked as (person:person) => string as any; - -export type person = { readonly name: string; readonly age: number }; - -export type renderMe = React.ComponentType<{ readonly randomString: string; readonly poly: a }>; - -export type props = { - readonly actions?: actions; - readonly person: person; - readonly children: children; - readonly renderMe: renderMe -}; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHooks.res.js b/tests/gentype_tests/typescript-react-example/src/ImportHooks.res.js deleted file mode 100644 index 8bcba0f408..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportHooks.res.js +++ /dev/null @@ -1,15 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as ImportHooksGen from "./ImportHooks.gen"; - -let make = ImportHooksGen.makeRenamed; - -function foo(prim) { - return ImportHooksGen.foo(prim); -} - -export { - make, - foo, -} -/* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx deleted file mode 100644 index 31f142f075..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/* TypeScript file generated from ImportIndex.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import {default as defaultNotChecked} from './'; - -// In case of type error, check the type of 'default' in 'ImportIndex.res' and './'. -export const defaultTypeChecked: React.ComponentType<{ readonly method?: "push" | "replace" }> = defaultNotChecked as any; - -// Export '$$default' early to allow circular import from the '.bs.js' file. -export const $$default: unknown = defaultTypeChecked as React.ComponentType<{ readonly method?: "push" | "replace" }> as any; - -export type props = { readonly method?: method }; - -export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportIndex.res.js b/tests/gentype_tests/typescript-react-example/src/ImportIndex.res.js deleted file mode 100644 index 34ab9cf267..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/ImportIndex.res.js +++ /dev/null @@ -1,10 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import ImportIndexGen from "./ImportIndex.gen"; - -let make = ImportIndexGen; - -export { - make, -} -/* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx b/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx deleted file mode 100644 index 5d138887bf..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* TypeScript file generated from JSXV4.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import {make as makeNotChecked} from './hookExample'; - -// In case of type error, check the type of 'make' in 'JSXV4.res' and './hookExample'. -export const makeTypeChecked: React.ComponentType<{ - readonly actions?: JSX.Element; - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: renderMe -}> = makeNotChecked as any; - -// Export 'make' early to allow circular import from the '.bs.js' file. -export const make: unknown = makeTypeChecked as React.ComponentType<{ - readonly actions?: JSX.Element; - readonly person: person; - readonly children: React.ReactNode; - readonly renderMe: renderMe -}> as any; - -const JSXV4JS = require('./JSXV4.res.js'); - -export type CompV4_props = { readonly x: x; readonly y: y }; - -export type person = { readonly name: string; readonly age: number }; - -export type props2 = { readonly randomString: string; readonly poly: a }; - -export type renderMe = (_1:props2) => JSX.Element; - -export type props = { - readonly actions?: actions; - readonly person: person; - readonly children: children; - readonly renderMe: renderMe -}; - -export const CompV4_make: React.ComponentType<{ readonly x: string; readonly y: string }> = JSXV4JS.CompV4.make as any; - -export const CompV4: { make: React.ComponentType<{ readonly x: string; readonly y: string }> } = JSXV4JS.CompV4 as any; diff --git a/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js b/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js deleted file mode 100644 index 016dda6790..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js +++ /dev/null @@ -1,19 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JSXV4Gen from "./JSXV4.gen"; - -function JSXV4$CompV4(props) { - return props.x + props.y; -} - -let CompV4 = { - make: JSXV4$CompV4 -}; - -let make = JSXV4Gen.make; - -export { - CompV4, - make, -} -/* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx b/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx deleted file mode 100644 index 9e9e897357..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* TypeScript file generated from MyInput.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import {default as defaultNotChecked} from './MyInput'; - -// In case of type error, check the type of 'default' in 'MyInput.res' and './MyInput'. -export const defaultTypeChecked: React.ComponentType<{ readonly onFocus?: (_1:inputFocusEvent) => void }> = defaultNotChecked as any; - -// Export '$$default' early to allow circular import from the '.bs.js' file. -export const $$default: unknown = defaultTypeChecked as React.ComponentType<{ readonly onFocus?: (_1:inputFocusEvent) => void }> as any; - -import type {inputFocusEvent as $$inputFocusEvent} from './shims/JsxEvent.shim'; - -export type inputFocusEvent = $$inputFocusEvent; - -export type props = { readonly onFocus?: onFocus }; - -export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/MyInput.res.js b/tests/gentype_tests/typescript-react-example/src/MyInput.res.js deleted file mode 100644 index 6fdab560cb..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/MyInput.res.js +++ /dev/null @@ -1,10 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import MyInputGen from "./MyInput.gen"; - -let make = MyInputGen; - -export { - make, -} -/* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx b/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx deleted file mode 100644 index a804d5483d..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx +++ /dev/null @@ -1,12 +0,0 @@ -/* TypeScript file generated from OnClick2.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -import * as OnClick2JS from './OnClick2.res.js'; - -import type {Mouse_t as JsxEvent_Mouse_t} from '../src/shims/JsxEvent.shim'; - -export type props = { readonly onClick: onClick }; - -export const make: React.ComponentType<{ readonly onClick: (_1:JsxEvent_Mouse_t) => void }> = OnClick2JS.make as any; diff --git a/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js b/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js deleted file mode 100644 index 1106cd2f83..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js +++ /dev/null @@ -1,16 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function OnClick2(props) { - return JsxRuntime.jsx("div", { - onClick: props.onClick - }); -} - -let make = OnClick2; - -export { - make, -} -/* react/jsx-runtime Not a pure module */ diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/await.res b/tests/syntax_tests/data/parsing/grammar/expressions/await.res index 71224c58ad..6c39592b52 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/await.res +++ b/tests/syntax_tests/data/parsing/grammar/expressions/await.res @@ -2,7 +2,7 @@ await wait(2) let maybeSomeValue = switch await fetchData(url) { | data => Some(data) -| exception JsError(_) => None +| exception JsExn(_) => None } let x = await 1 + 2 diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/await.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/await.res.txt index e487c3f519..332d9800b9 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/await.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/await.res.txt @@ -2,7 +2,7 @@ let maybeSomeValue = match await (fetchData url) with | data -> Some data - | exception JsError _ -> None + | exception JsExn _ -> None let x = (await 1) + 2 let x = (await (wait 1)) + (await (wait 2)) let () = diff --git a/tests/syntax_tests/data/printer/expr/asyncAwait.res b/tests/syntax_tests/data/printer/expr/asyncAwait.res index 2c66ec8ad1..fafba9c3d5 100644 --- a/tests/syntax_tests/data/printer/expr/asyncAwait.res +++ b/tests/syntax_tests/data/printer/expr/asyncAwait.res @@ -15,7 +15,7 @@ let f = async (. a, b) => a + b let maybeSomeValue = switch await fetchData(url) { | data => Some(data) -| exception JsError(_) => None +| exception JsExn(_) => None } (await f)(a, b) diff --git a/tests/syntax_tests/data/printer/expr/expected/asyncAwait.res.txt b/tests/syntax_tests/data/printer/expr/expected/asyncAwait.res.txt index 59f726f6ee..cb61de0fa2 100644 --- a/tests/syntax_tests/data/printer/expr/expected/asyncAwait.res.txt +++ b/tests/syntax_tests/data/printer/expr/expected/asyncAwait.res.txt @@ -14,7 +14,7 @@ let f = async (a, b) => a + b let maybeSomeValue = switch await fetchData(url) { | data => Some(data) -| exception JsError(_) => None +| exception JsExn(_) => None } (await f)(a, b) diff --git a/tests/tests/src/core/Core_ErrorTests.mjs b/tests/tests/src/core/Core_ErrorTests.mjs index 1d0276de6a..1b3c62d8e4 100644 --- a/tests/tests/src/core/Core_ErrorTests.mjs +++ b/tests/tests/src/core/Core_ErrorTests.mjs @@ -2,7 +2,6 @@ import * as Test from "./Test.mjs"; import * as Stdlib from "rescript/lib/es6/Stdlib.js"; -import * as Stdlib_Exn from "rescript/lib/es6/Stdlib_Exn.js"; import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js"; function panicTest() { @@ -11,7 +10,7 @@ function panicTest() { caught = Stdlib.panic("uh oh"); } catch (raw_err) { let err = Primitive_exceptions.internalToException(raw_err); - if (err.RE_EXN_ID === Stdlib_Exn.$$Error) { + if (err.RE_EXN_ID === "JsExn") { caught = err._1.message; } else { throw err; diff --git a/tests/tests/src/core/Core_ErrorTests.res b/tests/tests/src/core/Core_ErrorTests.res index 2595d88768..1096dda72a 100644 --- a/tests/tests/src/core/Core_ErrorTests.res +++ b/tests/tests/src/core/Core_ErrorTests.res @@ -1,6 +1,6 @@ let panicTest = () => { let caught = try panic("uh oh") catch { - | Exn.Error(err) => Error.message(err) + | JsExn(err) => JsExn.message(err) } Test.run(__POS_OF__("Should resolve test"), caught, \"===", Some("Panic! uh oh")) diff --git a/tests/tests/src/core/Core_IntTests.mjs b/tests/tests/src/core/Core_IntTests.mjs index f873104d52..83c6c30a79 100644 --- a/tests/tests/src/core/Core_IntTests.mjs +++ b/tests/tests/src/core/Core_IntTests.mjs @@ -2,7 +2,6 @@ import * as Test from "./Test.mjs"; import * as Pervasives from "rescript/lib/es6/Pervasives.js"; -import * as Stdlib_Exn from "rescript/lib/es6/Stdlib_Exn.js"; import * as Stdlib_Int from "rescript/lib/es6/Stdlib_Int.js"; import * as Primitive_object from "rescript/lib/es6/Primitive_object.js"; import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js"; @@ -15,7 +14,7 @@ function $$catch(f) { return Pervasives.failwith("no exception raised"); } catch (raw_err) { let err = Primitive_exceptions.internalToException(raw_err); - if (err.RE_EXN_ID === Stdlib_Exn.$$Error) { + if (err.RE_EXN_ID === "JsExn") { return err._1; } throw err; @@ -54,9 +53,9 @@ Test.run([ "Core_IntTests.res", 13, 20, - 51 + 52 ], - "range - cross-zero, incresing" + "range - cross-zero, increasing" ], Stdlib_Int.range(-1, 2, undefined), eq, [ -1, 0, diff --git a/tests/tests/src/core/Core_IntTests.res b/tests/tests/src/core/Core_IntTests.res index b9d88125a3..f2cc09d772 100644 --- a/tests/tests/src/core/Core_IntTests.res +++ b/tests/tests/src/core/Core_IntTests.res @@ -5,12 +5,12 @@ let catch = f => let _ = f() failwith("no exception raised") } catch { - | Exn.Error(err) => err + | JsExn(err) => err } Test.run(__POS_OF__("range - positive, increasing"), Int.range(3, 6), eq, [3, 4, 5]) Test.run(__POS_OF__("range - negative, increasing"), Int.range(-3, -1), eq, [-3, -2]) -Test.run(__POS_OF__("range - cross-zero, incresing"), Int.range(-1, 2), eq, [-1, 0, 1]) +Test.run(__POS_OF__("range - cross-zero, increasing"), Int.range(-1, 2), eq, [-1, 0, 1]) Test.run(__POS_OF__("range - start == end"), Int.range(3, 3), eq, []) Test.run(__POS_OF__("range - positive, decreasing"), Int.range(3, 1), eq, [3, 2]) Test.run(__POS_OF__("range - negative, decreasing"), Int.range(-1, -3), eq, [-1, -2]) @@ -43,7 +43,7 @@ Test.run( __POS_OF__("range - positive, increasing, step 0"), catch(() => Int.range(3, 6, ~options={step: 0})), eq, - Error.RangeError.make("Incorrect range arguments"), + JsError.RangeError.make("Incorrect range arguments")->JsError.toJsExn, ) Test.run(__POS_OF__("range - start == end, step 0"), Int.range(3, 3, ~options={step: 0}), eq, []) Test.run( @@ -110,7 +110,7 @@ Test.run( __POS_OF__("range - positive, increasing, step 0, inclusive"), catch(() => Int.range(3, 6, ~options={step: 0, inclusive: true})), eq, - Error.RangeError.make("Incorrect range arguments"), + JsError.RangeError.make("Incorrect range arguments")->JsError.toJsExn, ) Test.run( __POS_OF__("range - start == end, step 0, inclusive"), diff --git a/tests/tests/src/core/Core_PromiseTest.mjs b/tests/tests/src/core/Core_PromiseTest.mjs index 3935f8d730..861a3e00dd 100644 --- a/tests/tests/src/core/Core_PromiseTest.mjs +++ b/tests/tests/src/core/Core_PromiseTest.mjs @@ -149,7 +149,7 @@ let asyncParseFail = (function() { function testExternalPromiseThrow() { return Stdlib_Promise.$$catch(asyncParseFail().then(param => Promise.resolve()), e => { - let success = e.RE_EXN_ID === Stdlib_Exn.$$Error ? Primitive_object.equal(e._1.name, "SyntaxError") : false; + let success = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(e._1.name, "SyntaxError") : false; Test.run([ [ "Core_PromiseTest.res", @@ -187,7 +187,7 @@ function testExnThrow() { function testRaiseErrorThrow() { return Stdlib_Promise.$$catch(Promise.resolve().then(() => Stdlib_Exn.raiseError("Some JS error")), e => { - let isTestErr = e.RE_EXN_ID === Stdlib_Exn.$$Error ? Primitive_object.equal(e._1.message, "Some JS error") : false; + let isTestErr = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(e._1.message, "Some JS error") : false; Test.run([ [ "Core_PromiseTest.res", diff --git a/tests/tests/src/core/Core_PromiseTest.res b/tests/tests/src/core/Core_PromiseTest.res index f8bfa06a17..e017071e43 100644 --- a/tests/tests/src/core/Core_PromiseTest.res +++ b/tests/tests/src/core/Core_PromiseTest.res @@ -130,7 +130,7 @@ module Catching = { ->then(_ => resolve()) // Since our asyncParse will fail anyways, we convert to promise for our catch later ->catch(e => { let success = switch e { - | Exn.Error(err) => Exn.name(err) == Some("SyntaxError") + | JsExn(err) => JsExn.name(err) == Some("SyntaxError") | _ => false } @@ -173,7 +173,7 @@ module Catching = { }) ->catch(e => { let isTestErr = switch e { - | Exn.Error(err) => Exn.message(err) == Some("Some JS error") + | JsExn(err) => JsExn.message(err) == Some("Some JS error") | _ => false } Test.run(__POS_OF__("Should be some JS error"), isTestErr, equal, true) diff --git a/tests/tests/src/core/intl/Core_IntlTests.mjs b/tests/tests/src/core/intl/Core_IntlTests.mjs index eb96c87316..b7d396f046 100644 --- a/tests/tests/src/core/intl/Core_IntlTests.mjs +++ b/tests/tests/src/core/intl/Core_IntlTests.mjs @@ -1,7 +1,6 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as Stdlib_Exn from "rescript/lib/es6/Stdlib_Exn.js"; -import * as Stdlib_Error from "rescript/lib/es6/Stdlib_Error.js"; +import * as Stdlib_JsExn from "rescript/lib/es6/Stdlib_JsExn.js"; import * as Stdlib_Option from "rescript/lib/es6/Stdlib_Option.js"; import * as Primitive_option from "rescript/lib/es6/Primitive_option.js"; import * as Core_Intl_LocaleTest from "./Core_Intl_LocaleTest.mjs"; @@ -29,7 +28,7 @@ try { console.log(Intl.getCanonicalLocales("bloop")); } catch (raw_e) { let e = Primitive_exceptions.internalToException(raw_e); - if (e.RE_EXN_ID === Stdlib_Exn.$$Error) { + if (e.RE_EXN_ID === "JsExn") { console.error(e._1); } else { throw e; @@ -45,7 +44,7 @@ try { console.log(Intl.supportedValuesOf("unit")); } catch (raw_e$1) { let e$1 = Primitive_exceptions.internalToException(raw_e$1); - if (e$1.RE_EXN_ID === Stdlib_Exn.$$Error) { + if (e$1.RE_EXN_ID === "JsExn") { console.error(e$1._1); } else { throw e$1; @@ -57,7 +56,7 @@ try { console.error("Shouldn't have been hit"); } catch (raw_e$2) { let e$2 = Primitive_exceptions.internalToException(raw_e$2); - if (e$2.RE_EXN_ID === Stdlib_Exn.$$Error) { + if (e$2.RE_EXN_ID === "JsExn") { let e$3 = e$2._1; let message = Stdlib_Option.map(e$3.message, prim => prim.toLowerCase()); let exit = 0; @@ -72,7 +71,7 @@ try { } } else { - let e$4 = Stdlib_Error.fromException(e$2); + let e$4 = Stdlib_JsExn.fromException(e$2); if (e$4 !== undefined) { throw Primitive_option.valFromOption(e$4); } diff --git a/tests/tests/src/core/intl/Core_IntlTests.res b/tests/tests/src/core/intl/Core_IntlTests.res index 7b1f45d75e..a1640cc28d 100644 --- a/tests/tests/src/core/intl/Core_IntlTests.res +++ b/tests/tests/src/core/intl/Core_IntlTests.res @@ -16,7 +16,7 @@ Intl.getCanonicalLocalesManyExn(["EN-US", "Fr"])->Console.log try { Intl.getCanonicalLocalesExn("bloop")->Console.log } catch { -| Exn.Error(e) => Console.error(e) +| JsExn(e) => Console.error(e) } try { @@ -27,7 +27,7 @@ try { Intl.supportedValuesOfExn("timeZone")->Console.log Intl.supportedValuesOfExn("unit")->Console.log } catch { -| Exn.Error(e) => Console.error(e) +| JsExn(e) => Console.error(e) } try { @@ -35,17 +35,17 @@ try { Console.error("Shouldn't have been hit") } catch { -| Exn.Error(e) => - switch Error.message(e)->Option.map(String.toLowerCase) { +| JsExn(e) => + switch JsExn.message(e)->Option.map(String.toLowerCase) { | Some("invalid key : someinvalidkey") => Console.log("Caught expected error") | message => { Console.warn(`Unexpected error message: "${message->Option.getUnsafe}"`) - Error.raise(e) + JsExn.throw(e) } } | e => - switch Error.fromException(e) { - | Some(e) => Error.raise(e) + switch JsExn.fromException(e) { + | Some(e) => JsExn.throw(e) | None => Console.error("Unexpected error") } } From 2b33a194b0d12b647cd5b8a825bf6b8706703b8f Mon Sep 17 00:00:00 2001 From: tsnobip Date: Mon, 28 Apr 2025 09:37:45 +0200 Subject: [PATCH 2/2] make JsExn getters type safe --- lib/es6/Stdlib_JsExn.js | 16 +++++++++++++++- lib/js/Stdlib_JsExn.js | 16 +++++++++++++++- runtime/Stdlib_JsExn.res | 12 ++++++++---- runtime/Stdlib_JsExn.resi | 12 ++++-------- tests/tests/src/core/Core_ErrorTests.mjs | 3 ++- tests/tests/src/core/Core_PromiseTest.mjs | 5 +++-- tests/tests/src/core/intl/Core_IntlTests.mjs | 2 +- 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/lib/es6/Stdlib_JsExn.js b/lib/es6/Stdlib_JsExn.js index f392e96434..4273b89a74 100644 --- a/lib/es6/Stdlib_JsExn.js +++ b/lib/es6/Stdlib_JsExn.js @@ -9,7 +9,21 @@ function fromException(exn) { } +let getOrUndefined = (fieldName => t => (t && typeof t[fieldName] === "string" ? t[fieldName] : undefined)); + +let stack = getOrUndefined("stack"); + +let message = getOrUndefined("message"); + +let name = getOrUndefined("name"); + +let fileName = getOrUndefined("fileName"); + export { fromException, + stack, + message, + name, + fileName, } -/* No side effect */ +/* stack Not a pure module */ diff --git a/lib/js/Stdlib_JsExn.js b/lib/js/Stdlib_JsExn.js index 6e0dc49505..c89eb0d97e 100644 --- a/lib/js/Stdlib_JsExn.js +++ b/lib/js/Stdlib_JsExn.js @@ -9,5 +9,19 @@ function fromException(exn) { } +let getOrUndefined = (fieldName => t => (t && typeof t[fieldName] === "string" ? t[fieldName] : undefined)); + +let stack = getOrUndefined("stack"); + +let message = getOrUndefined("message"); + +let name = getOrUndefined("name"); + +let fileName = getOrUndefined("fileName"); + exports.fromException = fromException; -/* No side effect */ +exports.stack = stack; +exports.message = message; +exports.name = name; +exports.fileName = fileName; +/* stack Not a pure module */ diff --git a/runtime/Stdlib_JsExn.res b/runtime/Stdlib_JsExn.res index 92cd620710..45e29af43a 100644 --- a/runtime/Stdlib_JsExn.res +++ b/runtime/Stdlib_JsExn.res @@ -8,10 +8,14 @@ let fromException: exn => option = exn => external anyToExnInternal: 'a => exn = "%wrap_exn" -@get external stack: t => option = "stack" -@get external message: t => option = "message" -@get external name: t => option = "name" -@get external fileName: t => option = "fileName" +let getOrUndefined: string => t => option< + string, +> = %raw(`fieldName => t => (t && typeof t[fieldName] === "string" ? t[fieldName] : undefined)`) + +let stack = getOrUndefined("stack") +let message = getOrUndefined("message") +let name = getOrUndefined("name") +let fileName = getOrUndefined("fileName") external throw: 'a => 'b = "%raise" diff --git a/runtime/Stdlib_JsExn.resi b/runtime/Stdlib_JsExn.resi index 917b355ac6..d371877636 100644 --- a/runtime/Stdlib_JsExn.resi +++ b/runtime/Stdlib_JsExn.resi @@ -38,8 +38,7 @@ try {JsError.make("error")->JsError.throw} catch { } ``` */ -@get -external stack: t => option = "stack" +let stack: t => option /** `message(error)` retrieves the `message` property of the error, if it exists. @@ -54,8 +53,7 @@ try {JsError.SyntaxError.throwWithMessage("Some message here")} catch { } ``` */ -@get -external message: t => option = "message" +let message: t => option /** `name(error)` retrieves the `name` property of the error, if it exists. @@ -70,16 +68,14 @@ try {JsError.SyntaxError.throwWithMessage("Some message here")} catch { } ``` */ -@get -external name: t => option = "name" +let name: t => option /** `fileName(error)` retrieves the `fileName` property of the error, if it exists. See [`Error.prototype.fileName`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName) on MDN. */ -@get -external fileName: t => option = "fileName" +let fileName: t => option /** Throws the given value, terminating execution unless caught by a surrounding try/catch block. diff --git a/tests/tests/src/core/Core_ErrorTests.mjs b/tests/tests/src/core/Core_ErrorTests.mjs index 1b3c62d8e4..d875de16de 100644 --- a/tests/tests/src/core/Core_ErrorTests.mjs +++ b/tests/tests/src/core/Core_ErrorTests.mjs @@ -2,6 +2,7 @@ import * as Test from "./Test.mjs"; import * as Stdlib from "rescript/lib/es6/Stdlib.js"; +import * as Stdlib_JsExn from "rescript/lib/es6/Stdlib_JsExn.js"; import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js"; function panicTest() { @@ -11,7 +12,7 @@ function panicTest() { } catch (raw_err) { let err = Primitive_exceptions.internalToException(raw_err); if (err.RE_EXN_ID === "JsExn") { - caught = err._1.message; + caught = Stdlib_JsExn.message(err._1); } else { throw err; } diff --git a/tests/tests/src/core/Core_PromiseTest.mjs b/tests/tests/src/core/Core_PromiseTest.mjs index 861a3e00dd..e9f70f3474 100644 --- a/tests/tests/src/core/Core_PromiseTest.mjs +++ b/tests/tests/src/core/Core_PromiseTest.mjs @@ -2,6 +2,7 @@ import * as Test from "./Test.mjs"; import * as Stdlib_Exn from "rescript/lib/es6/Stdlib_Exn.js"; +import * as Stdlib_JsExn from "rescript/lib/es6/Stdlib_JsExn.js"; import * as Stdlib_Promise from "rescript/lib/es6/Stdlib_Promise.js"; import * as Primitive_object from "rescript/lib/es6/Primitive_object.js"; import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js"; @@ -149,7 +150,7 @@ let asyncParseFail = (function() { function testExternalPromiseThrow() { return Stdlib_Promise.$$catch(asyncParseFail().then(param => Promise.resolve()), e => { - let success = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(e._1.name, "SyntaxError") : false; + let success = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(Stdlib_JsExn.name(e._1), "SyntaxError") : false; Test.run([ [ "Core_PromiseTest.res", @@ -187,7 +188,7 @@ function testExnThrow() { function testRaiseErrorThrow() { return Stdlib_Promise.$$catch(Promise.resolve().then(() => Stdlib_Exn.raiseError("Some JS error")), e => { - let isTestErr = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(e._1.message, "Some JS error") : false; + let isTestErr = e.RE_EXN_ID === "JsExn" ? Primitive_object.equal(Stdlib_JsExn.message(e._1), "Some JS error") : false; Test.run([ [ "Core_PromiseTest.res", diff --git a/tests/tests/src/core/intl/Core_IntlTests.mjs b/tests/tests/src/core/intl/Core_IntlTests.mjs index b7d396f046..eba8a592b8 100644 --- a/tests/tests/src/core/intl/Core_IntlTests.mjs +++ b/tests/tests/src/core/intl/Core_IntlTests.mjs @@ -58,7 +58,7 @@ try { let e$2 = Primitive_exceptions.internalToException(raw_e$2); if (e$2.RE_EXN_ID === "JsExn") { let e$3 = e$2._1; - let message = Stdlib_Option.map(e$3.message, prim => prim.toLowerCase()); + let message = Stdlib_Option.map(Stdlib_JsExn.message(e$3), prim => prim.toLowerCase()); let exit = 0; if (message === "invalid key : someinvalidkey") { console.log("Caught expected error");