@tanstack/store
Version:
Framework agnostic type-safe store w/ reactive framework adapters
184 lines (183 loc) • 5.63 kB
JavaScript
//#region src/alien.ts
let ReactiveFlags = /* @__PURE__ */ function(ReactiveFlags) {
ReactiveFlags[ReactiveFlags["None"] = 0] = "None";
ReactiveFlags[ReactiveFlags["Mutable"] = 1] = "Mutable";
ReactiveFlags[ReactiveFlags["Watching"] = 2] = "Watching";
ReactiveFlags[ReactiveFlags["RecursedCheck"] = 4] = "RecursedCheck";
ReactiveFlags[ReactiveFlags["Recursed"] = 8] = "Recursed";
ReactiveFlags[ReactiveFlags["Dirty"] = 16] = "Dirty";
ReactiveFlags[ReactiveFlags["Pending"] = 32] = "Pending";
return ReactiveFlags;
}({});
/* @__NO_SIDE_EFFECTS__ */
function createReactiveSystem({ update, notify, unwatched }) {
return {
link,
unlink,
propagate,
checkDirty,
shallowPropagate
};
function link(dep, sub, version) {
const prevDep = sub.depsTail;
if (prevDep !== void 0 && prevDep.dep === dep) return;
const nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;
if (nextDep !== void 0 && nextDep.dep === dep) {
nextDep.version = version;
sub.depsTail = nextDep;
return;
}
const prevSub = dep.subsTail;
if (prevSub !== void 0 && prevSub.version === version && prevSub.sub === sub) return;
const newLink = sub.depsTail = dep.subsTail = {
version,
dep,
sub,
prevDep,
nextDep,
prevSub,
nextSub: void 0
};
if (nextDep !== void 0) nextDep.prevDep = newLink;
if (prevDep !== void 0) prevDep.nextDep = newLink;
else sub.deps = newLink;
if (prevSub !== void 0) prevSub.nextSub = newLink;
else dep.subs = newLink;
}
function unlink(link, sub = link.sub) {
const dep = link.dep;
const prevDep = link.prevDep;
const nextDep = link.nextDep;
const nextSub = link.nextSub;
const prevSub = link.prevSub;
if (nextDep !== void 0) nextDep.prevDep = prevDep;
else sub.depsTail = prevDep;
if (prevDep !== void 0) prevDep.nextDep = nextDep;
else sub.deps = nextDep;
if (nextSub !== void 0) nextSub.prevSub = prevSub;
else dep.subsTail = prevSub;
if (prevSub !== void 0) prevSub.nextSub = nextSub;
else if ((dep.subs = nextSub) === void 0) unwatched(dep);
return nextDep;
}
function propagate(link) {
let next = link.nextSub;
let stack;
top: do {
const sub = link.sub;
let flags = sub.flags;
if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed | ReactiveFlags.Dirty | ReactiveFlags.Pending))) sub.flags = flags | ReactiveFlags.Pending;
else if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))) flags = ReactiveFlags.None;
else if (!(flags & ReactiveFlags.RecursedCheck)) sub.flags = flags & ~ReactiveFlags.Recursed | ReactiveFlags.Pending;
else if (!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) && isValidLink(link, sub)) {
sub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending);
flags &= ReactiveFlags.Mutable;
} else flags = ReactiveFlags.None;
if (flags & ReactiveFlags.Watching) notify(sub);
if (flags & ReactiveFlags.Mutable) {
const subSubs = sub.subs;
if (subSubs !== void 0) {
const nextSub = (link = subSubs).nextSub;
if (nextSub !== void 0) {
stack = {
value: next,
prev: stack
};
next = nextSub;
}
continue;
}
}
if ((link = next) !== void 0) {
next = link.nextSub;
continue;
}
while (stack !== void 0) {
link = stack.value;
stack = stack.prev;
if (link !== void 0) {
next = link.nextSub;
continue top;
}
}
break;
} while (true);
}
function checkDirty(link, sub) {
let stack;
let checkDepth = 0;
let dirty = false;
top: do {
const dep = link.dep;
const flags = dep.flags;
if (sub.flags & ReactiveFlags.Dirty) dirty = true;
else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) === (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) {
if (update(dep)) {
const subs = dep.subs;
if (subs.nextSub !== void 0) shallowPropagate(subs);
dirty = true;
}
} else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) === (ReactiveFlags.Mutable | ReactiveFlags.Pending)) {
if (link.nextSub !== void 0 || link.prevSub !== void 0) stack = {
value: link,
prev: stack
};
link = dep.deps;
sub = dep;
++checkDepth;
continue;
}
if (!dirty) {
const nextDep = link.nextDep;
if (nextDep !== void 0) {
link = nextDep;
continue;
}
}
while (checkDepth--) {
const firstSub = sub.subs;
const hasMultipleSubs = firstSub.nextSub !== void 0;
if (hasMultipleSubs) {
link = stack.value;
stack = stack.prev;
} else link = firstSub;
if (dirty) {
if (update(sub)) {
if (hasMultipleSubs) shallowPropagate(firstSub);
sub = link.sub;
continue;
}
dirty = false;
} else sub.flags &= ~ReactiveFlags.Pending;
sub = link.sub;
const nextDep = link.nextDep;
if (nextDep !== void 0) {
link = nextDep;
continue top;
}
}
return dirty;
} while (true);
}
function shallowPropagate(link) {
do {
const sub = link.sub;
const flags = sub.flags;
if ((flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) === ReactiveFlags.Pending) {
sub.flags = flags | ReactiveFlags.Dirty;
if ((flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) === ReactiveFlags.Watching) notify(sub);
}
} while ((link = link.nextSub) !== void 0);
}
function isValidLink(checkLink, sub) {
let link = sub.depsTail;
while (link !== void 0) {
if (link === checkLink) return true;
link = link.prevDep;
}
return false;
}
}
//#endregion
export { ReactiveFlags, createReactiveSystem };
//# sourceMappingURL=alien.js.map