Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fluidstate

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fluidstate - npm Package Compare versions

Comparing version 0.0.12 to 0.0.13

reactive-cleanup-utils.d.ts

7

api.d.ts

@@ -9,6 +9,6 @@ import { Configuration } from "./types";

getConfiguration: () => Configuration;
createCustomObserved: <T_3>(inert: import("./types").InertControl<T_3>) => import("./types").Observed<T_3>;
createCustomObserved: <T_3>(inert: import("./types").InertControl<T_3>, lifeCycle?: import("./types").LifeCycle | undefined) => import("./types").Observed<T_3>;
createObserved: <T_4>(value: T_4) => import("./types").Observed<T_4>;
createEmptyObserved: () => import("./types").Observed<void>;
createObserved: <T_4>(value: T_4) => import("./types").Observed<T_4>;
createCustomComputed: <T_5>(inert: import("./types").InertControl<T_5>, getCalculate: () => () => T_5) => import("./types").Computed<T_5>;
createCustomComputed: <T_5>(inert: import("./types").InertControl<T_5>, getCalculate: () => () => T_5, lifeCycle?: import("./types").LifeCycle | undefined) => import("./types").Computed<T_5>;
createComputed: <T_6>(calculate: () => T_6) => import("./types").Computed<T_6>;

@@ -21,2 +21,3 @@ createEffect: import("./types").CreateEffect;

}) => void;
stopAllEffects: () => void;
};

@@ -26,8 +26,9 @@ "use strict";

createCustomObserved,
createObserved,
createEmptyObserved,
createObserved,
createCustomComputed,
createComputed,
createEffect
} = (0, _nodes.createNodesApi)(configuration, dependenciesManager, updateManager);
createEffect,
stopAllEffects
} = (0, _nodes.createNodesApi)(dependenciesManager, updateManager);
return {

@@ -40,4 +41,4 @@ set,

createCustomObserved,
createObserved,
createEmptyObserved,
createObserved,
createCustomComputed,

@@ -48,3 +49,4 @@ createComputed,

batch: updateManager.batch,
triggerUpdate: updateManager.triggerUpdate
triggerUpdate: updateManager.triggerUpdate,
stopAllEffects
};

@@ -51,0 +53,0 @@ };

import { Configuration } from "./types";
export declare const DEFAULT_CLEANUP_DEBOUNCE_TIME_MS = 500;
export declare function createConfiguration(defaultConfiguration?: Partial<Configuration>): {

@@ -3,0 +4,0 @@ configuration: Configuration;

@@ -6,3 +6,6 @@ "use strict";

});
exports.DEFAULT_CLEANUP_DEBOUNCE_TIME_MS = void 0;
exports.createConfiguration = createConfiguration;
const DEFAULT_CLEANUP_DEBOUNCE_TIME_MS = 500;
exports.DEFAULT_CLEANUP_DEBOUNCE_TIME_MS = DEFAULT_CLEANUP_DEBOUNCE_TIME_MS;
const scheduleDefault = update => {

@@ -19,3 +22,4 @@ return setTimeout(() => {

scheduleFunction: scheduleDefault,
cancelFunction: cancelDefault
cancelFunction: cancelDefault,
reactiveCleanupDebounceTime: DEFAULT_CLEANUP_DEBOUNCE_TIME_MS
};

@@ -29,2 +33,5 @@ const configure = newConfiguration => {

}
if (newConfiguration.reactiveCleanupDebounceTime !== undefined) {
configuration.reactiveCleanupDebounceTime = newConfiguration.reactiveCleanupDebounceTime;
}
};

@@ -31,0 +38,0 @@ if (defaultConfiguration) {

@@ -9,5 +9,15 @@ "use strict";

const createDependenciesManager = nodeCollector => {
const nodeSelfWeakRefMap = new WeakMap();
const previousDependenciesMap = new WeakMap();
const getPreviousDependenciesStore = computed => {
let previousDependenciesStore = previousDependenciesMap.get(computed);
if (previousDependenciesStore) {
return previousDependenciesStore;
}
previousDependenciesStore = new Set();
previousDependenciesMap.set(computed, previousDependenciesStore);
return previousDependenciesStore;
};
const calculateValueAndDependencies = node => {
removeFromDerivedListOfDependencies(node);
const previousDependencies = getPreviousDependenciesStore(node);
(0, _utils.cloneSetToEmpty)(node.dependencies, previousDependencies);
node.dependencies.clear();

@@ -20,3 +30,11 @@ nodeCollector.startCollecting(node.dependencies);

nodeCollector.stopCollecting();
addToDerivedListOfDependencies(node);
for (const removed of (0, _utils.getSetRemoved)(previousDependencies, node.dependencies)) {
removed.derived.delete(node);
removed.lifeCycle?.onDerivedChanged(removed);
}
for (const added of (0, _utils.getSetAdded)(previousDependencies, node.dependencies)) {
added.derived.add(node);
added.lifeCycle?.onDerivedChanged(added);
}
previousDependencies.clear();
}

@@ -26,10 +44,6 @@ };

for (const dependency of node.dependencies) {
(0, _utils.removeItemFromWeakRefSetIfExists)(nodeSelfWeakRefMap, node, dependency.derived);
dependency.derived.delete(node);
dependency.lifeCycle?.onDerivedChanged(dependency);
}
};
const addToDerivedListOfDependencies = node => {
for (const dependency of node.dependencies) {
(0, _utils.addUniqueItemToWeakRefSet)(nodeSelfWeakRefMap, node, dependency.derived);
}
};
const disableComputed = node => {

@@ -36,0 +50,0 @@ const currentValue = node.inert.get();

@@ -9,6 +9,6 @@ import { createApi } from "./api";

getConfiguration: () => import("./types").Configuration;
createCustomObserved: <T_3>(inert: import("./types").InertControl<T_3>) => import("./types").Observed<T_3>;
createCustomObserved: <T_3>(inert: import("./types").InertControl<T_3>, lifeCycle?: import("./types").LifeCycle | undefined) => import("./types").Observed<T_3>;
createObserved: <T_4>(value: T_4) => import("./types").Observed<T_4>;
createEmptyObserved: () => import("./types").Observed<void>;
createObserved: <T_4>(value: T_4) => import("./types").Observed<T_4>;
createCustomComputed: <T_5>(inert: import("./types").InertControl<T_5>, getCalculate: () => () => T_5) => import("./types").Computed<T_5>;
createCustomComputed: <T_5>(inert: import("./types").InertControl<T_5>, getCalculate: () => () => T_5, lifeCycle?: import("./types").LifeCycle | undefined) => import("./types").Computed<T_5>;
createComputed: <T_6>(calculate: () => T_6) => import("./types").Computed<T_6>;

@@ -21,2 +21,3 @@ createEffect: import("./types").CreateEffect;

}) => void;
stopAllEffects: () => void;
};

