@reckona/mreact-reactive-core 0.0.152 → 0.0.153

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 CHANGED
@@ -52,6 +52,8 @@ document.startViewTransition(() => {
52
52
 
53
53
  If you need the DOM committed synchronously before the current task continues, for example to measure layout right after an update, wrap the update in `flushSync` from the React DOM-compatible entrypoint (`react-dom` in mreact apps, `@reckona/mreact-dom` standalone), which drains pending reactive computations before returning. Updates deferred through `startTransition` or `useDeferredValue` run on a macrotask scheduler and are not guaranteed to land inside a view transition capture.
54
54
 
55
+ `batchAsync()` keeps effect flushing suspended for the full callback, including every awaited step, then releases the queued work once when the callback resolves or rejects. Use it for short transaction-style updates where intermediate effects would be misleading; avoid wrapping long I/O or user interaction flows because observers will not see effects until the batch finishes, even though direct `.get()` reads still see the latest cell values.
56
+
55
57
  ## Testing
56
58
 
57
59
  `@reckona/mreact-reactive-core/testing` exports `flushMicrotasks()` and
@@ -1 +1 @@
1
- {"version":3,"file":"cell.d.ts","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAUvC,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAuD3C"}
1
+ {"version":3,"file":"cell.d.ts","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAUvC,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAgD3C"}
package/dist/cell.js CHANGED
@@ -38,11 +38,6 @@ export function cell(initial) {
38
38
  });
39
39
  }
40
40
  }
41
- const singleSubscriber = source.singleSubscriber;
42
- if (singleSubscriber !== undefined &&
43
- (singleSubscriber.disposed || singleSubscriber.queued)) {
44
- return;
45
- }
46
41
  notifySubscribers(source);
47
42
  },
48
43
  };
