Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
nuxodin committed Feb 7, 2023
1 parent bbc52b2 commit 859ec10
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 28 deletions.
32 changes: 14 additions & 18 deletions item.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

// signal / effect
const relatedEffects = new WeakMap();
let currentEffect = null;

Expand All @@ -7,18 +7,16 @@ export function effect(fn){
currentEffect = fn;
if (outer) {
(outer.nested ??= new Set()).add(fn);
if (fn.parent && fn.parent !== outer) throw('effect(cb) callbacks should not be reused for other effects');
fn.parent = outer;
}
fn();
currentEffect = outer;
return () => fn.disposed = true
}


let batches = null;
function batch(effect) {
if (batches) return batches.add(effect);

batches = new Set([effect]);
Promise.resolve().then(()=>{ // setImmediate-alternative
batches.forEach(fn => {
Expand All @@ -29,23 +27,21 @@ function batch(effect) {
batches = null; // restart batch
});
}


export function signalize(item) {
item.addEventListener('getIn', ({detail:{item}}) => {
if (!currentEffect) return;
if (!relatedEffects.has(item)) relatedEffects.set(item, new Set());
relatedEffects.get(item).add(currentEffect);
});
item.addEventListener('changeIn', ({detail:{item}}) => {
const effects = relatedEffects.get(item);
if (!effects) return;
function registerCurrentEffectFor(signal) {
if (currentEffect) {
if (!relatedEffects.has(signal)) relatedEffects.set(signal, new Set());
relatedEffects.get(signal).add(currentEffect);
}
}
function triggerEffectsFor(signal) {
const effects = relatedEffects.get(signal);
if (effects) { // "&& effects.size" faster?
effects.forEach(fn => {
fn.nested?.forEach(fn => fn.disposed = true); // dispose child-effects
if (fn.disposed) return effects.delete(fn);
batch(fn);
});
});
}
}


Expand All @@ -62,6 +58,7 @@ export class Item extends EventTarget {
super();
this.#parent = parent;
this.#key = key;
this.addEventListener('change', () => triggerEffectsFor(this) );
}

get key(){ return this.#key }
Expand All @@ -72,8 +69,8 @@ export class Item extends EventTarget {
if (this.#isgetting) throw new Error('circular get');
this.#isgetting = true;
dispatchEvent(this, 'get', { item: this, value:this.#value });
registerCurrentEffectFor(this);
this.#isgetting = false;
//if (!this.#filled) throw new Error('value was never set');
return this.$get();
}
set value(value){
Expand All @@ -90,7 +87,6 @@ export class Item extends EventTarget {
} else {
const value = this.#value ??= Object.create(null); // if undefined, create object (todo? should always be object)
return Object.fromEntries(Object.entries(value).map(([key, {value}]) => [key, value]));
//return Object.fromEntries(Object.entries(this.#value).map(([key, {value}]) => [key, value]));
}
}
$set(value){
Expand Down
23 changes: 17 additions & 6 deletions tests/signalize.html → tests/effect.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@ <h1>Test</h1>

// local storage

import {item, effect, signalize } from "../item.js";
import {item, effect} from "../item.js";

const itm = item({outer:'0', inner:'0'});
signalize(itm);
const itm = item({outer:'0', inner:'0', deeper:0});

const eff = ()=>{

log("inner effect, value:" + itm.item('inner').value);

}

effect(()=>{

log("outer effect, value:" + itm.item('outer').value);

effect(()=>{

effect(()=>{
log("deeper effect (bevore inner), value:" + itm.item('deeper').value);
});

log("inner effect, value:" + itm.item('inner').value);

});
Expand All @@ -36,28 +44,31 @@ <h1>Test</h1>
console.log(msg)
}

log('<br>start mutating<br>');
log('<br>start mutating (firstly skiped because batched)<br>');

itm.item('inner').value = '2';
itm.item('outer').value = '2';
itm.item('deeper').value = 2;

log("<br>new values (skiped because batched)<br>");
log("<br>new values<br>");

itm.item('inner').value = '3';
itm.item('outer').value = '3';
itm.item('deeper').value = 3;

log("<br>new values<br>");

setTimeout(()=>{
log("<br>new values after 50ms<br>");
itm.item('inner').value = '4';
itm.item('outer').value = '4';
itm.item('deeper').value = 4;
}, 50);

setTimeout(()=>{
log("<br>new values after 100ms<br>");
itm.item('inner').value = '5';
itm.item('outer').value = '5';
itm.item('deeper').value = 5;
}, 100);

</script>
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ <h1>Test</h1>

<script type=module>

import {effect, signalize, proxy} from "../item.js";
import {effect, proxy} from "../item.js";
import {localStorageItem} from "../drivers/localStorage.js";

let item = localStorageItem();
signalize(item);
window.ls = proxy(item);
window.ls = proxy(localStorageItem());

effect(()=>{
sayHi.innerHTML = 'Hi '+ls.firstname+' '+ls.lastname+'!';
Expand Down

0 comments on commit 859ec10

Please sign in to comment.