@@ -32,3 +33,3 @@ declare const defaultReactiveApi: {

shouldResolveImmediatelyAfterBatch?: boolean | undefined;
}) => void;
}) => void, stopAllEffects: () => void;
declare const createEffect: import("./types").CreateEffect, createReactive: <T>(something: T) => T, getInert: <T extends object>(proxy: T) => T | null, getReactive: <T extends object>(something: T) => T | null, getComputedKeys: <T>(object: T) => Set<string | symbol>;

@@ -54,3 +55,3 @@ export { createApi, createReactiveApi };

* during batching, update will happen after the batch is finished (or ignored
* if the option is overriden). Update triggering will also be ignored in case
* if the option is overridden). Update triggering will also be ignored in case
* a current update is already in progress

@@ -68,5 +69,9 @@ */

/**
* Stops all effects that were created but not stopped yet
*/
stopAllEffects,
/**
* Creates a reactive wrapper (proxy) around any object. Arrays, sets, maps and
* regular objects are natively supported. Effects / computed properties that access
* items of these objects (such as keys, values, etc) automaticlaly subscribe to
* items of these objects (such as keys, values, etc) automatically subscribe to
* them. The reactive wrapper does not create a clone of the object - the original

@@ -73,0 +78,0 @@ * object is still used for all storage and is changed as changes are made to the

@@ -20,3 +20,3 @@ "use strict";

});
exports.triggerUpdate = exports.getReactive = exports.getInert = exports.getConfiguration = exports.getComputedKeys = exports.defaultReactiveApi = exports.defaultApi = void 0;
exports.triggerUpdate = exports.stopAllEffects = exports.getReactive = exports.getInert = exports.getConfiguration = exports.getComputedKeys = exports.defaultReactiveApi = exports.defaultApi = void 0;
var _api = require("./api");

@@ -32,4 +32,6 @@ var _reactiveApi = require("./reactive-api");

batch,
triggerUpdate
triggerUpdate,
stopAllEffects
} = defaultApi;
exports.stopAllEffects = stopAllEffects;
exports.triggerUpdate = triggerUpdate;

@@ -36,0 +38,0 @@ exports.batch = batch;

@@ -7,3 +7,2 @@ "use strict";

exports.createNodeCollector = void 0;
var _utils = require("./utils");
const createNodeCollector = () => {

@@ -18,3 +17,3 @@ const collectedStack = [];

}
const lastCollected = (0, _utils.lastArrayItem)(collectedStack);
const lastCollected = collectedStack[collectedStack.length - 1];
lastCollected.add(node);

@@ -21,0 +20,0 @@ };

import { DependenciesManager } from "./dependencies-manager";
import { Computed, Configuration, CreateEffect, InertControl, Node, Observed } from "./types";
import { Computed, CreateEffect, InertControl, LifeCycle, Node, Observed } from "./types";
import { UpdateManager } from "./update-manager";

@@ -10,12 +10,13 @@ export declare const isNode: (value: unknown) => value is Computed<unknown> | Observed<unknown>;

export declare const createDefaultCalculateControl: <T>(calculate: () => T) => () => () => T;
export declare const createNodesApi: (configuration: Configuration, dependenciesManager: DependenciesManager, updateManager: UpdateManager) => {
export declare const createNodesApi: (dependenciesManager: DependenciesManager, updateManager: UpdateManager) => {
set: <T>(node: Node<T>, newValue: T) => void;
notify: <T_1>(node: Node<T_1>) => void;
get: <T_2>(node: Node<T_2>) => T_2;
createCustomObserved: <T_3>(inert: InertControl<T_3>) => Observed<T_3>;
createCustomComputed: <T_4>(inert: InertControl<T_4>, getCalculate: () => () => T_4) => Computed<T_4>;
createCustomObserved: <T_3>(inert: InertControl<T_3>, lifeCycle?: LifeCycle) => Observed<T_3>;
createCustomComputed: <T_4>(inert: InertControl<T_4>, getCalculate: () => () => T_4, lifeCycle?: LifeCycle) => Computed<T_4>;
createObserved: <T_5>(value: T_5) => Observed<T_5>;
createEmptyObserved: () => Observed<void>;
createObserved: <T_5>(value: T_5) => Observed<T_5>;
createComputed: <T_6>(calculate: () => T_6) => Computed<T_6>;
createEffect: CreateEffect;
stopAllEffects: () => void;
};

@@ -47,3 +47,5 @@ "use strict";

exports.createDefaultCalculateControl = createDefaultCalculateControl;
const createNodesApi = (configuration, dependenciesManager, updateManager) => {
const createNodesApi = (dependenciesManager, updateManager) => {
const computedStopEffectMap = new WeakMap();
const effectComputedRefs = new Set();
const set = (node, newValue) => {

@@ -58,6 +60,7 @@ updateManager.set(node, newValue);

};
const createCustomObserved = inert => {
const createCustomObserved = (inert, lifeCycle) => {
const observed = {
derived: new Set(),
inert
inert,
lifeCycle
};

@@ -67,3 +70,3 @@ observedSet.add(observed);

};
const createCustomComputed = (inert, getCalculate) => {
const createCustomComputed = (inert, getCalculate, lifeCycle) => {
const computed = {

@@ -73,3 +76,4 @@ getCalculate,

derived: new Set(),
inert
inert,
lifeCycle
};

@@ -83,8 +87,8 @@ computedSet.add(computed);

};
const createEmptyObserved = () => {
return createCustomObserved(emptyInertControl);
};
const createComputed = calculate => {
return createCustomComputed(createDefaultInertControl(null), createDefaultCalculateControl(calculate));
};
const createEmptyObserved = () => {
return createCustomObserved(emptyInertControl);
};
const createEffect = (calculate, perform) => {

@@ -99,2 +103,4 @@ const effectId = Symbol();

});
const effectComputedRef = new WeakRef(computed);
effectComputedRefs.add(effectComputedRef);
isInitial = false;

@@ -104,7 +110,25 @@ if (!isEffectScheduled) {

}
return () => {
let isStopped = false;
const stopEffect = () => {
if (isStopped) {
return;
}
isStopped = true;
dependenciesManager.disableComputed(computed);
updateManager.cancelEffect(effectId);
effectComputedRefs.delete(effectComputedRef);
computedStopEffectMap.delete(computed);
};
computedStopEffectMap.set(computed, stopEffect);
return stopEffect;
};
const stopAllEffects = () => {
for (const effectComputedRef of effectComputedRefs) {
const effectComputed = effectComputedRef.deref();
const stopEffect = !effectComputed ? undefined : computedStopEffectMap.get(effectComputed);
if (stopEffect) {
stopEffect();
}
}
};
return {

@@ -116,6 +140,7 @@ set,

createCustomComputed,
createObserved,
createEmptyObserved,
createObserved,
createComputed,
createEffect
createEffect,
stopAllEffects
};

@@ -122,0 +147,0 @@ };

{
"name": "fluidstate",
"version": "0.0.12",
"version": "0.0.13",
"description": "Library for fine-grained reactivity state management",

@@ -5,0 +5,0 @@ "repository": "https://gitlab.com/fluidstate/fluidstate",

import { Api } from "./api";
import { Observed, ProxyApi } from "./types";
type Reactive = {
length: WeakRef<Observed<void>> | undefined;
items: Array<WeakRef<Observed<void>> | undefined>;
keys: WeakRef<Observed<void>> | undefined;
length?: Observed<void>;
items: Array<Observed<void> | undefined>;
keys?: Observed<void>;
};
type MarkedForDeletion = {
length: boolean;
items: Set<number>;
keys: boolean;
};
type Context = {

@@ -12,7 +17,5 @@ api: Api;

reactive: Reactive;
markedForDeletion: MarkedForDeletion;
getProxy: () => Array<unknown>;
};
declare const cleanupReactiveItems: (reactive: Reactive) => void;
declare const cleanupReactiveLength: (reactive: Reactive) => void;
declare const cleanupReactiveKeys: (reactive: Reactive) => void;
/**

@@ -23,5 +26,2 @@ * For internal tests only

context?: Context;
cleanupReactiveItems?: typeof cleanupReactiveItems;
cleanupReactiveLength?: typeof cleanupReactiveLength;
cleanupReactiveKeys?: typeof cleanupReactiveKeys;
};

@@ -28,0 +28,0 @@ export declare const createReactiveArray: <T extends unknown[]>(api: Api, proxyApi: ProxyApi, inertArr: T) => T;

@@ -7,54 +7,99 @@ "use strict";

exports.testData = exports.observeReactiveArray = exports.createReactiveArray = void 0;
var _reactiveUtils = require("./reactive-utils");
const elementArrayMap = new WeakMap();
const cleanupReactiveItems = reactive => {
let index = reactive.items.length - 1;
var _nodes = require("./nodes");
var _reactiveCleanupUtils = require("./reactive-cleanup-utils");
const scheduleContextCleanup = (0, _reactiveCleanupUtils.debounceCleanup)(context => {
if (context.markedForDeletion.length) {
delete context.reactive.length;
context.markedForDeletion.length = false;
}
if (context.markedForDeletion.keys) {
delete context.reactive.keys;
context.markedForDeletion.keys = false;
}
for (const index of context.markedForDeletion.items) {
context.reactive.items[index] = undefined;
}
context.markedForDeletion.items.clear();
let index = context.reactive.items.length - 1;
for (; index >= 0; index--) {
if (reactive.items[index]?.deref()) {
if (context.reactive.items[index]) {
break;
}
}
reactive.items.splice(index + 1);
context.reactive.items.splice(index + 1);
});
const createItemLifeCycle = (context, p) => {
const markForDeletion = () => {
context.markedForDeletion.items.add(p);
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.items.delete(p);
} else {
markForDeletion();
}
}
};
};
const cleanupReactiveLength = reactive => {
if (!reactive.length?.deref()) {
reactive.length = undefined;
}
const createKeysLifeCycle = context => {
const markForDeletion = () => {
context.markedForDeletion.keys = true;
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.keys = false;
} else {
markForDeletion();
}
}
};
};
const cleanupReactiveKeys = reactive => {
if (!reactive.keys?.deref()) {
reactive.keys = undefined;
}
const createLengthLifeCycle = context => {
const markForDeletion = () => {
context.markedForDeletion.length = true;
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.length = false;
} else {
markForDeletion();
}
}
};
};
const reactiveItemsCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveItems));
const reactiveLengthCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveLength));
const reactiveKeysCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveKeys));
const readItem = (context, p) => {
let observed = context.reactive.items[p]?.deref();
let observed = context.reactive.items[p];
if (!observed) {
observed = context.api.createEmptyObserved();
elementArrayMap.set(observed, context.getProxy());
reactiveItemsCleanupRegistry.register(observed, context.reactive);
context.reactive.items[p] = new WeakRef(observed);
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createItemLifeCycle(context, p));
context.reactive.items[p] = observed;
}
context.api.get(observed);
};
const notifyItem = (context, p) => {
const observed = context.reactive.items[p]?.deref();
if (observed) {
context.api.notify(observed);
const readLength = context => {
let observed = context.reactive.length;
if (!observed) {
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createLengthLifeCycle(context));
context.reactive.length = observed;
}
context.api.get(observed);
};
const readLength = context => {
let observed = context.reactive.length?.deref();
const readKeys = context => {
let observed = context.reactive.keys;
if (!observed) {
observed = context.api.createEmptyObserved();
elementArrayMap.set(observed, context.getProxy());
reactiveLengthCleanupRegistry.register(observed, context.reactive);
context.reactive.length = new WeakRef(observed);
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createKeysLifeCycle(context));
context.reactive.keys = observed;
}
context.api.get(observed);
};
const notifyLength = context => {
const observed = context.reactive.length?.deref();
const notifyItem = (context, p) => {
const observed = context.reactive.items[p];
if (observed) {

@@ -64,14 +109,10 @@ context.api.notify(observed);

};
const readKeys = context => {
let observed = context.reactive.keys?.deref();
if (!observed) {
observed = context.api.createEmptyObserved();
elementArrayMap.set(observed, context.getProxy());
reactiveKeysCleanupRegistry.register(observed, context.reactive);
context.reactive.keys = new WeakRef(observed);
const notifyLength = context => {
const observed = context.reactive.length;
if (observed) {
context.api.notify(observed);
}
context.api.get(observed);
};
const notifyKeys = context => {
const observed = context.reactive.keys?.deref();
const observed = context.reactive.keys;
if (observed) {

@@ -162,6 +203,9 @@ context.api.notify(observed);

reactive: {
length: undefined,
items: Array(inertArr.length),
keys: undefined
items: Array(inertArr.length)
},
markedForDeletion: {
length: false,
items: new Set(),
keys: false
},
getProxy: () => proxy

@@ -174,5 +218,2 @@ };

testData.context = context;
testData.cleanupReactiveItems = cleanupReactiveItems;
testData.cleanupReactiveLength = cleanupReactiveLength;
testData.cleanupReactiveKeys = cleanupReactiveKeys;
}

@@ -179,0 +220,0 @@ return proxy;

import { Api } from "./api";
import { Observed, ProxyApi } from "./types";
type Reactive = {
keys: Map<unknown, WeakRef<Observed<void>>>;
values: Map<unknown, WeakRef<Observed<void>>>;
size: WeakRef<Observed<void>> | undefined;
keys: Map<unknown, Observed<void>>;
values: Map<unknown, Observed<void>>;
size?: Observed<void>;
};
type MarkedForDeletion = {
keys: Set<unknown>;
values: Set<unknown>;
size: boolean;
};
type Context = {

@@ -12,7 +17,5 @@ api: Api;

reactive: Reactive;
markedForDeletion: MarkedForDeletion;
getProxy: () => Map<unknown, unknown>;
};
declare const cleanupReactiveKeys: (reactive: Reactive) => void;
declare const cleanupReactiveValues: (reactive: Reactive) => void;
declare const cleanupReactiveSize: (reactive: Reactive) => void;
/**

@@ -23,5 +26,2 @@ * For internal tests only

context?: Context;
cleanupReactiveKeys?: typeof cleanupReactiveKeys;
cleanupReactiveSize?: typeof cleanupReactiveSize;
cleanupReactiveValues?: typeof cleanupReactiveValues;
};

@@ -28,0 +28,0 @@ export declare const createReactiveMap: <T extends Map<unknown, unknown>>(api: Api, proxyApi: ProxyApi, inertMap: T) => T;

@@ -7,44 +7,80 @@ "use strict";

exports.testData = exports.observeReactiveMap = exports.createReactiveMap = void 0;
var _reactiveUtils = require("./reactive-utils");
const elementMapMap = new WeakMap();
const cleanupReactiveKeys = reactive => {
for (let [key, ref] of reactive.keys) {
if (!ref.deref()) {
reactive.keys.delete(key);
var _nodes = require("./nodes");
var _reactiveCleanupUtils = require("./reactive-cleanup-utils");
const scheduleContextCleanup = (0, _reactiveCleanupUtils.debounceCleanup)(context => {
if (context.markedForDeletion.size) {
delete context.reactive.size;
context.markedForDeletion.size = false;
}
for (const key of context.markedForDeletion.keys) {
context.reactive.keys.delete(key);
}
for (const key of context.markedForDeletion.values) {
context.reactive.values.delete(key);
}
context.markedForDeletion.keys.clear();
context.markedForDeletion.values.clear();
});
const createKeysLifeCycle = (context, key) => {
const markForDeletion = () => {
context.markedForDeletion.keys.add(key);
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.keys.delete(key);
} else {
markForDeletion();
}
}
}
};
};
const cleanupReactiveValues = reactive => {
for (let [key, ref] of reactive.values) {
if (!ref.deref()) {
reactive.values.delete(key);
const createValuesLifeCycle = (context, key) => {
const markForDeletion = () => {
context.markedForDeletion.values.add(key);
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.values.delete(key);
} else {
markForDeletion();
}
}
}
};
};
const cleanupReactiveSize = reactive => {
if (!reactive.size?.deref()) {
reactive.size = undefined;
}
const createSizeLifeCycle = context => {
const markForDeletion = () => {
context.markedForDeletion.size = true;
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.size = false;
} else {
markForDeletion();
}
}
};
};
const reactiveKeysCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveKeys));
const reactiveValuesCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveValues));
const reactiveSizeCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveSize));
const readKey = (context, key) => {
const notifyKey = (context, key) => {
if (!context) {
return;
}
let observed = context.reactive.keys.get(key)?.deref();
if (!observed) {
observed = context.api.createEmptyObserved();
elementMapMap.set(observed, context.getProxy());
reactiveKeysCleanupRegistry.register(observed, context.reactive);
context.reactive.keys.set(key, new WeakRef(observed));
const observed = context.reactive.keys.get(key);
if (observed) {
context.api.notify(observed);
}
context.api.get(observed);
};
const notifyKey = (context, key) => {
const notifyValue = (context, key) => {
if (!context) {
return;
}
const observed = context.reactive.keys.get(key)?.deref();
const observed = context.reactive.values.get(key);
if (observed) {

@@ -54,45 +90,43 @@ context.api.notify(observed);

};
const readValue = (context, key) => {
const notifySize = context => {
if (!context) {
return;
}
let observed = context.reactive.values.get(key)?.deref();
if (!observed) {
observed = context.api.createEmptyObserved();
elementMapMap.set(observed, context.getProxy());
reactiveValuesCleanupRegistry.register(observed, context.reactive);
context.reactive.values.set(key, new WeakRef(observed));
const observed = context.reactive.size;
if (observed) {
context.api.notify(observed);
}
context.api.get(observed);
};
const notifyValue = (context, key) => {
const readKey = (context, key) => {
if (!context) {
return;
}
const observed = context.reactive.values.get(key)?.deref();
if (observed) {
context.api.notify(observed);
let observed = context.reactive.keys.get(key);
if (!observed) {
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createKeysLifeCycle(context, key));
context.reactive.keys.set(key, observed);
}
context.api.get(observed);
};
const readSize = context => {
const readValue = (context, key) => {
if (!context) {
return;
}
let observed = context.reactive.size?.deref();
let observed = context.reactive.values.get(key);
if (!observed) {
observed = context.api.createEmptyObserved();
elementMapMap.set(observed, context.getProxy());
reactiveSizeCleanupRegistry.register(observed, context.reactive);
context.reactive.size = new WeakRef(observed);
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createValuesLifeCycle(context, key));
context.reactive.values.set(key, observed);
}
context.api.get(observed);
};
const notifySize = context => {
const readSize = context => {
if (!context) {
return;
}
const observed = context.reactive.size?.deref();
if (observed) {
context.api.notify(observed);
let observed = context.reactive.size;
if (!observed) {
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createSizeLifeCycle(context));
context.reactive.size = observed;
}
context.api.get(observed);
};

@@ -244,5 +278,9 @@ const createReactiveMapProxyHandler = fullContext => ({

keys: new Map(),
values: new Map(),
size: undefined
values: new Map()
},
markedForDeletion: {
keys: new Set(),
values: new Set(),
size: false
},
getProxy: () => proxy

@@ -259,5 +297,2 @@ };

testData.context = context;
testData.cleanupReactiveKeys = cleanupReactiveKeys;
testData.cleanupReactiveSize = cleanupReactiveSize;
testData.cleanupReactiveValues = cleanupReactiveValues;
}

@@ -264,0 +299,0 @@ return proxy;

@@ -5,6 +5,10 @@ import { Api } from "./api";

values: {
[k: string | symbol | number]: WeakRef<Observed<void> | Computed<unknown>> | undefined;
[k: string | symbol | number]: Observed<void> | Computed<unknown>;
};
keys: WeakRef<Observed<void>> | undefined;
keys?: Observed<void>;
};
type MarkedForDeletion = {
values: Set<string | symbol | number>;
keys: boolean;
};
type Context = {

@@ -14,6 +18,5 @@ api: Api;

reactive: Reactive;
markedForDeletion: MarkedForDeletion;
getProxy: () => object;
};
declare const cleanupReactiveValues: (reactive: Reactive) => void;
declare const cleanupReactiveKeys: (reactive: Reactive) => void;
/**

@@ -24,4 +27,2 @@ * For internal tests only

context?: Context;
cleanupReactiveKeys?: typeof cleanupReactiveKeys;
cleanupReactiveValues?: typeof cleanupReactiveValues;
};

@@ -28,0 +29,0 @@ export declare const createReactiveObject: <T extends object>(api: Api, proxyApi: ProxyApi, inertObject: T) => T;

@@ -8,25 +8,52 @@ "use strict";

var _nodes = require("./nodes");
var _reactiveCleanupUtils = require("./reactive-cleanup-utils");
var _reactiveUtils = require("./reactive-utils");
const elementObjectMap = new WeakMap();
const cleanupReactiveValues = reactive => {
for (const key of Reflect.ownKeys(reactive.values)) {
if (!reactive.values[key]?.deref()) {
delete reactive.values[key];
}
const scheduleContextCleanup = (0, _reactiveCleanupUtils.debounceCleanup)(context => {
if (context.markedForDeletion.keys) {
delete context.reactive.keys;
context.markedForDeletion.keys = false;
}
};
const cleanupReactiveKeys = reactive => {
if (!reactive.keys?.deref()) {
reactive.keys = undefined;
for (const key of context.markedForDeletion.values) {
delete context.reactive.values[key];
}
context.markedForDeletion.values.clear();
});
const createValueLifeCycle = (context, p) => {
const markForDeletion = () => {
context.markedForDeletion.values.add(p);
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.values.delete(p);
} else {
markForDeletion();
}
}
};
};
const reactiveValuesCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveValues));
const reactiveKeysCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveKeys));
const readComputedValue = (proxy, context, p, computed) => {
let node = context.reactive.values[p]?.deref();
const createKeysLifeCycle = context => {
const markForDeletion = () => {
context.markedForDeletion.keys = true;
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.keys = false;
} else {
markForDeletion();
}
}
};
};
const readComputedValue = (context, p, computed) => {
let node = context.reactive.values[p];
if (!node || !(0, _nodes.isComputed)(node)) {
node = context.api.createComputed(computed.bind(proxy));
elementObjectMap.set(node, context.getProxy());
reactiveValuesCleanupRegistry.register(node, context.reactive);
context.reactive.values[p] = new WeakRef(node);
const proxy = context.getProxy();
node = context.api.createCustomComputed((0, _nodes.createDefaultInertControl)(null), (0, _nodes.createDefaultCalculateControl)(computed.bind(proxy)), createValueLifeCycle(context, p));
context.reactive.values[p] = node;
}

@@ -36,13 +63,19 @@ return context.api.get(node);

const readObservedValue = (context, p) => {
let node = context.reactive.values[p]?.deref();
let node = context.reactive.values[p];
if (!node || !(0, _nodes.isObserved)(node)) {
node = context.api.createEmptyObserved();
elementObjectMap.set(node, context.getProxy());
reactiveValuesCleanupRegistry.register(node, context.reactive);
context.reactive.values[p] = new WeakRef(node);
node = context.api.createCustomObserved(_nodes.emptyInertControl, createValueLifeCycle(context, p));
context.reactive.values[p] = node;
}
context.api.get(node);
};
const readKeys = context => {
let node = context.reactive.keys;
if (!node) {
node = context.api.createCustomObserved(_nodes.emptyInertControl, createKeysLifeCycle(context));
context.reactive.keys = node;
}
context.api.get(node);
};
const notifyValue = (context, p) => {
const node = context.reactive.values[p]?.deref();
const node = context.reactive.values[p];
if (node) {

@@ -52,14 +85,4 @@ context.api.notify(node);

};
const readKeys = context => {
let node = context.reactive.keys?.deref();
if (!node) {
node = context.api.createEmptyObserved();
elementObjectMap.set(node, context.getProxy());
reactiveKeysCleanupRegistry.register(node, context.reactive);
context.reactive.keys = new WeakRef(node);
}
context.api.get(node);
};
const notifyKeys = context => {
const observed = context.reactive.keys?.deref();
const observed = context.reactive.keys;
if (observed) {

@@ -85,4 +108,3 @@ context.api.notify(observed);

if (descriptor?.get) {
const proxy = context.proxyApi.getProxy(inertObject);
return context.proxyApi.createProxy(readComputedValue(proxy, context, p, descriptor.get));
return context.proxyApi.createProxy(readComputedValue(context, p, descriptor.get));
}

@@ -164,5 +186,8 @@ readObservedValue(context, p);

reactive: {
values: {},
keys: undefined
values: {}
},
markedForDeletion: {
values: new Set(),
keys: false
},
getProxy: () => proxy

@@ -175,4 +200,2 @@ };

testData.context = context;
testData.cleanupReactiveKeys = cleanupReactiveKeys;
testData.cleanupReactiveValues = cleanupReactiveValues;
}

@@ -179,0 +202,0 @@ return proxy;

import { Api } from "./api";
import { Observed, ProxyApi } from "./types";
type Reactive = {
items: Map<unknown, WeakRef<Observed<void>>>;
size: WeakRef<Observed<void>> | undefined;
items: Map<unknown, Observed<void>>;
size?: Observed<void>;
};
type MarkedForDeletion = {
items: Set<unknown>;
size: boolean;
};
type Context = {

@@ -11,6 +15,5 @@ api: Api;

reactive: Reactive;
markedForDeletion: MarkedForDeletion;
getProxy: () => Set<unknown>;
};
declare const cleanupReactiveItems: (reactive: Reactive) => void;
declare const cleanupReactiveSize: (reactive: Reactive) => void;
/**

@@ -21,4 +24,2 @@ * For internal tests only

context?: Context;
cleanupReactiveItems?: typeof cleanupReactiveItems;
cleanupReactiveSize?: typeof cleanupReactiveSize;
};

@@ -25,0 +26,0 @@ export declare const createReactiveSet: <T extends Set<unknown>>(api: Api, proxyApi: ProxyApi, inertSet: T) => T;

@@ -7,36 +7,60 @@ "use strict";

exports.testData = exports.observeReactiveSet = exports.createReactiveSet = void 0;
var _reactiveUtils = require("./reactive-utils");
const elementSetMap = new WeakMap();
const cleanupReactiveItems = reactive => {
for (let [key, ref] of reactive.items) {
if (!ref.deref()) {
reactive.items.delete(key);
}
var _nodes = require("./nodes");
var _reactiveCleanupUtils = require("./reactive-cleanup-utils");
const scheduleContextCleanup = (0, _reactiveCleanupUtils.debounceCleanup)(context => {
if (context.markedForDeletion.size) {
delete context.reactive.size;
context.markedForDeletion.size = false;
}
};
const cleanupReactiveSize = reactive => {
if (!reactive.size?.deref()) {
reactive.size = undefined;
for (const key of context.markedForDeletion.items) {
context.reactive.items.delete(key);
}
context.markedForDeletion.items.clear();
});
const createItemLifeCycle = (context, item) => {
const markForDeletion = () => {
context.markedForDeletion.items.add(item);
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.items.delete(item);
} else {
markForDeletion();
}
}
};
};
const reactiveItemsCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveItems));
const reactiveSizeCleanupRegistry = new FinalizationRegistry((0, _reactiveUtils.debouncePerObject)(_reactiveUtils.CLEANUP_DEBOUNCE_TIME_MS, cleanupReactiveSize));
const readItem = (context, item) => {
const createSizeLifeCycle = context => {
const markForDeletion = () => {
context.markedForDeletion.size = true;
scheduleContextCleanup(context);
};
markForDeletion();
return {
onDerivedChanged(node) {
if (node.derived.size > 0) {
context.markedForDeletion.size = false;
} else {
markForDeletion();
}
}
};
};
const notifyItem = (context, item) => {
if (!context) {
return;
}
let observed = context.reactive.items.get(item)?.deref();
if (!observed) {
observed = context.api.createEmptyObserved();
elementSetMap.set(observed, context.getProxy());
reactiveItemsCleanupRegistry.register(observed, context.reactive);
context.reactive.items.set(item, new WeakRef(observed));
const observed = context.reactive.items.get(item);
if (observed) {
context.api.notify(observed);
}
context.api.get(observed);
};
const notifyItem = (context, item) => {
const notifySize = context => {
if (!context) {
return;
}
const observed = context.reactive.items.get(item)?.deref();
const observed = context.reactive.size;
if (observed) {

@@ -46,23 +70,23 @@ context.api.notify(observed);

};
const readSize = context => {
const readItem = (context, item) => {
if (!context) {
return;
}
let observed = context.reactive.size?.deref();
let observed = context.reactive.items.get(item);
if (!observed) {
observed = context.api.createEmptyObserved();
elementSetMap.set(observed, context.getProxy());
reactiveSizeCleanupRegistry.register(observed, context.reactive);
context.reactive.size = new WeakRef(observed);
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createItemLifeCycle(context, item));
context.reactive.items.set(item, observed);
}
context.api.get(observed);
};
const notifySize = context => {
const readSize = context => {
if (!context) {
return;
}
const observed = context.reactive.size?.deref();
if (observed) {
context.api.notify(observed);
let observed = context.reactive.size;
if (!observed) {
observed = context.api.createCustomObserved(_nodes.emptyInertControl, createSizeLifeCycle(context));
context.reactive.size = observed;
}
context.api.get(observed);
};

@@ -180,5 +204,8 @@ const createReactiveSetProxyHandler = fullContext => ({

reactive: {
items: new Map(),
size: undefined
items: new Map()
},
markedForDeletion: {
items: new Set(),
size: false
},
getProxy: () => proxy

@@ -195,4 +222,2 @@ };

testData.context = context;
testData.cleanupReactiveItems = cleanupReactiveItems;
testData.cleanupReactiveSize = cleanupReactiveSize;
}

@@ -199,0 +224,0 @@ return proxy;

@@ -1,2 +0,1 @@

export declare const CLEANUP_DEBOUNCE_TIME_MS = 100;
export declare const isObject: <T>(value: T) => value is T & object;

@@ -11,2 +10,1 @@ export declare const getDescriptor: (inertObject: object, p: string | symbol | number) => {

export declare const getAllGetterKeys: (inertObject: object) => Set<string | symbol>;
export declare const debouncePerObject: <T extends object>(time: number, fn: (object: T) => void) => (object: T) => void;

@@ -6,5 +6,3 @@ "use strict";

});
exports.isObject = exports.getDescriptor = exports.getAllGetterKeys = exports.debouncePerObject = exports.CLEANUP_DEBOUNCE_TIME_MS = void 0;
const CLEANUP_DEBOUNCE_TIME_MS = 100;
exports.CLEANUP_DEBOUNCE_TIME_MS = CLEANUP_DEBOUNCE_TIME_MS;
exports.isObject = exports.getDescriptor = exports.getAllGetterKeys = void 0;
const isObject = value => {

@@ -45,13 +43,2 @@ return value && typeof value === "object";

exports.getAllGetterKeys = getAllGetterKeys;
const timeoutMap = new WeakMap();
const debouncePerObject = (time, fn) => {
return object => {
clearTimeout(timeoutMap.get(object));
timeoutMap.set(object, setTimeout(() => {
fn(object);
timeoutMap.delete(object);
}, time));
};
};
exports.debouncePerObject = debouncePerObject;
//# sourceMappingURL=reactive-utils.js.map

@@ -7,7 +7,6 @@ "use strict";

exports.createSingleUpdateManger = void 0;
var _utils = require("./utils");
const createSingleUpdateManger = (dependenciesManager, resolutionVisitor, scheduledNodes, modifiedNodes) => {
const update = () => {
for (const scheduledNode of scheduledNodes) {
for (const derivedItem of (0, _utils.getItemsOfWeakRefSet)(scheduledNode.derived)) {
for (const derivedItem of scheduledNode.derived) {
visitNode(derivedItem);

@@ -23,3 +22,3 @@ }

resolutionVisitor.pre(node);
for (const derivedItem of (0, _utils.getItemsOfWeakRefSet)(node.derived)) {
for (const derivedItem of node.derived) {
visitNode(derivedItem);

@@ -26,0 +25,0 @@ }

@@ -12,5 +12,9 @@ export type ProxyApi = {

};
export type LifeCycle = {
onDerivedChanged: (node: Node<unknown>) => void;
};
export type Node<T> = {
inert: InertControl<T>;
derived: Set<WeakRef<Computed<unknown>>>;
derived: Set<Computed<unknown>>;
lifeCycle?: LifeCycle;
};

@@ -25,3 +29,5 @@ export type Observed<T> = Node<T>;

cancelFunction: (scheduledId: any) => void;
reactiveCleanupDebounceTime: number;
};
export type CreateEffect = <ComputedValue, Result>(calculate: () => ComputedValue, perform: (computedValue: ComputedValue) => Result) => () => void;
export type EffectStop = () => void;
export type CreateEffect = <ComputedValue, Result>(calculate: () => ComputedValue, perform: (computedValue: ComputedValue) => Result) => EffectStop;

@@ -1,4 +0,3 @@

export declare function getItemsOfWeakRefSet<T extends object>(weakRefSet: Set<WeakRef<T>>): IterableIterator<T>;
export declare const lastArrayItem: <T>(array: T[]) => T;
export declare const addUniqueItemToWeakRefSet: <T extends object>(selfWeakRefMap: WeakMap<T, WeakRef<T>>, object: T, weakRefSet: Set<WeakRef<T>>) => void;
export declare const removeItemFromWeakRefSetIfExists: <T extends object>(selfWeakRefMap: WeakMap<T, WeakRef<T>>, object: T, weakRefSet: Set<WeakRef<T>>) => void;
export declare function getSetRemoved<T>(previousSet: Set<T>, newSet: Set<T>): Generator<T, void, unknown>;
export declare function getSetAdded<T>(previousSet: Set<T>, newSet: Set<T>): Generator<T, void, unknown>;
export declare const cloneSetToEmpty: <T>(fromSet: Set<T>, emptySet: Set<T>) => void;

@@ -6,42 +6,25 @@ "use strict";

});
exports.addUniqueItemToWeakRefSet = void 0;
exports.getItemsOfWeakRefSet = getItemsOfWeakRefSet;
exports.removeItemFromWeakRefSetIfExists = exports.lastArrayItem = void 0;
function* getItemsOfWeakRefSet(weakRefSet) {
for (const item of weakRefSet) {
const value = item.deref();
if (value === undefined) {
weakRefSet.delete(item);
} else {
yield value;
exports.cloneSetToEmpty = void 0;
exports.getSetAdded = getSetAdded;
exports.getSetRemoved = getSetRemoved;
function* getSetRemoved(previousSet, newSet) {
for (let previousElement of previousSet) {
if (!newSet.has(previousElement)) {
yield previousElement;
}
}
}
const lastArrayItem = array => {
return array[array.length - 1];
};
exports.lastArrayItem = lastArrayItem;
const addUniqueItemToWeakRefSet = (selfWeakRefMap, object, weakRefSet) => {
let weakRef = selfWeakRefMap.get(object);
if (!weakRef) {
weakRef = new WeakRef(object);
selfWeakRefMap.set(object, weakRef);
}
weakRefSet.add(weakRef);
};
exports.addUniqueItemToWeakRefSet = addUniqueItemToWeakRefSet;
const removeItemFromWeakRefSetIfExists = (selfWeakRefMap, object, weakRefSet) => {
let weakRef = selfWeakRefMap.get(object);
if (weakRef) {
weakRefSet.delete(weakRef);
} else {
// This should never happen, but we can fallback to this in case:
for (const item of weakRefSet) {
if (object === item.deref()) {
weakRefSet.delete(item);
}
function* getSetAdded(previousSet, newSet) {
for (let newElement of newSet) {
if (!previousSet.has(newElement)) {
yield newElement;
}
}
}
const cloneSetToEmpty = (fromSet, emptySet) => {
for (let fromElement of fromSet) {
emptySet.add(fromElement);
}
};
exports.removeItemFromWeakRefSetIfExists = removeItemFromWeakRefSetIfExists;
exports.cloneSetToEmpty = cloneSetToEmpty;
//# sourceMappingURL=utils.js.map

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc