import path from './path.js'; /** @class Cache @private */ export default class Cache { constructor(equals) { this._equals = equals; this._proxyCache = new WeakMap(); this._pathCache = new WeakMap(); this.isUnsubscribed = false; } _getDescriptorCache() { if (this._descriptorCache === undefined) { this._descriptorCache = new WeakMap(); } return this._descriptorCache; } _getProperties(target) { const descriptorCache = this._getDescriptorCache(); let properties = descriptorCache.get(target); if (properties === undefined) { properties = {}; descriptorCache.set(target, properties); } return properties; } _getOwnPropertyDescriptor(target, property) { if (this.isUnsubscribed) { return Reflect.getOwnPropertyDescriptor(target, property); } const properties = this._getProperties(target); let descriptor = properties[property]; if (descriptor === undefined) { descriptor = Reflect.getOwnPropertyDescriptor(target, property); properties[property] = descriptor; } return descriptor; } getProxy(target, path, handler, proxyTarget) { if (this.isUnsubscribed) { return target; } const reflectTarget = target[proxyTarget]; const source = reflectTarget ?? target; this._pathCache.set(source, path); let proxy = this._proxyCache.get(source); if (proxy === undefined) { proxy = reflectTarget === undefined ? new Proxy(target, handler) : target; this._proxyCache.set(source, proxy); } return proxy; } getPath(target) { return this.isUnsubscribed ? undefined : this._pathCache.get(target); } isDetached(target, object) { return !Object.is(target, path.get(object, this.getPath(target))); } defineProperty(target, property, descriptor) { if (!Reflect.defineProperty(target, property, descriptor)) { return false; } if (!this.isUnsubscribed) { this._getProperties(target)[property] = descriptor; } return true; } setProperty(target, property, value, receiver, previous) { // eslint-disable-line max-params if (!this._equals(previous, value) || !(property in target)) { const descriptor = this._getOwnPropertyDescriptor(target, property); if (descriptor !== undefined && 'set' in descriptor) { return Reflect.set(target, property, value, receiver); } return Reflect.set(target, property, value); } return true; } deleteProperty(target, property, previous) { if (Reflect.deleteProperty(target, property)) { if (!this.isUnsubscribed) { const properties = this._getDescriptorCache().get(target); if (properties) { delete properties[property]; this._pathCache.delete(previous); } } return true; } return false; } isSameDescriptor(a, target, property) { const b = this._getOwnPropertyDescriptor(target, property); return a !== undefined && b !== undefined && Object.is(a.value, b.value) && (a.writable || false) === (b.writable || false) && (a.enumerable || false) === (b.enumerable || false) && (a.configurable || false) === (b.configurable || false) && a.get === b.get && a.set === b.set; } isGetInvariant(target, property) { const descriptor = this._getOwnPropertyDescriptor(target, property); return descriptor !== undefined && descriptor.configurable !== true && descriptor.writable !== true; } unsubscribe() { this._descriptorCache = null; this._pathCache = null; this._proxyCache = null; this.isUnsubscribed = true; } }