UNPKG

@zedux/atoms

Version:

A Molecular State Engine for React

99 lines (98 loc) 4.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EvaluationStack = exports.setStack = exports.readInstance = exports.stack = void 0; const core_1 = require("@zedux/core"); const index_1 = require("../utils/index"); const plugin_actions_1 = require("../utils/plugin-actions"); const AtomInstanceBase_1 = require("./instances/AtomInstanceBase"); /** * A stack of AtomInstances and AtomSelectors that are currently evaluating - * innermost instance/selector (the one that's actually currently evaluating) at * the end of the array. * * This has to live in the module scope so `readInstance` can access it without * any ecosystem context. That's how injectors work. */ exports.stack = []; const readInstance = () => { const item = exports.stack[exports.stack.length - 1]; if (true /* DEV */ && !(0, core_1.is)(item === null || item === void 0 ? void 0 : item.node, AtomInstanceBase_1.AtomInstanceBase)) { throw new Error('Zedux: Injectors can only be used in atom state factories'); } return item.node; }; exports.readInstance = readInstance; const setStack = (newStack) => (exports.stack = newStack); exports.setStack = setStack; class EvaluationStack { constructor(ecosystem) { this.ecosystem = ecosystem; const { _graph, selectors } = ecosystem; const get = ((atom, params) => { const { id, store } = ecosystem.getInstance(atom, params); // when called outside evaluation, get() is just an alias for // ecosystem.get() if (!exports.stack.length) return store.getState(); // if get is called during evaluation, track the required atom instances so // we can add graph edges for them _graph.addEdge(exports.stack[exports.stack.length - 1].node.id, id, 'get', 0); return store.getState(); }); const getInstance = (atom, params, edgeInfo) => { var _a; const instance = ecosystem.getInstance(atom, params); // when called outside evaluation, getInstance() is just an alias for // ecosystem.getInstance() if (!exports.stack.length) return instance; // if getInstance is called during evaluation, track the required atom // instances so we can add graph edges for them _graph.addEdge(exports.stack[exports.stack.length - 1].node.id, instance.id, (edgeInfo === null || edgeInfo === void 0 ? void 0 : edgeInfo[1]) || 'getInstance', (_a = edgeInfo === null || edgeInfo === void 0 ? void 0 : edgeInfo[0]) !== null && _a !== void 0 ? _a : index_1.Static); return instance; }; const select = (selectable, ...args) => { // when called outside evaluation, select() is just an alias for // ecosystem.select() if (!exports.stack.length) { return ecosystem.select(selectable, ...args); } const cache = selectors.getCache(selectable, args); _graph.addEdge(exports.stack[exports.stack.length - 1].node.id, cache.id, 'select', 0); return cache.result; }; this.atomGetters = { ecosystem, get, getInstance, select, }; } finish() { const item = exports.stack.pop(); const { _idGenerator, _mods, modBus } = this.ecosystem; // if we just popped the last thing off the stack, restore the default // scheduler if (!exports.stack.length) core_1.Store._scheduler = undefined; if (!item || !_mods.evaluationFinished) return; const time = item.start ? _idGenerator.now(true) - item.start : 0; const action = { node: item.node, time }; modBus.dispatch(plugin_actions_1.pluginActions.evaluationFinished(action)); } read() { return exports.stack[exports.stack.length - 1]; } start(node) { const { _idGenerator, _mods, _scheduler } = this.ecosystem; const newItem = { node, start: _mods.evaluationFinished ? _idGenerator.now(true) : undefined, }; exports.stack.push(newItem); // all stores created during evaluation automatically belong to the ecosystem core_1.Store._scheduler = _scheduler; } } exports.EvaluationStack = EvaluationStack;