From c243aeb6d99accbe0c45128f462755bd1ec337b3 Mon Sep 17 00:00:00 2001 From: Tobias Buschor Date: Thu, 9 May 2024 02:48:43 +0200 Subject: [PATCH] refactor: improve error handling in effect function --- drivers/htmlElementAttributes.js | 59 +++++++++++++++++++++++++ drivers/htmlElementAttributes.test.html | 58 ++++++++++++++++++++++++ item.js | 7 +-- tests/effect.html | 7 +++ 4 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 drivers/htmlElementAttributes.js create mode 100644 drivers/htmlElementAttributes.test.html diff --git a/drivers/htmlElementAttributes.js b/drivers/htmlElementAttributes.js new file mode 100644 index 0000000..f45c052 --- /dev/null +++ b/drivers/htmlElementAttributes.js @@ -0,0 +1,59 @@ +import { Item, item } from '../item.js'; + + +// todo, weakmap for caching? +const all = new WeakMap(); + +export function attributes(element) { + + if (all.has(element)) return all.get(element); + + const root = item(); + + all.set(element, root); + + root.ChildClass = AttributeItem; + + // initial data + for (const attr of element.attributes) { + root.item(attr.name).set(attr.value); + } + + // dom changes + new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.type === 'attributes') { + if (mutation.target !== element) console.error('what?'); + const name = mutation.attributeName; + const value = element.getAttribute(name); + value === null ? root.item(name).remove() : root.item(name).set(value); + } + } + }).observe(element, { attributes: true }); + + // item changes + root.addEventListener('changeIn', ({detail}) => { + if (detail.add) return; + if (detail.remove) { + element.removeAttribute(detail.remove.key); + return; + } + if (detail.item.parent === root) { + element.setAttribute(detail.item.key, detail.value); + return; + } + console.error('what?'); + }); + + return root; +} + +class AttributeItem extends Item { + constructor(root, key) { + super(root, key); + } + $set(value) { + super.$set(String(value)); + } + ChildClass = false; +} \ No newline at end of file diff --git a/drivers/htmlElementAttributes.test.html b/drivers/htmlElementAttributes.test.html new file mode 100644 index 0000000..ba4b4fc --- /dev/null +++ b/drivers/htmlElementAttributes.test.html @@ -0,0 +1,58 @@ + + + + + + Test + + + + + + + + +
+

Html Attributes Test

+ +
+ +
+ +

+ +
+ + + +
\ No newline at end of file diff --git a/item.js b/item.js index ad6b076..2804dfb 100644 --- a/item.js +++ b/item.js @@ -166,8 +166,8 @@ export function effect(fn){ // async? fn.parent = outer; } currentEffect = fn; - fn(); // await, so that signals in async functions are collected? - currentEffect = outer; + try { fn(); } // await, so that signals in async functions are collected? + finally { currentEffect = outer; } return () => fn.disposed = true } @@ -190,7 +190,8 @@ function batch(effect) { batches.forEach(fn => { if (batches.has(fn?.parent)) return; // its parent has also to run, so it will run anyway currentEffect = fn; // effect() called inside fn(callback) has to know his parent effect - fn(); // TODO? fn(fn) to rerun effect? https://github.com/nuxodin/item.js/issues/2 + // todo? try + fn(); // TODO? fn({rerun:fn}) to rerun effect? https://github.com/nuxodin/item.js/issues/2 }); batches = null; // restart collecting }); diff --git a/tests/effect.html b/tests/effect.html index 8285ae5..f6dfdc3 100644 --- a/tests/effect.html +++ b/tests/effect.html @@ -28,6 +28,13 @@

Test

effect(()=>{ + // try { + // effect(()=>log("error:" + itm.item('outer').value + asdf)) + // } catch(e){ + // log("error in effect:" + e.message); + // } + + effect(()=>{ log("deeper effect (bevore inner), value:" + itm.item('deeper').value); });