@solidjs/web 2.0.0-beta.31 → 2.0.0-beta.33

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 (73) hide show
  1. package/README.md +1 -6
  2. package/dist/dev.cjs +285 -60
  3. package/dist/dev.js +267 -57
  4. package/dist/server.cjs +1148 -176
  5. package/dist/server.js +1133 -175
  6. package/dist/web.cjs +285 -60
  7. package/dist/web.js +267 -57
  8. package/frames/dist/client.cjs +397 -175
  9. package/frames/dist/client.dev.cjs +401 -175
  10. package/frames/dist/client.dev.js +399 -173
  11. package/frames/dist/client.js +395 -173
  12. package/frames/dist/server.cjs +1424 -277
  13. package/frames/dist/server.js +1426 -280
  14. package/package.json +69 -7
  15. package/serialization/decode/package.json +20 -0
  16. package/serialization/dist/decode.cjs +110 -0
  17. package/serialization/dist/decode.js +104 -0
  18. package/serialization/dist/serialization.cjs +106 -43
  19. package/serialization/dist/serialization.js +100 -44
  20. package/serialization/types/index.d.ts +85 -60
  21. package/serialization/types/serializer-decode.d.ts +182 -0
  22. package/serialization/types-cjs/index.d.cts +85 -60
  23. package/serialization/types-cjs/serializer-decode.d.cts +182 -0
  24. package/server-functions/dist/client.cjs +131 -98
  25. package/server-functions/dist/client.js +131 -99
  26. package/server-functions/dist/rich-args.cjs +11 -0
  27. package/server-functions/dist/rich-args.js +9 -0
  28. package/server-functions/dist/server.cjs +367 -194
  29. package/server-functions/dist/server.dev.cjs +1077 -0
  30. package/server-functions/dist/server.dev.js +1045 -0
  31. package/server-functions/dist/server.js +365 -195
  32. package/server-functions/package.json +10 -0
  33. package/server-functions/rich-args/package.json +20 -0
  34. package/storage/types/index.d.ts +1 -1
  35. package/storage/types-cjs/index.d.cts +1 -1
  36. package/types/client.d.ts +149 -6
  37. package/types/cookies.d.ts +93 -0
  38. package/types/core.d.ts +4 -2
  39. package/types/frames/client.d.ts +15 -1
  40. package/types/frames/frame-client.d.ts +63 -7
  41. package/types/frames/frame-sink.d.ts +26 -3
  42. package/types/frames/frame-transport.d.ts +40 -8
  43. package/types/frames/serializer.d.ts +85 -60
  44. package/types/frames/server.d.ts +22 -0
  45. package/types/index.d.ts +2 -3
  46. package/types/response.d.ts +45 -0
  47. package/types/serializer-decode.d.ts +182 -0
  48. package/types/serializer.d.ts +85 -60
  49. package/types/server-functions/client.d.ts +2 -1
  50. package/types/server-functions/rich-args.d.ts +10 -0
  51. package/types/server-functions/server.d.ts +99 -1
  52. package/types/server-functions/shared.d.ts +79 -1
  53. package/types/server-mock.d.ts +171 -59
  54. package/types/server.d.ts +209 -37
  55. package/types-cjs/client.d.cts +149 -6
  56. package/types-cjs/cookies.d.cts +93 -0
  57. package/types-cjs/core.d.cts +4 -2
  58. package/types-cjs/frames/client.d.cts +15 -1
  59. package/types-cjs/frames/frame-client.d.cts +63 -7
  60. package/types-cjs/frames/frame-sink.d.cts +26 -3
  61. package/types-cjs/frames/frame-transport.d.cts +40 -8
  62. package/types-cjs/frames/serializer.d.cts +85 -60
  63. package/types-cjs/frames/server.d.cts +22 -0
  64. package/types-cjs/index.d.cts +2 -3
  65. package/types-cjs/response.d.cts +45 -0
  66. package/types-cjs/serializer-decode.d.cts +182 -0
  67. package/types-cjs/serializer.d.cts +85 -60
  68. package/types-cjs/server-functions/client.d.cts +2 -1
  69. package/types-cjs/server-functions/rich-args.d.cts +10 -0
  70. package/types-cjs/server-functions/server.d.cts +99 -1
  71. package/types-cjs/server-functions/shared.d.cts +79 -1
  72. package/types-cjs/server-mock.d.cts +171 -59
  73. package/types-cjs/server.d.cts +209 -37
@@ -1,10 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var solidJs = require('solid-js');
4
- var web$1 = require('@solidjs/web');
5
- var seroval = require('seroval');
4
+ var web = require('@solidjs/web');
6
5
  var client = require('@solidjs/web/server-functions/client');
7
- var web = require('seroval-plugins/web');
8
6
 
9
7
  const ELEMENT_NODE = 1;
10
8
  const TEXT_NODE = 3;
@@ -67,16 +65,32 @@ function chunkToRecords(chunk) {
67
65
  args: chunk.args
68
66
  }
69
67
  };
68
+ case "hole":
69
+ return {
70
+ [`hole:${chunk.key}`]: {
71
+ kind: "html",
72
+ value: chunk.html
73
+ }
74
+ };
75
+ case "attr":
76
+ return {
77
+ [`attr:${chunk.key}`]: {
78
+ kind: "attrs",
79
+ value: chunk.attrs,
80
+ removed: chunk.removed
81
+ }
82
+ };
70
83
  case "complete":
71
84
  return {
72
85
  ":complete": true
73
86
  };
74
87
  case "error":
75
- return chunk.key ? {
76
- [`seg:${chunk.key}:error`]: chunk.error
77
- } : {
88
+ if (!chunk.key) return {
78
89
  ":error": chunk.error
79
90
  };
91
+ return {
92
+ [`${/^lha?:/.test(chunk.key) ? "hole" : "seg"}:${chunk.key}:error`]: chunk.error
93
+ };
80
94
  default:
81
95
  return {};
82
96
  }
