@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.
- package/README.md +1 -6
- package/dist/dev.cjs +285 -60
- package/dist/dev.js +267 -57
- package/dist/server.cjs +1148 -176
- package/dist/server.js +1133 -175
- package/dist/web.cjs +285 -60
- package/dist/web.js +267 -57
- package/frames/dist/client.cjs +397 -175
- package/frames/dist/client.dev.cjs +401 -175
- package/frames/dist/client.dev.js +399 -173
- package/frames/dist/client.js +395 -173
- package/frames/dist/server.cjs +1424 -277
- package/frames/dist/server.js +1426 -280
- package/package.json +69 -7
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +110 -0
- package/serialization/dist/decode.js +104 -0
- package/serialization/dist/serialization.cjs +106 -43
- package/serialization/dist/serialization.js +100 -44
- package/serialization/types/index.d.ts +85 -60
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +85 -60
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +131 -98
- package/server-functions/dist/client.js +131 -99
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +367 -194
- package/server-functions/dist/server.dev.cjs +1077 -0
- package/server-functions/dist/server.dev.js +1045 -0
- package/server-functions/dist/server.js +365 -195
- package/server-functions/package.json +10 -0
- package/server-functions/rich-args/package.json +20 -0
- package/storage/types/index.d.ts +1 -1
- package/storage/types-cjs/index.d.cts +1 -1
- package/types/client.d.ts +149 -6
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +4 -2
- package/types/frames/client.d.ts +15 -1
- package/types/frames/frame-client.d.ts +63 -7
- package/types/frames/frame-sink.d.ts +26 -3
- package/types/frames/frame-transport.d.ts +40 -8
- package/types/frames/serializer.d.ts +85 -60
- package/types/frames/server.d.ts +22 -0
- package/types/index.d.ts +2 -3
- package/types/response.d.ts +45 -0
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +85 -60
- package/types/server-functions/client.d.ts +2 -1
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +99 -1
- package/types/server-functions/shared.d.ts +79 -1
- package/types/server-mock.d.ts +171 -59
- package/types/server.d.ts +209 -37
- package/types-cjs/client.d.cts +149 -6
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +4 -2
- package/types-cjs/frames/client.d.cts +15 -1
- package/types-cjs/frames/frame-client.d.cts +63 -7
- package/types-cjs/frames/frame-sink.d.cts +26 -3
- package/types-cjs/frames/frame-transport.d.cts +40 -8
- package/types-cjs/frames/serializer.d.cts +85 -60
- package/types-cjs/frames/server.d.cts +22 -0
- package/types-cjs/index.d.cts +2 -3
- package/types-cjs/response.d.cts +45 -0
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +85 -60
- package/types-cjs/server-functions/client.d.cts +2 -1
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +99 -1
- package/types-cjs/server-functions/shared.d.cts +79 -1
- package/types-cjs/server-mock.d.cts +171 -59
- package/types-cjs/server.d.cts +209 -37
package/frames/dist/client.cjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var solidJs = require('solid-js');
|
|
4
|
-
var 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.#
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
437
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
505
|
-
|
|
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 (
|
|
531
|
-
if (
|
|
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
|
|
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.#
|
|
601
|
-
this.#
|
|
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
|
-
#
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
811
|
+
return !!value && typeof value.$ref === "string";
|
|
771
812
|
}
|
|
772
813
|
function isFrameRef(value) {
|
|
773
|
-
return
|
|
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
|
|
782
|
-
|
|
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.
|
|
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 &&
|
|
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 =
|
|
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
|
-
|
|
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"
|
|
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
|
-
|
|
1309
|
-
const
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
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
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
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
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
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
|
-
|
|
1359
|
-
if (
|
|
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,
|
|
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) =>
|
|
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
|
|
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
|
|
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 =>
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
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
|
|
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
|
-
|
|
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)
|
|
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;
|