From: Lady Date: Sat, 22 Jul 2023 07:39:17 +0000 (-0700) Subject: Add completesNormally to function.js X-Git-Url: https://git.ladys.computer/Pisces/commitdiff_plain/b78e2445d9f73ee3f784dfc59b5e04458fbe7f77 Add completesNormally to function.js This is a convenience function which returns true if calling the argument results in a normal completion (i·e not a throw), and false otherwise. --- diff --git a/function.js b/function.js index 5f397a9..ca7cad5 100644 --- a/function.js +++ b/function.js @@ -95,6 +95,32 @@ export const { construct, } = Reflect; +/** + * Returns whether calling the provided function with no `this` value + * or arguments completes normally; that is, does not throw an error. + * + * ☡ This function will throw an error if the provided argument is not + * callable. + */ +export const completesNormally = ($) => { + if (!isCallable($)) { + // The provided value is not callable; this is an error. + throw new TypeError( + `Piscēs: Cannot determine completion of noncallable value: ${$}`, + ); + } else { + // The provided value is callable. + try { + // Attempt to call the function and return true if this succeeds. + $(); + return true; + } catch { + // Calling the function did not succeed; return false. + return false; + } + } +}; + /** * Returns the provided value. * diff --git a/function.test.js b/function.test.js index 17e77e2..a9a5f3f 100644 --- a/function.test.js +++ b/function.test.js @@ -10,12 +10,14 @@ import { assertEquals, assertStrictEquals, + assertThrows, describe, it, } from "./dev-deps.js"; import { bind, call, + completesNormally, construct, identity, isCallable, @@ -115,6 +117,33 @@ describe("call", () => { }); }); +describe("completesNormally", () => { + it("[[Call]] returns true for functions which complete normally", () => { + assertStrictEquals(completesNormally(() => {}), true); + }); + + it("[[Call]] returns false for functions which throw", () => { + assertStrictEquals( + completesNormally(() => { + throw null; + }), + false, + ); + }); + + it("[[Call]] throws when the argument is not callable", () => { + assertThrows(() => { + completesNormally(null); + }); + }); + + it("[[Call]] throws when the argument is not provided", () => { + assertThrows(() => { + completesNormally(); + }); + }); +}); + describe("construct", () => { it("[[Call]] defaults to the constructor as the target", () => { const constructor = class {};