@@ -96,9 +110,7 @@ function createFrameHost(options = {}) {
96
110
  if (store.version !== undefined && version < store.version) return false;
97
111
  if (store.version === undefined || version > store.version) {
98
112
  store.version = version;
99
- for (const key of Object.keys(store.records)) {
100
- if (key.startsWith("seg:") || key === ":error") delete store.records[key];
101
- }
113
+ clearStreamRecords(store.records);
102
114
  }
103
115
  Object.assign(store.records, records);
104
116
  return true;
@@ -163,7 +175,10 @@ function createFrameHost(options = {}) {
163
175
  },
164
176
  resolve(ref, frameId) {
165
177
  return options.resolve ? options.resolve(ref, frameId) : undefined;
166
- }
178
+ },
179
+ revive: options.revive,
180
+ isContainer: options.isContainer,
181
+ prepareData: options.prepareData
167
182
  };
168
183
  }
169
184
  const FRAME_APPLIED_EVENT = "frame:applied";
@@ -176,8 +191,10 @@ class FrameImpl {
176
191
  #store = Object.create(null);
177
192
  #appliedRootValue;
178
193
  #hasContent = false;
194
+ #errorNotified = false;
179
195
  #revealed = new Set();
180
196
  #fallbackShown = new Set();
197
+ #appliedHoles = new Map();
181
198
  #slots;
182
199
  #mountedSlots = new Set();
183
200
  #slotCleanups = new Map();
@@ -195,10 +212,12 @@ class FrameImpl {
195
212
  #claimTree = (node, direct) => {
196
213
  const handlers = claimHandlers();
197
214
  if (!handlers) return;
198
- const run = () => direct ? claimNode(handlers, node) : claimTree(handlers, node);
199
- const scope = this.#options.ownerScope;
200
- scope ? scope(run) : run();
215
+ this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
201
216
  };
217
+ #scoped(fn) {
218
+ const scope = this.#options.ownerScope;
219
+ return scope ? scope(fn) : fn();
220
+ }
202
221
  constructor(element, start, end, options = {}) {
203
222
  this.#element = element;
204
223
  this.#start = start;
@@ -259,15 +278,9 @@ class FrameImpl {
259
278
  return;
260
279
  } else if (v > this.#version) {
261
280
  this.#version = v;
262
- this.#revealed.clear();
263
- this.#fallbackShown.clear();
264
- for (const key of Object.keys(this.#store)) {
265
- if (key.startsWith("seg:") || key === ":error") {
266
- delete this.#store[key];
267
- }
268
- }
281
+ this.#resetStreamState();
269
282
  }
270
- for (const key of Object.keys(write.r)) {
283
+ for (const key in write.r) {
271
284
  const incoming = write.r[key];
272
285
  if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
273
286
  const existing = this.#store[key];
@@ -279,6 +292,13 @@ class FrameImpl {
279
292
  }
280
293
  this.#flush();
281
294
  }
295
+ #resetStreamState(root) {
296
+ this.#revealed.clear();
297
+ this.#fallbackShown.clear();
298
+ this.#appliedHoles.clear();
299
+ this.#errorNotified = false;
300
+ clearStreamRecords(this.#store, root);
301
+ }
282
302
  #flush() {
283
303
  if (this.#disposed) return;
284
304
  const version = this.#version;
@@ -289,10 +309,14 @@ class FrameImpl {
289
309
  this.#appliedRootValue = root.value;
290
310
  this.#applied(version, reason);
291
311
  }
312
+ if (this.#store[":error"] && !this.#errorNotified) {
313
+ this.#errorNotified = true;
314
+ this.#applied(version, "error");
315
+ }
292
316
  let progressed = true;
293
317
  while (progressed) {
294
318
  progressed = false;
295
- for (const key of Object.keys(this.#store)) {
319
+ for (const key in this.#store) {
296
320
  const name = segmentName(key);
297
321
  if (name === null || this.#revealed.has(name)) continue;
298
322
  if (this.#segmentReady(name)) {
@@ -301,7 +325,7 @@ class FrameImpl {
301
325
  progressed = true;
302
326
  }
303
327
  }
304
- for (const key of Object.keys(this.#store)) {
328
+ for (const key in this.#store) {
305
329
  const m = /^seg:([^:]+):fallback$/.exec(key);
306
330
  if (!m) continue;
307
331
  const name = m[1];
@@ -313,7 +337,24 @@ class FrameImpl {
313
337
  }
314
338
  }
315
339
  }
316
- for (const key of Object.keys(this.#store)) {
340
+ for (const key in this.#store) {
341
+ const record = this.#store[key];
342
+ if (!record || this.#appliedHoles.get(key) === record) continue;
343
+ if (key.startsWith("hole:")) {
344
+ if (key.endsWith(":error")) {
345
+ this.#appliedHoles.set(key, record);
346
+ } else if (this.#applyHole(key.slice(5), record.value)) {
347
+ this.#appliedHoles.set(key, record);
348
+ this.#applied(version, "morph");
349
+ }
350
+ } else if (key.startsWith("attr:")) {
351
+ if (this.#applyAttrs(key.slice(5), record.value, record.removed)) {
352
+ this.#appliedHoles.set(key, record);
353
+ this.#applied(version, "morph");
354
+ }
355
+ }
356
+ }
357
+ for (const key in this.#store) {
317
358
  if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
318
359
  this.#processedAssets.add(key);
319
360
  const record = this.#store[key];
@@ -345,6 +386,7 @@ class FrameImpl {
345
386
  const callback = this.#resolveSlot(propOf(occurrence));
346
387
  if (!callback) continue;
347
388
  const record = this.#resolveSlotRecord(occurrence);
389
+ if (record && record.kind === "slot" && this.#refsUnresolved(record.args)) continue;
348
390
  const prev = this.#slotNodes.get(occurrence);
349
391
  const prevFirst = Array.isArray(prev) ? prev[0] : prev;
350
392
  const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
@@ -400,15 +442,7 @@ class FrameImpl {
400
442
  const cleanups = this.#slotCleanups.get(occurrence) ?? [];
401
443
  let existing = [];
402
444
  let end = null;
403
- if (start) {
404
- const endData = slotEnd(occurrence);
405
- let n = start.nextSibling;
406
- while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
407
- existing.push(n);
408
- n = n.nextSibling;
409
- }
410
- end = n;
411
- }
445
+ if (start) end = eachInRange(start, occurrence, n => existing.push(n));
412
446
  const ctx = {
413
447
  frame: this.#options.claimScope ?? this.#options.id,
414
448
  key: occurrence,
@@ -423,23 +457,16 @@ class FrameImpl {
423
457
  } : undefined
424
458
  };
425
459
  const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
426
- const scope = this.#options.ownerScope;
427
- const content = scope ? scope(() => callback(props, ctx)) : callback(props, ctx);
460
+ const content = this.#scoped(() => callback(props, ctx));
428
461
  this.#slotArgs.set(occurrence, record);
429
462
  if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
430
463
  if (content == null) return null;
431
464
  return Array.isArray(content) ? content : [content];
432
465
  }
433
466
  #replaceRange(key, start, nodes) {
434
- const end = slotEnd(key);
435
467
  const parent = start.parentNode;
436
- let n = start.nextSibling;
437
- while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
438
- const next = n.nextSibling;
439
- parent.removeChild(n);
440
- n = next;
441
- }
442
- for (const node of nodes) parent.insertBefore(node, n);
468
+ const end = eachInRange(start, key, n => parent.removeChild(n));
469
+ for (const node of nodes) parent.insertBefore(node, end);
443
470
  }
444
471
  #unmountSlot(key) {
445
472
  this.#mountedSlots.delete(key);
@@ -451,9 +478,7 @@ class FrameImpl {
451
478
  this.#runSlotCleanups(key);
452
479
  const regions = this.#slotRegions.get(key);
453
480
  if (regions) {
454
- for (const {
455
- frame
456
- } of regions.values()) frame?.dispose();
481
+ disposeRegions(regions);
457
482
  this.#slotRegions.delete(key);
458
483
  }
459
484
  }
@@ -463,15 +488,26 @@ class FrameImpl {
463
488
  this.#slotCleanups.delete(key);
464
489
  for (const fn of cleanups) fn();
465
490
  }
491
+ #refsUnresolved(args) {
492
+ const {
493
+ host,
494
+ id
495
+ } = this.#options;
496
+ if (host) for (const key in args) {
497
+ if (isDataRef(args[key]) && host.resolve(args[key], id) === undefined) return true;
498
+ }
499
+ return false;
500
+ }
501
+ #regionsFor(slotKey) {
502
+ let regions = this.#slotRegions.get(slotKey);
503
+ if (!regions) this.#slotRegions.set(slotKey, regions = new Map());
504
+ return regions;
505
+ }
466
506
  #resolveArgs(slotKey, args) {
467
507
  const host = this.#options.host;
468
- let regions = this.#slotRegions.get(slotKey);
469
- if (!regions) {
470
- regions = new Map();
471
- this.#slotRegions.set(slotKey, regions);
472
- }
508
+ const regions = this.#regionsFor(slotKey);
473
509
  const props = {};
474
- for (const key of Object.keys(args)) {
510
+ for (const key in args) {
475
511
  const value = args[key];
476
512
  if (isDataRef(value)) {
477
513
  const resolved = host ? host.resolve(value, this.#options.id) : undefined;
@@ -494,24 +530,15 @@ class FrameImpl {
494
530
  }
495
531
  props[key] = entry.element;
496
532
  } else {
497
- props[key] = value;
533
+ props[key] = host && host.revive ? host.revive(value) : value;
498
534
  }
499
535
  }
500
536
  return props;
501
537
  }
502
538
  #discoverRegions(slotKey, start) {
503
539
  if (!start) return;
504
- let regions = this.#slotRegions.get(slotKey);
505
- if (!regions) {
506
- regions = new Map();
507
- this.#slotRegions.set(slotKey, regions);
508
- }
509
- const endData = slotEnd(slotKey);
510
- let n = start.nextSibling;
511
- while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
512
- collectRegionElements(n, regions);
513
- n = n.nextSibling;
514
- }
540
+ const regions = this.#regionsFor(slotKey);
541
+ eachInRange(start, slotKey, n => collectRegionElements(n, regions));
515
542
  }
516
543
  #refArgsUnchanged(occurrence, record) {
517
544
  const old = this.#slotArgs.get(occurrence);
@@ -527,11 +554,15 @@ class FrameImpl {
527
554
  const va = a[key];
528
555
  const vb = b[key];
529
556
  if (va === vb) continue;
530
- if (!va || !vb || typeof va !== "object" || typeof vb !== "object") return false;
531
- if (typeof va.$frame === "string" && typeof vb.$frame === "string") continue;
532
- if (typeof va.$ref === "string" && typeof vb.$ref === "string" && cache && key in cache) {
557
+ if (isFrameRef(va) && isFrameRef(vb)) continue;
558
+ if (isDataRef(va) && isDataRef(vb) && cache && key in cache) {
533
559
  const host = this.#options.host;
534
560
  const next = host ? host.resolve(vb, this.#options.id) : undefined;
561
+ if (host && host.isContainer && (host.isContainer(next) || host.isContainer(cache[key]))) {
562
+ if (next === cache[key]) continue;
563
+ return false;
564
+ }
565
+ if (isAsyncLike(next) || isAsyncLike(cache[key])) return false;
535
566
  try {
536
567
  if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
537
568
  } catch (e) {
@@ -547,7 +578,7 @@ class FrameImpl {
547
578
  if (!args) return;
548
579
  const regions = this.#slotRegions.get(occurrence);
549
580
  if (!regions) return;
550
- for (const key of Object.keys(args)) {
581
+ for (const key in args) {
551
582
  const value = args[key];
552
583
  if (!isFrameRef(value)) continue;
553
584
  const entry = regions.get(key);
@@ -597,11 +628,8 @@ class FrameImpl {
597
628
  this.#element.setAttribute(FRAME_ID_ATTR, id);
598
629
  }
599
630
  this.#version = undefined;
600
- this.#revealed.clear();
601
- this.#fallbackShown.clear();
602
- for (const key of Object.keys(this.#store)) {
603
- if (key.startsWith("seg:") || key === ":error") delete this.#store[key];
604
- }
631
+ this.#appliedRootValue = undefined;
632
+ this.#resetStreamState(true);
605
633
  if (host) host.register(id, this);
606
634
  }
607
635
  rebase() {
@@ -621,11 +649,7 @@ class FrameImpl {
621
649
  }
622
650
  for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
623
651
  for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
624
- for (const regions of this.#slotRegions.values()) {
625
- for (const {
626
- frame
627
- } of regions.values()) frame?.dispose();
628
- }
652
+ for (const regions of this.#slotRegions.values()) disposeRegions(regions);
629
653
  this.#slotRegions.clear();
630
654
  this.#mountedSlots.clear();
631
655
  }
@@ -646,14 +670,37 @@ class FrameImpl {
646
670
  if (ranges.size) for (const root of grafts) flushGrafts(root, ranges);
647
671
  }
648
672
  }
649
- #clearContent() {
650
- const parent = this.#parent();
651
- let n = this.#firstContent();
652
- while (n && n !== this.#end) {
653
- const next = n.nextSibling;
654
- parent.removeChild(n);
655
- n = next;
673
+ #applyHole(marker, html) {
674
+ if (!this.#hasContent) return false;
675
+ const open = findLiveTarget(this.#firstContent(), this.#end, n => n.nodeType === COMMENT_NODE && n.data === marker);
676
+ if (!open) return false;
677
+ const close = rangeClose(open, "lh:/" + marker.slice(3));
678
+ if (!close) {
679
+ return false;
680
+ }
681
+ const claim = claimHandlers() ? this.#claimTree : null;
682
+ reconcileChildren(open.parentNode, parseFragment(html), open, close, claim);
683
+ return true;
684
+ }
685
+ #applyAttrs(addr, text, removed) {
686
+ if (!this.#hasContent) return false;
687
+ const el = findLiveTarget(this.#firstContent(), this.#end, n => n.nodeType === ELEMENT_NODE && n.getAttribute("data-lha") === addr);
688
+ if (!el) return false;
689
+ const parsed = parseFragment(`<i${text}></i>`).firstChild;
690
+ if (parsed) {
691
+ for (let i = 0; i < parsed.attributes.length; i++) {
692
+ const {
693
+ name,
694
+ value
695
+ } = parsed.attributes[i];
696
+ if (el.getAttribute(name) !== value) el.setAttribute(name, value);
697
+ }
656
698
  }
699
+ if (removed) for (const name of removed) el.removeAttribute(name);
700
+ return true;
701
+ }
702
+ #clearContent() {
703
+ removeUntil(this.#parent(), this.#firstContent(), this.#end);
657
704
  }
658
705
  #claimContent() {
659
706
  if (!claimHandlers()) return;
@@ -670,9 +717,7 @@ class FrameImpl {
670
717
  const assets = this.#store[`seg:${name}:assets`];
671
718
  if (assets && assets.styles) {
672
719
  let ready = true;
673
- for (const entry of assets.styles) {
674
- if (!ensureStylesheet(entry, this.#styleFlush)) ready = false;
675
- }
720
+ for (const entry of assets.styles) ready = ensureStylesheet(entry, this.#styleFlush) && ready;
676
721
  if (!ready) return false;
677
722
  }
678
723
  if (!this.#findPlaceholder(name)) return false;
@@ -686,12 +731,7 @@ class FrameImpl {
686
731
  const content = this.#store[`seg:${name}`];
687
732
  const closing = rangeClose(tpl, placeholderId(name));
688
733
  const parent = tpl.parentNode;
689
- let n = tpl.nextSibling;
690
- while (n && n !== closing) {
691
- const next = n.nextSibling;
692
- parent.removeChild(n);
693
- n = next;
694
- }
734
+ removeUntil(parent, tpl.nextSibling, closing);
695
735
  if (this.#options.reveal) {
696
736
  const fallbackFrag = tpl.content.cloneNode(true);
697
737
  this.#claimTree(fallbackFrag);
@@ -740,9 +780,7 @@ function createFrameElement(options) {
740
780
  const frame = new FrameImpl(el, null, null, options);
741
781
  return {
742
782
  element: el,
743
- get frame() {
744
- return frame;
745
- },
783
+ frame,
746
784
  dispose() {
747
785
  frame.dispose();
748
786
  el.remove();
@@ -762,15 +800,30 @@ function segmentName(key) {
762
800
  const m = /^seg:([^:]+)$/.exec(key);
763
801
  return m ? m[1] : null;
764
802
  }
803
+ function isAsyncLike(v) {
804
+ return !!v && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
805
+ }
765
806
  function propOf(occurrence) {
766
807
  const hash = occurrence.indexOf("#");
767
808
  return hash === -1 ? occurrence : occurrence.slice(0, hash);
768
809
  }
769
810
  function isDataRef(value) {
770
- return typeof value === "object" && value !== null && typeof value.$ref === "string";
811
+ return !!value && typeof value.$ref === "string";
771
812
  }
772
813
  function isFrameRef(value) {
773
- return typeof value === "object" && value !== null && typeof value.$frame === "string";
814
+ return !!value && typeof value.$frame === "string";
815
+ }
816
+ function disposeRegions(regions) {
817
+ for (const {
818
+ frame
819
+ } of regions.values()) frame?.dispose();
820
+ }
821
+ function removeUntil(parent, n, stop) {
822
+ while (n && n !== stop) {
823
+ const next = n.nextSibling;
824
+ parent.removeChild(n);
825
+ n = next;
826
+ }
774
827
  }
775
828
  function parseFragment(html) {
776
829
  const template = document.createElement("template");
@@ -778,9 +831,8 @@ function parseFragment(html) {
778
831
  return template.content;
779
832
  }
780
833
  function findHeadElement(selector, attr, value) {
781
- const nodes = document.head.querySelectorAll(selector);
782
- for (let i = 0; i < nodes.length; i++) {
783
- if (nodes[i].getAttribute(attr) === value) return nodes[i];
834
+ for (const node of document.head.querySelectorAll(selector)) {
835
+ if (node.getAttribute(attr) === value) return node;
784
836
  }
785
837
  return null;
786
838
  }
@@ -829,7 +881,7 @@ function applyInlineStyles(inlineStyles) {
829
881
  }
830
882
  }
831
883
  function isPlaceholderStart(node, id) {
832
- return node.nodeType === ELEMENT_NODE && node.tagName === "TEMPLATE" && node.getAttribute("id") === id;
884
+ return node.tagName === "TEMPLATE" && node.id === id;
833
885
  }
834
886
  function rangeClose(start, id) {
835
887
  let n = start.nextSibling;
@@ -839,6 +891,20 @@ function rangeClose(start, id) {
839
891
  }
840
892
  return null;
841
893
  }
894
+ function findLiveTarget(n, end, test) {
895
+ while (n && n !== end) {
896
+ if (n.nodeType === ELEMENT_NODE) {
897
+ const fid = isFrameElement(n) ? n.getAttribute(FRAME_ID_ATTR) : null;
898
+ if (fid === null || fid.includes(".")) {
899
+ if (test(n)) return n;
900
+ const found = findLiveTarget(n.firstChild, null, test);
901
+ if (found) return found;
902
+ }
903
+ } else if (test(n)) return n;
904
+ n = n.nextSibling;
905
+ }
906
+ return null;
907
+ }
842
908
  function findPlaceholder(n, end, id) {
843
909
  while (n && n !== end) {
844
910
  if (isPlaceholderStart(n, id)) return n;
@@ -885,6 +951,23 @@ function renameRegion(entry, childId) {
885
951
  entry.childId = childId;
886
952
  if (entry.frame) entry.frame.rebind(childId);else entry.element.setAttribute(FRAME_ID_ATTR, childId);
887
953
  }
954
+ function eachInRange(start, key, cb) {
955
+ const end = slotEnd(key);
956
+ let n = start.nextSibling;
957
+ while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
958
+ const next = n.nextSibling;
959
+ cb(n);
960
+ n = next;
961
+ }
962
+ return n;
963
+ }
964
+ function clearStreamRecords(records, root) {
965
+ for (const key in records) {
966
+ if (/^(seg|hole|attr):/.test(key) || key === ":error" || root && key === "") {
967
+ delete records[key];
968
+ }
969
+ }
970
+ }
888
971
  function argsEquivalent(a, b) {
889
972
  if (a === b) return true;
890
973
  if (!a || !b) return false;
@@ -895,9 +978,7 @@ function argsEquivalent(a, b) {
895
978
  const va = a[key];
896
979
  const vb = b[key];
897
980
  if (va === vb) continue;
898
- if (va && vb && typeof va === "object" && typeof vb === "object" && typeof va.$frame === "string" && va.$frame === vb.$frame) {
899
- continue;
900
- }
981
+ if (isFrameRef(va) && va.$frame === vb?.$frame) continue;
901
982
  return false;
902
983
  }
903
984
  return true;
@@ -1140,6 +1221,7 @@ async function applyFrameResponse(response, host, options = {}) {
1140
1221
  if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
1141
1222
  chunk.version = v;
1142
1223
  } else if (version !== undefined) chunk.version = version;
1224
+ if (chunk.type === "data" && host.prepareData) await host.prepareData();
1143
1225
  host.apply(chunk);
1144
1226
  }
1145
1227
  result = await reader.next();
@@ -1156,7 +1238,7 @@ function parseServerComponent(value, ctx) {
1156
1238
  address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
1157
1239
  };
1158
1240
  }
1159
- const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
1241
+ const ServerComponentPlugin = {
1160
1242
  tag: "dom-expressions/server-component",
1161
1243
  test(value) {
1162
1244
  return typeof value === "function" && SERVER_COMPONENT in value;
@@ -1183,12 +1265,10 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
1183
1265
  }
1184
1266
  return globalThis._$SC.r(id);
1185
1267
  }
1186
- });
1268
+ };
1187
1269
  function flightCodec(codec) {
1188
1270
  const plugins = codec && codec.plugins || [];
1189
- for (const plugin of plugins) {
1190
- if (plugin && plugin.tag === "dom-expressions/server-component") return codec;
1191
- }
1271
+ if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
1192
1272
  return {
1193
1273
  ...codec,
1194
1274
  plugins: [...plugins, ServerComponentPlugin]
@@ -1260,7 +1340,7 @@ function createServerComponentHandler({
1260
1340
  showing(address, functionId) {
1261
1341
  bindingFor(address, functionId);
1262
1342
  const comp = componentFor(functionId);
1263
- if ((typeof comp === "function" || typeof comp === "object" && comp !== null) && !comp[COMPONENT_BINDING]) {
1343
+ if (comp && (typeof comp === "function" || typeof comp === "object") && !comp[COMPONENT_BINDING]) {
1264
1344
  comp[COMPONENT_BINDING] = {
1265
1345
  component: comp,
1266
1346
  address
@@ -1305,69 +1385,74 @@ function createServerComponentHandler({
1305
1385
  }
1306
1386
  }
1307
1387
 
1308
- seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
1309
- const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
1310
- web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
1311
- web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin]);
1312
- function resolveSerializerPlugins(customPlugins) {
1313
- return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
1314
- }
1315
- const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
1316
- const JSON_CODEC_DEPTH_LIMIT = 64;
1317
- function resolveCodecOptions({
1318
- plugins,
1319
- disabledFeatures,
1320
- depthLimit
1321
- } = {}) {
1322
- return {
1323
- plugins: resolveSerializerPlugins(plugins),
1324
- disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
1325
- depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
1326
- };
1388
+ const STATE = Symbol.for("dom-expressions.container-trace-state");
1389
+ const state = globalThis[STATE] || (globalThis[STATE] = {
1390
+ materialized: new WeakMap(),
1391
+ materializedValues: new WeakSet()
1392
+ });
1393
+ function setContainerTraceMaterializer(fn) {
1394
+ state.materializeTrace = fn;
1327
1395
  }
1328
- function createJSONDeserializer(options) {
1329
- const refs = new Map();
1330
- const resolved = resolveCodecOptions(options);
1331
- return function deserializeJSONChunk(node) {
1332
- return seroval.fromCrossJSON(node, {
1333
- refs,
1334
- ...resolved
1335
- });
1336
- };
1396
+ function materialize(marker) {
1397
+ let value = state.materialized.get(marker.$tr);
1398
+ if (value === undefined) {
1399
+ value = state.materializeTrace(marker);
1400
+ state.materialized.set(marker.$tr, value);
1401
+ if (value !== null && typeof value === "object") state.materializedValues.add(value);
1402
+ }
1403
+ return value;
1337
1404
  }
1338
- function createJSONDataTable(options) {
1339
- const deserialize = createJSONDeserializer(options);
1340
- const table = new Map();
1341
- return {
1342
- apply(record) {
1343
- const value = deserialize(record.node);
1344
- if (record.initial) table.set(record.key, value);
1345
- },
1346
- get(key) {
1347
- return table.get(key);
1348
- },
1349
- resolve(ref) {
1350
- return table.get(ref.$ref);
1351
- }
1352
- };
1405
+ function isMaterializedContainer(value) {
1406
+ return value !== null && typeof value === "object" && state.materializedValues.has(value);
1407
+ }
1408
+ function isContainerTraceMarker(value) {
1409
+ return value != null && typeof value === "object" && value.$tr != null && typeof value.$tr[Symbol.asyncIterator] === "function";
1410
+ }
1411
+ function reviveContainerTraces(value) {
1412
+ if (!state.materializeTrace || value == null || typeof value !== "object") return value;
1413
+ if (isContainerTraceMarker(value)) return materialize(value);
1414
+ if (Array.isArray(value)) {
1415
+ for (let i = 0; i < value.length; i++) value[i] = reviveContainerTraces(value[i]);
1416
+ } else if (Object.getPrototypeOf(value) === Object.prototype) {
1417
+ for (const key of Object.keys(value)) value[key] = reviveContainerTraces(value[key]);
1418
+ }
1419
+ return value;
1353
1420
  }
1354
1421
 
1422
+ setContainerTraceMaterializer(solidJs.materializeContainerTrace);
1423
+ function asyncArg(value) {
1424
+ return value;
1425
+ }
1355
1426
  let sharedHost;
1427
+ let codec;
1428
+ let codecLoading;
1429
+ function loadCodec() {
1430
+ return codecLoading ??= import('@solidjs/web/serialization/decode').then(m => {
1431
+ codec = m;
1432
+ });
1433
+ }
1356
1434
  const tables = new Map();
1435
+ function ensureTable(root) {
1436
+ let table = tables.get(root);
1437
+ if (!table && codec) tables.set(root, table = codec.createJSONDataTable());
1438
+ return table;
1439
+ }
1357
1440
  function tableFor(id) {
1358
- const table = tables.get(id);
1359
- if (table) return table;
1360
- for (const [root, t] of tables) if (id.startsWith(root + ".")) return t;
1441
+ if (tables.has(id)) return ensureTable(id);
1442
+ for (const root of tables.keys()) if (id.startsWith(root + ".")) return ensureTable(root);
1361
1443
  return undefined;
1362
1444
  }
1363
1445
  function beginStream(frameId) {
1364
- tables.set(frameId, createJSONDataTable());
1446
+ tables.set(frameId, undefined);
1365
1447
  }
1366
1448
  function getFrameHost() {
1367
1449
  if (!sharedHost) {
1368
1450
  sharedHost = createFrameHost({
1451
+ prepareData: loadCodec,
1369
1452
  applyData: c => tableFor(c.id)?.apply(c),
1370
- resolve: (ref, id) => tableFor(id)?.resolve(ref)
1453
+ resolve: (ref, id) => tableFor(id)?.resolve(ref),
1454
+ revive: reviveContainerTraces,
1455
+ isContainer: isMaterializedContainer
1371
1456
  });
1372
1457
  }
1373
1458
  return sharedHost;
@@ -1428,8 +1513,27 @@ function claimRender(prefix, existing, render) {
1428
1513
  function liveSlotProps(initial, ctx) {
1429
1514
  const [args, setArgs] = solidJs.createSignal(initial);
1430
1515
  ctx.onUpdate(next => setArgs(() => next));
1516
+ return slotArgsProxy(args);
1517
+ }
1518
+ function isAsyncValue(v) {
1519
+ return v !== null && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
1520
+ }
1521
+ function slotArgsProxy(args) {
1522
+ const owner = solidJs.getOwner();
1523
+ const asyncReads = new Map();
1431
1524
  return new Proxy({}, {
1432
- get: (_, key) => args()[key],
1525
+ get: (_, key) => {
1526
+ const v = args()[key];
1527
+ if (isMaterializedContainer(v)) return v;
1528
+ if (!isAsyncValue(v)) return v;
1529
+ let read = asyncReads.get(key);
1530
+ if (!read) {
1531
+ const make = () => solidJs.createMemo(() => args()[key]);
1532
+ read = owner ? solidJs.runWithOwner(owner, make) : make();
1533
+ asyncReads.set(key, read);
1534
+ }
1535
+ return read();
1536
+ },
1433
1537
  has: (_, key) => key in args(),
1434
1538
  ownKeys: () => Reflect.ownKeys(args()),
1435
1539
  getOwnPropertyDescriptor: (_, key) => key in args() ? {
@@ -1447,6 +1551,7 @@ function isReactiveContent(value) {
1447
1551
  }
1448
1552
  function slotsFor(props) {
1449
1553
  const bindings = new Map();
1554
+ const fillScopes = new Map();
1450
1555
  return new Proxy({}, {
1451
1556
  get(_, prop) {
1452
1557
  if (typeof prop !== "string" || !(prop in props)) return undefined;
@@ -1457,6 +1562,19 @@ function slotsFor(props) {
1457
1562
  bindings.delete(key);
1458
1563
  prev.dispose();
1459
1564
  }
1565
+ const prevFill = key !== undefined && fillScopes.get(key);
1566
+ if (prevFill) {
1567
+ fillScopes.delete(key);
1568
+ prevFill.dispose();
1569
+ }
1570
+ const fillOwner = streamInvoke ? solidJs.createOwner() : null;
1571
+ if (fillOwner && key !== undefined && ctx) {
1572
+ fillScopes.set(key, fillOwner);
1573
+ ctx.onCleanup(() => {
1574
+ if (fillScopes.get(key) === fillOwner) fillScopes.delete(key);
1575
+ fillOwner.dispose();
1576
+ });
1577
+ }
1460
1578
  const settle = out => {
1461
1579
  const existing = ctx && ctx.existing || [];
1462
1580
  if (existing.length) {
@@ -1469,13 +1587,13 @@ function slotsFor(props) {
1469
1587
  const evaluate = () => {
1470
1588
  const v = props[prop];
1471
1589
  if (typeof v === "function" && ctx && ctx.invoked) {
1472
- return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotProps);
1590
+ return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotArgsProxy(() => slotProps));
1473
1591
  }
1474
1592
  return v;
1475
1593
  };
1476
1594
  const adopted = !!(ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length);
1477
1595
  const prefix = ctx && ctx.frame ? `sc-${ctx.frame}-${ctx.key}-` : "";
1478
- const value = adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
1596
+ const value = fillOwner ? solidJs.runWithOwner(fillOwner, () => adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate()) : adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
1479
1597
  if (!isReactiveContent(value)) {
1480
1598
  return settle(normalizeSlotContent(value));
1481
1599
  }
@@ -1488,7 +1606,7 @@ function slotsFor(props) {
1488
1606
  owner.dispose();
1489
1607
  });
1490
1608
  const end = ctx.range.end;
1491
- const bind = () => web$1.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
1609
+ const bind = () => web.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
1492
1610
  solidJs.runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
1493
1611
  return undefined;
1494
1612
  }
@@ -1498,34 +1616,84 @@ function slotsFor(props) {
1498
1616
  });
1499
1617
  }
1500
1618
  function revealSeam(owner) {
1501
- return seam => solidJs.runWithOwner(owner, () => web$1.insert(seam.before.parentNode, solidJs.createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
1619
+ return seam => solidJs.runWithOwner(owner, () => web.insert(seam.before.parentNode, solidJs.createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
1502
1620
  }
1621
+ let streamInvoke = false;
1503
1622
  function boundaryScope(owner) {
1504
- return fn => solidJs.getOwner() ? fn() : solidJs.runWithOwner(owner, fn);
1505
- }
1506
- function followBinding(frame, binding) {
1507
- solidJs.createRenderEffect(binding, address => frame.rebind(address));
1623
+ return fn => {
1624
+ if (solidJs.getOwner()) return fn();
1625
+ streamInvoke = true;
1626
+ try {
1627
+ return solidJs.runWithOwner(owner, fn);
1628
+ } finally {
1629
+ streamInvoke = false;
1630
+ }
1631
+ };
1508
1632
  }
1509
1633
  function boundaryComponent(host, fnId) {
1510
1634
  return (props, binding) => {
1511
1635
  const owner = solidJs.getOwner();
1636
+ const id = binding ? binding() : fnId;
1637
+ let applied = !tables.has(id);
1638
+ let release;
1639
+ const arm = () => new Promise(r => release = r);
1640
+ const mountGate = applied ? undefined : arm();
1641
+ let setGate;
1512
1642
  const {
1513
1643
  element,
1514
1644
  frame,
1515
1645
  dispose
1516
1646
  } = createFrameElement({
1517
1647
  host,
1518
- id: binding ? binding() : fnId,
1648
+ id,
1519
1649
  slots: slotsFor(props),
1520
1650
  ownerScope: boundaryScope(owner),
1521
- reveal: revealSeam(owner)
1651
+ reveal: revealSeam(owner),
1652
+ onApply: () => {
1653
+ applied = true;
1654
+ if (release) {
1655
+ release();
1656
+ release = undefined;
1657
+ }
1658
+ setGate && setGate(undefined);
1659
+ }
1522
1660
  });
1523
- if (binding) followBinding(frame, binding);
1661
+ const [gatePromise, setGatePromise] = solidJs.createSignal(applied ? undefined : mountGate);
1662
+ setGate = setGatePromise;
1663
+ if (binding) {
1664
+ solidJs.createRenderEffect(binding, (address, prev) => {
1665
+ if (prev !== undefined && address !== prev && tables.has(address)) {
1666
+ applied = false;
1667
+ setGatePromise(arm());
1668
+ }
1669
+ frame.rebind(address);
1670
+ });
1671
+ }
1524
1672
  solidJs.onCleanup(dispose);
1525
- return element;
1673
+ if (applied && !binding) return element;
1674
+ const gate = solidJs.createMemo(() => gatePromise());
1675
+ return solidJs.createMemo(() => (gate(), element));
1526
1676
  };
1527
1677
  }
1528
1678
  const claimedBoundaries = new Set();
1679
+ const liveOps = new Map();
1680
+ const liveAppliers = new Set();
1681
+ let livePumped = null;
1682
+ function pumpLiveChannel() {
1683
+ const stream = globalThis._$HY?.r?.["sc:live"];
1684
+ if (!stream || stream === livePumped || typeof stream.getReader !== "function") return;
1685
+ livePumped = stream;
1686
+ const reader = stream.getReader();
1687
+ const pump = () => reader.read().then(r => {
1688
+ if (r.done) return;
1689
+ const op = r.value;
1690
+ liveOps.set(`${op.type}:${op.fid || ""}:${op.key || ""}`, op);
1691
+ for (const apply of liveAppliers) apply(op);
1692
+ return pump();
1693
+ });
1694
+ pump().catch(() => {
1695
+ });
1696
+ }
1529
1697
  let boundaryIndex = null;
1530
1698
  const isBoundaryId = id => !id.includes(".");
1531
1699
  function indexBoundaries(root) {
@@ -1590,9 +1758,21 @@ function adoptBoundary(host, id, el, props, binding) {
1590
1758
  claimedBoundaries.add(id);
1591
1759
  const address = binding ? binding() : documentAddress(id);
1592
1760
  const appliedRecords = new Set();
1761
+ const claimedFragments = new Set();
1762
+ const claimRegionFragments = root => {
1763
+ const fr = globalThis._$HY?.fr;
1764
+ if (!fr || !fr.claim) return;
1765
+ root.querySelectorAll('template[id^="pl-"]').forEach(tpl => {
1766
+ const fragId = tpl.id.slice(3);
1767
+ if (claimedFragments.has(fragId)) return;
1768
+ claimedFragments.add(fragId);
1769
+ fr.claim(fragId);
1770
+ });
1771
+ };
1593
1772
  const drainRecords = () => {
1594
1773
  const hy = globalThis._$HY;
1595
1774
  if (!hy || !hy.r) return;
1775
+ pumpLiveChannel();
1596
1776
  const slotPrefix = `sc:slot:${id}:`;
1597
1777
  for (const key of Object.keys(hy.r)) {
1598
1778
  if (appliedRecords.has(key)) continue;
@@ -1621,8 +1801,31 @@ function adoptBoundary(host, id, el, props, binding) {
1621
1801
  }
1622
1802
  }
1623
1803
  };
1804
+ claimRegionFragments(el);
1805
+ const fr = globalThis._$HY?.fr;
1806
+ const unsubscribe = fr ? fr.subscribe((_fragId, parent) => {
1807
+ if (fr.claim && parent && el.contains(parent)) claimRegionFragments(parent);
1808
+ drainRecords();
1809
+ }) : undefined;
1810
+ const applyLiveOp = op => {
1811
+ if (op.type === "slot" && op.fid !== id) return;
1812
+ host.apply({
1813
+ ...op,
1814
+ id: address,
1815
+ version: 0
1816
+ });
1817
+ };
1818
+ liveAppliers.add(applyLiveOp);
1819
+ solidJs.onCleanup(() => {
1820
+ liveAppliers.delete(applyLiveOp);
1821
+ unsubscribe && unsubscribe();
1822
+ if (fr && fr.release) for (const fragId of claimedFragments) fr.release(fragId);
1823
+ });
1624
1824
  drainRecords();
1825
+ for (const op of liveOps.values()) applyLiveOp(op);
1625
1826
  const owner = solidJs.getOwner();
1827
+ let release;
1828
+ let setGate;
1626
1829
  const frame = createFrame(el, {
1627
1830
  adopt: true,
1628
1831
  host,
@@ -1630,6 +1833,13 @@ function adoptBoundary(host, id, el, props, binding) {
1630
1833
  slots: slotsFor(props),
1631
1834
  ownerScope: boundaryScope(owner),
1632
1835
  reveal: revealSeam(owner),
1836
+ onApply: () => {
1837
+ if (release) {
1838
+ release();
1839
+ release = undefined;
1840
+ }
1841
+ setGate && setGate(undefined);
1842
+ },
1633
1843
  ...{
1634
1844
  recordsPending: () => {
1635
1845
  if (document.readyState === "loading") return true;
@@ -1640,7 +1850,19 @@ function adoptBoundary(host, id, el, props, binding) {
1640
1850
  claimScope: id
1641
1851
  }
1642
1852
  });
1643
- if (binding) followBinding(frame, binding);
1853
+ if (binding) {
1854
+ const arm = () => new Promise(r => release = r);
1855
+ const [gatePromise, setGatePromise] = solidJs.createSignal(undefined);
1856
+ setGate = setGatePromise;
1857
+ const gate = solidJs.createMemo(() => gatePromise());
1858
+ solidJs.createRenderEffect(binding, (address, prev) => {
1859
+ if (prev !== undefined && address !== prev && tables.has(address)) {
1860
+ setGatePromise(arm());
1861
+ }
1862
+ frame.rebind(address);
1863
+ });
1864
+ solidJs.createRenderEffect(() => (gate(), undefined), () => {});
1865
+ }
1644
1866
  solidJs.onCleanup(() => frame.dispose());
1645
1867
  return el;
1646
1868
  }
@@ -1684,10 +1906,10 @@ function installServerComponents(host = getFrameHost()) {
1684
1906
  exports.FRAME_APPLIED_EVENT = FRAME_APPLIED_EVENT;
1685
1907
  exports.FRAME_STREAM_HEADER = FRAME_STREAM_HEADER;
1686
1908
  exports.applyFrameResponse = applyFrameResponse;
1909
+ exports.asyncArg = asyncArg;
1687
1910
  exports.createFrame = createFrame;
1688
1911
  exports.createFrameElement = createFrameElement;
1689
1912
  exports.createFrameHost = createFrameHost;
1690
- exports.createJSONDataTable = createJSONDataTable;
1691
1913
  exports.createServerComponentHandler = createServerComponentHandler;
1692
1914
  exports.getFrameHost = getFrameHost;
1693
1915
  exports.installServerComponents = installServerComponents;