From 4ed7e53d28b2bae910542ee46864878cb6ebf695 Mon Sep 17 00:00:00 2001 From: Mattia Manzati <mattia.manzati@gmail.com> Date: Fri, 9 May 2025 09:27:08 +0200 Subject: [PATCH] fallback path for fn when isGeneratorFunction is not available --- packages/effect/src/Effect.ts | 6 +++++- packages/effect/src/Utils.ts | 9 ++++++++- packages/effect/test/Effect/fn.test.ts | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/effect/src/Effect.ts b/packages/effect/src/Effect.ts index 795b5e70194..2dc0caa4fc1 100644 --- a/packages/effect/src/Effect.ts +++ b/packages/effect/src/Effect.ts @@ -62,7 +62,7 @@ import type * as Supervisor from "./Supervisor.js" import type * as Tracer from "./Tracer.js" import type { Concurrency, Contravariant, Covariant, NoExcessProperties, NoInfer, NotFunction } from "./Types.js" import type * as Unify from "./Unify.js" -import { isGeneratorFunction, type YieldWrap } from "./Utils.js" +import { isGeneratorFunction, isGeneratorIterator, type YieldWrap } from "./Utils.js" /** * @since 2.0.0 @@ -14545,6 +14545,10 @@ function fnApply(options: { } else { try { effect = options.body.apply(options.self, options.args) + if (isGeneratorIterator(effect)) { + const iterator = effect + effect = core.fromIterator(() => iterator) + } } catch (error) { fnError = error effect = die(error) diff --git a/packages/effect/src/Utils.ts b/packages/effect/src/Utils.ts index ef4a0701939..63031b80874 100644 --- a/packages/effect/src/Utils.ts +++ b/packages/effect/src/Utils.ts @@ -5,7 +5,7 @@ import { identity } from "./Function.js" import { globalValue } from "./GlobalValue.js" import type { Kind, TypeLambda } from "./HKT.js" import { getBugErrorMessage } from "./internal/errors.js" -import { isNullable, isObject } from "./Predicate.js" +import { hasProperty, isFunction, isNullable, isObject } from "./Predicate.js" import type * as Types from "./Types.js" /* @@ -807,3 +807,10 @@ const genConstructor = (function*() {}).constructor */ export const isGeneratorFunction = (u: unknown): u is (...args: Array<any>) => Generator<any, any, any> => isObject(u) && u.constructor === genConstructor + +/** + * @since 3.14.21 + */ +export const isGeneratorIterator = (u: unknown): u is Generator<any, any, any> => + isObject(u) && hasProperty(u, "return") && hasProperty(u, "throw") && + hasProperty(u, Symbol.iterator) && isFunction(u[Symbol.iterator]) diff --git a/packages/effect/test/Effect/fn.test.ts b/packages/effect/test/Effect/fn.test.ts index a5416625a5a..134541556e5 100644 --- a/packages/effect/test/Effect/fn.test.ts +++ b/packages/effect/test/Effect/fn.test.ts @@ -76,6 +76,13 @@ describe("Effect.fn", () => { strictEqual(fn2.length, 1) strictEqual(Effect.runSync(fn2(2)), 2) }) + it("should work with introduced functions", () => { + const f = function*(n: number) { + return n + } + const fn1 = Effect.fn("fn1")((n: number) => f(n)) + strictEqual(Effect.runSync(fn1(2)), 2) + }) }) describe("Effect.fnUntraced", () => {