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