From 00b6c6d4001f5de728b7d990a1b14560b4961a63 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 15 Aug 2024 13:59:34 +1200 Subject: [PATCH] ensure defects are caught in Effect.tryPromise (#3459) --- .changeset/happy-geckos-push.md | 5 +++ packages/effect/src/internal/core-effect.ts | 40 ++++++++++--------- .../effect/test/Effect/tryPromise.test.ts | 16 +++++++- 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 .changeset/happy-geckos-push.md diff --git a/.changeset/happy-geckos-push.md b/.changeset/happy-geckos-push.md new file mode 100644 index 0000000000..85a8cc4c4e --- /dev/null +++ b/.changeset/happy-geckos-push.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +ensure defects are caught in Effect.tryPromise diff --git a/packages/effect/src/internal/core-effect.ts b/packages/effect/src/internal/core-effect.ts index 577191cd72..8dfc44b07d 100644 --- a/packages/effect/src/internal/core-effect.ts +++ b/packages/effect/src/internal/core-effect.ts @@ -1200,12 +1200,20 @@ export const patchFiberRefs = (patch: FiberRefsPatch.FiberRefsPatch): Effect.Eff export const promise = (evaluate: (signal: AbortSignal) => PromiseLike): Effect.Effect => evaluate.length >= 1 ? core.async((resolve, signal) => { - evaluate(signal) - .then((a) => resolve(core.exitSucceed(a)), (e) => resolve(core.exitDie(e))) + try { + evaluate(signal) + .then((a) => resolve(core.exitSucceed(a)), (e) => resolve(core.exitDie(e))) + } catch (e) { + resolve(core.exitDie(e)) + } }) : core.async((resolve) => { - ;(evaluate as LazyArg>)() - .then((a) => resolve(core.exitSucceed(a)), (e) => resolve(core.exitDie(e))) + try { + ;(evaluate as LazyArg>)() + .then((a) => resolve(core.exitSucceed(a)), (e) => resolve(core.exitDie(e))) + } catch (e) { + resolve(core.exitDie(e)) + } }) /* @internal */ @@ -1668,14 +1676,12 @@ export const tryPromise: { return core.async((resolve, signal) => { try { evaluate(signal) - .then((a) => resolve(core.exitSucceed(a)), (e) => - resolve(core.fail( - catcher ? catcher(e) : new core.UnknownException(e) - ))) + .then( + (a) => resolve(core.exitSucceed(a)), + (e) => resolve(catcher ? core.failSync(() => catcher(e)) : core.fail(new core.UnknownException(e))) + ) } catch (e) { - resolve(core.fail( - catcher ? catcher(e) : new core.UnknownException(e) - )) + resolve(catcher ? core.failSync(() => catcher(e)) : core.fail(new core.UnknownException(e))) } }) } @@ -1683,14 +1689,12 @@ export const tryPromise: { return core.async((resolve) => { try { evaluate() - .then((a) => resolve(core.exitSucceed(a)), (e) => - resolve(core.fail( - catcher ? catcher(e) : new core.UnknownException(e) - ))) + .then( + (a) => resolve(core.exitSucceed(a)), + (e) => resolve(catcher ? core.failSync(() => catcher(e)) : core.fail(new core.UnknownException(e))) + ) } catch (e) { - resolve(core.fail( - catcher ? catcher(e) : new core.UnknownException(e) - )) + resolve(catcher ? core.failSync(() => catcher(e)) : core.fail(new core.UnknownException(e))) } }) } diff --git a/packages/effect/test/Effect/tryPromise.test.ts b/packages/effect/test/Effect/tryPromise.test.ts index 43e9acec78..ae9ac41de1 100644 --- a/packages/effect/test/Effect/tryPromise.test.ts +++ b/packages/effect/test/Effect/tryPromise.test.ts @@ -1,7 +1,7 @@ import * as Cause from "effect/Cause" import * as Effect from "effect/Effect" import * as Either from "effect/Either" -import { describe, expect, it } from "vitest" +import { describe, expect, it } from "effect/test/utils/extend" describe("Effect", () => { it("tryPromise - success, no catch, no AbortSignal", async () => { @@ -88,4 +88,18 @@ describe("Effect", () => { expect(exit._tag).toBe("Success") expect(aborted).toBe(true) }) + + it.effect("tryPromise - defects in catch", () => + Effect.gen(function*() { + const cause = yield* Effect.tryPromise({ + try: () => Promise.reject("error"), + catch: (error) => { + throw new Error(String(error)) + } + }).pipe( + Effect.sandbox, + Effect.flip + ) + expect(cause).toStrictEqual(Cause.die(new Error("error"))) + })) })