UNPKG

@dhmk/atom

Version:

Lightweight mobx-like observable values, computed values and side-effects

130 lines (129 loc) 4.73 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; import { removeAtom, useAtom } from "../shared"; import { Id, AtomState, defaultAtomOptions, } from "../types"; import { runtime } from "../runtime"; var ComputedAtom = /** @class */ (function () { function ComputedAtom(fn, options) { this.fn = fn; this.observers = new Map(); this.deps = Array(); this.prevDeps = Array(); this.prevDepsIndex = 0; this.runId = new Id(); this.versionId = new Id(); this.isObserved = false; this.depsForUnobserved = new Set(); this.isError = false; this.state = AtomState.Stale; this.depsVersions = Array(); this.options = __assign(__assign({}, defaultAtomOptions), options); } ComputedAtom.prototype.invalidate = function (state, isValueAtom) { var oldState = this.state; if (state > this.state) this.state = state; if (oldState === AtomState.Actual) this.observers.forEach(function (_, a) { return a.invalidate(AtomState.PossiblyStale, false); }); }; ComputedAtom.prototype.calculate = function () { this.prevDeps = this.deps; this.deps = []; this.prevDepsIndex = 0; this.runId = new Id(); if (!this.isObserved && runtime.currentAtom) { this.isObserved = true; var onBO = this.options.onBecomeObserved; if (onBO) runtime.addEffect({ actualize: onBO }); } if (!this.isObserved) this.depsForUnobserved = new Set(); var nextValue; var isError; var prevAtom = runtime.currentAtom; runtime.currentAtom = this; try { nextValue = this.fn(); } catch (e) { isError = true; nextValue = e; } runtime.currentAtom = prevAtom; if (!this.isObserved) this.deps = Array.from(this.depsForUnobserved); this.depsVersions.length = this.deps.length; for (var i = 0; i < this.deps.length; ++i) { var dep = this.deps[i]; dep.runId = this.runId; this.depsVersions[i] = dep.versionId; } for (var i = this.prevDepsIndex; i < this.prevDeps.length; ++i) { var a = this.prevDeps[i]; if (a.runId !== this.runId) removeAtom(a, this); } this.prevDeps = []; this.state = this.isObserved ? AtomState.Actual : AtomState.PossiblyStale; if (!this.options.equals(nextValue, this.value)) { this.value = nextValue; this.isError = isError; this.versionId = new Id(); this.observers.forEach(function (_, a) { return a.invalidate(AtomState.Stale, false); }); } }; ComputedAtom.prototype.actualize = function () { if (this.state === AtomState.Actual) return; if (this.state === AtomState.PossiblyStale) { for (var i = 0; i < this.deps.length; ++i) { var dep = this.deps[i]; dep.actualize(); if (dep.versionId !== this.depsVersions[i]) { this.state = AtomState.Stale; break; } } } if (this.state === AtomState.PossiblyStale) this.state = AtomState.Actual; if (this.state === AtomState.Stale) this.calculate(); }; ComputedAtom.prototype.get = function () { this.actualize(); useAtom(this); if (this.isError) throw this.value; return this.value; }; ComputedAtom.prototype.toJSON = function () { return this.get(); }; ComputedAtom.prototype.dispose = function () { if (this.isObserved) { this.isObserved = false; var onBUO = this.options.onBecomeUnobserved; if (onBUO) runtime.addEffect({ actualize: onBUO }); for (var i = 0; i < this.deps.length; ++i) { removeAtom(this.deps[i], this); } this.state = AtomState.Stale; } }; return ComputedAtom; }()); export { ComputedAtom };