diff --git a/src/behavior.ts b/src/behavior.ts index 627832f..d790572 100644 --- a/src/behavior.ts +++ b/src/behavior.ts @@ -274,6 +274,18 @@ export class LiftBehavior extends Behavior { update(_t: number): R { return this.f(...(this.bs.map((b) => b.last) as any)); } + changeStateDown(_: State): void { + let state = State.Done; + for (const p of this.parents) { + state = Math.max(state, p.state); + } + if (this.state !== state) { + this.state = state; + for (const child of this.children) { + child.changeStateDown(state); + } + } + } } class FlatMapBehavior extends Behavior { diff --git a/test/behavior.ts b/test/behavior.ts index 61f3e2f..780dfbc 100644 --- a/test/behavior.ts +++ b/test/behavior.ts @@ -316,6 +316,31 @@ describe("behavior", () => { p.newValue(4); assert.deepEqual(cb.args, [[16], [24]]); }); + it("only switched to push if all parents are push", () => { + // In this test the lifted behavior `b3` starts out in the pull state + // since both of its parents are in pull. Then one of the parents + // switches to push. But, since one parent is still in pull the lifted + // behavior should remain in pull. + let n = 1; + const b1 = H.fromFunction(() => n); + const fut = H.sinkFuture>(); + const b2 = H.switchTo(fromFunction(() => 2), fut); + const b3 = H.lift((n, m) => n + m, b1, b2); + observe( + () => {}, + () => { + return () => { + throw new Error("Should not be called."); + }; + }, + b3 + ); + expect(H.at(b3)).toEqual(3); + fut.resolve(H.sinkBehavior(5)); + expect(H.at(b3)).toEqual(6); + n = 2; + expect(H.at(b3)).toEqual(7); + }); }); }); describe("flatMap", () => {