@but212/atom-effect 0.30.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -11
- package/dist/atom-effect.min.js +1 -1
- package/dist/atom-effect.min.js.map +1 -1
- package/dist/constants.d.ts +157 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/core/atom.d.ts +19 -0
- package/dist/core/atom.d.ts.map +1 -0
- package/dist/core/base.d.ts +136 -0
- package/dist/core/base.d.ts.map +1 -0
- package/dist/core/buffers.d.ts +113 -0
- package/dist/core/buffers.d.ts.map +1 -0
- package/dist/core/computed.d.ts +84 -0
- package/dist/core/computed.d.ts.map +1 -0
- package/dist/core/effect.d.ts +52 -0
- package/dist/core/effect.d.ts.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/lens.d.ts +102 -0
- package/dist/core/lens.d.ts.map +1 -0
- package/dist/core/scheduler.d.ts +145 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/tracking.d.ts +123 -0
- package/dist/core/tracking.d.ts.map +1 -0
- package/dist/errors.d.ts +163 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -510
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +1078 -913
- package/dist/index.mjs.map +1 -1
- package/dist/symbols.d.ts +30 -0
- package/dist/symbols.d.ts.map +1 -0
- package/dist/types.d.ts +259 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/debug.d.ts +20 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/type-guards.d.ts +81 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/package.json +15 -14
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compound bitmasks for multi-state validation and bulk resets.
|
|
3
|
+
*
|
|
4
|
+
* Optimization: Bulk Validation
|
|
5
|
+
* Using compound masks reduces the number of bitwise comparisons in hot paths
|
|
6
|
+
* (e.g., checking if a node is in any async state).
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare const STATE_MASKS: Readonly<{
|
|
11
|
+
/** Covers all asynchronous lifecycle states. */
|
|
12
|
+
ASYNC_STATE: number;
|
|
13
|
+
/** Covers all states indicating a requirement for re-computation. */
|
|
14
|
+
COMPUTED_DIRTY_MASK: number;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Asynchronous operation states for public API consumption.
|
|
18
|
+
*
|
|
19
|
+
* When to use:
|
|
20
|
+
* - To verify or branch logic based on the status of an asynchronous atom or computed node.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { AsyncState } from '@but212/atom-effect';
|
|
25
|
+
*
|
|
26
|
+
* if (userProfile.status === AsyncState.PENDING) {
|
|
27
|
+
* showSpinner();
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const AsyncState: Readonly<{
|
|
32
|
+
IDLE: string;
|
|
33
|
+
PENDING: string;
|
|
34
|
+
RESOLVED: string;
|
|
35
|
+
REJECTED: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Logic: Shared State Interface
|
|
39
|
+
* Defines the bitmask contract for Effect-type nodes.
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export declare const EFFECT_STATE_FLAGS: Readonly<{
|
|
43
|
+
DISPOSED: number;
|
|
44
|
+
EXECUTING: number;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Logic: Shared State Interface
|
|
48
|
+
* Defines the bitmask contract for Computed-type nodes.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare const COMPUTED_STATE_FLAGS: Readonly<{
|
|
52
|
+
DISPOSED: number;
|
|
53
|
+
IS_COMPUTED: number;
|
|
54
|
+
DIRTY: number;
|
|
55
|
+
IDLE: number;
|
|
56
|
+
PENDING: number;
|
|
57
|
+
RESOLVED: number;
|
|
58
|
+
REJECTED: number;
|
|
59
|
+
RECOMPUTING: number;
|
|
60
|
+
HAS_ERROR: number;
|
|
61
|
+
FORCE_COMPUTE: number;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Logic: Shared State Interface
|
|
65
|
+
* Defines the bitmask contract for Atom-type nodes.
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
export declare const ATOM_STATE_FLAGS: Readonly<{
|
|
69
|
+
DISPOSED: number;
|
|
70
|
+
SYNC: number;
|
|
71
|
+
NOTIFICATION_SCHEDULED: number;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Global configuration parameters for the Scheduler.
|
|
75
|
+
*
|
|
76
|
+
* Caution: Modification of these thresholds can lead to instability,
|
|
77
|
+
* memory leaks, or execution overflows in complex dependency graphs.
|
|
78
|
+
*/
|
|
79
|
+
export declare const SCHEDULER_CONFIG: Readonly<{
|
|
80
|
+
/**
|
|
81
|
+
* Reason: Prevents infinite loops or runaway effects from freezing the main thread.
|
|
82
|
+
*/
|
|
83
|
+
MAX_EXECUTIONS_PER_SECOND: number;
|
|
84
|
+
/**
|
|
85
|
+
* Reason: Detects and stops circular dependencies within a single microtask.
|
|
86
|
+
*/
|
|
87
|
+
MAX_EXECUTIONS_PER_EFFECT: number;
|
|
88
|
+
/**
|
|
89
|
+
* Reason: Limits the total workload per flush to maintain frame-rate stability.
|
|
90
|
+
*/
|
|
91
|
+
MAX_EXECUTIONS_PER_FLUSH: number;
|
|
92
|
+
/**
|
|
93
|
+
* Reason: Safety break for the drain-loop to prevent stack overflows or infinite flushing.
|
|
94
|
+
*/
|
|
95
|
+
MAX_FLUSH_ITERATIONS: number;
|
|
96
|
+
/**
|
|
97
|
+
* Optimization: Batching
|
|
98
|
+
* Ensures a minimum number of iterations are processed to allow for nested batched updates.
|
|
99
|
+
*/
|
|
100
|
+
MIN_FLUSH_ITERATIONS: number;
|
|
101
|
+
/**
|
|
102
|
+
* Optimization: Memory Pressure
|
|
103
|
+
* Threshold for shrinking the internal batch queue to release memory back to the heap.
|
|
104
|
+
*/
|
|
105
|
+
BATCH_QUEUE_SHRINK_THRESHOLD: number;
|
|
106
|
+
}>;
|
|
107
|
+
/**
|
|
108
|
+
* Optimization: V8 SMI (Small Integer) Limit
|
|
109
|
+
*
|
|
110
|
+
* Values within this range (up to 30-bit signed) are stored directly in CPU registers
|
|
111
|
+
* by V8, bypassing heap allocation and boxing overhead.
|
|
112
|
+
*
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
export declare const SMI_MAX = 1073741823;
|
|
116
|
+
/**
|
|
117
|
+
* Thresholds for development-time diagnostics.
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
export declare const DEBUG_CONFIG: Readonly<{
|
|
121
|
+
/** Enables console warnings when potential infinite loops are detected. */
|
|
122
|
+
WARN_INFINITE_LOOP: true;
|
|
123
|
+
/** The time window (ms) for monitoring update frequency. */
|
|
124
|
+
EFFECT_FREQUENCY_WINDOW: number;
|
|
125
|
+
/** The update count limit before triggering a loop warning. */
|
|
126
|
+
LOOP_THRESHOLD: number;
|
|
127
|
+
}>;
|
|
128
|
+
/**
|
|
129
|
+
* Sentinel values for epoch-based staleness tracking.
|
|
130
|
+
*
|
|
131
|
+
* Logic: Drift Detection
|
|
132
|
+
* Epochs are used to determine if a dependency has changed since the last
|
|
133
|
+
* computation without needing deep comparison.
|
|
134
|
+
*
|
|
135
|
+
* @internal
|
|
136
|
+
*/
|
|
137
|
+
export declare const EPOCH_CONSTANTS: Readonly<{
|
|
138
|
+
/** Initial state indicating no computation has occurred. */
|
|
139
|
+
UNINITIALIZED: -1;
|
|
140
|
+
/** Reset floor for epoch counters to avoid 0/falsy confusion. */
|
|
141
|
+
MIN: 1;
|
|
142
|
+
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Indicates if the library is running in a development environment.
|
|
145
|
+
* When true, additional validation, diagnostic warnings, and loop protections are active.
|
|
146
|
+
*/
|
|
147
|
+
export declare const IS_DEV: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Optimization: Shared Immutable Empty State
|
|
150
|
+
*
|
|
151
|
+
* Constraint: Must remain immutable to prevent memory leaks and unexpected
|
|
152
|
+
* side-effects in subscriber logic that expects an array structure.
|
|
153
|
+
*
|
|
154
|
+
* @internal
|
|
155
|
+
*/
|
|
156
|
+
export declare const EMPTY_ERROR_ARRAY: readonly Error[];
|
|
157
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AA+CA;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;IACtB,gDAAgD;;IAEhD,qEAAqE;;EAErE,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU;;;;;EAKY,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;EAG7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;EAW/B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;EAI3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;;IAEH;;OAEG;;IAGH;;OAEG;;IAEH;;OAEG;;IAEH;;;OAGG;;IAGH;;;OAGG;;EAEuB,CAAC;AAE7B;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,aAAa,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB,2EAA2E;;IAE3E,4DAA4D;;IAE5D,+DAA+D;;EAEpB,CAAC;AAE9C;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B,4DAA4D;;IAE5D,iEAAiE;;EAEjE,CAAC;AAyCH;;;GAGG;AACH,eAAO,MAAM,MAAM,SACgE,CAAC;AAIpF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,KAAK,EAAsB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AtomOptions, WritableAtom } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a reactive atom holding mutable state.
|
|
4
|
+
*
|
|
5
|
+
* When to use:
|
|
6
|
+
* - As a primary source of truth for local or global state.
|
|
7
|
+
* - When state needs to be updated manually via `.value = ...`.
|
|
8
|
+
*
|
|
9
|
+
* @param initialValue - The starting value.
|
|
10
|
+
* @param options - Configuration for custom equality or synchronous delivery.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const count = atom(0);
|
|
15
|
+
* count.value++; // Triggers downstream updates
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function atom<T>(initialValue: T, options?: AtomOptions<T>): WritableAtom<T>;
|
|
19
|
+
//# sourceMappingURL=atom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atom.d.ts","sourceRoot":"","sources":["../../src/core/atom.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAiJzD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,GAAE,WAAW,CAAC,CAAC,CAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAEtF"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { SlotBuffer } from '@but212/atom-effect-utils';
|
|
2
|
+
import { DependencyId, Subscriber } from '../types';
|
|
3
|
+
import { DepBufferState } from './buffers';
|
|
4
|
+
import { Subscription } from './tracking';
|
|
5
|
+
/**
|
|
6
|
+
* A unified base class for all reactive primitives, including Atoms, Computeds, and Effects.
|
|
7
|
+
*
|
|
8
|
+
* When to use:
|
|
9
|
+
* - As an internal base for implementing new reactive primitives.
|
|
10
|
+
* - When a custom primitive requires integration with the core dependency graph.
|
|
11
|
+
*
|
|
12
|
+
* Optimization:
|
|
13
|
+
* Designed with a fixed field layout to maintain Hidden Class Monomorphism in V8.
|
|
14
|
+
* Avoid adding dynamic properties to instances to prevent de-optimization.
|
|
15
|
+
*
|
|
16
|
+
* @template T - The type of value produced by the node, used for subscriber notifications.
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class ReactiveNode<T> {
|
|
19
|
+
/**
|
|
20
|
+
* Internal bitfield representing the current state (Dirty, Computed, Disposed).
|
|
21
|
+
* Logic: Direct bitwise operations are used for high-frequency state checks.
|
|
22
|
+
*/
|
|
23
|
+
flags: number;
|
|
24
|
+
/**
|
|
25
|
+
* A monotonically increasing counter representing the version of the node's value.
|
|
26
|
+
* Logic: Allows consumers to quickly verify if their cached values are stale.
|
|
27
|
+
*/
|
|
28
|
+
version: number;
|
|
29
|
+
/**
|
|
30
|
+
* The epoch ID of the last time this node was visited during a dependency walk.
|
|
31
|
+
* Logic: Prevents redundant visits and infinite loops during graph traversal.
|
|
32
|
+
*/
|
|
33
|
+
_lastSeenEpoch: number;
|
|
34
|
+
/**
|
|
35
|
+
* A tag used by the scheduler to deduplicate execution within a single flush cycle.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
_nextEpoch: number | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Unique identifier used for debugging and graph traversal.
|
|
41
|
+
* Optimization: Uses SMI (Small Integer) range for memory efficiency and faster comparisons.
|
|
42
|
+
*/
|
|
43
|
+
readonly id: DependencyId;
|
|
44
|
+
/**
|
|
45
|
+
* Buffered storage for active subscribers.
|
|
46
|
+
* Logic: Uses `SlotBuffer` to support O(1) removal and deferred structural updates.
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
_slots: SlotBuffer<Subscription<T>> | null;
|
|
50
|
+
/**
|
|
51
|
+
* Buffered storage for captured dependencies.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
_deps: DepBufferState | null;
|
|
55
|
+
constructor();
|
|
56
|
+
/**
|
|
57
|
+
* Indicates whether the node has been explicitly disposed.
|
|
58
|
+
*/
|
|
59
|
+
get isDisposed(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Indicates whether the node is a computed atom.
|
|
62
|
+
*/
|
|
63
|
+
get isComputed(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Indicates whether the node is currently notifying subscribers.
|
|
66
|
+
*/
|
|
67
|
+
get isNotifying(): boolean;
|
|
68
|
+
private _hasFlag;
|
|
69
|
+
/**
|
|
70
|
+
* Indicates whether the node or its dependency sub-graph is currently in an error state.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
get hasError(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Registers a subscriber to be notified when the node's value changes.
|
|
76
|
+
*
|
|
77
|
+
* When to use:
|
|
78
|
+
* - To observe value changes manually outside of reactive contexts (e.g., in UI adapters).
|
|
79
|
+
*
|
|
80
|
+
* @param listener - A callback function or a Subscriber object.
|
|
81
|
+
* @returns A cleanup function to terminate the subscription.
|
|
82
|
+
* @throws {AtomError} If the provided listener is not a function or a valid Subscriber.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const unsub = node.subscribe((next, prev) => {
|
|
87
|
+
* console.log(`Value changed from ${prev} to ${next}`);
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // Later:
|
|
91
|
+
* unsub();
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
subscribe(listener: ((newValue?: T, oldValue?: T) => void) | Subscriber): () => void;
|
|
95
|
+
private _hasSubscription;
|
|
96
|
+
/**
|
|
97
|
+
* Internal removal of a subscription link.
|
|
98
|
+
*
|
|
99
|
+
* Caution: Compaction is deferred if a notification loop is currently active to
|
|
100
|
+
* prevent index shifting during iteration.
|
|
101
|
+
*/
|
|
102
|
+
protected _unsubscribe(link: Subscription<T>): void;
|
|
103
|
+
/**
|
|
104
|
+
* Returns the number of active subscribers for this node.
|
|
105
|
+
*
|
|
106
|
+
* When to use:
|
|
107
|
+
* - To monitor subscription health or detect leaks during development.
|
|
108
|
+
*/
|
|
109
|
+
subscriberCount(): number;
|
|
110
|
+
/**
|
|
111
|
+
* Dispatches notifications to all registered subscribers.
|
|
112
|
+
*
|
|
113
|
+
* Logic:
|
|
114
|
+
* Increments the `_notifying` guard to protect the subscriber buffer from
|
|
115
|
+
* structural changes during iteration. Error handling is encapsulated per subscriber
|
|
116
|
+
* to ensure a single failing listener does not terminate the entire notification cycle.
|
|
117
|
+
*/
|
|
118
|
+
protected _notifySubscribers(newValue: T | undefined, oldValue: T | undefined): void;
|
|
119
|
+
/**
|
|
120
|
+
* Determines if the node requires re-evaluation due to dependency changes.
|
|
121
|
+
* Logic: Checks the status of the cached dependency buffer.
|
|
122
|
+
*/
|
|
123
|
+
protected _isDirty(): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Performs a shallow validation of immediate dependencies.
|
|
126
|
+
* Logic: Used for fast path guards that must not trigger re-computation.
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
protected _isShallowDirty(): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Performs an exhaustive validation of the full dependency chain.
|
|
132
|
+
* Required for Computeds and Effects to handle deep dependency invalidation.
|
|
133
|
+
*/
|
|
134
|
+
protected abstract _deepDirtyCheck(): boolean;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/core/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGvD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAExD,OAAO,EAAE,KAAK,cAAc,EAAuC,MAAM,WAAW,CAAC;AACrF,OAAO,EAKL,KAAK,YAAY,EAElB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,8BAAsB,YAAY,CAAC,CAAC;IAClC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAE1B;;;;OAIG;IACH,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE3C;;;OAGG;IACH,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;;IAc7B;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,CAAC,QAAQ;IAIhB;;;OAGG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAMD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,IAAI;IA8BpF,OAAO,CAAC,gBAAgB;IAQxB;;;;;OAKG;IACH,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAQnD;;;;;OAKG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IAqBpF;;;OAGG;IACH,SAAS,CAAC,QAAQ,IAAI,OAAO;IAI7B;;;;OAIG;IACH,SAAS,CAAC,eAAe,IAAI,OAAO;IAIpC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,OAAO;CAC9C"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { SlotBuffer } from '@but212/atom-effect-utils';
|
|
2
|
+
import { Dependency } from '../types';
|
|
3
|
+
import { DependencyLink } from './tracking';
|
|
4
|
+
/** @internal */
|
|
5
|
+
export interface Indexer {
|
|
6
|
+
get(dep: Dependency): number | undefined;
|
|
7
|
+
set(dep: Dependency, index: number): void;
|
|
8
|
+
delete(dep: Dependency): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Logic: Subscription Reconciliation State
|
|
12
|
+
* Orchestrates the transition of dependencies between execution cycles.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export interface DepBufferState {
|
|
16
|
+
/**
|
|
17
|
+
* Ordered sequence of active subscriptions.
|
|
18
|
+
* Optimization: Uses SlotBuffer for contiguous memory and fast iteration.
|
|
19
|
+
*/
|
|
20
|
+
slots: SlotBuffer<DependencyLink>;
|
|
21
|
+
/**
|
|
22
|
+
* Optimization: O(1) Lookup
|
|
23
|
+
* Always present via Indexer interface to avoid branching.
|
|
24
|
+
* Switched to NullIndexer when inactive.
|
|
25
|
+
*/
|
|
26
|
+
map: Indexer;
|
|
27
|
+
/**
|
|
28
|
+
* Optimization: Skip Check
|
|
29
|
+
* When false, indicates no computed nodes are present, allowing the engine
|
|
30
|
+
* to skip recursive dirty validation.
|
|
31
|
+
*/
|
|
32
|
+
hasComputeds: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Factory for dependency buffers.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function createDepBuffer(): DepBufferState;
|
|
39
|
+
/**
|
|
40
|
+
* Resets diagnostic flags before a new tracking phase.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export declare function prepareTracking(state: DepBufferState): void;
|
|
44
|
+
/**
|
|
45
|
+
* Logic: Subscription Reuse (Claiming)
|
|
46
|
+
* Attempts to locate and move an existing subscription to the current
|
|
47
|
+
* tracking index.
|
|
48
|
+
*
|
|
49
|
+
* Why:
|
|
50
|
+
* Re-attaching listeners is expensive. Reusing the `unsub` handle from a
|
|
51
|
+
* previous run maintains the reactive connection without triggering
|
|
52
|
+
* subscriber count changes.
|
|
53
|
+
*
|
|
54
|
+
* Strategy:
|
|
55
|
+
* 1. Check if the current slot already holds the dependency (Fast Path).
|
|
56
|
+
* 2. Look ahead using the lookup map or linear search.
|
|
57
|
+
* 3. If found, swap the link to the front to preserve order for the next run.
|
|
58
|
+
*
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export declare function claimExisting(state: DepBufferState, dep: Dependency, trackIndex: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Logic: Displaced Occupant Preservation
|
|
64
|
+
* Inserts a new link at the current index. If an existing link is displaced,
|
|
65
|
+
* it is pushed to the tail so it can be reclaimed later in the same cycle.
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
export declare function insertNew(state: DepBufferState, trackIdx: number, link: DependencyLink): void;
|
|
69
|
+
/**
|
|
70
|
+
* Atomic mutation that synchronizes the O(1) lookup map with the slot buffer.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export declare function depBufferSetAt(state: DepBufferState, index: number, item: DependencyLink | null): void;
|
|
74
|
+
/**
|
|
75
|
+
* Atomic append operation that maintains the lookup map.
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
export declare function depBufferPush(state: DepBufferState, item: DependencyLink): number;
|
|
79
|
+
/**
|
|
80
|
+
* Logic: Dirty Propagation Check
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export declare function isBufferDirty(state: DepBufferState): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Logic: Push-Path Validation
|
|
86
|
+
* A non-recursive check used during the notification phase to avoid
|
|
87
|
+
* re-entrant computation cascades.
|
|
88
|
+
*
|
|
89
|
+
* It returns true if:
|
|
90
|
+
* 1. Any dependency version has already changed.
|
|
91
|
+
* 2. Any dependency is already marked as DIRTY.
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
export declare function isBufferShallowDirty(state: DepBufferState): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Logic: Post-Tracking Cleanup
|
|
98
|
+
* Removes and unsubscribes from all dependencies that were not reclaimed
|
|
99
|
+
* during the last tracking cycle.
|
|
100
|
+
*
|
|
101
|
+
* Constraint: Memory Integrity
|
|
102
|
+
* Failure to invoke `link.unsub()` results in "Ghost Executions" where
|
|
103
|
+
* disposed or inactive nodes continue to react to state changes.
|
|
104
|
+
*
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
export declare function depBufferTruncateFrom(state: DepBufferState, index: number): void;
|
|
108
|
+
/**
|
|
109
|
+
* Releases all subscriptions and resets the buffer to an empty state.
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
export declare function disposeAll(state: DepBufferState): void;
|
|
113
|
+
//# sourceMappingURL=buffers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffers.d.ts","sourceRoot":"","sources":["../../src/core/buffers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,gBAAgB;AAChB,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAUD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAClC;;;;OAIG;IACH,GAAG,EAAE,OAAO,CAAC;IACb;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,cAAc,CAMhD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAE3D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAwBjG;AAkBD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAO7F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,cAAc,GAAG,IAAI,GAC1B,IAAI,CASN;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,CAOjF;AA+BD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAc5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAcnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAuBhF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAGtD"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ComputedAtom, ComputedOptions, Dependency, MergedDependencyValue } from '../types';
|
|
2
|
+
import { DepBufferState } from './buffers';
|
|
3
|
+
/**
|
|
4
|
+
* Logic: Computed Result Resolution
|
|
5
|
+
* Determines the final value or error to return based on current flags and cache.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveComputedResult<T>(flags: number, value: T, error: Error | null, defaultValue: T): T;
|
|
9
|
+
/**
|
|
10
|
+
* Logic: Re-computation Heuristics
|
|
11
|
+
* Determines if a node requires re-evaluation based on its state and dependencies.
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare function shouldRecompute(flags: number, deps: DepBufferState): boolean;
|
|
15
|
+
/** @internal */
|
|
16
|
+
interface InternalComputedNode {
|
|
17
|
+
readonly id: number;
|
|
18
|
+
readonly flags: number;
|
|
19
|
+
readonly lastError: Error | null;
|
|
20
|
+
readonly _deps: DepBufferState | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Logic: Iterative Graph Traversal
|
|
24
|
+
* Crawls the dependency graph to collect errors.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectErrorsRecursive(startNode: InternalComputedNode, stopOnFirst: boolean): Error[];
|
|
28
|
+
/**
|
|
29
|
+
* Creates a reactive computation derived from other atoms or computed nodes.
|
|
30
|
+
*
|
|
31
|
+
* When to use:
|
|
32
|
+
* - To define values that automatically update when their dependencies change.
|
|
33
|
+
* - To optimize performance through caching of expensive calculations.
|
|
34
|
+
* - To transform or aggregate raw state for UI presentation.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const count = atom(1);
|
|
39
|
+
* const doubled = computed(() => count.value * 2);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function computed<T>(fn: () => T, options?: ComputedOptions<T>): ComputedAtom<T>;
|
|
43
|
+
/**
|
|
44
|
+
* Creates an asynchronous reactive computation.
|
|
45
|
+
*
|
|
46
|
+
* When to use:
|
|
47
|
+
* - For logic involving fetch, database queries, or long-running tasks.
|
|
48
|
+
*
|
|
49
|
+
* Attention:
|
|
50
|
+
* A `defaultValue` is mandatory for async computations to provide a valid
|
|
51
|
+
* state while the Promise is PENDING.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const user = computed(
|
|
56
|
+
* async () => fetchUser(userId.value),
|
|
57
|
+
* { defaultValue: null }
|
|
58
|
+
* );
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function computed<T>(fn: () => Promise<T>, options: ComputedOptions<T> & {
|
|
62
|
+
defaultValue: T;
|
|
63
|
+
}): ComputedAtom<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Combines multiple object-based atoms into a single computed atom with a flattened type.
|
|
66
|
+
*
|
|
67
|
+
* This utility merges the value types of all input atoms into a single
|
|
68
|
+
* unified object type using the {@link Merge} utility.
|
|
69
|
+
*
|
|
70
|
+
* @param atoms - A variadic list of atoms or computed nodes to merge.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const a = atom({ x: 1 });
|
|
75
|
+
* const b = atom({ y: 2 });
|
|
76
|
+
* const c = computed(() => ({ z: 3 }));
|
|
77
|
+
*
|
|
78
|
+
* const combined = mergeAtoms(a, b, c);
|
|
79
|
+
* // combined.value is { x: number; y: number; z: number }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare function mergeAtoms<T extends Dependency<unknown>[]>(...atoms: T): ComputedAtom<MergedDependencyValue<T>>;
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=computed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/core/computed.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,YAAY,EACZ,eAAe,EACf,UAAU,EACV,qBAAqB,EAEtB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAGL,KAAK,cAAc,EAMpB,MAAM,WAAW,CAAC;AA4CnB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,YAAY,EAAE,CAAC,GACd,CAAC,CAiBH;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAQ5E;AAED,gBAAgB;AAChB,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,oBAAoB,EAC/B,WAAW,EAAE,OAAO,GACnB,KAAK,EAAE,CA6BT;AA6YD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACxF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG;IAAE,YAAY,EAAE,CAAC,CAAA;CAAE,GAChD,YAAY,CAAC,CAAC,CAAC,CAAC;AAQnB;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,EACxD,GAAG,KAAK,EAAE,CAAC,GACV,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAExC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EffectFunction, EffectObject, EffectOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Internal state for tracking effect execution budgets.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export interface EffectBudgetState {
|
|
7
|
+
loopCount: number;
|
|
8
|
+
lastFlushEpoch: number;
|
|
9
|
+
windowCount: number;
|
|
10
|
+
windowStart: number;
|
|
11
|
+
totalExecutions: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Factory for effect budget state.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function createEffectBudgetState(): EffectBudgetState;
|
|
18
|
+
/**
|
|
19
|
+
* Logic: Effect Budget Validation
|
|
20
|
+
* Ensures an effect doesn't run too many times in a single flush cycle,
|
|
21
|
+
* preventing infinite loops.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateEffectBudget(state: EffectBudgetState, maxExecutionsPerFlush: number, currentFlushEpoch: number, incrementGlobalFlushCount: () => number, onAbort: (type: 'per-effect' | 'global') => never): void;
|
|
25
|
+
/**
|
|
26
|
+
* Logic: Frequency Limiter
|
|
27
|
+
* Throttles effects that fire too rapidly in development mode.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkEffectFrequencyLimit(state: EffectBudgetState, maxExecutions: number, onLimitExceeded: () => never): void;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a reactive side-effect.
|
|
33
|
+
*
|
|
34
|
+
* When to use:
|
|
35
|
+
* - To synchronize reactive state with the DOM or external APIs.
|
|
36
|
+
* - To perform logging or diagnostic tasks.
|
|
37
|
+
* - To manage timers or subscriptions that depend on atom values.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const count = atom(0);
|
|
42
|
+
* effect(() => {
|
|
43
|
+
* const el = document.getElementById('display')!;
|
|
44
|
+
* el.textContent = `Value: ${count.value}`;
|
|
45
|
+
*
|
|
46
|
+
* // Optional teardown
|
|
47
|
+
* return () => console.log('Cleaning up effect...');
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function effect(fn: EffectFunction, options?: EffectOptions): EffectObject;
|
|
52
|
+
//# sourceMappingURL=effect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/core/effect.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAc,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA2BvF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAQ3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,EACxB,qBAAqB,EAAE,MAAM,EAC7B,iBAAiB,EAAE,MAAM,EACzB,yBAAyB,EAAE,MAAM,MAAM,EACvC,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,KAAK,KAAK,GAChD,IAAI,CAeN;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,iBAAiB,EACxB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,KAAK,GAC3B,IAAI,CAcN;AAySD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,GAAE,aAAkB,GAAG,YAAY,CASpF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { atom } from './atom';
|
|
2
|
+
export { computed, mergeAtoms } from './computed';
|
|
3
|
+
export { effect } from './effect';
|
|
4
|
+
export type { Paths, PathValue } from './lens';
|
|
5
|
+
export { atomLens, composeLens, getPathValue, lensFor, mergeLenses, setDeepValue, } from './lens';
|
|
6
|
+
export { aeNextTick, batch, scheduler } from './scheduler';
|
|
7
|
+
export { untracked } from './tracking';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,OAAO,EACP,WAAW,EACX,YAAY,GACb,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|