wirejs/wire.js

177 lines
4.2 KiB
JavaScript
Raw Normal View History

2023-05-17 23:39:01 +03:00
function é(defaultValue)
{
let value = undefined;
let effects = [];
let piping = é.pipeLine();
let flag = 0;
let version = 0;
let diff = é.diff;
let get = () => {
return (flag & 2) ? piping.get(value) : value;
};
let set = (newValue) => {
newValue = é.extract(newValue, value);
(flag & 4) && (newValue = piping.set(newValue));
if(diff(newValue,value))
{
(flag & 1) && effects.filter(e => e.o).forEach(k => k());
value = newValue;
version++;
(flag & 1) && effects.map(e => e.f());
}
};
let useEffect = (e) => {
flag = flag | 1;
let k = {
f:e,
o:undefined
};
requestAnimationFrame(()=> {
k.o = e();
})
effects.push(k);
}
value = é.extract(defaultValue, value);
return {
get,
set,
useEffect,
fp: é.fingerPrint,
getVersion: () => version,
equalTo: n => é.isSame(n, value),
readLayer: (a,b) => {
flag = flag | 2;
piping.read(a,b)
},
writeLayer: (a,b) => {
flag = flag | 4;
piping.write(a,b)
}
}
}
é.isWire = n => n?.fp == é.fingerPrint;
é.extract = (e,v) => typeof e=='function'?e(v):e;
é.isSame = (a,b) => !é.diff(a,b);
é.fingerPrint = Symbol("wire");
é.useEffect = (fn, assoc) =>
{
for (const wireVar of assoc)
{
if(é.isWire(wireVar))
{
wireVar.useEffect(fn);
}
}
};
é.diff = (a,b,c) => {
let cursoryDiffResult = é.cDiff(a,b);
if(cursoryDiffResult == é.cDiff.adiff)
{
return é.adiff(a,b,c||[])
}else{
return cursoryDiffResult == é.cDiff.some ? false : true;
}
}
é.adiff = (a,b,c) => {
if(c.includes(a) && c.includes(b))
{
console.error("Circular object detected !")
return é.cObjectDiff(a,b);
}
let typea = a instanceof Array ? 0 : a.byteLength ? 1 : 2;
let typeb = b instanceof Array ? 0 : b.byteLength ? 1 : 2;
if(typea != typeb)
{
return true;
}
if(typea==0)
{
if(a.length != b.length)
{
return true
}
for(let k = 0; k < a.length; k++)
{
if(é.diff(a[k], b[k]))
{
return true
}
}
return false
}
if(a instanceof Object)
{
if(Object.keys(a).length != Object.keys(b).length)
{
return true
}
c.push(a);
c.push(b);
for (const key in a)
{
if (Object.hasOwnProperty.call(a, key))
{
if(é.diff(a[key], b[key], c))
{
return true
}
}
}
return false
}
}
é.cArrDiff = (a,b) => {
return a.length != b.length || !a.every((v,i) => a[i] === v)
};
é.cObjectDiff = (a,b) => {
return é.cArrDiff(
Object.keys(a),
Object.keys(b)
);
};
é.cDiff = (a,b) => {
switch(typeof a)
{
case "undefined":
case "function":{
return typeof a == typeof b ? é.cDiff.some : é.cDiff.different
}
case "symbol":
case "bigint":
case "boolean":
case "number":
case "string":{
return a === b ? é.cDiff.some : é.cDiff.different;
}
case "object":{
return é.cDiff.adiff;
}
};
}
é.cDiff.adiff = -1;
é.cDiff.some = 0;
é.cDiff.different = 1;
é.pipeLine = () => {
let k = {};
let reads = [];
let writes = [];
k.read = (fn,pr) => reads.push({fn,pr});
k.write = (fn,pr) => writes.push({fn,pr});
k.get = (val) => {
let fns = reads.sort((a,b) => (a?.pr|0) - (b?.pr|0)),
real = val;
for (const { fn } of fns) {
fn( real, e => real = e );
};
return real;
};
k.set = (val) => {
let fns = writes.sort((a,b) => (a?.pr|0) - (b?.pr|0)),
real = val;
for (const { fn } of fns) {
fn( real, e => real = e );
};
return real;
};
return k;
}