@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.cjs
CHANGED
|
@@ -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() {
|
|
@@ -903,11 +862,11 @@ function collectSlots(n, end, out) {
|
|
|
903
862
|
n = n.nextSibling;
|
|
904
863
|
}
|
|
905
864
|
}
|
|
906
|
-
function collectRegionElements(node, regions
|
|
865
|
+
function collectRegionElements(node, regions) {
|
|
907
866
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
908
867
|
if (isFrameElement(node)) {
|
|
909
868
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
910
|
-
if (childId && childId.
|
|
869
|
+
if (childId && childId.includes(".")) {
|
|
911
870
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
912
871
|
if (!regions.has(argKey)) {
|
|
913
872
|
regions.set(argKey, {
|
|
@@ -920,7 +879,7 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
920
879
|
}
|
|
921
880
|
return;
|
|
922
881
|
}
|
|
923
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
882
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
924
883
|
}
|
|
925
884
|
function renameRegion(entry, childId) {
|
|
926
885
|
entry.childId = childId;
|
|
@@ -988,11 +947,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
988
947
|
}
|
|
989
948
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
990
949
|
}
|
|
991
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
950
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
992
951
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
993
952
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
994
953
|
morphAttributes(oldNode, newNode, claim);
|
|
995
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
954
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
996
955
|
} else if (oldNode.data !== newNode.data) {
|
|
997
956
|
oldNode.data = newNode.data;
|
|
998
957
|
}
|
|
@@ -1026,6 +985,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1026
985
|
n = next;
|
|
1027
986
|
}
|
|
1028
987
|
}
|
|
988
|
+
function placeRange(parent, range, id, ref) {
|
|
989
|
+
if (range.nodeType === 11 ) {
|
|
990
|
+
parent.insertBefore(range, ref);
|
|
991
|
+
} else {
|
|
992
|
+
moveRangeBefore(parent, range, id, ref);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
1029
995
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1030
996
|
const end = slotEnd(id);
|
|
1031
997
|
let n = start;
|
|
@@ -1043,7 +1009,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1043
1009
|
}
|
|
1044
1010
|
return after;
|
|
1045
1011
|
}
|
|
1046
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1012
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1047
1013
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1048
1014
|
let newChild = source.firstChild;
|
|
1049
1015
|
while (newChild) {
|
|
@@ -1059,11 +1025,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1059
1025
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1060
1026
|
if (existing) {
|
|
1061
1027
|
if (ranges) ranges.delete(pid);
|
|
1062
|
-
|
|
1063
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1064
|
-
} else {
|
|
1065
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1066
|
-
}
|
|
1028
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1067
1029
|
newChild = afterRange(newChild, pid);
|
|
1068
1030
|
} else {
|
|
1069
1031
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1074,17 +1036,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1074
1036
|
if (!old) {
|
|
1075
1037
|
parent.insertBefore(newChild, boundEnd);
|
|
1076
1038
|
if (claim) claim(newChild);
|
|
1039
|
+
if (grafts) grafts.push(newChild);
|
|
1077
1040
|
newChild = nextNew;
|
|
1078
1041
|
continue;
|
|
1079
1042
|
}
|
|
1080
1043
|
if (isSlotMarker(old)) {
|
|
1081
1044
|
parent.insertBefore(newChild, old);
|
|
1082
1045
|
if (claim) claim(newChild);
|
|
1046
|
+
if (grafts) grafts.push(newChild);
|
|
1083
1047
|
newChild = nextNew;
|
|
1084
1048
|
continue;
|
|
1085
1049
|
}
|
|
1086
1050
|
if (compatible(old, newChild)) {
|
|
1087
|
-
morphNode(old, newChild, claim, ranges);
|
|
1051
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1088
1052
|
oldChild = old.nextSibling;
|
|
1089
1053
|
newChild = nextNew;
|
|
1090
1054
|
continue;
|
|
@@ -1097,13 +1061,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1097
1061
|
}
|
|
1098
1062
|
if (ahead && ahead !== boundEnd) {
|
|
1099
1063
|
parent.insertBefore(ahead, old);
|
|
1100
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1064
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1101
1065
|
newChild = nextNew;
|
|
1102
1066
|
continue;
|
|
1103
1067
|
}
|
|
1104
1068
|
}
|
|
1105
1069
|
parent.insertBefore(newChild, old);
|
|
1106
1070
|
if (claim) claim(newChild);
|
|
1071
|
+
if (grafts) grafts.push(newChild);
|
|
1107
1072
|
newChild = nextNew;
|
|
1108
1073
|
}
|
|
1109
1074
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1120,20 +1085,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1120
1085
|
oldChild = next;
|
|
1121
1086
|
}
|
|
1122
1087
|
}
|
|
1123
|
-
function
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
const
|
|
1128
|
-
if (
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1088
|
+
function flushGrafts(node, ranges) {
|
|
1089
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1090
|
+
let n = node.firstChild;
|
|
1091
|
+
while (n) {
|
|
1092
|
+
const id = slotStartId(n);
|
|
1093
|
+
if (id !== null) {
|
|
1094
|
+
const next = afterRange(n, id);
|
|
1095
|
+
const displaced = ranges.get(id);
|
|
1096
|
+
if (displaced) {
|
|
1097
|
+
ranges.delete(id);
|
|
1098
|
+
placeRange(node, displaced, id, n);
|
|
1099
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1100
|
+
}
|
|
1101
|
+
n = next;
|
|
1102
|
+
continue;
|
|
1135
1103
|
}
|
|
1136
|
-
|
|
1104
|
+
flushGrafts(n, ranges);
|
|
1105
|
+
n = n.nextSibling;
|
|
1137
1106
|
}
|
|
1138
1107
|
}
|
|
1139
1108
|
function stashRange(frag, start, id) {
|
|
@@ -1165,7 +1134,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1165
1134
|
if (chunk.type === "outcome") {
|
|
1166
1135
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1167
1136
|
} else {
|
|
1168
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1137
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1169
1138
|
if (perFrame) {
|
|
1170
1139
|
let v = perFrame.get(chunk.id);
|
|
1171
1140
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1179,7 +1148,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1179
1148
|
}
|
|
1180
1149
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1181
1150
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1182
|
-
const
|
|
1151
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1183
1152
|
let resolveServerComponent;
|
|
1184
1153
|
function parseServerComponent(value, ctx) {
|
|
1185
1154
|
return {
|
|
@@ -1203,7 +1172,8 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
|
|
|
1203
1172
|
stream: parseServerComponent
|
|
1204
1173
|
},
|
|
1205
1174
|
serialize(node, ctx) {
|
|
1206
|
-
|
|
1175
|
+
const registry = "self._$SC";
|
|
1176
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1207
1177
|
},
|
|
1208
1178
|
deserialize(node, ctx) {
|
|
1209
1179
|
const id = ctx.deserialize(node.id);
|
|
@@ -1228,120 +1198,79 @@ function createServerComponentHandler({
|
|
|
1228
1198
|
host,
|
|
1229
1199
|
component,
|
|
1230
1200
|
onStream,
|
|
1231
|
-
documentComponent,
|
|
1232
1201
|
intercept,
|
|
1233
1202
|
consumer = client.getFlightDataConsumer,
|
|
1234
1203
|
codec = client.getServerFunctionsCodec
|
|
1235
1204
|
}) {
|
|
1236
|
-
const
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1241
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1242
|
-
fnId,
|
|
1243
|
-
frameId,
|
|
1244
|
-
take(prev) {
|
|
1245
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1246
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1247
|
-
const root = meta.frameId;
|
|
1248
|
-
let cur = forwards.get(root) ?? root;
|
|
1249
|
-
if (cur !== root && !host.get(cur)) {
|
|
1250
|
-
forwards.delete(root);
|
|
1251
|
-
cur = root;
|
|
1252
|
-
}
|
|
1253
|
-
if (cur === frameId) return true;
|
|
1254
|
-
let frame = host.get(cur);
|
|
1255
|
-
if (!frame) return false;
|
|
1256
|
-
while (frame) {
|
|
1257
|
-
frame.rebind(frameId);
|
|
1258
|
-
frame = host.get(cur);
|
|
1259
|
-
}
|
|
1260
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1261
|
-
return true;
|
|
1262
|
-
}
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1205
|
+
const byFn = new Map();
|
|
1206
|
+
const componentFor = fnId => {
|
|
1207
|
+
let comp = byFn.get(fnId);
|
|
1208
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1265
1209
|
return comp;
|
|
1266
1210
|
};
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1211
|
+
const byAddress = new Map();
|
|
1212
|
+
const bindingFor = (address, fnId) => {
|
|
1213
|
+
let binding = byAddress.get(address);
|
|
1214
|
+
if (!binding) {
|
|
1215
|
+
const comp = componentFor(fnId);
|
|
1216
|
+
binding = props => comp(props, () => address);
|
|
1217
|
+
binding[COMPONENT_BINDING] = {
|
|
1218
|
+
component: comp,
|
|
1219
|
+
address
|
|
1273
1220
|
};
|
|
1274
|
-
byAddress.set(address,
|
|
1221
|
+
byAddress.set(address, binding);
|
|
1275
1222
|
}
|
|
1276
|
-
return
|
|
1223
|
+
return binding;
|
|
1277
1224
|
};
|
|
1278
|
-
|
|
1279
|
-
resolveServerComponent = resolveAddress;
|
|
1225
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1280
1226
|
const versions = new Map();
|
|
1281
|
-
const bump =
|
|
1282
|
-
const version = (versions.get(
|
|
1283
|
-
versions.set(
|
|
1227
|
+
const bump = address => {
|
|
1228
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1229
|
+
versions.set(address, version);
|
|
1284
1230
|
return version;
|
|
1285
1231
|
};
|
|
1286
1232
|
return {
|
|
1287
1233
|
intercept: intercept && (info => {
|
|
1288
1234
|
const hit = intercept(info);
|
|
1289
|
-
if (hit
|
|
1290
|
-
|
|
1291
|
-
byAddress.set(address, {
|
|
1292
|
-
frameId: info.id,
|
|
1293
|
-
component: brand(hit, info.id, info.id)
|
|
1294
|
-
});
|
|
1295
|
-
}
|
|
1296
|
-
return hit;
|
|
1235
|
+
if (hit === undefined) return undefined;
|
|
1236
|
+
return bindingFor(client.frameAddress(info.id, info.args), info.id);
|
|
1297
1237
|
}),
|
|
1298
1238
|
handle(response, ctx) {
|
|
1299
1239
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1300
1240
|
const address = client.frameAddress(ctx.id, ctx.args);
|
|
1301
|
-
|
|
1302
|
-
if (!entry) {
|
|
1303
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1304
|
-
if (adopted) {
|
|
1305
|
-
entry = {
|
|
1306
|
-
frameId: ctx.id,
|
|
1307
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1308
|
-
};
|
|
1309
|
-
byAddress.set(address, entry);
|
|
1310
|
-
} else {
|
|
1311
|
-
entry = boundaryFor(address, ctx.id);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1241
|
+
const binding = bindingFor(address, ctx.id);
|
|
1314
1242
|
if (response.headers.has(client.SINGLE_FLIGHT_HEADER)) {
|
|
1315
|
-
return applyFlightResponse(response,
|
|
1243
|
+
return applyFlightResponse(response, address, binding);
|
|
1316
1244
|
}
|
|
1317
|
-
const version = bump(
|
|
1318
|
-
if (onStream) onStream(
|
|
1245
|
+
const version = bump(address);
|
|
1246
|
+
if (onStream) onStream(address, version, response);
|
|
1319
1247
|
applyFrameResponse(response, host, {
|
|
1320
|
-
as:
|
|
1248
|
+
as: address,
|
|
1321
1249
|
version
|
|
1322
1250
|
}).catch(err => host.apply({
|
|
1323
1251
|
type: "error",
|
|
1324
|
-
id:
|
|
1252
|
+
id: address,
|
|
1325
1253
|
version,
|
|
1326
1254
|
error: {
|
|
1327
1255
|
message: String(err && err.message)
|
|
1328
1256
|
}
|
|
1329
1257
|
}));
|
|
1330
|
-
return
|
|
1258
|
+
return binding;
|
|
1331
1259
|
},
|
|
1332
|
-
showing(address, functionId
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1260
|
+
showing(address, functionId) {
|
|
1261
|
+
bindingFor(address, functionId);
|
|
1262
|
+
const comp = componentFor(functionId);
|
|
1263
|
+
if ((typeof comp === "function" || typeof comp === "object" && comp !== null) && !comp[COMPONENT_BINDING]) {
|
|
1264
|
+
comp[COMPONENT_BINDING] = {
|
|
1265
|
+
component: comp,
|
|
1337
1266
|
address
|
|
1338
|
-
}
|
|
1267
|
+
};
|
|
1339
1268
|
}
|
|
1340
1269
|
}
|
|
1341
1270
|
};
|
|
1342
|
-
async function applyFlightResponse(response,
|
|
1271
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1343
1272
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1344
|
-
const as = rootId ?
|
|
1273
|
+
const as = rootId ? address : undefined;
|
|
1345
1274
|
let feed;
|
|
1346
1275
|
const source = new ReadableStream({
|
|
1347
1276
|
start(controller) {
|
|
@@ -1352,10 +1281,6 @@ function createServerComponentHandler({
|
|
|
1352
1281
|
let carried = false;
|
|
1353
1282
|
await applyFrameResponse(response, host, {
|
|
1354
1283
|
as,
|
|
1355
|
-
route: id => {
|
|
1356
|
-
const local = byAddress.get(id);
|
|
1357
|
-
return local ? local.frameId : id;
|
|
1358
|
-
},
|
|
1359
1284
|
version: frameId => {
|
|
1360
1285
|
const version = bump(frameId);
|
|
1361
1286
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1376,7 +1301,7 @@ function createServerComponentHandler({
|
|
|
1376
1301
|
if (response.headers.has(client.ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(client.REVALIDATE_HEADER)) {
|
|
1377
1302
|
throw envelope.value;
|
|
1378
1303
|
}
|
|
1379
|
-
return rootId ?
|
|
1304
|
+
return rootId ? binding : envelope.value;
|
|
1380
1305
|
}
|
|
1381
1306
|
}
|
|
1382
1307
|
|
|
@@ -1555,15 +1480,7 @@ function slotsFor(props) {
|
|
|
1555
1480
|
return settle(normalizeSlotContent(value));
|
|
1556
1481
|
}
|
|
1557
1482
|
if (ctx && ctx.range) {
|
|
1558
|
-
let claim = adopted;
|
|
1559
1483
|
const source = value;
|
|
1560
|
-
const accessor = () => {
|
|
1561
|
-
if (claim) {
|
|
1562
|
-
claim = false;
|
|
1563
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1564
|
-
}
|
|
1565
|
-
return typeof source === "function" ? source() : source;
|
|
1566
|
-
};
|
|
1567
1484
|
const owner = solidJs.createOwner();
|
|
1568
1485
|
bindings.set(key, owner);
|
|
1569
1486
|
ctx.onCleanup(() => {
|
|
@@ -1571,7 +1488,8 @@ function slotsFor(props) {
|
|
|
1571
1488
|
owner.dispose();
|
|
1572
1489
|
});
|
|
1573
1490
|
const end = ctx.range.end;
|
|
1574
|
-
|
|
1491
|
+
const bind = () => web$1.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1492
|
+
solidJs.runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1575
1493
|
return undefined;
|
|
1576
1494
|
}
|
|
1577
1495
|
return settle(normalizeSlotContent(value));
|
|
@@ -1585,19 +1503,24 @@ function revealSeam(owner) {
|
|
|
1585
1503
|
function boundaryScope(owner) {
|
|
1586
1504
|
return fn => solidJs.getOwner() ? fn() : solidJs.runWithOwner(owner, fn);
|
|
1587
1505
|
}
|
|
1588
|
-
function
|
|
1589
|
-
|
|
1506
|
+
function followBinding(frame, binding) {
|
|
1507
|
+
solidJs.createRenderEffect(binding, address => frame.rebind(address));
|
|
1508
|
+
}
|
|
1509
|
+
function boundaryComponent(host, fnId) {
|
|
1510
|
+
return (props, binding) => {
|
|
1590
1511
|
const owner = solidJs.getOwner();
|
|
1591
1512
|
const {
|
|
1592
1513
|
element,
|
|
1514
|
+
frame,
|
|
1593
1515
|
dispose
|
|
1594
1516
|
} = createFrameElement({
|
|
1595
1517
|
host,
|
|
1596
|
-
id,
|
|
1518
|
+
id: binding ? binding() : fnId,
|
|
1597
1519
|
slots: slotsFor(props),
|
|
1598
1520
|
ownerScope: boundaryScope(owner),
|
|
1599
1521
|
reveal: revealSeam(owner)
|
|
1600
1522
|
});
|
|
1523
|
+
if (binding) followBinding(frame, binding);
|
|
1601
1524
|
solidJs.onCleanup(dispose);
|
|
1602
1525
|
return element;
|
|
1603
1526
|
};
|
|
@@ -1619,51 +1542,65 @@ function findBoundaryElement(id) {
|
|
|
1619
1542
|
return boundaryIndex.get(id);
|
|
1620
1543
|
}
|
|
1621
1544
|
const boundaryWaiters = new Map();
|
|
1622
|
-
function
|
|
1545
|
+
function boundaryMayArrive() {
|
|
1623
1546
|
const hy = globalThis._$HY;
|
|
1624
|
-
|
|
1547
|
+
if (!hy) return false;
|
|
1548
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1625
1549
|
}
|
|
1626
1550
|
function installRevealHook() {
|
|
1627
1551
|
const hy = globalThis._$HY;
|
|
1628
|
-
if (!hy || hy.$sc) return;
|
|
1552
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1629
1553
|
hy.$sc = true;
|
|
1630
|
-
|
|
1631
|
-
hy.fe = (fragmentId, parent) => {
|
|
1632
|
-
if (prev) prev(fragmentId, parent);
|
|
1554
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1633
1555
|
if (!boundaryIndex) return;
|
|
1634
1556
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1635
|
-
if (
|
|
1636
|
-
|
|
1557
|
+
if (root) indexBoundaries(root);
|
|
1558
|
+
if (!boundaryWaiters.size) return;
|
|
1559
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1637
1560
|
for (const [id, notify] of boundaryWaiters) {
|
|
1638
|
-
const el = boundaryIndex.get(id);
|
|
1639
|
-
if (!el) continue;
|
|
1561
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1562
|
+
if (!el && !exhausted) continue;
|
|
1640
1563
|
boundaryWaiters.delete(id);
|
|
1641
1564
|
notify(el);
|
|
1642
1565
|
}
|
|
1643
|
-
};
|
|
1566
|
+
});
|
|
1644
1567
|
}
|
|
1645
|
-
function documentBoundary(host, id, props) {
|
|
1568
|
+
function documentBoundary(host, id, props, binding) {
|
|
1569
|
+
installRevealHook();
|
|
1646
1570
|
const claimed = claimedBoundaries.has(id);
|
|
1647
1571
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1648
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1649
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1572
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1573
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1650
1574
|
const owner = solidJs.getOwner();
|
|
1651
1575
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1652
1576
|
solidJs.onCleanup(() => boundaryWaiters.delete(id));
|
|
1653
|
-
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1577
|
+
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1578
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1579
|
+
}
|
|
1580
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1581
|
+
}
|
|
1582
|
+
function documentAddress(id) {
|
|
1583
|
+
const records = globalThis._$SC?.a;
|
|
1584
|
+
if (records) {
|
|
1585
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1654
1586
|
}
|
|
1655
|
-
return
|
|
1587
|
+
return id;
|
|
1656
1588
|
}
|
|
1657
|
-
function adoptBoundary(host, id, el, props) {
|
|
1589
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1658
1590
|
claimedBoundaries.add(id);
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1591
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1592
|
+
const appliedRecords = new Set();
|
|
1593
|
+
const drainRecords = () => {
|
|
1594
|
+
const hy = globalThis._$HY;
|
|
1595
|
+
if (!hy || !hy.r) return;
|
|
1661
1596
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1662
1597
|
for (const key of Object.keys(hy.r)) {
|
|
1598
|
+
if (appliedRecords.has(key)) continue;
|
|
1663
1599
|
if (key.startsWith(slotPrefix)) {
|
|
1600
|
+
appliedRecords.add(key);
|
|
1664
1601
|
host.apply({
|
|
1665
1602
|
type: "slot",
|
|
1666
|
-
id,
|
|
1603
|
+
id: address,
|
|
1667
1604
|
version: 0,
|
|
1668
1605
|
key: key.slice(slotPrefix.length),
|
|
1669
1606
|
args: hy.r[key]
|
|
@@ -1671,6 +1608,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1671
1608
|
} else if (key.startsWith("sc:region:")) {
|
|
1672
1609
|
const childId = key.slice("sc:region:".length);
|
|
1673
1610
|
if (childId.startsWith(id + ".")) {
|
|
1611
|
+
appliedRecords.add(key);
|
|
1674
1612
|
const val = hy.r[key];
|
|
1675
1613
|
const apply = html => host.apply({
|
|
1676
1614
|
type: "html",
|
|
@@ -1682,16 +1620,27 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1682
1620
|
}
|
|
1683
1621
|
}
|
|
1684
1622
|
}
|
|
1685
|
-
}
|
|
1623
|
+
};
|
|
1624
|
+
drainRecords();
|
|
1686
1625
|
const owner = solidJs.getOwner();
|
|
1687
1626
|
const frame = createFrame(el, {
|
|
1688
1627
|
adopt: true,
|
|
1689
1628
|
host,
|
|
1690
|
-
id,
|
|
1629
|
+
id: address,
|
|
1691
1630
|
slots: slotsFor(props),
|
|
1692
1631
|
ownerScope: boundaryScope(owner),
|
|
1693
|
-
reveal: revealSeam(owner)
|
|
1632
|
+
reveal: revealSeam(owner),
|
|
1633
|
+
...{
|
|
1634
|
+
recordsPending: () => {
|
|
1635
|
+
if (document.readyState === "loading") return true;
|
|
1636
|
+
const hy = globalThis._$HY;
|
|
1637
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1638
|
+
},
|
|
1639
|
+
drainRecords,
|
|
1640
|
+
claimScope: id
|
|
1641
|
+
}
|
|
1694
1642
|
});
|
|
1643
|
+
if (binding) followBinding(frame, binding);
|
|
1695
1644
|
solidJs.onCleanup(() => frame.dispose());
|
|
1696
1645
|
return el;
|
|
1697
1646
|
}
|
|
@@ -1706,17 +1655,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1706
1655
|
g._$SC.a[a] = i;
|
|
1707
1656
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1708
1657
|
}
|
|
1709
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1658
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1710
1659
|
}
|
|
1711
1660
|
};
|
|
1712
1661
|
}
|
|
1713
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1662
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1714
1663
|
installRevealHook();
|
|
1715
1664
|
const handler = createServerComponentHandler({
|
|
1716
1665
|
host,
|
|
1717
|
-
component:
|
|
1718
|
-
onStream:
|
|
1719
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1666
|
+
component: fnId => g._$SC.r(fnId),
|
|
1667
|
+
onStream: address => beginStream(address),
|
|
1720
1668
|
intercept: ({
|
|
1721
1669
|
id
|
|
1722
1670
|
}) => {
|
|
@@ -1724,7 +1672,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1724
1672
|
return g._$SC.r(id);
|
|
1725
1673
|
}
|
|
1726
1674
|
});
|
|
1727
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1675
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1728
1676
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1729
1677
|
for (const address in records) showing(address, records[address]);
|
|
1730
1678
|
g._$SC.reg = showing;
|