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
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
|
-
const debug = require("../debug-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const debug = require("../debug-CbAX7VeM.js");
|
|
6
|
+
const config = require("../config-D6wyrhrW.js");
|
|
7
|
+
const componentShared = require("../component-shared-BjwFh5Jq.js");
|
|
8
|
+
const snapshot = require("../snapshot-BTMVSd8Y.js");
|
|
8
9
|
function _interopNamespaceDefault(e) {
|
|
9
10
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
11
|
if (e) {
|
|
@@ -43,7 +44,14 @@ function ContextProvider({ children, contexts = [], inherit = true }) {
|
|
|
43
44
|
return jsxRuntime.jsx(ScopeContext.Provider, { value: scope, children });
|
|
44
45
|
}
|
|
45
46
|
class PauseSignalsManager {
|
|
46
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Readers per registered signal. Scope-cached signals can be shared across providers, so pausing
|
|
49
|
+
* counts readers on the signal instead of pausing it outright.
|
|
50
|
+
*/
|
|
51
|
+
signals = /* @__PURE__ */ new Map();
|
|
52
|
+
/** Unclaimed render leases taken under this provider (e.g. a suspended mount). Pruned lazily. */
|
|
53
|
+
leases = /* @__PURE__ */ new Set();
|
|
54
|
+
pruneLeasesAt = 64;
|
|
47
55
|
_paused;
|
|
48
56
|
constructor(initialPaused) {
|
|
49
57
|
this._paused = initialPaused;
|
|
@@ -51,22 +59,52 @@ class PauseSignalsManager {
|
|
|
51
59
|
get paused() {
|
|
52
60
|
return this._paused;
|
|
53
61
|
}
|
|
62
|
+
trackLease(signal) {
|
|
63
|
+
const leases = this.leases;
|
|
64
|
+
leases.add(signal);
|
|
65
|
+
if (leases.size >= this.pruneLeasesAt) {
|
|
66
|
+
for (const leased of leases) {
|
|
67
|
+
if (!leased._isLeased)
|
|
68
|
+
leases.delete(leased);
|
|
69
|
+
}
|
|
70
|
+
this.pruneLeasesAt = Math.max(64, leases.size * 2);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Call before the reader subscribes, so a paused reader never takes the watch. */
|
|
54
74
|
register(signal) {
|
|
55
|
-
this.signals.
|
|
75
|
+
this.signals.set(signal, (this.signals.get(signal) ?? 0) + 1);
|
|
76
|
+
this.leases.delete(signal);
|
|
77
|
+
if (this._paused) {
|
|
78
|
+
signal._addPausedReaders(1);
|
|
79
|
+
}
|
|
56
80
|
}
|
|
57
81
|
unregister(signal) {
|
|
58
|
-
this.signals.
|
|
82
|
+
const count = this.signals.get(signal);
|
|
83
|
+
if (count === void 0)
|
|
84
|
+
return;
|
|
85
|
+
if (count > 1) {
|
|
86
|
+
this.signals.set(signal, count - 1);
|
|
87
|
+
} else {
|
|
88
|
+
this.signals.delete(signal);
|
|
89
|
+
}
|
|
90
|
+
if (this._paused) {
|
|
91
|
+
signal._addPausedReaders(-1, true);
|
|
92
|
+
}
|
|
59
93
|
}
|
|
60
94
|
setPaused(value) {
|
|
61
95
|
if (value === this._paused)
|
|
62
96
|
return;
|
|
63
97
|
this._paused = value;
|
|
64
|
-
for (const signal of this.signals) {
|
|
65
|
-
|
|
66
|
-
|
|
98
|
+
for (const [signal, count] of this.signals) {
|
|
99
|
+
signal._addPausedReaders(value ? count : -count);
|
|
100
|
+
}
|
|
101
|
+
for (const signal of this.leases) {
|
|
102
|
+
if (!signal._isLeased) {
|
|
103
|
+
this.leases.delete(signal);
|
|
104
|
+
} else if (value) {
|
|
105
|
+
signal._pauseWatch();
|
|
67
106
|
} else {
|
|
68
|
-
|
|
69
|
-
debug.schedulePull(signal);
|
|
107
|
+
signal._resumeWatch();
|
|
70
108
|
}
|
|
71
109
|
}
|
|
72
110
|
}
|
|
@@ -86,6 +124,299 @@ function PauseSignalsProvider({ value, children }) {
|
|
|
86
124
|
function usePauseSignalsManager() {
|
|
87
125
|
return React.useContext(PauseSignalsManagerContext);
|
|
88
126
|
}
|
|
127
|
+
function addRenderListener(signal, manager) {
|
|
128
|
+
const subscribe = signal.addListenerLazy(!manager?.paused);
|
|
129
|
+
if (manager !== null && signal._isLeased) {
|
|
130
|
+
manager.trackLease(signal);
|
|
131
|
+
}
|
|
132
|
+
return subscribe;
|
|
133
|
+
}
|
|
134
|
+
function usePausableStore(manager, signal, subscribe, getSnapshot) {
|
|
135
|
+
React.useEffect(() => {
|
|
136
|
+
if (manager === null)
|
|
137
|
+
return;
|
|
138
|
+
manager.register(signal);
|
|
139
|
+
return () => manager.unregister(signal);
|
|
140
|
+
}, [manager, signal]);
|
|
141
|
+
return React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
142
|
+
}
|
|
143
|
+
const { imul } = Math;
|
|
144
|
+
const { getPrototypeOf, keys: objectKeys } = Object;
|
|
145
|
+
const EMPTY_PROPS_HASH = debug.hashValue({});
|
|
146
|
+
function hashPropValue(value, seen) {
|
|
147
|
+
if (typeof value === "object" && value !== null) {
|
|
148
|
+
const proto = getPrototypeOf(value);
|
|
149
|
+
if (proto === Object.prototype) {
|
|
150
|
+
const keys = objectKeys(value);
|
|
151
|
+
if (keys.includes("$$typeof") && typeof value.$$typeof === "symbol") {
|
|
152
|
+
return debug.getObjectHash(value);
|
|
153
|
+
}
|
|
154
|
+
seen.push(value);
|
|
155
|
+
const h = debug.hashObjectKeys(value, keys, seen);
|
|
156
|
+
seen.pop();
|
|
157
|
+
return h;
|
|
158
|
+
}
|
|
159
|
+
if (proto === Array.prototype) {
|
|
160
|
+
if (seen.includes(value))
|
|
161
|
+
return 0;
|
|
162
|
+
seen.push(value);
|
|
163
|
+
const array = value;
|
|
164
|
+
let h = debug.ARRAY_SEED;
|
|
165
|
+
for (let i = 0; i < array.length; i++) {
|
|
166
|
+
h = debug.mixHash(h, hashPropValue(array[i], seen));
|
|
167
|
+
}
|
|
168
|
+
seen.pop();
|
|
169
|
+
return debug.finalizeHash(h, array.length);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return debug.hashValue(value, seen);
|
|
173
|
+
}
|
|
174
|
+
function hashProps(props) {
|
|
175
|
+
const keyMultiplier = 2654435769;
|
|
176
|
+
const seen = [];
|
|
177
|
+
let sum = EMPTY_PROPS_HASH;
|
|
178
|
+
for (const key of objectKeys(props)) {
|
|
179
|
+
sum += imul(debug.hashValue(key), keyMultiplier) ^ hashPropValue(props[key], seen);
|
|
180
|
+
}
|
|
181
|
+
return sum >>> 0;
|
|
182
|
+
}
|
|
183
|
+
function shallowIdentical(prev, next) {
|
|
184
|
+
let count = 0;
|
|
185
|
+
for (const key in next) {
|
|
186
|
+
if (!Object.is(prev[key], next[key]) || !(key in prev))
|
|
187
|
+
return false;
|
|
188
|
+
count++;
|
|
189
|
+
}
|
|
190
|
+
for (const _key in prev) {
|
|
191
|
+
count--;
|
|
192
|
+
}
|
|
193
|
+
return count === 0;
|
|
194
|
+
}
|
|
195
|
+
class PropsHashCache {
|
|
196
|
+
props;
|
|
197
|
+
hash;
|
|
198
|
+
constructor(props, hash) {
|
|
199
|
+
this.props = props;
|
|
200
|
+
this.hash = hash;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function usePropsHash(props) {
|
|
204
|
+
const ref = React.useRef(null);
|
|
205
|
+
const cache = ref.current;
|
|
206
|
+
if (cache !== null) {
|
|
207
|
+
if (cache.props === props || shallowIdentical(cache.props, props)) {
|
|
208
|
+
return cache.hash;
|
|
209
|
+
}
|
|
210
|
+
const hash2 = hashProps(props);
|
|
211
|
+
cache.props = props;
|
|
212
|
+
cache.hash = hash2;
|
|
213
|
+
return hash2;
|
|
214
|
+
}
|
|
215
|
+
const hash = hashProps(props);
|
|
216
|
+
ref.current = new PropsHashCache(props, hash);
|
|
217
|
+
return hash;
|
|
218
|
+
}
|
|
219
|
+
function useDeliveryMode(override) {
|
|
220
|
+
const ref = React.useRef(void 0);
|
|
221
|
+
return ref.current ??= override ?? config.getReactDelivery();
|
|
222
|
+
}
|
|
223
|
+
const useCommitEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;
|
|
224
|
+
const increment = (n) => n + 1;
|
|
225
|
+
class StateDelivery {
|
|
226
|
+
signal;
|
|
227
|
+
committed;
|
|
228
|
+
forceUpdate;
|
|
229
|
+
/** In the pending-delivery queue. */
|
|
230
|
+
queued = false;
|
|
231
|
+
/** A `setState` was delivered and its render has not committed yet. */
|
|
232
|
+
awaitingCommit = false;
|
|
233
|
+
/** Visible: between the subscription layout effect's setup and cleanup. Only visible readers get deliveries. */
|
|
234
|
+
mounted = false;
|
|
235
|
+
/**
|
|
236
|
+
* Set by every render, cleared by its commit. Still set when Suspense hides the reader, it means
|
|
237
|
+
* the reader's own render suspended, so it stays live: a change may no longer need what it
|
|
238
|
+
* suspended on.
|
|
239
|
+
*/
|
|
240
|
+
rendering = false;
|
|
241
|
+
/** The subscription layout effect has run before: its next run is a reveal, not a first mount. */
|
|
242
|
+
connected = false;
|
|
243
|
+
/**
|
|
244
|
+
* A commit included the reader without connecting it: it was committed hidden (prerendered in a
|
|
245
|
+
* hidden `<Activity>`, or mounted into a Suspense-hidden tree), so its first connect is a reveal.
|
|
246
|
+
*/
|
|
247
|
+
committedHidden = false;
|
|
248
|
+
/** The subscription currently held, the subscribe function it was made with, and its signal and pause manager. */
|
|
249
|
+
subscribedWith = null;
|
|
250
|
+
subscribedSignal = null;
|
|
251
|
+
pauseManager = null;
|
|
252
|
+
unsubscribe = null;
|
|
253
|
+
listener;
|
|
254
|
+
constructor(signal, version, forceUpdate) {
|
|
255
|
+
this.signal = signal;
|
|
256
|
+
this.committed = version;
|
|
257
|
+
this.forceUpdate = forceUpdate;
|
|
258
|
+
this.listener = () => this.check();
|
|
259
|
+
}
|
|
260
|
+
check() {
|
|
261
|
+
if (this.queued || this.awaitingCommit || !this.mounted)
|
|
262
|
+
return;
|
|
263
|
+
if (this.signal.updatedCount !== this.committed) {
|
|
264
|
+
enqueueDelivery(this);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Brings the signal up to date the way a read would, and reports whether it moved past the
|
|
269
|
+
* committed version. A signal nobody watched (the reader was hidden, or its render lease expired
|
|
270
|
+
* before the commit) is not recomputed when its dependencies change, so its `updatedCount` alone
|
|
271
|
+
* can be stale.
|
|
272
|
+
*/
|
|
273
|
+
pull() {
|
|
274
|
+
try {
|
|
275
|
+
debug.checkSignal(this.signal);
|
|
276
|
+
} catch {
|
|
277
|
+
return 2;
|
|
278
|
+
}
|
|
279
|
+
return this.signal.updatedCount !== this.committed ? 1 : 0;
|
|
280
|
+
}
|
|
281
|
+
subscribe(subscribe, manager) {
|
|
282
|
+
if (this.subscribedWith === subscribe && this.pauseManager === manager)
|
|
283
|
+
return;
|
|
284
|
+
this.release();
|
|
285
|
+
manager?.register(this.signal);
|
|
286
|
+
this.subscribedSignal = this.signal;
|
|
287
|
+
this.pauseManager = manager;
|
|
288
|
+
this.unsubscribe = subscribe(this.listener);
|
|
289
|
+
this.subscribedWith = subscribe;
|
|
290
|
+
}
|
|
291
|
+
release() {
|
|
292
|
+
if (this.unsubscribe === null)
|
|
293
|
+
return;
|
|
294
|
+
this.unsubscribe();
|
|
295
|
+
this.pauseManager?.unregister(this.subscribedSignal);
|
|
296
|
+
this.unsubscribe = null;
|
|
297
|
+
this.subscribedWith = null;
|
|
298
|
+
this.subscribedSignal = null;
|
|
299
|
+
this.pauseManager = null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
let PENDING_DELIVERIES = [];
|
|
303
|
+
let deliveryScheduled = false;
|
|
304
|
+
function enqueueDelivery(delivery) {
|
|
305
|
+
delivery.queued = true;
|
|
306
|
+
PENDING_DELIVERIES.push(delivery);
|
|
307
|
+
if (!deliveryScheduled) {
|
|
308
|
+
deliveryScheduled = true;
|
|
309
|
+
config.scheduleReactDelivery(flushDeliveries);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function flushDeliveries() {
|
|
313
|
+
deliveryScheduled = false;
|
|
314
|
+
const deliveries = PENDING_DELIVERIES;
|
|
315
|
+
PENDING_DELIVERIES = [];
|
|
316
|
+
config.runBatch(() => {
|
|
317
|
+
for (const delivery of deliveries) {
|
|
318
|
+
delivery.queued = false;
|
|
319
|
+
if (delivery.mounted && delivery.signal.updatedCount !== delivery.committed) {
|
|
320
|
+
delivery.awaitingCommit = true;
|
|
321
|
+
delivery.forceUpdate();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
function useStateDeliveryState(signal) {
|
|
327
|
+
const [, forceUpdate] = React.useReducer(increment, 0);
|
|
328
|
+
const [delivery] = React.useState(() => new StateDelivery(signal, signal.updatedCount, forceUpdate));
|
|
329
|
+
delivery.rendering = true;
|
|
330
|
+
return delivery;
|
|
331
|
+
}
|
|
332
|
+
function useStateDelivery(delivery, signal, subscribe, version, manager) {
|
|
333
|
+
useCommitEffect(() => {
|
|
334
|
+
delivery.signal = signal;
|
|
335
|
+
delivery.committed = version;
|
|
336
|
+
delivery.awaitingCommit = false;
|
|
337
|
+
delivery.rendering = false;
|
|
338
|
+
delivery.check();
|
|
339
|
+
});
|
|
340
|
+
React.useInsertionEffect(() => {
|
|
341
|
+
if (delivery.connected)
|
|
342
|
+
return;
|
|
343
|
+
queueMicrotask(() => {
|
|
344
|
+
if (!delivery.connected)
|
|
345
|
+
delivery.committedHidden = true;
|
|
346
|
+
});
|
|
347
|
+
}, [delivery]);
|
|
348
|
+
useCommitEffect(() => {
|
|
349
|
+
const revealing = delivery.connected || delivery.committedHidden;
|
|
350
|
+
delivery.connected = true;
|
|
351
|
+
delivery.committedHidden = false;
|
|
352
|
+
delivery.mounted = true;
|
|
353
|
+
delivery.subscribe(subscribe, manager);
|
|
354
|
+
const pulled = delivery.pull();
|
|
355
|
+
if (pulled === 2 || pulled === 1 && revealing) {
|
|
356
|
+
delivery.awaitingCommit = true;
|
|
357
|
+
delivery.forceUpdate();
|
|
358
|
+
} else if (pulled === 1) {
|
|
359
|
+
delivery.check();
|
|
360
|
+
}
|
|
361
|
+
return () => {
|
|
362
|
+
if (delivery.rendering) {
|
|
363
|
+
delivery.awaitingCommit = false;
|
|
364
|
+
} else {
|
|
365
|
+
delivery.mounted = false;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
}, [subscribe, manager]);
|
|
369
|
+
React.useEffect(() => () => delivery.release(), [delivery]);
|
|
370
|
+
}
|
|
371
|
+
const elementPropsByInnerProps = /* @__PURE__ */ new WeakMap();
|
|
372
|
+
const suspendedAttemptsByElement = /* @__PURE__ */ new WeakMap();
|
|
373
|
+
function createComponentElement(Inner, props) {
|
|
374
|
+
const element = React.createElement(Inner, props);
|
|
375
|
+
elementPropsByInnerProps.set(element.props, props);
|
|
376
|
+
return element;
|
|
377
|
+
}
|
|
378
|
+
function isReactSuspenseException(error) {
|
|
379
|
+
if (!(error instanceof Error))
|
|
380
|
+
return false;
|
|
381
|
+
const { message } = error;
|
|
382
|
+
return message.startsWith("Suspense Exception") || /^Minified React error #(460|542)\b/.test(message);
|
|
383
|
+
}
|
|
384
|
+
function readComponentSignal(signal, props) {
|
|
385
|
+
const element = elementPropsByInnerProps.get(props);
|
|
386
|
+
let attempts = element === void 0 ? void 0 : suspendedAttemptsByElement.get(element);
|
|
387
|
+
try {
|
|
388
|
+
debug.runSignal(signal);
|
|
389
|
+
const value = signal.value;
|
|
390
|
+
attempts?.delete(signal);
|
|
391
|
+
return value;
|
|
392
|
+
} catch (error) {
|
|
393
|
+
let pinned = true;
|
|
394
|
+
if (error !== null && typeof error === "object" && debug.isThennable(error)) {
|
|
395
|
+
debug.holdLeaseUntilSettled(signal, error);
|
|
396
|
+
} else if (isReactSuspenseException(error)) {
|
|
397
|
+
debug.holdSuspendedLease(signal);
|
|
398
|
+
} else {
|
|
399
|
+
pinned = false;
|
|
400
|
+
}
|
|
401
|
+
if (pinned && element !== void 0 && signal._isLeased) {
|
|
402
|
+
if (attempts === void 0) {
|
|
403
|
+
attempts = /* @__PURE__ */ new Set();
|
|
404
|
+
suspendedAttemptsByElement.set(element, attempts);
|
|
405
|
+
}
|
|
406
|
+
attempts.add(signal);
|
|
407
|
+
}
|
|
408
|
+
throw error;
|
|
409
|
+
} finally {
|
|
410
|
+
if (attempts !== void 0) {
|
|
411
|
+
for (const attempt of attempts) {
|
|
412
|
+
if (attempt !== signal) {
|
|
413
|
+
debug.releaseAbandonedAttempt(attempt);
|
|
414
|
+
attempts.delete(attempt);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
89
420
|
const thenableOutcome = /* @__PURE__ */ new WeakMap();
|
|
90
421
|
function adoptYieldedThenable(thenable) {
|
|
91
422
|
const expanded = thenable;
|
|
@@ -152,10 +483,12 @@ function runSyncReplayAsyncComponent(fn, props, ownerSignal) {
|
|
|
152
483
|
debug.setCurrentConsumer(prevConsumer);
|
|
153
484
|
}
|
|
154
485
|
}
|
|
155
|
-
function createAsyncComponentWrapper(fn) {
|
|
486
|
+
function createAsyncComponentWrapper(fn, options) {
|
|
487
|
+
const deliveryOverride = options?.delivery;
|
|
156
488
|
const Inner = (props) => {
|
|
157
489
|
const scope = useScope();
|
|
158
490
|
const manager = usePauseSignalsManager();
|
|
491
|
+
const delivery = useDeliveryMode(deliveryOverride);
|
|
159
492
|
const fnSignalRef = React.useRef(void 0);
|
|
160
493
|
const propsRef = React.useRef(props);
|
|
161
494
|
propsRef.current = props;
|
|
@@ -171,18 +504,20 @@ function createAsyncComponentWrapper(fn) {
|
|
|
171
504
|
owned._isLazy = true;
|
|
172
505
|
fnSignalRef.current = sig = owned;
|
|
173
506
|
}
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
507
|
+
const subscribe = addRenderListener(sig, manager);
|
|
508
|
+
const stateDelivery = delivery === "state" ? useStateDeliveryState(sig) : null;
|
|
509
|
+
const value = readComponentSignal(sig, props);
|
|
510
|
+
if (stateDelivery !== null) {
|
|
511
|
+
useStateDelivery(stateDelivery, sig, subscribe, sig.updatedCount, manager);
|
|
512
|
+
} else {
|
|
513
|
+
const getSnapshot = () => sig.updatedCount;
|
|
514
|
+
usePausableStore(manager, sig, subscribe, getSnapshot);
|
|
515
|
+
}
|
|
516
|
+
return value;
|
|
182
517
|
};
|
|
183
518
|
const Outer = (props) => {
|
|
184
|
-
const hash =
|
|
185
|
-
return React.useMemo(() =>
|
|
519
|
+
const hash = usePropsHash(props);
|
|
520
|
+
return React.useMemo(() => createComponentElement(Inner, props), [hash]);
|
|
186
521
|
};
|
|
187
522
|
Object.defineProperty(Outer, SIGNALIUM_ASYNC_COMPONENT, { value: true, enumerable: false });
|
|
188
523
|
return Outer;
|
|
@@ -198,7 +533,7 @@ function ensureSsrScope() {
|
|
|
198
533
|
debug.setRequestScopeGetter(() => getScope());
|
|
199
534
|
}
|
|
200
535
|
}
|
|
201
|
-
function component(fn) {
|
|
536
|
+
function component(fn, options) {
|
|
202
537
|
ensureSsrScope();
|
|
203
538
|
if (componentShared.isAsyncFunctionWithoutTransform(fn)) {
|
|
204
539
|
throw new Error("signalium: `component(async (props) => { await ... })` requires the Signalium Babel preset (async transform).");
|
|
@@ -207,12 +542,14 @@ function component(fn) {
|
|
|
207
542
|
if (typeof window === "undefined") {
|
|
208
543
|
return componentShared.createServerAsyncComponentWrapper(fn);
|
|
209
544
|
}
|
|
210
|
-
return createAsyncComponentWrapper(fn);
|
|
545
|
+
return createAsyncComponentWrapper(fn, options);
|
|
211
546
|
}
|
|
212
547
|
const syncFn = fn;
|
|
548
|
+
const deliveryOverride = options?.delivery;
|
|
213
549
|
const Component = (props) => {
|
|
214
550
|
const scope = useScope();
|
|
215
551
|
const manager = usePauseSignalsManager();
|
|
552
|
+
const delivery = useDeliveryMode(deliveryOverride);
|
|
216
553
|
const fnSignalRef = React.useRef(void 0);
|
|
217
554
|
const propsRef = React.useRef(props);
|
|
218
555
|
propsRef.current = props;
|
|
@@ -227,18 +564,20 @@ function component(fn) {
|
|
|
227
564
|
created._isLazy = true;
|
|
228
565
|
fnSignalRef.current = signal = created;
|
|
229
566
|
}
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
567
|
+
const subscribe = addRenderListener(signal, manager);
|
|
568
|
+
const stateDelivery = delivery === "state" ? useStateDeliveryState(signal) : null;
|
|
569
|
+
const value = readComponentSignal(signal, props);
|
|
570
|
+
if (stateDelivery !== null) {
|
|
571
|
+
useStateDelivery(stateDelivery, signal, subscribe, signal.updatedCount, manager);
|
|
572
|
+
} else {
|
|
573
|
+
const getSnapshot = () => signal.updatedCount;
|
|
574
|
+
usePausableStore(manager, signal, subscribe, getSnapshot);
|
|
575
|
+
}
|
|
576
|
+
return value;
|
|
238
577
|
};
|
|
239
578
|
return (props) => {
|
|
240
|
-
const hash =
|
|
241
|
-
return React.useMemo(() =>
|
|
579
|
+
const hash = usePropsHash(props);
|
|
580
|
+
return React.useMemo(() => createComponentElement(Component, props), [hash]);
|
|
242
581
|
};
|
|
243
582
|
}
|
|
244
583
|
function useSignal(value, opts) {
|
|
@@ -248,30 +587,34 @@ function useSignal(value, opts) {
|
|
|
248
587
|
}
|
|
249
588
|
return ref.current;
|
|
250
589
|
}
|
|
251
|
-
function useSignalWithSuspension(signal) {
|
|
590
|
+
function useSignalWithSuspension(signal, options) {
|
|
252
591
|
const manager = usePauseSignalsManager();
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
592
|
+
const delivery = useDeliveryMode(options?.delivery);
|
|
593
|
+
const subscribe = addRenderListener(signal, manager);
|
|
594
|
+
if (delivery === "state") {
|
|
595
|
+
const stateDelivery = useStateDeliveryState(signal);
|
|
596
|
+
const value = signal.value;
|
|
597
|
+
useStateDelivery(stateDelivery, signal, subscribe, signal.updatedCount, manager);
|
|
598
|
+
return value;
|
|
599
|
+
}
|
|
600
|
+
const getSnapshot = () => signal.value;
|
|
601
|
+
return usePausableStore(manager, signal, subscribe, getSnapshot);
|
|
259
602
|
}
|
|
260
|
-
function useReactiveShallow(fn) {
|
|
603
|
+
function useReactiveShallow(fn, options) {
|
|
261
604
|
if (debug.getCurrentConsumer()) {
|
|
262
605
|
throw new Error("signalium: `useReactiveShallow` cannot be called inside a reactive function. Call your reactive function directly instead — it already participates in the signal graph.");
|
|
263
606
|
}
|
|
264
607
|
const [, def] = snapshot.getReactiveFnAndDefinition(fn);
|
|
265
608
|
const scope = useScope() ?? debug.getGlobalScope();
|
|
266
609
|
const signal = scope.get(def, []);
|
|
267
|
-
return useSignalWithSuspension(signal);
|
|
610
|
+
return useSignalWithSuspension(signal, options);
|
|
268
611
|
}
|
|
269
|
-
function useReactive(fn) {
|
|
612
|
+
function useReactive(fn, options) {
|
|
270
613
|
if (debug.getCurrentConsumer()) {
|
|
271
614
|
throw new Error("signalium: `useReactive` cannot be called inside a reactive function. Call your reactive function directly instead — it already participates in the signal graph.");
|
|
272
615
|
}
|
|
273
616
|
const manager = usePauseSignalsManager();
|
|
274
|
-
const
|
|
617
|
+
const delivery = useDeliveryMode(options?.delivery);
|
|
275
618
|
const scope = useScope() ?? debug.getGlobalScope();
|
|
276
619
|
const innerSignalRef = React.useRef(void 0);
|
|
277
620
|
const cloneSignalRef = React.useRef(void 0);
|
|
@@ -288,17 +631,21 @@ function useReactive(fn) {
|
|
|
288
631
|
});
|
|
289
632
|
}
|
|
290
633
|
const cloneSignal = cloneSignalRef.current;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
634
|
+
const subscribe = addRenderListener(cloneSignal, manager);
|
|
635
|
+
if (delivery === "state") {
|
|
636
|
+
const stateDelivery = useStateDeliveryState(cloneSignal);
|
|
637
|
+
const value = cloneSignal.value;
|
|
638
|
+
useStateDelivery(stateDelivery, cloneSignal, subscribe, cloneSignal.updatedCount, manager);
|
|
639
|
+
return value;
|
|
640
|
+
}
|
|
641
|
+
const getSnapshot = () => cloneSignal.value;
|
|
642
|
+
return usePausableStore(manager, cloneSignal, subscribe, getSnapshot);
|
|
296
643
|
}
|
|
297
|
-
function useReactiveDeep(fn) {
|
|
644
|
+
function useReactiveDeep(fn, options) {
|
|
298
645
|
{
|
|
299
646
|
warnUseReactiveDeepOnce();
|
|
300
647
|
}
|
|
301
|
-
return useReactive(fn);
|
|
648
|
+
return useReactive(fn, options);
|
|
302
649
|
}
|
|
303
650
|
let _useReactiveDeepWarned = false;
|
|
304
651
|
function warnUseReactiveDeepOnce() {
|