(
context: {
terminated: false | "with-value" | "without-value";
terminatedValue: R | undefined;
interceptIterator: Iterator<E, R, unknown> | null;
},
effectName: string | symbol | ((...args: never) => unknown),
effect: E,
handler: (
{
effect,
resume,
terminate,
}: {
effect: Effect;
resume: (value: R) => void;
terminate: (value: R) => void;
},
...payloads: unknown[]
) => void | Generator<Effect, void, unknown> | Effected<Effect, void>,
)
| 2711 | * @returns |
| 2712 | */ |
| 2713 | const handleEffect = <E extends Effect, R>( |
| 2714 | context: { |
| 2715 | terminated: false | "with-value" | "without-value"; |
| 2716 | terminatedValue: R | undefined; |
| 2717 | interceptIterator: Iterator<E, R, unknown> | null; |
| 2718 | }, |
| 2719 | |
| 2720 | effectName: string | symbol | ((...args: never) => unknown), |
| 2721 | effect: E, |
| 2722 | handler: ( |
| 2723 | { |
| 2724 | effect, |
| 2725 | resume, |
| 2726 | terminate, |
| 2727 | }: { |
| 2728 | effect: Effect; |
| 2729 | resume: (value: R) => void; |
| 2730 | terminate: (value: R) => void; |
| 2731 | }, |
| 2732 | ...payloads: unknown[] |
| 2733 | ) => void | Generator<Effect, void, unknown> | Effected<Effect, void>, |
| 2734 | ): IteratorResult<E, R> => { |
| 2735 | let resumed: false | "with-value" | "without-value" = false; |
| 2736 | let resumedValue: R; |
| 2737 | let onComplete: ((...args: [] | [R]) => void) | null = null; |
| 2738 | const warnMultipleHandling = (type: "resume" | "terminate", ...args: [] | [R]) => { |
| 2739 | let message = `Effect ${stringifyEffectNameQuoted(effectName)} has been handled multiple times`; |
| 2740 | message += " (received `"; |
| 2741 | message += `${type} ${stringifyEffect(effect)}`; |
| 2742 | if (args.length > 0) message += ` with ${stringify(args[0])}`; |
| 2743 | message += "` after it has been "; |
| 2744 | if (resumed) { |
| 2745 | message += "resumed"; |
| 2746 | if (resumed === "with-value") message += ` with ${stringify(resumedValue)}`; |
| 2747 | } else if (context.terminated) { |
| 2748 | message += "terminated"; |
| 2749 | if (context.terminated === "with-value") |
| 2750 | message += ` with ${stringify(context.terminatedValue)}`; |
| 2751 | } |
| 2752 | message += "). Only the first handler will be used."; |
| 2753 | logger.warn(message); |
| 2754 | }; |
| 2755 | const resume = (...args: [] | [R]) => { |
| 2756 | if (resumed || context.terminated) { |
| 2757 | warnMultipleHandling("resume", ...args); |
| 2758 | return; |
| 2759 | } |
| 2760 | resumed = args.length > 0 ? "with-value" : "without-value"; |
| 2761 | if (args.length > 0) resumedValue = args[0]!; |
| 2762 | if (onComplete) { |
| 2763 | onComplete(...args); |
| 2764 | onComplete = null; |
| 2765 | } |
| 2766 | }; |
| 2767 | const terminate = (...args: [] | [R]) => { |
| 2768 | if (resumed || context.terminated) { |
| 2769 | warnMultipleHandling("terminate", ...args); |
| 2770 | return; |
no test coverage detected