UNPKG

fluidstate

Version:

Library for fine-grained reactivity state management

195 lines (194 loc) 7.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createReactiveObject = void 0; var _reactiveNames = require("../extras/reactive-names"); var _reactivePlugin = require("../extras/reactive-plugin"); var _reactivePluginObject = require("../extras/reactive-plugin-object"); var _reactiveAction = require("../primitives/reactive-action"); var _reactiveAtom = require("../primitives/reactive-atom"); var _reactiveComputed = require("../primitives/reactive-computed"); var _reactiveOptions = require("../primitives/reactive-options"); var _reactiveTracking = require("../primitives/reactive-tracking"); var _reactiveChildren = require("./reactive-children"); var _reactiveProxy = require("./reactive-proxy"); var _reactiveUtils = require("./reactive-utils"); var ValueType; (function (ValueType) { ValueType[ValueType["atom"] = 0] = "atom"; ValueType[ValueType["computed"] = 1] = "computed"; })(ValueType || (ValueType = {})); const createReactiveObject = (inertObject, reactiveOptions, nameOptions) => { const atomName = (0, _reactiveNames.createAtomNameFromOptions)(nameOptions); const proxy = new Proxy(inertObject, new ReactiveObjectProxyHandler(atomName, { values: {}, keys: (0, _reactiveAtom.createAtom)((0, _reactiveNames.createObjectKeysAtomName)(atomName)) }, () => proxy, reactiveOptions)); return proxy; }; exports.createReactiveObject = createReactiveObject; class ReactiveObjectProxyHandler { #atomName; #reactive; #getProxy; #options; constructor(atomName, reactive, getProxy, reactiveOptions) { this.#atomName = atomName; this.#reactive = reactive; this.#getProxy = getProxy; this.#options = { reactiveOptions }; } get(inertObject, p, receiver) { const isReactive = this.#isReactiveProperty(p); if (!isReactive) { return (0, _reactiveTracking.untrack)(() => { return Reflect.get(inertObject, p, receiver); }); } const { descriptor } = (0, _reactiveUtils.getDescriptor)(inertObject, p); if (descriptor?.get) { const result = this.#readComputedValue(p, descriptor.get); return (0, _reactiveChildren.getChild)(this.#options, result, () => (0, _reactiveProxy.createProxy)(result, (0, _reactiveChildren.getChildOptions)(this.#options), { parentAtomName: this.#atomName, createAtomName: _reactiveNames.createObjectComputedValueAtomName, childIndex: p.toString() })); } this.#readAtomValue(p); const result = Reflect.get(inertObject, p, receiver); if (typeof result === "function") { return (0, _reactiveAction.createAction)(result); } return (0, _reactiveChildren.getChild)(this.#options, result, () => (0, _reactiveProxy.createProxy)(result, (0, _reactiveChildren.getChildOptions)(this.#options), { parentAtomName: this.#atomName, createAtomName: _reactiveNames.createObjectValueAtomName, childIndex: p.toString() })); } set(inertObject, p, newValue, receiver) { const isReactive = this.#isReactiveProperty(p); const newStoredValue = !isReactive || this.#options.reactiveOptions?.deep === false ? newValue : (0, _reactiveProxy.ensureInert)(newValue); const { descriptor } = (0, _reactiveUtils.getDescriptor)(inertObject, p); if (descriptor?.get || descriptor?.set) { return (0, _reactiveAction.runAction)(() => { return Reflect.set(inertObject, p, newStoredValue, receiver); }); } const hasProperty = inertObject.hasOwnProperty(p); const currentValue = Reflect.get(inertObject, p, receiver); const isChanged = !(0, _reactiveOptions.reactiveValueEquals)(currentValue, newStoredValue); const changes = !this.#hasPlugins() || !isChanged ? null : (0, _reactivePluginObject.getObjectSetChanges)(this.#getProxy(), p, currentValue, newStoredValue); if (changes) { (0, _reactivePlugin.beforeChange)(changes, this.#options.reactiveOptions?.plugins); } const result = Reflect.set(inertObject, p, newStoredValue, receiver); if (result && isReactive) { (0, _reactiveAction.runTransaction)(() => { if (isChanged) { this.#notifyValue(p); } if (!hasProperty) { this.#reactive.keys.reportChanged(); } }); } if (changes) { (0, _reactivePlugin.afterChange)(changes, this.#options.reactiveOptions?.plugins); } return result; } deleteProperty(inertObject, p) { const isReactive = this.#isReactiveProperty(p); const { descriptor } = (0, _reactiveUtils.getDescriptor)(inertObject, p); const hasProperty = inertObject.hasOwnProperty(p); const currentValue = Reflect.get(inertObject, p); const isChanged = descriptor?.get || descriptor?.set || !(0, _reactiveOptions.reactiveValueEquals)(currentValue, undefined); const changes = !this.#hasPlugins() || !isChanged ? null : (0, _reactivePluginObject.getObjectDeleteChanges)(this.#getProxy(), p, currentValue); if (changes) { (0, _reactivePlugin.beforeChange)(changes, this.#options.reactiveOptions?.plugins); } const result = Reflect.deleteProperty(inertObject, p); if (result && isReactive) { (0, _reactiveAction.runTransaction)(() => { if (isChanged) { this.#notifyValue(p); } if (hasProperty) { this.#reactive.keys.reportChanged(); } }); } if (changes) { (0, _reactivePlugin.afterChange)(changes, this.#options.reactiveOptions?.plugins); } return result; } ownKeys(inertObject) { this.#reactive.keys.reportObserved(); return Reflect.ownKeys(inertObject); } #isReactiveProperty(p) { return (!this.#options.reactiveOptions?.reactiveList || this.#options.reactiveOptions.reactiveList.indexOf(p) >= 0) && (!this.#options.reactiveOptions?.nonReactiveList || this.#options.reactiveOptions.nonReactiveList.indexOf(p) < 0); } #notifyValue(p) { const node = this.#reactive.values[p]; if (node && node.type === ValueType.atom) { node.value.reportChanged(); } } #readAtomValue(p) { let node = this.#reactive.values[p]; if (!node || node.type !== ValueType.atom) { if (!(0, _reactiveTracking.isTracking)()) { return; } const value = (0, _reactiveAtom.createAtom)((0, _reactiveNames.createObjectValueAtomName)(this.#atomName, p.toString()), { onBecomeUnobservedListener: () => { this.#cleanupValue(p); } }); node = { type: ValueType.atom, value }; this.#reactive.values[p] = node; } node.value.reportObserved(); } #cleanupValue(p) { delete this.#reactive.values[p]; } #readComputedValue(p, calculate) { let node = this.#reactive.values[p]; if (!node || node.type !== ValueType.computed) { const proxy = this.#getProxy(); if (!(0, _reactiveTracking.isTracking)()) { return calculate.call(proxy); } const value = (0, _reactiveComputed.createComputedAtom)((0, _reactiveNames.createObjectComputedValueAtomName)(this.#atomName, p.toString()), calculate.bind(proxy), { onBecomeUnobservedListener: () => { this.#cleanupValue(p); } }); node = { type: ValueType.computed, value }; this.#reactive.values[p] = node; } return node.value.get(); } #hasPlugins() { return (this.#options.reactiveOptions?.plugins?.length ?? 0) > 0; } } //# sourceMappingURL=reactive-object.js.map