package/dist/cell.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cell.js","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,sBAAsB,GAC1B,OAAO,0BAA0B,KAAK,WAAW;IACjD,0BAA0B,KAAK,KAAK,CAAC;AAEvC,MAAM,UAAU,IAAI,CAAI,OAAU;IAChC,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,MAAM,MAAM,GAAW;QACrB,WAAW,EAAE,IAAI,GAAG,EAAE;KACvB,CAAC;IAEF,OAAO;QACL,GAAG;YACD,WAAW,CAAC,MAAM,CAAC,CAAC;YACpB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,GAAG,CAAC,IAA0B;YAC5B,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAE,IAAuB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEvF,IAAI,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACjC,OAAO;YACT,CAAC;YAED,IAAI,sBAAsB,EAAE,CAAC;gBAC3B,OAAO,GAAG,QAAQ,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,MAAM,QAAQ,GACZ,UAKD,CAAC,gBAAgB,CAAC;gBACnB,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;gBAE5B,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;oBAC/B,OAAO,GAAG,QAAQ,CAAC;gBACrB,CAAC;qBAAM,CAAC;oBACN,MAAM,QAAQ,GAAG,OAAO,CAAC;oBACzB,OAAO,GAAG,QAAQ,CAAC;oBACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;wBAClB,OAAO,EAAE,+BAA+B;wBACxC,QAAQ;wBACR,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;wBACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,IAAI,EAAE,mBAAmB;wBACzB,KAAK,EAAE,QAAQ;qBAChB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACjD,IACE,gBAAgB,KAAK,SAAS;gBAC9B,CAAC,gBAAgB,CAAC,QAAQ,IAAI,gBAAgB,CAAC,MAAM,CAAC,EACtD,CAAC;gBACD,OAAO;YACT,CAAC;YACD,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Cell } from \"./types.js\";\nimport type { Source } from \"./state.js\";\nimport { notifySubscribers, trackSource } from \"./tracking.js\";\n\ndeclare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;\n\nconst clientDevtoolsDisabled =\n typeof __MREACT_CLIENT_DEVTOOLS__ !== \"undefined\" &&\n __MREACT_CLIENT_DEVTOOLS__ === false;\n\nexport function cell<T>(initial: T): Cell<T> {\n let current = initial;\n const source: Source = {\n subscribers: new Set(),\n };\n\n return {\n get(): T {\n trackSource(source);\n return current;\n },\n set(next: T | ((prev: T) => T)): void {\n const resolved = typeof next === \"function\" ? (next as (prev: T) => T)(current) : next;\n\n if (Object.is(current, resolved)) {\n return;\n }\n\n if (clientDevtoolsDisabled) {\n current = resolved;\n } else {\n const devtools = (\n globalThis as typeof globalThis & {\n __mreactDevtools?:\n | { emit?: (event: Record<string, unknown>) => void }\n | undefined;\n }\n ).__mreactDevtools;\n const emit = devtools?.emit;\n\n if (typeof emit !== \"function\") {\n current = resolved;\n } else {\n const previous = current;\n current = resolved;\n emit.call(devtools, {\n package: \"@reckona/mreact-reactive-core\",\n previous,\n subscribers: source.subscribers.size,\n timestamp: Date.now(),\n type: \"reactive:cell:set\",\n value: resolved,\n });\n }\n }\n const singleSubscriber = source.singleSubscriber;\n if (\n singleSubscriber !== undefined &&\n (singleSubscriber.disposed || singleSubscriber.queued)\n ) {\n return;\n }\n notifySubscribers(source);\n },\n };\n}\n"]}
1
+ {"version":3,"file":"cell.js","sourceRoot":"","sources":["../src/cell.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,sBAAsB,GAC1B,OAAO,0BAA0B,KAAK,WAAW;IACjD,0BAA0B,KAAK,KAAK,CAAC;AAEvC,MAAM,UAAU,IAAI,CAAI,OAAU;IAChC,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,MAAM,MAAM,GAAW;QACrB,WAAW,EAAE,IAAI,GAAG,EAAE;KACvB,CAAC;IAEF,OAAO;QACL,GAAG;YACD,WAAW,CAAC,MAAM,CAAC,CAAC;YACpB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,GAAG,CAAC,IAA0B;YAC5B,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAE,IAAuB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEvF,IAAI,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACjC,OAAO;YACT,CAAC;YAED,IAAI,sBAAsB,EAAE,CAAC;gBAC3B,OAAO,GAAG,QAAQ,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,MAAM,QAAQ,GACZ,UAKD,CAAC,gBAAgB,CAAC;gBACnB,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;gBAE5B,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;oBAC/B,OAAO,GAAG,QAAQ,CAAC;gBACrB,CAAC;qBAAM,CAAC;oBACN,MAAM,QAAQ,GAAG,OAAO,CAAC;oBACzB,OAAO,GAAG,QAAQ,CAAC;oBACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;wBAClB,OAAO,EAAE,+BAA+B;wBACxC,QAAQ;wBACR,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;wBACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,IAAI,EAAE,mBAAmB;wBACzB,KAAK,EAAE,QAAQ;qBAChB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Cell } from \"./types.js\";\nimport type { Source } from \"./state.js\";\nimport { notifySubscribers, trackSource } from \"./tracking.js\";\n\ndeclare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;\n\nconst clientDevtoolsDisabled =\n typeof __MREACT_CLIENT_DEVTOOLS__ !== \"undefined\" &&\n __MREACT_CLIENT_DEVTOOLS__ === false;\n\nexport function cell<T>(initial: T): Cell<T> {\n let current = initial;\n const source: Source = {\n subscribers: new Set(),\n };\n\n return {\n get(): T {\n trackSource(source);\n return current;\n },\n set(next: T | ((prev: T) => T)): void {\n const resolved = typeof next === \"function\" ? (next as (prev: T) => T)(current) : next;\n\n if (Object.is(current, resolved)) {\n return;\n }\n\n if (clientDevtoolsDisabled) {\n current = resolved;\n } else {\n const devtools = (\n globalThis as typeof globalThis & {\n __mreactDevtools?:\n | { emit?: (event: Record<string, unknown>) => void }\n | undefined;\n }\n ).__mreactDevtools;\n const emit = devtools?.emit;\n\n if (typeof emit !== \"function\") {\n current = resolved;\n } else {\n const previous = current;\n current = resolved;\n emit.call(devtools, {\n package: \"@reckona/mreact-reactive-core\",\n previous,\n subscribers: source.subscribers.size,\n timestamp: Date.now(),\n type: \"reactive:cell:set\",\n value: resolved,\n });\n }\n }\n notifySubscribers(source);\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACjD,YAAY,CAAC,CAAC,CAAC,CAuIjB"}
1
+ {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACjD,YAAY,CAAC,CAAC,CAAC,CA0IjB"}
package/dist/computed.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { schedulePendingFlush } from "./scheduler.js";
2
2
  import { runtimeState } from "./state.js";
3
- import { cleanupAddedDeps, cleanupDeps, cleanupUntrackedDeps, notifySubscribers, preserveIncrementalTracking, trackIncrementalSource, trackSource, } from "./tracking.js";
3
+ import { cleanupAddedDeps, cleanupDeps, cleanupUntrackedDeps, nextTrackingVersionFor, notifySubscribers, preserveIncrementalTracking, trackIncrementalSource, trackSource, } from "./tracking.js";
4
4
  export function computed(fn, options) {
5
5
  let hasValue = false;
6
6
  let value;
@@ -41,8 +41,11 @@ export function computed(fn, options) {
41
41
  return;
42
42
  }
43
43
  computation.disposed = true;
44
+ computation.queued = false;
45
+ runtimeState.pendingComputed.delete(computation);
44
46
  cleanupDeps(computation);
45
47
  source.subscribers.clear();
48
+ source.singleSubscriber = undefined;
46
49
  },
47
50
  };
48
51
  runtimeState.nextComputationId += 1;
@@ -74,7 +77,7 @@ export function computed(fn, options) {
74
77
  }
75
78
  const previousTracker = runtimeState.activeTracker;
76
79
  const previousDepsSize = computation.deps.size;
77
- const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
80
+ const nextTrackingVersion = nextTrackingVersionFor(computation);
78
81
  computation.trackingAddedDeps = [];
79
82
  computation.trackingCount = 0;
80
83
  computation.trackingVersion = nextTrackingVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"computed.js","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveComputation, Source } from \"./state.js\";\nimport { schedulePendingFlush } from \"./scheduler.js\";\nimport { runtimeState } from \"./state.js\";\nimport {\n cleanupAddedDeps,\n cleanupDeps,\n cleanupUntrackedDeps,\n notifySubscribers,\n preserveIncrementalTracking,\n trackIncrementalSource,\n trackSource,\n} from \"./tracking.js\";\nimport type { ReadonlyCell } from \"./types.js\";\n\nexport type ComputedEquality<T> = (previous: T, next: T) => boolean;\n\nexport interface ComputedOptions<T> {\n equals?: ComputedEquality<T> | undefined;\n}\n\nexport function computed<T>(\n fn: () => T,\n options?: ComputedOptions<T> | ComputedEquality<T>,\n): ReadonlyCell<T> {\n let hasValue = false;\n let value: T;\n let dirty = true;\n const equals = typeof options === \"function\" ? options : (options?.equals ?? Object.is);\n\n const source: Source = {\n subscribers: new Set(),\n };\n\n const computation: ReactiveComputation = {\n id: runtimeState.nextComputationId,\n deps: new Set(),\n disposed: false,\n queued: false,\n markDirty() {\n if (dirty) {\n if (source.subscribers.size === 0 || computation.queued) {\n return;\n }\n }\n\n dirty = true;\n\n if (source.subscribers.size > 0) {\n if (runtimeState.notificationDepth > 0) {\n computation.queued = true;\n runtimeState.pendingComputed.add(computation);\n return;\n }\n\n publishIfChanged();\n }\n },\n run() {\n publishIfChanged();\n },\n trackSource(source) {\n trackIncrementalSource(source, computation);\n },\n dispose() {\n if (computation.disposed) {\n return;\n }\n\n computation.disposed = true;\n cleanupDeps(computation);\n source.subscribers.clear();\n },\n };\n\n runtimeState.nextComputationId += 1;\n\n function publishIfChanged(): void {\n const previousHasValue = hasValue;\n const previousValue = value;\n\n try {\n const nextValue = recompute();\n\n if (!previousHasValue || !equals(previousValue, nextValue)) {\n notifySubscribers(source);\n }\n } catch {\n runtimeState.batchDepth += 1;\n\n try {\n notifySubscribers(source);\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n schedulePendingFlush();\n }\n }\n }\n }\n\n function recompute(): T {\n if (!dirty && hasValue) {\n return value;\n }\n\n const previousTracker = runtimeState.activeTracker;\n const previousDepsSize = computation.deps.size;\n const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;\n\n computation.trackingAddedDeps = [];\n computation.trackingCount = 0;\n computation.trackingVersion = nextTrackingVersion;\n runtimeState.activeTracker = computation;\n\n try {\n const nextValue = fn();\n\n const addedDeps = computation.trackingAddedDeps;\n const trackedCount = computation.trackingCount ?? 0;\n\n if (trackedCount !== previousDepsSize || (addedDeps?.length ?? 0) > 0) {\n cleanupUntrackedDeps(computation, nextTrackingVersion);\n }\n\n value = nextValue;\n hasValue = true;\n dirty = false;\n\n return value;\n } catch (error) {\n cleanupAddedDeps(computation);\n dirty = true;\n\n throw error;\n } finally {\n computation.trackingAddedDeps = undefined;\n computation.trackingCount = undefined;\n computation.trackingTouchedDeps = undefined;\n runtimeState.activeTracker = previousTracker;\n }\n }\n\n return {\n get(): T {\n trackSource(source);\n\n if (dirty) {\n const activeTracker = runtimeState.activeTracker;\n\n if (activeTracker !== null && activeTracker !== computation) {\n preserveIncrementalTracking(activeTracker);\n }\n }\n\n return recompute();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"computed.js","sourceRoot":"","sources":["../src/computed.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveComputation, Source } from \"./state.js\";\nimport { schedulePendingFlush } from \"./scheduler.js\";\nimport { runtimeState } from \"./state.js\";\nimport {\n cleanupAddedDeps,\n cleanupDeps,\n cleanupUntrackedDeps,\n nextTrackingVersionFor,\n notifySubscribers,\n preserveIncrementalTracking,\n trackIncrementalSource,\n trackSource,\n} from \"./tracking.js\";\nimport type { ReadonlyCell } from \"./types.js\";\n\nexport type ComputedEquality<T> = (previous: T, next: T) => boolean;\n\nexport interface ComputedOptions<T> {\n equals?: ComputedEquality<T> | undefined;\n}\n\nexport function computed<T>(\n fn: () => T,\n options?: ComputedOptions<T> | ComputedEquality<T>,\n): ReadonlyCell<T> {\n let hasValue = false;\n let value: T;\n let dirty = true;\n const equals = typeof options === \"function\" ? options : (options?.equals ?? Object.is);\n\n const source: Source = {\n subscribers: new Set(),\n };\n\n const computation: ReactiveComputation = {\n id: runtimeState.nextComputationId,\n deps: new Set(),\n disposed: false,\n queued: false,\n markDirty() {\n if (dirty) {\n if (source.subscribers.size === 0 || computation.queued) {\n return;\n }\n }\n\n dirty = true;\n\n if (source.subscribers.size > 0) {\n if (runtimeState.notificationDepth > 0) {\n computation.queued = true;\n runtimeState.pendingComputed.add(computation);\n return;\n }\n\n publishIfChanged();\n }\n },\n run() {\n publishIfChanged();\n },\n trackSource(source) {\n trackIncrementalSource(source, computation);\n },\n dispose() {\n if (computation.disposed) {\n return;\n }\n\n computation.disposed = true;\n computation.queued = false;\n runtimeState.pendingComputed.delete(computation);\n cleanupDeps(computation);\n source.subscribers.clear();\n source.singleSubscriber = undefined;\n },\n };\n\n runtimeState.nextComputationId += 1;\n\n function publishIfChanged(): void {\n const previousHasValue = hasValue;\n const previousValue = value;\n\n try {\n const nextValue = recompute();\n\n if (!previousHasValue || !equals(previousValue, nextValue)) {\n notifySubscribers(source);\n }\n } catch {\n runtimeState.batchDepth += 1;\n\n try {\n notifySubscribers(source);\n } finally {\n runtimeState.batchDepth -= 1;\n\n if (runtimeState.batchDepth === 0) {\n schedulePendingFlush();\n }\n }\n }\n }\n\n function recompute(): T {\n if (!dirty && hasValue) {\n return value;\n }\n\n const previousTracker = runtimeState.activeTracker;\n const previousDepsSize = computation.deps.size;\n const nextTrackingVersion = nextTrackingVersionFor(computation);\n\n computation.trackingAddedDeps = [];\n computation.trackingCount = 0;\n computation.trackingVersion = nextTrackingVersion;\n runtimeState.activeTracker = computation;\n\n try {\n const nextValue = fn();\n\n const addedDeps = computation.trackingAddedDeps;\n const trackedCount = computation.trackingCount ?? 0;\n\n if (trackedCount !== previousDepsSize || (addedDeps?.length ?? 0) > 0) {\n cleanupUntrackedDeps(computation, nextTrackingVersion);\n }\n\n value = nextValue;\n hasValue = true;\n dirty = false;\n\n return value;\n } catch (error) {\n cleanupAddedDeps(computation);\n dirty = true;\n\n throw error;\n } finally {\n computation.trackingAddedDeps = undefined;\n computation.trackingCount = undefined;\n computation.trackingTouchedDeps = undefined;\n runtimeState.activeTracker = previousTracker;\n }\n }\n\n return {\n get(): T {\n trackSource(source);\n\n if (dirty) {\n const activeTracker = runtimeState.activeTracker;\n\n if (activeTracker !== null && activeTracker !== computation) {\n preserveIncrementalTracking(activeTracker);\n }\n }\n\n return recompute();\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"AAgBA,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,CAuGhE"}
1
+ {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"AAiBA,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,CA2GhE"}
package/dist/effect.js CHANGED
@@ -2,7 +2,7 @@ import { queueComputation } from "./scheduler.js";
2
2
  import { currentReactiveDevtools } from "./devtools.js";
3
3
  import { registerCleanup } from "./cleanup-scope.js";
4
4
  import { runtimeState } from "./state.js";
5
- import { cleanupDeps, cleanupUntrackedDeps, trackIncrementalSource, } from "./tracking.js";
5
+ import { cleanupDeps, cleanupUntrackedDeps, nextTrackingVersionFor, trackIncrementalSource, } from "./tracking.js";
6
6
  const clientDevtoolsDisabled = typeof __MREACT_CLIENT_DEVTOOLS__ !== "undefined" &&
7
7
  __MREACT_CLIENT_DEVTOOLS__ === false;
8
8
  export function effect(fn) {
@@ -26,7 +26,7 @@ export function effect(fn) {
26
26
  cleanup = undefined;
27
27
  }
28
28
  const previousDepsSize = computation.deps.size;
29
- const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
29
+ const nextTrackingVersion = nextTrackingVersionFor(computation);
30
30
  computation.trackingAddedDeps = [];
31
31
  computation.trackingCount = 0;
32
32
  computation.trackingTouchedDeps = [];
@@ -72,6 +72,8 @@ export function effect(fn) {
72
72
  return;
73
73
  }
74
74
  computation.disposed = true;
75
+ computation.queued = false;
76
+ runtimeState.pendingComputed.delete(computation);
75
77
  cleanupDeps(computation);
76
78
  if (cleanup !== undefined) {
77
79
  const currentCleanup = cleanup;
@@ -86,6 +88,8 @@ export function effect(fn) {
86
88
  }
87
89
  catch (error) {
88
90
  computation.disposed = true;
91
+ computation.queued = false;
92
+ runtimeState.pendingComputed.delete(computation);
89
93
  cleanupDeps(computation);
90
94
  if (cleanup !== undefined) {
91
95
  const currentCleanup = cleanup;
@@ -1 +1 @@
1
- {"version":3,"file":"effect.js","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"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","sourcesContent":["import { queueComputation } from \"./scheduler.js\";\nimport { currentReactiveDevtools } from \"./devtools.js\";\nimport { registerCleanup } from \"./cleanup-scope.js\";\nimport { runtimeState, type ReactiveComputation } from \"./state.js\";\nimport {\n cleanupDeps,\n cleanupUntrackedDeps,\n trackIncrementalSource,\n} from \"./tracking.js\";\n\ndeclare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;\n\nconst clientDevtoolsDisabled =\n typeof __MREACT_CLIENT_DEVTOOLS__ !== \"undefined\" &&\n __MREACT_CLIENT_DEVTOOLS__ === false;\n\nexport function effect(fn: () => void | (() => void)): () => void {\n let cleanup: (() => void) | undefined;\n\n const computation: ReactiveComputation = {\n id: runtimeState.nextComputationId,\n deps: new Set(),\n disposed: false,\n queued: false,\n markDirty() {\n queueComputation(computation);\n },\n run() {\n if (computation.disposed) {\n return;\n }\n\n const previousTracker = runtimeState.activeTracker;\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n currentCleanup();\n cleanup = undefined;\n }\n\n const previousDepsSize = computation.deps.size;\n const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;\n\n computation.trackingAddedDeps = [];\n computation.trackingCount = 0;\n computation.trackingTouchedDeps = [];\n computation.trackingVersion = nextTrackingVersion;\n runtimeState.activeTracker = computation;\n\n if (clientDevtoolsDisabled) {\n try {\n const result = fn();\n cleanup = typeof result === \"function\" ? result : undefined;\n } finally {\n finishIncrementalTracking(computation, previousDepsSize, nextTrackingVersion);\n runtimeState.activeTracker = previousTracker;\n }\n return;\n }\n\n const devtools = currentReactiveDevtools();\n const emit = devtools?.emit;\n const startedAt = emit === undefined ? 0 : performanceNow();\n\n try {\n const result = fn();\n cleanup = typeof result === \"function\" ? result : undefined;\n } finally {\n finishIncrementalTracking(computation, previousDepsSize, nextTrackingVersion);\n runtimeState.activeTracker = previousTracker;\n if (typeof emit === \"function\") {\n emit.call(devtools, {\n durationMs: performanceNow() - startedAt,\n id: computation.id,\n package: \"@reckona/mreact-reactive-core\",\n timestamp: Date.now(),\n type: \"reactive:effect:run\",\n });\n }\n }\n },\n trackSource(source) {\n trackIncrementalSource(source, computation);\n },\n dispose() {\n if (computation.disposed) {\n return;\n }\n\n computation.disposed = true;\n cleanupDeps(computation);\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n cleanup = undefined;\n currentCleanup();\n }\n },\n };\n\n runtimeState.nextComputationId += 1;\n\n try {\n computation.run();\n } catch (error) {\n computation.disposed = true;\n cleanupDeps(computation);\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n cleanup = undefined;\n currentCleanup();\n }\n\n throw error;\n }\n\n registerCleanup(computation.dispose);\n return computation.dispose;\n}\n\nfunction finishIncrementalTracking(\n computation: ReactiveComputation,\n previousDepsSize: number,\n trackingVersion: number,\n): void {\n const addedDeps = computation.trackingAddedDeps;\n const trackedCount = computation.trackingCount ?? 0;\n\n if (trackedCount !== previousDepsSize || (addedDeps?.length ?? 0) > 0) {\n cleanupUntrackedDeps(computation, trackingVersion);\n }\n\n computation.trackingAddedDeps = undefined;\n computation.trackingCount = undefined;\n computation.trackingTouchedDeps = undefined;\n}\n\nfunction performanceNow(): number {\n return typeof performance === \"undefined\" ? Date.now() : performance.now();\n}\n"]}
1
+ {"version":3,"file":"effect.js","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"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","sourcesContent":["import { queueComputation } from \"./scheduler.js\";\nimport { currentReactiveDevtools } from \"./devtools.js\";\nimport { registerCleanup } from \"./cleanup-scope.js\";\nimport { runtimeState, type ReactiveComputation } from \"./state.js\";\nimport {\n cleanupDeps,\n cleanupUntrackedDeps,\n nextTrackingVersionFor,\n trackIncrementalSource,\n} from \"./tracking.js\";\n\ndeclare const __MREACT_CLIENT_DEVTOOLS__: boolean | undefined;\n\nconst clientDevtoolsDisabled =\n typeof __MREACT_CLIENT_DEVTOOLS__ !== \"undefined\" &&\n __MREACT_CLIENT_DEVTOOLS__ === false;\n\nexport function effect(fn: () => void | (() => void)): () => void {\n let cleanup: (() => void) | undefined;\n\n const computation: ReactiveComputation = {\n id: runtimeState.nextComputationId,\n deps: new Set(),\n disposed: false,\n queued: false,\n markDirty() {\n queueComputation(computation);\n },\n run() {\n if (computation.disposed) {\n return;\n }\n\n const previousTracker = runtimeState.activeTracker;\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n currentCleanup();\n cleanup = undefined;\n }\n\n const previousDepsSize = computation.deps.size;\n const nextTrackingVersion = nextTrackingVersionFor(computation);\n\n computation.trackingAddedDeps = [];\n computation.trackingCount = 0;\n computation.trackingTouchedDeps = [];\n computation.trackingVersion = nextTrackingVersion;\n runtimeState.activeTracker = computation;\n\n if (clientDevtoolsDisabled) {\n try {\n const result = fn();\n cleanup = typeof result === \"function\" ? result : undefined;\n } finally {\n finishIncrementalTracking(computation, previousDepsSize, nextTrackingVersion);\n runtimeState.activeTracker = previousTracker;\n }\n return;\n }\n\n const devtools = currentReactiveDevtools();\n const emit = devtools?.emit;\n const startedAt = emit === undefined ? 0 : performanceNow();\n\n try {\n const result = fn();\n cleanup = typeof result === \"function\" ? result : undefined;\n } finally {\n finishIncrementalTracking(computation, previousDepsSize, nextTrackingVersion);\n runtimeState.activeTracker = previousTracker;\n if (typeof emit === \"function\") {\n emit.call(devtools, {\n durationMs: performanceNow() - startedAt,\n id: computation.id,\n package: \"@reckona/mreact-reactive-core\",\n timestamp: Date.now(),\n type: \"reactive:effect:run\",\n });\n }\n }\n },\n trackSource(source) {\n trackIncrementalSource(source, computation);\n },\n dispose() {\n if (computation.disposed) {\n return;\n }\n\n computation.disposed = true;\n computation.queued = false;\n runtimeState.pendingComputed.delete(computation);\n cleanupDeps(computation);\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n cleanup = undefined;\n currentCleanup();\n }\n },\n };\n\n runtimeState.nextComputationId += 1;\n\n try {\n computation.run();\n } catch (error) {\n computation.disposed = true;\n computation.queued = false;\n runtimeState.pendingComputed.delete(computation);\n cleanupDeps(computation);\n\n if (cleanup !== undefined) {\n const currentCleanup = cleanup;\n cleanup = undefined;\n currentCleanup();\n }\n\n throw error;\n }\n\n registerCleanup(computation.dispose);\n return computation.dispose;\n}\n\nfunction finishIncrementalTracking(\n computation: ReactiveComputation,\n previousDepsSize: number,\n trackingVersion: number,\n): void {\n const addedDeps = computation.trackingAddedDeps;\n const trackedCount = computation.trackingCount ?? 0;\n\n if (trackedCount !== previousDepsSize || (addedDeps?.length ?? 0) > 0) {\n cleanupUntrackedDeps(computation, trackingVersion);\n }\n\n computation.trackingAddedDeps = undefined;\n computation.trackingCount = undefined;\n computation.trackingTouchedDeps = undefined;\n}\n\nfunction performanceNow(): number {\n return typeof performance === \"undefined\" ? Date.now() : performance.now();\n}\n"]}
@@ -3,6 +3,7 @@ export interface Scheduler {
3
3
  schedule(flush: () => void): void;
4
4
  }
5
5
  export declare function setScheduler(nextScheduler: Scheduler): () => void;
6
+ export declare function resetSchedulerStateForTesting(): void;
6
7
  export declare function queueComputation(computation: ReactiveComputation): void;
7
8
  export declare function schedulePendingFlush(): void;
8
9
  export declare function flushQueuedComputations(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACnC;AAqBD,wBAAgB,YAAY,CAAC,aAAa,EAAE,SAAS,GAAG,MAAM,IAAI,CAOjE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAkBvE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAiB3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAoC9C"}
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACnC;AAqBD,wBAAgB,YAAY,CAAC,aAAa,EAAE,SAAS,GAAG,MAAM,IAAI,CAOjE;AAED,wBAAgB,6BAA6B,IAAI,IAAI,CAQpD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAkBvE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAiB3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAoC9C"}
package/dist/scheduler.js CHANGED
@@ -22,6 +22,14 @@ export function setScheduler(nextScheduler) {
22
22
  scheduler = previous;
23
23
  };
24
24
  }
25
+ export function resetSchedulerStateForTesting() {
26
+ for (const computation of queue) {
27
+ computation.queued = false;
28
+ }
29
+ clearQueue();
30
+ scheduled = false;
31
+ flushing = false;
32
+ }
25
33
  export function queueComputation(computation) {
26
34
  if (computation.disposed || computation.queued) {
27
35
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation } from \"./state.js\";\n\nexport interface Scheduler {\n schedule(flush: () => void): void;\n}\n\nconst defaultScheduler: Scheduler = {\n schedule(flush) {\n if (typeof queueMicrotask === \"function\") {\n queueMicrotask(flush);\n return;\n }\n\n void Promise.resolve().then(flush);\n },\n};\n\nlet scheduler = defaultScheduler;\nlet queue: ReactiveComputation[] = [];\nlet lastQueuedComputationId = -1;\nlet queueRequiresSort = false;\nlet scheduled = false;\nlet flushing = false;\nconst maxFlushIterations = 100;\n\nexport function setScheduler(nextScheduler: Scheduler): () => void {\n const previous = scheduler;\n scheduler = nextScheduler;\n\n return () => {\n scheduler = previous;\n };\n}\n\nexport function queueComputation(computation: ReactiveComputation): void {\n if (computation.disposed || computation.queued) {\n return;\n }\n\n if (computation.id < lastQueuedComputationId) {\n queueRequiresSort = true;\n }\n\n lastQueuedComputationId = computation.id;\n queue.push(computation);\n computation.queued = true;\n\n if (runtimeState.batchDepth > 0) {\n return;\n }\n\n schedulePendingFlush();\n}\n\nexport function schedulePendingFlush(): void {\n if (queue.length === 0 || scheduled || flushing) {\n return;\n }\n\n scheduled = true;\n\n try {\n scheduler.schedule(flushQueuedComputations);\n } catch (error) {\n scheduled = false;\n for (const computation of queue) {\n computation.queued = false;\n }\n clearQueue();\n throw error;\n }\n}\n\nexport function flushQueuedComputations(): void {\n if (flushing) {\n return;\n }\n\n scheduled = false;\n flushing = true;\n let firstError: unknown;\n\n try {\n for (let iteration = 0; queue.length > 0; iteration += 1) {\n if (iteration >= maxFlushIterations) {\n throw new Error(\"Reactive flush limit exceeded\");\n }\n\n const current = takeQueuedComputations();\n\n for (const computation of current) {\n computation.queued = false;\n\n if (!computation.disposed) {\n try {\n computation.run();\n } catch (error) {\n firstError ??= error;\n }\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n } finally {\n flushing = false;\n }\n}\n\nfunction clearQueue(): void {\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n}\n\nfunction takeQueuedComputations(): ReactiveComputation[] {\n if (queueRequiresSort) {\n const current = queue.sort((a, b) => a.id - b.id);\n clearQueue();\n return current;\n }\n\n const current = queue;\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n return current;\n}\n"]}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation } from \"./state.js\";\n\nexport interface Scheduler {\n schedule(flush: () => void): void;\n}\n\nconst defaultScheduler: Scheduler = {\n schedule(flush) {\n if (typeof queueMicrotask === \"function\") {\n queueMicrotask(flush);\n return;\n }\n\n void Promise.resolve().then(flush);\n },\n};\n\nlet scheduler = defaultScheduler;\nlet queue: ReactiveComputation[] = [];\nlet lastQueuedComputationId = -1;\nlet queueRequiresSort = false;\nlet scheduled = false;\nlet flushing = false;\nconst maxFlushIterations = 100;\n\nexport function setScheduler(nextScheduler: Scheduler): () => void {\n const previous = scheduler;\n scheduler = nextScheduler;\n\n return () => {\n scheduler = previous;\n };\n}\n\nexport function resetSchedulerStateForTesting(): void {\n for (const computation of queue) {\n computation.queued = false;\n }\n\n clearQueue();\n scheduled = false;\n flushing = false;\n}\n\nexport function queueComputation(computation: ReactiveComputation): void {\n if (computation.disposed || computation.queued) {\n return;\n }\n\n if (computation.id < lastQueuedComputationId) {\n queueRequiresSort = true;\n }\n\n lastQueuedComputationId = computation.id;\n queue.push(computation);\n computation.queued = true;\n\n if (runtimeState.batchDepth > 0) {\n return;\n }\n\n schedulePendingFlush();\n}\n\nexport function schedulePendingFlush(): void {\n if (queue.length === 0 || scheduled || flushing) {\n return;\n }\n\n scheduled = true;\n\n try {\n scheduler.schedule(flushQueuedComputations);\n } catch (error) {\n scheduled = false;\n for (const computation of queue) {\n computation.queued = false;\n }\n clearQueue();\n throw error;\n }\n}\n\nexport function flushQueuedComputations(): void {\n if (flushing) {\n return;\n }\n\n scheduled = false;\n flushing = true;\n let firstError: unknown;\n\n try {\n for (let iteration = 0; queue.length > 0; iteration += 1) {\n if (iteration >= maxFlushIterations) {\n throw new Error(\"Reactive flush limit exceeded\");\n }\n\n const current = takeQueuedComputations();\n\n for (const computation of current) {\n computation.queued = false;\n\n if (!computation.disposed) {\n try {\n computation.run();\n } catch (error) {\n firstError ??= error;\n }\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n } finally {\n flushing = false;\n }\n}\n\nfunction clearQueue(): void {\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n}\n\nfunction takeQueuedComputations(): ReactiveComputation[] {\n if (queueRequiresSort) {\n const current = queue.sort((a, b) => a.id - b.id);\n clearQueue();\n return current;\n }\n\n const current = queue;\n queue = [];\n lastQueuedComputationId = -1;\n queueRequiresSort = false;\n return current;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAIlD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,IAAI,IAAI,CAAC;IACjB,SAAS,IAAI,OAAO,CAAC;IACrB,mBAAmB,IAAI,MAAM,CAAC;CAC/B;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CA0C/D"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAIlD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,IAAI,IAAI,CAAC;IACjB,SAAS,IAAI,OAAO,CAAC;IACrB,mBAAmB,IAAI,MAAM,CAAC;CAC/B;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CA2C/D"}
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { flushQueuedComputations } from "./scheduler.js";
1
+ import { flushQueuedComputations, resetSchedulerStateForTesting } from "./scheduler.js";
2
2
  import { setScheduler } from "./scheduler.js";
3
3
  export async function flushMicrotasks() {
4
4
  await Promise.resolve();
@@ -29,6 +29,7 @@ export function createReactiveTestRuntime() {
29
29
  }
30
30
  disposed = true;
31
31
  scheduled.length = 0;
32
+ resetSchedulerStateForTesting();
32
33
  restore();
33
34
  },
34
35
  flushAll() {
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAkB,MAAM,gBAAgB,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,uBAAuB,EAAE,CAAC;IAC1B,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB,uBAAuB,EAAE,CAAC;AAC5B,CAAC;AASD,MAAM,UAAU,yBAAyB;IACvC,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAc;QAC3B,QAAQ,CAAC,KAAK;YACZ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,OAAO;YACL,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,QAAQ;YACN,YAAY,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA,CAAC;QAC7B,CAAC;QACD,SAAS;YACP,YAAY,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,KAAK,EAAE,CAAC;YACR,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mBAAmB;YACjB,OAAO,SAAS,CAAC,MAAM,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { flushQueuedComputations } from \"./scheduler.js\";\nimport { setScheduler, type Scheduler } from \"./scheduler.js\";\n\nexport async function flushMicrotasks(): Promise<void> {\n await Promise.resolve();\n}\n\nexport async function flushEffects(): Promise<void> {\n flushQueuedComputations();\n await Promise.resolve();\n flushQueuedComputations();\n}\n\nexport interface ReactiveTestRuntime {\n dispose(): void;\n flushAll(): void;\n flushNext(): boolean;\n scheduledFlushCount(): number;\n}\n\nexport function createReactiveTestRuntime(): ReactiveTestRuntime {\n const scheduled: Array<() => void> = [];\n const scheduler: Scheduler = {\n schedule(flush) {\n scheduled.push(flush);\n },\n };\n const restore = setScheduler(scheduler);\n let disposed = false;\n\n const assertActive = () => {\n if (disposed) {\n throw new Error(\"Reactive test runtime has already been disposed\");\n }\n };\n\n return {\n dispose() {\n if (disposed) {\n return;\n }\n disposed = true;\n scheduled.length = 0;\n restore();\n },\n flushAll() {\n assertActive();\n while (this.flushNext()) {}\n },\n flushNext() {\n assertActive();\n const flush = scheduled.shift();\n if (flush === undefined) {\n return false;\n }\n flush();\n return true;\n },\n scheduledFlushCount() {\n return scheduled.length;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAkB,MAAM,gBAAgB,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,uBAAuB,EAAE,CAAC;IAC1B,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB,uBAAuB,EAAE,CAAC;AAC5B,CAAC;AASD,MAAM,UAAU,yBAAyB;IACvC,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAc;QAC3B,QAAQ,CAAC,KAAK;YACZ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,OAAO;YACL,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YACrB,6BAA6B,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,QAAQ;YACN,YAAY,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA,CAAC;QAC7B,CAAC;QACD,SAAS;YACP,YAAY,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,KAAK,EAAE,CAAC;YACR,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mBAAmB;YACjB,OAAO,SAAS,CAAC,MAAM,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { flushQueuedComputations, resetSchedulerStateForTesting } from \"./scheduler.js\";\nimport { setScheduler, type Scheduler } from \"./scheduler.js\";\n\nexport async function flushMicrotasks(): Promise<void> {\n await Promise.resolve();\n}\n\nexport async function flushEffects(): Promise<void> {\n flushQueuedComputations();\n await Promise.resolve();\n flushQueuedComputations();\n}\n\nexport interface ReactiveTestRuntime {\n dispose(): void;\n flushAll(): void;\n flushNext(): boolean;\n scheduledFlushCount(): number;\n}\n\nexport function createReactiveTestRuntime(): ReactiveTestRuntime {\n const scheduled: Array<() => void> = [];\n const scheduler: Scheduler = {\n schedule(flush) {\n scheduled.push(flush);\n },\n };\n const restore = setScheduler(scheduler);\n let disposed = false;\n\n const assertActive = () => {\n if (disposed) {\n throw new Error(\"Reactive test runtime has already been disposed\");\n }\n };\n\n return {\n dispose() {\n if (disposed) {\n return;\n }\n disposed = true;\n scheduled.length = 0;\n resetSchedulerStateForTesting();\n restore();\n },\n flushAll() {\n assertActive();\n while (this.flushNext()) {}\n },\n flushNext() {\n assertActive();\n const flush = scheduled.shift();\n if (flush === undefined) {\n return false;\n }\n flush();\n return true;\n },\n scheduledFlushCount() {\n return scheduled.length;\n },\n };\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { type ReactiveComputation, type Source } from "./state.js";
2
2
  export declare function trackSource(source: Source): void;
3
3
  export declare function cleanupDeps(computation: ReactiveComputation): void;
4
+ export declare function nextTrackingVersionFor(computation: ReactiveComputation): number;
4
5
  export declare function trackIncrementalSource(source: Source, computation: ReactiveComputation): void;
5
6
  export declare function preserveIncrementalTracking(computation: ReactiveComputation): void;
6
7
  export declare function cleanupUntrackedDeps(computation: ReactiveComputation, trackingVersion: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAIjF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA0BhD;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAmBlE;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,IAAI,CA+BN;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAgBlF;AAED,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,MAAM,GACtB,IAAI,CA+BN;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAyBvE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAqDtD;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAmC3C"}
1
+ {"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAIjF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA0BhD;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAmBlE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAc/E;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,IAAI,CA+BN;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAgBlF;AAED,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,mBAAmB,EAChC,eAAe,EAAE,MAAM,GACtB,IAAI,CA+BN;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAyBvE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAmDtD;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAmC3C"}
package/dist/tracking.js CHANGED
@@ -41,6 +41,18 @@ export function cleanupDeps(computation) {
41
41
  }
42
42
  computation.deps.clear();
43
43
  }
44
+ export function nextTrackingVersionFor(computation) {
45
+ const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
46
+ if (Number.isSafeInteger(nextTrackingVersion)) {
47
+ return nextTrackingVersion;
48
+ }
49
+ for (const dep of computation.deps) {
50
+ if (dep.trackedBy === computation) {
51
+ dep.trackedVersion = undefined;
52
+ }
53
+ }
54
+ return 1;
55
+ }
44
56
  export function trackIncrementalSource(source, computation) {
45
57
  const trackingVersion = computation.trackingVersion;
46
58
  if (trackingVersion === undefined) {
@@ -134,12 +146,11 @@ export function notifySubscribers(source) {
134
146
  }
135
147
  const cachedSingleSubscriber = source.singleSubscriber;
136
148
  if (cachedSingleSubscriber !== undefined) {
137
- if (cachedSingleSubscriber.disposed || cachedSingleSubscriber.queued) {
138
- return;
139
- }
140
149
  runtimeState.notificationDepth += 1;
141
150
  try {
142
- cachedSingleSubscriber.markDirty();
151
+ if (!cachedSingleSubscriber.disposed && !cachedSingleSubscriber.queued) {
152
+ cachedSingleSubscriber.markDirty();
153
+ }
143
154
  }
144
155
  finally {
145
156
  runtimeState.notificationDepth -= 1;
@@ -1 +1 @@
1
- {"version":3,"file":"tracking.js","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"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","sourcesContent":["import { runtimeState, type ReactiveComputation, type Source } from \"./state.js\";\n\nconst maxPendingComputedFlushIterations = 100;\n\nexport function trackSource(source: Source): void {\n const tracker = runtimeState.activeTracker;\n\n if (tracker === null || tracker.disposed) {\n return;\n }\n\n if (tracker.trackSource !== undefined) {\n tracker.trackSource(source);\n return;\n }\n\n if (source.singleSubscriber === tracker) {\n tracker.deps.add(source);\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(tracker);\n tracker.deps.add(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = tracker;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function cleanupDeps(computation: ReactiveComputation): void {\n for (const dep of computation.deps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n\n computation.deps.clear();\n}\n\nexport function trackIncrementalSource(\n source: Source,\n computation: ReactiveComputation,\n): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined) {\n trackSource(source);\n return;\n }\n\n if (source.trackedBy === computation && source.trackedVersion === trackingVersion) {\n return;\n }\n\n source.trackedBy = computation;\n source.trackedVersion = trackingVersion;\n computation.trackingCount = (computation.trackingCount ?? 0) + 1;\n computation.trackingTouchedDeps?.push(source);\n\n if (computation.deps.has(source)) {\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(computation);\n computation.deps.add(source);\n computation.trackingAddedDeps?.push(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = computation;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function preserveIncrementalTracking(computation: ReactiveComputation): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined || computation.trackingTouchedDeps !== undefined) {\n return;\n }\n\n const touchedDeps: Source[] = [];\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation && dep.trackedVersion === trackingVersion) {\n touchedDeps.push(dep);\n }\n }\n\n computation.trackingTouchedDeps = touchedDeps;\n}\n\nexport function cleanupUntrackedDeps(\n computation: ReactiveComputation,\n trackingVersion: number,\n): void {\n const touchedDeps =\n computation.trackingTouchedDeps === undefined\n ? undefined\n : new Set(computation.trackingTouchedDeps);\n\n for (const dep of computation.deps) {\n if (\n touchedDeps?.has(dep) === true ||\n (dep.trackedBy === computation && dep.trackedVersion === trackingVersion)\n ) {\n continue;\n }\n\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function cleanupAddedDeps(computation: ReactiveComputation): void {\n const addedDeps = computation.trackingAddedDeps;\n\n if (addedDeps === undefined) {\n return;\n }\n\n for (const dep of addedDeps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function notifySubscribers(source: Source): void {\n if (source.subscribers.size === 0) {\n return;\n }\n\n const cachedSingleSubscriber = source.singleSubscriber;\n if (cachedSingleSubscriber !== undefined) {\n if (cachedSingleSubscriber.disposed || cachedSingleSubscriber.queued) {\n return;\n }\n\n runtimeState.notificationDepth += 1;\n\n try {\n cachedSingleSubscriber.markDirty();\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n return;\n }\n\n runtimeState.notificationDepth += 1;\n\n try {\n const singleSubscriber =\n source.subscribers.size === 1\n ? source.subscribers.values().next().value\n : undefined;\n\n if (singleSubscriber !== undefined) {\n if (!singleSubscriber.disposed && !singleSubscriber.queued) {\n singleSubscriber.markDirty();\n }\n } else {\n const subscribers = orderedComputations(source.subscribers);\n\n for (const subscriber of subscribers) {\n if (!subscriber.disposed && !subscriber.queued) {\n subscriber.markDirty();\n }\n }\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n}\n\nexport function flushPendingComputed(): void {\n if (runtimeState.flushingComputed) {\n return;\n }\n\n runtimeState.flushingComputed = true;\n\n try {\n for (\n let iteration = 0;\n runtimeState.pendingComputed.size > 0;\n iteration += 1\n ) {\n if (iteration >= maxPendingComputedFlushIterations) {\n runtimeState.pendingComputed.clear();\n throw new Error(\"Reactive computed flush limit exceeded\");\n }\n\n const computations =\n runtimeState.pendingComputed.size === 1\n ? [runtimeState.pendingComputed.values().next().value as ReactiveComputation]\n : orderedComputations(runtimeState.pendingComputed);\n runtimeState.pendingComputed.clear();\n\n for (const computation of computations) {\n computation.queued = false;\n\n if (!computation.disposed) {\n computation.run();\n }\n }\n }\n } finally {\n runtimeState.flushingComputed = false;\n }\n}\n\nfunction orderedComputations(\n computations: ReadonlySet<ReactiveComputation>,\n): ReactiveComputation[] {\n const ordered: ReactiveComputation[] = [];\n let previousId = -1;\n let monotonic = true;\n\n for (const computation of computations) {\n ordered.push(computation);\n\n if (computation.id < previousId) {\n monotonic = false;\n }\n\n previousId = computation.id;\n }\n\n return monotonic || ordered.length < 2\n ? ordered\n : ordered.sort((a, b) => a.id - b.id);\n}\n"]}
1
+ {"version":3,"file":"tracking.js","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AAEjF,MAAM,iCAAiC,GAAG,GAAG,CAAC;AAE9C,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC;IAE3C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzC,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;IAC7C,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEzB,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,gBAAgB,GAAG,OAAO,CAAC;IACpC,CAAC;SAAM,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,WAAgC;IAC1D,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;YAC1B,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,WAAgC;IACrE,MAAM,mBAAmB,GAAG,CAAC,WAAW,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAEnE,IAAI,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9C,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAc,EACd,WAAgC;IAEhC,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC;IAEpD,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,WAAW,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,WAAW,IAAI,MAAM,CAAC,cAAc,KAAK,eAAe,EAAE,CAAC;QAClF,OAAO;IACT,CAAC;IAED,MAAM,CAAC,SAAS,GAAG,WAAW,CAAC;IAC/B,MAAM,CAAC,cAAc,GAAG,eAAe,CAAC;IACxC,WAAW,CAAC,aAAa,GAAG,CAAC,WAAW,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,WAAW,CAAC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAE9C,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;IAC7C,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACpC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,WAAW,CAAC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,gBAAgB,GAAG,WAAW,CAAC;IACxC,CAAC;SAAM,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,WAAgC;IAC1E,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC;IAEpD,IAAI,eAAe,KAAK,SAAS,IAAI,WAAW,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACnF,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,IAAI,GAAG,CAAC,cAAc,KAAK,eAAe,EAAE,CAAC;YAC5E,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,WAAW,CAAC,mBAAmB,GAAG,WAAW,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,WAAgC,EAChC,eAAuB;IAEvB,MAAM,WAAW,GACf,WAAW,CAAC,mBAAmB,KAAK,SAAS;QAC3C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;IAE/C,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,IACE,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;YAC9B,CAAC,GAAG,CAAC,SAAS,KAAK,WAAW,IAAI,GAAG,CAAC,cAAc,KAAK,eAAe,CAAC,EACzE,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;YAC1B,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC/D,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAgC;IAC/D,MAAM,SAAS,GAAG,WAAW,CAAC,iBAAiB,CAAC;IAEhD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;YAC1B,GAAG,CAAC,cAAc,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC/D,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO;IACT,CAAC;IAED,MAAM,sBAAsB,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACvD,IAAI,sBAAsB,KAAK,SAAS,EAAE,CAAC;QACzC,YAAY,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAEpC,IAAI,CAAC;YACH,IAAI,CAAC,sBAAsB,CAAC,QAAQ,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC;gBACvE,sBAAsB,CAAC,SAAS,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,iBAAiB,IAAI,CAAC,CAAC;YAEpC,IAAI,YAAY,CAAC,iBAAiB,KAAK,CAAC,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC1E,oBAAoB,EAAE,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IAED,YAAY,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,gBAAgB,GACpB,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;YAC3B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK;YAC1C,CAAC,CAAC,SAAS,CAAC;QAEhB,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;gBAC3D,gBAAgB,CAAC,SAAS,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAE5D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;gBACrC,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;oBAC/C,UAAU,CAAC,SAAS,EAAE,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAEpC,IAAI,YAAY,CAAC,iBAAiB,KAAK,CAAC,IAAI,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAC1E,oBAAoB,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,IAAI,YAAY,CAAC,gBAAgB,EAAE,CAAC;QAClC,OAAO;IACT,CAAC;IAED,YAAY,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAErC,IAAI,CAAC;QACH,KACE,IAAI,SAAS,GAAG,CAAC,EACjB,YAAY,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,EACrC,SAAS,IAAI,CAAC,EACd,CAAC;YACD,IAAI,SAAS,IAAI,iCAAiC,EAAE,CAAC;gBACnD,YAAY,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,YAAY,GAChB,YAAY,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC;gBACrC,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAA4B,CAAC;gBAC7E,CAAC,CAAC,mBAAmB,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YACxD,YAAY,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAErC,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;gBACvC,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC;gBAE3B,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;oBAC1B,WAAW,CAAC,GAAG,EAAE,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,gBAAgB,GAAG,KAAK,CAAC;IACxC,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAC1B,YAA8C;IAE9C,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;IACpB,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE1B,IAAI,WAAW,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;YAChC,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QAED,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QACpC,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["import { runtimeState, type ReactiveComputation, type Source } from \"./state.js\";\n\nconst maxPendingComputedFlushIterations = 100;\n\nexport function trackSource(source: Source): void {\n const tracker = runtimeState.activeTracker;\n\n if (tracker === null || tracker.disposed) {\n return;\n }\n\n if (tracker.trackSource !== undefined) {\n tracker.trackSource(source);\n return;\n }\n\n if (source.singleSubscriber === tracker) {\n tracker.deps.add(source);\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(tracker);\n tracker.deps.add(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = tracker;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function cleanupDeps(computation: ReactiveComputation): void {\n for (const dep of computation.deps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n\n computation.deps.clear();\n}\n\nexport function nextTrackingVersionFor(computation: ReactiveComputation): number {\n const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;\n\n if (Number.isSafeInteger(nextTrackingVersion)) {\n return nextTrackingVersion;\n }\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation) {\n dep.trackedVersion = undefined;\n }\n }\n\n return 1;\n}\n\nexport function trackIncrementalSource(\n source: Source,\n computation: ReactiveComputation,\n): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined) {\n trackSource(source);\n return;\n }\n\n if (source.trackedBy === computation && source.trackedVersion === trackingVersion) {\n return;\n }\n\n source.trackedBy = computation;\n source.trackedVersion = trackingVersion;\n computation.trackingCount = (computation.trackingCount ?? 0) + 1;\n computation.trackingTouchedDeps?.push(source);\n\n if (computation.deps.has(source)) {\n return;\n }\n\n const previousSize = source.subscribers.size;\n source.subscribers.add(computation);\n computation.deps.add(source);\n computation.trackingAddedDeps?.push(source);\n\n if (previousSize === 0) {\n source.singleSubscriber = computation;\n } else if (source.subscribers.size > 1) {\n source.singleSubscriber = undefined;\n }\n}\n\nexport function preserveIncrementalTracking(computation: ReactiveComputation): void {\n const trackingVersion = computation.trackingVersion;\n\n if (trackingVersion === undefined || computation.trackingTouchedDeps !== undefined) {\n return;\n }\n\n const touchedDeps: Source[] = [];\n\n for (const dep of computation.deps) {\n if (dep.trackedBy === computation && dep.trackedVersion === trackingVersion) {\n touchedDeps.push(dep);\n }\n }\n\n computation.trackingTouchedDeps = touchedDeps;\n}\n\nexport function cleanupUntrackedDeps(\n computation: ReactiveComputation,\n trackingVersion: number,\n): void {\n const touchedDeps =\n computation.trackingTouchedDeps === undefined\n ? undefined\n : new Set(computation.trackingTouchedDeps);\n\n for (const dep of computation.deps) {\n if (\n touchedDeps?.has(dep) === true ||\n (dep.trackedBy === computation && dep.trackedVersion === trackingVersion)\n ) {\n continue;\n }\n\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function cleanupAddedDeps(computation: ReactiveComputation): void {\n const addedDeps = computation.trackingAddedDeps;\n\n if (addedDeps === undefined) {\n return;\n }\n\n for (const dep of addedDeps) {\n if (!dep.subscribers.delete(computation)) {\n continue;\n }\n\n if (dep.trackedBy === computation) {\n dep.trackedBy = undefined;\n dep.trackedVersion = undefined;\n }\n\n computation.deps.delete(dep);\n\n if (dep.subscribers.size === 0) {\n dep.singleSubscriber = undefined;\n } else if (dep.subscribers.size === 1) {\n dep.singleSubscriber = dep.subscribers.values().next().value;\n }\n }\n}\n\nexport function notifySubscribers(source: Source): void {\n if (source.subscribers.size === 0) {\n return;\n }\n\n const cachedSingleSubscriber = source.singleSubscriber;\n if (cachedSingleSubscriber !== undefined) {\n runtimeState.notificationDepth += 1;\n\n try {\n if (!cachedSingleSubscriber.disposed && !cachedSingleSubscriber.queued) {\n cachedSingleSubscriber.markDirty();\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n return;\n }\n\n runtimeState.notificationDepth += 1;\n\n try {\n const singleSubscriber =\n source.subscribers.size === 1\n ? source.subscribers.values().next().value\n : undefined;\n\n if (singleSubscriber !== undefined) {\n if (!singleSubscriber.disposed && !singleSubscriber.queued) {\n singleSubscriber.markDirty();\n }\n } else {\n const subscribers = orderedComputations(source.subscribers);\n\n for (const subscriber of subscribers) {\n if (!subscriber.disposed && !subscriber.queued) {\n subscriber.markDirty();\n }\n }\n }\n } finally {\n runtimeState.notificationDepth -= 1;\n\n if (runtimeState.notificationDepth === 0 && runtimeState.batchDepth === 0) {\n flushPendingComputed();\n }\n }\n}\n\nexport function flushPendingComputed(): void {\n if (runtimeState.flushingComputed) {\n return;\n }\n\n runtimeState.flushingComputed = true;\n\n try {\n for (\n let iteration = 0;\n runtimeState.pendingComputed.size > 0;\n iteration += 1\n ) {\n if (iteration >= maxPendingComputedFlushIterations) {\n runtimeState.pendingComputed.clear();\n throw new Error(\"Reactive computed flush limit exceeded\");\n }\n\n const computations =\n runtimeState.pendingComputed.size === 1\n ? [runtimeState.pendingComputed.values().next().value as ReactiveComputation]\n : orderedComputations(runtimeState.pendingComputed);\n runtimeState.pendingComputed.clear();\n\n for (const computation of computations) {\n computation.queued = false;\n\n if (!computation.disposed) {\n computation.run();\n }\n }\n }\n } finally {\n runtimeState.flushingComputed = false;\n }\n}\n\nfunction orderedComputations(\n computations: ReadonlySet<ReactiveComputation>,\n): ReactiveComputation[] {\n const ordered: ReactiveComputation[] = [];\n let previousId = -1;\n let monotonic = true;\n\n for (const computation of computations) {\n ordered.push(computation);\n\n if (computation.id < previousId) {\n monotonic = false;\n }\n\n previousId = computation.id;\n }\n\n return monotonic || ordered.length < 2\n ? ordered\n : ordered.sort((a, b) => a.id - b.id);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reckona/mreact-reactive-core",
3
- "version": "0.0.152",
3
+ "version": "0.0.153",
4
4
  "description": "Fine-grained reactive primitives used across mreact.",
5
5
  "keywords": [
6
6
  "jsx",
package/src/cell.ts CHANGED
@@ -53,13 +53,6 @@ export function cell<T>(initial: T): Cell<T> {
53
53
  });
54
54
  }
55
55
  }
56
- const singleSubscriber = source.singleSubscriber;
57
- if (
58
- singleSubscriber !== undefined &&
59
- (singleSubscriber.disposed || singleSubscriber.queued)
60
- ) {
61
- return;
62
- }
63
56
  notifySubscribers(source);
64
57
  },
65
58
  };
package/src/computed.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  cleanupAddedDeps,
6
6
  cleanupDeps,
7
7
  cleanupUntrackedDeps,
8
+ nextTrackingVersionFor,
8
9
  notifySubscribers,
9
10
  preserveIncrementalTracking,
10
11
  trackIncrementalSource,
@@ -67,8 +68,11 @@ export function computed<T>(
67
68
  }
68
69
 
69
70
  computation.disposed = true;
71
+ computation.queued = false;
72
+ runtimeState.pendingComputed.delete(computation);
70
73
  cleanupDeps(computation);
71
74
  source.subscribers.clear();
75
+ source.singleSubscriber = undefined;
72
76
  },
73
77
  };
74
78
 
@@ -106,7 +110,7 @@ export function computed<T>(
106
110
 
107
111
  const previousTracker = runtimeState.activeTracker;
108
112
  const previousDepsSize = computation.deps.size;
109
- const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
113
+ const nextTrackingVersion = nextTrackingVersionFor(computation);
110
114
 
111
115
  computation.trackingAddedDeps = [];
112
116
  computation.trackingCount = 0;
package/src/effect.ts CHANGED
@@ -5,6 +5,7 @@ import { runtimeState, type ReactiveComputation } from "./state.js";
5
5
  import {
6
6
  cleanupDeps,
7
7
  cleanupUntrackedDeps,
8
+ nextTrackingVersionFor,
8
9
  trackIncrementalSource,
9
10
  } from "./tracking.js";
10
11
 
@@ -39,7 +40,7 @@ export function effect(fn: () => void | (() => void)): () => void {
39
40
  }
40
41
 
41
42
  const previousDepsSize = computation.deps.size;
42
- const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
43
+ const nextTrackingVersion = nextTrackingVersionFor(computation);
43
44
 
44
45
  computation.trackingAddedDeps = [];
45
46
  computation.trackingCount = 0;
@@ -88,6 +89,8 @@ export function effect(fn: () => void | (() => void)): () => void {
88
89
  }
89
90
 
90
91
  computation.disposed = true;
92
+ computation.queued = false;
93
+ runtimeState.pendingComputed.delete(computation);
91
94
  cleanupDeps(computation);
92
95
 
93
96
  if (cleanup !== undefined) {
@@ -104,6 +107,8 @@ export function effect(fn: () => void | (() => void)): () => void {
104
107
  computation.run();
105
108
  } catch (error) {
106
109
  computation.disposed = true;
110
+ computation.queued = false;
111
+ runtimeState.pendingComputed.delete(computation);
107
112
  cleanupDeps(computation);
108
113
 
109
114
  if (cleanup !== undefined) {
package/src/scheduler.ts CHANGED
@@ -32,6 +32,16 @@ export function setScheduler(nextScheduler: Scheduler): () => void {
32
32
  };
33
33
  }
34
34
 
35
+ export function resetSchedulerStateForTesting(): void {
36
+ for (const computation of queue) {
37
+ computation.queued = false;
38
+ }
39
+
40
+ clearQueue();
41
+ scheduled = false;
42
+ flushing = false;
43
+ }
44
+
35
45
  export function queueComputation(computation: ReactiveComputation): void {
36
46
  if (computation.disposed || computation.queued) {
37
47
  return;
package/src/testing.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { flushQueuedComputations } from "./scheduler.js";
1
+ import { flushQueuedComputations, resetSchedulerStateForTesting } from "./scheduler.js";
2
2
  import { setScheduler, type Scheduler } from "./scheduler.js";
3
3
 
4
4
  export async function flushMicrotasks(): Promise<void> {
@@ -41,6 +41,7 @@ export function createReactiveTestRuntime(): ReactiveTestRuntime {
41
41
  }
42
42
  disposed = true;
43
43
  scheduled.length = 0;
44
+ resetSchedulerStateForTesting();
44
45
  restore();
45
46
  },
46
47
  flushAll() {
package/src/tracking.ts CHANGED
@@ -51,6 +51,22 @@ export function cleanupDeps(computation: ReactiveComputation): void {
51
51
  computation.deps.clear();
52
52
  }
53
53
 
54
+ export function nextTrackingVersionFor(computation: ReactiveComputation): number {
55
+ const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
56
+
57
+ if (Number.isSafeInteger(nextTrackingVersion)) {
58
+ return nextTrackingVersion;
59
+ }
60
+
61
+ for (const dep of computation.deps) {
62
+ if (dep.trackedBy === computation) {
63
+ dep.trackedVersion = undefined;
64
+ }
65
+ }
66
+
67
+ return 1;
68
+ }
69
+
54
70
  export function trackIncrementalSource(
55
71
  source: Source,
56
72
  computation: ReactiveComputation,
@@ -175,14 +191,12 @@ export function notifySubscribers(source: Source): void {
175
191
 
176
192
  const cachedSingleSubscriber = source.singleSubscriber;
177
193
  if (cachedSingleSubscriber !== undefined) {
178
- if (cachedSingleSubscriber.disposed || cachedSingleSubscriber.queued) {
179
- return;
180
- }
181
-
182
194
  runtimeState.notificationDepth += 1;
183
195
 
184
196
  try {
185
- cachedSingleSubscriber.markDirty();
197
+ if (!cachedSingleSubscriber.disposed && !cachedSingleSubscriber.queued) {
198
+ cachedSingleSubscriber.markDirty();
199
+ }
186
200
  } finally {
187
201
  runtimeState.notificationDepth -= 1;
188
202