From ec95d2a63f7b1e8daf297717dfea7be5ca7db9ae Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sun, 24 Aug 2025 09:47:53 +0200 Subject: [PATCH 1/4] add failing tests for derive --- bau/test/derive.test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/bau/test/derive.test.js b/bau/test/derive.test.js index 66a77056..6cf8cb56 100644 --- a/bau/test/derive.test.js +++ b/bau/test/derive.test.js @@ -115,4 +115,35 @@ describe("derive", async () => { assert.equal(b.val, 1); expect(spys).toHaveBeenCalledTimes(2); }); + + it("updates incrementally", () => { + const a = bau.state(false); + const b = bau.state(false); + const derived = bau.derive(() => { + if (!a.val) return 1; + if (!b.val) return 2; + return 3; + }); + + assert.equal(derived.val, 1); + a.val = true; + assert.equal(derived.val, 2); + b.val = true; + assert.equal(derived.val, 3); + }); + + it("updates when first null", () => { + const a = bau.state(false); + const b = bau.state(false); + const derived = bau.derive(() => { + if (!a.val) return null; + if (!b.val) return null; + return true; + }); + + assert.equal(derived.val, null); + a.val = true; + b.val = true; + assert.equal(derived.val, true); + }); }); From 25e09543d0bc74ecd44d0f2089f3dba67ce9fa0a Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sun, 24 Aug 2025 10:18:20 +0200 Subject: [PATCH 2/4] add potential fix --- bau/bau.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bau/bau.js b/bau/bau.js index 39560ae0..fce8e5b6 100644 --- a/bau/bau.js +++ b/bau/bau.js @@ -52,6 +52,7 @@ export default function Bau(input) { let updateDom = (state, op) => { !_stateOps.length && _window.requestAnimationFrame(processDom); _stateOps.push([state, op]); + for (let l of state.listeners) l.state.dirty = true; }; const processDom = () => { @@ -249,10 +250,14 @@ export default function Bau(input) { rawVal: initVal, bindings: [], listeners: [], + dirty: false, __isState: true, get val() { let _state = this; _curDeps?.g?.add(_state); + if (_state.computed && _state.dirty) { + deriveInternal(_state.computed, _state); + } return ( _state.valProxy ?? ((_state.valProxy = isArrayOrObject(initVal) @@ -270,9 +275,11 @@ export default function Bau(input) { if (isArrayOrObject(value)) { state.valProxy = createProxy(state, value); updateDom(state, ["assign", value]); + state.dirty = false; } else if (value !== oldVal) { state.valProxy = value; state.bindings.length + state.listeners.length && updateDom(state); + state.dirty = false; } }, }); @@ -304,12 +311,13 @@ export default function Bau(input) { ) )) dep.listeners.push(listener); + state.dirty = false; }; let derive = (computed, options) => { let state = createState(undefined, options); + state.computed = computed; deriveInternal(computed, state); - state.computed = true; return state; }; From 8d2e45ffc471ca763957ac590eb9baf86ce1884d Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sun, 24 Aug 2025 10:20:40 +0200 Subject: [PATCH 3/4] remove redundant state.dirty reset in value assignment --- bau/bau.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/bau/bau.js b/bau/bau.js index fce8e5b6..bd72fbbe 100644 --- a/bau/bau.js +++ b/bau/bau.js @@ -275,11 +275,9 @@ export default function Bau(input) { if (isArrayOrObject(value)) { state.valProxy = createProxy(state, value); updateDom(state, ["assign", value]); - state.dirty = false; } else if (value !== oldVal) { state.valProxy = value; state.bindings.length + state.listeners.length && updateDom(state); - state.dirty = false; } }, }); From fddf3fa72d21be0ac4f6e3ae8e42b06b52388a9d Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sun, 24 Aug 2025 12:33:19 +0200 Subject: [PATCH 4/4] add another test --- bau/test/derive.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bau/test/derive.test.js b/bau/test/derive.test.js index 6cf8cb56..f686792e 100644 --- a/bau/test/derive.test.js +++ b/bau/test/derive.test.js @@ -146,4 +146,24 @@ describe("derive", async () => { b.val = true; assert.equal(derived.val, true); }); + + it("does not call derive when non-dependencies change", () => { + const a = bau.state(0); + const b = bau.state(0); + let called = 0; + const derived = bau.derive(() => { + ++called; + return a.val; + }); + assert.equal(derived.val, 0); + assert.equal(derived.val, 0); + assert.equal(called, 1); + ++a.val; + assert.equal(derived.val, 1); + assert.equal(derived.val, 1); + assert.equal(called, 2); + ++b.val; + assert.equal(derived.val, 1); + assert.equal(called, 2); + }); });