signals.mjs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /**
  2. * @license Angular v19.2.13
  3. * (c) 2010-2025 Google LLC. https://angular.io/
  4. * License: MIT
  5. */
  6. import { consumerMarkDirty, SIGNAL, consumerDestroy, isInNotificationPhase, consumerPollProducersForChange, consumerBeforeComputation, consumerAfterComputation, REACTIVE_NODE } from '../untracked-BKcld_ew.mjs';
  7. export { SIGNAL_NODE, createComputed, createLinkedSignal, createSignal, defaultEquals, getActiveConsumer, isReactive, linkedSignalSetFn, linkedSignalUpdateFn, producerAccessed, producerIncrementEpoch, producerMarkClean, producerNotifyConsumers, producerUpdateValueVersion, producerUpdatesAllowed, runPostSignalSetFn, setActiveConsumer, setAlternateWeakRefImpl, setPostSignalSetFn, setThrowInvalidWriteToSignalError, signalSetFn, signalUpdateFn, untracked } from '../untracked-BKcld_ew.mjs';
  8. function createWatch(fn, schedule, allowSignalWrites) {
  9. const node = Object.create(WATCH_NODE);
  10. if (allowSignalWrites) {
  11. node.consumerAllowSignalWrites = true;
  12. }
  13. node.fn = fn;
  14. node.schedule = schedule;
  15. const registerOnCleanup = (cleanupFn) => {
  16. node.cleanupFn = cleanupFn;
  17. };
  18. function isWatchNodeDestroyed(node) {
  19. return node.fn === null && node.schedule === null;
  20. }
  21. function destroyWatchNode(node) {
  22. if (!isWatchNodeDestroyed(node)) {
  23. consumerDestroy(node); // disconnect watcher from the reactive graph
  24. node.cleanupFn();
  25. // nullify references to the integration functions to mark node as destroyed
  26. node.fn = null;
  27. node.schedule = null;
  28. node.cleanupFn = NOOP_CLEANUP_FN;
  29. }
  30. }
  31. const run = () => {
  32. if (node.fn === null) {
  33. // trying to run a destroyed watch is noop
  34. return;
  35. }
  36. if (isInNotificationPhase()) {
  37. throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);
  38. }
  39. node.dirty = false;
  40. if (node.hasRun && !consumerPollProducersForChange(node)) {
  41. return;
  42. }
  43. node.hasRun = true;
  44. const prevConsumer = consumerBeforeComputation(node);
  45. try {
  46. node.cleanupFn();
  47. node.cleanupFn = NOOP_CLEANUP_FN;
  48. node.fn(registerOnCleanup);
  49. }
  50. finally {
  51. consumerAfterComputation(node, prevConsumer);
  52. }
  53. };
  54. node.ref = {
  55. notify: () => consumerMarkDirty(node),
  56. run,
  57. cleanup: () => node.cleanupFn(),
  58. destroy: () => destroyWatchNode(node),
  59. [SIGNAL]: node,
  60. };
  61. return node.ref;
  62. }
  63. const NOOP_CLEANUP_FN = () => { };
  64. // Note: Using an IIFE here to ensure that the spread assignment is not considered
  65. // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
  66. // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
  67. const WATCH_NODE = /* @__PURE__ */ (() => {
  68. return {
  69. ...REACTIVE_NODE,
  70. consumerIsAlwaysLive: true,
  71. consumerAllowSignalWrites: false,
  72. consumerMarkedDirty: (node) => {
  73. if (node.schedule !== null) {
  74. node.schedule(node.ref);
  75. }
  76. },
  77. hasRun: false,
  78. cleanupFn: NOOP_CLEANUP_FN,
  79. };
  80. })();
  81. export { REACTIVE_NODE, SIGNAL, consumerAfterComputation, consumerBeforeComputation, consumerDestroy, consumerMarkDirty, consumerPollProducersForChange, createWatch, isInNotificationPhase };
  82. //# sourceMappingURL=signals.mjs.map