jotai-effect
Version:
109 lines • 4.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.withAtomEffect = withAtomEffect;
const internals_1 = require("jotai/vanilla/internals");
const atomEffect_1 = require("./atomEffect.js");
const env_1 = require("./env.js");
function withAtomEffect(targetAtom, effect) {
const proto = Object.getPrototypeOf(targetAtom);
const desc = Object.getOwnPropertyDescriptors(targetAtom);
let depth = 0;
desc.read.value = function read(get, options) {
try {
++depth;
// handles case when withAtomEffect is nested
const context = depth === 1 ? targetAtom : this;
return targetAtom.read.call(context, get, options);
}
finally {
--depth;
}
};
if (isWritableAtom(targetAtom)) {
desc.write.value = function write(get, set, ...args) {
try {
++depth;
const context = depth === 1 ? targetAtom : this;
return targetAtom.write.call(context, get, set, ...args);
}
finally {
--depth;
}
};
}
const targetWithEffect = Object.create(proto, desc);
targetWithEffect.unstable_onInit = (store) => {
const buildingBlocks = (0, internals_1.INTERNAL_getBuildingBlocksRev2)(store);
const invalidatedAtoms = buildingBlocks[2];
const storeHooks = (0, internals_1.INTERNAL_initializeStoreHooksRev2)(buildingBlocks[6]);
const ensureAtomState = buildingBlocks[11];
const flushCallbacks = buildingBlocks[12];
const readAtomState = buildingBlocks[14];
const mountDependencies = buildingBlocks[17];
const mountAtom = buildingBlocks[18];
const unmountAtom = buildingBlocks[19];
let inProgress = false;
let isSubscribed = false;
const effectAtom = (0, atomEffect_1.atomEffect)((get, set) => {
if (inProgress) {
return;
}
isSubscribed = false;
const getter = (a) => {
if (a === targetWithEffect) {
isSubscribed = true;
return get.peek(a);
}
return get(a);
};
getter.peek = get.peek;
const setter = (a, ...args) => {
if (a === targetWithEffect) {
inProgress = true;
return set(a, ...args);
}
return set(a, ...args);
};
setter.recurse = (...args) => {
inProgress = false;
return set.recurse(...args);
};
return targetWithEffect.effect.call(targetAtom, getter, setter);
});
if ((0, env_1.isDev)()) {
Object.defineProperty(effectAtom, 'debugLabel', {
get: () => { var _a; return `${(_a = targetWithEffect.debugLabel) !== null && _a !== void 0 ? _a : 'atom'}:effect`; },
});
effectAtom.debugPrivate = true;
}
const effectAtomState = ensureAtomState(store, effectAtom);
const targetWithEffectAtomState = ensureAtomState(store, targetWithEffect);
storeHooks.c.add(targetWithEffect, function atomChanged() {
if (isSubscribed) {
invalidatedAtoms.set(effectAtom, effectAtomState.n);
effectAtomState.d.set(targetWithEffect, targetWithEffectAtomState.n - 1);
readAtomState(store, effectAtom);
mountDependencies(store, effectAtom);
invalidatedAtoms.delete(effectAtom);
effectAtomState.d.delete(targetWithEffect);
}
});
storeHooks.m.add(targetWithEffect, function mountEffect() {
mountAtom(store, effectAtom);
flushCallbacks(store);
});
storeHooks.u.add(targetWithEffect, function unmountEffect() {
unmountAtom(store, effectAtom);
flushCallbacks(store);
});
storeHooks.f.add(function flushEffect() {
inProgress = false;
});
};
targetWithEffect.effect = effect;
return targetWithEffect;
}
function isWritableAtom(atom) {
return 'write' in atom && typeof atom.write === 'function';
}
//# sourceMappingURL=withAtomEffect.js.map