signalium 3.0.2 → 4.0.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.
- package/CHANGELOG.md +39 -0
- package/dist/cjs/development/{component-shared-Cug2Y5YZ.js → component-shared-BjwFh5Jq.js} +2 -2
- package/dist/cjs/development/{component-shared-Cug2Y5YZ.js.map → component-shared-BjwFh5Jq.js.map} +1 -1
- package/dist/cjs/development/config-D6wyrhrW.js +58 -0
- package/dist/cjs/development/config-D6wyrhrW.js.map +1 -0
- package/dist/cjs/development/config.js +1 -1
- package/dist/cjs/development/{debug-C46WDxhL.js → debug-CbAX7VeM.js} +260 -43
- package/dist/cjs/development/debug-CbAX7VeM.js.map +1 -0
- package/dist/cjs/development/debug.js +3 -1
- package/dist/cjs/development/debug.js.map +1 -1
- package/dist/cjs/development/index.js +3 -2
- package/dist/cjs/development/index.js.map +1 -1
- package/dist/cjs/development/react/index.js +399 -52
- package/dist/cjs/development/react/index.js.map +1 -1
- package/dist/cjs/development/react/index.server.js +2 -2
- package/dist/cjs/development/react/index.server.js.map +1 -1
- package/dist/cjs/development/react/server.js +1 -1
- package/dist/cjs/development/{snapshot-CbZ6IH3B.js → snapshot-BTMVSd8Y.js} +4 -2
- package/dist/cjs/development/snapshot-BTMVSd8Y.js.map +1 -0
- package/dist/cjs/development/transform/index.js +5 -2
- package/dist/cjs/development/transform/index.js.map +1 -1
- package/dist/cjs/development/utils.js +34 -2
- package/dist/cjs/development/utils.js.map +1 -1
- package/dist/cjs/production/{component-shared-D0J85PUi.js → component-shared-CcxyLg4p.js} +2 -2
- package/dist/cjs/production/{component-shared-D0J85PUi.js.map → component-shared-CcxyLg4p.js.map} +1 -1
- package/dist/cjs/production/config-BHvmcsLQ.js +52 -0
- package/dist/cjs/production/config-BHvmcsLQ.js.map +1 -0
- package/dist/cjs/production/config.js +1 -1
- package/dist/cjs/production/{contexts-CM3QLfV8.js → contexts-waczQzHZ.js} +260 -43
- package/dist/cjs/production/contexts-waczQzHZ.js.map +1 -0
- package/dist/cjs/production/debug.js +3 -1
- package/dist/cjs/production/debug.js.map +1 -1
- package/dist/cjs/production/index.js +3 -2
- package/dist/cjs/production/index.js.map +1 -1
- package/dist/cjs/production/react/index.js +399 -52
- package/dist/cjs/production/react/index.js.map +1 -1
- package/dist/cjs/production/react/index.server.js +2 -2
- package/dist/cjs/production/react/index.server.js.map +1 -1
- package/dist/cjs/production/react/server.js +1 -1
- package/dist/cjs/production/{snapshot-DWwH7_9y.js → snapshot-7264bWj1.js} +4 -2
- package/dist/cjs/production/snapshot-7264bWj1.js.map +1 -0
- package/dist/cjs/production/transform/index.js +5 -2
- package/dist/cjs/production/transform/index.js.map +1 -1
- package/dist/cjs/production/utils.js +34 -2
- package/dist/cjs/production/utils.js.map +1 -1
- package/dist/esm/config.d.ts +1 -1
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/debug.d.ts +1 -0
- package/dist/esm/debug.d.ts.map +1 -1
- package/dist/esm/development/{component-shared-CLSmdnGU.js → component-shared-B3Q6mIzY.js} +2 -2
- package/dist/esm/development/{component-shared-CLSmdnGU.js.map → component-shared-B3Q6mIzY.js.map} +1 -1
- package/dist/esm/development/config-CQLKpPRj.js +59 -0
- package/dist/esm/development/config-CQLKpPRj.js.map +1 -0
- package/dist/esm/development/config.js +2 -2
- package/dist/esm/development/{debug-BTLbgTPK.js → debug-C3HD8WcT.js} +288 -71
- package/dist/esm/development/debug-C3HD8WcT.js.map +1 -0
- package/dist/esm/development/debug.js +12 -10
- package/dist/esm/development/index.js +18 -17
- package/dist/esm/development/react/index.js +400 -53
- package/dist/esm/development/react/index.js.map +1 -1
- package/dist/esm/development/react/index.server.js +2 -2
- package/dist/esm/development/react/index.server.js.map +1 -1
- package/dist/esm/development/react/server.js +1 -1
- package/dist/esm/development/{snapshot-CkndI4Hh.js → snapshot-CCKlBy-y.js} +7 -5
- package/dist/esm/development/snapshot-CCKlBy-y.js.map +1 -0
- package/dist/esm/development/transform/index.js +5 -2
- package/dist/esm/development/transform/index.js.map +1 -1
- package/dist/esm/development/utils.js +38 -6
- package/dist/esm/development/utils.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/internals/async.d.ts.map +1 -1
- package/dist/esm/internals/config.d.ts +40 -0
- package/dist/esm/internals/config.d.ts.map +1 -1
- package/dist/esm/internals/lease.d.ts +30 -0
- package/dist/esm/internals/lease.d.ts.map +1 -0
- package/dist/esm/internals/reactive.d.ts +18 -1
- package/dist/esm/internals/reactive.d.ts.map +1 -1
- package/dist/esm/internals/scheduling.d.ts +2 -1
- package/dist/esm/internals/scheduling.d.ts.map +1 -1
- package/dist/esm/internals/utils/hash.d.ts +7 -0
- package/dist/esm/internals/utils/hash.d.ts.map +1 -1
- package/dist/esm/internals/utils/snapshot.d.ts +2 -0
- package/dist/esm/internals/utils/snapshot.d.ts.map +1 -1
- package/dist/esm/internals/watch.d.ts +3 -2
- package/dist/esm/internals/watch.d.ts.map +1 -1
- package/dist/esm/production/{component-shared-Dva0S5e3.js → component-shared-CycOXiis.js} +2 -2
- package/dist/esm/production/{component-shared-Dva0S5e3.js.map → component-shared-CycOXiis.js.map} +1 -1
- package/dist/esm/production/config-BhtwQYAN.js +53 -0
- package/dist/esm/production/config-BhtwQYAN.js.map +1 -0
- package/dist/esm/production/config.js +2 -2
- package/dist/esm/production/{contexts-FxCndlvf.js → contexts-ry5lvNSx.js} +291 -74
- package/dist/esm/production/contexts-ry5lvNSx.js.map +1 -0
- package/dist/esm/production/debug.js +3 -1
- package/dist/esm/production/index.js +19 -18
- package/dist/esm/production/react/index.js +400 -53
- package/dist/esm/production/react/index.js.map +1 -1
- package/dist/esm/production/react/index.server.js +2 -2
- package/dist/esm/production/react/index.server.js.map +1 -1
- package/dist/esm/production/react/server.js +1 -1
- package/dist/esm/production/{snapshot-CdCaJJ0L.js → snapshot-1d_HVP3L.js} +7 -5
- package/dist/esm/production/snapshot-1d_HVP3L.js.map +1 -0
- package/dist/esm/production/transform/index.js +5 -2
- package/dist/esm/production/transform/index.js.map +1 -1
- package/dist/esm/production/utils.js +39 -7
- package/dist/esm/production/utils.js.map +1 -1
- package/dist/esm/react/async-component.d.ts +10 -2
- package/dist/esm/react/async-component.d.ts.map +1 -1
- package/dist/esm/react/component-server.d.ts +6 -2
- package/dist/esm/react/component-server.d.ts.map +1 -1
- package/dist/esm/react/component.d.ts +5 -2
- package/dist/esm/react/component.d.ts.map +1 -1
- package/dist/esm/react/delivery.d.ts +107 -0
- package/dist/esm/react/delivery.d.ts.map +1 -0
- package/dist/esm/react/index.d.ts +3 -2
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/pause-signals-context.d.ts +16 -2
- package/dist/esm/react/pause-signals-context.d.ts.map +1 -1
- package/dist/esm/react/props-hash.d.ts +20 -0
- package/dist/esm/react/props-hash.d.ts.map +1 -0
- package/dist/esm/react/use-reactive.d.ts +6 -3
- package/dist/esm/react/use-reactive.d.ts.map +1 -1
- package/dist/esm/transform/async.d.ts.map +1 -1
- package/dist/esm/transform/callback.d.ts.map +1 -1
- package/dist/esm/transform/promise.d.ts.map +1 -1
- package/dist/esm/transform/use-reactive.d.ts.map +1 -1
- package/dist/esm/transform/utils.d.ts +1 -1
- package/dist/esm/transform/utils.d.ts.map +1 -1
- package/dist/esm/types.d.ts +20 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +17 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/development/config-B0MtLBgx.js +0 -21
- package/dist/cjs/development/config-B0MtLBgx.js.map +0 -1
- package/dist/cjs/development/debug-C46WDxhL.js.map +0 -1
- package/dist/cjs/development/snapshot-CbZ6IH3B.js.map +0 -1
- package/dist/cjs/production/config-B0MtLBgx.js +0 -21
- package/dist/cjs/production/config-B0MtLBgx.js.map +0 -1
- package/dist/cjs/production/contexts-CM3QLfV8.js.map +0 -1
- package/dist/cjs/production/snapshot-DWwH7_9y.js.map +0 -1
- package/dist/esm/development/config-CPQL7hX-.js +0 -22
- package/dist/esm/development/config-CPQL7hX-.js.map +0 -1
- package/dist/esm/development/debug-BTLbgTPK.js.map +0 -1
- package/dist/esm/development/snapshot-CkndI4Hh.js.map +0 -1
- package/dist/esm/production/config-CPQL7hX-.js +0 -22
- package/dist/esm/production/config-CPQL7hX-.js.map +0 -1
- package/dist/esm/production/contexts-FxCndlvf.js.map +0 -1
- package/dist/esm/production/snapshot-CdCaJJ0L.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# signalium
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- c4449de: Release the React render-path changes as a major version. They change behavior that existing apps can observe:
|
|
8
|
+
|
|
9
|
+
- `component()` props are treated as immutable, the same contract as `React.memo`. When every prop is identical (by `Object.is`) to the previous render, the previous props hash is reused, and React element props are hashed by identity. A plain object, array, `Map`, `Set` or `Date` mutated in place and passed again no longer re-renders a `component()` child; pass a new value instead. Freshly created element children (`children={<X />}`) re-render the child on every parent render.
|
|
10
|
+
- `component()` mounts in one render instead of two.
|
|
11
|
+
- Watches taken during render are leases. A render React discards (an interrupted transition, a mount that suspends, a StrictMode double render) releases its relays after `renderLeaseTtl` (default 10 s) instead of keeping them active for the rest of the session. `useReactive` and `useReactiveShallow` readers suspended by React 19's `use()` for longer than the TTL lose their lease, so their relays may deactivate and restart when React retries the render.
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- d96ce16: `component()` no longer walks React element trees when hashing props. A React element is a plain object, so the structural props hash recursed through `props` and every descendant element — for a component taking `children`, that walk dominated each render, and reached into whatever the child elements' own props pointed at. Element-valued props are now hashed by identity: nothing reads through an element, and `hashValue` already hashes by identity any object whose prototype it doesn't recognise — elements only escaped that because they happen to be plain objects.
|
|
16
|
+
|
|
17
|
+
Every other prop keeps its structural hash, so a new-but-equivalent object or array still reuses the previous render, and a value whose class has a `registerCustomHash` function (an `Array` subclass included) is still hashed by it. Applies to async `component()` too, which hashed props the same way.
|
|
18
|
+
|
|
19
|
+
**Behaviour change:** a freshly-created children tree that is structurally identical to the previous one no longer reuses the memoized render, so such a component re-renders where it used to be skipped. Nothing can go stale as a result — React skips a subtree whose element is referentially identical, so a re-render was never what made an update visible. If a component relied on being skipped for a fresh-but-equal `children` (or other element) prop, hoist the element or memoize it so the same element is passed again.
|
|
20
|
+
|
|
21
|
+
- c4449de: `component()` no longer hashes its props when every prop is identical (by `Object.is`) to the previous render's — the common case of a parent re-rendering without changing anything — and reuses the previous hash instead. A shallow identity check costs a fraction of the structural hash (6–30x less for typical props in a micro-benchmark).
|
|
22
|
+
|
|
23
|
+
**Behaviour change:** props are now treated as immutable, the same contract as `React.memo` and the React Compiler: a plain object, array, `Map`, `Set` or `Date` prop mutated in place and passed again under the same identity no longer re-renders the component (the structural hash used to notice such a mutation). Pass a new object, or read changing data from a signal inside the component. Applies to async `component()` too.
|
|
24
|
+
|
|
25
|
+
- 1b46c55: Export `snapshotArray`, `snapshotPlainObject` and the `SnapshotFn` type from `signalium/utils`.
|
|
26
|
+
- c4449de: New opt-in `'state'` delivery mode for React readers. By default `component()`, `useReactive` and `useReactiveShallow` reach React through `useSyncExternalStore`, which always renders at SyncLane and throws away any in-progress transition render; with live data ticking underneath, a transition only finishes at React's ~5 s expiry. In `'state'` mode a reader reads its signal directly during render, subscribes on commit (claiming its render lease), and delivers changes with a default-priority `setState`, coalesced per reader and flushed for all readers in one `runBatch` on a microtask (`scheduleReactDelivery`). Default-priority updates wait for an in-progress transition instead of restarting it. A change between render and subscribe, or during a delivered render, is caught by a version check on commit, which first re-validates the signal so a change it missed while unwatched (an expired render lease) is not lost. The subscription lives as long as a `useSyncExternalStore` one would: a Suspense hide (react-freeze) keeps it and its relays, `<Activity mode="hidden">` and unmount release it. A hidden reader is not rendered, unless its own render is what suspended, so it can still recover when a change no longer needs the pending data; when it is revealed (including the first reveal of content prerendered inside a hidden `<Activity>`) it re-validates and, if anything changed since it rendered, renders before that commit paints. A first mount delivers a change between its render and its commit at default priority instead.
|
|
27
|
+
|
|
28
|
+
Enable globally with `setConfig({ reactDelivery: 'state' })` (the default stays `'sync'`), or per reader with `component(fn, { delivery })`, `useReactive(fn, { delivery })` and `useReactiveShallow(fn, { delivery })`. The Babel preset memoizes the thunk of a `useReactive` / `useReactiveShallow` / `useReactiveDeep` call that passes options too (it used to skip any call with a second argument, so such a call created a new signal on every render); the options argument is left as written. The mode is fixed when a reader mounts. Trade-off: updates are consistent per delivery batch, but a reader that mounts while a delivery is pending can show a newer value than its already-mounted siblings for one commit; readers whose values must stay correlated keep `'sync'`.
|
|
29
|
+
|
|
30
|
+
- 98ef30c: React render-time watches are now leases. `component()`, `useReactive` and `useReactiveShallow` watch their signal while rendering so relays read during the render activate, but React can discard a render (an interrupted transition, a mount that suspends, a StrictMode double render) without ever subscribing or running an effect, and the watch — with every relay under it — stayed active for the rest of the session. The render-time watch is now a provisional lease: the store subscription React makes on commit claims it (keeping the relays warm, with no restart), and a lease nobody claims is released after `renderLeaseTtl` (default 10 s, configurable via `setConfig`; a lease lives between one and two TTLs). A render that reads a still-leased signal again extends the lease. A `component()` render that suspends keeps its lease until the thrown thenable settles; one suspended by React 19's `use()` (whose thenable React keeps to itself) keeps it until React retries or commits it, or for 30 TTLs if React abandons it. `useReactive` / `useReactiveShallow` cannot see a `use()` that suspends the component after they return, so their leases follow the TTL. Committed components behave exactly as before.
|
|
31
|
+
|
|
32
|
+
`PauseSignalsProvider` pausing is counted per reader. A signal stays watched while any of its subscribers is unpaused, so a `useReactiveShallow` signal shared with readers outside a paused provider keeps updating for them, and an unpaused reader that suspends on such a signal still starts its relays. Readers register on commit, before they subscribe, so un-pausing no longer re-watches a signal from a discarded render; a provider also tracks render leases taken under it, so pausing reaches a mount that suspended before committing.
|
|
33
|
+
|
|
34
|
+
New: `retain(fn, { ttl })` keeps `fn`'s relays/queries watched for `ttl` ms (or until the returned release function is called) — an app-level lease for prefetching or keeping a hidden surface warm. The Babel preset transforms async callbacks passed to it. `ttl: Infinity` retains until released, and a `ttl` above 2^31 - 1 ms (the longest timer delay) is clamped to it. `setConfig({ renderLeaseTtl })` clamps values above that limit and ignores non-positive ones, warning in development. `signalium/debug` exports `getRenderLeaseCount()` and `releaseRenderLeases()`, which both include leases pinned for a suspended render.
|
|
35
|
+
|
|
36
|
+
## 3.0.3
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- bad3258: `RelayHooks.deactivate` now receives a `DeactivateOptions` object with an `isPausing` flag, distinguishing a temporary pause (e.g. `PauseSignalsProvider`) from a genuine cleanup. Relays can use it to skip destructive work like garbage collection while pausing. `DeactivateOptions` is exported.
|
|
41
|
+
|
|
3
42
|
## 3.0.2
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const debug = require("./debug-
|
|
2
|
+
const debug = require("./debug-CbAX7VeM.js");
|
|
3
3
|
function isGeneratorFunction(fn) {
|
|
4
4
|
return typeof fn === "function" && fn.constructor?.name === "GeneratorFunction";
|
|
5
5
|
}
|
|
@@ -30,4 +30,4 @@ exports.createServerAsyncComponentWrapper = createServerAsyncComponentWrapper;
|
|
|
30
30
|
exports.createServerSyncComponentWrapper = createServerSyncComponentWrapper;
|
|
31
31
|
exports.isAsyncFunctionWithoutTransform = isAsyncFunctionWithoutTransform;
|
|
32
32
|
exports.isGeneratorFunction = isGeneratorFunction;
|
|
33
|
-
//# sourceMappingURL=component-shared-
|
|
33
|
+
//# sourceMappingURL=component-shared-BjwFh5Jq.js.map
|
package/dist/cjs/development/{component-shared-Cug2Y5YZ.js.map → component-shared-BjwFh5Jq.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-shared-
|
|
1
|
+
{"version":3,"file":"component-shared-BjwFh5Jq.js","sources":["../../../.tsc-out/react/component-shared.js"],"sourcesContent":["import { getCurrentConsumer, setCurrentConsumer } from '../internals/consumer.js';\nimport { getCurrentScope } from '../internals/contexts.js';\nimport { createReactiveSignal } from '../internals/reactive.js';\nimport { generatorResultToPromiseWithConsumer } from '../internals/generators.js';\nexport function isGeneratorFunction(fn) {\n return (typeof fn === 'function' && fn.constructor?.name === 'GeneratorFunction');\n}\nexport function isAsyncFunctionWithoutTransform(fn) {\n return typeof fn === 'function' && fn.constructor?.name === 'AsyncFunction';\n}\n/**\n * Wrap a Babel-transformed async generator in a real `async function` that drives it\n * with {@link generatorResultToPromiseWithConsumer}. Used on the server (RSC + SSR)\n * where hooks-based Suspense replay is not appropriate.\n */\nexport function createServerAsyncComponentWrapper(fn) {\n return async function (props) {\n const scope = getCurrentScope();\n const owned = createReactiveSignal({ compute: () => null, equals: () => true, isRelay: false, tracer: undefined }, [], undefined, scope);\n return generatorResultToPromiseWithConsumer(fn(props), owned);\n };\n}\n/**\n * Wrap a sync render function with consumer/scope tracking. Used by the server\n * `component()` for non-generator definitions.\n */\nexport function createServerSyncComponentWrapper(fn) {\n return function (props) {\n const scope = getCurrentScope();\n const owned = createReactiveSignal({ compute: () => null, equals: () => true, isRelay: false, tracer: undefined }, [], undefined, scope);\n const prevConsumer = getCurrentConsumer();\n try {\n setCurrentConsumer(owned);\n return fn(props);\n }\n finally {\n setCurrentConsumer(prevConsumer);\n }\n };\n}\n"],"names":["getCurrentScope","createReactiveSignal","generatorResultToPromiseWithConsumer","getCurrentConsumer","setCurrentConsumer"],"mappings":";;AAIO,SAAS,oBAAoB,IAAI;AACpC,SAAQ,OAAO,OAAO,cAAc,GAAG,aAAa,SAAS;AACjE;AACO,SAAS,gCAAgC,IAAI;AAChD,SAAO,OAAO,OAAO,cAAc,GAAG,aAAa,SAAS;AAChE;AAMO,SAAS,kCAAkC,IAAI;AAClD,SAAO,eAAgB,OAAO;AAC1B,UAAM,QAAQA,MAAAA,gBAAe;AAC7B,UAAM,QAAQC,MAAAA,qBAAqB,EAAE,SAAS,MAAM,MAAM,QAAQ,MAAM,MAAM,SAAS,OAAO,QAAQ,OAAS,GAAI,CAAA,GAAI,QAAW,KAAK;AACvI,WAAOC,2CAAqC,GAAG,KAAK,GAAG,KAAK;AAAA,EAChE;AACJ;AAKO,SAAS,iCAAiC,IAAI;AACjD,SAAO,SAAU,OAAO;AACpB,UAAM,QAAQF,MAAAA,gBAAe;AAC7B,UAAM,QAAQC,MAAAA,qBAAqB,EAAE,SAAS,MAAM,MAAM,QAAQ,MAAM,MAAM,SAAS,OAAO,QAAQ,OAAS,GAAI,CAAA,GAAI,QAAW,KAAK;AACvI,UAAM,eAAeE,MAAAA,mBAAkB;AACvC,QAAI;AACAC,YAAAA,mBAAmB,KAAK;AACxB,aAAO,GAAG,KAAK;AAAA,IACnB,UACR;AACYA,YAAAA,mBAAmB,YAAY;AAAA,IACnC;AAAA,EACJ;AACJ;;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
let _scheduleFlush = (flushWatchers) => {
|
|
3
|
+
setTimeout(() => {
|
|
4
|
+
flushWatchers();
|
|
5
|
+
}, 0);
|
|
6
|
+
};
|
|
7
|
+
let _runBatch = (fn) => fn();
|
|
8
|
+
const DEFAULT_RENDER_LEASE_TTL = 1e4;
|
|
9
|
+
let _renderLeaseTtl = DEFAULT_RENDER_LEASE_TTL;
|
|
10
|
+
const MAX_TIMEOUT = 2 ** 31 - 1;
|
|
11
|
+
function validateRenderLeaseTtl(ttl) {
|
|
12
|
+
if (typeof ttl !== "number" || Number.isNaN(ttl) || ttl <= 0) {
|
|
13
|
+
{
|
|
14
|
+
console.warn(`signalium: setConfig({ renderLeaseTtl: ${String(ttl)} }) ignored; it must be a positive number of milliseconds.`);
|
|
15
|
+
}
|
|
16
|
+
return _renderLeaseTtl;
|
|
17
|
+
}
|
|
18
|
+
if (ttl > MAX_TIMEOUT) {
|
|
19
|
+
{
|
|
20
|
+
console.warn(`signalium: setConfig({ renderLeaseTtl: ${String(ttl)} }) clamped to ${MAX_TIMEOUT} ms, the longest timer delay.`);
|
|
21
|
+
}
|
|
22
|
+
return MAX_TIMEOUT;
|
|
23
|
+
}
|
|
24
|
+
return ttl;
|
|
25
|
+
}
|
|
26
|
+
let _reactDelivery = "sync";
|
|
27
|
+
const resolvedPromise = Promise.resolve();
|
|
28
|
+
let _scheduleReactDelivery = (fn) => {
|
|
29
|
+
resolvedPromise.then(fn);
|
|
30
|
+
};
|
|
31
|
+
function setConfig(cfg) {
|
|
32
|
+
_scheduleFlush = cfg.scheduleFlush ?? _scheduleFlush;
|
|
33
|
+
_runBatch = cfg.runBatch ?? _runBatch;
|
|
34
|
+
if (cfg.renderLeaseTtl !== void 0) {
|
|
35
|
+
_renderLeaseTtl = validateRenderLeaseTtl(cfg.renderLeaseTtl);
|
|
36
|
+
}
|
|
37
|
+
_reactDelivery = cfg.reactDelivery ?? _reactDelivery;
|
|
38
|
+
_scheduleReactDelivery = cfg.scheduleReactDelivery ?? _scheduleReactDelivery;
|
|
39
|
+
}
|
|
40
|
+
const scheduleFlush = (fn) => {
|
|
41
|
+
_scheduleFlush(fn);
|
|
42
|
+
};
|
|
43
|
+
const runBatch = (fn) => {
|
|
44
|
+
_runBatch(fn);
|
|
45
|
+
};
|
|
46
|
+
const getRenderLeaseTtl = () => _renderLeaseTtl;
|
|
47
|
+
const getReactDelivery = () => _reactDelivery;
|
|
48
|
+
const scheduleReactDelivery = (fn) => {
|
|
49
|
+
_scheduleReactDelivery(fn);
|
|
50
|
+
};
|
|
51
|
+
exports.MAX_TIMEOUT = MAX_TIMEOUT;
|
|
52
|
+
exports.getReactDelivery = getReactDelivery;
|
|
53
|
+
exports.getRenderLeaseTtl = getRenderLeaseTtl;
|
|
54
|
+
exports.runBatch = runBatch;
|
|
55
|
+
exports.scheduleFlush = scheduleFlush;
|
|
56
|
+
exports.scheduleReactDelivery = scheduleReactDelivery;
|
|
57
|
+
exports.setConfig = setConfig;
|
|
58
|
+
//# sourceMappingURL=config-D6wyrhrW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-D6wyrhrW.js","sources":["../../../.tsc-out/internals/config.js"],"sourcesContent":["let _scheduleFlush = flushWatchers => {\n setTimeout(() => {\n flushWatchers();\n }, 0);\n};\nlet _runBatch = fn => fn();\n/** Default render lease TTL (ms). It must outlive a transition render, which React caps at 5 s. */\nexport const DEFAULT_RENDER_LEASE_TTL = 10_000;\nlet _renderLeaseTtl = DEFAULT_RENDER_LEASE_TTL;\n/** The longest `setTimeout` delay (2^31 - 1 ms); longer ones fire immediately. */\nexport const MAX_TIMEOUT = 2 ** 31 - 1;\nfunction validateRenderLeaseTtl(ttl) {\n if (typeof ttl !== 'number' || Number.isNaN(ttl) || ttl <= 0) {\n if (IS_DEV) {\n console.warn(`signalium: setConfig({ renderLeaseTtl: ${String(ttl)} }) ignored; it must be a positive number of milliseconds.`);\n }\n return _renderLeaseTtl;\n }\n if (ttl > MAX_TIMEOUT) {\n if (IS_DEV) {\n console.warn(`signalium: setConfig({ renderLeaseTtl: ${String(ttl)} }) clamped to ${MAX_TIMEOUT} ms, the longest timer delay.`);\n }\n return MAX_TIMEOUT;\n }\n return ttl;\n}\nlet _reactDelivery = 'sync';\nconst resolvedPromise = Promise.resolve();\nlet _scheduleReactDelivery = fn => {\n resolvedPromise.then(fn);\n};\nexport function setConfig(cfg) {\n _scheduleFlush = cfg.scheduleFlush ?? _scheduleFlush;\n _runBatch = cfg.runBatch ?? _runBatch;\n if (cfg.renderLeaseTtl !== undefined) {\n _renderLeaseTtl = validateRenderLeaseTtl(cfg.renderLeaseTtl);\n }\n _reactDelivery = cfg.reactDelivery ?? _reactDelivery;\n _scheduleReactDelivery = cfg.scheduleReactDelivery ?? _scheduleReactDelivery;\n}\nexport const scheduleFlush = (fn) => {\n _scheduleFlush(fn);\n};\nexport const runBatch = (fn) => {\n _runBatch(fn);\n};\nexport const getRenderLeaseTtl = () => _renderLeaseTtl;\nexport const getReactDelivery = () => _reactDelivery;\nexport const scheduleReactDelivery = (fn) => {\n _scheduleReactDelivery(fn);\n};\n"],"names":[],"mappings":";AAAA,IAAI,iBAAiB,CAAA,kBAAiB;AAClC,aAAW,MAAM;AACb,kBAAA;AAAA,EACJ,GAAG,CAAC;AACR;AACA,IAAI,YAAY,QAAM,GAAA;AAEf,MAAM,2BAA2B;AACxC,IAAI,kBAAkB;AAEf,MAAM,cAAc,KAAK,KAAK;AACrC,SAAS,uBAAuB,KAAK;AACjC,MAAI,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG,KAAK,OAAO,GAAG;AAC9C;AACR,cAAQ,KAAK,0CAA0C,OAAO,GAAG,CAAC,4DAA4D;AAAA,IAClI;AACA,WAAO;AAAA,EACX;AACA,MAAI,MAAM,aAAa;AACP;AACR,cAAQ,KAAK,0CAA0C,OAAO,GAAG,CAAC,kBAAkB,WAAW,+BAA+B;AAAA,IAClI;AACA,WAAO;AAAA,EACX;AACA,SAAO;AACX;AACA,IAAI,iBAAiB;AACrB,MAAM,kBAAkB,QAAQ,QAAA;AAChC,IAAI,yBAAyB,CAAA,OAAM;AAC/B,kBAAgB,KAAK,EAAE;AAC3B;AACO,SAAS,UAAU,KAAK;AAC3B,mBAAiB,IAAI,iBAAiB;AACtC,cAAY,IAAI,YAAY;AAC5B,MAAI,IAAI,mBAAmB,QAAW;AAClC,sBAAkB,uBAAuB,IAAI,cAAc;AAAA,EAC/D;AACA,mBAAiB,IAAI,iBAAiB;AACtC,2BAAyB,IAAI,yBAAyB;AAC1D;AACO,MAAM,gBAAgB,CAAC,OAAO;AACjC,iBAAe,EAAE;AACrB;AACO,MAAM,WAAW,CAAC,OAAO;AAC5B,YAAU,EAAE;AAChB;AACO,MAAM,oBAAoB,MAAM;AAChC,MAAM,mBAAmB,MAAM;AAC/B,MAAM,wBAAwB,CAAC,OAAO;AACzC,yBAAuB,EAAE;AAC7B;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const config = require("./config-
|
|
2
|
+
const config = require("./config-D6wyrhrW.js");
|
|
3
3
|
let UNKNOWN_SIGNAL_ID = 0;
|
|
4
4
|
const UNKNOWN_SIGNAL_NAMES = /* @__PURE__ */ new Map();
|
|
5
5
|
function getUnknownSignalFnName(fn) {
|
|
@@ -428,12 +428,12 @@ function watchSignal(signal2) {
|
|
|
428
428
|
}
|
|
429
429
|
activateSignal(signal2);
|
|
430
430
|
}
|
|
431
|
-
function unwatchSignal(signal2) {
|
|
431
|
+
function unwatchSignal(signal2, options = {}) {
|
|
432
432
|
const { watchCount } = signal2;
|
|
433
433
|
const newWatchCount = Math.max(watchCount - 1, 0);
|
|
434
434
|
signal2.watchCount = newWatchCount;
|
|
435
435
|
if (newWatchCount === 0) {
|
|
436
|
-
scheduleDeactivate(signal2);
|
|
436
|
+
scheduleDeactivate(signal2, options);
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
function activateSignal(signal2) {
|
|
@@ -443,22 +443,22 @@ function activateSignal(signal2) {
|
|
|
443
443
|
checkSignal(signal2);
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
|
-
function deactivateSignal(signal2) {
|
|
446
|
+
function deactivateSignal(signal2, options = {}) {
|
|
447
447
|
signal2._isActive = false;
|
|
448
448
|
for (const dep of signal2.deps.keys()) {
|
|
449
449
|
const newWatchCount = Math.max(dep.watchCount - 1, 0);
|
|
450
450
|
dep.watchCount = newWatchCount;
|
|
451
451
|
if (newWatchCount === 0) {
|
|
452
|
-
deactivateSignal(dep);
|
|
452
|
+
deactivateSignal(dep, options);
|
|
453
453
|
}
|
|
454
454
|
}
|
|
455
455
|
if (isRelay(signal2)) {
|
|
456
|
-
signal2._value?.();
|
|
456
|
+
signal2._value?.(options);
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
459
|
let PENDING_PULLS = /* @__PURE__ */ new Set();
|
|
460
460
|
let PENDING_ASYNC_PULLS = [];
|
|
461
|
-
let PENDING_DEACTIVE = /* @__PURE__ */ new
|
|
461
|
+
let PENDING_DEACTIVE = /* @__PURE__ */ new Map();
|
|
462
462
|
let PENDING_LISTENERS = [];
|
|
463
463
|
let PENDING_TRACERS = [];
|
|
464
464
|
const microtask = () => Promise.resolve();
|
|
@@ -482,8 +482,9 @@ const scheduleAsyncPull = (signal2) => {
|
|
|
482
482
|
PENDING_ASYNC_PULLS.push(signal2);
|
|
483
483
|
scheduleFlush();
|
|
484
484
|
};
|
|
485
|
-
const scheduleDeactivate = (signal2) => {
|
|
486
|
-
PENDING_DEACTIVE.
|
|
485
|
+
const scheduleDeactivate = (signal2, options = {}) => {
|
|
486
|
+
const existing = PENDING_DEACTIVE.get(signal2);
|
|
487
|
+
PENDING_DEACTIVE.set(signal2, existing === void 0 ? options : { isPausing: Boolean(existing.isPausing && options.isPausing) });
|
|
487
488
|
scheduleFlush();
|
|
488
489
|
};
|
|
489
490
|
const cancelDeactivate = (signal2) => {
|
|
@@ -518,8 +519,8 @@ const flushWatchers = async () => {
|
|
|
518
519
|
}
|
|
519
520
|
currentFlush = null;
|
|
520
521
|
config.runBatch(() => {
|
|
521
|
-
for (const signal2 of PENDING_DEACTIVE) {
|
|
522
|
-
deactivateSignal(signal2);
|
|
522
|
+
for (const [signal2, options] of PENDING_DEACTIVE) {
|
|
523
|
+
deactivateSignal(signal2, options);
|
|
523
524
|
}
|
|
524
525
|
PENDING_DEACTIVE.clear();
|
|
525
526
|
for (const signal2 of PENDING_LISTENERS) {
|
|
@@ -1299,11 +1300,11 @@ function createRelay(activate, scope, opts) {
|
|
|
1299
1300
|
const p = new ReactivePromiseImpl();
|
|
1300
1301
|
let active = false;
|
|
1301
1302
|
let currentSub;
|
|
1302
|
-
const unsubscribe = () => {
|
|
1303
|
+
const unsubscribe = (options) => {
|
|
1303
1304
|
if (typeof currentSub === "function") {
|
|
1304
1305
|
currentSub();
|
|
1305
1306
|
} else if (currentSub !== void 0) {
|
|
1306
|
-
currentSub.deactivate?.();
|
|
1307
|
+
currentSub.deactivate?.(options);
|
|
1307
1308
|
}
|
|
1308
1309
|
const signal2 = p["_signal"];
|
|
1309
1310
|
signal2.subs = /* @__PURE__ */ new Map();
|
|
@@ -1603,32 +1604,43 @@ function hashNumber(num, seed = 0) {
|
|
|
1603
1604
|
h ^= h >>> 16;
|
|
1604
1605
|
return h >>> 0;
|
|
1605
1606
|
}
|
|
1606
|
-
function
|
|
1607
|
-
let h = ARRAY;
|
|
1607
|
+
function mixHash(h, k) {
|
|
1608
1608
|
const c1 = 3432918353;
|
|
1609
1609
|
const c2 = 461845907;
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1610
|
+
const n = 3864292196;
|
|
1611
|
+
k = imul(k, c1);
|
|
1612
|
+
k = k << 15 | k >>> 17;
|
|
1613
|
+
k = imul(k, c2);
|
|
1614
|
+
h ^= k;
|
|
1615
|
+
h = h << 13 | h >>> 19;
|
|
1616
|
+
return imul(h, 5) + n | 0;
|
|
1617
|
+
}
|
|
1618
|
+
function finalizeHash(h, length) {
|
|
1619
|
+
const fmix1 = 2246822507;
|
|
1620
|
+
const fmix2 = 3266489909;
|
|
1621
|
+
h ^= length;
|
|
1620
1622
|
h ^= h >>> 16;
|
|
1621
|
-
h = imul(h,
|
|
1623
|
+
h = imul(h, fmix1);
|
|
1622
1624
|
h ^= h >>> 13;
|
|
1623
|
-
h = imul(h,
|
|
1625
|
+
h = imul(h, fmix2);
|
|
1624
1626
|
h ^= h >>> 16;
|
|
1625
1627
|
return h >>> 0;
|
|
1626
1628
|
}
|
|
1629
|
+
function hashArray(arr, seen) {
|
|
1630
|
+
let h = ARRAY_SEED;
|
|
1631
|
+
for (const item of arr) {
|
|
1632
|
+
h = mixHash(h, hashValue(item, seen));
|
|
1633
|
+
}
|
|
1634
|
+
return finalizeHash(h, arr.length);
|
|
1635
|
+
}
|
|
1627
1636
|
function hashObject(obj, seen) {
|
|
1637
|
+
return hashObjectKeys(obj, Object.keys(obj), seen);
|
|
1638
|
+
}
|
|
1639
|
+
function hashObjectKeys(obj, keys, seen) {
|
|
1640
|
+
const keyMultiplier = 2654435769;
|
|
1628
1641
|
let sum = OBJECT;
|
|
1629
|
-
const keys = Object.keys(obj);
|
|
1630
1642
|
for (const key of keys) {
|
|
1631
|
-
sum += imul(hashValue(key, seen),
|
|
1643
|
+
sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(obj[key], seen);
|
|
1632
1644
|
}
|
|
1633
1645
|
return sum >>> 0;
|
|
1634
1646
|
}
|
|
@@ -1640,9 +1652,10 @@ function hashSet(set, seen) {
|
|
|
1640
1652
|
return sum >>> 0;
|
|
1641
1653
|
}
|
|
1642
1654
|
function hashMap(map, seen) {
|
|
1655
|
+
const keyMultiplier = 2654435769;
|
|
1643
1656
|
let sum = MAP;
|
|
1644
1657
|
for (const [key, value] of map) {
|
|
1645
|
-
sum += imul(hashValue(key, seen),
|
|
1658
|
+
sum += imul(hashValue(key, seen), keyMultiplier) ^ hashValue(value, seen);
|
|
1646
1659
|
}
|
|
1647
1660
|
return sum >>> 0;
|
|
1648
1661
|
}
|
|
@@ -1681,7 +1694,7 @@ const FALSE = hashStr(
|
|
|
1681
1694
|
3
|
|
1682
1695
|
/* HashType.FALSE */
|
|
1683
1696
|
);
|
|
1684
|
-
const
|
|
1697
|
+
const ARRAY_SEED = hashStr(
|
|
1685
1698
|
"array",
|
|
1686
1699
|
7
|
|
1687
1700
|
/* HashType.ARRAY */
|
|
@@ -1845,6 +1858,95 @@ function stringifyValue(value) {
|
|
|
1845
1858
|
return getObjectId(value);
|
|
1846
1859
|
}
|
|
1847
1860
|
}
|
|
1861
|
+
let young = /* @__PURE__ */ new Set();
|
|
1862
|
+
let old = /* @__PURE__ */ new Set();
|
|
1863
|
+
let timer;
|
|
1864
|
+
const pinned = /* @__PURE__ */ new Map();
|
|
1865
|
+
const SUSPENDED_LEASE_HOLD_TTLS = 30;
|
|
1866
|
+
function armTimer() {
|
|
1867
|
+
timer = setTimeout(sweepLeases, config.getRenderLeaseTtl());
|
|
1868
|
+
timer.unref?.();
|
|
1869
|
+
}
|
|
1870
|
+
function sweepLeases() {
|
|
1871
|
+
timer = void 0;
|
|
1872
|
+
const expired = old;
|
|
1873
|
+
for (const signal2 of expired) {
|
|
1874
|
+
signal2._releaseLease();
|
|
1875
|
+
}
|
|
1876
|
+
expired.clear();
|
|
1877
|
+
old = young;
|
|
1878
|
+
young = expired;
|
|
1879
|
+
if (old.size > 0) {
|
|
1880
|
+
armTimer();
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
function addLease(signal2) {
|
|
1884
|
+
if (!pinned.delete(signal2)) {
|
|
1885
|
+
old.delete(signal2);
|
|
1886
|
+
}
|
|
1887
|
+
young.add(signal2);
|
|
1888
|
+
if (timer === void 0) {
|
|
1889
|
+
armTimer();
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
function removeLease(signal2) {
|
|
1893
|
+
if (!young.delete(signal2) && !old.delete(signal2)) {
|
|
1894
|
+
pinned.delete(signal2);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
function pinLease(signal2) {
|
|
1898
|
+
if (!signal2._isLeased) {
|
|
1899
|
+
return void 0;
|
|
1900
|
+
}
|
|
1901
|
+
young.delete(signal2);
|
|
1902
|
+
old.delete(signal2);
|
|
1903
|
+
const token = {};
|
|
1904
|
+
pinned.set(signal2, token);
|
|
1905
|
+
return token;
|
|
1906
|
+
}
|
|
1907
|
+
function unpinLease(signal2, token) {
|
|
1908
|
+
if (pinned.get(signal2) === token && signal2._isLeased) {
|
|
1909
|
+
addLease(signal2);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function holdLeaseUntilSettled(signal2, thenable) {
|
|
1913
|
+
const token = pinLease(signal2);
|
|
1914
|
+
if (token === void 0) {
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
const renew = () => unpinLease(signal2, token);
|
|
1918
|
+
thenable.then(renew, renew);
|
|
1919
|
+
}
|
|
1920
|
+
function holdSuspendedLease(signal2) {
|
|
1921
|
+
const token = pinLease(signal2);
|
|
1922
|
+
if (token === void 0) {
|
|
1923
|
+
return;
|
|
1924
|
+
}
|
|
1925
|
+
const hold = setTimeout(() => unpinLease(signal2, token), Math.min(config.getRenderLeaseTtl() * SUSPENDED_LEASE_HOLD_TTLS, config.MAX_TIMEOUT));
|
|
1926
|
+
hold.unref?.();
|
|
1927
|
+
}
|
|
1928
|
+
function releaseAbandonedAttempt(signal2) {
|
|
1929
|
+
const token = pinned.get(signal2);
|
|
1930
|
+
if (token !== void 0) {
|
|
1931
|
+
unpinLease(signal2, token);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
function releaseRenderLeases() {
|
|
1935
|
+
if (timer !== void 0) {
|
|
1936
|
+
clearTimeout(timer);
|
|
1937
|
+
timer = void 0;
|
|
1938
|
+
}
|
|
1939
|
+
const leases = [...old, ...young, ...pinned.keys()];
|
|
1940
|
+
old = /* @__PURE__ */ new Set();
|
|
1941
|
+
young = /* @__PURE__ */ new Set();
|
|
1942
|
+
pinned.clear();
|
|
1943
|
+
for (const signal2 of leases) {
|
|
1944
|
+
signal2._releaseLease();
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
function getRenderLeaseCount() {
|
|
1948
|
+
return young.size + old.size + pinned.size;
|
|
1949
|
+
}
|
|
1848
1950
|
let ID = 0;
|
|
1849
1951
|
function createReactiveDefinition(id, desc, compute, equals, isRelay2, paramKey, tracer) {
|
|
1850
1952
|
const def = {
|
|
@@ -1917,6 +2019,9 @@ class ReactiveSignal {
|
|
|
1917
2019
|
this.flags &= -33;
|
|
1918
2020
|
}
|
|
1919
2021
|
}
|
|
2022
|
+
get _isLeased() {
|
|
2023
|
+
return (this.flags & 128) !== 0;
|
|
2024
|
+
}
|
|
1920
2025
|
get _isLazy() {
|
|
1921
2026
|
return (this.flags & 64) !== 0;
|
|
1922
2027
|
}
|
|
@@ -1931,6 +2036,7 @@ class ReactiveSignal {
|
|
|
1931
2036
|
return this._listeners ?? (this._listeners = {
|
|
1932
2037
|
updatedAt: 0,
|
|
1933
2038
|
current: /* @__PURE__ */ new Map(),
|
|
2039
|
+
pausedReaders: 0,
|
|
1934
2040
|
cachedBoundAdd: this.addListener.bind(this)
|
|
1935
2041
|
});
|
|
1936
2042
|
}
|
|
@@ -1938,7 +2044,8 @@ class ReactiveSignal {
|
|
|
1938
2044
|
return getSignal(this);
|
|
1939
2045
|
}
|
|
1940
2046
|
addListener(listener, opts) {
|
|
1941
|
-
const
|
|
2047
|
+
const meta = this.listeners;
|
|
2048
|
+
const { current } = meta;
|
|
1942
2049
|
if (!current.has(listener)) {
|
|
1943
2050
|
let effective = listener;
|
|
1944
2051
|
if (opts?.skipInitial) {
|
|
@@ -1951,23 +2058,39 @@ class ReactiveSignal {
|
|
|
1951
2058
|
listener();
|
|
1952
2059
|
};
|
|
1953
2060
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
2061
|
+
const flags = this.flags;
|
|
2062
|
+
current.set(listener, effective);
|
|
2063
|
+
const unpaused = meta.pausedReaders < current.size;
|
|
2064
|
+
if ((flags & 16) === 0) {
|
|
2065
|
+
this.flags = flags | 16;
|
|
2066
|
+
} else if ((flags & 128) !== 0 && (unpaused || (flags & 256) === 0)) {
|
|
2067
|
+
this.flags = flags & -129;
|
|
2068
|
+
removeLease(this);
|
|
2069
|
+
}
|
|
2070
|
+
if (unpaused) {
|
|
2071
|
+
this._takeListenerWatch();
|
|
2072
|
+
} else {
|
|
2073
|
+
this._pauseListenerWatch();
|
|
1957
2074
|
}
|
|
1958
2075
|
if (this.watchCount > 0) {
|
|
1959
2076
|
schedulePull(this);
|
|
1960
2077
|
}
|
|
1961
|
-
current.set(listener, effective);
|
|
1962
2078
|
}
|
|
1963
2079
|
return () => {
|
|
1964
2080
|
if (current.has(listener)) {
|
|
1965
2081
|
current.delete(listener);
|
|
1966
2082
|
if (current.size === 0) {
|
|
2083
|
+
const flags = this.flags;
|
|
2084
|
+
if ((flags & 128) !== 0)
|
|
2085
|
+
return;
|
|
1967
2086
|
cancelPull(this);
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2087
|
+
this.flags = flags & -273;
|
|
2088
|
+
if ((flags & 256) !== 0) {
|
|
2089
|
+
unwatchSignal(this);
|
|
2090
|
+
}
|
|
2091
|
+
meta.updatedAt = 0;
|
|
2092
|
+
} else if (meta.pausedReaders >= current.size) {
|
|
2093
|
+
this._pauseListenerWatch();
|
|
1971
2094
|
}
|
|
1972
2095
|
}
|
|
1973
2096
|
};
|
|
@@ -1975,15 +2098,99 @@ class ReactiveSignal {
|
|
|
1975
2098
|
// This method is used in React hooks specifically. It returns a bound add method
|
|
1976
2099
|
// that is cached to avoid creating a new one on each call, and it eagerly sets
|
|
1977
2100
|
// the listener as watched so that relays that are accessed will be activated.
|
|
2101
|
+
//
|
|
2102
|
+
// The eager watch is a lease (see `lease.ts`): the commit's subscription claims it, and a
|
|
2103
|
+
// discarded render's lease expires. Each render of a still-leased signal extends it.
|
|
1978
2104
|
addListenerLazy(watch = true) {
|
|
1979
|
-
|
|
2105
|
+
const flags = this.flags;
|
|
2106
|
+
if ((flags & 16) === 0) {
|
|
1980
2107
|
if (watch) {
|
|
1981
2108
|
watchSignal(this);
|
|
2109
|
+
this.flags |= 16 | 128 | 256;
|
|
2110
|
+
} else {
|
|
2111
|
+
this.flags |= 16 | 128;
|
|
2112
|
+
}
|
|
2113
|
+
addLease(this);
|
|
2114
|
+
} else if ((flags & 128) !== 0 || watch && (flags & 256) === 0) {
|
|
2115
|
+
if (watch && (flags & 256) === 0) {
|
|
2116
|
+
watchSignal(this);
|
|
2117
|
+
this.flags |= 256;
|
|
1982
2118
|
}
|
|
1983
|
-
this.flags |=
|
|
2119
|
+
this.flags |= 128;
|
|
2120
|
+
addLease(this);
|
|
1984
2121
|
}
|
|
1985
2122
|
return this.listeners.cachedBoundAdd;
|
|
1986
2123
|
}
|
|
2124
|
+
/** Drops the listener watch; listeners stay subscribed. */
|
|
2125
|
+
_pauseWatch() {
|
|
2126
|
+
const flags = this.flags;
|
|
2127
|
+
if ((flags & 256) !== 0) {
|
|
2128
|
+
this.flags = flags & -257;
|
|
2129
|
+
unwatchSignal(this, { isPausing: true });
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
/** Retakes the listener watch, pulling changes missed while unwatched. */
|
|
2133
|
+
_resumeWatch() {
|
|
2134
|
+
if ((this.flags & 16) !== 0 && this._takeListenerWatch()) {
|
|
2135
|
+
schedulePull(this);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
_takeListenerWatch() {
|
|
2139
|
+
if ((this.flags & 256) !== 0) {
|
|
2140
|
+
return false;
|
|
2141
|
+
}
|
|
2142
|
+
watchSignal(this);
|
|
2143
|
+
this.flags |= 256;
|
|
2144
|
+
return true;
|
|
2145
|
+
}
|
|
2146
|
+
/** `deferred` reconciles in a microtask, for a reader that unregisters before it unsubscribes. */
|
|
2147
|
+
_addPausedReaders(delta, deferred = false) {
|
|
2148
|
+
this.listeners.pausedReaders += delta;
|
|
2149
|
+
if (deferred) {
|
|
2150
|
+
queueMicrotask(() => this._reconcilePausedReaders());
|
|
2151
|
+
} else {
|
|
2152
|
+
this._reconcilePausedReaders();
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
_reconcilePausedReaders() {
|
|
2156
|
+
const { current, pausedReaders } = this.listeners;
|
|
2157
|
+
if (current.size === 0)
|
|
2158
|
+
return;
|
|
2159
|
+
if (pausedReaders < current.size) {
|
|
2160
|
+
this._resumeWatch();
|
|
2161
|
+
} else {
|
|
2162
|
+
this._pauseListenerWatch();
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
/** Pauses for the listeners' sake; an unclaimed render lease's watch belongs to its render. */
|
|
2166
|
+
_pauseListenerWatch() {
|
|
2167
|
+
if ((this.flags & 128) === 0) {
|
|
2168
|
+
this._pauseWatch();
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
/** Releases an unclaimed render lease; a no-op once claimed. */
|
|
2172
|
+
_releaseLease() {
|
|
2173
|
+
const flags = this.flags;
|
|
2174
|
+
if ((flags & 128) === 0) {
|
|
2175
|
+
return;
|
|
2176
|
+
}
|
|
2177
|
+
const meta = this._listeners;
|
|
2178
|
+
if (meta !== null && meta.current.size > 0) {
|
|
2179
|
+
this.flags = flags & -129;
|
|
2180
|
+
if (meta.pausedReaders >= meta.current.size) {
|
|
2181
|
+
this._pauseWatch();
|
|
2182
|
+
}
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
this.flags = flags & -401;
|
|
2186
|
+
if (meta !== null) {
|
|
2187
|
+
meta.updatedAt = 0;
|
|
2188
|
+
}
|
|
2189
|
+
cancelPull(this);
|
|
2190
|
+
if ((flags & 256) !== 0) {
|
|
2191
|
+
unwatchSignal(this);
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
1987
2194
|
}
|
|
1988
2195
|
const runListeners = (signal2) => {
|
|
1989
2196
|
const { listeners } = signal2;
|
|
@@ -2123,11 +2330,13 @@ const getScopeOwner = (obj) => {
|
|
|
2123
2330
|
}
|
|
2124
2331
|
return scope;
|
|
2125
2332
|
};
|
|
2333
|
+
exports.ARRAY_SEED = ARRAY_SEED;
|
|
2126
2334
|
exports.ReactivePromise = ReactivePromise;
|
|
2127
2335
|
exports.SignalScope = SignalScope;
|
|
2128
2336
|
exports.Tracer = Tracer;
|
|
2129
2337
|
exports.VisualizerNode = VisualizerNode;
|
|
2130
2338
|
exports.callback = callback;
|
|
2339
|
+
exports.checkSignal = checkSignal;
|
|
2131
2340
|
exports.clearGlobalContexts = clearGlobalContexts;
|
|
2132
2341
|
exports.context = context;
|
|
2133
2342
|
exports.createReactiveDefinition = createReactiveDefinition;
|
|
@@ -2136,24 +2345,32 @@ exports.createRelay = createRelay;
|
|
|
2136
2345
|
exports.createTask = createTask;
|
|
2137
2346
|
exports.createTracer = createTracer;
|
|
2138
2347
|
exports.createTracerFromId = createTracerFromId;
|
|
2348
|
+
exports.finalizeHash = finalizeHash;
|
|
2139
2349
|
exports.generatorResultToPromiseWithConsumer = generatorResultToPromiseWithConsumer;
|
|
2140
2350
|
exports.getContext = getContext;
|
|
2141
2351
|
exports.getCurrentConsumer = getCurrentConsumer;
|
|
2142
2352
|
exports.getCurrentScope = getCurrentScope;
|
|
2143
2353
|
exports.getGlobalScope = getGlobalScope;
|
|
2354
|
+
exports.getObjectHash = getObjectHash;
|
|
2355
|
+
exports.getRenderLeaseCount = getRenderLeaseCount;
|
|
2144
2356
|
exports.getScopeOwner = getScopeOwner;
|
|
2145
2357
|
exports.getSignal = getSignal;
|
|
2146
2358
|
exports.getTracerProxy = getTracerProxy;
|
|
2359
|
+
exports.hashObjectKeys = hashObjectKeys;
|
|
2147
2360
|
exports.hashValue = hashValue;
|
|
2361
|
+
exports.holdLeaseUntilSettled = holdLeaseUntilSettled;
|
|
2362
|
+
exports.holdSuspendedLease = holdSuspendedLease;
|
|
2148
2363
|
exports.isPromise = isPromise;
|
|
2149
2364
|
exports.isReactivePromise = isReactivePromise;
|
|
2150
2365
|
exports.isSignal = isSignal;
|
|
2151
2366
|
exports.isThennable = isThennable;
|
|
2367
|
+
exports.mixHash = mixHash;
|
|
2152
2368
|
exports.notifier = notifier;
|
|
2153
2369
|
exports.registerCustomHash = registerCustomHash;
|
|
2370
|
+
exports.releaseAbandonedAttempt = releaseAbandonedAttempt;
|
|
2371
|
+
exports.releaseRenderLeases = releaseRenderLeases;
|
|
2154
2372
|
exports.removeTracer = removeTracer;
|
|
2155
2373
|
exports.runSignal = runSignal;
|
|
2156
|
-
exports.schedulePull = schedulePull;
|
|
2157
2374
|
exports.scheduleTracer = scheduleTracer;
|
|
2158
2375
|
exports.setCurrentConsumer = setCurrentConsumer;
|
|
2159
2376
|
exports.setGlobalContexts = setGlobalContexts;
|
|
@@ -2166,4 +2383,4 @@ exports.signal = signal;
|
|
|
2166
2383
|
exports.unwatchSignal = unwatchSignal;
|
|
2167
2384
|
exports.watchSignal = watchSignal;
|
|
2168
2385
|
exports.withContexts = withContexts;
|
|
2169
|
-
//# sourceMappingURL=debug-
|
|
2386
|
+
//# sourceMappingURL=debug-CbAX7VeM.js.map
|