All files / src/primitives effect.ts

100% Statements 28/28
100% Branches 7/7
100% Functions 3/3
100% Lines 28/28

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 501x     1x 1x               1x   132x 132x 132x 132x   132x 132x   264x   264x 264x 264x 264x   264x 264x 264x 132x   132x 132x     132x   132x 91x 91x     132x   132x 132x  
import { effectStack, cleanup } from '../internal/scheduler';
import type { Subscriber } from '../internal/scheduler';
import type { Disposer, ReactiveOptions } from '../types';
import { hasOwner, onCleanup } from '../lifecycle/lifecycle';
import { devWarning } from '../error';
 
/**
 * Creates an effect that automatically re-runs when its dependencies (signals) change.
 *
 * @param fn The function to run as an effect.
 * @returns A disposer function to manually stop the effect.
 */
export function createEffect(fn: () => void, options?: ReactiveOptions): Disposer {
  // Add the warning here
  devWarning(
    hasOwner(),
    `createEffect(${options?.name ? `"${options.name}"` : ''}) was called outside of a reactive root. This effect will not be automatically cleaned up.`
  );
  
  const effect: Subscriber = {
    execute: () => {
      // Clean up any old dependencies before re-running the effect.
      cleanup(effect);
      // Push this effect onto the global stack to track new dependencies.
      effectStack.push(effect);
      try {
        fn();
      } finally {
        // Always pop the effect from the stack after execution.
        effectStack.pop();
      }
    },
    dependencies: new Set(),
    // NEW: Store the name on the subscriber object
    name: options?.name,
  };
 
  // Run the effect immediately to establish its initial dependencies.
  effect.execute();
 
  const disposer = () => {
    cleanup(effect);
  };
 
  // NEW: Register the effect's own disposer with the current owner.
  onCleanup(disposer);
 
  return disposer;
}