diff --git a/.changeset/cool-foxes-press.md b/.changeset/cool-foxes-press.md new file mode 100644 index 0000000000..77c356796c --- /dev/null +++ b/.changeset/cool-foxes-press.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +only add onInterrupt in Effect.async if required diff --git a/.changeset/quiet-turkeys-bake.md b/.changeset/quiet-turkeys-bake.md new file mode 100644 index 0000000000..e1fda27de2 --- /dev/null +++ b/.changeset/quiet-turkeys-bake.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +simplify Effect.tryCatch implementation diff --git a/src/internal/core-effect.ts b/src/internal/core-effect.ts index 0a97bd8110..54ad01ac70 100644 --- a/src/internal/core-effect.ts +++ b/src/internal/core-effect.ts @@ -1629,7 +1629,6 @@ export const tryPromise: { ): Effect.Effect => { let evaluate: (signal?: AbortSignal) => Promise let catcher: ((error: unknown) => E) | undefined = undefined - if (typeof arg === "function") { evaluate = arg as (signal?: AbortSignal) => Promise } else { @@ -1638,40 +1637,38 @@ export const tryPromise: { } if (evaluate.length >= 1) { - return core.suspend(() => { - const controller = new AbortController() - return core.flatMap(try_(() => evaluate(controller.signal)), (promise) => - core.async((resolve) => { - promise - .then((a) => resolve(core.exitSucceed(a))) - .catch((e) => - resolve(core.fail( - catcher ? catcher(e) : new core.UnknownException(e) - )) - ) - return core.sync(() => controller.abort()) - })) - }) - } - - return core.flatMap( - try_( - arg as { - readonly try: LazyArg> - readonly catch: (error: unknown) => E - } - ), - (promise) => - core.async((resolve) => { - promise + return core.async((resolve, signal) => { + try { + evaluate(signal) .then((a) => resolve(core.exitSucceed(a))) .catch((e) => resolve(core.fail( catcher ? catcher(e) : new core.UnknownException(e) )) ) - }) - ) + } catch (e) { + resolve(core.fail( + catcher ? catcher(e) : new core.UnknownException(e) + )) + } + }) + } + + return core.async((resolve) => { + try { + evaluate() + .then((a) => resolve(core.exitSucceed(a))) + .catch((e) => + resolve(core.fail( + catcher ? catcher(e) : new core.UnknownException(e) + )) + ) + } catch (e) { + resolve(core.fail( + catcher ? catcher(e) : new core.UnknownException(e) + )) + } + }) } /* @internal */ diff --git a/src/internal/core.ts b/src/internal/core.ts index 9b583e13af..3560847424 100644 --- a/src/internal/core.ts +++ b/src/internal/core.ts @@ -439,28 +439,41 @@ export const async = ( blockingOn: FiberId.FiberId = FiberId.none ): Effect.Effect => suspend(() => { + let backingResume: ((_: Effect.Effect) => void) | undefined = undefined + let pendingEffect: Effect.Effect | undefined = undefined + function proxyResume(effect: Effect.Effect) { + if (backingResume) { + backingResume(effect) + } else if (pendingEffect === undefined) { + pendingEffect = effect + } + } + const effect = new EffectPrimitive(OpCodes.OP_ASYNC) as any + effect.i0 = (resume: (_: Effect.Effect) => void) => { + backingResume = resume + if (pendingEffect) { + resume(pendingEffect) + } + } + effect.i1 = blockingOn + let cancelerRef: Effect.Effect | void = undefined let controllerRef: AbortController | void = undefined - const effect = new EffectPrimitive(OpCodes.OP_ASYNC) as any if (register.length !== 1) { - const controller = new AbortController() - controllerRef = controller - effect.i0 = (resume: (_: Effect.Effect) => void) => { - cancelerRef = register(resume, controller.signal) - } + controllerRef = new AbortController() + cancelerRef = register(proxyResume, controllerRef.signal) } else { - effect.i0 = (resume: (_: Effect.Effect) => void) => { - // @ts-expect-error - cancelerRef = register(resume) - } + cancelerRef = (register as any)(proxyResume) } - effect.i1 = blockingOn - return onInterrupt(effect, () => { - if (controllerRef) { - controllerRef.abort() - } - return cancelerRef ?? unit - }) + + return (cancelerRef || controllerRef) ? + onInterrupt(effect, (_) => { + if (controllerRef) { + controllerRef.abort() + } + return cancelerRef ?? unit + }) : + effect }) /* @internal */