Skip to content

Commit c243aeb

Browse files
committed
refactor: improve error handling in effect function
1 parent f669d3a commit c243aeb

File tree

4 files changed

+128
-3
lines changed

4 files changed

+128
-3
lines changed

drivers/htmlElementAttributes.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Item, item } from '../item.js';
2+
3+
4+
// todo, weakmap for caching?
5+
const all = new WeakMap();
6+
7+
export function attributes(element) {
8+
9+
if (all.has(element)) return all.get(element);
10+
11+
const root = item();
12+
13+
all.set(element, root);
14+
15+
root.ChildClass = AttributeItem;
16+
17+
// initial data
18+
for (const attr of element.attributes) {
19+
root.item(attr.name).set(attr.value);
20+
}
21+
22+
// dom changes
23+
new MutationObserver(mutations => {
24+
for (const mutation of mutations) {
25+
if (mutation.type === 'attributes') {
26+
if (mutation.target !== element) console.error('what?');
27+
const name = mutation.attributeName;
28+
const value = element.getAttribute(name);
29+
value === null ? root.item(name).remove() : root.item(name).set(value);
30+
}
31+
}
32+
}).observe(element, { attributes: true });
33+
34+
// item changes
35+
root.addEventListener('changeIn', ({detail}) => {
36+
if (detail.add) return;
37+
if (detail.remove) {
38+
element.removeAttribute(detail.remove.key);
39+
return;
40+
}
41+
if (detail.item.parent === root) {
42+
element.setAttribute(detail.item.key, detail.value);
43+
return;
44+
}
45+
console.error('what?');
46+
});
47+
48+
return root;
49+
}
50+
51+
class AttributeItem extends Item {
52+
constructor(root, key) {
53+
super(root, key);
54+
}
55+
$set(value) {
56+
super.$set(String(value));
57+
}
58+
ChildClass = false;
59+
}
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width">
6+
<title>Test</title>
7+
<script src="https://cdn.jsdelivr.net/gh/nuxodin/lazyfill@main/mod.min.js"></script>
8+
9+
<link rel=stylesheet href="http://gcdn.li/u2ui/u2/css/classless/full.css">
10+
<link rel=stylesheet href="http://gcdn.li/u2ui/u2/css/classless/simple.css">
11+
12+
<body>
13+
14+
15+
<section>
16+
<h1>Html Attributes Test</h1>
17+
18+
<figure style="padding:2rem">
19+
<input type="text" name="xyz" id="testElement" value="" placeholder="Name">
20+
</figure>
21+
22+
<br><br>
23+
24+
<table id="table"></table>
25+
26+
<script type=module>
27+
import {effect} from '../item.js';
28+
import {render, html, htmlFor} from 'https://unpkg.com/[email protected]/keyed.js';
29+
30+
import {attributes} from "./htmlElementAttributes.js";
31+
32+
const root = attributes(testElement);
33+
34+
effect(() => {
35+
render(table, html`
36+
<thead>
37+
<tr>
38+
<th> Name
39+
<th> Value
40+
<tbody>
41+
<tr>
42+
<td> <input id=inp style="width:100%">
43+
<td> <button onclick="${()=>{root.item(inp.value).set(''); inp.value=''}}">add</button></td>
44+
</tr>
45+
${[...root].map(item => {
46+
return html`
47+
<tr>
48+
<td> ${item.key}
49+
<td> <input oninput="${({target})=>{item.set(target.value) }}" .value="${item.value}">
50+
<td> <button onclick="${()=>{item.remove()}}">delete</button>
51+
`;
52+
})}
53+
`);
54+
});
55+
56+
</script>
57+
58+
</section>

item.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ export function effect(fn){ // async?
166166
fn.parent = outer;
167167
}
168168
currentEffect = fn;
169-
fn(); // await, so that signals in async functions are collected?
170-
currentEffect = outer;
169+
try { fn(); } // await, so that signals in async functions are collected?
170+
finally { currentEffect = outer; }
171171
return () => fn.disposed = true
172172
}
173173

@@ -190,7 +190,8 @@ function batch(effect) {
190190
batches.forEach(fn => {
191191
if (batches.has(fn?.parent)) return; // its parent has also to run, so it will run anyway
192192
currentEffect = fn; // effect() called inside fn(callback) has to know his parent effect
193-
fn(); // TODO? fn(fn) to rerun effect? https://github.com/nuxodin/item.js/issues/2
193+
// todo? try
194+
fn(); // TODO? fn({rerun:fn}) to rerun effect? https://github.com/nuxodin/item.js/issues/2
194195
});
195196
batches = null; // restart collecting
196197
});

tests/effect.html

+7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ <h1>Test</h1>
2828

2929
effect(()=>{
3030

31+
// try {
32+
// effect(()=>log("error:" + itm.item('outer').value + asdf))
33+
// } catch(e){
34+
// log("error in effect:" + e.message);
35+
// }
36+
37+
3138
effect(()=>{
3239
log("deeper effect (bevore inner), value:" + itm.item('deeper').value);
3340
});

0 commit comments

Comments
 (0)