deno.land / x / solid@v1.5.6 / bench / kairo.cjs
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472let currentCollecting = null;function setData(data, value) { if (!inTransaction) { return runInTransaction(() => setData(data, value)); } if (data.value !== value) { data.value = value; data.flags |= 1024 /* Changed */; dirtyDataQueue.push(data); // TODO: redunant? markObserversMaybeStale(data); }}const dirtyDataQueue = [];const effects = [];function markObserversMaybeStale(computation) { if (computation.flags & 64 /* SingleObserver */) { const observer = computation.observer; if (observer !== null) { if ((observer.flags & 2048) /* Zombie */ === 0) { observer.depsReadyBits |= 1 << computation.observerSlot; // maximum 52 dependencies } if (observer.flags & 8 /* MaybeStale */) { return; } observer.flags |= 8 /* MaybeStale */; markObserversMaybeStale(observer); } } else { for (let i = 0; i < computation.observers.length; i++) { const observer = computation.observers[i]; if ((observer.flags & 2048) /* Zombie */ === 0) { observer.depsReadyBits |= 1 << computation.observerSlots[i]; } if (observer.flags & 8 /* MaybeStale */) { continue; } observer.flags |= 8 /* MaybeStale */; markObserversMaybeStale(observer); } }}function accessData(data) { if (currentCollecting !== null) { if (currentCollecting.flags & 256 /* Dynamic */) { insertNewSource(currentCollecting, data); } else if (currentCollecting.flags & 512 /* MaybeStable */) { logUnstable(currentCollecting, data); } if (data.flags & 2048 /* Zombie */) { if ((currentCollecting.flags & 2048) /* Zombie */ === 0) { data.flags -= 2048 /* Zombie */; // dezombie naturally } } } return data.value;}function accessComputation(data) { if (data.flags & 32 /* Computing */) { throw new Error("Circular dependency"); } if (currentCollecting !== null) { if (currentCollecting.flags & 256 /* Dynamic */) { insertNewSource(currentCollecting, data); } else if (currentCollecting.flags & 512 /* MaybeStable */) { logUnstable(currentCollecting, data); } if (data.flags & 2048 /* Zombie */) { if ((currentCollecting.flags & 2048) /* Zombie */ === 0) { data.flags -= 2048 /* Zombie */; // dezombie naturally } } } if (data.flags & 8 /* MaybeStale */) { updateComputation(data); data.flags -= 8 /* MaybeStale */; } return data.value;}function logUnstable(accessor, data) { if (accessor.flags & 128 /* SingleSource */) { if (accessor.source !== data) { // currentCollecting.source is definitely not null? why? // deps changed accessor.flags -= 512 /* MaybeStable */; accessor.flags |= 256 /* Dynamic */; // clean observers from here if (accessor.checkIndex === 0) { // checkIndex == 0 means this is the first source // first source doesn't match? cleanupComputationOfSingleSource(accessor); // otherwise it changes from single source to multi source. } insertNewSource(accessor, data); // still need to log. } else { accessor.checkIndex++; } } else { const checkIndex = accessor.checkIndex; if (checkIndex >= accessor.sources.length || data !== accessor.sources[checkIndex]) { // deps changed. accessor.flags -= 512 /* MaybeStable */; accessor.flags |= 256 /* Dynamic */; // clean observers from here cleanupComputation(accessor, checkIndex); insertNewSource(accessor, data); } else { accessor.checkIndex++; } }}function collectSourceAndRecomputeComputation(computation) { const stored = currentCollecting; currentCollecting = computation; computation.flags |= 32 /* Computing */; const currentValue = computation.collect(); computation.flags -= 32 /* Computing */; if (computation.flags & 512 /* MaybeStable */) { // check the real used deps is lesser than assumed. if (computation.flags & 128 /* SingleSource */) { if (computation.checkIndex === 0 && computation.source !== null) { computation.flags -= 512 /* MaybeStable */; computation.flags |= 256 /* Dynamic */; cleanupComputationOfSingleSource(computation); } } else if (computation.checkIndex != computation.sources.length) { computation.flags -= 512 /* MaybeStable */; computation.flags |= 256 /* Dynamic */; cleanupComputation(computation, computation.checkIndex); } currentCollecting.checkIndex = 0; } currentCollecting = stored; return currentValue;}function untrack(fn, ...args) { const stored = currentCollecting; currentCollecting = null; const ret = fn(...args); currentCollecting = stored; return ret;}function updateComputation(computation) { if (computation.flags & 256 /* Dynamic */) { cleanupComputation(computation, 0); } const currentValue = collectSourceAndRecomputeComputation(computation); if (computation.flags & 4096 /* NotReady */) { computation.flags -= 4096 /* NotReady */ | 256 /* Dynamic */; if (computation.flags & 16384 /* Stable */) { computation.flags |= 16384 /* Stable */; } else { computation.flags |= 512 /* MaybeStable */; } } // compare value , if changed, mark as changed if (currentValue !== computation.value) { computation.value = currentValue; computation.flags |= 1024 /* Changed */; // maybe problematic? }}function cleanupComputationOfSingleSource(cell) { if (cell.source === null) { return; } let theSource = cell.source; let observerSlotOfLastSourceOfComputation = cell.sourceSlot; cell.source = null; cell.sourceSlot = -1; if (theSource.flags & 64 /* SingleObserver */ && theSource.observer !== null) { theSource.observer = null; theSource.observerSlot = -1; } else { // here observers is definitely not empty: let lastObserverOfSource = theSource.observers.pop(); let sourceSlotOfLastObserverOfSource = theSource.observerSlots.pop(); //我原来在哪儿,要找回去。 if (observerSlotOfLastSourceOfComputation == theSource.observers.length) { // lucky, you are just the last observer return; } // replace you with last observer theSource.observers[observerSlotOfLastSourceOfComputation] = lastObserverOfSource; theSource.observerSlots[ observerSlotOfLastSourceOfComputation ] = sourceSlotOfLastObserverOfSource; // notify the change of position if (lastObserverOfSource.flags & 128 /* SingleSource */) { lastObserverOfSource.sourceSlot = observerSlotOfLastSourceOfComputation; } else { lastObserverOfSource.sourceSlots[ sourceSlotOfLastObserverOfSource ] = observerSlotOfLastSourceOfComputation; } }}function cleanupComputation(cell, remain) { if (cell.flags & 128 /* SingleSource */) { return cleanupComputationOfSingleSource(cell); } while (cell.sources.length > remain) { let theSource = cell.sources.pop(); let observerSlotOfLastSourceOfComputation = cell.sourceSlots.pop(); if (theSource.flags & 64 /* SingleObserver */ && theSource.observer !== null) { theSource.observer = null; theSource.observerSlot = -1; } else { let lastObserverOfSource = theSource.observers.pop(); let sourceSlotOfLastObserverOfSource = theSource.observerSlots.pop(); if (observerSlotOfLastSourceOfComputation == theSource.observers.length) { continue; } theSource.observers[observerSlotOfLastSourceOfComputation] = lastObserverOfSource; theSource.observerSlots[ observerSlotOfLastSourceOfComputation ] = sourceSlotOfLastObserverOfSource; if (lastObserverOfSource.flags & 128 /* SingleSource */) { lastObserverOfSource.sourceSlot = observerSlotOfLastSourceOfComputation; } else { lastObserverOfSource.sourceSlots[ sourceSlotOfLastObserverOfSource ] = observerSlotOfLastSourceOfComputation; } } }}function propagate(computation) { let notZombie = false; // if maybe stale if (computation.flags & 8 /* MaybeStale */) { if (computation.depsReadyBits !== 0) { throw "this should never happen."; } if (computation.flags & 4 /* Stale */) { updateComputation(computation); computation.flags -= 4 /* Stale */; } computation.flags -= 8 /* MaybeStale */; // now it is definitely not stale! } // if changed if (computation.flags & 1024 /* Changed */) { let hasObserver = false; if (computation.flags & 64 /* SingleObserver */) { const observer = computation.observer; if (observer !== null) { if ((observer.flags & 2048) /* Zombie */ === 0) { observer.flags |= 4 /* Stale */; observer.depsReadyBits -= 1 << computation.observerSlot; if (observer.depsReadyBits === 0 && propagate(observer)) { notZombie = true; } hasObserver = true; } } } else { for (let i = 0; i < computation.observers.length; ) { let current = computation.observers[i]; if (current.flags & 2048 /* Zombie */) { i++; continue; } if ((current.flags & 8) /* MaybeStale */ === 0) { i++; hasObserver = true; // ??? continue; } current.flags |= 4 /* Stale */; current.depsReadyBits -= 1 << computation.observerSlots[i]; if (current.depsReadyBits === 0 && propagate(current)) { notZombie = true; } if (current === computation.observers[i]) { i++; } hasObserver = true; } } // now remove changed mark. computation.flags -= 1024 /* Changed */; if (computation.last_effect) { let wnode = computation.last_effect; while (wnode !== null) { effects.push(wnode.fn); wnode = wnode.prev; } } else if (!hasObserver) { computation.flags |= 2048 /* Zombie */; } } else { if (computation.flags & 64 /* SingleObserver */) { if (computation.observer !== null) { // TODO: make inline cache? if (!((computation.observer.flags & 2048) /* Zombie */)) { computation.observer.depsReadyBits -= 1 << computation.observerSlot; if (computation.observer.depsReadyBits === 0 && propagate(computation.observer)) { notZombie = true; } } } } else { for (let i = 0; i < computation.observers.length; i++) { let current = computation.observers[i]; if (current.flags & 2048 /* Zombie */) { continue; } current.depsReadyBits -= 1 << computation.observerSlots[i]; if (current.depsReadyBits === 0 && propagate(current)) { notZombie = true; } } } } return notZombie;}function watch(data, sideEffect) { if (data.flags & 2048 /* Zombie */) { data.flags -= 2048 /* Zombie */; } if (data.flags & 1 /* Data */) { accessData(data); // TODO: is it necessary? } else { accessComputation(data); // because it maybe stale? } const node = { fn: sideEffect, prev: data.last_effect, next: null, disposed: false, data: data }; if (data.last_effect) { data.last_effect.next = node; } data.last_effect = node; return node;}function disposeWatcher(watcher) { if (watcher.disposed) { return; } watcher.disposed = true; if (watcher.next === null) { // it is the last. watcher.data.last_effect = watcher.prev; } else { watcher.next.prev = watcher.prev; } if (watcher.prev) { watcher.prev.next = watcher.next; }}let inTransaction = false;function runInTransaction(fn) { if (inTransaction) { // already inside a transaction return fn(); } inTransaction = true; const retValue = fn(); inTransaction = false; while (dirtyDataQueue.length) { const data = dirtyDataQueue.pop(); propagate(data); } while (effects.length) { effects.pop()(); } return retValue;}function insertNewSource(accessing, source) { if (accessing.flags & 128 /* SingleSource */) { if (accessing.source === null) { accessing.source = source; accessing.sourceSlot = insertNewObserver(source, accessing, -1); } else { accessing.flags -= 128 /* SingleSource */; // notify relocation if (accessing.source.flags & 64 /* SingleObserver */) { accessing.source.observerSlot = 0; } else { accessing.source.observerSlots[accessing.sourceSlot] = 0; } accessing.sources = [accessing.source]; accessing.sourceSlots = [accessing.sourceSlot]; accessing.source = null; accessing.sourceSlot = -1; return insertNewSource(accessing, source); } } else { accessing.sources.push(source); accessing.sourceSlots.push(insertNewObserver(source, accessing, accessing.sourceSlots.length)); }}function insertNewObserver(accesed, observer, atWhichSlotOfObserver) { if (accesed.flags & 64 /* SingleObserver */) { if (accesed.observer === null) { accesed.observer = observer; accesed.observerSlot = atWhichSlotOfObserver; return -1; } else { accesed.flags -= 64 /* SingleObserver */; if (accesed.observer.flags & 128 /* SingleSource */) { accesed.observer.sourceSlot = 0; } else { accesed.observer.sourceSlots[accesed.observerSlot] = 0; } accesed.observers = [accesed.observer]; accesed.observerSlots = [accesed.observerSlot]; accesed.observer = null; accesed.observerSlot = -1; return insertNewObserver(accesed, observer, atWhichSlotOfObserver); } } else { accesed.observers.push(observer); accesed.observerSlots.push(atWhichSlotOfObserver); return accesed.observerSlots.length - 1; }}function createData(value) { return { flags: 1 /* Data */ | 64 /* SingleObserver */ | 2048 /* Zombie */, last_effect: null, observer: null, observerSlot: -1, observers: null, observerSlots: null, value };}function createComputation(fn, options) { const ret = { flags: 2 /* Computation */ | 128 /* SingleSource */ | 64 /* SingleObserver */ | 2048 /* Zombie */ | 8 /* MaybeStale */ | 256 /* Dynamic */ | 4096 /* NotReady */, last_effect: null, observer: null, observerSlot: -1, observers: null, observerSlots: null, value: null, source: null, sourceSlot: -1, sources: null, sourceSlots: null, collect: fn, depsReadyBits: 0, checkIndex: 0 }; // ret.value = collectSourceAndRecomputeComputation(ret); if (options === null || options === void 0 ? void 0 : options.static) { // if source is ready: give it ready. ret.flags |= 16384 /* Stable */; } return ret;}
module.exports = { createRoot: fn => fn(), createSignal: value => { const node = createData(value); return [() => accessData(node), v => setData(node, v)]; }, createComputed: fn => { const g = createComputation(fn); watch(g, () => {}); }};
Version Info