@solidjs/web 2.0.0-beta.30 → 2.0.0-beta.32
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 +284 -82
- package/dist/dev.js +271 -79
- package/dist/server.cjs +555 -135
- package/dist/server.js +544 -132
- package/dist/web.cjs +281 -79
- package/dist/web.js +268 -76
- package/frames/dist/client.cjs +413 -360
- package/frames/dist/client.dev.cjs +413 -360
- package/frames/dist/client.dev.js +414 -361
- package/frames/dist/client.js +414 -361
- package/frames/dist/server.cjs +604 -199
- package/frames/dist/server.js +605 -201
- package/package.json +56 -6
- package/serialization/dist/serialization.cjs +8 -0
- package/serialization/dist/serialization.js +1 -0
- package/serialization/types/index.d.ts +173 -6
- package/serialization/types-cjs/index.d.cts +173 -6
- package/server-functions/dist/client.cjs +46 -9
- package/server-functions/dist/client.js +47 -11
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +275 -126
- package/server-functions/dist/server.dev.cjs +1053 -0
- package/server-functions/dist/server.dev.js +1021 -0
- package/server-functions/dist/server.js +273 -127
- 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 +134 -11
- package/types/core.d.ts +3 -1
- package/types/frames/client.d.ts +24 -8
- package/types/frames/frame-client.d.ts +49 -7
- package/types/frames/frame-sink.d.ts +32 -6
- package/types/frames/frame-transport.d.ts +88 -62
- package/types/frames/serializer.d.ts +173 -6
- package/types/frames/server.d.ts +22 -0
- package/types/index.d.ts +2 -3
- package/types/jsx.d.ts +3 -3
- package/types/response.d.ts +45 -0
- package/types/serializer.d.ts +173 -6
- package/types/server-functions/client.d.ts +1 -0
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +98 -0
- package/types/server-functions/shared.d.ts +22 -0
- package/types/server-mock.d.ts +171 -59
- package/types/server.d.ts +196 -42
- package/types-cjs/client.d.cts +134 -11
- package/types-cjs/core.d.cts +3 -1
- package/types-cjs/frames/client.d.cts +24 -8
- package/types-cjs/frames/frame-client.d.cts +49 -7
- package/types-cjs/frames/frame-sink.d.cts +32 -6
- package/types-cjs/frames/frame-transport.d.cts +88 -62
- package/types-cjs/frames/serializer.d.cts +173 -6
- package/types-cjs/frames/server.d.cts +22 -0
- package/types-cjs/index.d.cts +2 -3
- package/types-cjs/jsx.d.cts +3 -3
- package/types-cjs/response.d.cts +45 -0
- package/types-cjs/serializer.d.cts +173 -6
- package/types-cjs/server-functions/client.d.cts +1 -0
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +98 -0
- package/types-cjs/server-functions/shared.d.cts +22 -0
- package/types-cjs/server-mock.d.cts +171 -59
- package/types-cjs/server.d.cts +196 -42
|
@@ -83,98 +83,73 @@ function chunkToRecords(chunk) {
|
|
|
83
83
|
}
|
|
84
84
|
function createFrameHost(options = {}) {
|
|
85
85
|
const frames = new Map();
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
frame.apply({
|
|
94
|
-
version: chunk.version,
|
|
95
|
-
r: chunkToRecords(chunk)
|
|
86
|
+
const stores = new Map();
|
|
87
|
+
const storeFor = id => {
|
|
88
|
+
let store = stores.get(id);
|
|
89
|
+
if (!store) stores.set(id, store = {
|
|
90
|
+
version: undefined,
|
|
91
|
+
records: {}
|
|
96
92
|
});
|
|
93
|
+
return store;
|
|
94
|
+
};
|
|
95
|
+
const write = (store, version, records) => {
|
|
96
|
+
if (store.version !== undefined && version < store.version) return false;
|
|
97
|
+
if (store.version === undefined || version > store.version) {
|
|
98
|
+
store.version = version;
|
|
99
|
+
clearStreamRecords(store.records);
|
|
100
|
+
}
|
|
101
|
+
Object.assign(store.records, records);
|
|
102
|
+
return true;
|
|
97
103
|
};
|
|
98
104
|
return {
|
|
99
105
|
register(id, frame) {
|
|
100
106
|
let set = frames.get(id);
|
|
101
107
|
if (!set) frames.set(id, set = new Set());
|
|
102
|
-
const sibling = set.size ? set.values().next().value : undefined;
|
|
103
108
|
set.add(frame);
|
|
104
|
-
|
|
109
|
+
const store = stores.get(id);
|
|
110
|
+
if (store && store.version !== undefined) {
|
|
105
111
|
frame.apply({
|
|
106
|
-
version:
|
|
107
|
-
r:
|
|
108
|
-
});
|
|
109
|
-
if (sibling.version === undefined) frame.rebase && frame.rebase();
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const kept = retained.get(id);
|
|
113
|
-
if (kept) {
|
|
114
|
-
retained.delete(id);
|
|
115
|
-
frame.apply({
|
|
116
|
-
version: kept.version,
|
|
117
|
-
r: kept.records
|
|
112
|
+
version: store.version,
|
|
113
|
+
r: store.records
|
|
118
114
|
});
|
|
119
115
|
frame.rebase && frame.rebase();
|
|
120
116
|
}
|
|
121
|
-
const buffered = pending.get(id);
|
|
122
|
-
if (buffered) {
|
|
123
|
-
pending.delete(id);
|
|
124
|
-
const records = {};
|
|
125
|
-
let version;
|
|
126
|
-
for (const chunk of buffered.chunks) {
|
|
127
|
-
if (chunk.type === "data") {
|
|
128
|
-
options.applyData && options.applyData(chunk);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
version = chunk.version;
|
|
132
|
-
Object.assign(records, chunkToRecords(chunk));
|
|
133
|
-
}
|
|
134
|
-
if (version !== undefined) frame.apply({
|
|
135
|
-
version,
|
|
136
|
-
r: records
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
117
|
},
|
|
140
118
|
unregister(id, frame) {
|
|
141
119
|
const set = frames.get(id);
|
|
142
120
|
if (set && frame) set.delete(frame);
|
|
143
121
|
if (!set || !frame || !set.size) {
|
|
144
|
-
if (frame) {
|
|
145
|
-
const kept = frame.snapshot && frame.snapshot();
|
|
146
|
-
if (kept) retained.set(id, kept);
|
|
147
|
-
} else {
|
|
148
|
-
retained.delete(id);
|
|
149
|
-
}
|
|
150
122
|
frames.delete(id);
|
|
151
|
-
|
|
123
|
+
if (frame && frame.contentHTML) {
|
|
124
|
+
const store = storeFor(id);
|
|
125
|
+
if (!store.records[""]) {
|
|
126
|
+
const html = frame.contentHTML();
|
|
127
|
+
if (html != null) {
|
|
128
|
+
store.records[""] = {
|
|
129
|
+
kind: "html",
|
|
130
|
+
value: html
|
|
131
|
+
};
|
|
132
|
+
if (store.version === undefined) store.version = 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
152
136
|
}
|
|
137
|
+
if (!frame) stores.delete(id);
|
|
153
138
|
},
|
|
154
139
|
apply(chunk) {
|
|
155
140
|
if (chunk.type === "data") {
|
|
156
141
|
options.applyData && options.applyData(chunk);
|
|
157
142
|
return;
|
|
158
143
|
}
|
|
144
|
+
const records = chunkToRecords(chunk);
|
|
145
|
+
if (!write(storeFor(chunk.id), chunk.version, records)) return;
|
|
159
146
|
const set = frames.get(chunk.id);
|
|
160
|
-
if (set
|
|
161
|
-
for (const frame of set)
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const buffered = pending.get(chunk.id);
|
|
165
|
-
if (!buffered) {
|
|
166
|
-
pending.set(chunk.id, {
|
|
147
|
+
if (set) {
|
|
148
|
+
for (const frame of set) frame.apply({
|
|
167
149
|
version: chunk.version,
|
|
168
|
-
|
|
150
|
+
r: records
|
|
169
151
|
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (chunk.version < buffered.version) return;
|
|
173
|
-
if (chunk.version > buffered.version) {
|
|
174
|
-
buffered.version = chunk.version;
|
|
175
|
-
buffered.chunks.length = 0;
|
|
176
152
|
}
|
|
177
|
-
buffered.chunks.push(chunk);
|
|
178
153
|
},
|
|
179
154
|
get(id) {
|
|
180
155
|
const set = frames.get(id);
|
|
@@ -199,6 +174,7 @@ class FrameImpl {
|
|
|
199
174
|
#store = Object.create(null);
|
|
200
175
|
#appliedRootValue;
|
|
201
176
|
#hasContent = false;
|
|
177
|
+
#errorNotified = false;
|
|
202
178
|
#revealed = new Set();
|
|
203
179
|
#fallbackShown = new Set();
|
|
204
180
|
#slots;
|
|
@@ -210,6 +186,7 @@ class FrameImpl {
|
|
|
210
186
|
#slotResolvedRefs = new Map();
|
|
211
187
|
#slotNodes = new Map();
|
|
212
188
|
#processedAssets = new Set();
|
|
189
|
+
#recordRefresh = null;
|
|
213
190
|
#disposed = false;
|
|
214
191
|
#styleFlush = () => {
|
|
215
192
|
if (!this.#disposed) this.#flush();
|
|
@@ -217,10 +194,12 @@ class FrameImpl {
|
|
|
217
194
|
#claimTree = (node, direct) => {
|
|
218
195
|
const handlers = claimHandlers();
|
|
219
196
|
if (!handlers) return;
|
|
220
|
-
|
|
221
|
-
const scope = this.#options.ownerScope;
|
|
222
|
-
scope ? scope(run) : run();
|
|
197
|
+
this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
|
|
223
198
|
};
|
|
199
|
+
#scoped(fn) {
|
|
200
|
+
const scope = this.#options.ownerScope;
|
|
201
|
+
return scope ? scope(fn) : fn();
|
|
202
|
+
}
|
|
224
203
|
constructor(element, start, end, options = {}) {
|
|
225
204
|
this.#element = element;
|
|
226
205
|
this.#start = start;
|
|
@@ -281,15 +260,9 @@ class FrameImpl {
|
|
|
281
260
|
return;
|
|
282
261
|
} else if (v > this.#version) {
|
|
283
262
|
this.#version = v;
|
|
284
|
-
this.#
|
|
285
|
-
this.#fallbackShown.clear();
|
|
286
|
-
for (const key of Object.keys(this.#store)) {
|
|
287
|
-
if (key.startsWith("seg:") || key === ":error") {
|
|
288
|
-
delete this.#store[key];
|
|
289
|
-
}
|
|
290
|
-
}
|
|
263
|
+
this.#resetStreamState();
|
|
291
264
|
}
|
|
292
|
-
for (const key
|
|
265
|
+
for (const key in write.r) {
|
|
293
266
|
const incoming = write.r[key];
|
|
294
267
|
if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
|
|
295
268
|
const existing = this.#store[key];
|
|
@@ -301,6 +274,12 @@ class FrameImpl {
|
|
|
301
274
|
}
|
|
302
275
|
this.#flush();
|
|
303
276
|
}
|
|
277
|
+
#resetStreamState(root) {
|
|
278
|
+
this.#revealed.clear();
|
|
279
|
+
this.#fallbackShown.clear();
|
|
280
|
+
this.#errorNotified = false;
|
|
281
|
+
clearStreamRecords(this.#store, root);
|
|
282
|
+
}
|
|
304
283
|
#flush() {
|
|
305
284
|
if (this.#disposed) return;
|
|
306
285
|
const version = this.#version;
|
|
@@ -311,10 +290,14 @@ class FrameImpl {
|
|
|
311
290
|
this.#appliedRootValue = root.value;
|
|
312
291
|
this.#applied(version, reason);
|
|
313
292
|
}
|
|
293
|
+
if (this.#store[":error"] && !this.#errorNotified) {
|
|
294
|
+
this.#errorNotified = true;
|
|
295
|
+
this.#applied(version, "error");
|
|
296
|
+
}
|
|
314
297
|
let progressed = true;
|
|
315
298
|
while (progressed) {
|
|
316
299
|
progressed = false;
|
|
317
|
-
for (const key
|
|
300
|
+
for (const key in this.#store) {
|
|
318
301
|
const name = segmentName(key);
|
|
319
302
|
if (name === null || this.#revealed.has(name)) continue;
|
|
320
303
|
if (this.#segmentReady(name)) {
|
|
@@ -323,7 +306,7 @@ class FrameImpl {
|
|
|
323
306
|
progressed = true;
|
|
324
307
|
}
|
|
325
308
|
}
|
|
326
|
-
for (const key
|
|
309
|
+
for (const key in this.#store) {
|
|
327
310
|
const m = /^seg:([^:]+):fallback$/.exec(key);
|
|
328
311
|
if (!m) continue;
|
|
329
312
|
const name = m[1];
|
|
@@ -335,7 +318,7 @@ class FrameImpl {
|
|
|
335
318
|
}
|
|
336
319
|
}
|
|
337
320
|
}
|
|
338
|
-
for (const key
|
|
321
|
+
for (const key in this.#store) {
|
|
339
322
|
if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
|
|
340
323
|
this.#processedAssets.add(key);
|
|
341
324
|
const record = this.#store[key];
|
|
@@ -355,7 +338,9 @@ class FrameImpl {
|
|
|
355
338
|
}
|
|
356
339
|
#removeSlotRecord(occurrence) {
|
|
357
340
|
const key = `slot:${occurrence}`;
|
|
358
|
-
if (key in this.#store)
|
|
341
|
+
if (key in this.#store) {
|
|
342
|
+
if (!this.#mountedSlots.has(occurrence)) delete this.#store[key];
|
|
343
|
+
} else this.#options.removeSlotRecord?.(occurrence);
|
|
359
344
|
}
|
|
360
345
|
#syncSlots(root) {
|
|
361
346
|
if (!this.#slots && !this.#options.resolveSlot) return;
|
|
@@ -365,6 +350,7 @@ class FrameImpl {
|
|
|
365
350
|
const callback = this.#resolveSlot(propOf(occurrence));
|
|
366
351
|
if (!callback) continue;
|
|
367
352
|
const record = this.#resolveSlotRecord(occurrence);
|
|
353
|
+
if (record && record.kind === "slot" && this.#refsUnresolved(record.args)) continue;
|
|
368
354
|
const prev = this.#slotNodes.get(occurrence);
|
|
369
355
|
const prevFirst = Array.isArray(prev) ? prev[0] : prev;
|
|
370
356
|
const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
|
|
@@ -373,6 +359,15 @@ class FrameImpl {
|
|
|
373
359
|
this.#runSlotCleanups(occurrence);
|
|
374
360
|
}
|
|
375
361
|
if (!this.#mountedSlots.has(occurrence)) {
|
|
362
|
+
if (record === undefined && !root && this.#options.adopt && this.#options.recordsPending?.()) {
|
|
363
|
+
this.#recordRefresh ??= setTimeout(() => {
|
|
364
|
+
this.#recordRefresh = null;
|
|
365
|
+
if (this.#disposed) return;
|
|
366
|
+
this.#options.drainRecords?.();
|
|
367
|
+
this.#syncSlots();
|
|
368
|
+
});
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
376
371
|
if (this.#options.adopt) this.#discoverRegions(occurrence, start);
|
|
377
372
|
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
378
373
|
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
@@ -389,12 +384,6 @@ class FrameImpl {
|
|
|
389
384
|
const update = this.#slotUpdaters.get(occurrence);
|
|
390
385
|
if (update) {
|
|
391
386
|
const props = this.#resolveArgs(occurrence, record.args);
|
|
392
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
393
|
-
if (regions) {
|
|
394
|
-
for (const [argKey, entry] of regions) {
|
|
395
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
387
|
this.#slotArgs.set(occurrence, record);
|
|
399
388
|
update(props);
|
|
400
389
|
this.#bindRegions(occurrence);
|
|
@@ -417,15 +406,7 @@ class FrameImpl {
|
|
|
417
406
|
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
418
407
|
let existing = [];
|
|
419
408
|
let end = null;
|
|
420
|
-
if (start)
|
|
421
|
-
const endData = slotEnd(occurrence);
|
|
422
|
-
let n = start.nextSibling;
|
|
423
|
-
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
424
|
-
existing.push(n);
|
|
425
|
-
n = n.nextSibling;
|
|
426
|
-
}
|
|
427
|
-
end = n;
|
|
428
|
-
}
|
|
409
|
+
if (start) end = eachInRange(start, occurrence, n => existing.push(n));
|
|
429
410
|
const ctx = {
|
|
430
411
|
frame: this.#options.claimScope ?? this.#options.id,
|
|
431
412
|
key: occurrence,
|
|
@@ -440,29 +421,16 @@ class FrameImpl {
|
|
|
440
421
|
} : undefined
|
|
441
422
|
};
|
|
442
423
|
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
443
|
-
const
|
|
444
|
-
if (regions) {
|
|
445
|
-
for (const [argKey, entry] of regions) {
|
|
446
|
-
if (!(argKey in props)) props[argKey] = entry.element;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
const scope = this.#options.ownerScope;
|
|
450
|
-
const content = scope ? scope(() => callback(props, ctx)) : callback(props, ctx);
|
|
424
|
+
const content = this.#scoped(() => callback(props, ctx));
|
|
451
425
|
this.#slotArgs.set(occurrence, record);
|
|
452
426
|
if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
|
|
453
427
|
if (content == null) return null;
|
|
454
428
|
return Array.isArray(content) ? content : [content];
|
|
455
429
|
}
|
|
456
430
|
#replaceRange(key, start, nodes) {
|
|
457
|
-
const end = slotEnd(key);
|
|
458
431
|
const parent = start.parentNode;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const next = n.nextSibling;
|
|
462
|
-
parent.removeChild(n);
|
|
463
|
-
n = next;
|
|
464
|
-
}
|
|
465
|
-
for (const node of nodes) parent.insertBefore(node, n);
|
|
432
|
+
const end = eachInRange(start, key, n => parent.removeChild(n));
|
|
433
|
+
for (const node of nodes) parent.insertBefore(node, end);
|
|
466
434
|
}
|
|
467
435
|
#unmountSlot(key) {
|
|
468
436
|
this.#mountedSlots.delete(key);
|
|
@@ -474,9 +442,7 @@ class FrameImpl {
|
|
|
474
442
|
this.#runSlotCleanups(key);
|
|
475
443
|
const regions = this.#slotRegions.get(key);
|
|
476
444
|
if (regions) {
|
|
477
|
-
|
|
478
|
-
frame
|
|
479
|
-
} of regions.values()) frame?.dispose();
|
|
445
|
+
disposeRegions(regions);
|
|
480
446
|
this.#slotRegions.delete(key);
|
|
481
447
|
}
|
|
482
448
|
}
|
|
@@ -486,15 +452,26 @@ class FrameImpl {
|
|
|
486
452
|
this.#slotCleanups.delete(key);
|
|
487
453
|
for (const fn of cleanups) fn();
|
|
488
454
|
}
|
|
455
|
+
#refsUnresolved(args) {
|
|
456
|
+
const {
|
|
457
|
+
host,
|
|
458
|
+
id
|
|
459
|
+
} = this.#options;
|
|
460
|
+
if (host) for (const key in args) {
|
|
461
|
+
if (isDataRef(args[key]) && host.resolve(args[key], id) === undefined) return true;
|
|
462
|
+
}
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
#regionsFor(slotKey) {
|
|
466
|
+
let regions = this.#slotRegions.get(slotKey);
|
|
467
|
+
if (!regions) this.#slotRegions.set(slotKey, regions = new Map());
|
|
468
|
+
return regions;
|
|
469
|
+
}
|
|
489
470
|
#resolveArgs(slotKey, args) {
|
|
490
471
|
const host = this.#options.host;
|
|
491
|
-
|
|
492
|
-
if (!regions) {
|
|
493
|
-
regions = new Map();
|
|
494
|
-
this.#slotRegions.set(slotKey, regions);
|
|
495
|
-
}
|
|
472
|
+
const regions = this.#regionsFor(slotKey);
|
|
496
473
|
const props = {};
|
|
497
|
-
for (const key
|
|
474
|
+
for (const key in args) {
|
|
498
475
|
const value = args[key];
|
|
499
476
|
if (isDataRef(value)) {
|
|
500
477
|
const resolved = host ? host.resolve(value, this.#options.id) : undefined;
|
|
@@ -524,18 +501,8 @@ class FrameImpl {
|
|
|
524
501
|
}
|
|
525
502
|
#discoverRegions(slotKey, start) {
|
|
526
503
|
if (!start) return;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
regions = new Map();
|
|
530
|
-
this.#slotRegions.set(slotKey, regions);
|
|
531
|
-
}
|
|
532
|
-
const endData = slotEnd(slotKey);
|
|
533
|
-
const prefix = `${this.#options.id}.`;
|
|
534
|
-
let n = start.nextSibling;
|
|
535
|
-
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
536
|
-
collectRegionElements(n, regions, prefix);
|
|
537
|
-
n = n.nextSibling;
|
|
538
|
-
}
|
|
504
|
+
const regions = this.#regionsFor(slotKey);
|
|
505
|
+
eachInRange(start, slotKey, n => collectRegionElements(n, regions));
|
|
539
506
|
}
|
|
540
507
|
#refArgsUnchanged(occurrence, record) {
|
|
541
508
|
const old = this.#slotArgs.get(occurrence);
|
|
@@ -545,26 +512,17 @@ class FrameImpl {
|
|
|
545
512
|
const b = record.args || {};
|
|
546
513
|
const ka = Object.keys(a);
|
|
547
514
|
const kb = Object.keys(b);
|
|
548
|
-
if (kb.length
|
|
549
|
-
if (kb.length !== ka.length) {
|
|
550
|
-
const regions = this.#slotRegions.get(occurrence);
|
|
551
|
-
for (const key of kb) {
|
|
552
|
-
if (key in a) continue;
|
|
553
|
-
const vb = b[key];
|
|
554
|
-
if (!vb || typeof vb !== "object" || typeof vb.$frame !== "string") return false;
|
|
555
|
-
if (!regions || !regions.has(key)) return false;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
515
|
+
if (kb.length !== ka.length) return false;
|
|
558
516
|
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
559
517
|
for (const key of ka) {
|
|
560
518
|
const va = a[key];
|
|
561
519
|
const vb = b[key];
|
|
562
520
|
if (va === vb) continue;
|
|
563
|
-
if (
|
|
564
|
-
if (
|
|
565
|
-
if (typeof va.$ref === "string" && typeof vb.$ref === "string" && cache && key in cache) {
|
|
521
|
+
if (isFrameRef(va) && isFrameRef(vb)) continue;
|
|
522
|
+
if (isDataRef(va) && isDataRef(vb) && cache && key in cache) {
|
|
566
523
|
const host = this.#options.host;
|
|
567
524
|
const next = host ? host.resolve(vb, this.#options.id) : undefined;
|
|
525
|
+
if (isAsyncLike(next) || isAsyncLike(cache[key])) return false;
|
|
568
526
|
try {
|
|
569
527
|
if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
|
|
570
528
|
} catch (e) {
|
|
@@ -580,7 +538,7 @@ class FrameImpl {
|
|
|
580
538
|
if (!args) return;
|
|
581
539
|
const regions = this.#slotRegions.get(occurrence);
|
|
582
540
|
if (!regions) return;
|
|
583
|
-
for (const key
|
|
541
|
+
for (const key in args) {
|
|
584
542
|
const value = args[key];
|
|
585
543
|
if (!isFrameRef(value)) continue;
|
|
586
544
|
const entry = regions.get(key);
|
|
@@ -611,22 +569,9 @@ class FrameImpl {
|
|
|
611
569
|
#findPlaceholder(name) {
|
|
612
570
|
return findPlaceholder(this.#firstContent(), this.#end, placeholderId(name));
|
|
613
571
|
}
|
|
614
|
-
|
|
615
|
-
if (this.#disposed) return null;
|
|
616
|
-
|
|
617
|
-
...this.#store
|
|
618
|
-
};
|
|
619
|
-
if (!records[""] && this.#element && this.#hasContent) {
|
|
620
|
-
records[""] = {
|
|
621
|
-
kind: "html",
|
|
622
|
-
value: this.#element.innerHTML
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
if (!records[""] && this.#version === undefined) return null;
|
|
626
|
-
return {
|
|
627
|
-
version: this.#version ?? 0,
|
|
628
|
-
records
|
|
629
|
-
};
|
|
572
|
+
contentHTML() {
|
|
573
|
+
if (this.#disposed || !this.#element || !this.#hasContent) return null;
|
|
574
|
+
return this.#element.innerHTML;
|
|
630
575
|
}
|
|
631
576
|
rebind(id) {
|
|
632
577
|
if (this.#disposed || id === this.#options.id) return;
|
|
@@ -643,11 +588,8 @@ class FrameImpl {
|
|
|
643
588
|
this.#element.setAttribute(FRAME_ID_ATTR, id);
|
|
644
589
|
}
|
|
645
590
|
this.#version = undefined;
|
|
646
|
-
this.#
|
|
647
|
-
this.#
|
|
648
|
-
for (const key of Object.keys(this.#store)) {
|
|
649
|
-
if (key.startsWith("seg:") || key === ":error") delete this.#store[key];
|
|
650
|
-
}
|
|
591
|
+
this.#appliedRootValue = undefined;
|
|
592
|
+
this.#resetStreamState(true);
|
|
651
593
|
if (host) host.register(id, this);
|
|
652
594
|
}
|
|
653
595
|
rebase() {
|
|
@@ -661,13 +603,13 @@ class FrameImpl {
|
|
|
661
603
|
} = this.#options;
|
|
662
604
|
if (host && id !== undefined) host.unregister(id, this);
|
|
663
605
|
this.#disposed = true;
|
|
606
|
+
if (this.#recordRefresh) {
|
|
607
|
+
clearTimeout(this.#recordRefresh);
|
|
608
|
+
this.#recordRefresh = null;
|
|
609
|
+
}
|
|
664
610
|
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
665
611
|
for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
|
|
666
|
-
for (const regions of this.#slotRegions.values())
|
|
667
|
-
for (const {
|
|
668
|
-
frame
|
|
669
|
-
} of regions.values()) frame?.dispose();
|
|
670
|
-
}
|
|
612
|
+
for (const regions of this.#slotRegions.values()) disposeRegions(regions);
|
|
671
613
|
this.#slotRegions.clear();
|
|
672
614
|
this.#mountedSlots.clear();
|
|
673
615
|
}
|
|
@@ -683,18 +625,13 @@ class FrameImpl {
|
|
|
683
625
|
const claim = claimHandlers() ? this.#claimTree : null;
|
|
684
626
|
const ranges = new Map();
|
|
685
627
|
this.#collectSlots(ranges);
|
|
686
|
-
|
|
687
|
-
|
|
628
|
+
const grafts = [];
|
|
629
|
+
reconcileChildren(parent, fragment, this.#start, this.#end, claim, ranges, grafts);
|
|
630
|
+
if (ranges.size) for (const root of grafts) flushGrafts(root, ranges);
|
|
688
631
|
}
|
|
689
632
|
}
|
|
690
633
|
#clearContent() {
|
|
691
|
-
|
|
692
|
-
let n = this.#firstContent();
|
|
693
|
-
while (n && n !== this.#end) {
|
|
694
|
-
const next = n.nextSibling;
|
|
695
|
-
parent.removeChild(n);
|
|
696
|
-
n = next;
|
|
697
|
-
}
|
|
634
|
+
removeUntil(this.#parent(), this.#firstContent(), this.#end);
|
|
698
635
|
}
|
|
699
636
|
#claimContent() {
|
|
700
637
|
if (!claimHandlers()) return;
|
|
@@ -711,9 +648,7 @@ class FrameImpl {
|
|
|
711
648
|
const assets = this.#store[`seg:${name}:assets`];
|
|
712
649
|
if (assets && assets.styles) {
|
|
713
650
|
let ready = true;
|
|
714
|
-
for (const entry of assets.styles)
|
|
715
|
-
if (!ensureStylesheet(entry, this.#styleFlush)) ready = false;
|
|
716
|
-
}
|
|
651
|
+
for (const entry of assets.styles) ready = ensureStylesheet(entry, this.#styleFlush) && ready;
|
|
717
652
|
if (!ready) return false;
|
|
718
653
|
}
|
|
719
654
|
if (!this.#findPlaceholder(name)) return false;
|
|
@@ -730,12 +665,7 @@ class FrameImpl {
|
|
|
730
665
|
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);
|
|
731
666
|
}
|
|
732
667
|
const parent = tpl.parentNode;
|
|
733
|
-
|
|
734
|
-
while (n && n !== closing) {
|
|
735
|
-
const next = n.nextSibling;
|
|
736
|
-
parent.removeChild(n);
|
|
737
|
-
n = next;
|
|
738
|
-
}
|
|
668
|
+
removeUntil(parent, tpl.nextSibling, closing);
|
|
739
669
|
if (this.#options.reveal) {
|
|
740
670
|
const fallbackFrag = tpl.content.cloneNode(true);
|
|
741
671
|
this.#claimTree(fallbackFrag);
|
|
@@ -784,9 +714,7 @@ function createFrameElement(options) {
|
|
|
784
714
|
const frame = new FrameImpl(el, null, null, options);
|
|
785
715
|
return {
|
|
786
716
|
element: el,
|
|
787
|
-
|
|
788
|
-
return frame;
|
|
789
|
-
},
|
|
717
|
+
frame,
|
|
790
718
|
dispose() {
|
|
791
719
|
frame.dispose();
|
|
792
720
|
el.remove();
|
|
@@ -806,15 +734,30 @@ function segmentName(key) {
|
|
|
806
734
|
const m = /^seg:([^:]+)$/.exec(key);
|
|
807
735
|
return m ? m[1] : null;
|
|
808
736
|
}
|
|
737
|
+
function isAsyncLike(v) {
|
|
738
|
+
return !!v && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
739
|
+
}
|
|
809
740
|
function propOf(occurrence) {
|
|
810
741
|
const hash = occurrence.indexOf("#");
|
|
811
742
|
return hash === -1 ? occurrence : occurrence.slice(0, hash);
|
|
812
743
|
}
|
|
813
744
|
function isDataRef(value) {
|
|
814
|
-
return
|
|
745
|
+
return !!value && typeof value.$ref === "string";
|
|
815
746
|
}
|
|
816
747
|
function isFrameRef(value) {
|
|
817
|
-
return
|
|
748
|
+
return !!value && typeof value.$frame === "string";
|
|
749
|
+
}
|
|
750
|
+
function disposeRegions(regions) {
|
|
751
|
+
for (const {
|
|
752
|
+
frame
|
|
753
|
+
} of regions.values()) frame?.dispose();
|
|
754
|
+
}
|
|
755
|
+
function removeUntil(parent, n, stop) {
|
|
756
|
+
while (n && n !== stop) {
|
|
757
|
+
const next = n.nextSibling;
|
|
758
|
+
parent.removeChild(n);
|
|
759
|
+
n = next;
|
|
760
|
+
}
|
|
818
761
|
}
|
|
819
762
|
function parseFragment(html) {
|
|
820
763
|
const template = document.createElement("template");
|
|
@@ -822,9 +765,8 @@ function parseFragment(html) {
|
|
|
822
765
|
return template.content;
|
|
823
766
|
}
|
|
824
767
|
function findHeadElement(selector, attr, value) {
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
if (nodes[i].getAttribute(attr) === value) return nodes[i];
|
|
768
|
+
for (const node of document.head.querySelectorAll(selector)) {
|
|
769
|
+
if (node.getAttribute(attr) === value) return node;
|
|
828
770
|
}
|
|
829
771
|
return null;
|
|
830
772
|
}
|
|
@@ -873,7 +815,7 @@ function applyInlineStyles(inlineStyles) {
|
|
|
873
815
|
}
|
|
874
816
|
}
|
|
875
817
|
function isPlaceholderStart(node, id) {
|
|
876
|
-
return node.
|
|
818
|
+
return node.tagName === "TEMPLATE" && node.id === id;
|
|
877
819
|
}
|
|
878
820
|
function rangeClose(start, id) {
|
|
879
821
|
let n = start.nextSibling;
|
|
@@ -907,11 +849,11 @@ function collectSlots(n, end, out) {
|
|
|
907
849
|
n = n.nextSibling;
|
|
908
850
|
}
|
|
909
851
|
}
|
|
910
|
-
function collectRegionElements(node, regions
|
|
852
|
+
function collectRegionElements(node, regions) {
|
|
911
853
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
912
854
|
if (isFrameElement(node)) {
|
|
913
855
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
914
|
-
if (childId && childId.
|
|
856
|
+
if (childId && childId.includes(".")) {
|
|
915
857
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
916
858
|
if (!regions.has(argKey)) {
|
|
917
859
|
regions.set(argKey, {
|
|
@@ -924,12 +866,27 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
924
866
|
}
|
|
925
867
|
return;
|
|
926
868
|
}
|
|
927
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
869
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
928
870
|
}
|
|
929
871
|
function renameRegion(entry, childId) {
|
|
930
872
|
entry.childId = childId;
|
|
931
873
|
if (entry.frame) entry.frame.rebind(childId);else entry.element.setAttribute(FRAME_ID_ATTR, childId);
|
|
932
874
|
}
|
|
875
|
+
function eachInRange(start, key, cb) {
|
|
876
|
+
const end = slotEnd(key);
|
|
877
|
+
let n = start.nextSibling;
|
|
878
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
|
|
879
|
+
const next = n.nextSibling;
|
|
880
|
+
cb(n);
|
|
881
|
+
n = next;
|
|
882
|
+
}
|
|
883
|
+
return n;
|
|
884
|
+
}
|
|
885
|
+
function clearStreamRecords(records, root) {
|
|
886
|
+
for (const key in records) {
|
|
887
|
+
if (key.startsWith("seg:") || key === ":error" || root && key === "") delete records[key];
|
|
888
|
+
}
|
|
889
|
+
}
|
|
933
890
|
function argsEquivalent(a, b) {
|
|
934
891
|
if (a === b) return true;
|
|
935
892
|
if (!a || !b) return false;
|
|
@@ -940,9 +897,7 @@ function argsEquivalent(a, b) {
|
|
|
940
897
|
const va = a[key];
|
|
941
898
|
const vb = b[key];
|
|
942
899
|
if (va === vb) continue;
|
|
943
|
-
if (va &&
|
|
944
|
-
continue;
|
|
945
|
-
}
|
|
900
|
+
if (isFrameRef(va) && va.$frame === vb?.$frame) continue;
|
|
946
901
|
return false;
|
|
947
902
|
}
|
|
948
903
|
return true;
|
|
@@ -992,11 +947,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
992
947
|
}
|
|
993
948
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
994
949
|
}
|
|
995
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
950
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
996
951
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
997
952
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
998
953
|
morphAttributes(oldNode, newNode, claim);
|
|
999
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
954
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
1000
955
|
} else if (oldNode.data !== newNode.data) {
|
|
1001
956
|
oldNode.data = newNode.data;
|
|
1002
957
|
}
|
|
@@ -1039,6 +994,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1039
994
|
n = next;
|
|
1040
995
|
}
|
|
1041
996
|
}
|
|
997
|
+
function placeRange(parent, range, id, ref) {
|
|
998
|
+
if (range.nodeType === 11 ) {
|
|
999
|
+
parent.insertBefore(range, ref);
|
|
1000
|
+
} else {
|
|
1001
|
+
moveRangeBefore(parent, range, id, ref);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1042
1004
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1043
1005
|
const end = slotEnd(id);
|
|
1044
1006
|
let n = start;
|
|
@@ -1056,7 +1018,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1056
1018
|
}
|
|
1057
1019
|
return after;
|
|
1058
1020
|
}
|
|
1059
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1021
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1060
1022
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1061
1023
|
let newChild = source.firstChild;
|
|
1062
1024
|
while (newChild) {
|
|
@@ -1072,11 +1034,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1072
1034
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1073
1035
|
if (existing) {
|
|
1074
1036
|
if (ranges) ranges.delete(pid);
|
|
1075
|
-
|
|
1076
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1077
|
-
} else {
|
|
1078
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1079
|
-
}
|
|
1037
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1080
1038
|
newChild = afterRange(newChild, pid);
|
|
1081
1039
|
} else {
|
|
1082
1040
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1087,17 +1045,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1087
1045
|
if (!old) {
|
|
1088
1046
|
parent.insertBefore(newChild, boundEnd);
|
|
1089
1047
|
if (claim) claim(newChild);
|
|
1048
|
+
if (grafts) grafts.push(newChild);
|
|
1090
1049
|
newChild = nextNew;
|
|
1091
1050
|
continue;
|
|
1092
1051
|
}
|
|
1093
1052
|
if (isSlotMarker(old)) {
|
|
1094
1053
|
parent.insertBefore(newChild, old);
|
|
1095
1054
|
if (claim) claim(newChild);
|
|
1055
|
+
if (grafts) grafts.push(newChild);
|
|
1096
1056
|
newChild = nextNew;
|
|
1097
1057
|
continue;
|
|
1098
1058
|
}
|
|
1099
1059
|
if (compatible(old, newChild)) {
|
|
1100
|
-
morphNode(old, newChild, claim, ranges);
|
|
1060
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1101
1061
|
oldChild = old.nextSibling;
|
|
1102
1062
|
newChild = nextNew;
|
|
1103
1063
|
continue;
|
|
@@ -1110,13 +1070,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1110
1070
|
}
|
|
1111
1071
|
if (ahead && ahead !== boundEnd) {
|
|
1112
1072
|
parent.insertBefore(ahead, old);
|
|
1113
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1073
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1114
1074
|
newChild = nextNew;
|
|
1115
1075
|
continue;
|
|
1116
1076
|
}
|
|
1117
1077
|
}
|
|
1118
1078
|
parent.insertBefore(newChild, old);
|
|
1119
1079
|
if (claim) claim(newChild);
|
|
1080
|
+
if (grafts) grafts.push(newChild);
|
|
1120
1081
|
newChild = nextNew;
|
|
1121
1082
|
}
|
|
1122
1083
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1133,20 +1094,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1133
1094
|
oldChild = next;
|
|
1134
1095
|
}
|
|
1135
1096
|
}
|
|
1136
|
-
function
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
const
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1097
|
+
function flushGrafts(node, ranges) {
|
|
1098
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1099
|
+
let n = node.firstChild;
|
|
1100
|
+
while (n) {
|
|
1101
|
+
const id = slotStartId(n);
|
|
1102
|
+
if (id !== null) {
|
|
1103
|
+
const next = afterRange(n, id);
|
|
1104
|
+
const displaced = ranges.get(id);
|
|
1105
|
+
if (displaced) {
|
|
1106
|
+
ranges.delete(id);
|
|
1107
|
+
placeRange(node, displaced, id, n);
|
|
1108
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1109
|
+
}
|
|
1110
|
+
n = next;
|
|
1111
|
+
continue;
|
|
1148
1112
|
}
|
|
1149
|
-
|
|
1113
|
+
flushGrafts(n, ranges);
|
|
1114
|
+
n = n.nextSibling;
|
|
1150
1115
|
}
|
|
1151
1116
|
}
|
|
1152
1117
|
function stashRange(frag, start, id) {
|
|
@@ -1178,7 +1143,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1178
1143
|
if (chunk.type === "outcome") {
|
|
1179
1144
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1180
1145
|
} else {
|
|
1181
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1146
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1182
1147
|
if (perFrame) {
|
|
1183
1148
|
let v = perFrame.get(chunk.id);
|
|
1184
1149
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1192,7 +1157,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1192
1157
|
}
|
|
1193
1158
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1194
1159
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1195
|
-
const
|
|
1160
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1196
1161
|
let resolveServerComponent;
|
|
1197
1162
|
function parseServerComponent(value, ctx) {
|
|
1198
1163
|
return {
|
|
@@ -1216,7 +1181,8 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
|
|
|
1216
1181
|
stream: parseServerComponent
|
|
1217
1182
|
},
|
|
1218
1183
|
serialize(node, ctx) {
|
|
1219
|
-
|
|
1184
|
+
const registry = "self._$SC";
|
|
1185
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1220
1186
|
},
|
|
1221
1187
|
deserialize(node, ctx) {
|
|
1222
1188
|
const id = ctx.deserialize(node.id);
|
|
@@ -1241,120 +1207,79 @@ function createServerComponentHandler({
|
|
|
1241
1207
|
host,
|
|
1242
1208
|
component,
|
|
1243
1209
|
onStream,
|
|
1244
|
-
documentComponent,
|
|
1245
1210
|
intercept,
|
|
1246
1211
|
consumer = client.getFlightDataConsumer,
|
|
1247
1212
|
codec = client.getServerFunctionsCodec
|
|
1248
1213
|
}) {
|
|
1249
|
-
const
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1254
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1255
|
-
fnId,
|
|
1256
|
-
frameId,
|
|
1257
|
-
take(prev) {
|
|
1258
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1259
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1260
|
-
const root = meta.frameId;
|
|
1261
|
-
let cur = forwards.get(root) ?? root;
|
|
1262
|
-
if (cur !== root && !host.get(cur)) {
|
|
1263
|
-
forwards.delete(root);
|
|
1264
|
-
cur = root;
|
|
1265
|
-
}
|
|
1266
|
-
if (cur === frameId) return true;
|
|
1267
|
-
let frame = host.get(cur);
|
|
1268
|
-
if (!frame) return false;
|
|
1269
|
-
while (frame) {
|
|
1270
|
-
frame.rebind(frameId);
|
|
1271
|
-
frame = host.get(cur);
|
|
1272
|
-
}
|
|
1273
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1274
|
-
return true;
|
|
1275
|
-
}
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1214
|
+
const byFn = new Map();
|
|
1215
|
+
const componentFor = fnId => {
|
|
1216
|
+
let comp = byFn.get(fnId);
|
|
1217
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1278
1218
|
return comp;
|
|
1279
1219
|
};
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1220
|
+
const byAddress = new Map();
|
|
1221
|
+
const bindingFor = (address, fnId) => {
|
|
1222
|
+
let binding = byAddress.get(address);
|
|
1223
|
+
if (!binding) {
|
|
1224
|
+
const comp = componentFor(fnId);
|
|
1225
|
+
binding = props => comp(props, () => address);
|
|
1226
|
+
binding[COMPONENT_BINDING] = {
|
|
1227
|
+
component: comp,
|
|
1228
|
+
address
|
|
1286
1229
|
};
|
|
1287
|
-
byAddress.set(address,
|
|
1230
|
+
byAddress.set(address, binding);
|
|
1288
1231
|
}
|
|
1289
|
-
return
|
|
1232
|
+
return binding;
|
|
1290
1233
|
};
|
|
1291
|
-
|
|
1292
|
-
resolveServerComponent = resolveAddress;
|
|
1234
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1293
1235
|
const versions = new Map();
|
|
1294
|
-
const bump =
|
|
1295
|
-
const version = (versions.get(
|
|
1296
|
-
versions.set(
|
|
1236
|
+
const bump = address => {
|
|
1237
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1238
|
+
versions.set(address, version);
|
|
1297
1239
|
return version;
|
|
1298
1240
|
};
|
|
1299
1241
|
return {
|
|
1300
1242
|
intercept: intercept && (info => {
|
|
1301
1243
|
const hit = intercept(info);
|
|
1302
|
-
if (hit
|
|
1303
|
-
|
|
1304
|
-
byAddress.set(address, {
|
|
1305
|
-
frameId: info.id,
|
|
1306
|
-
component: brand(hit, info.id, info.id)
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
return hit;
|
|
1244
|
+
if (hit === undefined) return undefined;
|
|
1245
|
+
return bindingFor(client.frameAddress(info.id, info.args), info.id);
|
|
1310
1246
|
}),
|
|
1311
1247
|
handle(response, ctx) {
|
|
1312
1248
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1313
1249
|
const address = client.frameAddress(ctx.id, ctx.args);
|
|
1314
|
-
|
|
1315
|
-
if (!entry) {
|
|
1316
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1317
|
-
if (adopted) {
|
|
1318
|
-
entry = {
|
|
1319
|
-
frameId: ctx.id,
|
|
1320
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1321
|
-
};
|
|
1322
|
-
byAddress.set(address, entry);
|
|
1323
|
-
} else {
|
|
1324
|
-
entry = boundaryFor(address, ctx.id);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1250
|
+
const binding = bindingFor(address, ctx.id);
|
|
1327
1251
|
if (response.headers.has(client.SINGLE_FLIGHT_HEADER)) {
|
|
1328
|
-
return applyFlightResponse(response,
|
|
1252
|
+
return applyFlightResponse(response, address, binding);
|
|
1329
1253
|
}
|
|
1330
|
-
const version = bump(
|
|
1331
|
-
if (onStream) onStream(
|
|
1254
|
+
const version = bump(address);
|
|
1255
|
+
if (onStream) onStream(address, version, response);
|
|
1332
1256
|
applyFrameResponse(response, host, {
|
|
1333
|
-
as:
|
|
1257
|
+
as: address,
|
|
1334
1258
|
version
|
|
1335
1259
|
}).catch(err => host.apply({
|
|
1336
1260
|
type: "error",
|
|
1337
|
-
id:
|
|
1261
|
+
id: address,
|
|
1338
1262
|
version,
|
|
1339
1263
|
error: {
|
|
1340
1264
|
message: String(err && err.message)
|
|
1341
1265
|
}
|
|
1342
1266
|
}));
|
|
1343
|
-
return
|
|
1267
|
+
return binding;
|
|
1344
1268
|
},
|
|
1345
|
-
showing(address, functionId
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1269
|
+
showing(address, functionId) {
|
|
1270
|
+
bindingFor(address, functionId);
|
|
1271
|
+
const comp = componentFor(functionId);
|
|
1272
|
+
if (comp && (typeof comp === "function" || typeof comp === "object") && !comp[COMPONENT_BINDING]) {
|
|
1273
|
+
comp[COMPONENT_BINDING] = {
|
|
1274
|
+
component: comp,
|
|
1350
1275
|
address
|
|
1351
|
-
}
|
|
1276
|
+
};
|
|
1352
1277
|
}
|
|
1353
1278
|
}
|
|
1354
1279
|
};
|
|
1355
|
-
async function applyFlightResponse(response,
|
|
1280
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1356
1281
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1357
|
-
const as = rootId ?
|
|
1282
|
+
const as = rootId ? address : undefined;
|
|
1358
1283
|
let feed;
|
|
1359
1284
|
const source = new ReadableStream({
|
|
1360
1285
|
start(controller) {
|
|
@@ -1365,10 +1290,6 @@ function createServerComponentHandler({
|
|
|
1365
1290
|
let carried = false;
|
|
1366
1291
|
await applyFrameResponse(response, host, {
|
|
1367
1292
|
as,
|
|
1368
|
-
route: id => {
|
|
1369
|
-
const local = byAddress.get(id);
|
|
1370
|
-
return local ? local.frameId : id;
|
|
1371
|
-
},
|
|
1372
1293
|
version: frameId => {
|
|
1373
1294
|
const version = bump(frameId);
|
|
1374
1295
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1389,7 +1310,7 @@ function createServerComponentHandler({
|
|
|
1389
1310
|
if (response.headers.has(client.ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(client.REVALIDATE_HEADER)) {
|
|
1390
1311
|
throw envelope.value;
|
|
1391
1312
|
}
|
|
1392
|
-
return rootId ?
|
|
1313
|
+
return rootId ? binding : envelope.value;
|
|
1393
1314
|
}
|
|
1394
1315
|
}
|
|
1395
1316
|
|
|
@@ -1440,6 +1361,9 @@ function createJSONDataTable(options) {
|
|
|
1440
1361
|
};
|
|
1441
1362
|
}
|
|
1442
1363
|
|
|
1364
|
+
function asyncArg(value) {
|
|
1365
|
+
return value;
|
|
1366
|
+
}
|
|
1443
1367
|
let sharedHost;
|
|
1444
1368
|
const tables = new Map();
|
|
1445
1369
|
function tableFor(id) {
|
|
@@ -1516,8 +1440,26 @@ function claimRender(prefix, existing, render) {
|
|
|
1516
1440
|
function liveSlotProps(initial, ctx) {
|
|
1517
1441
|
const [args, setArgs] = solidJs.createSignal(initial);
|
|
1518
1442
|
ctx.onUpdate(next => setArgs(() => next));
|
|
1443
|
+
return slotArgsProxy(args);
|
|
1444
|
+
}
|
|
1445
|
+
function isAsyncValue(v) {
|
|
1446
|
+
return v !== null && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
1447
|
+
}
|
|
1448
|
+
function slotArgsProxy(args) {
|
|
1449
|
+
const owner = solidJs.getOwner();
|
|
1450
|
+
const asyncReads = new Map();
|
|
1519
1451
|
return new Proxy({}, {
|
|
1520
|
-
get: (_, key) =>
|
|
1452
|
+
get: (_, key) => {
|
|
1453
|
+
const v = args()[key];
|
|
1454
|
+
if (!isAsyncValue(v)) return v;
|
|
1455
|
+
let read = asyncReads.get(key);
|
|
1456
|
+
if (!read) {
|
|
1457
|
+
const make = () => solidJs.createMemo(() => args()[key]);
|
|
1458
|
+
read = owner ? solidJs.runWithOwner(owner, make) : make();
|
|
1459
|
+
asyncReads.set(key, read);
|
|
1460
|
+
}
|
|
1461
|
+
return read();
|
|
1462
|
+
},
|
|
1521
1463
|
has: (_, key) => key in args(),
|
|
1522
1464
|
ownKeys: () => Reflect.ownKeys(args()),
|
|
1523
1465
|
getOwnPropertyDescriptor: (_, key) => key in args() ? {
|
|
@@ -1535,6 +1477,7 @@ function isReactiveContent(value) {
|
|
|
1535
1477
|
}
|
|
1536
1478
|
function slotsFor(props) {
|
|
1537
1479
|
const bindings = new Map();
|
|
1480
|
+
const fillScopes = new Map();
|
|
1538
1481
|
return new Proxy({}, {
|
|
1539
1482
|
get(_, prop) {
|
|
1540
1483
|
if (typeof prop !== "string" || !(prop in props)) return undefined;
|
|
@@ -1545,6 +1488,19 @@ function slotsFor(props) {
|
|
|
1545
1488
|
bindings.delete(key);
|
|
1546
1489
|
prev.dispose();
|
|
1547
1490
|
}
|
|
1491
|
+
const prevFill = key !== undefined && fillScopes.get(key);
|
|
1492
|
+
if (prevFill) {
|
|
1493
|
+
fillScopes.delete(key);
|
|
1494
|
+
prevFill.dispose();
|
|
1495
|
+
}
|
|
1496
|
+
const fillOwner = streamInvoke ? solidJs.createOwner() : null;
|
|
1497
|
+
if (fillOwner && key !== undefined && ctx) {
|
|
1498
|
+
fillScopes.set(key, fillOwner);
|
|
1499
|
+
ctx.onCleanup(() => {
|
|
1500
|
+
if (fillScopes.get(key) === fillOwner) fillScopes.delete(key);
|
|
1501
|
+
fillOwner.dispose();
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1548
1504
|
const settle = out => {
|
|
1549
1505
|
const existing = ctx && ctx.existing || [];
|
|
1550
1506
|
if (existing.length) {
|
|
@@ -1557,26 +1513,18 @@ function slotsFor(props) {
|
|
|
1557
1513
|
const evaluate = () => {
|
|
1558
1514
|
const v = props[prop];
|
|
1559
1515
|
if (typeof v === "function" && ctx && ctx.invoked) {
|
|
1560
|
-
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotProps);
|
|
1516
|
+
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotArgsProxy(() => slotProps));
|
|
1561
1517
|
}
|
|
1562
1518
|
return v;
|
|
1563
1519
|
};
|
|
1564
1520
|
const adopted = !!(ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length);
|
|
1565
1521
|
const prefix = ctx && ctx.frame ? `sc-${ctx.frame}-${ctx.key}-` : "";
|
|
1566
|
-
const value = adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1522
|
+
const value = fillOwner ? solidJs.runWithOwner(fillOwner, () => adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate()) : adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1567
1523
|
if (!isReactiveContent(value)) {
|
|
1568
1524
|
return settle(normalizeSlotContent(value));
|
|
1569
1525
|
}
|
|
1570
1526
|
if (ctx && ctx.range) {
|
|
1571
|
-
let claim = adopted;
|
|
1572
1527
|
const source = value;
|
|
1573
|
-
const accessor = () => {
|
|
1574
|
-
if (claim) {
|
|
1575
|
-
claim = false;
|
|
1576
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1577
|
-
}
|
|
1578
|
-
return typeof source === "function" ? source() : source;
|
|
1579
|
-
};
|
|
1580
1528
|
const owner = solidJs.createOwner();
|
|
1581
1529
|
bindings.set(key, owner);
|
|
1582
1530
|
ctx.onCleanup(() => {
|
|
@@ -1584,7 +1532,8 @@ function slotsFor(props) {
|
|
|
1584
1532
|
owner.dispose();
|
|
1585
1533
|
});
|
|
1586
1534
|
const end = ctx.range.end;
|
|
1587
|
-
|
|
1535
|
+
const bind = () => web$1.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1536
|
+
solidJs.runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1588
1537
|
return undefined;
|
|
1589
1538
|
}
|
|
1590
1539
|
return settle(normalizeSlotContent(value));
|
|
@@ -1595,24 +1544,61 @@ function slotsFor(props) {
|
|
|
1595
1544
|
function revealSeam(owner) {
|
|
1596
1545
|
return seam => solidJs.runWithOwner(owner, () => web$1.insert(seam.before.parentNode, solidJs.createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
|
|
1597
1546
|
}
|
|
1547
|
+
let streamInvoke = false;
|
|
1598
1548
|
function boundaryScope(owner) {
|
|
1599
|
-
return fn =>
|
|
1549
|
+
return fn => {
|
|
1550
|
+
if (solidJs.getOwner()) return fn();
|
|
1551
|
+
streamInvoke = true;
|
|
1552
|
+
try {
|
|
1553
|
+
return solidJs.runWithOwner(owner, fn);
|
|
1554
|
+
} finally {
|
|
1555
|
+
streamInvoke = false;
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1600
1558
|
}
|
|
1601
|
-
function boundaryComponent(host,
|
|
1602
|
-
return props => {
|
|
1559
|
+
function boundaryComponent(host, fnId) {
|
|
1560
|
+
return (props, binding) => {
|
|
1603
1561
|
const owner = solidJs.getOwner();
|
|
1562
|
+
const id = binding ? binding() : fnId;
|
|
1563
|
+
let applied = !tables.has(id);
|
|
1564
|
+
let release;
|
|
1565
|
+
const arm = () => new Promise(r => release = r);
|
|
1566
|
+
const mountGate = applied ? undefined : arm();
|
|
1567
|
+
let setGate;
|
|
1604
1568
|
const {
|
|
1605
1569
|
element,
|
|
1570
|
+
frame,
|
|
1606
1571
|
dispose
|
|
1607
1572
|
} = createFrameElement({
|
|
1608
1573
|
host,
|
|
1609
1574
|
id,
|
|
1610
1575
|
slots: slotsFor(props),
|
|
1611
1576
|
ownerScope: boundaryScope(owner),
|
|
1612
|
-
reveal: revealSeam(owner)
|
|
1577
|
+
reveal: revealSeam(owner),
|
|
1578
|
+
onApply: () => {
|
|
1579
|
+
applied = true;
|
|
1580
|
+
if (release) {
|
|
1581
|
+
release();
|
|
1582
|
+
release = undefined;
|
|
1583
|
+
}
|
|
1584
|
+
setGate && setGate(undefined);
|
|
1585
|
+
}
|
|
1613
1586
|
});
|
|
1587
|
+
const [gatePromise, setGatePromise] = solidJs.createSignal(applied ? undefined : mountGate);
|
|
1588
|
+
setGate = setGatePromise;
|
|
1589
|
+
if (binding) {
|
|
1590
|
+
solidJs.createRenderEffect(binding, (address, prev) => {
|
|
1591
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1592
|
+
applied = false;
|
|
1593
|
+
setGatePromise(arm());
|
|
1594
|
+
}
|
|
1595
|
+
frame.rebind(address);
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1614
1598
|
solidJs.onCleanup(dispose);
|
|
1615
|
-
return element;
|
|
1599
|
+
if (applied && !binding) return element;
|
|
1600
|
+
const gate = solidJs.createMemo(() => gatePromise());
|
|
1601
|
+
return solidJs.createMemo(() => (gate(), element));
|
|
1616
1602
|
};
|
|
1617
1603
|
}
|
|
1618
1604
|
const claimedBoundaries = new Set();
|
|
@@ -1632,51 +1618,76 @@ function findBoundaryElement(id) {
|
|
|
1632
1618
|
return boundaryIndex.get(id);
|
|
1633
1619
|
}
|
|
1634
1620
|
const boundaryWaiters = new Map();
|
|
1635
|
-
function
|
|
1621
|
+
function boundaryMayArrive() {
|
|
1636
1622
|
const hy = globalThis._$HY;
|
|
1637
|
-
|
|
1623
|
+
if (!hy) return false;
|
|
1624
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1638
1625
|
}
|
|
1639
1626
|
function installRevealHook() {
|
|
1640
1627
|
const hy = globalThis._$HY;
|
|
1641
|
-
if (!hy || hy.$sc) return;
|
|
1628
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1642
1629
|
hy.$sc = true;
|
|
1643
|
-
|
|
1644
|
-
hy.fe = (fragmentId, parent) => {
|
|
1645
|
-
if (prev) prev(fragmentId, parent);
|
|
1630
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1646
1631
|
if (!boundaryIndex) return;
|
|
1647
1632
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1648
|
-
if (
|
|
1649
|
-
|
|
1633
|
+
if (root) indexBoundaries(root);
|
|
1634
|
+
if (!boundaryWaiters.size) return;
|
|
1635
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1650
1636
|
for (const [id, notify] of boundaryWaiters) {
|
|
1651
|
-
const el = boundaryIndex.get(id);
|
|
1652
|
-
if (!el) continue;
|
|
1637
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1638
|
+
if (!el && !exhausted) continue;
|
|
1653
1639
|
boundaryWaiters.delete(id);
|
|
1654
1640
|
notify(el);
|
|
1655
1641
|
}
|
|
1656
|
-
};
|
|
1642
|
+
});
|
|
1657
1643
|
}
|
|
1658
|
-
function documentBoundary(host, id, props) {
|
|
1644
|
+
function documentBoundary(host, id, props, binding) {
|
|
1645
|
+
installRevealHook();
|
|
1659
1646
|
const claimed = claimedBoundaries.has(id);
|
|
1660
1647
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1661
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1662
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1648
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1649
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1663
1650
|
const owner = solidJs.getOwner();
|
|
1664
1651
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1665
1652
|
solidJs.onCleanup(() => boundaryWaiters.delete(id));
|
|
1666
|
-
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1653
|
+
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1654
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1667
1655
|
}
|
|
1668
|
-
return boundaryComponent(host, id)(props);
|
|
1656
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1669
1657
|
}
|
|
1670
|
-
function
|
|
1658
|
+
function documentAddress(id) {
|
|
1659
|
+
const records = globalThis._$SC?.a;
|
|
1660
|
+
if (records) {
|
|
1661
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1662
|
+
}
|
|
1663
|
+
return id;
|
|
1664
|
+
}
|
|
1665
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1671
1666
|
claimedBoundaries.add(id);
|
|
1672
|
-
const
|
|
1673
|
-
|
|
1667
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1668
|
+
const appliedRecords = new Set();
|
|
1669
|
+
const claimedFragments = new Set();
|
|
1670
|
+
const claimRegionFragments = root => {
|
|
1671
|
+
const fr = globalThis._$HY?.fr;
|
|
1672
|
+
if (!fr || !fr.claim) return;
|
|
1673
|
+
root.querySelectorAll('template[id^="pl-"]').forEach(tpl => {
|
|
1674
|
+
const fragId = tpl.id.slice(3);
|
|
1675
|
+
if (claimedFragments.has(fragId)) return;
|
|
1676
|
+
claimedFragments.add(fragId);
|
|
1677
|
+
fr.claim(fragId);
|
|
1678
|
+
});
|
|
1679
|
+
};
|
|
1680
|
+
const drainRecords = () => {
|
|
1681
|
+
const hy = globalThis._$HY;
|
|
1682
|
+
if (!hy || !hy.r) return;
|
|
1674
1683
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1675
1684
|
for (const key of Object.keys(hy.r)) {
|
|
1685
|
+
if (appliedRecords.has(key)) continue;
|
|
1676
1686
|
if (key.startsWith(slotPrefix)) {
|
|
1687
|
+
appliedRecords.add(key);
|
|
1677
1688
|
host.apply({
|
|
1678
1689
|
type: "slot",
|
|
1679
|
-
id,
|
|
1690
|
+
id: address,
|
|
1680
1691
|
version: 0,
|
|
1681
1692
|
key: key.slice(slotPrefix.length),
|
|
1682
1693
|
args: hy.r[key]
|
|
@@ -1684,6 +1695,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1684
1695
|
} else if (key.startsWith("sc:region:")) {
|
|
1685
1696
|
const childId = key.slice("sc:region:".length);
|
|
1686
1697
|
if (childId.startsWith(id + ".")) {
|
|
1698
|
+
appliedRecords.add(key);
|
|
1687
1699
|
const val = hy.r[key];
|
|
1688
1700
|
const apply = html => host.apply({
|
|
1689
1701
|
type: "html",
|
|
@@ -1695,16 +1707,58 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1695
1707
|
}
|
|
1696
1708
|
}
|
|
1697
1709
|
}
|
|
1698
|
-
}
|
|
1710
|
+
};
|
|
1711
|
+
claimRegionFragments(el);
|
|
1712
|
+
const fr = globalThis._$HY?.fr;
|
|
1713
|
+
const unsubscribe = fr ? fr.subscribe((_fragId, parent) => {
|
|
1714
|
+
if (fr.claim && parent && el.contains(parent)) claimRegionFragments(parent);
|
|
1715
|
+
drainRecords();
|
|
1716
|
+
}) : undefined;
|
|
1717
|
+
solidJs.onCleanup(() => {
|
|
1718
|
+
unsubscribe && unsubscribe();
|
|
1719
|
+
if (fr && fr.release) for (const fragId of claimedFragments) fr.release(fragId);
|
|
1720
|
+
});
|
|
1721
|
+
drainRecords();
|
|
1699
1722
|
const owner = solidJs.getOwner();
|
|
1723
|
+
let release;
|
|
1724
|
+
let setGate;
|
|
1700
1725
|
const frame = createFrame(el, {
|
|
1701
1726
|
adopt: true,
|
|
1702
1727
|
host,
|
|
1703
|
-
id,
|
|
1728
|
+
id: address,
|
|
1704
1729
|
slots: slotsFor(props),
|
|
1705
1730
|
ownerScope: boundaryScope(owner),
|
|
1706
|
-
reveal: revealSeam(owner)
|
|
1731
|
+
reveal: revealSeam(owner),
|
|
1732
|
+
onApply: () => {
|
|
1733
|
+
if (release) {
|
|
1734
|
+
release();
|
|
1735
|
+
release = undefined;
|
|
1736
|
+
}
|
|
1737
|
+
setGate && setGate(undefined);
|
|
1738
|
+
},
|
|
1739
|
+
...{
|
|
1740
|
+
recordsPending: () => {
|
|
1741
|
+
if (document.readyState === "loading") return true;
|
|
1742
|
+
const hy = globalThis._$HY;
|
|
1743
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1744
|
+
},
|
|
1745
|
+
drainRecords,
|
|
1746
|
+
claimScope: id
|
|
1747
|
+
}
|
|
1707
1748
|
});
|
|
1749
|
+
if (binding) {
|
|
1750
|
+
const arm = () => new Promise(r => release = r);
|
|
1751
|
+
const [gatePromise, setGatePromise] = solidJs.createSignal(undefined);
|
|
1752
|
+
setGate = setGatePromise;
|
|
1753
|
+
const gate = solidJs.createMemo(() => gatePromise());
|
|
1754
|
+
solidJs.createRenderEffect(binding, (address, prev) => {
|
|
1755
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1756
|
+
setGatePromise(arm());
|
|
1757
|
+
}
|
|
1758
|
+
frame.rebind(address);
|
|
1759
|
+
});
|
|
1760
|
+
solidJs.createRenderEffect(() => (gate(), undefined), () => {});
|
|
1761
|
+
}
|
|
1708
1762
|
solidJs.onCleanup(() => frame.dispose());
|
|
1709
1763
|
return el;
|
|
1710
1764
|
}
|
|
@@ -1719,17 +1773,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1719
1773
|
g._$SC.a[a] = i;
|
|
1720
1774
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1721
1775
|
}
|
|
1722
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1776
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1723
1777
|
}
|
|
1724
1778
|
};
|
|
1725
1779
|
}
|
|
1726
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1780
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1727
1781
|
installRevealHook();
|
|
1728
1782
|
const handler = createServerComponentHandler({
|
|
1729
1783
|
host,
|
|
1730
|
-
component:
|
|
1731
|
-
onStream:
|
|
1732
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1784
|
+
component: fnId => g._$SC.r(fnId),
|
|
1785
|
+
onStream: address => beginStream(address),
|
|
1733
1786
|
intercept: ({
|
|
1734
1787
|
id
|
|
1735
1788
|
}) => {
|
|
@@ -1737,7 +1790,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1737
1790
|
return g._$SC.r(id);
|
|
1738
1791
|
}
|
|
1739
1792
|
});
|
|
1740
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1793
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1741
1794
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1742
1795
|
for (const address in records) showing(address, records[address]);
|
|
1743
1796
|
g._$SC.reg = showing;
|
|
@@ -1749,10 +1802,10 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1749
1802
|
exports.FRAME_APPLIED_EVENT = FRAME_APPLIED_EVENT;
|
|
1750
1803
|
exports.FRAME_STREAM_HEADER = FRAME_STREAM_HEADER;
|
|
1751
1804
|
exports.applyFrameResponse = applyFrameResponse;
|
|
1805
|
+
exports.asyncArg = asyncArg;
|
|
1752
1806
|
exports.createFrame = createFrame;
|
|
1753
1807
|
exports.createFrameElement = createFrameElement;
|
|
1754
1808
|
exports.createFrameHost = createFrameHost;
|
|
1755
|
-
exports.createJSONDataTable = createJSONDataTable;
|
|
1756
1809
|
exports.createServerComponentHandler = createServerComponentHandler;
|
|
1757
1810
|
exports.getFrameHost = getFrameHost;
|
|
1758
1811
|
exports.installServerComponents = installServerComponents;
|