@vorthain/react-state
Version:
A minimal and reactive state management library for React, enabling automatic UI updates through direct, mutable state changes.
1,186 lines (1,182 loc) • 65.7 kB
JavaScript
'use strict';
var React = require('react');
var jsxRuntime = require('react/jsx-runtime');
let currentComponent = null;
const propertySubscriptions = new Map();
const liveComponents = new WeakSet();
const observableCache = new WeakMap();
let objectIdCounter = 1;
const objectIds$1 = new WeakMap();
const computedDependencies = new Map();
const computedCache = new Map();
let isBatching = false;
let batchedUpdates = new Set();
let vGripNotifier = null;
let vGripBatchStartFn = null;
let vGripBatchEndFn = null;
let vGripGetCurrentTracker$1 = null;
let vGripTrackDependency$1 = null;
function registerVGripNotifier(notifier) {
vGripNotifier = notifier;
}
function registerVGripBatchHandlers(startFn, endFn) {
vGripBatchStartFn = startFn;
vGripBatchEndFn = endFn;
}
function registerVGripTracking(getCurrentTracker, trackDependency) {
vGripGetCurrentTracker$1 = getCurrentTracker;
vGripTrackDependency$1 = trackDependency;
}
function getObjectId$1(obj) {
if (!objectIds$1.has(obj)) {
objectIds$1.set(obj, objectIdCounter++);
}
return objectIds$1.get(obj);
}
function getPropertyKey(target, prop) {
return `${getObjectId$1(target)}:${String(prop)}`;
}
function isObservable(obj) {
return obj && typeof obj === 'object' && obj.__vorthainReactive === true;
}
function vAction(actionFn) {
if (isBatching) {
return actionFn();
}
isBatching = true;
batchedUpdates.clear();
if (vGripBatchStartFn) {
vGripBatchStartFn();
}
try {
const result = actionFn();
if (batchedUpdates.size > 0 || vGripBatchEndFn) {
queueMicrotask(() => {
batchedUpdates.forEach((updateFn) => {
if (liveComponents.has(updateFn)) {
try {
updateFn();
}
catch (e) {
console.error('Error in batched update:', e);
}
}
});
batchedUpdates.clear();
if (vGripBatchEndFn) {
vGripBatchEndFn();
}
});
}
return result;
}
finally {
isBatching = false;
}
}
function makeObservable(target) {
if (!target || typeof target !== 'object')
return target;
if (target.__vorthainReactive)
return target;
if (observableCache.has(target)) {
return observableCache.get(target);
}
if (target instanceof Date ||
target instanceof RegExp ||
target instanceof HTMLElement ||
target instanceof File ||
target instanceof Blob ||
target instanceof FormData ||
target instanceof ArrayBuffer ||
ArrayBuffer.isView(target) ||
target instanceof NodeList ||
target instanceof HTMLCollection) {
return target;
}
observableCache.set(target, target);
if (Array.isArray(target)) {
return makeArrayObservable(target);
}
else if (target instanceof Map) {
return makeMapObservable(target);
}
else if (target instanceof Set) {
return makeSetObservable(target);
}
else {
return makeObjectObservable(target);
}
}
function makeObjectObservable(target) {
Object.defineProperty(target, '__vorthainReactive', {
value: true,
writable: false,
enumerable: false,
configurable: false
});
const allProps = new Set([
...Object.getOwnPropertyNames(target),
...Object.getOwnPropertySymbols(target)
]);
allProps.forEach((prop) => {
if (prop === '__vorthainReactive')
return;
const descriptor = Object.getOwnPropertyDescriptor(target, prop);
if (!descriptor || !descriptor.configurable)
return;
if (descriptor.get || descriptor.set) {
makeGetterSetterReactive(target, prop, descriptor);
}
else {
if (descriptor.value && typeof descriptor.value === 'object') {
descriptor.value = makeObservable(descriptor.value);
}
makePropertyReactive(target, prop, descriptor.value);
}
});
return target;
}
function makePropertyReactive(target, prop, initialValue) {
let currentValue = initialValue;
if (currentValue && typeof currentValue === 'object') {
currentValue = makeObservable(currentValue);
}
Object.defineProperty(target, prop, {
get() {
const propKey = getPropertyKey(target, prop);
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
if (vGripGetCurrentTracker$1 && vGripTrackDependency$1) {
const tracker = vGripGetCurrentTracker$1();
if (tracker && tracker.isRendering) {
vGripTrackDependency$1(tracker, target, prop, currentValue);
}
}
if (currentComputedContext) {
trackComputedDependency(propKey);
}
return currentValue;
},
set(newValue) {
if (currentValue === newValue)
return;
if (newValue && typeof newValue === 'object') {
newValue = makeObservable(newValue);
}
currentValue = newValue;
invalidateComputedsThatDependOn(target, prop);
const propKey = getPropertyKey(target, prop);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, prop);
}
},
enumerable: true,
configurable: true
});
}
let currentComputedContext = null;
function trackComputedDependency(propKey) {
if (!currentComputedContext)
return;
const { target, prop } = currentComputedContext;
if (!computedDependencies.has(target)) {
computedDependencies.set(target, new Map());
}
const targetDeps = computedDependencies.get(target);
if (!targetDeps.has(prop)) {
targetDeps.set(prop, new Set());
}
targetDeps.get(prop).add(propKey);
}
function invalidateComputedsThatDependOn(obj, prop) {
const propKey = getPropertyKey(obj, prop);
computedCache.forEach((cache, target) => {
cache.forEach((cacheEntry, computedProp) => {
const deps = computedDependencies.get(target)?.get(computedProp);
if (deps && deps.has(propKey)) {
const oldValue = cacheEntry.value;
cacheEntry.isValid = false;
if (vGripNotifier) {
const descriptor = Object.getOwnPropertyDescriptor(target, computedProp);
if (descriptor && descriptor.get) {
try {
const newValue = descriptor.get.call(target);
if (newValue !== oldValue) {
vGripNotifier(target, computedProp);
}
}
catch (e) {
vGripNotifier(target, computedProp);
}
}
}
}
});
});
}
function makeGetterSetterReactive(target, prop, descriptor) {
const originalGet = descriptor.get;
const originalSet = descriptor.set;
Object.defineProperty(target, prop, {
get() {
if (!originalGet)
return undefined;
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, prop);
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
if (!computedCache.has(target)) {
computedCache.set(target, new Map());
}
const cache = computedCache.get(target);
if (!cache.has(prop)) {
cache.set(prop, { value: undefined, isValid: false });
}
const cacheEntry = cache.get(prop);
const tracker = vGripGetCurrentTracker$1?.();
const shouldUseCache = cacheEntry.isValid && !currentComponent && !tracker;
if (shouldUseCache) {
return cacheEntry.value;
}
const prevComponent = currentComponent;
const prevComputedContext = currentComputedContext;
currentComputedContext = { target, prop };
const computedNotifier = () => {
const propKey = getPropertyKey(target, prop);
notifySubscribers(propKey);
};
if (!tracker) {
currentComponent = computedNotifier;
}
try {
const result = originalGet.call(target);
cacheEntry.value = result;
cacheEntry.isValid = true;
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, prop, result);
}
return result;
}
finally {
if (!tracker) {
currentComponent = prevComponent;
}
currentComputedContext = prevComputedContext;
}
},
set(newValue) {
if (!originalSet)
return;
if (newValue && typeof newValue === 'object') {
newValue = makeObservable(newValue);
}
originalSet.call(target, newValue);
const cache = computedCache.get(target);
if (cache && cache.has(prop)) {
cache.get(prop).isValid = false;
}
const propKey = getPropertyKey(target, prop);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, prop);
}
},
enumerable: descriptor.enumerable,
configurable: true
});
}
const ARRAY_METHODS = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse',
'fill',
'copyWithin'
];
function makeArrayObservable(target) {
Object.defineProperty(target, '__vorthainReactive', {
value: true,
writable: false,
enumerable: false,
configurable: false
});
for (let i = 0; i < target.length; i++) {
if (target[i] && typeof target[i] === 'object' && !isObservable(target[i])) {
target[i] = makeObservable(target[i]);
}
}
const originalMethods = {};
ARRAY_METHODS.forEach((method) => {
const fn = target[method];
if (typeof fn === 'function') {
originalMethods[method] = fn.bind(target);
}
});
const arrayProxy = new Proxy(target, {
get(target, prop, receiver) {
if (typeof prop === 'string' && ARRAY_METHODS.includes(prop)) {
return function (...args) {
const oldLength = target.length;
const oldItems = [...target];
let processedArgs = args;
if (prop === 'push' || prop === 'unshift') {
processedArgs = args.map((item) => item && typeof item === 'object' ? makeObservable(item) : item);
}
else if (prop === 'splice' && args.length > 2) {
processedArgs = [...args];
for (let i = 2; i < processedArgs.length; i++) {
if (processedArgs[i] && typeof processedArgs[i] === 'object') {
processedArgs[i] = makeObservable(processedArgs[i]);
}
}
}
const result = originalMethods[prop].apply(target, processedArgs);
for (let i = 0; i < target.length; i++) {
if (target[i] && typeof target[i] === 'object' && !isObservable(target[i])) {
target[i] = makeObservable(target[i]);
}
}
const lengthChanged = target.length !== oldLength;
const itemsChanged = !oldItems.every((item, i) => target[i] === item);
if (lengthChanged) {
const lengthKey = getPropertyKey(target, 'length');
notifySubscribers(lengthKey);
}
if (vGripNotifier) {
if (lengthChanged) {
vGripNotifier(target, 'length');
}
if (itemsChanged || ['sort', 'reverse'].includes(prop)) {
const maxLength = Math.max(target.length, oldLength);
for (let i = 0; i < maxLength; i++) {
if (i >= target.length || i >= oldItems.length || target[i] !== oldItems[i]) {
vGripNotifier(target, i.toString());
}
}
}
}
return result;
};
}
if (typeof prop === 'string' && !isNaN(Number(prop))) {
const index = Number(prop);
let item = target[index];
if (item && typeof item === 'object' && !isObservable(item)) {
item = makeObservable(item);
target[index] = item;
}
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, prop);
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, prop, item);
}
return item;
}
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, prop);
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
const value = Reflect.get(target, prop, receiver);
vGripTrackDependency$1(tracker, target, prop, value);
return value;
}
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
if (prop === 'length') {
const oldLength = target.length;
const newLength = Number(value);
if (newLength < oldLength) {
for (let i = newLength; i < oldLength; i++) {
delete target[i];
}
}
target.length = newLength;
const propKey = getPropertyKey(target, 'length');
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, 'length');
for (let i = newLength; i < oldLength; i++) {
vGripNotifier(target, i.toString());
}
}
return true;
}
if (value && typeof value === 'object' && !isObservable(value)) {
value = makeObservable(value);
}
const oldValue = target[prop];
const result = Reflect.set(target, prop, value, receiver);
if (oldValue !== value) {
const propKey = getPropertyKey(target, prop);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, prop);
}
}
return result;
},
deleteProperty(target, prop) {
const result = Reflect.deleteProperty(target, prop);
if (result) {
const propKey = getPropertyKey(target, prop);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, prop);
}
}
return result;
}
});
return arrayProxy;
}
function makeMapObservable(target) {
Object.defineProperty(target, '__vorthainReactive', {
value: true,
writable: false,
enumerable: false,
configurable: false
});
for (const [key, value] of target) {
if (value && typeof value === 'object' && !isObservable(value)) {
target.set(key, makeObservable(value));
}
}
const originalGet = target.get.bind(target);
const originalSet = target.set.bind(target);
const originalDelete = target.delete.bind(target);
const originalClear = target.clear.bind(target);
const originalForEach = target.forEach.bind(target);
const originalEntries = target.entries.bind(target);
const originalValues = target.values.bind(target);
const originalKeys = target.keys.bind(target);
const mapProxy = new Proxy(target, {
get(target, prop, receiver) {
if (prop === 'size') {
const size = target.size;
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, 'size');
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, 'size', size);
}
return size;
}
if (prop === 'get') {
return function (key) {
const value = originalGet(key);
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, key);
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, key, value);
}
if (value && typeof value === 'object' && !isObservable(value)) {
const reactiveValue = makeObservable(value);
originalSet(key, reactiveValue);
return reactiveValue;
}
return value;
};
}
if (prop === 'set') {
return function (key, value) {
if (value && typeof value === 'object') {
value = makeObservable(value);
}
const oldValue = originalGet(key);
const oldSize = target.size;
const result = originalSet(key, value);
if (oldValue !== value) {
const propKey = getPropertyKey(target, key);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, key);
}
}
if (oldSize !== target.size) {
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
}
}
const iterKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, Symbol.for('__map_iteration__'));
}
return result;
};
}
if (prop === 'delete') {
return function (key) {
const oldSize = target.size;
const result = originalDelete(key);
if (result) {
const propKey = getPropertyKey(target, key);
notifySubscribers(propKey);
const iterKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, key);
vGripNotifier(target, Symbol.for('__map_iteration__'));
}
if (oldSize !== target.size) {
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
}
}
}
return result;
};
}
if (prop === 'clear') {
return function () {
const oldSize = target.size;
const oldKeys = Array.from(target.keys());
const result = originalClear();
if (oldSize > 0) {
oldKeys.forEach((key) => {
const propKey = getPropertyKey(target, key);
notifySubscribers(propKey);
if (vGripNotifier) {
vGripNotifier(target, key);
}
});
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
const iterKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
vGripNotifier(target, Symbol.for('__map_iteration__'));
}
}
return result;
};
}
if (prop === 'forEach') {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__map_iteration__'), null);
}
return function (callback, thisArg) {
return originalForEach((value, key, map) => {
if (value && typeof value === 'object' && !isObservable(value)) {
value = makeObservable(value);
originalSet(key, value);
}
callback.call(thisArg, value, key, map);
});
};
}
if (prop === 'keys') {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__map_iteration__'), null);
}
return function* () {
for (const key of originalKeys()) {
yield key;
}
};
}
if (prop === 'entries' || prop === Symbol.iterator) {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__map_iteration__'), null);
}
return function* () {
for (const [key, value] of originalEntries()) {
let reactiveValue = value;
if (value && typeof value === 'object' && !isObservable(value)) {
reactiveValue = makeObservable(value);
originalSet(key, reactiveValue);
}
yield [key, reactiveValue];
}
};
}
if (prop === 'values') {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__map_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__map_iteration__'), null);
}
return function* () {
for (const value of originalValues()) {
if (value && typeof value === 'object' && !isObservable(value)) {
const key = Array.from(originalEntries()).find(([k, v]) => v === value)?.[0];
if (key !== undefined) {
const reactiveValue = makeObservable(value);
originalSet(key, reactiveValue);
yield reactiveValue;
}
else {
yield value;
}
}
else {
yield value;
}
}
};
}
return Reflect.get(target, prop, target);
}
});
return mapProxy;
}
function makeSetObservable(target) {
Object.defineProperty(target, '__vorthainReactive', {
value: true,
writable: false,
enumerable: false,
configurable: false
});
const existingValues = Array.from(target);
target.clear();
existingValues.forEach((value) => {
if (value && typeof value === 'object' && !isObservable(value)) {
target.add(makeObservable(value));
}
else {
target.add(value);
}
});
const originalAdd = target.add.bind(target);
const originalDelete = target.delete.bind(target);
const originalClear = target.clear.bind(target);
const originalForEach = target.forEach.bind(target);
const originalValues = target.values.bind(target);
const originalEntries = target.entries.bind(target);
const originalHas = target.has.bind(target); // Bind the 'has' method
const setProxy = new Proxy(target, {
get(target, prop, receiver) {
if (prop === 'size') {
const size = target.size;
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, 'size');
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, 'size', size);
}
return size;
}
if (prop === 'has') {
return function (value) {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const iterKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
let subscribers = propertySubscriptions.get(iterKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(iterKey, subscribers);
}
subscribers.add(currentComponent);
}
return originalHas(value);
};
}
if (prop === 'add') {
return function (value) {
if (value && typeof value === 'object') {
value = makeObservable(value);
}
const oldSize = target.size;
const result = originalAdd(value);
if (oldSize !== target.size) {
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
const iterKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
vGripNotifier(target, Symbol.for('__set_iteration__'));
}
}
return result;
};
}
if (prop === 'delete') {
return function (value) {
target.size;
const result = originalDelete(value);
if (result) {
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
const iterKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
vGripNotifier(target, Symbol.for('__set_iteration__'));
}
}
return result;
};
}
if (prop === 'clear') {
return function () {
const oldSize = target.size;
const result = originalClear();
if (oldSize > 0) {
const sizeKey = getPropertyKey(target, 'size');
notifySubscribers(sizeKey);
const iterKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
notifySubscribers(iterKey);
if (vGripNotifier) {
vGripNotifier(target, 'size');
vGripNotifier(target, Symbol.for('__set_iteration__'));
}
}
return result;
};
}
if (prop === 'forEach') {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__set_iteration__'), null);
}
return function (callback, thisArg) {
return originalForEach((value, set) => {
if (value && typeof value === 'object' && !isObservable(value)) {
value = makeObservable(value);
}
callback.call(thisArg, value, value, set);
});
};
}
if (prop === 'values' || prop === 'keys' || prop === Symbol.iterator) {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__set_iteration__'), null);
}
return function* () {
for (const value of originalValues()) {
if (value && typeof value === 'object' && !isObservable(value)) {
yield makeObservable(value);
}
else {
yield value;
}
}
};
}
if (prop === 'entries') {
if (currentComponent && !vGripGetCurrentTracker$1?.()) {
const propKey = getPropertyKey(target, Symbol.for('__set_iteration__'));
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(currentComponent);
}
const tracker = vGripGetCurrentTracker$1?.();
if (tracker && tracker.isRendering && vGripTrackDependency$1) {
vGripTrackDependency$1(tracker, target, Symbol.for('__set_iteration__'), null);
}
return function* () {
for (const [value1, value2] of originalEntries()) {
let reactiveValue = value1;
if (value1 && typeof value1 === 'object' && !isObservable(value1)) {
reactiveValue = makeObservable(value1);
}
yield [reactiveValue, reactiveValue];
}
};
}
return Reflect.get(target, prop, target);
}
});
return setProxy;
}
function notifySubscribers(propKey) {
const subscribers = propertySubscriptions.get(propKey);
if (!subscribers || subscribers.size === 0)
return;
const subscriberArray = Array.from(subscribers);
subscriberArray.forEach((subscriber) => {
if (liveComponents.has(subscriber)) {
if (isBatching) {
batchedUpdates.add(subscriber);
}
else {
queueMicrotask(() => {
if (liveComponents.has(subscriber)) {
try {
subscriber();
}
catch (e) {
console.error('Error in subscriber update:', e);
liveComponents.delete(subscriber);
subscribers.delete(subscriber);
}
}
});
}
}
else {
subscribers.delete(subscriber);
}
});
if (subscribers.size === 0) {
propertySubscriptions.delete(propKey);
}
}
function useObservableSubscription(observableState) {
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
const instanceRef = React.useRef(null);
if (!instanceRef.current) {
instanceRef.current = {
subscriptions: new Set(),
forceUpdate,
isCleanedUp: false
};
}
instanceRef.current.forceUpdate = forceUpdate;
liveComponents.add(forceUpdate);
React.useEffect(() => {
const instance = instanceRef.current;
liveComponents.add(instance.forceUpdate);
currentComponent = instance.forceUpdate;
try {
subscribeToObject(observableState);
}
catch (e) {
console.warn('Error subscribing to observable:', e);
}
finally {
currentComponent = null;
}
instance.subscriptions.forEach((propKey) => {
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.forEach((sub) => {
if (!liveComponents.has(sub) && sub !== instance.forceUpdate) {
subscribers.delete(sub);
}
});
subscribers.add(instance.forceUpdate);
});
instance.isCleanedUp = false;
return () => {
instance.isCleanedUp = true;
queueMicrotask(() => {
if (instance.isCleanedUp) {
liveComponents.delete(instance.forceUpdate);
instance.subscriptions.forEach((propKey) => {
const subscribers = propertySubscriptions.get(propKey);
if (subscribers) {
subscribers.delete(instance.forceUpdate);
if (subscribers.size === 0) {
propertySubscriptions.delete(propKey);
}
}
});
}
});
};
}, [observableState]);
return new Proxy(observableState, {
get(target, prop, receiver) {
const instance = instanceRef.current;
// Helper function to wrap Map.get return values
const wrapMapGetResult = (originalGet, target) => {
return function (key) {
const result = originalGet.call(target, key);
if (result && typeof result === 'object') {
const proxyKey = Symbol.for('__vorthain_proxy__');
if (result[proxyKey]) {
return result;
}
const proxy = new Proxy(result, {
get(innerTarget, innerProp, innerReceiver) {
if (innerProp === proxyKey)
return true;
// Recursive handling for nested Maps
if (typeof innerTarget[innerProp] === 'function') {
if (innerTarget instanceof Map && innerProp === 'get') {
return wrapMapGetResult(Reflect.get(innerTarget, innerProp, innerReceiver), innerTarget);
}
return Reflect.get(innerTarget, innerProp, innerReceiver);
}
currentComponent = instance.forceUpdate;
liveComponents.add(instance.forceUpdate);
const innerPropKey = getPropertyKey(innerTarget, innerProp);
if (!instance.subscriptions.has(innerPropKey)) {
instance.subscriptions.add(innerPropKey);
}
let innerSubscribers = propertySubscriptions.get(innerPropKey);
if (!innerSubscribers) {
innerSubscribers = new Set();
propertySubscriptions.set(innerPropKey, innerSubscribers);
}
innerSubscribers.add(instance.forceUpdate);
const value = Reflect.get(innerTarget, innerProp, innerReceiver);
// Handle nested objects/Maps/Sets
if (value && typeof value === 'object') {
return new Proxy(value, this);
}
return value;
}
});
return proxy;
}
return result;
};
};
// Handle functions
if (typeof target[prop] === 'function') {
if (target instanceof Map && prop === 'get') {
return wrapMapGetResult(Reflect.get(target, prop, receiver), target);
}
return Reflect.get(target, prop, receiver);
}
// Regular property access
const propKey = getPropertyKey(target, prop);
if (!instance.subscriptions.has(propKey)) {
instance.subscriptions.add(propKey);
}
let subscribers = propertySubscriptions.get(propKey);
if (!subscribers) {
subscribers = new Set();
propertySubscriptions.set(propKey, subscribers);
}
subscribers.add(instance.forceUpdate);
const prevComponent = currentComponent;
if (!vGripGetCurrentTracker$1?.()) {
currentComponent = instance.forceUpdate;
}
try {
const value = Reflect.get(target, prop, receiver);
if (value && typeof value === 'object' && !vGripGetCurrentTracker$1?.()) {
const proxyKey = Symbol.for('__vorthain_proxy__');
if (value[proxyKey]) {
return value;
}
const proxy = new Proxy(value, {
get(innerTarget, innerProp, innerReceiver) {
if (innerProp === proxyKey)
return true;
if (typeof innerTarget[innerProp] === 'function') {
if (innerTarget instanceof Map && innerProp === 'get') {
return wrapMapGetResult(Reflect.get(innerTarget, innerProp, innerReceiver), innerTarget);
}
return Reflect.get(innerTarget, innerProp, innerReceiver);
}
currentComponent = instance.forceUpdate;
liveComponents.add(instance.forceUpdate);
const innerPropKey = getPropertyKey(innerTarget, innerProp);
if (!instance.subscriptions.has(innerPropKey)) {
instance.subscriptions.add(innerPropKey);
}
let innerSubscribers = propertySubscriptions.get(innerPropKey);
if (!innerSubscribers) {
innerSubscribers = new Set();
propertySubscriptions.set(innerPropKey, innerSubscribers);
}
innerSubscribers.add(instance.forceUpdate);
return Reflect.get(innerTarget, innerProp, innerReceiver);
}
});
return proxy;
}
return value;
}
finally {
currentComponent = prevComponent;
}
}
});
}
function subscribeToObject(obj, visited = new WeakSet()) {
if (!obj || typeof obj !== 'object' || visited.has(obj))
return;
visited.add(obj);
try {
if (Array.isArray(obj)) {
obj.length;
for (let i = 0; i < obj.length; i++) {
const item = obj[i];
}
}
else if (obj instanceof Map) {
obj.size;
}
else if (obj instanceof Set) {
obj.size;
}
else {
Object.keys(obj).forEach((key) => {
try {
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
if (descriptor && descriptor.get) {
return;
}
if (typeof obj[key] === 'function') {
return;
}
obj[key];
}
catch (e) { }
});
}
}
catch (e) { }
}
const vGripTrackers = new Map();
const objectToTrackers = new Map();
let currentRenderingTracker = null;
let insideVActionBatch = false;
const vActionBatchedTrackers = new Set();
const pendingTrackerUpdates = new Set();
let updateFlushScheduled = false;
let nextTrackerId = 0;
let nextObjectId = 0;
const objectIds = new WeakMap();
function getCurrentRenderingTracker() {
return currentRenderingTracker;
}
function vGripGetCurrentTracker() {
return currentRenderingTracker;
}
function getObjectId(obj) {
if (!objectIds.has(obj)) {
objectIds.set(obj, `obj_${++nextObjectId}`);
}
return objectIds.get(obj);
}
function createDependencyKey(obj, prop) {
return `${getObjectId(obj)}::${String(prop)}`;
}
function vGripTrackDependency(tracker, obj, prop, value, path = '') {
if (tracker !== currentRenderingTracker || !tracker.isRendering) {
return;
}
if (typeof value === 'function') {
return;
}
const key = createDependencyKey(obj, prop);
tracker.dependencies.set(key, {
object: obj,
property: prop,
value: value,
path: path || `${getObjectId(obj)}.${String(prop)}`
});
if (!objectToTrackers.has(obj)) {
objectToTrackers.set(obj, new Map());
}
const objTrackers = objectToTrackers.get(obj);
const propKey = String(prop);
if (!objTrackers.has(propKey)) {