@solidjs/web 2.0.0-beta.25 → 2.0.0-beta.27

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.
Files changed (43) hide show
  1. package/dist/dev.cjs +14 -9
  2. package/dist/dev.js +14 -10
  3. package/dist/server.cjs +41 -78
  4. package/dist/server.js +42 -80
  5. package/dist/web.cjs +14 -9
  6. package/dist/web.js +14 -10
  7. package/frames/dist/client.cjs +180 -224
  8. package/frames/dist/client.dev.cjs +1456 -0
  9. package/frames/dist/client.dev.js +1444 -0
  10. package/frames/dist/client.js +181 -225
  11. package/frames/dist/server.cjs +139 -123
  12. package/frames/dist/server.js +139 -123
  13. package/package.json +24 -4
  14. package/serialization/dist/serialization.cjs +6 -3
  15. package/serialization/dist/serialization.js +6 -3
  16. package/serialization/types/index.d.ts +7 -1
  17. package/serialization/types-cjs/index.d.cts +7 -1
  18. package/server-functions/dist/client.cjs +18 -5
  19. package/server-functions/dist/client.js +16 -6
  20. package/server-functions/dist/server.cjs +164 -8
  21. package/server-functions/dist/server.js +158 -9
  22. package/types/client.d.ts +3 -3
  23. package/types/frames/client.d.ts +1 -1
  24. package/types/frames/frame-client.d.ts +34 -28
  25. package/types/frames/serializer.d.ts +7 -1
  26. package/types/jsx.d.ts +1 -1
  27. package/types/response.d.ts +10 -0
  28. package/types/serializer.d.ts +7 -1
  29. package/types/server-functions/client.d.ts +3 -0
  30. package/types/server-functions/flash.d.ts +38 -0
  31. package/types/server-functions/server.d.ts +79 -4
  32. package/types/server-functions/shared.d.ts +35 -0
  33. package/types-cjs/client.d.cts +3 -3
  34. package/types-cjs/frames/client.d.cts +1 -1
  35. package/types-cjs/frames/frame-client.d.cts +34 -28
  36. package/types-cjs/frames/serializer.d.cts +7 -1
  37. package/types-cjs/jsx.d.cts +1 -1
  38. package/types-cjs/response.d.cts +10 -0
  39. package/types-cjs/serializer.d.cts +7 -1
  40. package/types-cjs/server-functions/client.d.cts +3 -0
  41. package/types-cjs/server-functions/flash.d.cts +38 -0
  42. package/types-cjs/server-functions/server.d.cts +79 -4
  43. package/types-cjs/server-functions/shared.d.cts +35 -0
