177 lines
4.2 KiB
JavaScript
177 lines
4.2 KiB
JavaScript
|
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;
|
||
|
}
|