signalium 3.0.3 → 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 +33 -0
- package/dist/cjs/development/{component-shared-DzjqSRY-.js → component-shared-BjwFh5Jq.js} +2 -2
- package/dist/cjs/development/{component-shared-DzjqSRY-.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-CDy1L3Id.js → debug-CbAX7VeM.js} +247 -31
- 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-D8Ydfj9E.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-BuDl2V-v.js → component-shared-CcxyLg4p.js} +2 -2
- package/dist/cjs/production/{component-shared-BuDl2V-v.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-CMvA-Ae9.js → contexts-waczQzHZ.js} +247 -31
- 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-I8W4cb8t.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-D_i2IMKF.js → component-shared-B3Q6mIzY.js} +2 -2
- package/dist/esm/development/{component-shared-D_i2IMKF.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-DCgp_XPm.js → debug-C3HD8WcT.js} +275 -59
- 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-D19Mgcgz.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 +1 -1
- package/dist/esm/index.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/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/production/{component-shared-XZnx53QZ.js → component-shared-CycOXiis.js} +2 -2
- package/dist/esm/production/{component-shared-XZnx53QZ.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-Cpo7QZDe.js → contexts-ry5lvNSx.js} +278 -62
- 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-CZTu3qTo.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/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-CDy1L3Id.js.map +0 -1
- package/dist/cjs/development/snapshot-D8Ydfj9E.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-CMvA-Ae9.js.map +0 -1
- package/dist/cjs/production/snapshot-I8W4cb8t.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-DCgp_XPm.js.map +0 -1
- package/dist/esm/development/snapshot-D19Mgcgz.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-Cpo7QZDe.js.map +0 -1
- package/dist/esm/production/snapshot-CZTu3qTo.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 contexts = require("../contexts-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const contexts = require("../contexts-waczQzHZ.js");
|
|
6
|
+
const config = require("../config-BHvmcsLQ.js");
|
|
7
|
+
const componentShared = require("../component-shared-CcxyLg4p.js");
|
|
8
|
+
const snapshot = require("../snapshot-7264bWj1.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: contexts$1 = [], 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
|
-
contexts.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 = contexts.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 contexts.getObjectHash(value);
|
|
153
|
+
}
|
|
154
|
+
seen.push(value);
|
|
155
|
+
const h = contexts.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 = contexts.ARRAY_SEED;
|
|
165
|
+
for (let i = 0; i < array.length; i++) {
|
|
166
|
+
h = contexts.mixHash(h, hashPropValue(array[i], seen));
|
|
167
|
+
}
|
|
168
|
+
seen.pop();
|
|
169
|
+
return contexts.finalizeHash(h, array.length);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return contexts.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(contexts.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
|
+
contexts.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
|
+
contexts.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" && contexts.isThennable(error)) {
|
|
395
|
+
contexts.holdLeaseUntilSettled(signal, error);
|
|
396
|
+
} else if (isReactSuspenseException(error)) {
|
|
397
|
+
contexts.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
|
+
contexts.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
|
contexts.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
|
contexts.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,24 +587,28 @@ 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
|
const [, def] = snapshot.getReactiveFnAndDefinition(fn);
|
|
262
605
|
const scope = useScope() ?? contexts.getGlobalScope();
|
|
263
606
|
const signal = scope.get(def, []);
|
|
264
|
-
return useSignalWithSuspension(signal);
|
|
607
|
+
return useSignalWithSuspension(signal, options);
|
|
265
608
|
}
|
|
266
|
-
function useReactive(fn) {
|
|
609
|
+
function useReactive(fn, options) {
|
|
267
610
|
const manager = usePauseSignalsManager();
|
|
268
|
-
const
|
|
611
|
+
const delivery = useDeliveryMode(options?.delivery);
|
|
269
612
|
const scope = useScope() ?? contexts.getGlobalScope();
|
|
270
613
|
const innerSignalRef = React.useRef(void 0);
|
|
271
614
|
const cloneSignalRef = React.useRef(void 0);
|
|
@@ -282,14 +625,18 @@ function useReactive(fn) {
|
|
|
282
625
|
});
|
|
283
626
|
}
|
|
284
627
|
const cloneSignal = cloneSignalRef.current;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
628
|
+
const subscribe = addRenderListener(cloneSignal, manager);
|
|
629
|
+
if (delivery === "state") {
|
|
630
|
+
const stateDelivery = useStateDeliveryState(cloneSignal);
|
|
631
|
+
const value = cloneSignal.value;
|
|
632
|
+
useStateDelivery(stateDelivery, cloneSignal, subscribe, cloneSignal.updatedCount, manager);
|
|
633
|
+
return value;
|
|
634
|
+
}
|
|
635
|
+
const getSnapshot = () => cloneSignal.value;
|
|
636
|
+
return usePausableStore(manager, cloneSignal, subscribe, getSnapshot);
|
|
290
637
|
}
|
|
291
|
-
function useReactiveDeep(fn) {
|
|
292
|
-
return useReactive(fn);
|
|
638
|
+
function useReactiveDeep(fn, options) {
|
|
639
|
+
return useReactive(fn, options);
|
|
293
640
|
}
|
|
294
641
|
exports.isAsyncFunctionWithoutTransform = componentShared.isAsyncFunctionWithoutTransform;
|
|
295
642
|
exports.ContextProvider = ContextProvider;
|