solid-js 2.0.0-beta.6 → 2.0.0-beta.8
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/dist/dev.cjs +66 -104
- package/dist/dev.js +66 -104
- package/dist/server.cjs +331 -132
- package/dist/server.js +331 -132
- package/dist/solid.cjs +66 -104
- package/dist/solid.js +66 -104
- package/package.json +78 -30
- package/types/client/flow.d.ts +34 -13
- package/types/client/hydration.d.ts +35 -9
- package/types/jsx-properties.d.ts +92 -0
- package/types/jsx.d.ts +390 -314
- package/types/server/flow.d.ts +40 -7
- package/types/server/hydration.d.ts +18 -1
- package/types/server/signals.d.ts +33 -15
- package/types-cjs/client/component.d.cts +75 -0
- package/types-cjs/client/core.d.cts +58 -0
- package/types-cjs/client/flow.d.cts +163 -0
- package/types-cjs/client/hydration.d.cts +121 -0
- package/types-cjs/index.d.cts +17 -0
- package/types-cjs/jsx-properties.d.cts +92 -0
- package/types-cjs/jsx.d.cts +4294 -0
- package/types-cjs/package.json +3 -0
- package/types-cjs/server/component.d.cts +67 -0
- package/types-cjs/server/core.d.cts +44 -0
- package/types-cjs/server/flow.d.cts +115 -0
- package/types-cjs/server/hydration.d.cts +63 -0
- package/types-cjs/server/index.d.cts +12 -0
- package/types-cjs/server/shared.d.cts +50 -0
- package/types-cjs/server/signals.d.cts +87 -0
package/dist/server.cjs
CHANGED
|
@@ -28,25 +28,82 @@ function runWithObserver(comp, fn) {
|
|
|
28
28
|
function getObserver() {
|
|
29
29
|
return Observer;
|
|
30
30
|
}
|
|
31
|
-
function
|
|
31
|
+
function createDeferredPromise() {
|
|
32
|
+
let settled = false;
|
|
33
|
+
let resolvePromise;
|
|
34
|
+
let rejectPromise;
|
|
35
|
+
const promise = new Promise((resolve, reject) => {
|
|
36
|
+
resolvePromise = resolve;
|
|
37
|
+
rejectPromise = reject;
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
promise,
|
|
41
|
+
resolve(value) {
|
|
42
|
+
if (settled) return;
|
|
43
|
+
settled = true;
|
|
44
|
+
promise.s = 1;
|
|
45
|
+
promise.v = value;
|
|
46
|
+
resolvePromise(value);
|
|
47
|
+
},
|
|
48
|
+
reject(error) {
|
|
49
|
+
if (settled) return;
|
|
50
|
+
settled = true;
|
|
51
|
+
promise.s = 2;
|
|
52
|
+
promise.v = error;
|
|
53
|
+
rejectPromise(error);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function subscribePendingRetry(error, retry) {
|
|
58
|
+
if (!(error instanceof signals.NotReadyError)) return false;
|
|
59
|
+
error.source?.then(() => retry(), () => retry());
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
function settleServerAsync(initial, rerun, deferred, onSuccess, onError, isDisposed) {
|
|
63
|
+
let first = true;
|
|
64
|
+
const attempt = () => {
|
|
65
|
+
if (isDisposed()) return;
|
|
66
|
+
let current;
|
|
67
|
+
try {
|
|
68
|
+
current = first ? initial : rerun();
|
|
69
|
+
first = false;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (subscribePendingRetry(error, attempt)) return;
|
|
72
|
+
onError(error);
|
|
73
|
+
deferred.reject(error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
Promise.resolve(current).then(value => {
|
|
77
|
+
if (isDisposed()) return;
|
|
78
|
+
deferred.resolve(onSuccess(value));
|
|
79
|
+
}, error => {
|
|
80
|
+
if (isDisposed()) return;
|
|
81
|
+
if (subscribePendingRetry(error, attempt)) return;
|
|
82
|
+
onError(error);
|
|
83
|
+
deferred.reject(error);
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
attempt();
|
|
87
|
+
}
|
|
88
|
+
function createSignal(first, second) {
|
|
32
89
|
if (typeof first === "function") {
|
|
33
|
-
const opts =
|
|
34
|
-
deferStream:
|
|
35
|
-
ssrSource:
|
|
90
|
+
const opts = second?.deferStream || second?.ssrSource ? {
|
|
91
|
+
deferStream: second?.deferStream,
|
|
92
|
+
ssrSource: second?.ssrSource
|
|
36
93
|
} : undefined;
|
|
37
|
-
const memo = createMemo(prev => first(prev),
|
|
94
|
+
const memo = createMemo(prev => first(prev), opts);
|
|
38
95
|
return [memo, () => undefined];
|
|
39
96
|
}
|
|
40
97
|
return [() => first, v => {
|
|
41
98
|
return first = typeof v === "function" ? v(first) : v;
|
|
42
99
|
}];
|
|
43
100
|
}
|
|
44
|
-
function createMemo(compute,
|
|
101
|
+
function createMemo(compute, options) {
|
|
45
102
|
const ctx = sharedConfig.context;
|
|
46
103
|
const owner = signals.createOwner();
|
|
47
104
|
const comp = {
|
|
48
105
|
owner,
|
|
49
|
-
value:
|
|
106
|
+
value: undefined,
|
|
50
107
|
compute: compute,
|
|
51
108
|
error: undefined,
|
|
52
109
|
computed: false,
|
|
@@ -57,21 +114,22 @@ function createMemo(compute, value, options) {
|
|
|
57
114
|
}));
|
|
58
115
|
function update() {
|
|
59
116
|
if (comp.disposed) return;
|
|
117
|
+
const run = () => signals.runWithOwner(owner, () => runWithObserver(comp, () => comp.compute(comp.value)));
|
|
60
118
|
try {
|
|
61
119
|
comp.error = undefined;
|
|
62
|
-
const result =
|
|
120
|
+
const result = run();
|
|
63
121
|
comp.computed = true;
|
|
64
|
-
processResult(comp, result, owner, ctx, options?.deferStream, options?.ssrSource);
|
|
122
|
+
processResult(comp, result, owner, ctx, options?.deferStream, options?.ssrSource, run);
|
|
65
123
|
} catch (err) {
|
|
66
124
|
if (err instanceof signals.NotReadyError) {
|
|
67
|
-
err
|
|
125
|
+
subscribePendingRetry(err, update);
|
|
68
126
|
}
|
|
69
127
|
comp.error = err;
|
|
70
128
|
comp.computed = true;
|
|
71
129
|
}
|
|
72
130
|
}
|
|
73
131
|
const ssrSource = options?.ssrSource;
|
|
74
|
-
if (ssrSource === "
|
|
132
|
+
if (ssrSource === "client") {
|
|
75
133
|
comp.computed = true;
|
|
76
134
|
} else if (!options?.lazy) {
|
|
77
135
|
update();
|
|
@@ -146,7 +204,7 @@ function createDeepProxy(target, patches, basePath = []) {
|
|
|
146
204
|
};
|
|
147
205
|
return new Proxy(target, handler);
|
|
148
206
|
}
|
|
149
|
-
function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
|
|
207
|
+
function processResult(comp, result, owner, ctx, deferStream, ssrSource, rerun) {
|
|
150
208
|
if (comp.disposed) return;
|
|
151
209
|
const id = owner.id;
|
|
152
210
|
const noHydrate = signals.getContext(NoHydrateContext, owner);
|
|
@@ -160,47 +218,78 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
|
|
|
160
218
|
comp.error = result.v;
|
|
161
219
|
return;
|
|
162
220
|
}
|
|
163
|
-
|
|
221
|
+
const deferred = createDeferredPromise();
|
|
222
|
+
if (ctx?.async && ctx.serialize && id && !noHydrate) ctx.serialize(id, deferred.promise, deferStream);
|
|
223
|
+
settleServerAsync(result, () => rerun ? rerun() : result, deferred, value => {
|
|
164
224
|
result.s = 1;
|
|
165
|
-
result.v =
|
|
166
|
-
|
|
167
|
-
comp.value = v;
|
|
225
|
+
result.v = value;
|
|
226
|
+
comp.value = value;
|
|
168
227
|
comp.error = undefined;
|
|
169
|
-
|
|
228
|
+
return value;
|
|
229
|
+
}, error => {
|
|
170
230
|
result.s = 2;
|
|
171
|
-
result.v =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (ctx?.async && ctx.serialize && id && !noHydrate) ctx.serialize(id, result, deferStream);
|
|
176
|
-
comp.error = new signals.NotReadyError(result);
|
|
231
|
+
result.v = error;
|
|
232
|
+
comp.error = error;
|
|
233
|
+
}, () => comp.disposed);
|
|
234
|
+
comp.error = new signals.NotReadyError(deferred.promise);
|
|
177
235
|
return;
|
|
178
236
|
}
|
|
179
237
|
const iterator = result?.[Symbol.asyncIterator];
|
|
180
238
|
if (typeof iterator === "function") {
|
|
181
|
-
const iter = iterator.call(result);
|
|
182
239
|
if (ssrSource === "hybrid") {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
240
|
+
let currentResult = result;
|
|
241
|
+
let iter;
|
|
242
|
+
const deferred = createDeferredPromise();
|
|
243
|
+
const runFirst = () => {
|
|
244
|
+
const source = currentResult ?? (rerun ? rerun() : result);
|
|
245
|
+
currentResult = undefined;
|
|
246
|
+
const nextIterator = source?.[Symbol.asyncIterator];
|
|
247
|
+
if (typeof nextIterator !== "function") {
|
|
248
|
+
throw new Error("Expected async iterator while retrying server createMemo");
|
|
249
|
+
}
|
|
250
|
+
iter = nextIterator.call(source);
|
|
251
|
+
return iter.next().then(value => {
|
|
252
|
+
if (!value.done) closeAsyncIterator(iter);
|
|
253
|
+
return value.value;
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
settleServerAsync(runFirst(), runFirst, deferred, value => {
|
|
257
|
+
comp.value = value;
|
|
189
258
|
comp.error = undefined;
|
|
190
|
-
return
|
|
191
|
-
},
|
|
192
|
-
|
|
193
|
-
|
|
259
|
+
return value;
|
|
260
|
+
}, error => {
|
|
261
|
+
comp.error = error;
|
|
262
|
+
}, () => comp.disposed);
|
|
263
|
+
if (ctx?.async && ctx.serialize && id && !noHydrate) ctx.serialize(id, deferred.promise, deferStream);
|
|
264
|
+
comp.error = new signals.NotReadyError(deferred.promise);
|
|
194
265
|
} else {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
266
|
+
let currentResult = result;
|
|
267
|
+
let iter;
|
|
268
|
+
let firstResult;
|
|
269
|
+
const deferred = createDeferredPromise();
|
|
270
|
+
const runFirst = () => {
|
|
271
|
+
const source = currentResult ?? (rerun ? rerun() : result);
|
|
272
|
+
currentResult = undefined;
|
|
273
|
+
const nextIterator = source?.[Symbol.asyncIterator];
|
|
274
|
+
if (typeof nextIterator !== "function") {
|
|
275
|
+
throw new Error("Expected async iterator while retrying server createMemo");
|
|
276
|
+
}
|
|
277
|
+
iter = nextIterator.call(source);
|
|
278
|
+
return iter.next().then(value => {
|
|
279
|
+
firstResult = value;
|
|
280
|
+
return Promise.resolve();
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
settleServerAsync(runFirst(), runFirst, deferred, () => {
|
|
284
|
+
const resolved = firstResult;
|
|
285
|
+
if (resolved && !resolved.done) {
|
|
286
|
+
comp.value = resolved.value;
|
|
200
287
|
}
|
|
201
288
|
comp.error = undefined;
|
|
202
|
-
return
|
|
203
|
-
},
|
|
289
|
+
return undefined;
|
|
290
|
+
}, error => {
|
|
291
|
+
comp.error = error;
|
|
292
|
+
}, () => comp.disposed);
|
|
204
293
|
if (ctx?.async && ctx.serialize && id && !noHydrate) {
|
|
205
294
|
let tappedFirst = true;
|
|
206
295
|
const tapped = {
|
|
@@ -208,7 +297,10 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
|
|
|
208
297
|
next() {
|
|
209
298
|
if (tappedFirst) {
|
|
210
299
|
tappedFirst = false;
|
|
211
|
-
return
|
|
300
|
+
return deferred.promise.then(() => firstResult?.done ? {
|
|
301
|
+
done: true,
|
|
302
|
+
value: undefined
|
|
303
|
+
} : firstResult);
|
|
212
304
|
}
|
|
213
305
|
return iter.next().then(r => r);
|
|
214
306
|
},
|
|
@@ -219,7 +311,7 @@ function processResult(comp, result, owner, ctx, deferStream, ssrSource) {
|
|
|
219
311
|
};
|
|
220
312
|
ctx.serialize(id, tapped, deferStream);
|
|
221
313
|
}
|
|
222
|
-
comp.error = new signals.NotReadyError(
|
|
314
|
+
comp.error = new signals.NotReadyError(deferred.promise);
|
|
223
315
|
}
|
|
224
316
|
return;
|
|
225
317
|
}
|
|
@@ -231,9 +323,9 @@ function closeAsyncIterator(iter, value) {
|
|
|
231
323
|
returned.then(undefined, () => {});
|
|
232
324
|
}
|
|
233
325
|
}
|
|
234
|
-
function serverEffect(compute, effectFn,
|
|
326
|
+
function serverEffect(compute, effectFn, options) {
|
|
235
327
|
const ssrSource = options?.ssrSource;
|
|
236
|
-
if (ssrSource === "client"
|
|
328
|
+
if (ssrSource === "client") {
|
|
237
329
|
signals.createOwner();
|
|
238
330
|
return;
|
|
239
331
|
}
|
|
@@ -241,7 +333,7 @@ function serverEffect(compute, effectFn, value, options) {
|
|
|
241
333
|
const owner = signals.createOwner();
|
|
242
334
|
const comp = {
|
|
243
335
|
owner,
|
|
244
|
-
value:
|
|
336
|
+
value: undefined,
|
|
245
337
|
compute: compute,
|
|
246
338
|
error: undefined,
|
|
247
339
|
computed: true,
|
|
@@ -253,19 +345,19 @@ function serverEffect(compute, effectFn, value, options) {
|
|
|
253
345
|
}));
|
|
254
346
|
}
|
|
255
347
|
try {
|
|
256
|
-
const result = signals.runWithOwner(owner, () => runWithObserver(comp, () => compute(
|
|
348
|
+
const result = signals.runWithOwner(owner, () => runWithObserver(comp, () => compute(undefined)));
|
|
257
349
|
if (ssrSource) {
|
|
258
350
|
processResult(comp, result, owner, ctx, options?.deferStream, ssrSource);
|
|
259
351
|
}
|
|
260
|
-
effectFn?.(ssrSource ? comp.value ?? result : result,
|
|
352
|
+
effectFn?.(ssrSource ? comp.value ?? result : result, undefined);
|
|
261
353
|
} catch (err) {
|
|
262
354
|
}
|
|
263
355
|
}
|
|
264
|
-
function createEffect(compute, effect,
|
|
265
|
-
serverEffect(compute, undefined,
|
|
356
|
+
function createEffect(compute, effect, options) {
|
|
357
|
+
serverEffect(compute, undefined, options);
|
|
266
358
|
}
|
|
267
|
-
function createRenderEffect(compute, effectFn,
|
|
268
|
-
serverEffect(compute, effectFn,
|
|
359
|
+
function createRenderEffect(compute, effectFn, options) {
|
|
360
|
+
serverEffect(compute, effectFn, options);
|
|
269
361
|
}
|
|
270
362
|
function createTrackedEffect(compute, options) {
|
|
271
363
|
const o = signals.getOwner();
|
|
@@ -276,8 +368,8 @@ function createReaction(effectFn, options) {
|
|
|
276
368
|
tracking();
|
|
277
369
|
};
|
|
278
370
|
}
|
|
279
|
-
function createOptimistic(first, second
|
|
280
|
-
return createSignal(first, second
|
|
371
|
+
function createOptimistic(first, second) {
|
|
372
|
+
return createSignal(first, second);
|
|
281
373
|
}
|
|
282
374
|
function setProperty(state, property, value) {
|
|
283
375
|
if (state[property] === value) return;
|
|
@@ -287,7 +379,7 @@ function setProperty(state, property, value) {
|
|
|
287
379
|
}
|
|
288
380
|
function createStore(first, second) {
|
|
289
381
|
if (typeof first === "function") {
|
|
290
|
-
const store = createProjection(first, second
|
|
382
|
+
const store = createProjection(first, second);
|
|
291
383
|
return [store, fn => fn(store)];
|
|
292
384
|
}
|
|
293
385
|
const state = first;
|
|
@@ -310,11 +402,11 @@ function createPendingProxy(state, source) {
|
|
|
310
402
|
pending = false;
|
|
311
403
|
}];
|
|
312
404
|
}
|
|
313
|
-
function createProjection(fn, initialValue
|
|
405
|
+
function createProjection(fn, initialValue, options) {
|
|
314
406
|
const ctx = sharedConfig.context;
|
|
315
407
|
const owner = signals.createOwner();
|
|
316
408
|
const [state] = createStore(initialValue);
|
|
317
|
-
if (options?.ssrSource === "
|
|
409
|
+
if (options?.ssrSource === "client") {
|
|
318
410
|
return state;
|
|
319
411
|
}
|
|
320
412
|
let disposed = false;
|
|
@@ -325,43 +417,69 @@ function createProjection(fn, initialValue = {}, options) {
|
|
|
325
417
|
const useProxy = ssrSource !== "hybrid";
|
|
326
418
|
const patches = [];
|
|
327
419
|
const draft = useProxy ? createDeepProxy(state, patches) : state;
|
|
328
|
-
const
|
|
420
|
+
const runProjection = () => signals.runWithOwner(owner, () => fn(draft));
|
|
421
|
+
const result = runProjection();
|
|
329
422
|
const iteratorFn = result?.[Symbol.asyncIterator];
|
|
330
423
|
if (typeof iteratorFn === "function") {
|
|
331
|
-
const iter = iteratorFn.call(result);
|
|
332
424
|
if (ssrSource === "hybrid") {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
425
|
+
let currentResult = result;
|
|
426
|
+
let iter;
|
|
427
|
+
const deferred = createDeferredPromise();
|
|
428
|
+
const [pending, markReady] = createPendingProxy(state, deferred.promise);
|
|
429
|
+
const runFirst = () => {
|
|
430
|
+
const source = currentResult ?? runProjection();
|
|
431
|
+
currentResult = undefined;
|
|
432
|
+
const nextIterator = source?.[Symbol.asyncIterator];
|
|
433
|
+
if (typeof nextIterator !== "function") {
|
|
434
|
+
throw new Error("Expected async iterator while retrying server createProjection");
|
|
339
435
|
}
|
|
340
|
-
|
|
341
|
-
|
|
436
|
+
iter = nextIterator.call(source);
|
|
437
|
+
return iter.next().then(r => {
|
|
438
|
+
if (!r.done) closeAsyncIterator(iter);
|
|
439
|
+
return r.value;
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
settleServerAsync(runFirst(), runFirst, deferred, value => {
|
|
443
|
+
if (value !== undefined && value !== state) {
|
|
444
|
+
Object.assign(state, value);
|
|
342
445
|
}
|
|
343
|
-
promise.v = state;
|
|
344
446
|
markReady();
|
|
345
447
|
return state;
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
|
|
448
|
+
}, error => {
|
|
449
|
+
markReady();
|
|
450
|
+
}, () => disposed);
|
|
451
|
+
if (ctx?.async && !signals.getContext(NoHydrateContext) && owner.id) ctx.serialize(owner.id, deferred.promise, options?.deferStream);
|
|
349
452
|
return pending;
|
|
350
453
|
} else {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
454
|
+
let currentResult = result;
|
|
455
|
+
let iter;
|
|
456
|
+
let firstResult;
|
|
457
|
+
const deferred = createDeferredPromise();
|
|
458
|
+
const [pending, markReady] = createPendingProxy(state, deferred.promise);
|
|
459
|
+
const runFirst = () => {
|
|
460
|
+
const source = currentResult ?? runProjection();
|
|
461
|
+
currentResult = undefined;
|
|
462
|
+
const nextIterator = source?.[Symbol.asyncIterator];
|
|
463
|
+
if (typeof nextIterator !== "function") {
|
|
464
|
+
throw new Error("Expected async iterator while retrying server createProjection");
|
|
465
|
+
}
|
|
466
|
+
iter = nextIterator.call(source);
|
|
467
|
+
return iter.next().then(value => {
|
|
468
|
+
firstResult = value;
|
|
469
|
+
return Promise.resolve();
|
|
470
|
+
});
|
|
471
|
+
};
|
|
472
|
+
settleServerAsync(runFirst(), runFirst, deferred, () => {
|
|
354
473
|
patches.length = 0;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
474
|
+
const resolved = firstResult;
|
|
475
|
+
if (resolved && !resolved.done && resolved.value !== undefined && resolved.value !== draft) {
|
|
476
|
+
Object.assign(state, resolved.value);
|
|
359
477
|
}
|
|
360
478
|
markReady(JSON.parse(JSON.stringify(state)));
|
|
361
|
-
return
|
|
362
|
-
},
|
|
479
|
+
return undefined;
|
|
480
|
+
}, error => {
|
|
363
481
|
markReady();
|
|
364
|
-
});
|
|
482
|
+
}, () => disposed);
|
|
365
483
|
if (ctx?.async && !signals.getContext(NoHydrateContext) && owner.id) {
|
|
366
484
|
let tappedFirst = true;
|
|
367
485
|
const tapped = {
|
|
@@ -369,8 +487,8 @@ function createProjection(fn, initialValue = {}, options) {
|
|
|
369
487
|
next() {
|
|
370
488
|
if (tappedFirst) {
|
|
371
489
|
tappedFirst = false;
|
|
372
|
-
return
|
|
373
|
-
if (
|
|
490
|
+
return deferred.promise.then(() => {
|
|
491
|
+
if (firstResult?.done) return {
|
|
374
492
|
done: true,
|
|
375
493
|
value: undefined
|
|
376
494
|
};
|
|
@@ -408,26 +526,22 @@ function createProjection(fn, initialValue = {}, options) {
|
|
|
408
526
|
};
|
|
409
527
|
ctx.serialize(owner.id, tapped, options?.deferStream);
|
|
410
528
|
}
|
|
411
|
-
const [pending, markReady] = createPendingProxy(state, firstReady);
|
|
412
529
|
return pending;
|
|
413
530
|
}
|
|
414
531
|
}
|
|
415
532
|
if (result instanceof Promise) {
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
if (v !== undefined && v !== state) {
|
|
423
|
-
Object.assign(state, v);
|
|
533
|
+
const deferred = createDeferredPromise();
|
|
534
|
+
const [pending, markReady] = createPendingProxy(state, deferred.promise);
|
|
535
|
+
settleServerAsync(result, () => runProjection(), deferred, value => {
|
|
536
|
+
if (value !== undefined && value !== state) {
|
|
537
|
+
Object.assign(state, value);
|
|
424
538
|
}
|
|
425
|
-
promise.v = state;
|
|
426
539
|
markReady();
|
|
427
540
|
return state;
|
|
428
|
-
},
|
|
429
|
-
|
|
430
|
-
|
|
541
|
+
}, error => {
|
|
542
|
+
markReady();
|
|
543
|
+
}, () => disposed);
|
|
544
|
+
if (ctx?.async && !signals.getContext(NoHydrateContext) && owner.id) ctx.serialize(owner.id, deferred.promise, options?.deferStream);
|
|
431
545
|
return pending;
|
|
432
546
|
}
|
|
433
547
|
if (result !== undefined && result !== state && result !== draft) {
|
|
@@ -625,10 +739,10 @@ function useContext(context) {
|
|
|
625
739
|
return signals.getContext(context);
|
|
626
740
|
}
|
|
627
741
|
function children(fn) {
|
|
628
|
-
const c = createMemo(fn,
|
|
742
|
+
const c = createMemo(fn, {
|
|
629
743
|
lazy: true
|
|
630
744
|
});
|
|
631
|
-
const memo = createMemo(() => signals.flatten(c()),
|
|
745
|
+
const memo = createMemo(() => signals.flatten(c()), {
|
|
632
746
|
lazy: true
|
|
633
747
|
});
|
|
634
748
|
memo.toArray = () => {
|
|
@@ -712,12 +826,6 @@ function ssrHandleError(err) {
|
|
|
712
826
|
}
|
|
713
827
|
throw err;
|
|
714
828
|
}
|
|
715
|
-
class InvalidTopLevelAsyncReadError extends Error {
|
|
716
|
-
constructor() {
|
|
717
|
-
super("Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).");
|
|
718
|
-
this.name = "InvalidTopLevelAsyncReadError";
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
829
|
function createLoadingBoundary(fn, fallback, options) {
|
|
722
830
|
const currentCtx = sharedConfig.context;
|
|
723
831
|
if (!currentCtx) {
|
|
@@ -732,6 +840,7 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
732
840
|
o.id = id + "00";
|
|
733
841
|
let done;
|
|
734
842
|
let handledRenderError;
|
|
843
|
+
let retryPromise;
|
|
735
844
|
let serializeBuffer = [];
|
|
736
845
|
const bufferedCtx = Object.create(ctx);
|
|
737
846
|
bufferedCtx.serialize = (id, value, deferStream) => {
|
|
@@ -775,21 +884,26 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
775
884
|
function runDiscovery() {
|
|
776
885
|
o.dispose(false);
|
|
777
886
|
serializeBuffer = [];
|
|
887
|
+
retryPromise = undefined;
|
|
778
888
|
return runLoadingPhase(() => {
|
|
779
889
|
try {
|
|
780
890
|
return ctx.resolve(fn());
|
|
781
891
|
} catch (err) {
|
|
782
|
-
if (err instanceof signals.NotReadyError)
|
|
892
|
+
if (err instanceof signals.NotReadyError) {
|
|
893
|
+
retryPromise = err.source;
|
|
894
|
+
return undefined;
|
|
895
|
+
}
|
|
783
896
|
throw err;
|
|
784
897
|
}
|
|
785
898
|
});
|
|
786
899
|
}
|
|
787
900
|
let ret = runDiscovery();
|
|
788
|
-
if (!ret?.p?.length) {
|
|
901
|
+
if (!retryPromise && !ret?.p?.length) {
|
|
789
902
|
commitBoundaryState();
|
|
790
903
|
return () => ret;
|
|
791
904
|
}
|
|
792
|
-
const
|
|
905
|
+
const regResult = revealGroup ? revealGroup.register(id) : null;
|
|
906
|
+
const collapseFallback = regResult?.collapseFallback ?? false;
|
|
793
907
|
if (collapseFallback && !ctx.async) {
|
|
794
908
|
commitBoundaryState();
|
|
795
909
|
ctx.serialize(id, "$$f");
|
|
@@ -810,6 +924,10 @@ function createLoadingBoundary(fn, fallback, options) {
|
|
|
810
924
|
done = ctx.registerFragment(id, regOpts);
|
|
811
925
|
(async () => {
|
|
812
926
|
try {
|
|
927
|
+
while (retryPromise) {
|
|
928
|
+
await retryPromise.catch(() => {});
|
|
929
|
+
ret = runDiscovery();
|
|
930
|
+
}
|
|
813
931
|
commitBoundaryState();
|
|
814
932
|
while (ret.p.length) {
|
|
815
933
|
await Promise.all(ret.p).catch(() => {});
|
|
@@ -912,15 +1030,16 @@ function Loading(props) {
|
|
|
912
1030
|
function Reveal(props) {
|
|
913
1031
|
const o = signals.createOwner();
|
|
914
1032
|
const id = o.id;
|
|
915
|
-
const
|
|
916
|
-
const collapsed = !!props.collapsed;
|
|
1033
|
+
const order = props.order ?? "sequential";
|
|
1034
|
+
const collapsed = order === "sequential" && !!props.collapsed;
|
|
917
1035
|
if (!sharedConfig.context?.async) {
|
|
918
1036
|
const parent = signals.getOwner();
|
|
919
1037
|
const parentGroup = parent ? signals.runWithOwner(parent, () => signals.getContext(RevealGroupContext)) : null;
|
|
920
1038
|
let collapsedByParent = false;
|
|
921
1039
|
if (parentGroup) {
|
|
922
|
-
|
|
923
|
-
|
|
1040
|
+
const reg = parentGroup.register(id);
|
|
1041
|
+
collapsedByParent = reg.collapseFallback;
|
|
1042
|
+
if (order === "together" || collapsed) console.warn("Nested <Reveal> with collapsed/together won't coordinate correctly with renderToString. Use renderToStream for full support.");
|
|
924
1043
|
}
|
|
925
1044
|
let count = 0;
|
|
926
1045
|
return signals.runWithOwner(o, () => {
|
|
@@ -928,8 +1047,11 @@ function Reveal(props) {
|
|
|
928
1047
|
id,
|
|
929
1048
|
register(_key) {
|
|
930
1049
|
count++;
|
|
931
|
-
|
|
932
|
-
return
|
|
1050
|
+
const collapseFallback = collapsedByParent || order === "sequential" && collapsed && count > 1;
|
|
1051
|
+
return {
|
|
1052
|
+
collapseFallback,
|
|
1053
|
+
held: false
|
|
1054
|
+
};
|
|
933
1055
|
},
|
|
934
1056
|
onResolved() {}
|
|
935
1057
|
});
|
|
@@ -939,58 +1061,129 @@ function Reveal(props) {
|
|
|
939
1061
|
const ctx = sharedConfig.context;
|
|
940
1062
|
const keys = [];
|
|
941
1063
|
const resolved = new Set();
|
|
1064
|
+
const minimallyResolved = new Set();
|
|
942
1065
|
const composites = new Map();
|
|
1066
|
+
const activated = new Set();
|
|
1067
|
+
const stash = [];
|
|
1068
|
+
const collapsedLeafKeys = [];
|
|
943
1069
|
let frontier = 0;
|
|
1070
|
+
let heldByParent = false;
|
|
1071
|
+
let collapsedByParent = false;
|
|
1072
|
+
let selfMinimallyResolved = false;
|
|
1073
|
+
let notifiedParentDone = false;
|
|
944
1074
|
const parent = signals.getOwner();
|
|
945
1075
|
const parentGroup = parent ? signals.runWithOwner(parent, () => signals.getContext(RevealGroupContext)) : null;
|
|
946
|
-
let collapsedByParent = false;
|
|
947
1076
|
if (parentGroup) {
|
|
948
|
-
|
|
1077
|
+
const reg = parentGroup.register(id, {
|
|
949
1078
|
onActivate: () => {
|
|
950
|
-
|
|
951
|
-
|
|
1079
|
+
if (!heldByParent) return;
|
|
1080
|
+
heldByParent = false;
|
|
1081
|
+
if (collapsedByParent) {
|
|
1082
|
+
collapsedByParent = false;
|
|
1083
|
+
if (collapsedLeafKeys.length) {
|
|
1084
|
+
ctx.revealFallbacks?.([...collapsedLeafKeys]);
|
|
1085
|
+
collapsedLeafKeys.length = 0;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (order === "sequential") advanceFrontier();else if (order === "together") checkTogetherRelease();else naturalRelease();
|
|
952
1089
|
}
|
|
953
1090
|
});
|
|
1091
|
+
collapsedByParent = reg.collapseFallback;
|
|
1092
|
+
heldByParent = reg.held;
|
|
954
1093
|
}
|
|
955
1094
|
function notifyParentIfDone() {
|
|
1095
|
+
if (notifiedParentDone) return;
|
|
956
1096
|
if (parentGroup && resolved.size === keys.length) {
|
|
1097
|
+
notifiedParentDone = true;
|
|
957
1098
|
parentGroup.onResolved(id);
|
|
958
1099
|
}
|
|
959
1100
|
}
|
|
1101
|
+
function activateComposite(key) {
|
|
1102
|
+
if (activated.has(key)) return;
|
|
1103
|
+
activated.add(key);
|
|
1104
|
+
composites.get(key)();
|
|
1105
|
+
}
|
|
1106
|
+
function updateSelfMinimallyResolved() {
|
|
1107
|
+
if (selfMinimallyResolved) return;
|
|
1108
|
+
if (keys.length === 0) selfMinimallyResolved = true;else if (order === "together") selfMinimallyResolved = minimallyResolved.size === keys.length;else if (order === "sequential") selfMinimallyResolved = minimallyResolved.has(keys[0]);
|
|
1109
|
+
else selfMinimallyResolved = resolved.size > 0;
|
|
1110
|
+
if (selfMinimallyResolved) parentGroup?.onMinimallyResolved?.(id);
|
|
1111
|
+
}
|
|
960
1112
|
function advanceFrontier() {
|
|
1113
|
+
if (heldByParent) return;
|
|
961
1114
|
while (frontier < keys.length && resolved.has(keys[frontier])) {
|
|
962
|
-
|
|
1115
|
+
const k = keys[frontier];
|
|
1116
|
+
if (composites.has(k)) activateComposite(k);else ctx.revealFragments?.([k]);
|
|
963
1117
|
frontier++;
|
|
964
1118
|
}
|
|
965
1119
|
if (frontier < keys.length) {
|
|
966
|
-
const
|
|
967
|
-
if (
|
|
1120
|
+
const k = keys[frontier];
|
|
1121
|
+
if (composites.has(k)) activateComposite(k);else if (order === "sequential" && collapsed) ctx.revealFallbacks?.([k]);
|
|
968
1122
|
}
|
|
969
1123
|
notifyParentIfDone();
|
|
970
1124
|
}
|
|
1125
|
+
function checkTogetherRelease() {
|
|
1126
|
+
if (order !== "together" || heldByParent) return;
|
|
1127
|
+
if (minimallyResolved.size < keys.length) return;
|
|
1128
|
+
if (stash.length) {
|
|
1129
|
+
ctx.revealFragments?.([...stash]);
|
|
1130
|
+
stash.length = 0;
|
|
1131
|
+
}
|
|
1132
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1133
|
+
notifyParentIfDone();
|
|
1134
|
+
}
|
|
1135
|
+
function naturalRelease() {
|
|
1136
|
+
if (stash.length) {
|
|
1137
|
+
ctx.revealFragments?.([...stash]);
|
|
1138
|
+
stash.length = 0;
|
|
1139
|
+
}
|
|
1140
|
+
composites.forEach((_, key) => activateComposite(key));
|
|
1141
|
+
notifyParentIfDone();
|
|
1142
|
+
}
|
|
971
1143
|
return signals.runWithOwner(o, () => {
|
|
972
1144
|
signals.setContext(RevealGroupContext, {
|
|
973
1145
|
id,
|
|
974
1146
|
register(key, options) {
|
|
975
1147
|
keys.push(key);
|
|
976
|
-
|
|
977
|
-
if (
|
|
978
|
-
|
|
1148
|
+
const isComposite = !!options?.onActivate;
|
|
1149
|
+
if (isComposite) composites.set(key, options.onActivate);
|
|
1150
|
+
const selfCollapse = order === "sequential" && collapsed && keys.length > 1;
|
|
1151
|
+
const collapseFallback = collapsedByParent || selfCollapse;
|
|
1152
|
+
if (collapseFallback && !isComposite) collapsedLeafKeys.push(key);
|
|
1153
|
+
let held = heldByParent;
|
|
1154
|
+
if (!held) {
|
|
1155
|
+
if (order === "together") held = true;else if (order === "sequential" && keys.length > 1) held = true;
|
|
1156
|
+
}
|
|
1157
|
+
return {
|
|
1158
|
+
collapseFallback,
|
|
1159
|
+
held
|
|
1160
|
+
};
|
|
979
1161
|
},
|
|
980
1162
|
onResolved(key) {
|
|
981
1163
|
resolved.add(key);
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1164
|
+
const isLeaf = !composites.has(key);
|
|
1165
|
+
if (isLeaf) {
|
|
1166
|
+
if (order === "together") {
|
|
1167
|
+
stash.push(key);
|
|
1168
|
+
} else if (order === "natural" && heldByParent) {
|
|
1169
|
+
stash.push(key);
|
|
1170
|
+
} else if (order === "natural") {
|
|
1171
|
+
ctx.revealFragments?.([key]);
|
|
990
1172
|
}
|
|
1173
|
+
markMinimallyResolved(key);
|
|
1174
|
+
if (order === "sequential" && !heldByParent) advanceFrontier();
|
|
1175
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
991
1176
|
} else {
|
|
992
|
-
|
|
1177
|
+
if (!heldByParent) {
|
|
1178
|
+
if (order === "sequential") advanceFrontier();else if (order === "natural") activateComposite(key);
|
|
1179
|
+
}
|
|
1180
|
+
if (order === "together") checkTogetherRelease();
|
|
1181
|
+
if (order === "natural") updateSelfMinimallyResolved();
|
|
993
1182
|
}
|
|
1183
|
+
notifyParentIfDone();
|
|
1184
|
+
},
|
|
1185
|
+
onMinimallyResolved(key) {
|
|
1186
|
+
markMinimallyResolved(key);
|
|
994
1187
|
}
|
|
995
1188
|
});
|
|
996
1189
|
const result = props.children;
|
|
@@ -999,6 +1192,12 @@ function Reveal(props) {
|
|
|
999
1192
|
}
|
|
1000
1193
|
return result;
|
|
1001
1194
|
});
|
|
1195
|
+
function markMinimallyResolved(key) {
|
|
1196
|
+
if (minimallyResolved.has(key)) return;
|
|
1197
|
+
minimallyResolved.add(key);
|
|
1198
|
+
updateSelfMinimallyResolved();
|
|
1199
|
+
if (order === "together") checkTogetherRelease();
|
|
1200
|
+
}
|
|
1002
1201
|
}
|
|
1003
1202
|
|
|
1004
1203
|
const DEV = undefined;
|