import { subscribable } from './subscribable.js'; export const hashableContainer = hash => store => { let id = hash && hash(store); let lockCount = 0; const containerMethods = { _lock: () => { lockCount += 1; return p; }, _unlock: () => { if (lockCount && --lockCount === 0) { checkUpdate(store); } }, ...subscribable() }; function checkUpdate(target) { if (lockCount) { return; } let newId = hash && hash(target); if (!hash || id !== newId) { id = newId; containerMethods._fire(target); } } const p = new Proxy(store, { apply: (target, context, args) => { return target; }, get: (target, name) => { if (name in containerMethods) { return containerMethods[name]; } if (name === '_') { return target; } const thing = target[name]; if (typeof thing === 'function') { return (...args) => { const ret = target[name](...args); checkUpdate(target); return ret; }; } return thing; }, set: (target, name, newVal) => { if (name in containerMethods) { throw new ReferenceError(`Cannot set ${name} in ${target}`); } target[name] = newVal; checkUpdate(target); // Returning a falsey value causes TypeError // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set#Invariants return newVal || true; } }); return p; }; export const container = hashableContainer();