@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
|
@@ -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() {
|
|
@@ -905,11 +864,11 @@ function collectSlots(n, end, out) {
|
|
|
905
864
|
n = n.nextSibling;
|
|
906
865
|
}
|
|
907
866
|
}
|
|
908
|
-
function collectRegionElements(node, regions
|
|
867
|
+
function collectRegionElements(node, regions) {
|
|
909
868
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
910
869
|
if (isFrameElement(node)) {
|
|
911
870
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
912
|
-
if (childId && childId.
|
|
871
|
+
if (childId && childId.includes(".")) {
|
|
913
872
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
914
873
|
if (!regions.has(argKey)) {
|
|
915
874
|
regions.set(argKey, {
|
|
@@ -922,7 +881,7 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
922
881
|
}
|
|
923
882
|
return;
|
|
924
883
|
}
|
|
925
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
884
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
926
885
|
}
|
|
927
886
|
function renameRegion(entry, childId) {
|
|
928
887
|
entry.childId = childId;
|
|
@@ -990,11 +949,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
990
949
|
}
|
|
991
950
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
992
951
|
}
|
|
993
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
952
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
994
953
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
995
954
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
996
955
|
morphAttributes(oldNode, newNode, claim);
|
|
997
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
956
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
998
957
|
} else if (oldNode.data !== newNode.data) {
|
|
999
958
|
oldNode.data = newNode.data;
|
|
1000
959
|
}
|
|
@@ -1037,6 +996,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1037
996
|
n = next;
|
|
1038
997
|
}
|
|
1039
998
|
}
|
|
999
|
+
function placeRange(parent, range, id, ref) {
|
|
1000
|
+
if (range.nodeType === 11 ) {
|
|
1001
|
+
parent.insertBefore(range, ref);
|
|
1002
|
+
} else {
|
|
1003
|
+
moveRangeBefore(parent, range, id, ref);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1040
1006
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1041
1007
|
const end = slotEnd(id);
|
|
1042
1008
|
let n = start;
|
|
@@ -1054,7 +1020,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1054
1020
|
}
|
|
1055
1021
|
return after;
|
|
1056
1022
|
}
|
|
1057
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1023
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1058
1024
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1059
1025
|
let newChild = source.firstChild;
|
|
1060
1026
|
while (newChild) {
|
|
@@ -1070,11 +1036,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1070
1036
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1071
1037
|
if (existing) {
|
|
1072
1038
|
if (ranges) ranges.delete(pid);
|
|
1073
|
-
|
|
1074
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1075
|
-
} else {
|
|
1076
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1077
|
-
}
|
|
1039
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1078
1040
|
newChild = afterRange(newChild, pid);
|
|
1079
1041
|
} else {
|
|
1080
1042
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1085,17 +1047,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1085
1047
|
if (!old) {
|
|
1086
1048
|
parent.insertBefore(newChild, boundEnd);
|
|
1087
1049
|
if (claim) claim(newChild);
|
|
1050
|
+
if (grafts) grafts.push(newChild);
|
|
1088
1051
|
newChild = nextNew;
|
|
1089
1052
|
continue;
|
|
1090
1053
|
}
|
|
1091
1054
|
if (isSlotMarker(old)) {
|
|
1092
1055
|
parent.insertBefore(newChild, old);
|
|
1093
1056
|
if (claim) claim(newChild);
|
|
1057
|
+
if (grafts) grafts.push(newChild);
|
|
1094
1058
|
newChild = nextNew;
|
|
1095
1059
|
continue;
|
|
1096
1060
|
}
|
|
1097
1061
|
if (compatible(old, newChild)) {
|
|
1098
|
-
morphNode(old, newChild, claim, ranges);
|
|
1062
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1099
1063
|
oldChild = old.nextSibling;
|
|
1100
1064
|
newChild = nextNew;
|
|
1101
1065
|
continue;
|
|
@@ -1108,13 +1072,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1108
1072
|
}
|
|
1109
1073
|
if (ahead && ahead !== boundEnd) {
|
|
1110
1074
|
parent.insertBefore(ahead, old);
|
|
1111
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1075
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1112
1076
|
newChild = nextNew;
|
|
1113
1077
|
continue;
|
|
1114
1078
|
}
|
|
1115
1079
|
}
|
|
1116
1080
|
parent.insertBefore(newChild, old);
|
|
1117
1081
|
if (claim) claim(newChild);
|
|
1082
|
+
if (grafts) grafts.push(newChild);
|
|
1118
1083
|
newChild = nextNew;
|
|
1119
1084
|
}
|
|
1120
1085
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1131,20 +1096,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1131
1096
|
oldChild = next;
|
|
1132
1097
|
}
|
|
1133
1098
|
}
|
|
1134
|
-
function
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
const
|
|
1139
|
-
if (
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1099
|
+
function flushGrafts(node, ranges) {
|
|
1100
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1101
|
+
let n = node.firstChild;
|
|
1102
|
+
while (n) {
|
|
1103
|
+
const id = slotStartId(n);
|
|
1104
|
+
if (id !== null) {
|
|
1105
|
+
const next = afterRange(n, id);
|
|
1106
|
+
const displaced = ranges.get(id);
|
|
1107
|
+
if (displaced) {
|
|
1108
|
+
ranges.delete(id);
|
|
1109
|
+
placeRange(node, displaced, id, n);
|
|
1110
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1111
|
+
}
|
|
1112
|
+
n = next;
|
|
1113
|
+
continue;
|
|
1146
1114
|
}
|
|
1147
|
-
|
|
1115
|
+
flushGrafts(n, ranges);
|
|
1116
|
+
n = n.nextSibling;
|
|
1148
1117
|
}
|
|
1149
1118
|
}
|
|
1150
1119
|
function stashRange(frag, start, id) {
|
|
@@ -1176,7 +1145,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1176
1145
|
if (chunk.type === "outcome") {
|
|
1177
1146
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1178
1147
|
} else {
|
|
1179
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1148
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1180
1149
|
if (perFrame) {
|
|
1181
1150
|
let v = perFrame.get(chunk.id);
|
|
1182
1151
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1190,7 +1159,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1190
1159
|
}
|
|
1191
1160
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1192
1161
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1193
|
-
const
|
|
1162
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1194
1163
|
let resolveServerComponent;
|
|
1195
1164
|
function parseServerComponent(value, ctx) {
|
|
1196
1165
|
return {
|
|
@@ -1214,7 +1183,8 @@ const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
|
1214
1183
|
stream: parseServerComponent
|
|
1215
1184
|
},
|
|
1216
1185
|
serialize(node, ctx) {
|
|
1217
|
-
|
|
1186
|
+
const registry = "self._$SC";
|
|
1187
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1218
1188
|
},
|
|
1219
1189
|
deserialize(node, ctx) {
|
|
1220
1190
|
const id = ctx.deserialize(node.id);
|
|
@@ -1239,120 +1209,79 @@ function createServerComponentHandler({
|
|
|
1239
1209
|
host,
|
|
1240
1210
|
component,
|
|
1241
1211
|
onStream,
|
|
1242
|
-
documentComponent,
|
|
1243
1212
|
intercept,
|
|
1244
1213
|
consumer = getFlightDataConsumer,
|
|
1245
1214
|
codec = getServerFunctionsCodec
|
|
1246
1215
|
}) {
|
|
1247
|
-
const
|
|
1248
|
-
const
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1252
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1253
|
-
fnId,
|
|
1254
|
-
frameId,
|
|
1255
|
-
take(prev) {
|
|
1256
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1257
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1258
|
-
const root = meta.frameId;
|
|
1259
|
-
let cur = forwards.get(root) ?? root;
|
|
1260
|
-
if (cur !== root && !host.get(cur)) {
|
|
1261
|
-
forwards.delete(root);
|
|
1262
|
-
cur = root;
|
|
1263
|
-
}
|
|
1264
|
-
if (cur === frameId) return true;
|
|
1265
|
-
let frame = host.get(cur);
|
|
1266
|
-
if (!frame) return false;
|
|
1267
|
-
while (frame) {
|
|
1268
|
-
frame.rebind(frameId);
|
|
1269
|
-
frame = host.get(cur);
|
|
1270
|
-
}
|
|
1271
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1272
|
-
return true;
|
|
1273
|
-
}
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1216
|
+
const byFn = new Map();
|
|
1217
|
+
const componentFor = fnId => {
|
|
1218
|
+
let comp = byFn.get(fnId);
|
|
1219
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1276
1220
|
return comp;
|
|
1277
1221
|
};
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1222
|
+
const byAddress = new Map();
|
|
1223
|
+
const bindingFor = (address, fnId) => {
|
|
1224
|
+
let binding = byAddress.get(address);
|
|
1225
|
+
if (!binding) {
|
|
1226
|
+
const comp = componentFor(fnId);
|
|
1227
|
+
binding = props => comp(props, () => address);
|
|
1228
|
+
binding[COMPONENT_BINDING] = {
|
|
1229
|
+
component: comp,
|
|
1230
|
+
address
|
|
1284
1231
|
};
|
|
1285
|
-
byAddress.set(address,
|
|
1232
|
+
byAddress.set(address, binding);
|
|
1286
1233
|
}
|
|
1287
|
-
return
|
|
1234
|
+
return binding;
|
|
1288
1235
|
};
|
|
1289
|
-
|
|
1290
|
-
resolveServerComponent = resolveAddress;
|
|
1236
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1291
1237
|
const versions = new Map();
|
|
1292
|
-
const bump =
|
|
1293
|
-
const version = (versions.get(
|
|
1294
|
-
versions.set(
|
|
1238
|
+
const bump = address => {
|
|
1239
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1240
|
+
versions.set(address, version);
|
|
1295
1241
|
return version;
|
|
1296
1242
|
};
|
|
1297
1243
|
return {
|
|
1298
1244
|
intercept: intercept && (info => {
|
|
1299
1245
|
const hit = intercept(info);
|
|
1300
|
-
if (hit
|
|
1301
|
-
|
|
1302
|
-
byAddress.set(address, {
|
|
1303
|
-
frameId: info.id,
|
|
1304
|
-
component: brand(hit, info.id, info.id)
|
|
1305
|
-
});
|
|
1306
|
-
}
|
|
1307
|
-
return hit;
|
|
1246
|
+
if (hit === undefined) return undefined;
|
|
1247
|
+
return bindingFor(frameAddress(info.id, info.args), info.id);
|
|
1308
1248
|
}),
|
|
1309
1249
|
handle(response, ctx) {
|
|
1310
1250
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1311
1251
|
const address = frameAddress(ctx.id, ctx.args);
|
|
1312
|
-
|
|
1313
|
-
if (!entry) {
|
|
1314
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1315
|
-
if (adopted) {
|
|
1316
|
-
entry = {
|
|
1317
|
-
frameId: ctx.id,
|
|
1318
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1319
|
-
};
|
|
1320
|
-
byAddress.set(address, entry);
|
|
1321
|
-
} else {
|
|
1322
|
-
entry = boundaryFor(address, ctx.id);
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1252
|
+
const binding = bindingFor(address, ctx.id);
|
|
1325
1253
|
if (response.headers.has(SINGLE_FLIGHT_HEADER)) {
|
|
1326
|
-
return applyFlightResponse(response,
|
|
1254
|
+
return applyFlightResponse(response, address, binding);
|
|
1327
1255
|
}
|
|
1328
|
-
const version = bump(
|
|
1329
|
-
if (onStream) onStream(
|
|
1256
|
+
const version = bump(address);
|
|
1257
|
+
if (onStream) onStream(address, version, response);
|
|
1330
1258
|
applyFrameResponse(response, host, {
|
|
1331
|
-
as:
|
|
1259
|
+
as: address,
|
|
1332
1260
|
version
|
|
1333
1261
|
}).catch(err => host.apply({
|
|
1334
1262
|
type: "error",
|
|
1335
|
-
id:
|
|
1263
|
+
id: address,
|
|
1336
1264
|
version,
|
|
1337
1265
|
error: {
|
|
1338
1266
|
message: String(err && err.message)
|
|
1339
1267
|
}
|
|
1340
1268
|
}));
|
|
1341
|
-
return
|
|
1269
|
+
return binding;
|
|
1342
1270
|
},
|
|
1343
|
-
showing(address, functionId
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1271
|
+
showing(address, functionId) {
|
|
1272
|
+
bindingFor(address, functionId);
|
|
1273
|
+
const comp = componentFor(functionId);
|
|
1274
|
+
if ((typeof comp === "function" || typeof comp === "object" && comp !== null) && !comp[COMPONENT_BINDING]) {
|
|
1275
|
+
comp[COMPONENT_BINDING] = {
|
|
1276
|
+
component: comp,
|
|
1348
1277
|
address
|
|
1349
|
-
}
|
|
1278
|
+
};
|
|
1350
1279
|
}
|
|
1351
1280
|
}
|
|
1352
1281
|
};
|
|
1353
|
-
async function applyFlightResponse(response,
|
|
1282
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1354
1283
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1355
|
-
const as = rootId ?
|
|
1284
|
+
const as = rootId ? address : undefined;
|
|
1356
1285
|
let feed;
|
|
1357
1286
|
const source = new ReadableStream({
|
|
1358
1287
|
start(controller) {
|
|
@@ -1363,10 +1292,6 @@ function createServerComponentHandler({
|
|
|
1363
1292
|
let carried = false;
|
|
1364
1293
|
await applyFrameResponse(response, host, {
|
|
1365
1294
|
as,
|
|
1366
|
-
route: id => {
|
|
1367
|
-
const local = byAddress.get(id);
|
|
1368
|
-
return local ? local.frameId : id;
|
|
1369
|
-
},
|
|
1370
1295
|
version: frameId => {
|
|
1371
1296
|
const version = bump(frameId);
|
|
1372
1297
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1387,7 +1312,7 @@ function createServerComponentHandler({
|
|
|
1387
1312
|
if (response.headers.has(ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(REVALIDATE_HEADER)) {
|
|
1388
1313
|
throw envelope.value;
|
|
1389
1314
|
}
|
|
1390
|
-
return rootId ?
|
|
1315
|
+
return rootId ? binding : envelope.value;
|
|
1391
1316
|
}
|
|
1392
1317
|
}
|
|
1393
1318
|
|
|
@@ -1566,15 +1491,7 @@ function slotsFor(props) {
|
|
|
1566
1491
|
return settle(normalizeSlotContent(value));
|
|
1567
1492
|
}
|
|
1568
1493
|
if (ctx && ctx.range) {
|
|
1569
|
-
let claim = adopted;
|
|
1570
1494
|
const source = value;
|
|
1571
|
-
const accessor = () => {
|
|
1572
|
-
if (claim) {
|
|
1573
|
-
claim = false;
|
|
1574
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1575
|
-
}
|
|
1576
|
-
return typeof source === "function" ? source() : source;
|
|
1577
|
-
};
|
|
1578
1495
|
const owner = createOwner();
|
|
1579
1496
|
bindings.set(key, owner);
|
|
1580
1497
|
ctx.onCleanup(() => {
|
|
@@ -1582,7 +1499,8 @@ function slotsFor(props) {
|
|
|
1582
1499
|
owner.dispose();
|
|
1583
1500
|
});
|
|
1584
1501
|
const end = ctx.range.end;
|
|
1585
|
-
|
|
1502
|
+
const bind = () => insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1503
|
+
runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1586
1504
|
return undefined;
|
|
1587
1505
|
}
|
|
1588
1506
|
return settle(normalizeSlotContent(value));
|
|
@@ -1596,19 +1514,24 @@ function revealSeam(owner) {
|
|
|
1596
1514
|
function boundaryScope(owner) {
|
|
1597
1515
|
return fn => getOwner() ? fn() : runWithOwner(owner, fn);
|
|
1598
1516
|
}
|
|
1599
|
-
function
|
|
1600
|
-
|
|
1517
|
+
function followBinding(frame, binding) {
|
|
1518
|
+
createRenderEffect(binding, address => frame.rebind(address));
|
|
1519
|
+
}
|
|
1520
|
+
function boundaryComponent(host, fnId) {
|
|
1521
|
+
return (props, binding) => {
|
|
1601
1522
|
const owner = getOwner();
|
|
1602
1523
|
const {
|
|
1603
1524
|
element,
|
|
1525
|
+
frame,
|
|
1604
1526
|
dispose
|
|
1605
1527
|
} = createFrameElement({
|
|
1606
1528
|
host,
|
|
1607
|
-
id,
|
|
1529
|
+
id: binding ? binding() : fnId,
|
|
1608
1530
|
slots: slotsFor(props),
|
|
1609
1531
|
ownerScope: boundaryScope(owner),
|
|
1610
1532
|
reveal: revealSeam(owner)
|
|
1611
1533
|
});
|
|
1534
|
+
if (binding) followBinding(frame, binding);
|
|
1612
1535
|
onCleanup(dispose);
|
|
1613
1536
|
return element;
|
|
1614
1537
|
};
|
|
@@ -1630,51 +1553,65 @@ function findBoundaryElement(id) {
|
|
|
1630
1553
|
return boundaryIndex.get(id);
|
|
1631
1554
|
}
|
|
1632
1555
|
const boundaryWaiters = new Map();
|
|
1633
|
-
function
|
|
1556
|
+
function boundaryMayArrive() {
|
|
1634
1557
|
const hy = globalThis._$HY;
|
|
1635
|
-
|
|
1558
|
+
if (!hy) return false;
|
|
1559
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1636
1560
|
}
|
|
1637
1561
|
function installRevealHook() {
|
|
1638
1562
|
const hy = globalThis._$HY;
|
|
1639
|
-
if (!hy || hy.$sc) return;
|
|
1563
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1640
1564
|
hy.$sc = true;
|
|
1641
|
-
|
|
1642
|
-
hy.fe = (fragmentId, parent) => {
|
|
1643
|
-
if (prev) prev(fragmentId, parent);
|
|
1565
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1644
1566
|
if (!boundaryIndex) return;
|
|
1645
1567
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1646
|
-
if (
|
|
1647
|
-
|
|
1568
|
+
if (root) indexBoundaries(root);
|
|
1569
|
+
if (!boundaryWaiters.size) return;
|
|
1570
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1648
1571
|
for (const [id, notify] of boundaryWaiters) {
|
|
1649
|
-
const el = boundaryIndex.get(id);
|
|
1650
|
-
if (!el) continue;
|
|
1572
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1573
|
+
if (!el && !exhausted) continue;
|
|
1651
1574
|
boundaryWaiters.delete(id);
|
|
1652
1575
|
notify(el);
|
|
1653
1576
|
}
|
|
1654
|
-
};
|
|
1577
|
+
});
|
|
1655
1578
|
}
|
|
1656
|
-
function documentBoundary(host, id, props) {
|
|
1579
|
+
function documentBoundary(host, id, props, binding) {
|
|
1580
|
+
installRevealHook();
|
|
1657
1581
|
const claimed = claimedBoundaries.has(id);
|
|
1658
1582
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1659
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1660
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1583
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1584
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1661
1585
|
const owner = getOwner();
|
|
1662
1586
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1663
1587
|
onCleanup(() => boundaryWaiters.delete(id));
|
|
1664
|
-
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1588
|
+
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1589
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1590
|
+
}
|
|
1591
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1592
|
+
}
|
|
1593
|
+
function documentAddress(id) {
|
|
1594
|
+
const records = globalThis._$SC?.a;
|
|
1595
|
+
if (records) {
|
|
1596
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1665
1597
|
}
|
|
1666
|
-
return
|
|
1598
|
+
return id;
|
|
1667
1599
|
}
|
|
1668
|
-
function adoptBoundary(host, id, el, props) {
|
|
1600
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1669
1601
|
claimedBoundaries.add(id);
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1602
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1603
|
+
const appliedRecords = new Set();
|
|
1604
|
+
const drainRecords = () => {
|
|
1605
|
+
const hy = globalThis._$HY;
|
|
1606
|
+
if (!hy || !hy.r) return;
|
|
1672
1607
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1673
1608
|
for (const key of Object.keys(hy.r)) {
|
|
1609
|
+
if (appliedRecords.has(key)) continue;
|
|
1674
1610
|
if (key.startsWith(slotPrefix)) {
|
|
1611
|
+
appliedRecords.add(key);
|
|
1675
1612
|
host.apply({
|
|
1676
1613
|
type: "slot",
|
|
1677
|
-
id,
|
|
1614
|
+
id: address,
|
|
1678
1615
|
version: 0,
|
|
1679
1616
|
key: key.slice(slotPrefix.length),
|
|
1680
1617
|
args: hy.r[key]
|
|
@@ -1682,6 +1619,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1682
1619
|
} else if (key.startsWith("sc:region:")) {
|
|
1683
1620
|
const childId = key.slice("sc:region:".length);
|
|
1684
1621
|
if (childId.startsWith(id + ".")) {
|
|
1622
|
+
appliedRecords.add(key);
|
|
1685
1623
|
const val = hy.r[key];
|
|
1686
1624
|
const apply = html => host.apply({
|
|
1687
1625
|
type: "html",
|
|
@@ -1693,16 +1631,27 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1693
1631
|
}
|
|
1694
1632
|
}
|
|
1695
1633
|
}
|
|
1696
|
-
}
|
|
1634
|
+
};
|
|
1635
|
+
drainRecords();
|
|
1697
1636
|
const owner = getOwner();
|
|
1698
1637
|
const frame = createFrame(el, {
|
|
1699
1638
|
adopt: true,
|
|
1700
1639
|
host,
|
|
1701
|
-
id,
|
|
1640
|
+
id: address,
|
|
1702
1641
|
slots: slotsFor(props),
|
|
1703
1642
|
ownerScope: boundaryScope(owner),
|
|
1704
|
-
reveal: revealSeam(owner)
|
|
1643
|
+
reveal: revealSeam(owner),
|
|
1644
|
+
...{
|
|
1645
|
+
recordsPending: () => {
|
|
1646
|
+
if (document.readyState === "loading") return true;
|
|
1647
|
+
const hy = globalThis._$HY;
|
|
1648
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1649
|
+
},
|
|
1650
|
+
drainRecords,
|
|
1651
|
+
claimScope: id
|
|
1652
|
+
}
|
|
1705
1653
|
});
|
|
1654
|
+
if (binding) followBinding(frame, binding);
|
|
1706
1655
|
onCleanup(() => frame.dispose());
|
|
1707
1656
|
return el;
|
|
1708
1657
|
}
|
|
@@ -1717,17 +1666,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1717
1666
|
g._$SC.a[a] = i;
|
|
1718
1667
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1719
1668
|
}
|
|
1720
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1669
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1721
1670
|
}
|
|
1722
1671
|
};
|
|
1723
1672
|
}
|
|
1724
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1673
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1725
1674
|
installRevealHook();
|
|
1726
1675
|
const handler = createServerComponentHandler({
|
|
1727
1676
|
host,
|
|
1728
|
-
component:
|
|
1729
|
-
onStream:
|
|
1730
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1677
|
+
component: fnId => g._$SC.r(fnId),
|
|
1678
|
+
onStream: address => beginStream(address),
|
|
1731
1679
|
intercept: ({
|
|
1732
1680
|
id
|
|
1733
1681
|
}) => {
|
|
@@ -1735,7 +1683,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1735
1683
|
return g._$SC.r(id);
|
|
1736
1684
|
}
|
|
1737
1685
|
});
|
|
1738
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1686
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1739
1687
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1740
1688
|
for (const address in records) showing(address, records[address]);
|
|
1741
1689
|
g._$SC.reg = showing;
|