@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.
@@ -83,98 +83,75 @@ function chunkToRecords(chunk) {
83
83
  }
84
84
  function createFrameHost(options = {}) {
85
85
  const frames = new Map();
86
- const pending = new Map();
87
- const retained = new Map();
88
- const deliver = (frame, chunk) => {
89
- if (chunk.type === "data") {
90
- options.applyData && options.applyData(chunk);
91
- return;
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
- if (sibling) {
111
+ const store = stores.get(id);
112
+ if (store && store.version !== undefined) {
105
113
  frame.apply({
106
- version: sibling.version ?? 0,
107
- r: sibling.store
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
- pending.delete(id);
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 && set.size) {
161
- for (const frame of set) deliver(frame, chunk);
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
- chunks: [chunk]
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) delete this.#store[key];else this.#options.removeSlotRecord?.(occurrence);
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, prefix);
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 < ka.length) return false;
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
- snapshot() {
615
- if (this.#disposed) return null;
616
- const records = {
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
- reconcileChildren(parent, fragment, this.#start, this.#end, claim, ranges);
687
- if (ranges.size) restoreDisplacedRanges(this.#firstContent(), this.#end, ranges);
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, prefix) {
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.startsWith(prefix)) {
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, prefix);
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
- if (existing.nodeType === 11 ) {
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 restoreDisplacedRanges(first, end, ranges) {
1137
- const found = new Map();
1138
- collectSlots(first, end, found);
1139
- for (const [id, start] of found) {
1140
- const displaced = ranges.get(id);
1141
- if (!displaced || displaced === start) continue;
1142
- ranges.delete(id);
1143
- const parent = start.parentNode;
1144
- if (displaced.nodeType === 11 ) {
1145
- parent.insertBefore(displaced, start);
1146
- } else {
1147
- moveRangeBefore(parent, displaced, id, start);
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
- stashRange(document.createDocumentFragment(), start, id);
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;else if (options.route) chunk.id = options.route(chunk.id);
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 COMPONENT_HANDOFF = /*#__PURE__*/Symbol.for("dom-expressions.component-handoff");
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
- return "self._$SC.r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
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 byAddress = new Map();
1250
- const forwards = new Map();
1251
- const brand = (comp, fnId, frameId) => {
1252
- const brandable = typeof comp === "function" || typeof comp === "object" && comp !== null;
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 boundaryFor = (address, fnId) => {
1281
- let entry = byAddress.get(address);
1282
- if (!entry) {
1283
- entry = {
1284
- frameId: address,
1285
- component: brand(component(address), fnId, address)
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, entry);
1234
+ byAddress.set(address, binding);
1288
1235
  }
1289
- return entry;
1236
+ return binding;
1290
1237
  };
1291
- const resolveAddress = (id, address) => boundaryFor(address, id).component;
1292
- resolveServerComponent = resolveAddress;
1238
+ resolveServerComponent = (id, address) => bindingFor(address, id);
1293
1239
  const versions = new Map();
1294
- const bump = frameId => {
1295
- const version = (versions.get(frameId) || 0) + 1;
1296
- versions.set(frameId, version);
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 !== undefined) {
1303
- const address = client.frameAddress(info.id, info.args);
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
- let entry = byAddress.get(address);
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, entry);
1256
+ return applyFlightResponse(response, address, binding);
1329
1257
  }
1330
- const version = bump(entry.frameId);
1331
- if (onStream) onStream(entry.frameId, version, response);
1258
+ const version = bump(address);
1259
+ if (onStream) onStream(address, version, response);
1332
1260
  applyFrameResponse(response, host, {
1333
- as: entry.frameId,
1261
+ as: address,
1334
1262
  version
1335
1263
  }).catch(err => host.apply({
1336
1264
  type: "error",
1337
- id: entry.frameId,
1265
+ id: address,
1338
1266
  version,
1339
1267
  error: {
1340
1268
  message: String(err && err.message)
1341
1269
  }
1342
1270
  }));
1343
- return entry.component;
1271
+ return binding;
1344
1272
  },
1345
- showing(address, functionId, component) {
1346
- if (!byAddress.has(address)) {
1347
- byAddress.set(address, {
1348
- frameId: functionId,
1349
- component: brand(component, functionId, functionId),
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, entry) {
1284
+ async function applyFlightResponse(response, address, binding) {
1356
1285
  const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
1357
- const as = rootId ? entry.frameId : undefined;
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 ? entry.component : envelope.value;
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
- solidJs.runWithOwner(owner, () => web$1.insert(end.parentNode, accessor, end, [...ctx.existing]));
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 boundaryComponent(host, id) {
1602
- return props => {
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 documentStreaming() {
1558
+ function boundaryMayArrive() {
1636
1559
  const hy = globalThis._$HY;
1637
- return !!hy && !hy.done;
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
- const prev = hy.fe;
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 (!root) return;
1649
- indexBoundaries(root);
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) && documentStreaming()) {
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, () => adoptBoundary(host, id, node, props))));
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 boundaryComponent(host, id)(props);
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 hy = globalThis._$HY;
1673
- if (hy && hy.r) {
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: frameId => boundaryComponent(host, frameId),
1731
- onStream: frameId => beginStream(frameId),
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, g._$SC.r(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;