Skip to content

Instantly share code, notes, and snippets.

@intrnl
Last active August 24, 2022 18:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intrnl/abab1b5f5a550392216d511482ebb803 to your computer and use it in GitHub Desktop.
Save intrnl/abab1b5f5a550392216d511482ebb803 to your computer and use it in GitHub Desktop.
let effects = [];
let current = null;
let dirty = 0n;
let flushing = false;
export let access = Symbol();
export function state (flag, value) {
return (next, effect = true) => {
if (next === access) {
if (current && effect) {
current.d |= flag;
}
return value;
}
else {
if (effect) {
dirty |= flag;
update();
}
return value = next;
}
};
}
export function computed (flag, getter) {
let _dirty = true;
let _value;
let _compute = effect(getter, () => {
_dirty = true;
dirty |= flag;
update();
});
return (next, effect = true) => {
if (next === access) {
if (current && effect) {
current.d |= flag;
}
if (_dirty) {
_value = _compute();
}
}
return _value;
};
}
export function effect (fn, scheduler) {
let run = () => {
let prev_current = current;
try {
current = run;
current.d = 0n;
return fn();
}
finally {
current = prev_current;
}
};
run.s = scheduler;
if (!scheduler) {
run();
}
effects.push(run);
}
let resolved_promise = Promise.resolve();
export function update () {
if (!flushing) {
flushing = true;
resolved_promise.then(flush);
}
}
function flush () {
while (dirty) {
let next = dirty;
dirty = 0n
for (let fn of effects) {
if (fn.d & next) {
fn.d = 0n;
if (fn.s) {
fn.s();
}
else {
fn();
}
}
}
}
flushing = false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment