All files / solid/src reactive.ts

100% Statements 35/35
100% Branches 10/10
100% Functions 0/0
100% Lines 35/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61  1x 1x     1x 1x   1x   1x   1x   1x                       1x 12x 12x   3x 3x 3x 1x 1x 3x   3x 3x 3x 3x 3x   3x 3x     3x 3x 3x 1x   1x 7x 6x 6x   1x 1x 1x  
import type { StateObserver } from '@anchorlib/core';
import { createObserver, microbatch, onGlobalCleanup, setCleanUpHandler, setTracker } from '@anchorlib/core';
import { createSignal, getOwner, onCleanup, type Owner } from 'solid-js';
import type { ConstantRef, VariableRef } from './types.js';
 
export const REF_REGISTRY = new WeakSet<VariableRef<unknown> | ConstantRef<unknown>>();
export const OWNER_REGISTRY = new WeakMap<Owner, StateObserver>();
 
const [batch] = microbatch(0);
 
let bindingInitialized = false;
 
if (!bindingInitialized) {
  // Make sure to initialize binding only once.
  bindingInitialized = true;
 
  /**
   * Setup global tracker to bind observer with component.
   * This tracker is responsible for synchronizing state changes with Solid component instances.
   * When a reactive state is accessed, this tracker captures the current component instance
   * and ensures that any observers associated with that component are notified of changes.
   *
   * @param init - The initial state value
   * @param observers - Array of observer functions to be notified of changes
   * @param key - The property key being accessed
   */
  setTracker((init, observers, key) => {
    const owner = getOwner();
    if (!owner) return;
 
    if (!OWNER_REGISTRY.has(owner)) {
      const [version, setVersion] = createSignal(0);
      const observer = createObserver(() => {
        observer.reset();
        setVersion(version() + 1);
      });
 
      version();
      onCleanup(() => {
        observer.destroy();
        OWNER_REGISTRY.delete(owner);
      });
 
      OWNER_REGISTRY.set(owner, observer);
    }
 
    // Batch the tracking to unblock the property reads.
    batch(() => {
      OWNER_REGISTRY.get(owner)?.assign(init, observers)(key);
    });
  });
 
  setCleanUpHandler((handler) => {
    if (getOwner()) {
      return onCleanup(handler);
    }
 
    return onGlobalCleanup(handler);
  });
}