@getforma/core 1.0.10 → 1.2.0

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.
Files changed (55) hide show
  1. package/dist/{chunk-T33QUD2Y.cjs → chunk-E3FV2VSU.cjs} +43 -43
  2. package/dist/{chunk-T33QUD2Y.cjs.map → chunk-E3FV2VSU.cjs.map} +1 -1
  3. package/dist/chunk-ETPJTPYD.js +103 -0
  4. package/dist/chunk-ETPJTPYD.js.map +1 -0
  5. package/dist/chunk-H7MDUHS5.cjs +110 -0
  6. package/dist/chunk-H7MDUHS5.cjs.map +1 -0
  7. package/dist/{chunk-6FW5E54W.cjs → chunk-KUXNZ5MG.cjs} +127 -103
  8. package/dist/chunk-KUXNZ5MG.cjs.map +1 -0
  9. package/dist/{chunk-3G7ET4O5.js → chunk-Y3A2EVVS.js} +121 -94
  10. package/dist/chunk-Y3A2EVVS.js.map +1 -0
  11. package/dist/{chunk-AFRFF7XL.js → chunk-YRNYOZF3.js} +4 -4
  12. package/dist/{chunk-AFRFF7XL.js.map → chunk-YRNYOZF3.js.map} +1 -1
  13. package/dist/forma-runtime-csp.js +52 -4
  14. package/dist/forma-runtime.js +98 -10
  15. package/dist/formajs-runtime-hardened.global.js +52 -4
  16. package/dist/formajs-runtime-hardened.global.js.map +1 -1
  17. package/dist/formajs-runtime.global.js +98 -10
  18. package/dist/formajs-runtime.global.js.map +1 -1
  19. package/dist/formajs.global.js +368 -147
  20. package/dist/formajs.global.js.map +1 -1
  21. package/dist/http.cjs +11 -11
  22. package/dist/http.js +2 -2
  23. package/dist/index.cjs +262 -141
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +32 -27
  26. package/dist/index.d.ts +32 -27
  27. package/dist/index.js +204 -83
  28. package/dist/index.js.map +1 -1
  29. package/dist/{resource-DeEzxUz6.d.cts → resource-D6HfVgiA.d.cts} +7 -2
  30. package/dist/{resource-BHsgURy0.d.ts → resource-ljs2X5NM.d.ts} +7 -2
  31. package/dist/runtime-hardened.cjs +53 -3
  32. package/dist/runtime-hardened.cjs.map +1 -1
  33. package/dist/runtime-hardened.js +53 -3
  34. package/dist/runtime-hardened.js.map +1 -1
  35. package/dist/runtime.cjs +29 -29
  36. package/dist/runtime.js +3 -3
  37. package/dist/server.cjs +7 -7
  38. package/dist/server.d.cts +2 -2
  39. package/dist/server.d.ts +2 -2
  40. package/dist/server.js +2 -2
  41. package/dist/{signal-C9v4akyJ.d.cts → signal-CRBJYQ6B.d.cts} +0 -8
  42. package/dist/{signal-C9v4akyJ.d.ts → signal-CRBJYQ6B.d.ts} +0 -8
  43. package/dist/tc39-compat.cjs +3 -6
  44. package/dist/tc39-compat.cjs.map +1 -1
  45. package/dist/tc39-compat.d.cts +1 -1
  46. package/dist/tc39-compat.d.ts +1 -1
  47. package/dist/tc39-compat.js +1 -4
  48. package/dist/tc39-compat.js.map +1 -1
  49. package/package.json +1 -1
  50. package/dist/chunk-3G7ET4O5.js.map +0 -1
  51. package/dist/chunk-6FW5E54W.cjs.map +0 -1
  52. package/dist/chunk-HLM5BZZQ.js +0 -35
  53. package/dist/chunk-HLM5BZZQ.js.map +0 -1
  54. package/dist/chunk-QLPCVK7C.cjs +0 -38
  55. package/dist/chunk-QLPCVK7C.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reactive/root.ts","../src/reactive/cleanup.ts","../src/reactive/effect.ts","../src/reactive/memo.ts","../src/reactive/batch.ts","../src/reactive/untrack.ts","../src/reactive/on.ts","../src/reactive/ref.ts","../src/reactive/reducer.ts","../src/reactive/suspense-context.ts","../src/reactive/resource.ts"],"names":["rawEffectScope","setActiveSub","reportError","rawEffect","getActiveSub","createComputed","startBatch","endBatch","value","createSignal"],"mappings":"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","file":"chunk-KUXNZ5MG.cjs","sourcesContent":["/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n *\n * Roots created inside another root are automatically owned by the parent\n * (Solid-style). When the parent is disposed, all child roots are disposed\n * too. Use {@link createUnownedRoot} for roots that must outlive their\n * lexical parent (e.g., mount points, test harnesses).\n */\n\nimport { effectScope as rawEffectScope, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\n/**\n * The minimal ownership unit: something that holds disposers. A {@link RootScope}\n * is an Owner with an extra alien-signals scope dispose. Effects use lightweight\n * child owners (no scopeDispose) to own their nested effects generation-by-generation.\n */\nexport interface Owner {\n /** Disposers to run when this owner is torn down. */\n disposers: (() => void)[];\n}\n\ninterface RootScope extends Owner {\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * The owner that new disposers register with. Inside a root this equals the\n * current {@link RootScope}; {@link runWithOwner} can temporarily point it at any\n * owner so work created outside the original synchronous scope is still owned.\n */\nlet currentOwner: Owner | null = null;\n\n/** @internal — the owner disposers currently register with (or null). */\nexport function getOwner(): Owner | null {\n return currentOwner;\n}\n\n/**\n * Run `fn` with `owner` installed as the current owner, restoring the previous\n * owner afterwards. Lets effects/roots created asynchronously (after the\n * original root callback returned) still be owned and disposed.\n */\nexport function runWithOwner<T>(owner: Owner | null, fn: () => T): T {\n const prev = currentOwner;\n currentOwner = owner;\n try {\n return fn();\n } finally {\n currentOwner = prev;\n }\n}\n\n/** @internal — register a disposer directly with a specific owner. */\nexport function registerOwnerDisposer(owner: Owner, dispose: () => void): void {\n owner.disposers.push(dispose);\n}\n\n/** @internal — a fresh lightweight owner (no alien scope). Used per effect run. */\nexport function createChildOwner(): Owner {\n return { disposers: [] };\n}\n\n/** @internal — run and clear an owner's disposers (guarded so one throw doesn't abort the rest). */\nexport function disposeOwner(owner: Owner): void {\n const ds = owner.disposers;\n for (const d of ds) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n ds.length = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Shared implementation\n// ---------------------------------------------------------------------------\n\nfunction createRootImpl<T>(fn: (dispose: () => void) => T, owned: boolean): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n const parentRoot = owned ? currentRoot : null;\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n const prevOwner = currentOwner;\n currentOwner = scope;\n\n let disposed = false;\n let setupComplete = false;\n let disposeRequestedDuringSetup = false;\n\n const runDisposers = () => {\n // Run userland disposers (includes child root disposes), guarded so one\n // throw does not abort the rest. Draining means a later runTeardown only\n // sees disposers registered since this drain.\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n const runTeardown = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n runDisposers();\n };\n\n const dispose = () => {\n if (disposed) return; // idempotent — safe to call after parent already disposed this\n disposed = true;\n // dispose() called synchronously DURING setup: scope.scopeDispose is not yet\n // assigned and anything created AFTER this call has not registered. Eagerly\n // run the disposers already registered (so cleanup for work created BEFORE\n // this call is synchronous, Solid-style), and defer the rest — the alien\n // scope dispose plus any after-created disposers — until setup finishes.\n // Without the deferral, everything created afterward would leak.\n if (!setupComplete) {\n disposeRequestedDuringSetup = true;\n runDisposers();\n return;\n }\n runTeardown();\n };\n\n // Auto-register with parent root so child dies when parent dies (Solid-style)\n if (parentRoot) {\n parentRoot.disposers.push(dispose);\n }\n\n let result: T;\n try {\n if (owned) {\n // Owned: alien-signals nesting is kept (belt + suspenders with Forma cascade)\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } else {\n // Unowned: break alien-signals scope nesting so this scope is NOT\n // disposed when the lexical parent scope is disposed.\n const prevSub = setActiveSub(undefined);\n try {\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n setActiveSub(prevSub);\n }\n }\n // Setup finished: scope.scopeDispose is assigned and all in-setup effects /\n // child-roots have registered. If dispose() was requested during setup, run\n // the deferred teardown now so everything created in the callback is torn down.\n setupComplete = true;\n if (disposeRequestedDuringSetup) {\n runTeardown();\n }\n } finally {\n currentRoot = rootStack.pop() ?? null;\n currentOwner = prevOwner;\n }\n\n return result!;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * Roots created inside another root are automatically owned by the parent.\n * When the parent is disposed, this root is disposed too.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n return createRootImpl(fn, true);\n}\n\n/**\n * Create a reactive root that is NOT owned by any parent root.\n *\n * Use this for roots that must outlive their lexical parent:\n * top-level mount points, island hydration, test harnesses, etc.\n *\n * ```ts\n * createRoot(() => {\n * // This root outlives the parent even though it's nested:\n * createUnownedRoot((dispose) => {\n * // effects here survive parent disposal\n * });\n * });\n * ```\n */\nexport function createUnownedRoot<T>(fn: (dispose: () => void) => T): T {\n return createRootImpl(fn, false);\n}\n\n/**\n * @internal — called by createEffect and DOM primitives to register disposers\n * with the current owner (a root scope, or an owner installed via runWithOwner).\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentOwner) {\n currentOwner.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside an owner scope (root or runWithOwner).\n */\nexport function hasActiveRoot(): boolean {\n return currentOwner !== null;\n}\n","/**\n * Forma Reactive - Cleanup\n *\n * Register cleanup functions within reactive scopes.\n * Inspired by SolidJS onCleanup().\n */\n\n// ---------------------------------------------------------------------------\n// Cleanup context tracking\n// ---------------------------------------------------------------------------\n\ntype CleanupCollector = ((fn: () => void) => void) | null;\n\nlet currentCleanupCollector: CleanupCollector = null;\n\n/**\n * Register a cleanup function in the current reactive scope.\n * The cleanup runs before the effect re-executes and on disposal.\n *\n * More composable than returning a cleanup from the effect function,\n * since it can be called from helper functions.\n *\n * ```ts\n * createEffect(() => {\n * const timer = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timer));\n * });\n * ```\n */\nexport function onCleanup(fn: () => void): void {\n currentCleanupCollector?.(fn);\n}\n\n/**\n * @internal — Set the cleanup collector for the current effect execution.\n */\nexport function setCleanupCollector(collector: CleanupCollector): CleanupCollector {\n const prev = currentCleanupCollector;\n currentCleanupCollector = collector;\n return prev;\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect, getActiveSub } from 'alien-signals';\nimport {\n hasActiveRoot,\n registerDisposer,\n getOwner,\n runWithOwner,\n registerOwnerDisposer,\n createChildOwner,\n disposeOwner,\n type Owner,\n} from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\n// ---------------------------------------------------------------------------\n// Self-write detection — alien-signals' propagate() never notifies a subscriber\n// that is currently running, so an effect writing a signal it depends on is left\n// stale. When that happens alien-signals still sets the Pending flag on the\n// running subscriber's node (but skips the re-run). We read that flag on the\n// EFFECT's own node after each run and loop, so a self-dependent effect\n// converges. Reading the effect's own node (not a global) makes this precise:\n// writes to signals the effect does not depend on, writes from a nested computed,\n// and a nested effect's self-write never set THIS node's Pending, so they cause\n// no spurious re-run. It also works through batch() (Pending is set at flush).\n// ---------------------------------------------------------------------------\n\n// alien-signals ReactiveFlags.Pending (not exported from the package root).\nconst PENDING = 32;\n\ninterface SubNode { flags: number; }\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n // Capture the owner active at creation time so this effect's disposer is owned\n // by whatever created it — a root, or (for a nested effect) the parent effect's\n // current child-owner. This replaces a hasActiveRoot() snapshot so nested\n // effects created during a parent re-run (when no root is lexically active) are\n // still owned and disposed.\n const ownerAtCreate = getOwner();\n\n // This effect owns its nested effects/roots via a reusable child-owner: it is\n // disposed (nested cleanups run) at the top of each run and on disposal, then\n // reused for the next generation. One small allocation per createEffect; the\n // hot DOM path uses internalEffect, which has no child-owner.\n const childOwner: Owner = createChildOwner();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n const runOnce = () => {\n // Dispose the previous generation of nested effects/roots (running their\n // cleanups) FIRST — children before parents, matching wrappedDispose so the\n // teardown order is consistent between the re-run and dispose paths and a\n // nested cleanup never observes parent-owned state already freed. (alien's\n // raw unwatched teardown of a nested effect bypasses our cleanup, so we own\n // nested work explicitly.)\n disposeOwner(childOwner);\n\n // Run and clear this effect's own previous cleanups.\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Always install the collector so onCleanup()/returned cleanups are captured\n // on EVERY run. (The old skipCleanupInfra fast-path latched after a clean\n // first run and then silently dropped — or cross-registered — cleanups\n // registered on later runs.) The single-cleanup/pooled-array promotion below\n // keeps the zero/one-cleanup case allocation-free.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n // Run the body with this effect's child-owner installed so any nested\n // effects/roots it creates are owned by this generation.\n const result = runWithOwner(childOwner, fn);\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n // Commit this run's cleanups. When none were registered, both stay\n // undefined (allocation-free).\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else if (nextCleanup !== undefined) {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else if (nextCleanup !== undefined) {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n }\n };\n\n const safeFn = () => {\n // alien-signals sets activeSub to this effect's node for the duration of this\n // callback, so getActiveSub() is our own node. If the body writes a signal we\n // depend on, alien-signals marks this node Pending but skips the re-run; we\n // detect that and run again, bounded so a genuine cycle is reported instead of\n // hanging.\n const node = getActiveSub() as SubNode | undefined;\n let reentrantRuns = 0;\n do {\n if (node) node.flags &= ~PENDING; // clear before running so we detect a fresh set\n runOnce();\n if (node === undefined || (node.flags & PENDING) === 0) break;\n if (++reentrantRuns >= MAX_REENTRANT_RUNS) {\n node.flags &= ~PENDING;\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} self-triggered re-runs (cycle?)`),\n 'effect',\n );\n break;\n }\n } while (true);\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n // Dispose nested effects/roots this effect owns, then run its own cleanups.\n disposeOwner(childOwner);\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register this effect's disposer with the owner active at creation (a root, or\n // a parent effect's child-owner).\n if (ownerAtCreate) {\n registerOwnerDisposer(ownerAtCreate, wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Memo\n *\n * Alias for createComputed with SolidJS/React-familiar naming.\n * A memoized derived value that only recomputes when its dependencies change.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { createComputed } from './computed.js';\n\n/**\n * Create a memoized computed value.\n * Identical to `createComputed` — provided for React/SolidJS familiarity.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), both createComputed and createMemo in FormaJS are lazy\n * cached derivations — equivalent to SolidJS's createMemo. They are\n * identical.\n *\n * The computation runs lazily and caches the result. It only recomputes\n * when a signal it reads during computation changes.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createMemo(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n */\nexport const createMemo: typeof createComputed = createComputed;\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma Reactive - Untrack\n *\n * Read signals without subscribing to them in the reactive graph.\n * Essential for reading values inside effects without creating dependencies.\n *\n * TC39 Signals equivalent: Signal.subtle.untrack()\n */\n\nimport { setActiveSub } from 'alien-signals';\n\n/**\n * Execute a function without tracking signal reads.\n * Any signals read inside `fn` will NOT become dependencies of the\n * surrounding effect or computed.\n *\n * ```ts\n * createEffect(() => {\n * const a = count(); // tracked — effect re-runs when count changes\n * const b = untrack(() => other()); // NOT tracked — effect ignores other changes\n * });\n * ```\n */\nexport function untrack<T>(fn: () => T): T {\n const prev = setActiveSub(undefined);\n try {\n return fn();\n } finally {\n setActiveSub(prev);\n }\n}\n","/**\n * Forma Reactive - On\n *\n * Explicit dependency tracking for effects.\n * Only re-runs when the specified signals change, ignoring all other reads.\n *\n * SolidJS equivalent: on()\n * Vue equivalent: watch() with explicit deps\n * React equivalent: useEffect dependency array\n */\n\nimport { untrack } from './untrack.js';\n\n/**\n * Create a tracked effect body that only fires when specific dependencies change.\n *\n * Wraps a function so that only the `deps` signals are tracked.\n * All signal reads inside `fn` are untracked (won't cause re-runs).\n *\n * Use with `createEffect`:\n *\n * ```ts\n * const [a, setA] = createSignal(1);\n * const [b, setB] = createSignal(2);\n *\n * // Only re-runs when `a` changes, NOT when `b` changes:\n * createEffect(on(a, (value, prev) => {\n * console.log(`a changed: ${prev} → ${value}, b is ${b()}`);\n * }));\n *\n * setA(10); // fires: \"a changed: 1 → 10, b is 2\"\n * setB(20); // does NOT fire\n * ```\n *\n * Multiple dependencies:\n * ```ts\n * createEffect(on(\n * () => [a(), b()] as const,\n * ([aVal, bVal], prev) => { ... }\n * ));\n * ```\n */\nexport function on<T, U>(\n deps: () => T,\n fn: (value: T, prev: T | undefined) => U,\n options?: { defer?: boolean },\n): () => U | undefined {\n let prev: T | undefined;\n let isFirst = true;\n\n return () => {\n // Track only the deps\n const value = deps();\n\n if (options?.defer && isFirst) {\n isFirst = false;\n prev = value;\n return undefined;\n }\n\n // Run the body untracked so it doesn't add extra dependencies\n const result = untrack(() => fn(value, prev));\n prev = value;\n return result;\n };\n}\n","/**\n * Forma Reactive - Ref\n *\n * Mutable container that does NOT trigger reactivity.\n * Use for DOM references, previous values, instance variables —\n * anything that needs to persist across effect re-runs without\n * causing re-execution.\n *\n * React equivalent: useRef\n * SolidJS equivalent: (none — uses plain variables in setup)\n */\n\n/** A mutable container that does NOT trigger reactivity when written to. */\nexport interface Ref<T> {\n /** The stored value. Mutating this does not notify effects. */\n current: T;\n}\n\n/**\n * Create a mutable ref container.\n *\n * Unlike signals, writing to `.current` does NOT trigger effects.\n * Use when you need a stable reference across reactive scopes.\n *\n * ```ts\n * const timerRef = createRef<number | null>(null);\n *\n * createEffect(() => {\n * timerRef.current = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timerRef.current!));\n * });\n *\n * // DOM ref pattern:\n * const elRef = createRef<HTMLElement | null>(null);\n * h('div', { ref: (el) => { elRef.current = el; } });\n * ```\n */\nexport function createRef<T>(initialValue: T): Ref<T> {\n return { current: initialValue };\n}\n","/**\n * Forma Reactive - Reducer\n *\n * State machine pattern — dispatch actions to a pure reducer function.\n * Fine-grained: only the resulting state signal is reactive.\n *\n * React equivalent: useReducer\n * SolidJS equivalent: (none — uses createSignal + helpers)\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\n\n/** A function that dispatches an action to a reducer. */\nexport type Dispatch<A> = (action: A) => void;\n\n/**\n * Create a reducer — predictable state updates via dispatched actions.\n *\n * The reducer function must be pure: `(state, action) => newState`.\n * Returns a [state, dispatch] tuple.\n *\n * ```ts\n * type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };\n *\n * const [count, dispatch] = createReducer(\n * (state: number, action: Action) => {\n * switch (action.type) {\n * case 'increment': return state + 1;\n * case 'decrement': return state - 1;\n * case 'reset': return 0;\n * }\n * },\n * 0,\n * );\n *\n * dispatch({ type: 'increment' }); // count() === 1\n * dispatch({ type: 'increment' }); // count() === 2\n * dispatch({ type: 'reset' }); // count() === 0\n * ```\n */\nexport function createReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initialState: S,\n): [state: SignalGetter<S>, dispatch: Dispatch<A>] {\n const [state, setState] = createSignal(initialState);\n\n const dispatch: Dispatch<A> = (action) => {\n setState((prev) => reducer(prev, action));\n };\n\n return [state, dispatch];\n}\n","/**\n * Forma Reactive - Suspense Context\n *\n * Shared context stack for Suspense boundaries. Lives in the reactive layer\n * (not DOM) so that createResource can import it without circular dependencies.\n *\n * The pattern mirrors the lifecycle context stack in component/define.ts.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Context object for a Suspense boundary, tracking pending async resources. */\nexport interface SuspenseContext {\n /** Increment when a resource starts loading inside this boundary. */\n increment(): void;\n /** Decrement when a resource resolves/rejects inside this boundary. */\n decrement(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Context stack\n// ---------------------------------------------------------------------------\n\nlet currentSuspenseContext: SuspenseContext | null = null;\nconst suspenseStack: (SuspenseContext | null)[] = [];\n\nexport function pushSuspenseContext(ctx: SuspenseContext): void {\n suspenseStack.push(currentSuspenseContext);\n currentSuspenseContext = ctx;\n}\n\nexport function popSuspenseContext(): void {\n currentSuspenseContext = suspenseStack.pop() ?? null;\n}\n\n/** Get the current Suspense context (if any). Called by createResource. */\nexport function getSuspenseContext(): SuspenseContext | null {\n return currentSuspenseContext;\n}\n","/**\n * Forma Reactive - Resource\n *\n * Async data fetching primitive with reactive loading/error state.\n * Tracks a source signal and refetches when it changes.\n *\n * SolidJS equivalent: createResource\n * React equivalent: use() + Suspense (React 19), or useSWR/react-query\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\nimport { internalEffect } from './effect.js';\nimport { untrack } from './untrack.js';\nimport { batch } from './batch.js';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { getSuspenseContext } from './suspense-context.js';\n\n/** Info passed to a resource fetcher — carries the AbortSignal for this fetch. */\nexport interface ResourceFetcherInfo {\n /** Aborted when the source changes / the resource refetches or is disposed. */\n signal: AbortSignal;\n}\n\n/** An async data resource with reactive loading and error state. */\nexport interface Resource<T> {\n /** The resolved data (or undefined while loading). */\n (): T | undefined;\n /** True while the fetcher is running. */\n loading: SignalGetter<boolean>;\n /** The error if the fetcher rejected (or undefined). */\n error: SignalGetter<unknown>;\n /** Manually refetch with the current source value. */\n refetch: () => void;\n /** Manually set the data (overrides fetcher result). */\n mutate: (value: T | undefined) => void;\n}\n\n/** Options for {@link createResource}. */\nexport interface ResourceOptions<T> {\n /** Initial value before first fetch resolves. */\n initialValue?: T;\n}\n\n/**\n * Create an async resource that fetches data reactively.\n *\n * When `source` changes, the fetcher re-runs automatically.\n * Provides reactive `loading` and `error` signals.\n *\n * ```ts\n * const [userId, setUserId] = createSignal(1);\n *\n * const user = createResource(\n * userId, // source signal\n * (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher\n * );\n *\n * internalEffect(() => {\n * if (user.loading()) console.log('Loading...');\n * else if (user.error()) console.log('Error:', user.error());\n * else console.log('User:', user());\n * });\n *\n * setUserId(2); // automatically refetches\n * ```\n *\n * Without a source signal (static fetch):\n * ```ts\n * const posts = createResource(\n * () => true, // constant source — fetches once\n * () => fetch('/api/posts').then(r => r.json()),\n * );\n * ```\n */\nexport function createResource<T, S = true>(\n source: SignalGetter<S>,\n fetcher: (source: S, info: ResourceFetcherInfo) => Promise<T>,\n options?: ResourceOptions<T>,\n): Resource<T> {\n const [data, setData] = createSignal<T | undefined>(options?.initialValue);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<unknown>(undefined);\n\n // Capture the Suspense context at creation time (not at fetch time).\n // This is critical because the Suspense boundary pushes/pops its context\n // synchronously during children() execution.\n const suspenseCtx = getSuspenseContext();\n\n let abortController: AbortController | null = null;\n let fetchVersion = 0;\n\n const doFetch = () => {\n // Read source outside tracking to get current value\n const sourceValue = untrack(source);\n\n // Abort previous in-flight request\n if (abortController) {\n abortController.abort();\n }\n const controller = new AbortController();\n abortController = controller;\n\n const version = ++fetchVersion;\n const isLatest = () => version === fetchVersion;\n let suspensePending = false;\n\n // Notify Suspense boundary that a fetch has started\n if (suspenseCtx) {\n suspenseCtx.increment();\n suspensePending = true;\n }\n\n // Batch the paired start writes so subscribers never see a glitch frame\n // (loading=true with a stale error from the previous fetch).\n batch(() => {\n setLoading(true);\n setError(undefined);\n });\n\n // Route a synchronously-thrown fetcher through the same rejection path so the\n // .catch/.finally below run — otherwise loading stays true forever and the\n // Suspense increment is never matched by a decrement.\n let promise: Promise<T>;\n try {\n promise = Promise.resolve(fetcher(sourceValue, { signal: controller.signal }));\n } catch (err) {\n promise = Promise.reject(err);\n }\n\n promise\n .then((result) => {\n // Only apply if this is still the latest fetch and wasn't aborted.\n // Batch data + loading so subscribers see one atomic settled frame.\n if (isLatest() && !controller.signal.aborted) {\n batch(() => {\n setData(() => result);\n setLoading(false);\n });\n }\n })\n .catch((err) => {\n if (isLatest() && !controller.signal.aborted && err?.name !== 'AbortError') {\n batch(() => {\n setError(err);\n setLoading(false);\n });\n }\n })\n .finally(() => {\n if (suspensePending) suspenseCtx?.decrement();\n // loading is cleared atomically in .then/.catch above; a stale/aborted\n // settlement leaves it to the newer fetch (or the dispose) and writes no\n // state here.\n if (isLatest() && abortController === controller) {\n abortController = null; // Release controller for GC\n }\n });\n };\n\n // Auto-fetch when source changes\n internalEffect(() => {\n source(); // track the source signal\n doFetch();\n });\n\n // Abort any in-flight fetch when the owning root is disposed. The fetchVersion\n // guard already neutralizes late settlements; this also cancels fetchers that\n // honor the AbortSignal.\n if (hasActiveRoot()) {\n registerDisposer(() => {\n // Invalidate any in-flight fetch so its late settlement writes no state\n // (isLatest() becomes false), then abort it.\n fetchVersion++;\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n });\n }\n\n // Build the resource object\n const resource = (() => data()) as Resource<T>;\n resource.loading = loading;\n resource.error = error;\n resource.refetch = doFetch;\n resource.mutate = (value) => setData(() => value);\n\n return resource;\n}\n"]}
@@ -1,32 +1,76 @@
1
- import { createComputed, createSignal } from './chunk-HLM5BZZQ.js';
2
- import { effect, startBatch, endBatch, setActiveSub, effectScope } from 'alien-signals';
1
+ import { createComputed, createSignal, reportError } from './chunk-ETPJTPYD.js';
2
+ import { effect, startBatch, endBatch, setActiveSub, getActiveSub, effectScope } from 'alien-signals';
3
3
  export { getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, trigger } from 'alien-signals';
4
4
 
5
5
  var currentRoot = null;
6
6
  var rootStack = [];
7
+ var currentOwner = null;
8
+ function getOwner() {
9
+ return currentOwner;
10
+ }
11
+ function runWithOwner(owner, fn) {
12
+ const prev = currentOwner;
13
+ currentOwner = owner;
14
+ try {
15
+ return fn();
16
+ } finally {
17
+ currentOwner = prev;
18
+ }
19
+ }
20
+ function registerOwnerDisposer(owner, dispose) {
21
+ owner.disposers.push(dispose);
22
+ }
23
+ function createChildOwner() {
24
+ return { disposers: [] };
25
+ }
26
+ function disposeOwner(owner) {
27
+ const ds = owner.disposers;
28
+ for (const d of ds) {
29
+ try {
30
+ d();
31
+ } catch {
32
+ }
33
+ }
34
+ ds.length = 0;
35
+ }
7
36
  function createRootImpl(fn, owned) {
8
37
  const scope = { disposers: [], scopeDispose: null };
9
38
  const parentRoot = owned ? currentRoot : null;
10
39
  rootStack.push(currentRoot);
11
40
  currentRoot = scope;
41
+ const prevOwner = currentOwner;
42
+ currentOwner = scope;
12
43
  let disposed = false;
13
- const dispose = () => {
14
- if (disposed) return;
15
- disposed = true;
16
- if (scope.scopeDispose) {
44
+ let setupComplete = false;
45
+ let disposeRequestedDuringSetup = false;
46
+ const runDisposers = () => {
47
+ for (const d of scope.disposers) {
17
48
  try {
18
- scope.scopeDispose();
49
+ d();
19
50
  } catch {
20
51
  }
21
- scope.scopeDispose = null;
22
52
  }
23
- for (const d of scope.disposers) {
53
+ scope.disposers.length = 0;
54
+ };
55
+ const runTeardown = () => {
56
+ if (scope.scopeDispose) {
24
57
  try {
25
- d();
58
+ scope.scopeDispose();
26
59
  } catch {
27
60
  }
61
+ scope.scopeDispose = null;
28
62
  }
29
- scope.disposers.length = 0;
63
+ runDisposers();
64
+ };
65
+ const dispose = () => {
66
+ if (disposed) return;
67
+ disposed = true;
68
+ if (!setupComplete) {
69
+ disposeRequestedDuringSetup = true;
70
+ runDisposers();
71
+ return;
72
+ }
73
+ runTeardown();
30
74
  };
31
75
  if (parentRoot) {
32
76
  parentRoot.disposers.push(dispose);
@@ -47,8 +91,13 @@ function createRootImpl(fn, owned) {
47
91
  setActiveSub(prevSub);
48
92
  }
49
93
  }
94
+ setupComplete = true;
95
+ if (disposeRequestedDuringSetup) {
96
+ runTeardown();
97
+ }
50
98
  } finally {
51
99
  currentRoot = rootStack.pop() ?? null;
100
+ currentOwner = prevOwner;
52
101
  }
53
102
  return result;
54
103
  }
@@ -59,12 +108,12 @@ function createUnownedRoot(fn) {
59
108
  return createRootImpl(fn, false);
60
109
  }
61
110
  function registerDisposer(dispose) {
62
- if (currentRoot) {
63
- currentRoot.disposers.push(dispose);
111
+ if (currentOwner) {
112
+ currentOwner.disposers.push(dispose);
64
113
  }
65
114
  }
66
115
  function hasActiveRoot() {
67
- return currentRoot !== null;
116
+ return currentOwner !== null;
68
117
  }
69
118
 
70
119
  // src/reactive/cleanup.ts
@@ -77,29 +126,12 @@ function setCleanupCollector(collector) {
77
126
  currentCleanupCollector = collector;
78
127
  return prev;
79
128
  }
80
-
81
- // src/reactive/dev.ts
82
- var __DEV__ = typeof process !== "undefined" ? process.env?.NODE_ENV !== "production" : true;
83
- var _errorHandler = null;
84
- function onError(handler) {
85
- _errorHandler = handler;
86
- }
87
- function reportError(error, source) {
88
- if (_errorHandler) {
89
- try {
90
- _errorHandler(error, source ? { source } : {});
91
- } catch {
92
- }
93
- }
94
- if (__DEV__) {
95
- console.error(`[forma] ${source ?? "Unknown"} error:`, error);
96
- }
97
- }
98
129
  var POOL_SIZE = 32;
99
130
  var MAX_REENTRANT_RUNS = 100;
100
131
  var pool = [];
101
132
  for (let i = 0; i < POOL_SIZE; i++) pool.push([]);
102
133
  var poolIdx = POOL_SIZE;
134
+ var PENDING = 32;
103
135
  function acquireArray() {
104
136
  if (poolIdx > 0) {
105
137
  const arr = pool[--poolIdx];
@@ -140,7 +172,8 @@ function internalEffect(fn) {
140
172
  return dispose;
141
173
  }
142
174
  function createEffect(fn) {
143
- const shouldRegister = hasActiveRoot();
175
+ const ownerAtCreate = getOwner();
176
+ const childOwner = createChildOwner();
144
177
  let cleanup;
145
178
  let cleanupBag;
146
179
  let nextCleanup;
@@ -159,11 +192,8 @@ function createEffect(fn) {
159
192
  }
160
193
  nextCleanup = cb;
161
194
  };
162
- let skipCleanupInfra = false;
163
- let firstRun = true;
164
- let running = false;
165
- let rerunRequested = false;
166
195
  const runOnce = () => {
196
+ disposeOwner(childOwner);
167
197
  if (cleanup !== void 0) {
168
198
  runCleanup(cleanup);
169
199
  cleanup = void 0;
@@ -173,68 +203,46 @@ function createEffect(fn) {
173
203
  releaseArray(cleanupBag);
174
204
  cleanupBag = void 0;
175
205
  }
176
- if (skipCleanupInfra) {
177
- try {
178
- fn();
179
- } catch (e) {
180
- reportError(e, "effect");
181
- }
182
- return;
183
- }
184
206
  nextCleanup = void 0;
185
207
  nextCleanupBag = void 0;
186
208
  const prevCollector = setCleanupCollector(addCleanup);
187
209
  try {
188
- const result = fn();
210
+ const result = runWithOwner(childOwner, fn);
189
211
  if (typeof result === "function") {
190
212
  addCleanup(result);
191
213
  }
192
- if (nextCleanup === void 0 && nextCleanupBag === void 0) {
193
- if (firstRun) skipCleanupInfra = true;
194
- return;
195
- }
196
214
  if (nextCleanupBag !== void 0) {
197
215
  cleanupBag = nextCleanupBag;
198
- } else {
216
+ } else if (nextCleanup !== void 0) {
199
217
  cleanup = nextCleanup;
200
218
  }
201
219
  } catch (e) {
202
220
  reportError(e, "effect");
203
221
  if (nextCleanupBag !== void 0) {
204
222
  cleanupBag = nextCleanupBag;
205
- } else {
223
+ } else if (nextCleanup !== void 0) {
206
224
  cleanup = nextCleanup;
207
225
  }
208
226
  } finally {
209
227
  setCleanupCollector(prevCollector);
210
- firstRun = false;
211
228
  }
212
229
  };
213
230
  const safeFn = () => {
214
- if (running) {
215
- rerunRequested = true;
216
- return;
217
- }
218
- running = true;
219
- try {
220
- let reentrantRuns = 0;
221
- do {
222
- rerunRequested = false;
223
- runOnce();
224
- if (rerunRequested) {
225
- reentrantRuns++;
226
- if (reentrantRuns >= MAX_REENTRANT_RUNS) {
227
- reportError(
228
- new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),
229
- "effect"
230
- );
231
- rerunRequested = false;
232
- }
233
- }
234
- } while (rerunRequested);
235
- } finally {
236
- running = false;
237
- }
231
+ const node = getActiveSub();
232
+ let reentrantRuns = 0;
233
+ do {
234
+ if (node) node.flags &= ~PENDING;
235
+ runOnce();
236
+ if (node === void 0 || (node.flags & PENDING) === 0) break;
237
+ if (++reentrantRuns >= MAX_REENTRANT_RUNS) {
238
+ node.flags &= ~PENDING;
239
+ reportError(
240
+ new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} self-triggered re-runs (cycle?)`),
241
+ "effect"
242
+ );
243
+ break;
244
+ }
245
+ } while (true);
238
246
  };
239
247
  const dispose = effect(safeFn);
240
248
  let disposed = false;
@@ -242,6 +250,7 @@ function createEffect(fn) {
242
250
  if (disposed) return;
243
251
  disposed = true;
244
252
  dispose();
253
+ disposeOwner(childOwner);
245
254
  if (cleanup !== void 0) {
246
255
  runCleanup(cleanup);
247
256
  cleanup = void 0;
@@ -252,8 +261,8 @@ function createEffect(fn) {
252
261
  cleanupBag = void 0;
253
262
  }
254
263
  };
255
- if (shouldRegister) {
256
- registerDisposer(wrappedDispose);
264
+ if (ownerAtCreate) {
265
+ registerOwnerDisposer(ownerAtCreate, wrappedDispose);
257
266
  }
258
267
  return wrappedDispose;
259
268
  }
@@ -344,25 +353,34 @@ function createResource(source, fetcher, options) {
344
353
  suspenseCtx.increment();
345
354
  suspensePending = true;
346
355
  }
347
- setLoading(true);
348
- setError(void 0);
349
- Promise.resolve(fetcher(sourceValue)).then((result) => {
356
+ batch(() => {
357
+ setLoading(true);
358
+ setError(void 0);
359
+ });
360
+ let promise;
361
+ try {
362
+ promise = Promise.resolve(fetcher(sourceValue, { signal: controller.signal }));
363
+ } catch (err) {
364
+ promise = Promise.reject(err);
365
+ }
366
+ promise.then((result) => {
350
367
  if (isLatest() && !controller.signal.aborted) {
351
- setData(() => result);
368
+ batch(() => {
369
+ setData(() => result);
370
+ setLoading(false);
371
+ });
352
372
  }
353
373
  }).catch((err) => {
354
- if (isLatest() && !controller.signal.aborted) {
355
- if (err?.name !== "AbortError") {
374
+ if (isLatest() && !controller.signal.aborted && err?.name !== "AbortError") {
375
+ batch(() => {
356
376
  setError(err);
357
- }
377
+ setLoading(false);
378
+ });
358
379
  }
359
380
  }).finally(() => {
360
381
  if (suspensePending) suspenseCtx?.decrement();
361
- if (isLatest()) {
362
- setLoading(false);
363
- if (abortController === controller) {
364
- abortController = null;
365
- }
382
+ if (isLatest() && abortController === controller) {
383
+ abortController = null;
366
384
  }
367
385
  });
368
386
  };
@@ -370,6 +388,15 @@ function createResource(source, fetcher, options) {
370
388
  source();
371
389
  doFetch();
372
390
  });
391
+ if (hasActiveRoot()) {
392
+ registerDisposer(() => {
393
+ fetchVersion++;
394
+ if (abortController) {
395
+ abortController.abort();
396
+ abortController = null;
397
+ }
398
+ });
399
+ }
373
400
  const resource = (() => data());
374
401
  resource.loading = loading;
375
402
  resource.error = error;
@@ -378,6 +405,6 @@ function createResource(source, fetcher, options) {
378
405
  return resource;
379
406
  }
380
407
 
381
- export { __DEV__, batch, createEffect, createMemo, createReducer, createRef, createResource, createRoot, createUnownedRoot, internalEffect, on, onCleanup, onError, popSuspenseContext, pushSuspenseContext, registerDisposer, reportError, untrack };
382
- //# sourceMappingURL=chunk-3G7ET4O5.js.map
383
- //# sourceMappingURL=chunk-3G7ET4O5.js.map
408
+ export { batch, createEffect, createMemo, createReducer, createRef, createResource, createRoot, createUnownedRoot, internalEffect, on, onCleanup, popSuspenseContext, pushSuspenseContext, registerDisposer, untrack };
409
+ //# sourceMappingURL=chunk-Y3A2EVVS.js.map
410
+ //# sourceMappingURL=chunk-Y3A2EVVS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reactive/root.ts","../src/reactive/cleanup.ts","../src/reactive/effect.ts","../src/reactive/memo.ts","../src/reactive/batch.ts","../src/reactive/untrack.ts","../src/reactive/on.ts","../src/reactive/ref.ts","../src/reactive/reducer.ts","../src/reactive/suspense-context.ts","../src/reactive/resource.ts"],"names":["rawEffectScope","rawEffect","setActiveSub","value"],"mappings":"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","file":"chunk-Y3A2EVVS.js","sourcesContent":["/**\n * Forma Reactive - Root\n *\n * Explicit reactive ownership scope. All effects created inside a root\n * are automatically disposed when the root is torn down.\n *\n * Uses alien-signals' `effectScope` under the hood for native graph-level\n * effect tracking, with a userland disposer list for non-effect cleanup\n * (e.g., event listeners, DOM references, timers).\n *\n * Roots created inside another root are automatically owned by the parent\n * (Solid-style). When the parent is disposed, all child roots are disposed\n * too. Use {@link createUnownedRoot} for roots that must outlive their\n * lexical parent (e.g., mount points, test harnesses).\n */\n\nimport { effectScope as rawEffectScope, setActiveSub } from 'alien-signals';\n\n// ---------------------------------------------------------------------------\n// Root scope tracking\n// ---------------------------------------------------------------------------\n\nlet currentRoot: RootScope | null = null;\nconst rootStack: (RootScope | null)[] = [];\n\n/**\n * The minimal ownership unit: something that holds disposers. A {@link RootScope}\n * is an Owner with an extra alien-signals scope dispose. Effects use lightweight\n * child owners (no scopeDispose) to own their nested effects generation-by-generation.\n */\nexport interface Owner {\n /** Disposers to run when this owner is torn down. */\n disposers: (() => void)[];\n}\n\ninterface RootScope extends Owner {\n /** alien-signals effect scope dispose — tears down all reactive effects */\n scopeDispose: (() => void) | null;\n}\n\n/**\n * The owner that new disposers register with. Inside a root this equals the\n * current {@link RootScope}; {@link runWithOwner} can temporarily point it at any\n * owner so work created outside the original synchronous scope is still owned.\n */\nlet currentOwner: Owner | null = null;\n\n/** @internal — the owner disposers currently register with (or null). */\nexport function getOwner(): Owner | null {\n return currentOwner;\n}\n\n/**\n * Run `fn` with `owner` installed as the current owner, restoring the previous\n * owner afterwards. Lets effects/roots created asynchronously (after the\n * original root callback returned) still be owned and disposed.\n */\nexport function runWithOwner<T>(owner: Owner | null, fn: () => T): T {\n const prev = currentOwner;\n currentOwner = owner;\n try {\n return fn();\n } finally {\n currentOwner = prev;\n }\n}\n\n/** @internal — register a disposer directly with a specific owner. */\nexport function registerOwnerDisposer(owner: Owner, dispose: () => void): void {\n owner.disposers.push(dispose);\n}\n\n/** @internal — a fresh lightweight owner (no alien scope). Used per effect run. */\nexport function createChildOwner(): Owner {\n return { disposers: [] };\n}\n\n/** @internal — run and clear an owner's disposers (guarded so one throw doesn't abort the rest). */\nexport function disposeOwner(owner: Owner): void {\n const ds = owner.disposers;\n for (const d of ds) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n ds.length = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Shared implementation\n// ---------------------------------------------------------------------------\n\nfunction createRootImpl<T>(fn: (dispose: () => void) => T, owned: boolean): T {\n const scope: RootScope = { disposers: [], scopeDispose: null };\n const parentRoot = owned ? currentRoot : null;\n\n rootStack.push(currentRoot);\n currentRoot = scope;\n const prevOwner = currentOwner;\n currentOwner = scope;\n\n let disposed = false;\n let setupComplete = false;\n let disposeRequestedDuringSetup = false;\n\n const runDisposers = () => {\n // Run userland disposers (includes child root disposes), guarded so one\n // throw does not abort the rest. Draining means a later runTeardown only\n // sees disposers registered since this drain.\n for (const d of scope.disposers) {\n try { d(); } catch { /* ensure all disposers run */ }\n }\n scope.disposers.length = 0;\n };\n\n const runTeardown = () => {\n // Dispose alien-signals effect scope first (reactive graph cleanup)\n if (scope.scopeDispose) {\n try { scope.scopeDispose(); } catch { /* ensure userland disposers still run */ }\n scope.scopeDispose = null;\n }\n runDisposers();\n };\n\n const dispose = () => {\n if (disposed) return; // idempotent — safe to call after parent already disposed this\n disposed = true;\n // dispose() called synchronously DURING setup: scope.scopeDispose is not yet\n // assigned and anything created AFTER this call has not registered. Eagerly\n // run the disposers already registered (so cleanup for work created BEFORE\n // this call is synchronous, Solid-style), and defer the rest — the alien\n // scope dispose plus any after-created disposers — until setup finishes.\n // Without the deferral, everything created afterward would leak.\n if (!setupComplete) {\n disposeRequestedDuringSetup = true;\n runDisposers();\n return;\n }\n runTeardown();\n };\n\n // Auto-register with parent root so child dies when parent dies (Solid-style)\n if (parentRoot) {\n parentRoot.disposers.push(dispose);\n }\n\n let result: T;\n try {\n if (owned) {\n // Owned: alien-signals nesting is kept (belt + suspenders with Forma cascade)\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } else {\n // Unowned: break alien-signals scope nesting so this scope is NOT\n // disposed when the lexical parent scope is disposed.\n const prevSub = setActiveSub(undefined);\n try {\n scope.scopeDispose = rawEffectScope(() => {\n result = fn(dispose);\n });\n } finally {\n setActiveSub(prevSub);\n }\n }\n // Setup finished: scope.scopeDispose is assigned and all in-setup effects /\n // child-roots have registered. If dispose() was requested during setup, run\n // the deferred teardown now so everything created in the callback is torn down.\n setupComplete = true;\n if (disposeRequestedDuringSetup) {\n runTeardown();\n }\n } finally {\n currentRoot = rootStack.pop() ?? null;\n currentOwner = prevOwner;\n }\n\n return result!;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive root scope.\n *\n * All effects created (via `createEffect`) inside the callback are tracked\n * at both the reactive graph level (via alien-signals effectScope) and the\n * userland level (via registerDisposer). The returned `dispose` function\n * tears down everything.\n *\n * Roots created inside another root are automatically owned by the parent.\n * When the parent is disposed, this root is disposed too.\n *\n * ```ts\n * const dispose = createRoot(() => {\n * createEffect(() => console.log(count()));\n * createEffect(() => console.log(name()));\n * });\n * // later: dispose() stops both effects\n * ```\n */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n return createRootImpl(fn, true);\n}\n\n/**\n * Create a reactive root that is NOT owned by any parent root.\n *\n * Use this for roots that must outlive their lexical parent:\n * top-level mount points, island hydration, test harnesses, etc.\n *\n * ```ts\n * createRoot(() => {\n * // This root outlives the parent even though it's nested:\n * createUnownedRoot((dispose) => {\n * // effects here survive parent disposal\n * });\n * });\n * ```\n */\nexport function createUnownedRoot<T>(fn: (dispose: () => void) => T): T {\n return createRootImpl(fn, false);\n}\n\n/**\n * @internal — called by createEffect and DOM primitives to register disposers\n * with the current owner (a root scope, or an owner installed via runWithOwner).\n */\nexport function registerDisposer(dispose: () => void): void {\n if (currentOwner) {\n currentOwner.disposers.push(dispose);\n }\n}\n\n/**\n * @internal — check if we're inside an owner scope (root or runWithOwner).\n */\nexport function hasActiveRoot(): boolean {\n return currentOwner !== null;\n}\n","/**\n * Forma Reactive - Cleanup\n *\n * Register cleanup functions within reactive scopes.\n * Inspired by SolidJS onCleanup().\n */\n\n// ---------------------------------------------------------------------------\n// Cleanup context tracking\n// ---------------------------------------------------------------------------\n\ntype CleanupCollector = ((fn: () => void) => void) | null;\n\nlet currentCleanupCollector: CleanupCollector = null;\n\n/**\n * Register a cleanup function in the current reactive scope.\n * The cleanup runs before the effect re-executes and on disposal.\n *\n * More composable than returning a cleanup from the effect function,\n * since it can be called from helper functions.\n *\n * ```ts\n * createEffect(() => {\n * const timer = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timer));\n * });\n * ```\n */\nexport function onCleanup(fn: () => void): void {\n currentCleanupCollector?.(fn);\n}\n\n/**\n * @internal — Set the cleanup collector for the current effect execution.\n */\nexport function setCleanupCollector(collector: CleanupCollector): CleanupCollector {\n const prev = currentCleanupCollector;\n currentCleanupCollector = collector;\n return prev;\n}\n","/**\n * Forma Reactive - Effect\n *\n * Side-effectful reactive computation that auto-tracks signal dependencies.\n * Backed by alien-signals for automatic dependency tracking.\n *\n * TC39 Signals equivalent: Signal.subtle.Watcher (effect is a userland concept)\n */\n\nimport { effect as rawEffect, getActiveSub } from 'alien-signals';\nimport {\n hasActiveRoot,\n registerDisposer,\n getOwner,\n runWithOwner,\n registerOwnerDisposer,\n createChildOwner,\n disposeOwner,\n type Owner,\n} from './root.js';\nimport { setCleanupCollector } from './cleanup.js';\nimport { reportError } from './dev.js';\n\n// ---------------------------------------------------------------------------\n// Cleanup array pool — avoids allocating a new array every effect re-run\n// ---------------------------------------------------------------------------\n\nconst POOL_SIZE = 32;\nconst MAX_REENTRANT_RUNS = 100;\nconst pool: (() => void)[][] = [];\nfor (let i = 0; i < POOL_SIZE; i++) pool.push([]);\nlet poolIdx = POOL_SIZE;\n\n// ---------------------------------------------------------------------------\n// Self-write detection — alien-signals' propagate() never notifies a subscriber\n// that is currently running, so an effect writing a signal it depends on is left\n// stale. When that happens alien-signals still sets the Pending flag on the\n// running subscriber's node (but skips the re-run). We read that flag on the\n// EFFECT's own node after each run and loop, so a self-dependent effect\n// converges. Reading the effect's own node (not a global) makes this precise:\n// writes to signals the effect does not depend on, writes from a nested computed,\n// and a nested effect's self-write never set THIS node's Pending, so they cause\n// no spurious re-run. It also works through batch() (Pending is set at flush).\n// ---------------------------------------------------------------------------\n\n// alien-signals ReactiveFlags.Pending (not exported from the package root).\nconst PENDING = 32;\n\ninterface SubNode { flags: number; }\n\nfunction acquireArray(): (() => void)[] {\n if (poolIdx > 0) {\n const arr = pool[--poolIdx]!;\n arr.length = 0;\n return arr;\n }\n return [];\n}\n\nfunction releaseArray(arr: (() => void)[]): void {\n arr.length = 0;\n if (poolIdx < POOL_SIZE) {\n pool[poolIdx++] = arr;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified cleanup runner — single function for both re-run and dispose paths\n// ---------------------------------------------------------------------------\n\nfunction runCleanup(fn: (() => void) | undefined): void {\n if (fn === undefined) return;\n try {\n fn();\n } catch (e) {\n reportError(e, 'effect cleanup');\n }\n}\n\nfunction runCleanups(bag: (() => void)[] | undefined): void {\n if (bag === undefined) return;\n for (let i = 0; i < bag.length; i++) {\n try { bag[i]!(); } catch (e) { reportError(e, 'effect cleanup'); }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a reactive effect that auto-tracks signal dependencies.\n *\n * The provided function runs immediately and re-runs whenever any signal it\n * reads changes. If the function returns a cleanup function, that cleanup is\n * called before each re-run and on disposal.\n *\n * Additionally, `onCleanup()` can be called inside the effect to register\n * cleanup functions composably.\n *\n * Returns a dispose function that stops the effect.\n */\n/**\n * @internal — Lightweight effect for Forma's internal DOM bindings.\n *\n * Bypasses createEffect's cleanup infrastructure (pool, collector, error\n * reporting, engine compression) since internal effects never use\n * onCleanup() or return cleanup functions. This saves ~4 function calls\n * per effect creation and per re-run.\n *\n * ONLY use for effects that:\n * 1. Never call onCleanup()\n * 2. Never return a cleanup function\n * 3. Contain simple \"read signal → write DOM\" logic\n */\nexport function internalEffect(fn: () => void): () => void {\n const dispose = rawEffect(fn);\n if (hasActiveRoot()) {\n registerDisposer(dispose);\n }\n return dispose;\n}\n\nexport function createEffect(fn: () => void | (() => void)): () => void {\n // Capture the owner active at creation time so this effect's disposer is owned\n // by whatever created it — a root, or (for a nested effect) the parent effect's\n // current child-owner. This replaces a hasActiveRoot() snapshot so nested\n // effects created during a parent re-run (when no root is lexically active) are\n // still owned and disposed.\n const ownerAtCreate = getOwner();\n\n // This effect owns its nested effects/roots via a reusable child-owner: it is\n // disposed (nested cleanups run) at the top of each run and on disposal, then\n // reused for the next generation. One small allocation per createEffect; the\n // hot DOM path uses internalEffect, which has no child-owner.\n const childOwner: Owner = createChildOwner();\n\n // Most effects have zero or one cleanup. Track the single-cleanup case\n // without array allocation; only promote to pooled array when needed.\n let cleanup: (() => void) | undefined;\n let cleanupBag: (() => void)[] | undefined;\n let nextCleanup: (() => void) | undefined;\n let nextCleanupBag: (() => void)[] | undefined;\n\n const addCleanup = (cb: () => void) => {\n if (nextCleanupBag !== undefined) {\n nextCleanupBag.push(cb);\n return;\n }\n if (nextCleanup !== undefined) {\n const bag = acquireArray();\n bag.push(nextCleanup, cb);\n nextCleanup = undefined;\n nextCleanupBag = bag;\n return;\n }\n nextCleanup = cb;\n };\n\n const runOnce = () => {\n // Dispose the previous generation of nested effects/roots (running their\n // cleanups) FIRST — children before parents, matching wrappedDispose so the\n // teardown order is consistent between the re-run and dispose paths and a\n // nested cleanup never observes parent-owned state already freed. (alien's\n // raw unwatched teardown of a nested effect bypasses our cleanup, so we own\n // nested work explicitly.)\n disposeOwner(childOwner);\n\n // Run and clear this effect's own previous cleanups.\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n\n nextCleanup = undefined;\n nextCleanupBag = undefined;\n\n // Always install the collector so onCleanup()/returned cleanups are captured\n // on EVERY run. (The old skipCleanupInfra fast-path latched after a clean\n // first run and then silently dropped — or cross-registered — cleanups\n // registered on later runs.) The single-cleanup/pooled-array promotion below\n // keeps the zero/one-cleanup case allocation-free.\n const prevCollector = setCleanupCollector(addCleanup);\n\n try {\n // Run the body with this effect's child-owner installed so any nested\n // effects/roots it creates are owned by this generation.\n const result = runWithOwner(childOwner, fn);\n if (typeof result === 'function') {\n addCleanup(result as () => void);\n }\n // Commit this run's cleanups. When none were registered, both stay\n // undefined (allocation-free).\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else if (nextCleanup !== undefined) {\n cleanup = nextCleanup;\n }\n } catch (e) {\n reportError(e, 'effect');\n if (nextCleanupBag !== undefined) {\n cleanupBag = nextCleanupBag;\n } else if (nextCleanup !== undefined) {\n cleanup = nextCleanup;\n }\n } finally {\n setCleanupCollector(prevCollector);\n }\n };\n\n const safeFn = () => {\n // alien-signals sets activeSub to this effect's node for the duration of this\n // callback, so getActiveSub() is our own node. If the body writes a signal we\n // depend on, alien-signals marks this node Pending but skips the re-run; we\n // detect that and run again, bounded so a genuine cycle is reported instead of\n // hanging.\n const node = getActiveSub() as SubNode | undefined;\n let reentrantRuns = 0;\n do {\n if (node) node.flags &= ~PENDING; // clear before running so we detect a fresh set\n runOnce();\n if (node === undefined || (node.flags & PENDING) === 0) break;\n if (++reentrantRuns >= MAX_REENTRANT_RUNS) {\n node.flags &= ~PENDING;\n reportError(\n new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} self-triggered re-runs (cycle?)`),\n 'effect',\n );\n break;\n }\n } while (true);\n };\n\n const dispose = rawEffect(safeFn);\n\n // Wrap dispose to also run final cleanups\n let disposed = false;\n const wrappedDispose = () => {\n if (disposed) return;\n disposed = true;\n dispose();\n // Dispose nested effects/roots this effect owns, then run its own cleanups.\n disposeOwner(childOwner);\n if (cleanup !== undefined) {\n runCleanup(cleanup);\n cleanup = undefined;\n }\n if (cleanupBag !== undefined) {\n runCleanups(cleanupBag);\n releaseArray(cleanupBag);\n cleanupBag = undefined;\n }\n };\n\n // Register this effect's disposer with the owner active at creation (a root, or\n // a parent effect's child-owner).\n if (ownerAtCreate) {\n registerOwnerDisposer(ownerAtCreate, wrappedDispose);\n }\n\n return wrappedDispose;\n}\n","/**\n * Forma Reactive - Memo\n *\n * Alias for createComputed with SolidJS/React-familiar naming.\n * A memoized derived value that only recomputes when its dependencies change.\n *\n * TC39 Signals equivalent: Signal.Computed\n */\n\nimport { createComputed } from './computed.js';\n\n/**\n * Create a memoized computed value.\n * Identical to `createComputed` — provided for React/SolidJS familiarity.\n *\n * Note: Unlike SolidJS's createComputed (which is an eager synchronous\n * side effect), both createComputed and createMemo in FormaJS are lazy\n * cached derivations — equivalent to SolidJS's createMemo. They are\n * identical.\n *\n * The computation runs lazily and caches the result. It only recomputes\n * when a signal it reads during computation changes.\n *\n * ```ts\n * const [count, setCount] = createSignal(0);\n * const doubled = createMemo(() => count() * 2);\n * console.log(doubled()); // 0\n * setCount(5);\n * console.log(doubled()); // 10\n * ```\n */\nexport const createMemo: typeof createComputed = createComputed;\n","/**\n * Forma Reactive - Batch\n *\n * Groups multiple signal updates and defers effect execution until the\n * outermost batch completes. Prevents intermediate re-renders.\n * Backed by alien-signals.\n *\n * TC39 Signals: no built-in batch — this is a userland optimization.\n */\n\nimport { startBatch, endBatch } from 'alien-signals';\n\n/**\n * Group multiple signal updates so that effects only run once after all\n * updates have been applied.\n *\n * ```ts\n * batch(() => {\n * setA(1);\n * setB(2);\n * // effects that depend on A and B won't run yet\n * });\n * // effects run here, once\n * ```\n *\n * Batches are nestable — only the outermost batch triggers the flush.\n */\nexport function batch(fn: () => void): void {\n startBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n}\n","/**\n * Forma Reactive - Untrack\n *\n * Read signals without subscribing to them in the reactive graph.\n * Essential for reading values inside effects without creating dependencies.\n *\n * TC39 Signals equivalent: Signal.subtle.untrack()\n */\n\nimport { setActiveSub } from 'alien-signals';\n\n/**\n * Execute a function without tracking signal reads.\n * Any signals read inside `fn` will NOT become dependencies of the\n * surrounding effect or computed.\n *\n * ```ts\n * createEffect(() => {\n * const a = count(); // tracked — effect re-runs when count changes\n * const b = untrack(() => other()); // NOT tracked — effect ignores other changes\n * });\n * ```\n */\nexport function untrack<T>(fn: () => T): T {\n const prev = setActiveSub(undefined);\n try {\n return fn();\n } finally {\n setActiveSub(prev);\n }\n}\n","/**\n * Forma Reactive - On\n *\n * Explicit dependency tracking for effects.\n * Only re-runs when the specified signals change, ignoring all other reads.\n *\n * SolidJS equivalent: on()\n * Vue equivalent: watch() with explicit deps\n * React equivalent: useEffect dependency array\n */\n\nimport { untrack } from './untrack.js';\n\n/**\n * Create a tracked effect body that only fires when specific dependencies change.\n *\n * Wraps a function so that only the `deps` signals are tracked.\n * All signal reads inside `fn` are untracked (won't cause re-runs).\n *\n * Use with `createEffect`:\n *\n * ```ts\n * const [a, setA] = createSignal(1);\n * const [b, setB] = createSignal(2);\n *\n * // Only re-runs when `a` changes, NOT when `b` changes:\n * createEffect(on(a, (value, prev) => {\n * console.log(`a changed: ${prev} → ${value}, b is ${b()}`);\n * }));\n *\n * setA(10); // fires: \"a changed: 1 → 10, b is 2\"\n * setB(20); // does NOT fire\n * ```\n *\n * Multiple dependencies:\n * ```ts\n * createEffect(on(\n * () => [a(), b()] as const,\n * ([aVal, bVal], prev) => { ... }\n * ));\n * ```\n */\nexport function on<T, U>(\n deps: () => T,\n fn: (value: T, prev: T | undefined) => U,\n options?: { defer?: boolean },\n): () => U | undefined {\n let prev: T | undefined;\n let isFirst = true;\n\n return () => {\n // Track only the deps\n const value = deps();\n\n if (options?.defer && isFirst) {\n isFirst = false;\n prev = value;\n return undefined;\n }\n\n // Run the body untracked so it doesn't add extra dependencies\n const result = untrack(() => fn(value, prev));\n prev = value;\n return result;\n };\n}\n","/**\n * Forma Reactive - Ref\n *\n * Mutable container that does NOT trigger reactivity.\n * Use for DOM references, previous values, instance variables —\n * anything that needs to persist across effect re-runs without\n * causing re-execution.\n *\n * React equivalent: useRef\n * SolidJS equivalent: (none — uses plain variables in setup)\n */\n\n/** A mutable container that does NOT trigger reactivity when written to. */\nexport interface Ref<T> {\n /** The stored value. Mutating this does not notify effects. */\n current: T;\n}\n\n/**\n * Create a mutable ref container.\n *\n * Unlike signals, writing to `.current` does NOT trigger effects.\n * Use when you need a stable reference across reactive scopes.\n *\n * ```ts\n * const timerRef = createRef<number | null>(null);\n *\n * createEffect(() => {\n * timerRef.current = setInterval(tick, 1000);\n * onCleanup(() => clearInterval(timerRef.current!));\n * });\n *\n * // DOM ref pattern:\n * const elRef = createRef<HTMLElement | null>(null);\n * h('div', { ref: (el) => { elRef.current = el; } });\n * ```\n */\nexport function createRef<T>(initialValue: T): Ref<T> {\n return { current: initialValue };\n}\n","/**\n * Forma Reactive - Reducer\n *\n * State machine pattern — dispatch actions to a pure reducer function.\n * Fine-grained: only the resulting state signal is reactive.\n *\n * React equivalent: useReducer\n * SolidJS equivalent: (none — uses createSignal + helpers)\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\n\n/** A function that dispatches an action to a reducer. */\nexport type Dispatch<A> = (action: A) => void;\n\n/**\n * Create a reducer — predictable state updates via dispatched actions.\n *\n * The reducer function must be pure: `(state, action) => newState`.\n * Returns a [state, dispatch] tuple.\n *\n * ```ts\n * type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };\n *\n * const [count, dispatch] = createReducer(\n * (state: number, action: Action) => {\n * switch (action.type) {\n * case 'increment': return state + 1;\n * case 'decrement': return state - 1;\n * case 'reset': return 0;\n * }\n * },\n * 0,\n * );\n *\n * dispatch({ type: 'increment' }); // count() === 1\n * dispatch({ type: 'increment' }); // count() === 2\n * dispatch({ type: 'reset' }); // count() === 0\n * ```\n */\nexport function createReducer<S, A>(\n reducer: (state: S, action: A) => S,\n initialState: S,\n): [state: SignalGetter<S>, dispatch: Dispatch<A>] {\n const [state, setState] = createSignal(initialState);\n\n const dispatch: Dispatch<A> = (action) => {\n setState((prev) => reducer(prev, action));\n };\n\n return [state, dispatch];\n}\n","/**\n * Forma Reactive - Suspense Context\n *\n * Shared context stack for Suspense boundaries. Lives in the reactive layer\n * (not DOM) so that createResource can import it without circular dependencies.\n *\n * The pattern mirrors the lifecycle context stack in component/define.ts.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Context object for a Suspense boundary, tracking pending async resources. */\nexport interface SuspenseContext {\n /** Increment when a resource starts loading inside this boundary. */\n increment(): void;\n /** Decrement when a resource resolves/rejects inside this boundary. */\n decrement(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Context stack\n// ---------------------------------------------------------------------------\n\nlet currentSuspenseContext: SuspenseContext | null = null;\nconst suspenseStack: (SuspenseContext | null)[] = [];\n\nexport function pushSuspenseContext(ctx: SuspenseContext): void {\n suspenseStack.push(currentSuspenseContext);\n currentSuspenseContext = ctx;\n}\n\nexport function popSuspenseContext(): void {\n currentSuspenseContext = suspenseStack.pop() ?? null;\n}\n\n/** Get the current Suspense context (if any). Called by createResource. */\nexport function getSuspenseContext(): SuspenseContext | null {\n return currentSuspenseContext;\n}\n","/**\n * Forma Reactive - Resource\n *\n * Async data fetching primitive with reactive loading/error state.\n * Tracks a source signal and refetches when it changes.\n *\n * SolidJS equivalent: createResource\n * React equivalent: use() + Suspense (React 19), or useSWR/react-query\n */\n\nimport { createSignal, type SignalGetter } from './signal.js';\nimport { internalEffect } from './effect.js';\nimport { untrack } from './untrack.js';\nimport { batch } from './batch.js';\nimport { hasActiveRoot, registerDisposer } from './root.js';\nimport { getSuspenseContext } from './suspense-context.js';\n\n/** Info passed to a resource fetcher — carries the AbortSignal for this fetch. */\nexport interface ResourceFetcherInfo {\n /** Aborted when the source changes / the resource refetches or is disposed. */\n signal: AbortSignal;\n}\n\n/** An async data resource with reactive loading and error state. */\nexport interface Resource<T> {\n /** The resolved data (or undefined while loading). */\n (): T | undefined;\n /** True while the fetcher is running. */\n loading: SignalGetter<boolean>;\n /** The error if the fetcher rejected (or undefined). */\n error: SignalGetter<unknown>;\n /** Manually refetch with the current source value. */\n refetch: () => void;\n /** Manually set the data (overrides fetcher result). */\n mutate: (value: T | undefined) => void;\n}\n\n/** Options for {@link createResource}. */\nexport interface ResourceOptions<T> {\n /** Initial value before first fetch resolves. */\n initialValue?: T;\n}\n\n/**\n * Create an async resource that fetches data reactively.\n *\n * When `source` changes, the fetcher re-runs automatically.\n * Provides reactive `loading` and `error` signals.\n *\n * ```ts\n * const [userId, setUserId] = createSignal(1);\n *\n * const user = createResource(\n * userId, // source signal\n * (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher\n * );\n *\n * internalEffect(() => {\n * if (user.loading()) console.log('Loading...');\n * else if (user.error()) console.log('Error:', user.error());\n * else console.log('User:', user());\n * });\n *\n * setUserId(2); // automatically refetches\n * ```\n *\n * Without a source signal (static fetch):\n * ```ts\n * const posts = createResource(\n * () => true, // constant source — fetches once\n * () => fetch('/api/posts').then(r => r.json()),\n * );\n * ```\n */\nexport function createResource<T, S = true>(\n source: SignalGetter<S>,\n fetcher: (source: S, info: ResourceFetcherInfo) => Promise<T>,\n options?: ResourceOptions<T>,\n): Resource<T> {\n const [data, setData] = createSignal<T | undefined>(options?.initialValue);\n const [loading, setLoading] = createSignal(false);\n const [error, setError] = createSignal<unknown>(undefined);\n\n // Capture the Suspense context at creation time (not at fetch time).\n // This is critical because the Suspense boundary pushes/pops its context\n // synchronously during children() execution.\n const suspenseCtx = getSuspenseContext();\n\n let abortController: AbortController | null = null;\n let fetchVersion = 0;\n\n const doFetch = () => {\n // Read source outside tracking to get current value\n const sourceValue = untrack(source);\n\n // Abort previous in-flight request\n if (abortController) {\n abortController.abort();\n }\n const controller = new AbortController();\n abortController = controller;\n\n const version = ++fetchVersion;\n const isLatest = () => version === fetchVersion;\n let suspensePending = false;\n\n // Notify Suspense boundary that a fetch has started\n if (suspenseCtx) {\n suspenseCtx.increment();\n suspensePending = true;\n }\n\n // Batch the paired start writes so subscribers never see a glitch frame\n // (loading=true with a stale error from the previous fetch).\n batch(() => {\n setLoading(true);\n setError(undefined);\n });\n\n // Route a synchronously-thrown fetcher through the same rejection path so the\n // .catch/.finally below run — otherwise loading stays true forever and the\n // Suspense increment is never matched by a decrement.\n let promise: Promise<T>;\n try {\n promise = Promise.resolve(fetcher(sourceValue, { signal: controller.signal }));\n } catch (err) {\n promise = Promise.reject(err);\n }\n\n promise\n .then((result) => {\n // Only apply if this is still the latest fetch and wasn't aborted.\n // Batch data + loading so subscribers see one atomic settled frame.\n if (isLatest() && !controller.signal.aborted) {\n batch(() => {\n setData(() => result);\n setLoading(false);\n });\n }\n })\n .catch((err) => {\n if (isLatest() && !controller.signal.aborted && err?.name !== 'AbortError') {\n batch(() => {\n setError(err);\n setLoading(false);\n });\n }\n })\n .finally(() => {\n if (suspensePending) suspenseCtx?.decrement();\n // loading is cleared atomically in .then/.catch above; a stale/aborted\n // settlement leaves it to the newer fetch (or the dispose) and writes no\n // state here.\n if (isLatest() && abortController === controller) {\n abortController = null; // Release controller for GC\n }\n });\n };\n\n // Auto-fetch when source changes\n internalEffect(() => {\n source(); // track the source signal\n doFetch();\n });\n\n // Abort any in-flight fetch when the owning root is disposed. The fetchVersion\n // guard already neutralizes late settlements; this also cancels fetchers that\n // honor the AbortSignal.\n if (hasActiveRoot()) {\n registerDisposer(() => {\n // Invalidate any in-flight fetch so its late settlement writes no state\n // (isLatest() becomes false), then abort it.\n fetchVersion++;\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n });\n }\n\n // Build the resource object\n const resource = (() => data()) as Resource<T>;\n resource.loading = loading;\n resource.error = error;\n resource.refetch = doFetch;\n resource.mutate = (value) => setData(() => value);\n\n return resource;\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { internalEffect, createRoot, untrack, registerDisposer, __DEV__ } from './chunk-3G7ET4O5.js';
2
- import { createSignal } from './chunk-HLM5BZZQ.js';
1
+ import { internalEffect, createRoot, untrack, registerDisposer } from './chunk-Y3A2EVVS.js';
2
+ import { __DEV__, createSignal } from './chunk-ETPJTPYD.js';
3
3
 
4
4
  // src/dom/element.ts
5
5
  var Fragment = /* @__PURE__ */ Symbol.for("forma.fragment");
@@ -1559,5 +1559,5 @@ function createList(items, keyFn, renderFn, options) {
1559
1559
  }
1560
1560
 
1561
1561
  export { Fragment, cleanup, createList, createShow, fragment, h, hydrateIsland, reconcileList };
1562
- //# sourceMappingURL=chunk-AFRFF7XL.js.map
1563
- //# sourceMappingURL=chunk-AFRFF7XL.js.map
1562
+ //# sourceMappingURL=chunk-YRNYOZF3.js.map
1563
+ //# sourceMappingURL=chunk-YRNYOZF3.js.map