···5858 */
5959let read_clock = 0;
60606161+/**
6262+ * increments the batch depth.
6363+ * when the depth is greater than 0, effects are not run immediately.
6464+ */
6165function start_batch(): void {
6266 batch_depth++;
6367}
64686969+/**
7070+ * decrements the batch depth.
7171+ * when the depth reaches 0, it runs all batched effects.
7272+ */
6573function end_batch(): void {
6674 if (batch_depth > 1) {
6775 batch_depth--;
···105113 }
106114}
107115116116+/**
117117+ * checks if a computation is stale.
118118+ * @param target the computation to check
119119+ * @param flags the flags of the computation
120120+ * @returns `true` if the computation is stale, `false` otherwise
121121+ */
108122function is_stale(target: Computation, flags: number): boolean {
109123 const dependencies = target._dependencies;
110124···125139 return false;
126140}
127141142142+/**
143143+ * finalizes the dependencies of the currently evaluating computation.
144144+ * this is where we subscribe to new dependencies and unsubscribe from old ones.
145145+ */
128146function finalize_dependencies(): void {
129147 let dependencies = eval_listener!._dependencies;
130148131149 if (eval_untracked_sources) {
132132- // we have new dependencies, so let's unsubscribe from stale dependencies.
150150+ // new dependencies were added, so we need to unsubscribe from stale ones.
133151 prune_old_dependencies();
134152135153 if (eval_sources_index > 0) {
136136- // we have existing dependencies still depended on, so let's expand the
137137- // existing array to make room for our new dependencies.
154154+ // some of the old dependencies are still active.
155155+ // so we need to combine the old and new dependencies.
138156 const ilen = eval_untracked_sources.length;
139157140158 dependencies.length = eval_sources_index + ilen;
141159142142- // override anything after the pointer with our new dependencies, this is
143143- // fine since we're no longer subscribed to them.
160160+ // override anything after the pointer with our new dependencies.
161161+ // this is fine since we're no longer subscribed to them.
144162 for (let i = 0; i < ilen; i++) {
145163 dependencies[eval_sources_index + i] = eval_untracked_sources[i];
146164 }
147165 } else {
148148- // there isn't any existing dependencies, so just replace the existing
149149- // array with the new one.
166166+ // no old dependencies are active, so we can just replace the array.
150167 dependencies = eval_listener!._dependencies = eval_untracked_sources;
151168 }
152169153153- // now we subscribe to the new dependencies, but only if we're currently
154154- // configured as tracking.
170170+ // subscribe to the new dependencies, but only if we're tracking.
155171 if (eval_listener!._flags & Flags.TRACKING) {
156172 for (let i = eval_sources_index, ilen = dependencies.length; i < ilen; i++) {
157173 const dep = dependencies[i];
···160176 }
161177 }
162178 } else if (eval_sources_index < eval_listener!._dependencies.length) {
163163- // we don't have new dependencies, but the index pointer isn't pointing to
164164- // the end of the array, so we need to clean up the rest.
179179+ // no new dependencies were added, but we need to remove the stale ones.
165180 prune_old_dependencies();
166181 dependencies.length = eval_sources_index;
167182 }
168183}
169184185185+/**
186186+ * unsubscribes from stale dependencies.
187187+ */
170188function prune_old_dependencies(): void {
171189 const dependencies = eval_listener!._dependencies;
172190···176194 }
177195}
178196197197+/**
198198+ * runs the cleanup functions of an effect.
199199+ * @param effect the effect to cleanup
200200+ */
179201function cleanup_effect(effect: Effect<any>): void {
180202 const cleanups = effect._cleanups;
181203···208230 }
209231}
210232233233+/**
234234+ * disposes an effect.
235235+ * @param effect the effect to dispose
236236+ * @param run_cleanup whether to run the cleanup functions
237237+ */
211238function dispose_effect(effect: Effect<any>, run_cleanup: boolean): void {
212239 const dependencies = effect._dependencies;
213240···297324 * retrieves the value of the signal and creates a dependency if inside a computation.
298325 */
299326 get value(): T {
300300- // check if we're running under a context
327327+ // if we're in a computation, we need to track this signal as a dependency.
301328 if (eval_listener !== undefined && eval_listener._context_epoch !== this._access_epoch) {
302302- // store the read epoch, we don't need to recheck the dependencies of
303303- // this effect.
329329+ // we've already seen this signal, so we don't need to track it again.
304330 this._access_epoch = eval_listener._context_epoch;
305331306306- // dependency tracking is simple: does the index pointer point to us?
307307- //
308308- // - if so, then we're already depended on and we can increment the
309309- // pointer for the next signal.
310310- //
311311- // - if not, then we need to create a new dependency array and stop
312312- // incrementing the pointer, now that pointer acts as a dividing line
313313- // between signals that are still being depended, and are no longer
314314- // depended upon. the new dependencies can be concatenated afterwards.
315315-332332+ // if the pointer is pointing to us, we're already a dependency.
333333+ // otherwise, we need to add ourselves to the new dependencies.
316334 if (eval_untracked_sources !== undefined) {
317335 eval_untracked_sources.push(this);
318336 } else if (eval_listener._dependencies[eval_sources_index] === this) {
+15
store.ts
···3030const get_descriptor = /*#__PURE__*/ Object.getOwnPropertyDescriptor;
3131const is_extensible = /*#__PURE__*/ Object.isExtensible;
32323333+/**
3434+ * the proxy handler for reactive objects.
3535+ */
3336const proxy_handler: ProxyHandler<any> = {
3437 get(target, prop, receiver) {
3538 if (prop === RAW_SYMBOL) {
···4043 let metadata: ObjectMetadata = target[METADATA_SYMBOL];
4144 let s = metadata._values[prop];
42454646+ // if we're in a computation and the property is not yet tracked,
4747+ // we need to create a new signal for it.
4348 if (s === undefined && eval_listener && (!(prop in target) || get_descriptor(target, prop)?.writable)) {
4449 s = metadata._values[prop] = signal(target[prop]);
4550 }
···180185 },
181186};
182187188188+/**
189189+ * checks if an object can be wrapped in a proxy.
190190+ * @param obj the object to check
191191+ * @returns `true` if the object is wrappable, `false` otherwise
192192+ */
183193function is_wrappable(obj: any): boolean {
184194 const proto = get_prototype_of(obj);
185195 return (proto === null || proto === object_proto || proto === array_proto) && is_extensible(obj);
186196}
187197198198+/**
199199+ * initializes the metadata for a reactive object.
200200+ * @param value the object to initialize
201201+ * @returns the metadata object
202202+ */
188203function initialize(value: any): ObjectMetadata {
189204 return {
190205 _is_array: get_prototype_of(value) === array_proto,