@solidjs/web 2.0.0-beta.30 → 2.0.0-beta.31
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 +52 -39
- package/dist/dev.js +53 -40
- package/dist/server.cjs +99 -12
- package/dist/server.js +99 -12
- package/dist/web.cjs +49 -36
- package/dist/web.js +50 -37
- package/frames/dist/client.cjs +208 -260
- package/frames/dist/client.dev.cjs +208 -260
- package/frames/dist/client.dev.js +209 -261
- package/frames/dist/client.js +209 -261
- package/frames/dist/server.cjs +116 -22
- package/frames/dist/server.js +116 -22
- package/package.json +4 -5
- package/types/client.d.ts +7 -5
- package/types/frames/client.d.ts +9 -7
- package/types/frames/frame-client.d.ts +12 -0
- package/types/frames/frame-sink.d.ts +6 -3
- package/types/frames/frame-transport.d.ts +50 -56
- package/types/jsx.d.ts +3 -3
- package/types/server.d.ts +8 -6
- package/types-cjs/client.d.cts +7 -5
- package/types-cjs/frames/client.d.cts +9 -7
- package/types-cjs/frames/frame-client.d.cts +12 -0
- package/types-cjs/frames/frame-sink.d.cts +6 -3
- package/types-cjs/frames/frame-transport.d.cts +50 -56
- package/types-cjs/jsx.d.cts +3 -3
- package/types-cjs/server.d.cts +8 -6
package/frames/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOwner, onCleanup, createMemo, runWithOwner, createLoadingBoundary, createOwner, sharedConfig, createSignal } from 'solid-js';
|
|
1
|
+
import { getOwner, onCleanup, createMemo, runWithOwner, createLoadingBoundary, createOwner, createRenderEffect, sharedConfig, createSignal } 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';
|
|
@@ -81,98 +81,75 @@ function chunkToRecords(chunk) {
|
|
|
81
81
|
}
|
|
82
82
|
function createFrameHost(options = {}) {
|
|
83
83
|
const frames = new Map();
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
frame.apply({
|
|
92
|
-
version: chunk.version,
|
|
93
|
-
r: chunkToRecords(chunk)
|
|
84
|
+
const stores = new Map();
|
|
85
|
+
const storeFor = id => {
|
|
86
|
+
let store = stores.get(id);
|
|
87
|
+
if (!store) stores.set(id, store = {
|
|
88
|
+
version: undefined,
|
|
89
|
+
records: {}
|
|
94
90
|
});
|
|
91
|
+
return store;
|
|
92
|
+
};
|
|
93
|
+
const write = (store, version, records) => {
|
|
94
|
+
if (store.version !== undefined && version < store.version) return false;
|
|
95
|
+
if (store.version === undefined || version > store.version) {
|
|
96
|
+
store.version = version;
|
|
97
|
+
for (const key of Object.keys(store.records)) {
|
|
98
|
+
if (key.startsWith("seg:") || key === ":error") delete store.records[key];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
Object.assign(store.records, records);
|
|
102
|
+
return true;
|
|
95
103
|
};
|
|
96
104
|
return {
|
|
97
105
|
register(id, frame) {
|
|
98
106
|
let set = frames.get(id);
|
|
99
107
|
if (!set) frames.set(id, set = new Set());
|
|
100
|
-
const sibling = set.size ? set.values().next().value : undefined;
|
|
101
108
|
set.add(frame);
|
|
102
|
-
|
|
109
|
+
const store = stores.get(id);
|
|
110
|
+
if (store && store.version !== undefined) {
|
|
103
111
|
frame.apply({
|
|
104
|
-
version:
|
|
105
|
-
r:
|
|
106
|
-
});
|
|
107
|
-
if (sibling.version === undefined) frame.rebase && frame.rebase();
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const kept = retained.get(id);
|
|
111
|
-
if (kept) {
|
|
112
|
-
retained.delete(id);
|
|
113
|
-
frame.apply({
|
|
114
|
-
version: kept.version,
|
|
115
|
-
r: kept.records
|
|
112
|
+
version: store.version,
|
|
113
|
+
r: store.records
|
|
116
114
|
});
|
|
117
115
|
frame.rebase && frame.rebase();
|
|
118
116
|
}
|
|
119
|
-
const buffered = pending.get(id);
|
|
120
|
-
if (buffered) {
|
|
121
|
-
pending.delete(id);
|
|
122
|
-
const records = {};
|
|
123
|
-
let version;
|
|
124
|
-
for (const chunk of buffered.chunks) {
|
|
125
|
-
if (chunk.type === "data") {
|
|
126
|
-
options.applyData && options.applyData(chunk);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
version = chunk.version;
|
|
130
|
-
Object.assign(records, chunkToRecords(chunk));
|
|
131
|
-
}
|
|
132
|
-
if (version !== undefined) frame.apply({
|
|
133
|
-
version,
|
|
134
|
-
r: records
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
117
|
},
|
|
138
118
|
unregister(id, frame) {
|
|
139
119
|
const set = frames.get(id);
|
|
140
120
|
if (set && frame) set.delete(frame);
|
|
141
121
|
if (!set || !frame || !set.size) {
|
|
142
|
-
if (frame) {
|
|
143
|
-
const kept = frame.snapshot && frame.snapshot();
|
|
144
|
-
if (kept) retained.set(id, kept);
|
|
145
|
-
} else {
|
|
146
|
-
retained.delete(id);
|
|
147
|
-
}
|
|
148
122
|
frames.delete(id);
|
|
149
|
-
|
|
123
|
+
if (frame && frame.contentHTML) {
|
|
124
|
+
const store = storeFor(id);
|
|
125
|
+
if (!store.records[""]) {
|
|
126
|
+
const html = frame.contentHTML();
|
|
127
|
+
if (html != null) {
|
|
128
|
+
store.records[""] = {
|
|
129
|
+
kind: "html",
|
|
130
|
+
value: html
|
|
131
|
+
};
|
|
132
|
+
if (store.version === undefined) store.version = 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
150
136
|
}
|
|
137
|
+
if (!frame) stores.delete(id);
|
|
151
138
|
},
|
|
152
139
|
apply(chunk) {
|
|
153
140
|
if (chunk.type === "data") {
|
|
154
141
|
options.applyData && options.applyData(chunk);
|
|
155
142
|
return;
|
|
156
143
|
}
|
|
144
|
+
const records = chunkToRecords(chunk);
|
|
145
|
+
if (!write(storeFor(chunk.id), chunk.version, records)) return;
|
|
157
146
|
const set = frames.get(chunk.id);
|
|
158
|
-
if (set
|
|
159
|
-
for (const frame of set)
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const buffered = pending.get(chunk.id);
|
|
163
|
-
if (!buffered) {
|
|
164
|
-
pending.set(chunk.id, {
|
|
147
|
+
if (set) {
|
|
148
|
+
for (const frame of set) frame.apply({
|
|
165
149
|
version: chunk.version,
|
|
166
|
-
|
|
150
|
+
r: records
|
|
167
151
|
});
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (chunk.version < buffered.version) return;
|
|
171
|
-
if (chunk.version > buffered.version) {
|
|
172
|
-
buffered.version = chunk.version;
|
|
173
|
-
buffered.chunks.length = 0;
|
|
174
152
|
}
|
|
175
|
-
buffered.chunks.push(chunk);
|
|
176
153
|
},
|
|
177
154
|
get(id) {
|
|
178
155
|
const set = frames.get(id);
|
|
@@ -208,6 +185,7 @@ class FrameImpl {
|
|
|
208
185
|
#slotResolvedRefs = new Map();
|
|
209
186
|
#slotNodes = new Map();
|
|
210
187
|
#processedAssets = new Set();
|
|
188
|
+
#recordRefresh = null;
|
|
211
189
|
#disposed = false;
|
|
212
190
|
#styleFlush = () => {
|
|
213
191
|
if (!this.#disposed) this.#flush();
|
|
@@ -353,7 +331,9 @@ class FrameImpl {
|
|
|
353
331
|
}
|
|
354
332
|
#removeSlotRecord(occurrence) {
|
|
355
333
|
const key = `slot:${occurrence}`;
|
|
356
|
-
if (key in this.#store)
|
|
334
|
+
if (key in this.#store) {
|
|
335
|
+
if (!this.#mountedSlots.has(occurrence)) delete this.#store[key];
|
|
336
|
+
} else this.#options.removeSlotRecord?.(occurrence);
|
|
357
337
|
}
|
|
358
338
|
#syncSlots(root) {
|
|
359
339
|
if (!this.#slots && !this.#options.resolveSlot) return;
|
|
@@ -371,6 +351,15 @@ class FrameImpl {
|
|
|
371
351
|
this.#runSlotCleanups(occurrence);
|
|
372
352
|
}
|
|
373
353
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
354
|
+
if (record === undefined && !root && this.#options.adopt && this.#options.recordsPending?.()) {
|
|
355
|
+
this.#recordRefresh ??= setTimeout(() => {
|
|
356
|
+
this.#recordRefresh = null;
|
|
357
|
+
if (this.#disposed) return;
|
|
358
|
+
this.#options.drainRecords?.();
|
|
359
|
+
this.#syncSlots();
|
|
360
|
+
});
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
374
363
|
if (this.#options.adopt) this.#discoverRegions(occurrence, start);
|
|
375
364
|
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
376
365
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
@@ -387,12 +376,6 @@ class FrameImpl {
|
|
|
387
376
|
const update = this.#slotUpdaters.get(occurrence);
|
|
388
377
|
if (update) {
|
|
389
378
|
const props = this.#resolveArgs(occurrence, record.args);
|
|
390
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
391
|
-
if (regions) {
|
|
392
|
-
for (const [argKey, entry] of regions) {
|
|
393
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
379
|
this.#slotArgs.set(occurrence, record);
|
|
397
380
|
update(props);
|
|
398
381
|
this.#bindRegions(occurrence);
|
|
@@ -438,12 +421,6 @@ class FrameImpl {
|
|
|
438
421
|
} : undefined
|
|
439
422
|
};
|
|
440
423
|
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
441
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
442
|
-
if (regions) {
|
|
443
|
-
for (const [argKey, entry] of regions) {
|
|
444
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
424
|
const scope = this.#options.ownerScope;
|
|
448
425
|
const content = scope ? scope(() => callback(props, ctx)) : callback(props, ctx);
|
|
449
426
|
this.#slotArgs.set(occurrence, record);
|
|
@@ -528,10 +505,9 @@ class FrameImpl {
|
|
|
528
505
|
this.#slotRegions.set(slotKey, regions);
|
|
529
506
|
}
|
|
530
507
|
const endData = slotEnd(slotKey);
|
|
531
|
-
const prefix = `${this.#options.id}.`;
|
|
532
508
|
let n = start.nextSibling;
|
|
533
509
|
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
534
|
-
collectRegionElements(n, regions
|
|
510
|
+
collectRegionElements(n, regions);
|
|
535
511
|
n = n.nextSibling;
|
|
536
512
|
}
|
|
537
513
|
}
|
|
@@ -543,16 +519,7 @@ class FrameImpl {
|
|
|
543
519
|
const b = record.args || {};
|
|
544
520
|
const ka = Object.keys(a);
|
|
545
521
|
const kb = Object.keys(b);
|
|
546
|
-
if (kb.length
|
|
547
|
-
if (kb.length !== ka.length) {
|
|
548
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
549
|
-
for (const key of kb) {
|
|
550
|
-
if (key in a) continue;
|
|
551
|
-
const vb = b[key];
|
|
552
|
-
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
553
|
-
if (!regions || !regions.has(key)) return false;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
522
|
+
if (kb.length !== ka.length) return false;
|
|
556
523
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
557
524
|
for (const key of ka) {
|
|
558
525
|
const va = a[key];
|
|
@@ -609,22 +576,9 @@ class FrameImpl {
|
|
|
609
576
|
#findPlaceholder(name) {
|
|
610
577
|
return findPlaceholder(this.#firstContent(), this.#end, placeholderId(name));
|
|
611
578
|
}
|
|
612
|
-
|
|
613
|
-
if (this.#disposed) return null;
|
|
614
|
-
|
|
615
|
-
...this.#store
|
|
616
|
-
};
|
|
617
|
-
if (!records[""] && this.#element && this.#hasContent) {
|
|
618
|
-
records[""] = {
|
|
619
|
-
kind: "html",
|
|
620
|
-
value: this.#element.innerHTML
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
if (!records[""] && this.#version === undefined) return null;
|
|
624
|
-
return {
|
|
625
|
-
version: this.#version ?? 0,
|
|
626
|
-
records
|
|
627
|
-
};
|
|
579
|
+
contentHTML() {
|
|
580
|
+
if (this.#disposed || !this.#element || !this.#hasContent) return null;
|
|
581
|
+
return this.#element.innerHTML;
|
|
628
582
|
}
|
|
629
583
|
rebind(id) {
|
|
630
584
|
if (this.#disposed || id === this.#options.id) return;
|
|
@@ -659,6 +613,10 @@ class FrameImpl {
|
|
|
659
613
|
} = this.#options;
|
|
660
614
|
if (host && id !== undefined) host.unregister(id, this);
|
|
661
615
|
this.#disposed = true;
|
|
616
|
+
if (this.#recordRefresh) {
|
|
617
|
+
clearTimeout(this.#recordRefresh);
|
|
618
|
+
this.#recordRefresh = null;
|
|
619
|
+
}
|
|
662
620
|
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
663
621
|
for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
|
|
664
622
|
for (const regions of this.#slotRegions.values()) {
|
|
@@ -681,8 +639,9 @@ class FrameImpl {
|
|
|
681
639
|
const claim = claimHandlers() ? this.#claimTree : null;
|
|
682
640
|
const ranges = new Map();
|
|
683
641
|
this.#collectSlots(ranges);
|
|
684
|
-
|
|
685
|
-
|
|
642
|
+
const grafts = [];
|
|
643
|
+
reconcileChildren(parent, fragment, this.#start, this.#end, claim, ranges, grafts);
|
|
644
|
+
if (ranges.size) for (const root of grafts) flushGrafts(root, ranges);
|
|
686
645
|
}
|
|
687
646
|
}
|
|
688
647
|
#clearContent() {
|
|
@@ -901,11 +860,11 @@ function collectSlots(n, end, out) {
|
|
|
901
860
|
n = n.nextSibling;
|
|
902
861
|
}
|
|
903
862
|
}
|
|
904
|
-
function collectRegionElements(node, regions
|
|
863
|
+
function collectRegionElements(node, regions) {
|
|
905
864
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
906
865
|
if (isFrameElement(node)) {
|
|
907
866
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
908
|
-
if (childId && childId.
|
|
867
|
+
if (childId && childId.includes(".")) {
|
|
909
868
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
910
869
|
if (!regions.has(argKey)) {
|
|
911
870
|
regions.set(argKey, {
|
|
@@ -918,7 +877,7 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
918
877
|
}
|
|
919
878
|
return;
|
|
920
879
|
}
|
|
921
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
880
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
922
881
|
}
|
|
923
882
|
function renameRegion(entry, childId) {
|
|
924
883
|
entry.childId = childId;
|
|
@@ -986,11 +945,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
986
945
|
}
|
|
987
946
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
988
947
|
}
|
|
989
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
948
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
990
949
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
991
950
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
992
951
|
morphAttributes(oldNode, newNode, claim);
|
|
993
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
952
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
994
953
|
} else if (oldNode.data !== newNode.data) {
|
|
995
954
|
oldNode.data = newNode.data;
|
|
996
955
|
}
|
|
@@ -1024,6 +983,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1024
983
|
n = next;
|
|
1025
984
|
}
|
|
1026
985
|
}
|
|
986
|
+
function placeRange(parent, range, id, ref) {
|
|
987
|
+
if (range.nodeType === 11 ) {
|
|
988
|
+
parent.insertBefore(range, ref);
|
|
989
|
+
} else {
|
|
990
|
+
moveRangeBefore(parent, range, id, ref);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
1027
993
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1028
994
|
const end = slotEnd(id);
|
|
1029
995
|
let n = start;
|
|
@@ -1041,7 +1007,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1041
1007
|
}
|
|
1042
1008
|
return after;
|
|
1043
1009
|
}
|
|
1044
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1010
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1045
1011
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1046
1012
|
let newChild = source.firstChild;
|
|
1047
1013
|
while (newChild) {
|
|
@@ -1057,11 +1023,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1057
1023
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1058
1024
|
if (existing) {
|
|
1059
1025
|
if (ranges) ranges.delete(pid);
|
|
1060
|
-
|
|
1061
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1062
|
-
} else {
|
|
1063
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1064
|
-
}
|
|
1026
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1065
1027
|
newChild = afterRange(newChild, pid);
|
|
1066
1028
|
} else {
|
|
1067
1029
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1072,17 +1034,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1072
1034
|
if (!old) {
|
|
1073
1035
|
parent.insertBefore(newChild, boundEnd);
|
|
1074
1036
|
if (claim) claim(newChild);
|
|
1037
|
+
if (grafts) grafts.push(newChild);
|
|
1075
1038
|
newChild = nextNew;
|
|
1076
1039
|
continue;
|
|
1077
1040
|
}
|
|
1078
1041
|
if (isSlotMarker(old)) {
|
|
1079
1042
|
parent.insertBefore(newChild, old);
|
|
1080
1043
|
if (claim) claim(newChild);
|
|
1044
|
+
if (grafts) grafts.push(newChild);
|
|
1081
1045
|
newChild = nextNew;
|
|
1082
1046
|
continue;
|
|
1083
1047
|
}
|
|
1084
1048
|
if (compatible(old, newChild)) {
|
|
1085
|
-
morphNode(old, newChild, claim, ranges);
|
|
1049
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1086
1050
|
oldChild = old.nextSibling;
|
|
1087
1051
|
newChild = nextNew;
|
|
1088
1052
|
continue;
|
|
@@ -1095,13 +1059,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1095
1059
|
}
|
|
1096
1060
|
if (ahead && ahead !== boundEnd) {
|
|
1097
1061
|
parent.insertBefore(ahead, old);
|
|
1098
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1062
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1099
1063
|
newChild = nextNew;
|
|
1100
1064
|
continue;
|
|
1101
1065
|
}
|
|
1102
1066
|
}
|
|
1103
1067
|
parent.insertBefore(newChild, old);
|
|
1104
1068
|
if (claim) claim(newChild);
|
|
1069
|
+
if (grafts) grafts.push(newChild);
|
|
1105
1070
|
newChild = nextNew;
|
|
1106
1071
|
}
|
|
1107
1072
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1118,20 +1083,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1118
1083
|
oldChild = next;
|
|
1119
1084
|
}
|
|
1120
1085
|
}
|
|
1121
|
-
function
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const
|
|
1126
|
-
if (
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1086
|
+
function flushGrafts(node, ranges) {
|
|
1087
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1088
|
+
let n = node.firstChild;
|
|
1089
|
+
while (n) {
|
|
1090
|
+
const id = slotStartId(n);
|
|
1091
|
+
if (id !== null) {
|
|
1092
|
+
const next = afterRange(n, id);
|
|
1093
|
+
const displaced = ranges.get(id);
|
|
1094
|
+
if (displaced) {
|
|
1095
|
+
ranges.delete(id);
|
|
1096
|
+
placeRange(node, displaced, id, n);
|
|
1097
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1098
|
+
}
|
|
1099
|
+
n = next;
|
|
1100
|
+
continue;
|
|
1133
1101
|
}
|
|
1134
|
-
|
|
1102
|
+
flushGrafts(n, ranges);
|
|
1103
|
+
n = n.nextSibling;
|
|
1135
1104
|
}
|
|
1136
1105
|
}
|
|
1137
1106
|
function stashRange(frag, start, id) {
|
|
@@ -1163,7 +1132,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1163
1132
|
if (chunk.type === "outcome") {
|
|
1164
1133
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1165
1134
|
} else {
|
|
1166
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1135
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1167
1136
|
if (perFrame) {
|
|
1168
1137
|
let v = perFrame.get(chunk.id);
|
|
1169
1138
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1177,7 +1146,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1177
1146
|
}
|
|
1178
1147
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1179
1148
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1180
|
-
const
|
|
1149
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1181
1150
|
let resolveServerComponent;
|
|
1182
1151
|
function parseServerComponent(value, ctx) {
|
|
1183
1152
|
return {
|
|
@@ -1201,7 +1170,8 @@ const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
|
1201
1170
|
stream: parseServerComponent
|
|
1202
1171
|
},
|
|
1203
1172
|
serialize(node, ctx) {
|
|
1204
|
-
|
|
1173
|
+
const registry = "self._$SC";
|
|
1174
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1205
1175
|
},
|
|
1206
1176
|
deserialize(node, ctx) {
|
|
1207
1177
|
const id = ctx.deserialize(node.id);
|
|
@@ -1226,120 +1196,79 @@ function createServerComponentHandler({
|
|
|
1226
1196
|
host,
|
|
1227
1197
|
component,
|
|
1228
1198
|
onStream,
|
|
1229
|
-
documentComponent,
|
|
1230
1199
|
intercept,
|
|
1231
1200
|
consumer = getFlightDataConsumer,
|
|
1232
1201
|
codec = getServerFunctionsCodec
|
|
1233
1202
|
}) {
|
|
1234
|
-
const
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1239
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1240
|
-
fnId,
|
|
1241
|
-
frameId,
|
|
1242
|
-
take(prev) {
|
|
1243
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1244
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1245
|
-
const root = meta.frameId;
|
|
1246
|
-
let cur = forwards.get(root) ?? root;
|
|
1247
|
-
if (cur !== root && !host.get(cur)) {
|
|
1248
|
-
forwards.delete(root);
|
|
1249
|
-
cur = root;
|
|
1250
|
-
}
|
|
1251
|
-
if (cur === frameId) return true;
|
|
1252
|
-
let frame = host.get(cur);
|
|
1253
|
-
if (!frame) return false;
|
|
1254
|
-
while (frame) {
|
|
1255
|
-
frame.rebind(frameId);
|
|
1256
|
-
frame = host.get(cur);
|
|
1257
|
-
}
|
|
1258
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1259
|
-
return true;
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1203
|
+
const byFn = new Map();
|
|
1204
|
+
const componentFor = fnId => {
|
|
1205
|
+
let comp = byFn.get(fnId);
|
|
1206
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1263
1207
|
return comp;
|
|
1264
1208
|
};
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1209
|
+
const byAddress = new Map();
|
|
1210
|
+
const bindingFor = (address, fnId) => {
|
|
1211
|
+
let binding = byAddress.get(address);
|
|
1212
|
+
if (!binding) {
|
|
1213
|
+
const comp = componentFor(fnId);
|
|
1214
|
+
binding = props => comp(props, () => address);
|
|
1215
|
+
binding[COMPONENT_BINDING] = {
|
|
1216
|
+
component: comp,
|
|
1217
|
+
address
|
|
1271
1218
|
};
|
|
1272
|
-
byAddress.set(address,
|
|
1219
|
+
byAddress.set(address, binding);
|
|
1273
1220
|
}
|
|
1274
|
-
return
|
|
1221
|
+
return binding;
|
|
1275
1222
|
};
|
|
1276
|
-
|
|
1277
|
-
resolveServerComponent = resolveAddress;
|
|
1223
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1278
1224
|
const versions = new Map();
|
|
1279
|
-
const bump =
|
|
1280
|
-
const version = (versions.get(
|
|
1281
|
-
versions.set(
|
|
1225
|
+
const bump = address => {
|
|
1226
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1227
|
+
versions.set(address, version);
|
|
1282
1228
|
return version;
|
|
1283
1229
|
};
|
|
1284
1230
|
return {
|
|
1285
1231
|
intercept: intercept && (info => {
|
|
1286
1232
|
const hit = intercept(info);
|
|
1287
|
-
if (hit
|
|
1288
|
-
|
|
1289
|
-
byAddress.set(address, {
|
|
1290
|
-
frameId: info.id,
|
|
1291
|
-
component: brand(hit, info.id, info.id)
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
return hit;
|
|
1233
|
+
if (hit === undefined) return undefined;
|
|
1234
|
+
return bindingFor(frameAddress(info.id, info.args), info.id);
|
|
1295
1235
|
}),
|
|
1296
1236
|
handle(response, ctx) {
|
|
1297
1237
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1298
1238
|
const address = frameAddress(ctx.id, ctx.args);
|
|
1299
|
-
|
|
1300
|
-
if (!entry) {
|
|
1301
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1302
|
-
if (adopted) {
|
|
1303
|
-
entry = {
|
|
1304
|
-
frameId: ctx.id,
|
|
1305
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1306
|
-
};
|
|
1307
|
-
byAddress.set(address, entry);
|
|
1308
|
-
} else {
|
|
1309
|
-
entry = boundaryFor(address, ctx.id);
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1239
|
+
const binding = bindingFor(address, ctx.id);
|
|
1312
1240
|
if (response.headers.has(SINGLE_FLIGHT_HEADER)) {
|
|
1313
|
-
return applyFlightResponse(response,
|
|
1241
|
+
return applyFlightResponse(response, address, binding);
|
|
1314
1242
|
}
|
|
1315
|
-
const version = bump(
|
|
1316
|
-
if (onStream) onStream(
|
|
1243
|
+
const version = bump(address);
|
|
1244
|
+
if (onStream) onStream(address, version, response);
|
|
1317
1245
|
applyFrameResponse(response, host, {
|
|
1318
|
-
as:
|
|
1246
|
+
as: address,
|
|
1319
1247
|
version
|
|
1320
1248
|
}).catch(err => host.apply({
|
|
1321
1249
|
type: "error",
|
|
1322
|
-
id:
|
|
1250
|
+
id: address,
|
|
1323
1251
|
version,
|
|
1324
1252
|
error: {
|
|
1325
1253
|
message: String(err && err.message)
|
|
1326
1254
|
}
|
|
1327
1255
|
}));
|
|
1328
|
-
return
|
|
1256
|
+
return binding;
|
|
1329
1257
|
},
|
|
1330
|
-
showing(address, functionId
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1258
|
+
showing(address, functionId) {
|
|
1259
|
+
bindingFor(address, functionId);
|
|
1260
|
+
const comp = componentFor(functionId);
|
|
1261
|
+
if ((typeof comp === "function" || typeof comp === "object" && comp !== null) && !comp[COMPONENT_BINDING]) {
|
|
1262
|
+
comp[COMPONENT_BINDING] = {
|
|
1263
|
+
component: comp,
|
|
1335
1264
|
address
|
|
1336
|
-
}
|
|
1265
|
+
};
|
|
1337
1266
|
}
|
|
1338
1267
|
}
|
|
1339
1268
|
};
|
|
1340
|
-
async function applyFlightResponse(response,
|
|
1269
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1341
1270
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1342
|
-
const as = rootId ?
|
|
1271
|
+
const as = rootId ? address : undefined;
|
|
1343
1272
|
let feed;
|
|
1344
1273
|
const source = new ReadableStream({
|
|
1345
1274
|
start(controller) {
|
|
@@ -1350,10 +1279,6 @@ function createServerComponentHandler({
|
|
|
1350
1279
|
let carried = false;
|
|
1351
1280
|
await applyFrameResponse(response, host, {
|
|
1352
1281
|
as,
|
|
1353
|
-
route: id => {
|
|
1354
|
-
const local = byAddress.get(id);
|
|
1355
|
-
return local ? local.frameId : id;
|
|
1356
|
-
},
|
|
1357
1282
|
version: frameId => {
|
|
1358
1283
|
const version = bump(frameId);
|
|
1359
1284
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1374,7 +1299,7 @@ function createServerComponentHandler({
|
|
|
1374
1299
|
if (response.headers.has(ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(REVALIDATE_HEADER)) {
|
|
1375
1300
|
throw envelope.value;
|
|
1376
1301
|
}
|
|
1377
|
-
return rootId ?
|
|
1302
|
+
return rootId ? binding : envelope.value;
|
|
1378
1303
|
}
|
|
1379
1304
|
}
|
|
1380
1305
|
|
|
@@ -1553,15 +1478,7 @@ function slotsFor(props) {
|
|
|
1553
1478
|
return settle(normalizeSlotContent(value));
|
|
1554
1479
|
}
|
|
1555
1480
|
if (ctx && ctx.range) {
|
|
1556
|
-
let claim = adopted;
|
|
1557
1481
|
const source = value;
|
|
1558
|
-
const accessor = () => {
|
|
1559
|
-
if (claim) {
|
|
1560
|
-
claim = false;
|
|
1561
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1562
|
-
}
|
|
1563
|
-
return typeof source === "function" ? source() : source;
|
|
1564
|
-
};
|
|
1565
1482
|
const owner = createOwner();
|
|
1566
1483
|
bindings.set(key, owner);
|
|
1567
1484
|
ctx.onCleanup(() => {
|
|
@@ -1569,7 +1486,8 @@ function slotsFor(props) {
|
|
|
1569
1486
|
owner.dispose();
|
|
1570
1487
|
});
|
|
1571
1488
|
const end = ctx.range.end;
|
|
1572
|
-
|
|
1489
|
+
const bind = () => insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1490
|
+
runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1573
1491
|
return undefined;
|
|
1574
1492
|
}
|
|
1575
1493
|
return settle(normalizeSlotContent(value));
|
|
@@ -1583,19 +1501,24 @@ function revealSeam(owner) {
|
|
|
1583
1501
|
function boundaryScope(owner) {
|
|
1584
1502
|
return fn => getOwner() ? fn() : runWithOwner(owner, fn);
|
|
1585
1503
|
}
|
|
1586
|
-
function
|
|
1587
|
-
|
|
1504
|
+
function followBinding(frame, binding) {
|
|
1505
|
+
createRenderEffect(binding, address => frame.rebind(address));
|
|
1506
|
+
}
|
|
1507
|
+
function boundaryComponent(host, fnId) {
|
|
1508
|
+
return (props, binding) => {
|
|
1588
1509
|
const owner = getOwner();
|
|
1589
1510
|
const {
|
|
1590
1511
|
element,
|
|
1512
|
+
frame,
|
|
1591
1513
|
dispose
|
|
1592
1514
|
} = createFrameElement({
|
|
1593
1515
|
host,
|
|
1594
|
-
id,
|
|
1516
|
+
id: binding ? binding() : fnId,
|
|
1595
1517
|
slots: slotsFor(props),
|
|
1596
1518
|
ownerScope: boundaryScope(owner),
|
|
1597
1519
|
reveal: revealSeam(owner)
|
|
1598
1520
|
});
|
|
1521
|
+
if (binding) followBinding(frame, binding);
|
|
1599
1522
|
onCleanup(dispose);
|
|
1600
1523
|
return element;
|
|
1601
1524
|
};
|
|
@@ -1617,51 +1540,65 @@ function findBoundaryElement(id) {
|
|
|
1617
1540
|
return boundaryIndex.get(id);
|
|
1618
1541
|
}
|
|
1619
1542
|
const boundaryWaiters = new Map();
|
|
1620
|
-
function
|
|
1543
|
+
function boundaryMayArrive() {
|
|
1621
1544
|
const hy = globalThis._$HY;
|
|
1622
|
-
|
|
1545
|
+
if (!hy) return false;
|
|
1546
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1623
1547
|
}
|
|
1624
1548
|
function installRevealHook() {
|
|
1625
1549
|
const hy = globalThis._$HY;
|
|
1626
|
-
if (!hy || hy.$sc) return;
|
|
1550
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1627
1551
|
hy.$sc = true;
|
|
1628
|
-
|
|
1629
|
-
hy.fe = (fragmentId, parent) => {
|
|
1630
|
-
if (prev) prev(fragmentId, parent);
|
|
1552
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1631
1553
|
if (!boundaryIndex) return;
|
|
1632
1554
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1555
|
+
if (root) indexBoundaries(root);
|
|
1556
|
+
if (!boundaryWaiters.size) return;
|
|
1557
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1635
1558
|
for (const [id, notify] of boundaryWaiters) {
|
|
1636
|
-
const el = boundaryIndex.get(id);
|
|
1637
|
-
if (!el) continue;
|
|
1559
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1560
|
+
if (!el && !exhausted) continue;
|
|
1638
1561
|
boundaryWaiters.delete(id);
|
|
1639
1562
|
notify(el);
|
|
1640
1563
|
}
|
|
1641
|
-
};
|
|
1564
|
+
});
|
|
1642
1565
|
}
|
|
1643
|
-
function documentBoundary(host, id, props) {
|
|
1566
|
+
function documentBoundary(host, id, props, binding) {
|
|
1567
|
+
installRevealHook();
|
|
1644
1568
|
const claimed = claimedBoundaries.has(id);
|
|
1645
1569
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1646
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1647
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1570
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1571
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1648
1572
|
const owner = getOwner();
|
|
1649
1573
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1650
1574
|
onCleanup(() => boundaryWaiters.delete(id));
|
|
1651
|
-
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1575
|
+
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1576
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1577
|
+
}
|
|
1578
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1579
|
+
}
|
|
1580
|
+
function documentAddress(id) {
|
|
1581
|
+
const records = globalThis._$SC?.a;
|
|
1582
|
+
if (records) {
|
|
1583
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1652
1584
|
}
|
|
1653
|
-
return
|
|
1585
|
+
return id;
|
|
1654
1586
|
}
|
|
1655
|
-
function adoptBoundary(host, id, el, props) {
|
|
1587
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1656
1588
|
claimedBoundaries.add(id);
|
|
1657
|
-
const
|
|
1658
|
-
|
|
1589
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1590
|
+
const appliedRecords = new Set();
|
|
1591
|
+
const drainRecords = () => {
|
|
1592
|
+
const hy = globalThis._$HY;
|
|
1593
|
+
if (!hy || !hy.r) return;
|
|
1659
1594
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1660
1595
|
for (const key of Object.keys(hy.r)) {
|
|
1596
|
+
if (appliedRecords.has(key)) continue;
|
|
1661
1597
|
if (key.startsWith(slotPrefix)) {
|
|
1598
|
+
appliedRecords.add(key);
|
|
1662
1599
|
host.apply({
|
|
1663
1600
|
type: "slot",
|
|
1664
|
-
id,
|
|
1601
|
+
id: address,
|
|
1665
1602
|
version: 0,
|
|
1666
1603
|
key: key.slice(slotPrefix.length),
|
|
1667
1604
|
args: hy.r[key]
|
|
@@ -1669,6 +1606,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1669
1606
|
} else if (key.startsWith("sc:region:")) {
|
|
1670
1607
|
const childId = key.slice("sc:region:".length);
|
|
1671
1608
|
if (childId.startsWith(id + ".")) {
|
|
1609
|
+
appliedRecords.add(key);
|
|
1672
1610
|
const val = hy.r[key];
|
|
1673
1611
|
const apply = html => host.apply({
|
|
1674
1612
|
type: "html",
|
|
@@ -1680,16 +1618,27 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1680
1618
|
}
|
|
1681
1619
|
}
|
|
1682
1620
|
}
|
|
1683
|
-
}
|
|
1621
|
+
};
|
|
1622
|
+
drainRecords();
|
|
1684
1623
|
const owner = getOwner();
|
|
1685
1624
|
const frame = createFrame(el, {
|
|
1686
1625
|
adopt: true,
|
|
1687
1626
|
host,
|
|
1688
|
-
id,
|
|
1627
|
+
id: address,
|
|
1689
1628
|
slots: slotsFor(props),
|
|
1690
1629
|
ownerScope: boundaryScope(owner),
|
|
1691
|
-
reveal: revealSeam(owner)
|
|
1630
|
+
reveal: revealSeam(owner),
|
|
1631
|
+
...{
|
|
1632
|
+
recordsPending: () => {
|
|
1633
|
+
if (document.readyState === "loading") return true;
|
|
1634
|
+
const hy = globalThis._$HY;
|
|
1635
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1636
|
+
},
|
|
1637
|
+
drainRecords,
|
|
1638
|
+
claimScope: id
|
|
1639
|
+
}
|
|
1692
1640
|
});
|
|
1641
|
+
if (binding) followBinding(frame, binding);
|
|
1693
1642
|
onCleanup(() => frame.dispose());
|
|
1694
1643
|
return el;
|
|
1695
1644
|
}
|
|
@@ -1704,17 +1653,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1704
1653
|
g._$SC.a[a] = i;
|
|
1705
1654
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1706
1655
|
}
|
|
1707
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1656
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1708
1657
|
}
|
|
1709
1658
|
};
|
|
1710
1659
|
}
|
|
1711
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1660
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1712
1661
|
installRevealHook();
|
|
1713
1662
|
const handler = createServerComponentHandler({
|
|
1714
1663
|
host,
|
|
1715
|
-
component:
|
|
1716
|
-
onStream:
|
|
1717
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1664
|
+
component: fnId => g._$SC.r(fnId),
|
|
1665
|
+
onStream: address => beginStream(address),
|
|
1718
1666
|
intercept: ({
|
|
1719
1667
|
id
|
|
1720
1668
|
}) => {
|
|
@@ -1722,7 +1670,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1722
1670
|
return g._$SC.r(id);
|
|
1723
1671
|
}
|
|
1724
1672
|
});
|
|
1725
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1673
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1726
1674
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1727
1675
|
for (const address in records) showing(address, records[address]);
|
|
1728
1676
|
g._$SC.reg = showing;
|