@solidjs/web 2.0.0-beta.31 → 2.0.0-beta.32
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/README.md +1 -6
- package/dist/dev.cjs +234 -45
- package/dist/dev.js +221 -42
- package/dist/server.cjs +456 -123
- package/dist/server.js +445 -120
- package/dist/web.cjs +234 -45
- package/dist/web.js +221 -42
- package/frames/dist/client.cjs +217 -112
- package/frames/dist/client.dev.cjs +217 -112
- package/frames/dist/client.dev.js +218 -113
- package/frames/dist/client.js +218 -113
- package/frames/dist/server.cjs +488 -177
- package/frames/dist/server.js +489 -179
- package/package.json +55 -4
- package/serialization/dist/serialization.cjs +8 -0
- package/serialization/dist/serialization.js +1 -0
- package/serialization/types/index.d.ts +173 -6
- package/serialization/types-cjs/index.d.cts +173 -6
- package/server-functions/dist/client.cjs +46 -9
- package/server-functions/dist/client.js +47 -11
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +275 -126
- package/server-functions/dist/server.dev.cjs +1053 -0
- package/server-functions/dist/server.dev.js +1021 -0
- package/server-functions/dist/server.js +273 -127
- package/server-functions/package.json +10 -0
- package/server-functions/rich-args/package.json +20 -0
- package/storage/types/index.d.ts +1 -1
- package/storage/types-cjs/index.d.cts +1 -1
- package/types/client.d.ts +127 -6
- package/types/core.d.ts +3 -1
- package/types/frames/client.d.ts +15 -1
- package/types/frames/frame-client.d.ts +37 -7
- package/types/frames/frame-sink.d.ts +26 -3
- package/types/frames/frame-transport.d.ts +39 -7
- package/types/frames/serializer.d.ts +173 -6
- package/types/frames/server.d.ts +22 -0
- package/types/index.d.ts +2 -3
- package/types/response.d.ts +45 -0
- package/types/serializer.d.ts +173 -6
- package/types/server-functions/client.d.ts +1 -0
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +98 -0
- package/types/server-functions/shared.d.ts +22 -0
- package/types/server-mock.d.ts +171 -59
- package/types/server.d.ts +188 -36
- package/types-cjs/client.d.cts +127 -6
- package/types-cjs/core.d.cts +3 -1
- package/types-cjs/frames/client.d.cts +15 -1
- package/types-cjs/frames/frame-client.d.cts +37 -7
- package/types-cjs/frames/frame-sink.d.cts +26 -3
- package/types-cjs/frames/frame-transport.d.cts +39 -7
- package/types-cjs/frames/serializer.d.cts +173 -6
- package/types-cjs/frames/server.d.cts +22 -0
- package/types-cjs/index.d.cts +2 -3
- package/types-cjs/response.d.cts +45 -0
- package/types-cjs/serializer.d.cts +173 -6
- package/types-cjs/server-functions/client.d.cts +1 -0
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +98 -0
- package/types-cjs/server-functions/shared.d.cts +22 -0
- package/types-cjs/server-mock.d.cts +171 -59
- package/types-cjs/server.d.cts +188 -36
package/frames/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOwner, onCleanup, createMemo, runWithOwner,
|
|
1
|
+
import { getOwner, onCleanup, createMemo, runWithOwner, createSignal, createRenderEffect, createLoadingBoundary, createOwner, sharedConfig } from 'solid-js';
|
|
2
2
|
import { insert } from '@solidjs/web';
|
|
3
3
|
import { createPlugin, fromCrossJSON, Feature } from 'seroval';
|
|
4
4
|
import { ChunkReader, frameAddress, SINGLE_FLIGHT_HEADER, deserializeStream, getServerFunctionsCodec, createChunk, getFlightDataConsumer, ERROR_HEADER, REVALIDATE_HEADER, configureServerFunctionsClient } from '@solidjs/web/server-functions/client';
|
|
@@ -94,9 +94,7 @@ function createFrameHost(options = {}) {
|
|
|
94
94
|
if (store.version !== undefined && version < store.version) return false;
|
|
95
95
|
if (store.version === undefined || version > store.version) {
|
|
96
96
|
store.version = version;
|
|
97
|
-
|
|
98
|
-
if (key.startsWith("seg:") || key === ":error") delete store.records[key];
|
|
99
|
-
}
|
|
97
|
+
clearStreamRecords(store.records);
|
|
100
98
|
}
|
|
101
99
|
Object.assign(store.records, records);
|
|
102
100
|
return true;
|
|
@@ -174,6 +172,7 @@ class FrameImpl {
|
|
|
174
172
|
#store = Object.create(null);
|
|
175
173
|
#appliedRootValue;
|
|
176
174
|
#hasContent = false;
|
|
175
|
+
#errorNotified = false;
|
|
177
176
|
#revealed = new Set();
|
|
178
177
|
#fallbackShown = new Set();
|
|
179
178
|
#slots;
|
|
@@ -193,10 +192,12 @@ class FrameImpl {
|
|
|
193
192
|
#claimTree = (node, direct) => {
|
|
194
193
|
const handlers = claimHandlers();
|
|
195
194
|
if (!handlers) return;
|
|
196
|
-
|
|
197
|
-
const scope = this.#options.ownerScope;
|
|
198
|
-
scope ? scope(run) : run();
|
|
195
|
+
this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
|
|
199
196
|
};
|
|
197
|
+
#scoped(fn) {
|
|
198
|
+
const scope = this.#options.ownerScope;
|
|
199
|
+
return scope ? scope(fn) : fn();
|
|
200
|
+
}
|
|
200
201
|
constructor(element, start, end, options = {}) {
|
|
201
202
|
this.#element = element;
|
|
202
203
|
this.#start = start;
|
|
@@ -257,15 +258,9 @@ class FrameImpl {
|
|
|
257
258
|
return;
|
|
258
259
|
} else if (v > this.#version) {
|
|
259
260
|
this.#version = v;
|
|
260
|
-
this.#
|
|
261
|
-
this.#fallbackShown.clear();
|
|
262
|
-
for (const key of Object.keys(this.#store)) {
|
|
263
|
-
if (key.startsWith("seg:") || key === ":error") {
|
|
264
|
-
delete this.#store[key];
|
|
265
|
-
}
|
|
266
|
-
}
|
|
261
|
+
this.#resetStreamState();
|
|
267
262
|
}
|
|
268
|
-
for (const key
|
|
263
|
+
for (const key in write.r) {
|
|
269
264
|
const incoming = write.r[key];
|
|
270
265
|
if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
|
|
271
266
|
const existing = this.#store[key];
|
|
@@ -277,6 +272,12 @@ class FrameImpl {
|
|
|
277
272
|
}
|
|
278
273
|
this.#flush();
|
|
279
274
|
}
|
|
275
|
+
#resetStreamState(root) {
|
|
276
|
+
this.#revealed.clear();
|
|
277
|
+
this.#fallbackShown.clear();
|
|
278
|
+
this.#errorNotified = false;
|
|
279
|
+
clearStreamRecords(this.#store, root);
|
|
280
|
+
}
|
|
280
281
|
#flush() {
|
|
281
282
|
if (this.#disposed) return;
|
|
282
283
|
const version = this.#version;
|
|
@@ -287,10 +288,14 @@ class FrameImpl {
|
|
|
287
288
|
this.#appliedRootValue = root.value;
|
|
288
289
|
this.#applied(version, reason);
|
|
289
290
|
}
|
|
291
|
+
if (this.#store[":error"] && !this.#errorNotified) {
|
|
292
|
+
this.#errorNotified = true;
|
|
293
|
+
this.#applied(version, "error");
|
|
294
|
+
}
|
|
290
295
|
let progressed = true;
|
|
291
296
|
while (progressed) {
|
|
292
297
|
progressed = false;
|
|
293
|
-
for (const key
|
|
298
|
+
for (const key in this.#store) {
|
|
294
299
|
const name = segmentName(key);
|
|
295
300
|
if (name === null || this.#revealed.has(name)) continue;
|
|
296
301
|
if (this.#segmentReady(name)) {
|
|
@@ -299,7 +304,7 @@ class FrameImpl {
|
|
|
299
304
|
progressed = true;
|
|
300
305
|
}
|
|
301
306
|
}
|
|
302
|
-
for (const key
|
|
307
|
+
for (const key in this.#store) {
|
|
303
308
|
const m = /^seg:([^:]+):fallback$/.exec(key);
|
|
304
309
|
if (!m) continue;
|
|
305
310
|
const name = m[1];
|
|
@@ -311,7 +316,7 @@ class FrameImpl {
|
|
|
311
316
|
}
|
|
312
317
|
}
|
|
313
318
|
}
|
|
314
|
-
for (const key
|
|
319
|
+
for (const key in this.#store) {
|
|
315
320
|
if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
|
|
316
321
|
this.#processedAssets.add(key);
|
|
317
322
|
const record = this.#store[key];
|
|
@@ -343,6 +348,7 @@ class FrameImpl {
|
|
|
343
348
|
const callback = this.#resolveSlot(propOf(occurrence));
|
|
344
349
|
if (!callback) continue;
|
|
345
350
|
const record = this.#resolveSlotRecord(occurrence);
|
|
351
|
+
if (record && record.kind === "slot" && this.#refsUnresolved(record.args)) continue;
|
|
346
352
|
const prev = this.#slotNodes.get(occurrence);
|
|
347
353
|
const prevFirst = Array.isArray(prev) ? prev[0] : prev;
|
|
348
354
|
const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
|
|
@@ -398,15 +404,7 @@ class FrameImpl {
|
|
|
398
404
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
399
405
|
let existing = [];
|
|
400
406
|
let end = null;
|
|
401
|
-
if (start)
|
|
402
|
-
const endData = slotEnd(occurrence);
|
|
403
|
-
let n = start.nextSibling;
|
|
404
|
-
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
405
|
-
existing.push(n);
|
|
406
|
-
n = n.nextSibling;
|
|
407
|
-
}
|
|
408
|
-
end = n;
|
|
409
|
-
}
|
|
407
|
+
if (start) end = eachInRange(start, occurrence, n => existing.push(n));
|
|
410
408
|
const ctx = {
|
|
411
409
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
412
410
|
key: occurrence,
|
|
@@ -421,23 +419,16 @@ class FrameImpl {
|
|
|
421
419
|
} : undefined
|
|
422
420
|
};
|
|
423
421
|
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
424
|
-
const
|
|
425
|
-
const content = scope ? scope(() => callback(props, ctx)) : callback(props, ctx);
|
|
422
|
+
const content = this.#scoped(() => callback(props, ctx));
|
|
426
423
|
this.#slotArgs.set(occurrence, record);
|
|
427
424
|
if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
|
|
428
425
|
if (content == null) return null;
|
|
429
426
|
return Array.isArray(content) ? content : [content];
|
|
430
427
|
}
|
|
431
428
|
#replaceRange(key, start, nodes) {
|
|
432
|
-
const end = slotEnd(key);
|
|
433
429
|
const parent = start.parentNode;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const next = n.nextSibling;
|
|
437
|
-
parent.removeChild(n);
|
|
438
|
-
n = next;
|
|
439
|
-
}
|
|
440
|
-
for (const node of nodes) parent.insertBefore(node, n);
|
|
430
|
+
const end = eachInRange(start, key, n => parent.removeChild(n));
|
|
431
|
+
for (const node of nodes) parent.insertBefore(node, end);
|
|
441
432
|
}
|
|
442
433
|
#unmountSlot(key) {
|
|
443
434
|
this.#mountedSlots.delete(key);
|
|
@@ -449,9 +440,7 @@ class FrameImpl {
|
|
|
449
440
|
this.#runSlotCleanups(key);
|
|
450
441
|
const regions = this.#slotRegions.get(key);
|
|
451
442
|
if (regions) {
|
|
452
|
-
|
|
453
|
-
frame
|
|
454
|
-
} of regions.values()) frame?.dispose();
|
|
443
|
+
disposeRegions(regions);
|
|
455
444
|
this.#slotRegions.delete(key);
|
|
456
445
|
}
|
|
457
446
|
}
|
|
@@ -461,15 +450,26 @@ class FrameImpl {
|
|
|
461
450
|
this.#slotCleanups.delete(key);
|
|
462
451
|
for (const fn of cleanups) fn();
|
|
463
452
|
}
|
|
453
|
+
#refsUnresolved(args) {
|
|
454
|
+
const {
|
|
455
|
+
host,
|
|
456
|
+
id
|
|
457
|
+
} = this.#options;
|
|
458
|
+
if (host) for (const key in args) {
|
|
459
|
+
if (isDataRef(args[key]) && host.resolve(args[key], id) === undefined) return true;
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
#regionsFor(slotKey) {
|
|
464
|
+
let regions = this.#slotRegions.get(slotKey);
|
|
465
|
+
if (!regions) this.#slotRegions.set(slotKey, regions = new Map());
|
|
466
|
+
return regions;
|
|
467
|
+
}
|
|
464
468
|
#resolveArgs(slotKey, args) {
|
|
465
469
|
const host = this.#options.host;
|
|
466
|
-
|
|
467
|
-
if (!regions) {
|
|
468
|
-
regions = new Map();
|
|
469
|
-
this.#slotRegions.set(slotKey, regions);
|
|
470
|
-
}
|
|
470
|
+
const regions = this.#regionsFor(slotKey);
|
|
471
471
|
const props = {};
|
|
472
|
-
for (const key
|
|
472
|
+
for (const key in args) {
|
|
473
473
|
const value = args[key];
|
|
474
474
|
if (isDataRef(value)) {
|
|
475
475
|
const resolved = host ? host.resolve(value, this.#options.id) : undefined;
|
|
@@ -499,17 +499,8 @@ class FrameImpl {
|
|
|
499
499
|
}
|
|
500
500
|
#discoverRegions(slotKey, start) {
|
|
501
501
|
if (!start) return;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
regions = new Map();
|
|
505
|
-
this.#slotRegions.set(slotKey, regions);
|
|
506
|
-
}
|
|
507
|
-
const endData = slotEnd(slotKey);
|
|
508
|
-
let n = start.nextSibling;
|
|
509
|
-
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
510
|
-
collectRegionElements(n, regions);
|
|
511
|
-
n = n.nextSibling;
|
|
512
|
-
}
|
|
502
|
+
const regions = this.#regionsFor(slotKey);
|
|
503
|
+
eachInRange(start, slotKey, n => collectRegionElements(n, regions));
|
|
513
504
|
}
|
|
514
505
|
#refArgsUnchanged(occurrence, record) {
|
|
515
506
|
const old = this.#slotArgs.get(occurrence);
|
|
@@ -525,11 +516,11 @@ class FrameImpl {
|
|
|
525
516
|
const va = a[key];
|
|
526
517
|
const vb = b[key];
|
|
527
518
|
if (va === vb) continue;
|
|
528
|
-
if (
|
|
529
|
-
if (
|
|
530
|
-
if (typeof va.$ref === "string" && typeof vb.$ref === "string" && cache && key in cache) {
|
|
519
|
+
if (isFrameRef(va) && isFrameRef(vb)) continue;
|
|
520
|
+
if (isDataRef(va) && isDataRef(vb) && cache && key in cache) {
|
|
531
521
|
const host = this.#options.host;
|
|
532
522
|
const next = host ? host.resolve(vb, this.#options.id) : undefined;
|
|
523
|
+
if (isAsyncLike(next) || isAsyncLike(cache[key])) return false;
|
|
533
524
|
try {
|
|
534
525
|
if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
|
|
535
526
|
} catch (e) {
|
|
@@ -545,7 +536,7 @@ class FrameImpl {
|
|
|
545
536
|
if (!args) return;
|
|
546
537
|
const regions = this.#slotRegions.get(occurrence);
|
|
547
538
|
if (!regions) return;
|
|
548
|
-
for (const key
|
|
539
|
+
for (const key in args) {
|
|
549
540
|
const value = args[key];
|
|
550
541
|
if (!isFrameRef(value)) continue;
|
|
551
542
|
const entry = regions.get(key);
|
|
@@ -595,11 +586,8 @@ class FrameImpl {
|
|
|
595
586
|
this.#element.setAttribute(FRAME_ID_ATTR, id);
|
|
596
587
|
}
|
|
597
588
|
this.#version = undefined;
|
|
598
|
-
this.#
|
|
599
|
-
this.#
|
|
600
|
-
for (const key of Object.keys(this.#store)) {
|
|
601
|
-
if (key.startsWith("seg:") || key === ":error") delete this.#store[key];
|
|
602
|
-
}
|
|
589
|
+
this.#appliedRootValue = undefined;
|
|
590
|
+
this.#resetStreamState(true);
|
|
603
591
|
if (host) host.register(id, this);
|
|
604
592
|
}
|
|
605
593
|
rebase() {
|
|
@@ -619,11 +607,7 @@ class FrameImpl {
|
|
|
619
607
|
}
|
|
620
608
|
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
621
609
|
for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
|
|
622
|
-
for (const regions of this.#slotRegions.values())
|
|
623
|
-
for (const {
|
|
624
|
-
frame
|
|
625
|
-
} of regions.values()) frame?.dispose();
|
|
626
|
-
}
|
|
610
|
+
for (const regions of this.#slotRegions.values()) disposeRegions(regions);
|
|
627
611
|
this.#slotRegions.clear();
|
|
628
612
|
this.#mountedSlots.clear();
|
|
629
613
|
}
|
|
@@ -645,13 +629,7 @@ class FrameImpl {
|
|
|
645
629
|
}
|
|
646
630
|
}
|
|
647
631
|
#clearContent() {
|
|
648
|
-
|
|
649
|
-
let n = this.#firstContent();
|
|
650
|
-
while (n && n !== this.#end) {
|
|
651
|
-
const next = n.nextSibling;
|
|
652
|
-
parent.removeChild(n);
|
|
653
|
-
n = next;
|
|
654
|
-
}
|
|
632
|
+
removeUntil(this.#parent(), this.#firstContent(), this.#end);
|
|
655
633
|
}
|
|
656
634
|
#claimContent() {
|
|
657
635
|
if (!claimHandlers()) return;
|
|
@@ -668,9 +646,7 @@ class FrameImpl {
|
|
|
668
646
|
const assets = this.#store[`seg:${name}:assets`];
|
|
669
647
|
if (assets && assets.styles) {
|
|
670
648
|
let ready = true;
|
|
671
|
-
for (const entry of assets.styles)
|
|
672
|
-
if (!ensureStylesheet(entry, this.#styleFlush)) ready = false;
|
|
673
|
-
}
|
|
649
|
+
for (const entry of assets.styles) ready = ensureStylesheet(entry, this.#styleFlush) && ready;
|
|
674
650
|
if (!ready) return false;
|
|
675
651
|
}
|
|
676
652
|
if (!this.#findPlaceholder(name)) return false;
|
|
@@ -684,12 +660,7 @@ class FrameImpl {
|
|
|
684
660
|
const content = this.#store[`seg:${name}`];
|
|
685
661
|
const closing = rangeClose(tpl, placeholderId(name));
|
|
686
662
|
const parent = tpl.parentNode;
|
|
687
|
-
|
|
688
|
-
while (n && n !== closing) {
|
|
689
|
-
const next = n.nextSibling;
|
|
690
|
-
parent.removeChild(n);
|
|
691
|
-
n = next;
|
|
692
|
-
}
|
|
663
|
+
removeUntil(parent, tpl.nextSibling, closing);
|
|
693
664
|
if (this.#options.reveal) {
|
|
694
665
|
const fallbackFrag = tpl.content.cloneNode(true);
|
|
695
666
|
this.#claimTree(fallbackFrag);
|
|
@@ -738,9 +709,7 @@ function createFrameElement(options) {
|
|
|
738
709
|
const frame = new FrameImpl(el, null, null, options);
|
|
739
710
|
return {
|
|
740
711
|
element: el,
|
|
741
|
-
|
|
742
|
-
return frame;
|
|
743
|
-
},
|
|
712
|
+
frame,
|
|
744
713
|
dispose() {
|
|
745
714
|
frame.dispose();
|
|
746
715
|
el.remove();
|
|
@@ -760,15 +729,30 @@ function segmentName(key) {
|
|
|
760
729
|
const m = /^seg:([^:]+)$/.exec(key);
|
|
761
730
|
return m ? m[1] : null;
|
|
762
731
|
}
|
|
732
|
+
function isAsyncLike(v) {
|
|
733
|
+
return !!v && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
734
|
+
}
|
|
763
735
|
function propOf(occurrence) {
|
|
764
736
|
const hash = occurrence.indexOf("#");
|
|
765
737
|
return hash === -1 ? occurrence : occurrence.slice(0, hash);
|
|
766
738
|
}
|
|
767
739
|
function isDataRef(value) {
|
|
768
|
-
return
|
|
740
|
+
return !!value && typeof value.$ref === "string";
|
|
769
741
|
}
|
|
770
742
|
function isFrameRef(value) {
|
|
771
|
-
return
|
|
743
|
+
return !!value && typeof value.$frame === "string";
|
|
744
|
+
}
|
|
745
|
+
function disposeRegions(regions) {
|
|
746
|
+
for (const {
|
|
747
|
+
frame
|
|
748
|
+
} of regions.values()) frame?.dispose();
|
|
749
|
+
}
|
|
750
|
+
function removeUntil(parent, n, stop) {
|
|
751
|
+
while (n && n !== stop) {
|
|
752
|
+
const next = n.nextSibling;
|
|
753
|
+
parent.removeChild(n);
|
|
754
|
+
n = next;
|
|
755
|
+
}
|
|
772
756
|
}
|
|
773
757
|
function parseFragment(html) {
|
|
774
758
|
const template = document.createElement("template");
|
|
@@ -776,9 +760,8 @@ function parseFragment(html) {
|
|
|
776
760
|
return template.content;
|
|
777
761
|
}
|
|
778
762
|
function findHeadElement(selector, attr, value) {
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
if (nodes[i].getAttribute(attr) === value) return nodes[i];
|
|
763
|
+
for (const node of document.head.querySelectorAll(selector)) {
|
|
764
|
+
if (node.getAttribute(attr) === value) return node;
|
|
782
765
|
}
|
|
783
766
|
return null;
|
|
784
767
|
}
|
|
@@ -827,7 +810,7 @@ function applyInlineStyles(inlineStyles) {
|
|
|
827
810
|
}
|
|
828
811
|
}
|
|
829
812
|
function isPlaceholderStart(node, id) {
|
|
830
|
-
return node.
|
|
813
|
+
return node.tagName === "TEMPLATE" && node.id === id;
|
|
831
814
|
}
|
|
832
815
|
function rangeClose(start, id) {
|
|
833
816
|
let n = start.nextSibling;
|
|
@@ -883,6 +866,21 @@ function renameRegion(entry, childId) {
|
|
|
883
866
|
entry.childId = childId;
|
|
884
867
|
if (entry.frame) entry.frame.rebind(childId);else entry.element.setAttribute(FRAME_ID_ATTR, childId);
|
|
885
868
|
}
|
|
869
|
+
function eachInRange(start, key, cb) {
|
|
870
|
+
const end = slotEnd(key);
|
|
871
|
+
let n = start.nextSibling;
|
|
872
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
|
|
873
|
+
const next = n.nextSibling;
|
|
874
|
+
cb(n);
|
|
875
|
+
n = next;
|
|
876
|
+
}
|
|
877
|
+
return n;
|
|
878
|
+
}
|
|
879
|
+
function clearStreamRecords(records, root) {
|
|
880
|
+
for (const key in records) {
|
|
881
|
+
if (key.startsWith("seg:") || key === ":error" || root && key === "") delete records[key];
|
|
882
|
+
}
|
|
883
|
+
}
|
|
886
884
|
function argsEquivalent(a, b) {
|
|
887
885
|
if (a === b) return true;
|
|
888
886
|
if (!a || !b) return false;
|
|
@@ -893,9 +891,7 @@ function argsEquivalent(a, b) {
|
|
|
893
891
|
const va = a[key];
|
|
894
892
|
const vb = b[key];
|
|
895
893
|
if (va === vb) continue;
|
|
896
|
-
if (va &&
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
894
|
+
if (isFrameRef(va) && va.$frame === vb?.$frame) continue;
|
|
899
895
|
return false;
|
|
900
896
|
}
|
|
901
897
|
return true;
|
|
@@ -1258,7 +1254,7 @@ function createServerComponentHandler({
|
|
|
1258
1254
|
showing(address, functionId) {
|
|
1259
1255
|
bindingFor(address, functionId);
|
|
1260
1256
|
const comp = componentFor(functionId);
|
|
1261
|
-
if ((typeof comp === "function" || typeof comp === "object"
|
|
1257
|
+
if (comp && (typeof comp === "function" || typeof comp === "object") && !comp[COMPONENT_BINDING]) {
|
|
1262
1258
|
comp[COMPONENT_BINDING] = {
|
|
1263
1259
|
component: comp,
|
|
1264
1260
|
address
|
|
@@ -1350,6 +1346,9 @@ function createJSONDataTable(options) {
|
|
|
1350
1346
|
};
|
|
1351
1347
|
}
|
|
1352
1348
|
|
|
1349
|
+
function asyncArg(value) {
|
|
1350
|
+
return value;
|
|
1351
|
+
}
|
|
1353
1352
|
let sharedHost;
|
|
1354
1353
|
const tables = new Map();
|
|
1355
1354
|
function tableFor(id) {
|
|
@@ -1426,8 +1425,26 @@ function claimRender(prefix, existing, render) {
|
|
|
1426
1425
|
function liveSlotProps(initial, ctx) {
|
|
1427
1426
|
const [args, setArgs] = createSignal(initial);
|
|
1428
1427
|
ctx.onUpdate(next => setArgs(() => next));
|
|
1428
|
+
return slotArgsProxy(args);
|
|
1429
|
+
}
|
|
1430
|
+
function isAsyncValue(v) {
|
|
1431
|
+
return v !== null && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
1432
|
+
}
|
|
1433
|
+
function slotArgsProxy(args) {
|
|
1434
|
+
const owner = getOwner();
|
|
1435
|
+
const asyncReads = new Map();
|
|
1429
1436
|
return new Proxy({}, {
|
|
1430
|
-
get: (_, key) =>
|
|
1437
|
+
get: (_, key) => {
|
|
1438
|
+
const v = args()[key];
|
|
1439
|
+
if (!isAsyncValue(v)) return v;
|
|
1440
|
+
let read = asyncReads.get(key);
|
|
1441
|
+
if (!read) {
|
|
1442
|
+
const make = () => createMemo(() => args()[key]);
|
|
1443
|
+
read = owner ? runWithOwner(owner, make) : make();
|
|
1444
|
+
asyncReads.set(key, read);
|
|
1445
|
+
}
|
|
1446
|
+
return read();
|
|
1447
|
+
},
|
|
1431
1448
|
has: (_, key) => key in args(),
|
|
1432
1449
|
ownKeys: () => Reflect.ownKeys(args()),
|
|
1433
1450
|
getOwnPropertyDescriptor: (_, key) => key in args() ? {
|
|
@@ -1445,6 +1462,7 @@ function isReactiveContent(value) {
|
|
|
1445
1462
|
}
|
|
1446
1463
|
function slotsFor(props) {
|
|
1447
1464
|
const bindings = new Map();
|
|
1465
|
+
const fillScopes = new Map();
|
|
1448
1466
|
return new Proxy({}, {
|
|
1449
1467
|
get(_, prop) {
|
|
1450
1468
|
if (typeof prop !== "string" || !(prop in props)) return undefined;
|
|
@@ -1455,6 +1473,19 @@ function slotsFor(props) {
|
|
|
1455
1473
|
bindings.delete(key);
|
|
1456
1474
|
prev.dispose();
|
|
1457
1475
|
}
|
|
1476
|
+
const prevFill = key !== undefined && fillScopes.get(key);
|
|
1477
|
+
if (prevFill) {
|
|
1478
|
+
fillScopes.delete(key);
|
|
1479
|
+
prevFill.dispose();
|
|
1480
|
+
}
|
|
1481
|
+
const fillOwner = streamInvoke ? createOwner() : null;
|
|
1482
|
+
if (fillOwner && key !== undefined && ctx) {
|
|
1483
|
+
fillScopes.set(key, fillOwner);
|
|
1484
|
+
ctx.onCleanup(() => {
|
|
1485
|
+
if (fillScopes.get(key) === fillOwner) fillScopes.delete(key);
|
|
1486
|
+
fillOwner.dispose();
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1458
1489
|
const settle = out => {
|
|
1459
1490
|
const existing = ctx && ctx.existing || [];
|
|
1460
1491
|
if (existing.length) {
|
|
@@ -1467,13 +1498,13 @@ function slotsFor(props) {
|
|
|
1467
1498
|
const evaluate = () => {
|
|
1468
1499
|
const v = props[prop];
|
|
1469
1500
|
if (typeof v === "function" && ctx && ctx.invoked) {
|
|
1470
|
-
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotProps);
|
|
1501
|
+
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotArgsProxy(() => slotProps));
|
|
1471
1502
|
}
|
|
1472
1503
|
return v;
|
|
1473
1504
|
};
|
|
1474
1505
|
const adopted = !!(ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length);
|
|
1475
1506
|
const prefix = ctx && ctx.frame ? `sc-${ctx.frame}-${ctx.key}-` : "";
|
|
1476
|
-
const value = adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1507
|
+
const value = fillOwner ? runWithOwner(fillOwner, () => adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate()) : adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1477
1508
|
if (!isReactiveContent(value)) {
|
|
1478
1509
|
return settle(normalizeSlotContent(value));
|
|
1479
1510
|
}
|
|
@@ -1498,29 +1529,61 @@ function slotsFor(props) {
|
|
|
1498
1529
|
function revealSeam(owner) {
|
|
1499
1530
|
return seam => runWithOwner(owner, () => insert(seam.before.parentNode, createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
|
|
1500
1531
|
}
|
|
1532
|
+
let streamInvoke = false;
|
|
1501
1533
|
function boundaryScope(owner) {
|
|
1502
|
-
return fn =>
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1534
|
+
return fn => {
|
|
1535
|
+
if (getOwner()) return fn();
|
|
1536
|
+
streamInvoke = true;
|
|
1537
|
+
try {
|
|
1538
|
+
return runWithOwner(owner, fn);
|
|
1539
|
+
} finally {
|
|
1540
|
+
streamInvoke = false;
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1506
1543
|
}
|
|
1507
1544
|
function boundaryComponent(host, fnId) {
|
|
1508
1545
|
return (props, binding) => {
|
|
1509
1546
|
const owner = getOwner();
|
|
1547
|
+
const id = binding ? binding() : fnId;
|
|
1548
|
+
let applied = !tables.has(id);
|
|
1549
|
+
let release;
|
|
1550
|
+
const arm = () => new Promise(r => release = r);
|
|
1551
|
+
const mountGate = applied ? undefined : arm();
|
|
1552
|
+
let setGate;
|
|
1510
1553
|
const {
|
|
1511
1554
|
element,
|
|
1512
1555
|
frame,
|
|
1513
1556
|
dispose
|
|
1514
1557
|
} = createFrameElement({
|
|
1515
1558
|
host,
|
|
1516
|
-
id
|
|
1559
|
+
id,
|
|
1517
1560
|
slots: slotsFor(props),
|
|
1518
1561
|
ownerScope: boundaryScope(owner),
|
|
1519
|
-
reveal: revealSeam(owner)
|
|
1562
|
+
reveal: revealSeam(owner),
|
|
1563
|
+
onApply: () => {
|
|
1564
|
+
applied = true;
|
|
1565
|
+
if (release) {
|
|
1566
|
+
release();
|
|
1567
|
+
release = undefined;
|
|
1568
|
+
}
|
|
1569
|
+
setGate && setGate(undefined);
|
|
1570
|
+
}
|
|
1520
1571
|
});
|
|
1521
|
-
|
|
1572
|
+
const [gatePromise, setGatePromise] = createSignal(applied ? undefined : mountGate);
|
|
1573
|
+
setGate = setGatePromise;
|
|
1574
|
+
if (binding) {
|
|
1575
|
+
createRenderEffect(binding, (address, prev) => {
|
|
1576
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1577
|
+
applied = false;
|
|
1578
|
+
setGatePromise(arm());
|
|
1579
|
+
}
|
|
1580
|
+
frame.rebind(address);
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1522
1583
|
onCleanup(dispose);
|
|
1523
|
-
return element;
|
|
1584
|
+
if (applied && !binding) return element;
|
|
1585
|
+
const gate = createMemo(() => gatePromise());
|
|
1586
|
+
return createMemo(() => (gate(), element));
|
|
1524
1587
|
};
|
|
1525
1588
|
}
|
|
1526
1589
|
const claimedBoundaries = new Set();
|
|
@@ -1588,6 +1651,17 @@ function adoptBoundary(host, id, el, props, binding) {
|
|
|
1588
1651
|
claimedBoundaries.add(id);
|
|
1589
1652
|
const address = binding ? binding() : documentAddress(id);
|
|
1590
1653
|
const appliedRecords = new Set();
|
|
1654
|
+
const claimedFragments = new Set();
|
|
1655
|
+
const claimRegionFragments = root => {
|
|
1656
|
+
const fr = globalThis._$HY?.fr;
|
|
1657
|
+
if (!fr || !fr.claim) return;
|
|
1658
|
+
root.querySelectorAll('template[id^="pl-"]').forEach(tpl => {
|
|
1659
|
+
const fragId = tpl.id.slice(3);
|
|
1660
|
+
if (claimedFragments.has(fragId)) return;
|
|
1661
|
+
claimedFragments.add(fragId);
|
|
1662
|
+
fr.claim(fragId);
|
|
1663
|
+
});
|
|
1664
|
+
};
|
|
1591
1665
|
const drainRecords = () => {
|
|
1592
1666
|
const hy = globalThis._$HY;
|
|
1593
1667
|
if (!hy || !hy.r) return;
|
|
@@ -1619,8 +1693,20 @@ function adoptBoundary(host, id, el, props, binding) {
|
|
|
1619
1693
|
}
|
|
1620
1694
|
}
|
|
1621
1695
|
};
|
|
1696
|
+
claimRegionFragments(el);
|
|
1697
|
+
const fr = globalThis._$HY?.fr;
|
|
1698
|
+
const unsubscribe = fr ? fr.subscribe((_fragId, parent) => {
|
|
1699
|
+
if (fr.claim && parent && el.contains(parent)) claimRegionFragments(parent);
|
|
1700
|
+
drainRecords();
|
|
1701
|
+
}) : undefined;
|
|
1702
|
+
onCleanup(() => {
|
|
1703
|
+
unsubscribe && unsubscribe();
|
|
1704
|
+
if (fr && fr.release) for (const fragId of claimedFragments) fr.release(fragId);
|
|
1705
|
+
});
|
|
1622
1706
|
drainRecords();
|
|
1623
1707
|
const owner = getOwner();
|
|
1708
|
+
let release;
|
|
1709
|
+
let setGate;
|
|
1624
1710
|
const frame = createFrame(el, {
|
|
1625
1711
|
adopt: true,
|
|
1626
1712
|
host,
|
|
@@ -1628,6 +1714,13 @@ function adoptBoundary(host, id, el, props, binding) {
|
|
|
1628
1714
|
slots: slotsFor(props),
|
|
1629
1715
|
ownerScope: boundaryScope(owner),
|
|
1630
1716
|
reveal: revealSeam(owner),
|
|
1717
|
+
onApply: () => {
|
|
1718
|
+
if (release) {
|
|
1719
|
+
release();
|
|
1720
|
+
release = undefined;
|
|
1721
|
+
}
|
|
1722
|
+
setGate && setGate(undefined);
|
|
1723
|
+
},
|
|
1631
1724
|
...{
|
|
1632
1725
|
recordsPending: () => {
|
|
1633
1726
|
if (document.readyState === "loading") return true;
|
|
@@ -1638,7 +1731,19 @@ function adoptBoundary(host, id, el, props, binding) {
|
|
|
1638
1731
|
claimScope: id
|
|
1639
1732
|
}
|
|
1640
1733
|
});
|
|
1641
|
-
if (binding)
|
|
1734
|
+
if (binding) {
|
|
1735
|
+
const arm = () => new Promise(r => release = r);
|
|
1736
|
+
const [gatePromise, setGatePromise] = createSignal(undefined);
|
|
1737
|
+
setGate = setGatePromise;
|
|
1738
|
+
const gate = createMemo(() => gatePromise());
|
|
1739
|
+
createRenderEffect(binding, (address, prev) => {
|
|
1740
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1741
|
+
setGatePromise(arm());
|
|
1742
|
+
}
|
|
1743
|
+
frame.rebind(address);
|
|
1744
|
+
});
|
|
1745
|
+
createRenderEffect(() => (gate(), undefined), () => {});
|
|
1746
|
+
}
|
|
1642
1747
|
onCleanup(() => frame.dispose());
|
|
1643
1748
|
return el;
|
|
1644
1749
|
}
|
|
@@ -1679,4 +1784,4 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1679
1784
|
});
|
|
1680
1785
|
}
|
|
1681
1786
|
|
|
1682
|
-
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, createFrame, createFrameElement, createFrameHost,
|
|
1787
|
+
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, asyncArg, createFrame, createFrameElement, createFrameHost, createServerComponentHandler, getFrameHost, installServerComponents, isFrameStreamResponse };
|