@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
|
@@ -83,98 +83,75 @@ function chunkToRecords(chunk) {
|
|
|
83
83
|
}
|
|
84
84
|
function createFrameHost(options = {}) {
|
|
85
85
|
const frames = new Map();
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
frame.apply({
|
|
94
|
-
version: chunk.version,
|
|
95
|
-
r: chunkToRecords(chunk)
|
|
86
|
+
const stores = new Map();
|
|
87
|
+
const storeFor = id => {
|
|
88
|
+
let store = stores.get(id);
|
|
89
|
+
if (!store) stores.set(id, store = {
|
|
90
|
+
version: undefined,
|
|
91
|
+
records: {}
|
|
96
92
|
});
|
|
93
|
+
return store;
|
|
94
|
+
};
|
|
95
|
+
const write = (store, version, records) => {
|
|
96
|
+
if (store.version !== undefined && version < store.version) return false;
|
|
97
|
+
if (store.version === undefined || version > store.version) {
|
|
98
|
+
store.version = version;
|
|
99
|
+
for (const key of Object.keys(store.records)) {
|
|
100
|
+
if (key.startsWith("seg:") || key === ":error") delete store.records[key];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
Object.assign(store.records, records);
|
|
104
|
+
return true;
|
|
97
105
|
};
|
|
98
106
|
return {
|
|
99
107
|
register(id, frame) {
|
|
100
108
|
let set = frames.get(id);
|
|
101
109
|
if (!set) frames.set(id, set = new Set());
|
|
102
|
-
const sibling = set.size ? set.values().next().value : undefined;
|
|
103
110
|
set.add(frame);
|
|
104
|
-
|
|
111
|
+
const store = stores.get(id);
|
|
112
|
+
if (store && store.version !== undefined) {
|
|
105
113
|
frame.apply({
|
|
106
|
-
version:
|
|
107
|
-
r:
|
|
108
|
-
});
|
|
109
|
-
if (sibling.version === undefined) frame.rebase && frame.rebase();
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const kept = retained.get(id);
|
|
113
|
-
if (kept) {
|
|
114
|
-
retained.delete(id);
|
|
115
|
-
frame.apply({
|
|
116
|
-
version: kept.version,
|
|
117
|
-
r: kept.records
|
|
114
|
+
version: store.version,
|
|
115
|
+
r: store.records
|
|
118
116
|
});
|
|
119
117
|
frame.rebase && frame.rebase();
|
|
120
118
|
}
|
|
121
|
-
const buffered = pending.get(id);
|
|
122
|
-
if (buffered) {
|
|
123
|
-
pending.delete(id);
|
|
124
|
-
const records = {};
|
|
125
|
-
let version;
|
|
126
|
-
for (const chunk of buffered.chunks) {
|
|
127
|
-
if (chunk.type === "data") {
|
|
128
|
-
options.applyData && options.applyData(chunk);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
version = chunk.version;
|
|
132
|
-
Object.assign(records, chunkToRecords(chunk));
|
|
133
|
-
}
|
|
134
|
-
if (version !== undefined) frame.apply({
|
|
135
|
-
version,
|
|
136
|
-
r: records
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
119
|
},
|
|
140
120
|
unregister(id, frame) {
|
|
141
121
|
const set = frames.get(id);
|
|
142
122
|
if (set && frame) set.delete(frame);
|
|
143
123
|
if (!set || !frame || !set.size) {
|
|
144
|
-
if (frame) {
|
|
145
|
-
const kept = frame.snapshot && frame.snapshot();
|
|
146
|
-
if (kept) retained.set(id, kept);
|
|
147
|
-
} else {
|
|
148
|
-
retained.delete(id);
|
|
149
|
-
}
|
|
150
124
|
frames.delete(id);
|
|
151
|
-
|
|
125
|
+
if (frame && frame.contentHTML) {
|
|
126
|
+
const store = storeFor(id);
|
|
127
|
+
if (!store.records[""]) {
|
|
128
|
+
const html = frame.contentHTML();
|
|
129
|
+
if (html != null) {
|
|
130
|
+
store.records[""] = {
|
|
131
|
+
kind: "html",
|
|
132
|
+
value: html
|
|
133
|
+
};
|
|
134
|
+
if (store.version === undefined) store.version = 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
152
138
|
}
|
|
139
|
+
if (!frame) stores.delete(id);
|
|
153
140
|
},
|
|
154
141
|
apply(chunk) {
|
|
155
142
|
if (chunk.type === "data") {
|
|
156
143
|
options.applyData && options.applyData(chunk);
|
|
157
144
|
return;
|
|
158
145
|
}
|
|
146
|
+
const records = chunkToRecords(chunk);
|
|
147
|
+
if (!write(storeFor(chunk.id), chunk.version, records)) return;
|
|
159
148
|
const set = frames.get(chunk.id);
|
|
160
|
-
if (set
|
|
161
|
-
for (const frame of set)
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const buffered = pending.get(chunk.id);
|
|
165
|
-
if (!buffered) {
|
|
166
|
-
pending.set(chunk.id, {
|
|
149
|
+
if (set) {
|
|
150
|
+
for (const frame of set) frame.apply({
|
|
167
151
|
version: chunk.version,
|
|
168
|
-
|
|
152
|
+
r: records
|
|
169
153
|
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (chunk.version < buffered.version) return;
|
|
173
|
-
if (chunk.version > buffered.version) {
|
|
174
|
-
buffered.version = chunk.version;
|
|
175
|
-
buffered.chunks.length = 0;
|
|
176
154
|
}
|
|
177
|
-
buffered.chunks.push(chunk);
|
|
178
155
|
},
|
|
179
156
|
get(id) {
|
|
180
157
|
const set = frames.get(id);
|
|
@@ -210,6 +187,7 @@ class FrameImpl {
|
|
|
210
187
|
#slotResolvedRefs = new Map();
|
|
211
188
|
#slotNodes = new Map();
|
|
212
189
|
#processedAssets = new Set();
|
|
190
|
+
#recordRefresh = null;
|
|
213
191
|
#disposed = false;
|
|
214
192
|
#styleFlush = () => {
|
|
215
193
|
if (!this.#disposed) this.#flush();
|
|
@@ -355,7 +333,9 @@ class FrameImpl {
|
|
|
355
333
|
}
|
|
356
334
|
#removeSlotRecord(occurrence) {
|
|
357
335
|
const key = `slot:${occurrence}`;
|
|
358
|
-
if (key in this.#store)
|
|
336
|
+
if (key in this.#store) {
|
|
337
|
+
if (!this.#mountedSlots.has(occurrence)) delete this.#store[key];
|
|
338
|
+
} else this.#options.removeSlotRecord?.(occurrence);
|
|
359
339
|
}
|
|
360
340
|
#syncSlots(root) {
|
|
361
341
|
if (!this.#slots && !this.#options.resolveSlot) return;
|
|
@@ -373,6 +353,15 @@ class FrameImpl {
|
|
|
373
353
|
this.#runSlotCleanups(occurrence);
|
|
374
354
|
}
|
|
375
355
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
356
|
+
if (record === undefined && !root && this.#options.adopt && this.#options.recordsPending?.()) {
|
|
357
|
+
this.#recordRefresh ??= setTimeout(() => {
|
|
358
|
+
this.#recordRefresh = null;
|
|
359
|
+
if (this.#disposed) return;
|
|
360
|
+
this.#options.drainRecords?.();
|
|
361
|
+
this.#syncSlots();
|
|
362
|
+
});
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
376
365
|
if (this.#options.adopt) this.#discoverRegions(occurrence, start);
|
|
377
366
|
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
378
367
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
@@ -389,12 +378,6 @@ class FrameImpl {
|
|
|
389
378
|
const update = this.#slotUpdaters.get(occurrence);
|
|
390
379
|
if (update) {
|
|
391
380
|
const props = this.#resolveArgs(occurrence, record.args);
|
|
392
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
393
|
-
if (regions) {
|
|
394
|
-
for (const [argKey, entry] of regions) {
|
|
395
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
381
|
this.#slotArgs.set(occurrence, record);
|
|
399
382
|
update(props);
|
|
400
383
|
this.#bindRegions(occurrence);
|
|
@@ -440,12 +423,6 @@ class FrameImpl {
|
|
|
440
423
|
} : undefined
|
|
441
424
|
};
|
|
442
425
|
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
443
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
444
|
-
if (regions) {
|
|
445
|
-
for (const [argKey, entry] of regions) {
|
|
446
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
426
|
const scope = this.#options.ownerScope;
|
|
450
427
|
const content = scope ? scope(() => callback(props, ctx)) : callback(props, ctx);
|
|
451
428
|
this.#slotArgs.set(occurrence, record);
|
|
@@ -530,10 +507,9 @@ class FrameImpl {
|
|
|
530
507
|
this.#slotRegions.set(slotKey, regions);
|
|
531
508
|
}
|
|
532
509
|
const endData = slotEnd(slotKey);
|
|
533
|
-
const prefix = `${this.#options.id}.`;
|
|
534
510
|
let n = start.nextSibling;
|
|
535
511
|
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
536
|
-
collectRegionElements(n, regions
|
|
512
|
+
collectRegionElements(n, regions);
|
|
537
513
|
n = n.nextSibling;
|
|
538
514
|
}
|
|
539
515
|
}
|
|
@@ -545,16 +521,7 @@ class FrameImpl {
|
|
|
545
521
|
const b = record.args || {};
|
|
546
522
|
const ka = Object.keys(a);
|
|
547
523
|
const kb = Object.keys(b);
|
|
548
|
-
if (kb.length
|
|
549
|
-
if (kb.length !== ka.length) {
|
|
550
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
551
|
-
for (const key of kb) {
|
|
552
|
-
if (key in a) continue;
|
|
553
|
-
const vb = b[key];
|
|
554
|
-
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
555
|
-
if (!regions || !regions.has(key)) return false;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
524
|
+
if (kb.length !== ka.length) return false;
|
|
558
525
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
559
526
|
for (const key of ka) {
|
|
560
527
|
const va = a[key];
|
|
@@ -611,22 +578,9 @@ class FrameImpl {
|
|
|
611
578
|
#findPlaceholder(name) {
|
|
612
579
|
return findPlaceholder(this.#firstContent(), this.#end, placeholderId(name));
|
|
613
580
|
}
|
|
614
|
-
|
|
615
|
-
if (this.#disposed) return null;
|
|
616
|
-
|
|
617
|
-
...this.#store
|
|
618
|
-
};
|
|
619
|
-
if (!records[""] && this.#element && this.#hasContent) {
|
|
620
|
-
records[""] = {
|
|
621
|
-
kind: "html",
|
|
622
|
-
value: this.#element.innerHTML
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
if (!records[""] && this.#version === undefined) return null;
|
|
626
|
-
return {
|
|
627
|
-
version: this.#version ?? 0,
|
|
628
|
-
records
|
|
629
|
-
};
|
|
581
|
+
contentHTML() {
|
|
582
|
+
if (this.#disposed || !this.#element || !this.#hasContent) return null;
|
|
583
|
+
return this.#element.innerHTML;
|
|
630
584
|
}
|
|
631
585
|
rebind(id) {
|
|
632
586
|
if (this.#disposed || id === this.#options.id) return;
|
|
@@ -661,6 +615,10 @@ class FrameImpl {
|
|
|
661
615
|
} = this.#options;
|
|
662
616
|
if (host && id !== undefined) host.unregister(id, this);
|
|
663
617
|
this.#disposed = true;
|
|
618
|
+
if (this.#recordRefresh) {
|
|
619
|
+
clearTimeout(this.#recordRefresh);
|
|
620
|
+
this.#recordRefresh = null;
|
|
621
|
+
}
|
|
664
622
|
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
665
623
|
for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
|
|
666
624
|
for (const regions of this.#slotRegions.values()) {
|
|
@@ -683,8 +641,9 @@ class FrameImpl {
|
|
|
683
641
|
const claim = claimHandlers() ? this.#claimTree : null;
|
|
684
642
|
const ranges = new Map();
|
|
685
643
|
this.#collectSlots(ranges);
|
|
686
|
-
|
|
687
|
-
|
|
644
|
+
const grafts = [];
|
|
645
|
+
reconcileChildren(parent, fragment, this.#start, this.#end, claim, ranges, grafts);
|
|
646
|
+
if (ranges.size) for (const root of grafts) flushGrafts(root, ranges);
|
|
688
647
|
}
|
|
689
648
|
}
|
|
690
649
|
#clearContent() {
|
|
@@ -907,11 +866,11 @@ function collectSlots(n, end, out) {
|
|
|
907
866
|
n = n.nextSibling;
|
|
908
867
|
}
|
|
909
868
|
}
|
|
910
|
-
function collectRegionElements(node, regions
|
|
869
|
+
function collectRegionElements(node, regions) {
|
|
911
870
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
912
871
|
if (isFrameElement(node)) {
|
|
913
872
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
914
|
-
if (childId && childId.
|
|
873
|
+
if (childId && childId.includes(".")) {
|
|
915
874
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
916
875
|
if (!regions.has(argKey)) {
|
|
917
876
|
regions.set(argKey, {
|
|
@@ -924,7 +883,7 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
924
883
|
}
|
|
925
884
|
return;
|
|
926
885
|
}
|
|
927
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
886
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
928
887
|
}
|
|
929
888
|
function renameRegion(entry, childId) {
|
|
930
889
|
entry.childId = childId;
|
|
@@ -992,11 +951,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
992
951
|
}
|
|
993
952
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
994
953
|
}
|
|
995
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
954
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
996
955
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
997
956
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
998
957
|
morphAttributes(oldNode, newNode, claim);
|
|
999
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
958
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
1000
959
|
} else if (oldNode.data !== newNode.data) {
|
|
1001
960
|
oldNode.data = newNode.data;
|
|
1002
961
|
}
|
|
@@ -1039,6 +998,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1039
998
|
n = next;
|
|
1040
999
|
}
|
|
1041
1000
|
}
|
|
1001
|
+
function placeRange(parent, range, id, ref) {
|
|
1002
|
+
if (range.nodeType === 11 ) {
|
|
1003
|
+
parent.insertBefore(range, ref);
|
|
1004
|
+
} else {
|
|
1005
|
+
moveRangeBefore(parent, range, id, ref);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1042
1008
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1043
1009
|
const end = slotEnd(id);
|
|
1044
1010
|
let n = start;
|
|
@@ -1056,7 +1022,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1056
1022
|
}
|
|
1057
1023
|
return after;
|
|
1058
1024
|
}
|
|
1059
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1025
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1060
1026
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1061
1027
|
let newChild = source.firstChild;
|
|
1062
1028
|
while (newChild) {
|
|
@@ -1072,11 +1038,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1072
1038
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1073
1039
|
if (existing) {
|
|
1074
1040
|
if (ranges) ranges.delete(pid);
|
|
1075
|
-
|
|
1076
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1077
|
-
} else {
|
|
1078
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1079
|
-
}
|
|
1041
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1080
1042
|
newChild = afterRange(newChild, pid);
|
|
1081
1043
|
} else {
|
|
1082
1044
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1087,17 +1049,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1087
1049
|
if (!old) {
|
|
1088
1050
|
parent.insertBefore(newChild, boundEnd);
|
|
1089
1051
|
if (claim) claim(newChild);
|
|
1052
|
+
if (grafts) grafts.push(newChild);
|
|
1090
1053
|
newChild = nextNew;
|
|
1091
1054
|
continue;
|
|
1092
1055
|
}
|
|
1093
1056
|
if (isSlotMarker(old)) {
|
|
1094
1057
|
parent.insertBefore(newChild, old);
|
|
1095
1058
|
if (claim) claim(newChild);
|
|
1059
|
+
if (grafts) grafts.push(newChild);
|
|
1096
1060
|
newChild = nextNew;
|
|
1097
1061
|
continue;
|
|
1098
1062
|
}
|
|
1099
1063
|
if (compatible(old, newChild)) {
|
|
1100
|
-
morphNode(old, newChild, claim, ranges);
|
|
1064
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1101
1065
|
oldChild = old.nextSibling;
|
|
1102
1066
|
newChild = nextNew;
|
|
1103
1067
|
continue;
|
|
@@ -1110,13 +1074,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1110
1074
|
}
|
|
1111
1075
|
if (ahead && ahead !== boundEnd) {
|
|
1112
1076
|
parent.insertBefore(ahead, old);
|
|
1113
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1077
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1114
1078
|
newChild = nextNew;
|
|
1115
1079
|
continue;
|
|
1116
1080
|
}
|
|
1117
1081
|
}
|
|
1118
1082
|
parent.insertBefore(newChild, old);
|
|
1119
1083
|
if (claim) claim(newChild);
|
|
1084
|
+
if (grafts) grafts.push(newChild);
|
|
1120
1085
|
newChild = nextNew;
|
|
1121
1086
|
}
|
|
1122
1087
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1133,20 +1098,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1133
1098
|
oldChild = next;
|
|
1134
1099
|
}
|
|
1135
1100
|
}
|
|
1136
|
-
function
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
const
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1101
|
+
function flushGrafts(node, ranges) {
|
|
1102
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1103
|
+
let n = node.firstChild;
|
|
1104
|
+
while (n) {
|
|
1105
|
+
const id = slotStartId(n);
|
|
1106
|
+
if (id !== null) {
|
|
1107
|
+
const next = afterRange(n, id);
|
|
1108
|
+
const displaced = ranges.get(id);
|
|
1109
|
+
if (displaced) {
|
|
1110
|
+
ranges.delete(id);
|
|
1111
|
+
placeRange(node, displaced, id, n);
|
|
1112
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1113
|
+
}
|
|
1114
|
+
n = next;
|
|
1115
|
+
continue;
|
|
1148
1116
|
}
|
|
1149
|
-
|
|
1117
|
+
flushGrafts(n, ranges);
|
|
1118
|
+
n = n.nextSibling;
|
|
1150
1119
|
}
|
|
1151
1120
|
}
|
|
1152
1121
|
function stashRange(frag, start, id) {
|
|
@@ -1178,7 +1147,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1178
1147
|
if (chunk.type === "outcome") {
|
|
1179
1148
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1180
1149
|
} else {
|
|
1181
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1150
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1182
1151
|
if (perFrame) {
|
|
1183
1152
|
let v = perFrame.get(chunk.id);
|
|
1184
1153
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1192,7 +1161,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1192
1161
|
}
|
|
1193
1162
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1194
1163
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1195
|
-
const
|
|
1164
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1196
1165
|
let resolveServerComponent;
|
|
1197
1166
|
function parseServerComponent(value, ctx) {
|
|
1198
1167
|
return {
|
|
@@ -1216,7 +1185,8 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
|
|
|
1216
1185
|
stream: parseServerComponent
|
|
1217
1186
|
},
|
|
1218
1187
|
serialize(node, ctx) {
|
|
1219
|
-
|
|
1188
|
+
const registry = "self._$SC";
|
|
1189
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1220
1190
|
},
|
|
1221
1191
|
deserialize(node, ctx) {
|
|
1222
1192
|
const id = ctx.deserialize(node.id);
|
|
@@ -1241,120 +1211,79 @@ function createServerComponentHandler({
|
|
|
1241
1211
|
host,
|
|
1242
1212
|
component,
|
|
1243
1213
|
onStream,
|
|
1244
|
-
documentComponent,
|
|
1245
1214
|
intercept,
|
|
1246
1215
|
consumer = client.getFlightDataConsumer,
|
|
1247
1216
|
codec = client.getServerFunctionsCodec
|
|
1248
1217
|
}) {
|
|
1249
|
-
const
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1254
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1255
|
-
fnId,
|
|
1256
|
-
frameId,
|
|
1257
|
-
take(prev) {
|
|
1258
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1259
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1260
|
-
const root = meta.frameId;
|
|
1261
|
-
let cur = forwards.get(root) ?? root;
|
|
1262
|
-
if (cur !== root && !host.get(cur)) {
|
|
1263
|
-
forwards.delete(root);
|
|
1264
|
-
cur = root;
|
|
1265
|
-
}
|
|
1266
|
-
if (cur === frameId) return true;
|
|
1267
|
-
let frame = host.get(cur);
|
|
1268
|
-
if (!frame) return false;
|
|
1269
|
-
while (frame) {
|
|
1270
|
-
frame.rebind(frameId);
|
|
1271
|
-
frame = host.get(cur);
|
|
1272
|
-
}
|
|
1273
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1274
|
-
return true;
|
|
1275
|
-
}
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1218
|
+
const byFn = new Map();
|
|
1219
|
+
const componentFor = fnId => {
|
|
1220
|
+
let comp = byFn.get(fnId);
|
|
1221
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1278
1222
|
return comp;
|
|
1279
1223
|
};
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1224
|
+
const byAddress = new Map();
|
|
1225
|
+
const bindingFor = (address, fnId) => {
|
|
1226
|
+
let binding = byAddress.get(address);
|
|
1227
|
+
if (!binding) {
|
|
1228
|
+
const comp = componentFor(fnId);
|
|
1229
|
+
binding = props => comp(props, () => address);
|
|
1230
|
+
binding[COMPONENT_BINDING] = {
|
|
1231
|
+
component: comp,
|
|
1232
|
+
address
|
|
1286
1233
|
};
|
|
1287
|
-
byAddress.set(address,
|
|
1234
|
+
byAddress.set(address, binding);
|
|
1288
1235
|
}
|
|
1289
|
-
return
|
|
1236
|
+
return binding;
|
|
1290
1237
|
};
|
|
1291
|
-
|
|
1292
|
-
resolveServerComponent = resolveAddress;
|
|
1238
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1293
1239
|
const versions = new Map();
|
|
1294
|
-
const bump =
|
|
1295
|
-
const version = (versions.get(
|
|
1296
|
-
versions.set(
|
|
1240
|
+
const bump = address => {
|
|
1241
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1242
|
+
versions.set(address, version);
|
|
1297
1243
|
return version;
|
|
1298
1244
|
};
|
|
1299
1245
|
return {
|
|
1300
1246
|
intercept: intercept && (info => {
|
|
1301
1247
|
const hit = intercept(info);
|
|
1302
|
-
if (hit
|
|
1303
|
-
|
|
1304
|
-
byAddress.set(address, {
|
|
1305
|
-
frameId: info.id,
|
|
1306
|
-
component: brand(hit, info.id, info.id)
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
return hit;
|
|
1248
|
+
if (hit === undefined) return undefined;
|
|
1249
|
+
return bindingFor(client.frameAddress(info.id, info.args), info.id);
|
|
1310
1250
|
}),
|
|
1311
1251
|
handle(response, ctx) {
|
|
1312
1252
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1313
1253
|
const address = client.frameAddress(ctx.id, ctx.args);
|
|
1314
|
-
|
|
1315
|
-
if (!entry) {
|
|
1316
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1317
|
-
if (adopted) {
|
|
1318
|
-
entry = {
|
|
1319
|
-
frameId: ctx.id,
|
|
1320
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1321
|
-
};
|
|
1322
|
-
byAddress.set(address, entry);
|
|
1323
|
-
} else {
|
|
1324
|
-
entry = boundaryFor(address, ctx.id);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1254
|
+
const binding = bindingFor(address, ctx.id);
|
|
1327
1255
|
if (response.headers.has(client.SINGLE_FLIGHT_HEADER)) {
|
|
1328
|
-
return applyFlightResponse(response,
|
|
1256
|
+
return applyFlightResponse(response, address, binding);
|
|
1329
1257
|
}
|
|
1330
|
-
const version = bump(
|
|
1331
|
-
if (onStream) onStream(
|
|
1258
|
+
const version = bump(address);
|
|
1259
|
+
if (onStream) onStream(address, version, response);
|
|
1332
1260
|
applyFrameResponse(response, host, {
|
|
1333
|
-
as:
|
|
1261
|
+
as: address,
|
|
1334
1262
|
version
|
|
1335
1263
|
}).catch(err => host.apply({
|
|
1336
1264
|
type: "error",
|
|
1337
|
-
id:
|
|
1265
|
+
id: address,
|
|
1338
1266
|
version,
|
|
1339
1267
|
error: {
|
|
1340
1268
|
message: String(err && err.message)
|
|
1341
1269
|
}
|
|
1342
1270
|
}));
|
|
1343
|
-
return
|
|
1271
|
+
return binding;
|
|
1344
1272
|
},
|
|
1345
|
-
showing(address, functionId
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1273
|
+
showing(address, functionId) {
|
|
1274
|
+
bindingFor(address, functionId);
|
|
1275
|
+
const comp = componentFor(functionId);
|
|
1276
|
+
if ((typeof comp === "function" || typeof comp === "object" && comp !== null) && !comp[COMPONENT_BINDING]) {
|
|
1277
|
+
comp[COMPONENT_BINDING] = {
|
|
1278
|
+
component: comp,
|
|
1350
1279
|
address
|
|
1351
|
-
}
|
|
1280
|
+
};
|
|
1352
1281
|
}
|
|
1353
1282
|
}
|
|
1354
1283
|
};
|
|
1355
|
-
async function applyFlightResponse(response,
|
|
1284
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1356
1285
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1357
|
-
const as = rootId ?
|
|
1286
|
+
const as = rootId ? address : undefined;
|
|
1358
1287
|
let feed;
|
|
1359
1288
|
const source = new ReadableStream({
|
|
1360
1289
|
start(controller) {
|
|
@@ -1365,10 +1294,6 @@ function createServerComponentHandler({
|
|
|
1365
1294
|
let carried = false;
|
|
1366
1295
|
await applyFrameResponse(response, host, {
|
|
1367
1296
|
as,
|
|
1368
|
-
route: id => {
|
|
1369
|
-
const local = byAddress.get(id);
|
|
1370
|
-
return local ? local.frameId : id;
|
|
1371
|
-
},
|
|
1372
1297
|
version: frameId => {
|
|
1373
1298
|
const version = bump(frameId);
|
|
1374
1299
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1389,7 +1314,7 @@ function createServerComponentHandler({
|
|
|
1389
1314
|
if (response.headers.has(client.ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(client.REVALIDATE_HEADER)) {
|
|
1390
1315
|
throw envelope.value;
|
|
1391
1316
|
}
|
|
1392
|
-
return rootId ?
|
|
1317
|
+
return rootId ? binding : envelope.value;
|
|
1393
1318
|
}
|
|
1394
1319
|
}
|
|
1395
1320
|
|
|
@@ -1568,15 +1493,7 @@ function slotsFor(props) {
|
|
|
1568
1493
|
return settle(normalizeSlotContent(value));
|
|
1569
1494
|
}
|
|
1570
1495
|
if (ctx && ctx.range) {
|
|
1571
|
-
let claim = adopted;
|
|
1572
1496
|
const source = value;
|
|
1573
|
-
const accessor = () => {
|
|
1574
|
-
if (claim) {
|
|
1575
|
-
claim = false;
|
|
1576
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1577
|
-
}
|
|
1578
|
-
return typeof source === "function" ? source() : source;
|
|
1579
|
-
};
|
|
1580
1497
|
const owner = solidJs.createOwner();
|
|
1581
1498
|
bindings.set(key, owner);
|
|
1582
1499
|
ctx.onCleanup(() => {
|
|
@@ -1584,7 +1501,8 @@ function slotsFor(props) {
|
|
|
1584
1501
|
owner.dispose();
|
|
1585
1502
|
});
|
|
1586
1503
|
const end = ctx.range.end;
|
|
1587
|
-
|
|
1504
|
+
const bind = () => web$1.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1505
|
+
solidJs.runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1588
1506
|
return undefined;
|
|
1589
1507
|
}
|
|
1590
1508
|
return settle(normalizeSlotContent(value));
|
|
@@ -1598,19 +1516,24 @@ function revealSeam(owner) {
|
|
|
1598
1516
|
function boundaryScope(owner) {
|
|
1599
1517
|
return fn => solidJs.getOwner() ? fn() : solidJs.runWithOwner(owner, fn);
|
|
1600
1518
|
}
|
|
1601
|
-
function
|
|
1602
|
-
|
|
1519
|
+
function followBinding(frame, binding) {
|
|
1520
|
+
solidJs.createRenderEffect(binding, address => frame.rebind(address));
|
|
1521
|
+
}
|
|
1522
|
+
function boundaryComponent(host, fnId) {
|
|
1523
|
+
return (props, binding) => {
|
|
1603
1524
|
const owner = solidJs.getOwner();
|
|
1604
1525
|
const {
|
|
1605
1526
|
element,
|
|
1527
|
+
frame,
|
|
1606
1528
|
dispose
|
|
1607
1529
|
} = createFrameElement({
|
|
1608
1530
|
host,
|
|
1609
|
-
id,
|
|
1531
|
+
id: binding ? binding() : fnId,
|
|
1610
1532
|
slots: slotsFor(props),
|
|
1611
1533
|
ownerScope: boundaryScope(owner),
|
|
1612
1534
|
reveal: revealSeam(owner)
|
|
1613
1535
|
});
|
|
1536
|
+
if (binding) followBinding(frame, binding);
|
|
1614
1537
|
solidJs.onCleanup(dispose);
|
|
1615
1538
|
return element;
|
|
1616
1539
|
};
|
|
@@ -1632,51 +1555,65 @@ function findBoundaryElement(id) {
|
|
|
1632
1555
|
return boundaryIndex.get(id);
|
|
1633
1556
|
}
|
|
1634
1557
|
const boundaryWaiters = new Map();
|
|
1635
|
-
function
|
|
1558
|
+
function boundaryMayArrive() {
|
|
1636
1559
|
const hy = globalThis._$HY;
|
|
1637
|
-
|
|
1560
|
+
if (!hy) return false;
|
|
1561
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1638
1562
|
}
|
|
1639
1563
|
function installRevealHook() {
|
|
1640
1564
|
const hy = globalThis._$HY;
|
|
1641
|
-
if (!hy || hy.$sc) return;
|
|
1565
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1642
1566
|
hy.$sc = true;
|
|
1643
|
-
|
|
1644
|
-
hy.fe = (fragmentId, parent) => {
|
|
1645
|
-
if (prev) prev(fragmentId, parent);
|
|
1567
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1646
1568
|
if (!boundaryIndex) return;
|
|
1647
1569
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1648
|
-
if (
|
|
1649
|
-
|
|
1570
|
+
if (root) indexBoundaries(root);
|
|
1571
|
+
if (!boundaryWaiters.size) return;
|
|
1572
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1650
1573
|
for (const [id, notify] of boundaryWaiters) {
|
|
1651
|
-
const el = boundaryIndex.get(id);
|
|
1652
|
-
if (!el) continue;
|
|
1574
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1575
|
+
if (!el && !exhausted) continue;
|
|
1653
1576
|
boundaryWaiters.delete(id);
|
|
1654
1577
|
notify(el);
|
|
1655
1578
|
}
|
|
1656
|
-
};
|
|
1579
|
+
});
|
|
1657
1580
|
}
|
|
1658
|
-
function documentBoundary(host, id, props) {
|
|
1581
|
+
function documentBoundary(host, id, props, binding) {
|
|
1582
|
+
installRevealHook();
|
|
1659
1583
|
const claimed = claimedBoundaries.has(id);
|
|
1660
1584
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1661
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1662
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1585
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1586
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1663
1587
|
const owner = solidJs.getOwner();
|
|
1664
1588
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1665
1589
|
solidJs.onCleanup(() => boundaryWaiters.delete(id));
|
|
1666
|
-
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1590
|
+
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1591
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1592
|
+
}
|
|
1593
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1594
|
+
}
|
|
1595
|
+
function documentAddress(id) {
|
|
1596
|
+
const records = globalThis._$SC?.a;
|
|
1597
|
+
if (records) {
|
|
1598
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1667
1599
|
}
|
|
1668
|
-
return
|
|
1600
|
+
return id;
|
|
1669
1601
|
}
|
|
1670
|
-
function adoptBoundary(host, id, el, props) {
|
|
1602
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1671
1603
|
claimedBoundaries.add(id);
|
|
1672
|
-
const
|
|
1673
|
-
|
|
1604
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1605
|
+
const appliedRecords = new Set();
|
|
1606
|
+
const drainRecords = () => {
|
|
1607
|
+
const hy = globalThis._$HY;
|
|
1608
|
+
if (!hy || !hy.r) return;
|
|
1674
1609
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1675
1610
|
for (const key of Object.keys(hy.r)) {
|
|
1611
|
+
if (appliedRecords.has(key)) continue;
|
|
1676
1612
|
if (key.startsWith(slotPrefix)) {
|
|
1613
|
+
appliedRecords.add(key);
|
|
1677
1614
|
host.apply({
|
|
1678
1615
|
type: "slot",
|
|
1679
|
-
id,
|
|
1616
|
+
id: address,
|
|
1680
1617
|
version: 0,
|
|
1681
1618
|
key: key.slice(slotPrefix.length),
|
|
1682
1619
|
args: hy.r[key]
|
|
@@ -1684,6 +1621,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1684
1621
|
} else if (key.startsWith("sc:region:")) {
|
|
1685
1622
|
const childId = key.slice("sc:region:".length);
|
|
1686
1623
|
if (childId.startsWith(id + ".")) {
|
|
1624
|
+
appliedRecords.add(key);
|
|
1687
1625
|
const val = hy.r[key];
|
|
1688
1626
|
const apply = html => host.apply({
|
|
1689
1627
|
type: "html",
|
|
@@ -1695,16 +1633,27 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1695
1633
|
}
|
|
1696
1634
|
}
|
|
1697
1635
|
}
|
|
1698
|
-
}
|
|
1636
|
+
};
|
|
1637
|
+
drainRecords();
|
|
1699
1638
|
const owner = solidJs.getOwner();
|
|
1700
1639
|
const frame = createFrame(el, {
|
|
1701
1640
|
adopt: true,
|
|
1702
1641
|
host,
|
|
1703
|
-
id,
|
|
1642
|
+
id: address,
|
|
1704
1643
|
slots: slotsFor(props),
|
|
1705
1644
|
ownerScope: boundaryScope(owner),
|
|
1706
|
-
reveal: revealSeam(owner)
|
|
1645
|
+
reveal: revealSeam(owner),
|
|
1646
|
+
...{
|
|
1647
|
+
recordsPending: () => {
|
|
1648
|
+
if (document.readyState === "loading") return true;
|
|
1649
|
+
const hy = globalThis._$HY;
|
|
1650
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1651
|
+
},
|
|
1652
|
+
drainRecords,
|
|
1653
|
+
claimScope: id
|
|
1654
|
+
}
|
|
1707
1655
|
});
|
|
1656
|
+
if (binding) followBinding(frame, binding);
|
|
1708
1657
|
solidJs.onCleanup(() => frame.dispose());
|
|
1709
1658
|
return el;
|
|
1710
1659
|
}
|
|
@@ -1719,17 +1668,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1719
1668
|
g._$SC.a[a] = i;
|
|
1720
1669
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1721
1670
|
}
|
|
1722
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1671
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1723
1672
|
}
|
|
1724
1673
|
};
|
|
1725
1674
|
}
|
|
1726
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1675
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1727
1676
|
installRevealHook();
|
|
1728
1677
|
const handler = createServerComponentHandler({
|
|
1729
1678
|
host,
|
|
1730
|
-
component:
|
|
1731
|
-
onStream:
|
|
1732
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1679
|
+
component: fnId => g._$SC.r(fnId),
|
|
1680
|
+
onStream: address => beginStream(address),
|
|
1733
1681
|
intercept: ({
|
|
1734
1682
|
id
|
|
1735
1683
|
}) => {
|
|
@@ -1737,7 +1685,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1737
1685
|
return g._$SC.r(id);
|
|
1738
1686
|
}
|
|
1739
1687
|
});
|
|
1740
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1688
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1741
1689
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1742
1690
|
for (const address in records) showing(address, records[address]);
|
|
1743
1691
|
g._$SC.reg = showing;
|