@@ -0,0 +1,1444 @@
1
+ import { getOwner, onCleanup, createMemo, runWithOwner, createLoadingBoundary, sharedConfig, createOwner } from 'solid-js';
2
+ import { insert } from '@solidjs/web';
3
+ import { configureServerFunctionsClient } from '@solidjs/web/server-functions/client';
4
+ import { fromCrossJSON, Feature } from 'seroval';
5
+ import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
6
+
7
+ const ELEMENT_NODE = 1;
8
+ const TEXT_NODE = 3;
9
+ const COMMENT_NODE = 8;
10
+ const CLAIM_SEAM = Symbol.for("dom-expressions.element-claims");
11
+ const CLAIMED_ELEMENTS = "a[href], form[action]";
12
+ function claimHandlers() {
13
+ const handlers = globalThis[CLAIM_SEAM];
14
+ return handlers !== undefined && handlers.length !== 0 ? handlers : undefined;
15
+ }
16
+ function claimNode(handlers, el) {
17
+ for (let i = 0; i < handlers.length; i++) handlers[i](el);
18
+ }
19
+ const claimedAttr = name => name === "href" || name === "action";
20
+ function claimTree(handlers, root) {
21
+ const isElement = root.nodeType === ELEMENT_NODE;
22
+ if (!isElement && root.nodeType !== 11 ) return;
23
+ if (isElement && root.matches(CLAIMED_ELEMENTS)) claimNode(handlers, root);
24
+ const found = root.querySelectorAll(CLAIMED_ELEMENTS);
25
+ for (let i = 0; i < found.length; i++) claimNode(handlers, found[i]);
26
+ }
27
+ const placeholderId = name => `pl-${name}`;
28
+ const SLOT_START = /^slot:(.+):start$/;
29
+ const SLOT_END = /^slot:(.+):end$/;
30
+ const slotEnd = id => `slot:${id}:end`;
31
+ function chunkToRecords(chunk) {
32
+ switch (chunk.type) {
33
+ case "start":
34
+ case "data":
35
+ return {};
36
+ case "html":
37
+ return {
38
+ "": {
39
+ kind: "html",
40
+ value: chunk.html
41
+ }
42
+ };
43
+ case "fragment":
44
+ return {
45
+ [`seg:${chunk.key}`]: {
46
+ kind: "html",
47
+ value: chunk.html
48
+ }
49
+ };
50
+ case "reveal":
51
+ {
52
+ const records = {};
53
+ const gate = chunk.fallback ? "fallback" : "reveal";
54
+ for (const key of chunk.keys) records[`seg:${key}:${gate}`] = true;
55
+ return records;
56
+ }
57
+ case "assets":
58
+ return {
59
+ [`seg:${chunk.key}:assets`]: chunk
60
+ };
61
+ case "slot":
62
+ return {
63
+ [`slot:${chunk.key}`]: {
64
+ kind: "slot",
65
+ args: chunk.args
66
+ }
67
+ };
68
+ case "complete":
69
+ return {
70
+ ":complete": true
71
+ };
72
+ case "error":
73
+ return chunk.key ? {
74
+ [`seg:${chunk.key}:error`]: chunk.error
75
+ } : {
76
+ ":error": chunk.error
77
+ };
78
+ default:
79
+ return {};
80
+ }
81
+ }
82
+ function createFrameHost(options = {}) {
83
+ const frames = new Map();
84
+ const pending = new Map();
85
+ const deliver = (frame, chunk) => {
86
+ if (chunk.type === "data") {
87
+ options.applyData && options.applyData(chunk);
88
+ return;
89
+ }
90
+ frame.apply({
91
+ version: chunk.version,
92
+ r: chunkToRecords(chunk)
93
+ });
94
+ };
95
+ return {
96
+ register(id, frame) {
97
+ let set = frames.get(id);
98
+ if (!set) frames.set(id, set = new Set());
99
+ const sibling = set.size ? set.values().next().value : undefined;
100
+ set.add(frame);
101
+ if (sibling) {
102
+ if (sibling.version !== undefined) {
103
+ frame.apply({
104
+ version: sibling.version,
105
+ r: sibling.store
106
+ });
107
+ }
108
+ return;
109
+ }
110
+ const buffered = pending.get(id);
111
+ if (buffered) {
112
+ pending.delete(id);
113
+ const records = {};
114
+ let version;
115
+ for (const chunk of buffered.chunks) {
116
+ if (chunk.type === "data") {
117
+ options.applyData && options.applyData(chunk);
118
+ continue;
119
+ }
120
+ version = chunk.version;
121
+ Object.assign(records, chunkToRecords(chunk));
122
+ }
123
+ if (version !== undefined) frame.apply({
124
+ version,
125
+ r: records
126
+ });
127
+ }
128
+ },
129
+ unregister(id, frame) {
130
+ const set = frames.get(id);
131
+ if (set && frame) set.delete(frame);
132
+ if (!set || !frame || !set.size) {
133
+ frames.delete(id);
134
+ pending.delete(id);
135
+ }
136
+ },
137
+ apply(chunk) {
138
+ if (chunk.type === "data") {
139
+ options.applyData && options.applyData(chunk);
140
+ return;
141
+ }
142
+ const set = frames.get(chunk.id);
143
+ if (set && set.size) {
144
+ for (const frame of set) deliver(frame, chunk);
145
+ return;
146
+ }
147
+ const buffered = pending.get(chunk.id);
148
+ if (!buffered) {
149
+ pending.set(chunk.id, {
150
+ version: chunk.version,
151
+ chunks: [chunk]
152
+ });
153
+ return;
154
+ }
155
+ if (chunk.version < buffered.version) return;
156
+ if (chunk.version > buffered.version) {
157
+ buffered.version = chunk.version;
158
+ buffered.chunks.length = 0;
159
+ }
160
+ buffered.chunks.push(chunk);
161
+ },
162
+ get(id) {
163
+ const set = frames.get(id);
164
+ return set && set.values().next().value;
165
+ },
166
+ serialize(value) {
167
+ if (!options.serialize) throw new Error("host has no serializer");
168
+ return options.serialize(value);
169
+ },
170
+ resolve(ref, frameId) {
171
+ return options.resolve ? options.resolve(ref, frameId) : undefined;
172
+ }
173
+ };
174
+ }
175
+ const FRAME_APPLIED_EVENT = "frame:applied";
176
+ class FrameImpl {
177
+ #element;
178
+ #start;
179
+ #end;
180
+ #options;
181
+ #version;
182
+ #store = Object.create(null);
183
+ #appliedRootValue;
184
+ #hasContent = false;
185
+ #revealed = new Set();
186
+ #fallbackShown = new Set();
187
+ #slots;
188
+ #mountedSlots = new Set();
189
+ #slotCleanups = new Map();
190
+ #slotArgs = new Map();
191
+ #slotRegions = new Map();
192
+ #slotResolvedRefs = new Map();
193
+ #slotNodes = new Map();
194
+ #processedAssets = new Set();
195
+ #disposed = false;
196
+ #styleFlush = () => {
197
+ if (!this.#disposed) this.#flush();
198
+ };
199
+ #claimTree = (node, direct) => {
200
+ const handlers = claimHandlers();
201
+ if (!handlers) return;
202
+ const run = () => direct ? claimNode(handlers, node) : claimTree(handlers, node);
203
+ const scope = this.#options.ownerScope;
204
+ scope ? scope(run) : run();
205
+ };
206
+ constructor(element, start, end, options = {}) {
207
+ this.#element = element;
208
+ this.#start = start;
209
+ this.#end = end;
210
+ this.#options = options;
211
+ this.#slots = options.slots;
212
+ if (options.adopt) {
213
+ this.#hasContent = true;
214
+ this.#claimContent();
215
+ }
216
+ if (options.host && options.id !== undefined) {
217
+ options.host.register(options.id, this);
218
+ }
219
+ if (options.adopt && this.#version === undefined) this.#syncSlots();
220
+ }
221
+ #parent() {
222
+ return this.#element ?? this.#start.parentNode;
223
+ }
224
+ #applied(version, reason) {
225
+ this.#options.onApply?.({
226
+ version,
227
+ reason
228
+ });
229
+ const parent = this.#parent();
230
+ const Ev = parent && (parent.ownerDocument || parent).defaultView?.CustomEvent;
231
+ if (Ev) {
232
+ parent.dispatchEvent(new Ev(FRAME_APPLIED_EVENT, {
233
+ bubbles: true,
234
+ detail: {
235
+ id: this.#options.id,
236
+ version,
237
+ reason
238
+ }
239
+ }));
240
+ }
241
+ }
242
+ #firstContent() {
243
+ return this.#start ? this.#start.nextSibling : this.#parent().firstChild;
244
+ }
245
+ get version() {
246
+ return this.#version;
247
+ }
248
+ get store() {
249
+ return this.#store;
250
+ }
251
+ isRevealed(segment) {
252
+ return this.#revealed.has(segment);
253
+ }
254
+ get error() {
255
+ return this.#store[":error"];
256
+ }
257
+ apply(write) {
258
+ if (this.#disposed) return;
259
+ const v = write.version;
260
+ if (this.#version === undefined) {
261
+ this.#version = v;
262
+ } else if (v < this.#version) {
263
+ return;
264
+ } else if (v > this.#version) {
265
+ this.#version = v;
266
+ this.#revealed.clear();
267
+ this.#fallbackShown.clear();
268
+ for (const key of Object.keys(this.#store)) {
269
+ if (key.startsWith("seg:") || key === ":error") {
270
+ delete this.#store[key];
271
+ }
272
+ }
273
+ }
274
+ for (const key of Object.keys(write.r)) {
275
+ const incoming = write.r[key];
276
+ if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
277
+ const existing = this.#store[key];
278
+ if (existing && existing.kind === "slot" && argsEquivalent(existing.args, incoming.args)) {
279
+ continue;
280
+ }
281
+ }
282
+ this.#store[key] = incoming;
283
+ }
284
+ this.#flush();
285
+ }
286
+ #flush() {
287
+ if (this.#disposed) return;
288
+ const version = this.#version;
289
+ const root = this.#store[""];
290
+ if (root && root.kind === "html" && root.value !== this.#appliedRootValue) {
291
+ const reason = this.#hasContent ? "morph" : "materialize";
292
+ this.#applyRoot(root.value);
293
+ this.#appliedRootValue = root.value;
294
+ this.#applied(version, reason);
295
+ }
296
+ let progressed = true;
297
+ while (progressed) {
298
+ progressed = false;
299
+ for (const key of Object.keys(this.#store)) {
300
+ const name = segmentName(key);
301
+ if (name === null || this.#revealed.has(name)) continue;
302
+ if (this.#segmentReady(name)) {
303
+ this.#revealSegment(name);
304
+ this.#applied(version, "reveal");
305
+ progressed = true;
306
+ }
307
+ }
308
+ for (const key of Object.keys(this.#store)) {
309
+ const m = /^seg:([^:]+):fallback$/.exec(key);
310
+ if (!m) continue;
311
+ const name = m[1];
312
+ if (this.#revealed.has(name) || this.#fallbackShown.has(name)) continue;
313
+ if (this.#showFallback(name)) {
314
+ this.#fallbackShown.add(name);
315
+ this.#applied(version, "reveal");
316
+ progressed = true;
317
+ }
318
+ }
319
+ }
320
+ for (const key of Object.keys(this.#store)) {
321
+ if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
322
+ this.#processedAssets.add(key);
323
+ const record = this.#store[key];
324
+ if (record && record.modules) {
325
+ for (const href of record.modules) ensureModulePreload(href);
326
+ }
327
+ }
328
+ this.#syncSlots();
329
+ }
330
+ #resolveSlot(prop) {
331
+ return this.#slots?.[prop] ?? this.#options.resolveSlot?.(prop);
332
+ }
333
+ #resolveSlotRecord(occurrence) {
334
+ const record = this.#store[`slot:${occurrence}`];
335
+ if (record !== undefined) return record;
336
+ return this.#options.resolveSlotRecord?.(occurrence);
337
+ }
338
+ #removeSlotRecord(occurrence) {
339
+ const key = `slot:${occurrence}`;
340
+ if (key in this.#store) delete this.#store[key];else this.#options.removeSlotRecord?.(occurrence);
341
+ }
342
+ #syncSlots(root) {
343
+ if (!this.#slots && !this.#options.resolveSlot) return;
344
+ const found = new Map();
345
+ if (root) collectSlots(root, found);else this.#collectSlots(found);
346
+ for (const [occurrence, start] of found) {
347
+ const callback = this.#resolveSlot(propOf(occurrence));
348
+ if (!callback) continue;
349
+ const record = this.#resolveSlotRecord(occurrence);
350
+ const prev = this.#slotNodes.get(occurrence);
351
+ const prevFirst = Array.isArray(prev) ? prev[0] : prev;
352
+ const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
353
+ if (zombie) {
354
+ this.#mountedSlots.delete(occurrence);
355
+ this.#runSlotCleanups(occurrence);
356
+ }
357
+ if (!this.#mountedSlots.has(occurrence)) {
358
+ if (this.#options.adopt) this.#discoverRegions(occurrence, start);
359
+ const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
360
+ if (nodes) this.#replaceRange(occurrence, start, nodes);
361
+ this.#slotNodes.set(occurrence, nodes);
362
+ this.#mountedSlots.add(occurrence);
363
+ if (!this.#options.adopt || nodes) this.#discoverRegions(occurrence, start);
364
+ this.#bindRegions(occurrence);
365
+ } else if (record !== this.#slotArgs.get(occurrence)) {
366
+ if (this.#refArgsUnchanged(occurrence, record)) {
367
+ this.#slotArgs.set(occurrence, record);
368
+ continue;
369
+ }
370
+ const nodes = this.#invokeSlot(occurrence, callback, record, start);
371
+ if (nodes) this.#replaceRange(occurrence, start, nodes);
372
+ this.#slotNodes.set(occurrence, nodes);
373
+ this.#bindRegions(occurrence);
374
+ }
375
+ }
376
+ if (!root) {
377
+ for (const occurrence of [...this.#mountedSlots]) {
378
+ if (!found.has(occurrence)) this.#unmountSlot(occurrence);
379
+ }
380
+ }
381
+ }
382
+ #invokeSlot(occurrence, callback, record, start, adopted) {
383
+ const cleanups = this.#slotCleanups.get(occurrence) ?? [];
384
+ const ctx = {
385
+ frame: this.#options.claimScope ?? this.#options.id,
386
+ key: occurrence,
387
+ adopted: !!adopted,
388
+ onCleanup: fn => cleanups.push(fn),
389
+ existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
390
+ };
391
+ const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
392
+ const regions = this.#slotRegions.get(occurrence);
393
+ if (regions) {
394
+ for (const entry of regions.values()) {
395
+ const argKey = entry.childId.slice(entry.childId.lastIndexOf(".") + 1);
396
+ if (!(argKey in props)) props[argKey] = entry.element;
397
+ }
398
+ }
399
+ const content = callback(props, ctx);
400
+ this.#slotArgs.set(occurrence, record);
401
+ if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
402
+ if (content == null) return null;
403
+ return Array.isArray(content) ? content : [content];
404
+ }
405
+ #replaceRange(key, start, nodes) {
406
+ const end = slotEnd(key);
407
+ const parent = start.parentNode;
408
+ let n = start.nextSibling;
409
+ while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
410
+ const next = n.nextSibling;
411
+ parent.removeChild(n);
412
+ n = next;
413
+ }
414
+ for (const node of nodes) parent.insertBefore(node, n);
415
+ }
416
+ #unmountSlot(key) {
417
+ this.#mountedSlots.delete(key);
418
+ this.#slotNodes.delete(key);
419
+ this.#slotArgs.delete(key);
420
+ this.#slotResolvedRefs.delete(key);
421
+ this.#removeSlotRecord(key);
422
+ this.#runSlotCleanups(key);
423
+ const regions = this.#slotRegions.get(key);
424
+ if (regions) {
425
+ for (const {
426
+ frame
427
+ } of regions.values()) frame?.dispose();
428
+ this.#slotRegions.delete(key);
429
+ }
430
+ this.#slotArgs.delete(key);
431
+ }
432
+ #runSlotCleanups(key) {
433
+ const cleanups = this.#slotCleanups.get(key);
434
+ if (!cleanups) return;
435
+ this.#slotCleanups.delete(key);
436
+ for (const fn of cleanups) fn();
437
+ }
438
+ #resolveArgs(slotKey, args) {
439
+ const host = this.#options.host;
440
+ let regions = this.#slotRegions.get(slotKey);
441
+ if (!regions) {
442
+ regions = new Map();
443
+ this.#slotRegions.set(slotKey, regions);
444
+ }
445
+ const props = {};
446
+ for (const key of Object.keys(args)) {
447
+ const value = args[key];
448
+ if (isDataRef(value)) {
449
+ const resolved = host ? host.resolve(value, this.#options.id) : undefined;
450
+ let cache = this.#slotResolvedRefs.get(slotKey);
451
+ if (!cache) this.#slotResolvedRefs.set(slotKey, cache = {});
452
+ cache[key] = resolved;
453
+ props[key] = resolved;
454
+ } else if (isFrameRef(value)) {
455
+ let entry = regions.get(value.$frame);
456
+ if (!entry) {
457
+ const element = makeFrameElement(value.$frame);
458
+ entry = {
459
+ childId: value.$frame,
460
+ element,
461
+ frame: undefined
462
+ };
463
+ regions.set(value.$frame, entry);
464
+ }
465
+ props[key] = entry.element;
466
+ } else {
467
+ props[key] = value;
468
+ }
469
+ }
470
+ return props;
471
+ }
472
+ #discoverRegions(slotKey, start) {
473
+ if (!start) return;
474
+ let regions = this.#slotRegions.get(slotKey);
475
+ if (!regions) {
476
+ regions = new Map();
477
+ this.#slotRegions.set(slotKey, regions);
478
+ }
479
+ const endData = slotEnd(slotKey);
480
+ let n = start.nextSibling;
481
+ while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
482
+ collectRegionElements(n, regions);
483
+ n = n.nextSibling;
484
+ }
485
+ }
486
+ #refArgsUnchanged(occurrence, record) {
487
+ const old = this.#slotArgs.get(occurrence);
488
+ if (!record || record.kind !== "slot") return false;
489
+ if (old && old.kind !== "slot") return false;
490
+ const a = old && old.args || {};
491
+ const b = record.args || {};
492
+ const ka = Object.keys(a);
493
+ const kb = Object.keys(b);
494
+ if (kb.length < ka.length) return false;
495
+ if (kb.length !== ka.length) {
496
+ const regions = this.#slotRegions.get(occurrence);
497
+ for (const key of kb) {
498
+ if (key in a) continue;
499
+ const vb = b[key];
500
+ if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
501
+ if (!regions || !regions.has(vb.$frame)) return false;
502
+ }
503
+ }
504
+ const cache = this.#slotResolvedRefs.get(occurrence);
505
+ for (const key of ka) {
506
+ const va = a[key];
507
+ const vb = b[key];
508
+ if (va === vb) continue;
509
+ if (!va || !vb || typeof va !== "object" || typeof vb !== "object") return false;
510
+ if (typeof va.$frame === "string" && va.$frame === vb.$frame) continue;
511
+ if (typeof va.$ref === "string" && typeof vb.$ref === "string" && cache && key in cache) {
512
+ const host = this.#options.host;
513
+ const next = host ? host.resolve(vb, this.#options.id) : undefined;
514
+ try {
515
+ if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
516
+ } catch (e) {
517
+ return false;
518
+ }
519
+ }
520
+ return false;
521
+ }
522
+ return true;
523
+ }
524
+ #bindRegions(slotKey) {
525
+ const regions = this.#slotRegions.get(slotKey);
526
+ if (!regions) return;
527
+ for (const entry of regions.values()) {
528
+ if (!entry.frame) {
529
+ entry.frame = new FrameImpl(entry.element, null, null, {
530
+ id: entry.childId,
531
+ host: this.#options.host,
532
+ adopt: entry.adopt,
533
+ claimScope: this.#options.claimScope ?? this.#options.id,
534
+ ownerScope: this.#options.ownerScope,
535
+ resolveSlot: prop => this.#resolveSlot(prop),
536
+ resolveSlotRecord: occurrence => this.#resolveSlotRecord(occurrence),
537
+ removeSlotRecord: occurrence => this.#removeSlotRecord(occurrence)
538
+ });
539
+ }
540
+ }
541
+ }
542
+ #collectSlots(found) {
543
+ let n = this.#firstContent();
544
+ const end = this.#end;
545
+ while (n && n !== end) {
546
+ const id = slotStartId(n);
547
+ if (id !== null) {
548
+ devCheckRange(n, id);
549
+ if (!found.has(id)) found.set(id, n);
550
+ n = afterRange(n, id);
551
+ continue;
552
+ }
553
+ if (n.nodeType === ELEMENT_NODE && !isFrameElement(n)) collectSlots(n, found);
554
+ n = n.nextSibling;
555
+ }
556
+ }
557
+ #findPlaceholder(name) {
558
+ const id = placeholderId(name);
559
+ let n = this.#firstContent();
560
+ const end = this.#end;
561
+ while (n && n !== end) {
562
+ if (isPlaceholderStart(n, id)) return n;
563
+ if (n.nodeType === ELEMENT_NODE) {
564
+ const found = findPlaceholder(n, id);
565
+ if (found) return found;
566
+ }
567
+ n = n.nextSibling;
568
+ }
569
+ return null;
570
+ }
571
+ dispose() {
572
+ if (this.#disposed) return;
573
+ this.#disposed = true;
574
+ for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
575
+ for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
576
+ for (const regions of this.#slotRegions.values()) {
577
+ for (const {
578
+ frame
579
+ } of regions.values()) frame?.dispose();
580
+ }
581
+ this.#slotRegions.clear();
582
+ this.#mountedSlots.clear();
583
+ const {
584
+ host,
585
+ id
586
+ } = this.#options;
587
+ if (host && id !== undefined) host.unregister(id, this);
588
+ }
589
+ #applyRoot(html) {
590
+ const fragment = parseFragment(html);
591
+ const parent = this.#parent();
592
+ if (!this.#hasContent) {
593
+ this.#clearContent();
594
+ this.#claimTree(fragment);
595
+ parent.insertBefore(fragment, this.#end);
596
+ this.#hasContent = true;
597
+ } else {
598
+ const claim = claimHandlers() ? this.#claimTree : null;
599
+ reconcileChildren(parent, fragment, this.#start, this.#end, claim);
600
+ }
601
+ }
602
+ #clearContent() {
603
+ const parent = this.#parent();
604
+ let n = this.#firstContent();
605
+ while (n && n !== this.#end) {
606
+ const next = n.nextSibling;
607
+ parent.removeChild(n);
608
+ n = next;
609
+ }
610
+ }
611
+ #claimContent() {
612
+ if (!claimHandlers()) return;
613
+ let n = this.#firstContent();
614
+ while (n && n !== this.#end) {
615
+ this.#claimTree(n);
616
+ n = n.nextSibling;
617
+ }
618
+ }
619
+ #segmentReady(name) {
620
+ const content = this.#store[`seg:${name}`];
621
+ if (!content || content.kind !== "html") return false;
622
+ if (!this.#store[`seg:${name}:reveal`]) return false;
623
+ const assets = this.#store[`seg:${name}:assets`];
624
+ if (assets && assets.styles) {
625
+ let ready = true;
626
+ for (const href of assets.styles) {
627
+ if (!ensureStylesheet(href, this.#styleFlush)) ready = false;
628
+ }
629
+ if (!ready) return false;
630
+ }
631
+ if (!this.#findPlaceholder(name)) return false;
632
+ return true;
633
+ }
634
+ #revealSegment(name) {
635
+ const tpl = this.#findPlaceholder(name);
636
+ if (!tpl) return;
637
+ const assets = this.#store[`seg:${name}:assets`];
638
+ if (assets && assets.inlineStyles) applyInlineStyles(assets.inlineStyles);
639
+ const content = this.#store[`seg:${name}`];
640
+ const closing = rangeClose(tpl, placeholderId(name));
641
+ if (!closing) {
642
+ console.error(`Frame fragment placeholder "${name}" is missing its closing comment ` + `(<!--${placeholderId(name)}-->); revealed content will be appended at the end of ` + `its parent instead of in place. Likely an HTML-rewriting layer stripped the ` + `comment, or invalid nesting split the placeholder range.`, tpl);
643
+ }
644
+ const parent = tpl.parentNode;
645
+ let n = tpl.nextSibling;
646
+ while (n && n !== closing) {
647
+ const next = n.nextSibling;
648
+ parent.removeChild(n);
649
+ n = next;
650
+ }
651
+ if (this.#options.reveal) {
652
+ const fallbackFrag = tpl.content.cloneNode(true);
653
+ this.#claimTree(fallbackFrag);
654
+ this.#options.reveal({
655
+ before: closing,
656
+ fallback: [...fallbackFrag.childNodes],
657
+ content: () => {
658
+ const materialized = this.#materialize(content);
659
+ this.#syncSlots(materialized);
660
+ this.#claimTree(materialized);
661
+ return materialized;
662
+ }
663
+ });
664
+ tpl.remove();
665
+ this.#revealed.add(name);
666
+ return;
667
+ }
668
+ const materialized = this.#materialize(content);
669
+ this.#claimTree(materialized);
670
+ parent.insertBefore(materialized, closing);
671
+ tpl.remove();
672
+ closing && closing.remove();
673
+ this.#revealed.add(name);
674
+ }
675
+ #showFallback(name) {
676
+ const tpl = this.#findPlaceholder(name);
677
+ if (!tpl) return false;
678
+ const closing = rangeClose(tpl, placeholderId(name));
679
+ if (!closing) return false;
680
+ const fallback = tpl.content.cloneNode(true);
681
+ this.#claimTree(fallback);
682
+ closing.parentNode.insertBefore(fallback, closing);
683
+ return true;
684
+ }
685
+ #materialize(record) {
686
+ return record.kind === "html" ? parseFragment(record.value) : parseFragment("");
687
+ }
688
+ }
689
+ function createFrame(boundary, options) {
690
+ return new FrameImpl(boundary, null, null, options);
691
+ }
692
+ const FRAME_TAG = "dx-frame";
693
+ const FRAME_ID_ATTR = "data-fid";
694
+ function createFrameElement(options) {
695
+ const el = makeFrameElement(options.id);
696
+ const frame = new FrameImpl(el, null, null, options);
697
+ return {
698
+ element: el,
699
+ get frame() {
700
+ return frame;
701
+ },
702
+ dispose() {
703
+ frame.dispose();
704
+ el.remove();
705
+ }
706
+ };
707
+ }
708
+ function makeFrameElement(id) {
709
+ const el = document.createElement(FRAME_TAG);
710
+ el.style.display = "contents";
711
+ if (id !== undefined) el.setAttribute(FRAME_ID_ATTR, id);
712
+ return el;
713
+ }
714
+ function isFrameElement(node) {
715
+ return node.nodeType === ELEMENT_NODE && node.hasAttribute(FRAME_ID_ATTR);
716
+ }
717
+ function segmentName(key) {
718
+ const m = /^seg:([^:]+)$/.exec(key);
719
+ return m ? m[1] : null;
720
+ }
721
+ function propOf(occurrence) {
722
+ const hash = occurrence.indexOf("#");
723
+ return hash === -1 ? occurrence : occurrence.slice(0, hash);
724
+ }
725
+ function isDataRef(value) {
726
+ return typeof value === "object" && value !== null && typeof value.$ref === "string";
727
+ }
728
+ function isFrameRef(value) {
729
+ return typeof value === "object" && value !== null && typeof value.$frame === "string";
730
+ }
731
+ function parseFragment(html) {
732
+ const template = document.createElement("template");
733
+ template.innerHTML = html;
734
+ return template.content;
735
+ }
736
+ function findHeadElement(selector, attr, value) {
737
+ const nodes = document.head.querySelectorAll(selector);
738
+ for (let i = 0; i < nodes.length; i++) {
739
+ if (nodes[i].getAttribute(attr) === value) return nodes[i];
740
+ }
741
+ return null;
742
+ }
743
+ function ensureStylesheet(href, onSettle) {
744
+ let link = findHeadElement('link[rel="stylesheet"]', "href", href);
745
+ if (!link) {
746
+ link = document.createElement("link");
747
+ link.rel = "stylesheet";
748
+ link.href = href;
749
+ const waiters = new Set();
750
+ link._$frWaiters = waiters;
751
+ const settle = () => {
752
+ link._$frWaiters = null;
753
+ for (const fn of waiters) fn();
754
+ };
755
+ link.addEventListener("load", settle);
756
+ link.addEventListener("error", settle);
757
+ document.head.appendChild(link);
758
+ }
759
+ const waiters = link._$frWaiters;
760
+ if (waiters == null) return true;
761
+ waiters.add(onSettle);
762
+ return false;
763
+ }
764
+ function ensureModulePreload(href) {
765
+ if (findHeadElement('link[rel="modulepreload"]', "href", href)) return;
766
+ const link = document.createElement("link");
767
+ link.rel = "modulepreload";
768
+ link.href = href;
769
+ document.head.appendChild(link);
770
+ }
771
+ function applyInlineStyles(inlineStyles) {
772
+ for (const entry of inlineStyles) {
773
+ if (findHeadElement("style[data-asset]", "data-asset", entry.id)) continue;
774
+ const el = document.createElement("style");
775
+ el.setAttribute("data-asset", entry.id);
776
+ if (entry.attrs) {
777
+ for (const name in entry.attrs) el.setAttribute(name, entry.attrs[name]);
778
+ }
779
+ el.textContent = entry.content || "";
780
+ document.head.appendChild(el);
781
+ }
782
+ }
783
+ function isPlaceholderStart(node, id) {
784
+ return node.nodeType === ELEMENT_NODE && node.tagName === "TEMPLATE" && node.getAttribute("id") === id;
785
+ }
786
+ function rangeClose(start, id) {
787
+ let n = start.nextSibling;
788
+ while (n) {
789
+ if (n.nodeType === COMMENT_NODE && n.data === id) return n;
790
+ n = n.nextSibling;
791
+ }
792
+ return null;
793
+ }
794
+ function findPlaceholder(root, id) {
795
+ let n = root.firstChild;
796
+ while (n) {
797
+ if (isPlaceholderStart(n, id)) return n;
798
+ if (n.nodeType === ELEMENT_NODE) {
799
+ const found = findPlaceholder(n, id);
800
+ if (found) return found;
801
+ }
802
+ n = n.nextSibling;
803
+ }
804
+ return null;
805
+ }
806
+ function collectSlots(root, out) {
807
+ let n = root.firstChild;
808
+ while (n) {
809
+ const id = slotStartId(n);
810
+ if (id !== null) {
811
+ devCheckRange(n, id);
812
+ if (!out.has(id)) out.set(id, n);
813
+ n = afterRange(n, id);
814
+ continue;
815
+ }
816
+ if (n.nodeType === ELEMENT_NODE && !isFrameElement(n)) collectSlots(n, out);
817
+ n = n.nextSibling;
818
+ }
819
+ }
820
+ function collectRegionElements(node, regions) {
821
+ if (node.nodeType !== ELEMENT_NODE) return;
822
+ if (isFrameElement(node)) {
823
+ const childId = node.getAttribute(FRAME_ID_ATTR);
824
+ if (childId && !regions.has(childId)) {
825
+ regions.set(childId, {
826
+ childId,
827
+ element: node,
828
+ frame: undefined,
829
+ adopt: true
830
+ });
831
+ }
832
+ return;
833
+ }
834
+ for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
835
+ }
836
+ function argsEquivalent(a, b) {
837
+ if (a === b) return true;
838
+ if (!a || !b) return false;
839
+ const ka = Object.keys(a);
840
+ const kb = Object.keys(b);
841
+ if (ka.length !== kb.length) return false;
842
+ for (const key of ka) {
843
+ const va = a[key];
844
+ const vb = b[key];
845
+ if (va === vb) continue;
846
+ if (va && vb && typeof va === "object" && typeof vb === "object" && typeof va.$frame === "string" && va.$frame === vb.$frame) {
847
+ continue;
848
+ }
849
+ return false;
850
+ }
851
+ return true;
852
+ }
853
+ function rangeInterior(start, endData) {
854
+ const nodes = [];
855
+ let n = start.nextSibling;
856
+ while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
857
+ nodes.push(n);
858
+ n = n.nextSibling;
859
+ }
860
+ return nodes;
861
+ }
862
+ function slotStartId(node) {
863
+ if (node.nodeType !== COMMENT_NODE) return null;
864
+ const m = SLOT_START.exec(node.data);
865
+ return m ? m[1] : null;
866
+ }
867
+ function isSlotMarker(node) {
868
+ if (node.nodeType !== COMMENT_NODE) return false;
869
+ const data = node.data;
870
+ return SLOT_START.test(data) || SLOT_END.test(data);
871
+ }
872
+ function compatible(a, b) {
873
+ if (a.nodeType !== b.nodeType) return false;
874
+ if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName;
875
+ return a.nodeType === TEXT_NODE || a.nodeType === COMMENT_NODE;
876
+ }
877
+ function preservesOpen(el) {
878
+ const t = el.tagName;
879
+ return t === "DETAILS" || t === "DIALOG";
880
+ }
881
+ function morphAttributes(oldEl, newEl, claim) {
882
+ let reclaim = false;
883
+ let changed = false;
884
+ const keepOpen = preservesOpen(oldEl);
885
+ const oldAttrs = oldEl.attributes;
886
+ for (let i = oldAttrs.length - 1; i >= 0; i--) {
887
+ const name = oldAttrs[i].name;
888
+ if (keepOpen && name === "open") continue;
889
+ if (!newEl.hasAttribute(name)) {
890
+ oldEl.removeAttribute(name);
891
+ changed = true;
892
+ reclaim ||= claimedAttr(name);
893
+ }
894
+ }
895
+ const newAttrs = newEl.attributes;
896
+ for (let i = 0; i < newAttrs.length; i++) {
897
+ const attr = newAttrs[i];
898
+ if (keepOpen && attr.name === "open") continue;
899
+ if (oldEl.getAttribute(attr.name) !== attr.value) {
900
+ oldEl.setAttribute(attr.name, attr.value);
901
+ changed = true;
902
+ reclaim ||= claimedAttr(attr.name);
903
+ }
904
+ }
905
+ if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
906
+ }
907
+ function morphNode(oldNode, newNode, claim) {
908
+ if (oldNode.nodeType === ELEMENT_NODE) {
909
+ if (oldNode.hasAttribute("data-preserve")) return;
910
+ morphAttributes(oldNode, newNode, claim);
911
+ reconcileChildren(oldNode, newNode, null, null, claim);
912
+ } else if (oldNode.data !== newNode.data) {
913
+ oldNode.data = newNode.data;
914
+ }
915
+ }
916
+ function afterRange(start, id) {
917
+ const end = slotEnd(id);
918
+ let n = start.nextSibling;
919
+ while (n) {
920
+ if (n.nodeType === COMMENT_NODE && n.data === end) return n.nextSibling;
921
+ n = n.nextSibling;
922
+ }
923
+ return null;
924
+ }
925
+ function devCheckRange(start, id) {
926
+ const end = slotEnd(id);
927
+ let n = start.nextSibling;
928
+ while (n) {
929
+ if (n.nodeType === COMMENT_NODE && n.data === end) return;
930
+ n = n.nextSibling;
931
+ }
932
+ console.error(`Frame slot range "${id}" is missing its end marker (<!--${end}-->) among its start ` + `marker's siblings. Slots after it in this content cannot be discovered. Likely causes: ` + `invalid HTML nesting split the range during parsing (e.g. a block element inside <p>), ` + `or an HTML-rewriting layer (CDN/minifier/translator) removed or moved the comment — ` + `serve frame documents with Cache-Control: no-transform.`, start);
933
+ }
934
+ function skipRange(start, id) {
935
+ return afterRange(start, id);
936
+ }
937
+ function findRangeStart(from, id, bound) {
938
+ const target = `slot:${id}:start`;
939
+ let n = from;
940
+ while (n && n !== bound) {
941
+ if (n.nodeType === COMMENT_NODE && n.data === target) return n;
942
+ n = n.nextSibling;
943
+ }
944
+ return null;
945
+ }
946
+ function moveRangeBefore(parent, start, id, ref) {
947
+ const end = slotEnd(id);
948
+ let n = start;
949
+ while (n) {
950
+ const next = n.nextSibling;
951
+ const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
952
+ parent.insertBefore(n, ref);
953
+ if (isEnd) break;
954
+ n = next;
955
+ }
956
+ }
957
+ function adoptRange(parent, start, id, ref, claim) {
958
+ const end = slotEnd(id);
959
+ let n = start;
960
+ let after = null;
961
+ while (n) {
962
+ const next = n.nextSibling;
963
+ const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
964
+ parent.insertBefore(n, ref);
965
+ if (claim) claim(n);
966
+ if (isEnd) {
967
+ after = next;
968
+ break;
969
+ }
970
+ n = next;
971
+ }
972
+ return after;
973
+ }
974
+ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null) {
975
+ let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
976
+ let newChild = source.firstChild;
977
+ while (newChild) {
978
+ const nextNew = newChild.nextSibling;
979
+ const pid = slotStartId(newChild);
980
+ const old = oldChild === boundEnd ? null : oldChild;
981
+ if (pid !== null) {
982
+ if (old && slotStartId(old) === pid) {
983
+ oldChild = afterRange(old, pid);
984
+ newChild = skipRange(newChild, pid);
985
+ } else {
986
+ const existing = findRangeStart(old, pid, boundEnd);
987
+ if (existing) {
988
+ moveRangeBefore(parent, existing, pid, old ?? boundEnd);
989
+ newChild = skipRange(newChild, pid);
990
+ } else {
991
+ newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
992
+ }
993
+ }
994
+ continue;
995
+ }
996
+ if (!old) {
997
+ parent.insertBefore(newChild, boundEnd);
998
+ if (claim) claim(newChild);
999
+ newChild = nextNew;
1000
+ continue;
1001
+ }
1002
+ if (isSlotMarker(old)) {
1003
+ parent.insertBefore(newChild, old);
1004
+ if (claim) claim(newChild);
1005
+ newChild = nextNew;
1006
+ continue;
1007
+ }
1008
+ if (compatible(old, newChild)) {
1009
+ morphNode(old, newChild, claim);
1010
+ oldChild = old.nextSibling;
1011
+ newChild = nextNew;
1012
+ continue;
1013
+ }
1014
+ if (newChild.nodeType === 1) {
1015
+ let ahead = old.nextSibling;
1016
+ while (ahead && ahead !== boundEnd && !compatible(ahead, newChild)) {
1017
+ const aheadPid = slotStartId(ahead);
1018
+ ahead = aheadPid !== null ? afterRange(ahead, aheadPid) : ahead.nextSibling;
1019
+ }
1020
+ if (ahead && ahead !== boundEnd) {
1021
+ parent.insertBefore(ahead, old);
1022
+ morphNode(ahead, newChild, claim);
1023
+ newChild = nextNew;
1024
+ continue;
1025
+ }
1026
+ }
1027
+ parent.insertBefore(newChild, old);
1028
+ if (claim) claim(newChild);
1029
+ newChild = nextNew;
1030
+ }
1031
+ while (oldChild && oldChild !== boundEnd) {
1032
+ const next = oldChild.nextSibling;
1033
+ parent.removeChild(oldChild);
1034
+ oldChild = next;
1035
+ }
1036
+ }
1037
+
1038
+ Feature.AggregateError | Feature.BigIntTypedArray;
1039
+ const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
1040
+ CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
1041
+ FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
1042
+ function resolveSerializerPlugins(customPlugins) {
1043
+ return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
1044
+ }
1045
+ const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
1046
+ const JSON_CODEC_DEPTH_LIMIT = 64;
1047
+ function resolveCodecOptions({
1048
+ plugins,
1049
+ disabledFeatures,
1050
+ depthLimit
1051
+ } = {}) {
1052
+ return {
1053
+ plugins: resolveSerializerPlugins(plugins),
1054
+ disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
1055
+ depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
1056
+ };
1057
+ }
1058
+ function createJSONDeserializer(options) {
1059
+ const refs = new Map();
1060
+ const resolved = resolveCodecOptions(options);
1061
+ return function deserializeJSONChunk(node) {
1062
+ return fromCrossJSON(node, {
1063
+ refs,
1064
+ ...resolved
1065
+ });
1066
+ };
1067
+ }
1068
+ function createJSONDataTable(options) {
1069
+ const deserialize = createJSONDeserializer(options);
1070
+ const table = new Map();
1071
+ return {
1072
+ apply(record) {
1073
+ const value = deserialize(record.node);
1074
+ if (record.initial) table.set(record.key, value);
1075
+ },
1076
+ get(key) {
1077
+ return table.get(key);
1078
+ },
1079
+ resolve(ref) {
1080
+ return table.get(ref.$ref);
1081
+ }
1082
+ };
1083
+ }
1084
+
1085
+ class ChunkReader {
1086
+ constructor(stream) {
1087
+ this.reader = stream.getReader();
1088
+ this.buffer = new Uint8Array(0);
1089
+ this.done = false;
1090
+ }
1091
+ async readChunk() {
1092
+ const chunk = await this.reader.read();
1093
+ if (!chunk.done) {
1094
+ const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
1095
+ newBuffer.set(this.buffer);
1096
+ newBuffer.set(chunk.value, this.buffer.length);
1097
+ this.buffer = newBuffer;
1098
+ } else {
1099
+ this.done = true;
1100
+ }
1101
+ }
1102
+ async next() {
1103
+ while (this.buffer.length < 12) {
1104
+ if (this.done) {
1105
+ if (this.buffer.length === 0) return {
1106
+ done: true,
1107
+ value: undefined
1108
+ };
1109
+ throw new Error("Malformed server function stream.");
1110
+ }
1111
+ await this.readChunk();
1112
+ }
1113
+ const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
1114
+ const bytes = Number.parseInt(head, 16);
1115
+ if (Number.isNaN(bytes)) {
1116
+ throw new Error("Malformed server function stream.");
1117
+ }
1118
+ while (bytes > this.buffer.length - 12) {
1119
+ if (this.done) {
1120
+ throw new Error("Malformed server function stream.");
1121
+ }
1122
+ await this.readChunk();
1123
+ }
1124
+ const partial = new TextDecoder().decode(this.buffer.subarray(12, 12 + bytes));
1125
+ this.buffer = this.buffer.subarray(12 + bytes);
1126
+ return {
1127
+ done: false,
1128
+ value: partial
1129
+ };
1130
+ }
1131
+ async drain(interpret) {
1132
+ while (true) {
1133
+ const result = await this.next();
1134
+ if (result.done) {
1135
+ break;
1136
+ }
1137
+ interpret(result.value);
1138
+ }
1139
+ }
1140
+ }
1141
+
1142
+ const FRAME_STREAM_HEADER = "X-Frame-Stream";
1143
+ function isFrameStreamResponse(response) {
1144
+ return response.headers.has(FRAME_STREAM_HEADER);
1145
+ }
1146
+ async function applyFrameResponse(response, host, options = {}) {
1147
+ const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
1148
+ const as = options.as;
1149
+ const version = options.version;
1150
+ const reader = new ChunkReader(response.body);
1151
+ let result = await reader.next();
1152
+ while (!result.done) {
1153
+ const chunk = JSON.parse(result.value);
1154
+ if (as !== undefined && chunk.id === rootId) chunk.id = as;
1155
+ if (version !== undefined) chunk.version = version;
1156
+ host.apply(chunk);
1157
+ result = await reader.next();
1158
+ }
1159
+ return as !== undefined ? as : rootId;
1160
+ }
1161
+ function createServerComponentHandler({
1162
+ host,
1163
+ component,
1164
+ capture,
1165
+ onStream,
1166
+ documentComponent,
1167
+ intercept
1168
+ }) {
1169
+ const byContext = new WeakMap();
1170
+ const byFunction = new Map();
1171
+ let boundary = 0;
1172
+ return {
1173
+ capture,
1174
+ intercept,
1175
+ handle(response, ctx) {
1176
+ if (!isFrameStreamResponse(response)) return undefined;
1177
+ const key = ctx.context;
1178
+ const keyed = key !== null && typeof key === "object";
1179
+ let entry = keyed ? byContext.get(key) : byFunction.get(ctx.id);
1180
+ if (!entry) {
1181
+ const adopted = documentComponent && documentComponent(ctx.id);
1182
+ if (adopted) {
1183
+ entry = {
1184
+ frameId: ctx.id,
1185
+ version: 0,
1186
+ component: adopted
1187
+ };
1188
+ } else {
1189
+ const frameId = `sc:${boundary++}`;
1190
+ entry = {
1191
+ frameId,
1192
+ version: 0,
1193
+ component: component(frameId)
1194
+ };
1195
+ }
1196
+ keyed ? byContext.set(key, entry) : byFunction.set(ctx.id, entry);
1197
+ }
1198
+ const version = ++entry.version;
1199
+ if (onStream) onStream(entry.frameId, version, response);
1200
+ applyFrameResponse(response, host, {
1201
+ as: entry.frameId,
1202
+ version
1203
+ }).catch(err => host.apply({
1204
+ type: "error",
1205
+ id: entry.frameId,
1206
+ version,
1207
+ error: {
1208
+ message: String(err && err.message)
1209
+ }
1210
+ }));
1211
+ return entry.component;
1212
+ }
1213
+ };
1214
+ }
1215
+
1216
+ let sharedHost;
1217
+ const tables = new Map();
1218
+ function tableFor(id) {
1219
+ const table = tables.get(id);
1220
+ if (table) return table;
1221
+ for (const [root, t] of tables) if (id.startsWith(root + ".")) return t;
1222
+ return undefined;
1223
+ }
1224
+ function beginStream(frameId) {
1225
+ tables.set(frameId, createJSONDataTable());
1226
+ }
1227
+ function getFrameHost() {
1228
+ if (!sharedHost) {
1229
+ sharedHost = createFrameHost({
1230
+ applyData: c => tableFor(c.id)?.apply(c),
1231
+ resolve: (ref, id) => tableFor(id)?.resolve(ref)
1232
+ });
1233
+ }
1234
+ return sharedHost;
1235
+ }
1236
+ function normalizeSlotContent(value) {
1237
+ while (typeof value === "function") value = value();
1238
+ if (Array.isArray(value)) {
1239
+ const out = [];
1240
+ for (const v of value) {
1241
+ const n = normalizeSlotContent(v);
1242
+ Array.isArray(n) ? out.push(...n) : out.push(n);
1243
+ }
1244
+ return out;
1245
+ }
1246
+ if (value == null || typeof value === "boolean") return document.createTextNode("");
1247
+ return value instanceof Node ? value : document.createTextNode(String(value));
1248
+ }
1249
+ function gatherClaims(el, registry) {
1250
+ if (el.hasAttribute("_hk")) registry.set(el.getAttribute("_hk"), el);
1251
+ if (el.hasAttribute(FRAME_ID_ATTR)) return;
1252
+ for (let c = el.firstElementChild; c; c = c.nextElementSibling) gatherClaims(c, registry);
1253
+ }
1254
+ function claimRender(prefix, existing, render) {
1255
+ const sc = sharedConfig;
1256
+ if (!sc.getNextContextId) return render();
1257
+ const registry = new Map();
1258
+ for (const n of existing) {
1259
+ if (n.nodeType !== 1) continue;
1260
+ gatherClaims(n, registry);
1261
+ }
1262
+ if (!registry.size) return render();
1263
+ const prevRegistry = sc.registry;
1264
+ const prevHydrating = sc.hydrating;
1265
+ sc.registry = registry;
1266
+ sc.hydrating = true;
1267
+ try {
1268
+ return runWithOwner(createOwner({
1269
+ id: prefix
1270
+ }), render);
1271
+ } finally {
1272
+ sc.registry = prevRegistry;
1273
+ sc.hydrating = prevHydrating;
1274
+ }
1275
+ }
1276
+ function slotsFor(props) {
1277
+ return new Proxy({}, {
1278
+ get(_, prop) {
1279
+ if (typeof prop !== "string" || !(prop in props)) return undefined;
1280
+ return (slotProps, ctx) => {
1281
+ const settle = out => {
1282
+ const existing = ctx && ctx.existing || [];
1283
+ if (existing.length) {
1284
+ const list = Array.isArray(out) ? out : [out];
1285
+ const inPlace = list.every(n => existing.some(e => e === n || e.nodeType === 1 && e.contains(n)));
1286
+ if (inPlace) return undefined;
1287
+ }
1288
+ return out;
1289
+ };
1290
+ const render = () => {
1291
+ const v = props[prop];
1292
+ return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
1293
+ };
1294
+ if (ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length) {
1295
+ return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
1296
+ }
1297
+ return render();
1298
+ };
1299
+ }
1300
+ });
1301
+ }
1302
+ function revealSeam(owner) {
1303
+ return seam => runWithOwner(owner, () => insert(seam.before.parentNode, createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
1304
+ }
1305
+ function boundaryComponent(host, id) {
1306
+ return props => {
1307
+ const owner = getOwner();
1308
+ const {
1309
+ element,
1310
+ dispose
1311
+ } = createFrameElement({
1312
+ host,
1313
+ id,
1314
+ slots: slotsFor(props),
1315
+ ownerScope: fn => runWithOwner(owner, fn),
1316
+ reveal: revealSeam(owner)
1317
+ });
1318
+ onCleanup(dispose);
1319
+ return element;
1320
+ };
1321
+ }
1322
+ const claimedBoundaries = new Set();
1323
+ let boundaryIndex = null;
1324
+ const isBoundaryId = id => !id.includes(".");
1325
+ function indexBoundaries(root) {
1326
+ root.querySelectorAll(`[${FRAME_ID_ATTR}]`).forEach(el => {
1327
+ const key = el.getAttribute(FRAME_ID_ATTR);
1328
+ if (key && isBoundaryId(key) && !boundaryIndex.has(key)) boundaryIndex.set(key, el);
1329
+ });
1330
+ }
1331
+ function findBoundaryElement(id) {
1332
+ if (!boundaryIndex) {
1333
+ boundaryIndex = new Map();
1334
+ if (typeof document !== "undefined" && document.body) indexBoundaries(document.body);
1335
+ }
1336
+ return boundaryIndex.get(id);
1337
+ }
1338
+ const boundaryWaiters = new Map();
1339
+ function documentStreaming() {
1340
+ const hy = globalThis._$HY;
1341
+ return !!hy && !hy.done;
1342
+ }
1343
+ function installRevealHook() {
1344
+ const hy = globalThis._$HY;
1345
+ if (!hy || hy.$sc) return;
1346
+ hy.$sc = true;
1347
+ const prev = hy.fe;
1348
+ hy.fe = (fragmentId, parent) => {
1349
+ if (prev) prev(fragmentId, parent);
1350
+ if (!boundaryIndex) return;
1351
+ const root = parent || (typeof document !== "undefined" ? document.body : null);
1352
+ if (!root) return;
1353
+ indexBoundaries(root);
1354
+ for (const [id, notify] of boundaryWaiters) {
1355
+ const el = boundaryIndex.get(id);
1356
+ if (!el) continue;
1357
+ boundaryWaiters.delete(id);
1358
+ notify(el);
1359
+ }
1360
+ };
1361
+ }
1362
+ function documentBoundary(host, id, props) {
1363
+ const claimed = claimedBoundaries.has(id);
1364
+ const el = !claimed ? findBoundaryElement(id) : undefined;
1365
+ if (el) return adoptBoundary(host, id, el, props);
1366
+ if (!claimed && !boundaryWaiters.has(id) && documentStreaming()) {
1367
+ const owner = getOwner();
1368
+ const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
1369
+ onCleanup(() => boundaryWaiters.delete(id));
1370
+ return createMemo(() => arrival.then(node => runWithOwner(owner, () => adoptBoundary(host, id, node, props))));
1371
+ }
1372
+ return boundaryComponent(host, id)(props);
1373
+ }
1374
+ function adoptBoundary(host, id, el, props) {
1375
+ claimedBoundaries.add(id);
1376
+ const hy = globalThis._$HY;
1377
+ if (hy && hy.r) {
1378
+ const slotPrefix = `sc:slot:${id}:`;
1379
+ for (const key of Object.keys(hy.r)) {
1380
+ if (key.startsWith(slotPrefix)) {
1381
+ host.apply({
1382
+ type: "slot",
1383
+ id,
1384
+ version: 0,
1385
+ key: key.slice(slotPrefix.length),
1386
+ args: hy.r[key]
1387
+ });
1388
+ } else if (key.startsWith("sc:region:")) {
1389
+ const childId = key.slice("sc:region:".length);
1390
+ if (childId.startsWith(id + ".")) {
1391
+ const val = hy.r[key];
1392
+ const apply = html => host.apply({
1393
+ type: "html",
1394
+ id: childId,
1395
+ version: 0,
1396
+ html
1397
+ });
1398
+ val && typeof val.then === "function" ? val.then(apply) : apply(val);
1399
+ }
1400
+ }
1401
+ }
1402
+ }
1403
+ const owner = getOwner();
1404
+ const frame = createFrame(el, {
1405
+ adopt: true,
1406
+ host,
1407
+ id,
1408
+ slots: slotsFor(props),
1409
+ ownerScope: fn => runWithOwner(owner, fn),
1410
+ reveal: revealSeam(owner)
1411
+ });
1412
+ onCleanup(() => frame.dispose());
1413
+ return el;
1414
+ }
1415
+ function installServerComponents(host = getFrameHost()) {
1416
+ const g = globalThis;
1417
+ if (!g._$SC) {
1418
+ g._$SC = {
1419
+ c: {},
1420
+ r(i) {
1421
+ return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
1422
+ }
1423
+ };
1424
+ }
1425
+ g._$SC.impl = (id, props) => documentBoundary(host, id, props);
1426
+ installRevealHook();
1427
+ configureServerFunctionsClient({
1428
+ responseHandler: createServerComponentHandler({
1429
+ host,
1430
+ capture: () => getOwner() ?? undefined,
1431
+ component: frameId => boundaryComponent(host, frameId),
1432
+ onStream: frameId => beginStream(frameId),
1433
+ documentComponent: functionId => g._$SC.c[functionId],
1434
+ intercept: ({
1435
+ id
1436
+ }) => {
1437
+ if (claimedBoundaries.has(id) || !findBoundaryElement(id)) return undefined;
1438
+ return g._$SC.r(id);
1439
+ }
1440
+ })
1441
+ });
1442
+ }
1443
+
1444
+ export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, createFrame, createFrameElement, createFrameHost, createJSONDataTable, createServerComponentHandler, getFrameHost, installServerComponents, isFrameStreamResponse };