{"version":3,"file":"signals.mjs","sources":["../../../../../../../packages/core/primitives/signals/src/watch.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n  consumerAfterComputation,\n  consumerBeforeComputation,\n  consumerDestroy,\n  consumerMarkDirty,\n  consumerPollProducersForChange,\n  isInNotificationPhase,\n  REACTIVE_NODE,\n  ReactiveNode,\n  SIGNAL,\n} from './graph';\n\n/**\n * A cleanup function that can be optionally registered from the watch logic. If registered, the\n * cleanup logic runs before the next watch execution.\n */\nexport type WatchCleanupFn = () => void;\n\n/**\n * A callback passed to the watch function that makes it possible to register cleanup logic.\n */\nexport type WatchCleanupRegisterFn = (cleanupFn: WatchCleanupFn) => void;\n\nexport interface Watch {\n  notify(): void;\n\n  /**\n   * Execute the reactive expression in the context of this `Watch` consumer.\n   *\n   * Should be called by the user scheduling algorithm when the provided\n   * `schedule` hook is called by `Watch`.\n   */\n  run(): void;\n\n  cleanup(): void;\n\n  /**\n   * Destroy the watcher:\n   * - disconnect it from the reactive graph;\n   * - mark it as destroyed so subsequent run and notify operations are noop.\n   */\n  destroy(): void;\n\n  [SIGNAL]: WatchNode;\n}\nexport interface WatchNode extends ReactiveNode {\n  hasRun: boolean;\n  fn: ((onCleanup: WatchCleanupRegisterFn) => void) | null;\n  schedule: ((watch: Watch) => void) | null;\n  cleanupFn: WatchCleanupFn;\n  ref: Watch;\n}\n\nexport function createWatch(\n  fn: (onCleanup: WatchCleanupRegisterFn) => void,\n  schedule: (watch: Watch) => void,\n  allowSignalWrites: boolean,\n): Watch {\n  const node: WatchNode = Object.create(WATCH_NODE);\n  if (allowSignalWrites) {\n    node.consumerAllowSignalWrites = true;\n  }\n\n  node.fn = fn;\n  node.schedule = schedule;\n\n  const registerOnCleanup = (cleanupFn: WatchCleanupFn) => {\n    node.cleanupFn = cleanupFn;\n  };\n\n  function isWatchNodeDestroyed(node: WatchNode) {\n    return node.fn === null && node.schedule === null;\n  }\n\n  function destroyWatchNode(node: WatchNode) {\n    if (!isWatchNodeDestroyed(node)) {\n      consumerDestroy(node); // disconnect watcher from the reactive graph\n      node.cleanupFn();\n\n      // nullify references to the integration functions to mark node as destroyed\n      node.fn = null;\n      node.schedule = null;\n      node.cleanupFn = NOOP_CLEANUP_FN;\n    }\n  }\n\n  const run = () => {\n    if (node.fn === null) {\n      // trying to run a destroyed watch is noop\n      return;\n    }\n\n    if (isInNotificationPhase()) {\n      throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);\n    }\n\n    node.dirty = false;\n    if (node.hasRun && !consumerPollProducersForChange(node)) {\n      return;\n    }\n    node.hasRun = true;\n\n    const prevConsumer = consumerBeforeComputation(node);\n    try {\n      node.cleanupFn();\n      node.cleanupFn = NOOP_CLEANUP_FN;\n      node.fn(registerOnCleanup);\n    } finally {\n      consumerAfterComputation(node, prevConsumer);\n    }\n  };\n\n  node.ref = {\n    notify: () => consumerMarkDirty(node),\n    run,\n    cleanup: () => node.cleanupFn(),\n    destroy: () => destroyWatchNode(node),\n    [SIGNAL]: node,\n  };\n\n  return node.ref;\n}\n\nconst NOOP_CLEANUP_FN: WatchCleanupFn = () => {};\n\n// Note: Using an IIFE here to ensure that the spread assignment is not considered\n// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.\n// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.\nconst WATCH_NODE: Partial<WatchNode> = /* @__PURE__ */ (() => {\n  return {\n    ...REACTIVE_NODE,\n    consumerIsAlwaysLive: true,\n    consumerAllowSignalWrites: false,\n    consumerMarkedDirty: (node: WatchNode) => {\n      if (node.schedule !== null) {\n        node.schedule(node.ref);\n      }\n    },\n    hasRun: false,\n    cleanupFn: NOOP_CLEANUP_FN,\n  };\n})();\n"],"names":[],"mappings":";;;;;;;;;SA6DgB,WAAW,CACzB,EAA+C,EAC/C,QAAgC,EAChC,iBAA0B,EAAA;IAE1B,MAAM,IAAI,GAAc,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;IACjD,IAAI,iBAAiB,EAAE;AACrB,QAAA,IAAI,CAAC,yBAAyB,GAAG,IAAI;;AAGvC,IAAA,IAAI,CAAC,EAAE,GAAG,EAAE;AACZ,IAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ;AAExB,IAAA,MAAM,iBAAiB,GAAG,CAAC,SAAyB,KAAI;AACtD,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;AAC5B,KAAC;IAED,SAAS,oBAAoB,CAAC,IAAe,EAAA;QAC3C,OAAO,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;;IAGnD,SAAS,gBAAgB,CAAC,IAAe,EAAA;AACvC,QAAA,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE;AAC/B,YAAA,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,IAAI,CAAC,SAAS,EAAE;;AAGhB,YAAA,IAAI,CAAC,EAAE,GAAG,IAAI;AACd,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,YAAA,IAAI,CAAC,SAAS,GAAG,eAAe;;;IAIpC,MAAM,GAAG,GAAG,MAAK;AACf,QAAA,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE;;YAEpB;;QAGF,IAAI,qBAAqB,EAAE,EAAE;AAC3B,YAAA,MAAM,IAAI,KAAK,CAAC,CAAA,iEAAA,CAAmE,CAAC;;AAGtF,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;QAClB,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,EAAE;YACxD;;AAEF,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;AAElB,QAAA,MAAM,YAAY,GAAG,yBAAyB,CAAC,IAAI,CAAC;AACpD,QAAA,IAAI;YACF,IAAI,CAAC,SAAS,EAAE;AAChB,YAAA,IAAI,CAAC,SAAS,GAAG,eAAe;AAChC,YAAA,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC;;gBAClB;AACR,YAAA,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC;;AAEhD,KAAC;IAED,IAAI,CAAC,GAAG,GAAG;AACT,QAAA,MAAM,EAAE,MAAM,iBAAiB,CAAC,IAAI,CAAC;QACrC,GAAG;AACH,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,SAAS,EAAE;AAC/B,QAAA,OAAO,EAAE,MAAM,gBAAgB,CAAC,IAAI,CAAC;QACrC,CAAC,MAAM,GAAG,IAAI;KACf;IAED,OAAO,IAAI,CAAC,GAAG;AACjB;AAEA,MAAM,eAAe,GAAmB,MAAK,GAAG;AAEhD;AACA;AACA;AACA,MAAM,UAAU,mBAAuC,CAAC,MAAK;IAC3D,OAAO;AACL,QAAA,GAAG,aAAa;AAChB,QAAA,oBAAoB,EAAE,IAAI;AAC1B,QAAA,yBAAyB,EAAE,KAAK;AAChC,QAAA,mBAAmB,EAAE,CAAC,IAAe,KAAI;AACvC,YAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE;AAC1B,gBAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;;SAE1B;AACD,QAAA,MAAM,EAAE,KAAK;AACb,QAAA,SAAS,EAAE,eAAe;KAC3B;AACH,CAAC,GAAG;;;;"}