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