@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
package/frames/dist/client.js
CHANGED
|
@@ -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;
|
|
@@ -725,12 +660,7 @@ class FrameImpl {
|
|
|
725
660
|
const content = this.#store[`seg:${name}`];
|
|
726
661
|
const closing = rangeClose(tpl, placeholderId(name));
|
|
727
662
|
const parent = tpl.parentNode;
|
|
728
|
-
|
|
729
|
-
while (n && n !== closing) {
|
|
730
|
-
const next = n.nextSibling;
|
|
731
|
-
parent.removeChild(n);
|
|
732
|
-
n = next;
|
|
733
|
-
}
|
|
663
|
+
removeUntil(parent, tpl.nextSibling, closing);
|
|
734
664
|
if (this.#options.reveal) {
|
|
735
665
|
const fallbackFrag = tpl.content.cloneNode(true);
|
|
736
666
|
this.#claimTree(fallbackFrag);
|
|
@@ -779,9 +709,7 @@ function createFrameElement(options) {
|
|
|
779
709
|
const frame = new FrameImpl(el, null, null, options);
|
|
780
710
|
return {
|
|
781
711
|
element: el,
|
|
782
|
-
|
|
783
|
-
return frame;
|
|
784
|
-
},
|
|
712
|
+
frame,
|
|
785
713
|
dispose() {
|
|
786
714
|
frame.dispose();
|
|
787
715
|
el.remove();
|
|
@@ -801,15 +729,30 @@ function segmentName(key) {
|
|
|
801
729
|
const m = /^seg:([^:]+)$/.exec(key);
|
|
802
730
|
return m ? m[1] : null;
|
|
803
731
|
}
|
|
732
|
+
function isAsyncLike(v) {
|
|
733
|
+
return !!v && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
734
|
+
}
|
|
804
735
|
function propOf(occurrence) {
|
|
805
736
|
const hash = occurrence.indexOf("#");
|
|
806
737
|
return hash === -1 ? occurrence : occurrence.slice(0, hash);
|
|
807
738
|
}
|
|
808
739
|
function isDataRef(value) {
|
|
809
|
-
return
|
|
740
|
+
return !!value && typeof value.$ref === "string";
|
|
810
741
|
}
|
|
811
742
|
function isFrameRef(value) {
|
|
812
|
-
return
|
|
743
|
+
return !!value && typeof value.$frame === "string";
|
|
744
|
+
}
|
|
745
|
+
function disposeRegions(regions) {
|
|
746
|
+
for (const {
|
|
747
|
+
frame
|
|
748
|
+
} of regions.values()) frame?.dispose();
|
|
749
|
+
}
|
|
750
|
+
function removeUntil(parent, n, stop) {
|
|
751
|
+
while (n && n !== stop) {
|
|
752
|
+
const next = n.nextSibling;
|
|
753
|
+
parent.removeChild(n);
|
|
754
|
+
n = next;
|
|
755
|
+
}
|
|
813
756
|
}
|
|
814
757
|
function parseFragment(html) {
|
|
815
758
|
const template = document.createElement("template");
|
|
@@ -817,9 +760,8 @@ function parseFragment(html) {
|
|
|
817
760
|
return template.content;
|
|
818
761
|
}
|
|
819
762
|
function findHeadElement(selector, attr, value) {
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
if (nodes[i].getAttribute(attr) === value) return nodes[i];
|
|
763
|
+
for (const node of document.head.querySelectorAll(selector)) {
|
|
764
|
+
if (node.getAttribute(attr) === value) return node;
|
|
823
765
|
}
|
|
824
766
|
return null;
|
|
825
767
|
}
|
|
@@ -868,7 +810,7 @@ function applyInlineStyles(inlineStyles) {
|
|
|
868
810
|
}
|
|
869
811
|
}
|
|
870
812
|
function isPlaceholderStart(node, id) {
|
|
871
|
-
return node.
|
|
813
|
+
return node.tagName === "TEMPLATE" && node.id === id;
|
|
872
814
|
}
|
|
873
815
|
function rangeClose(start, id) {
|
|
874
816
|
let n = start.nextSibling;
|
|
@@ -901,11 +843,11 @@ function collectSlots(n, end, out) {
|
|
|
901
843
|
n = n.nextSibling;
|
|
902
844
|
}
|
|
903
845
|
}
|
|
904
|
-
function collectRegionElements(node, regions
|
|
846
|
+
function collectRegionElements(node, regions) {
|
|
905
847
|
if (node.nodeType !== ELEMENT_NODE) return;
|
|
906
848
|
if (isFrameElement(node)) {
|
|
907
849
|
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
908
|
-
if (childId && childId.
|
|
850
|
+
if (childId && childId.includes(".")) {
|
|
909
851
|
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
910
852
|
if (!regions.has(argKey)) {
|
|
911
853
|
regions.set(argKey, {
|
|
@@ -918,12 +860,27 @@ function collectRegionElements(node, regions, prefix) {
|
|
|
918
860
|
}
|
|
919
861
|
return;
|
|
920
862
|
}
|
|
921
|
-
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions
|
|
863
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
922
864
|
}
|
|
923
865
|
function renameRegion(entry, childId) {
|
|
924
866
|
entry.childId = childId;
|
|
925
867
|
if (entry.frame) entry.frame.rebind(childId);else entry.element.setAttribute(FRAME_ID_ATTR, childId);
|
|
926
868
|
}
|
|
869
|
+
function eachInRange(start, key, cb) {
|
|
870
|
+
const end = slotEnd(key);
|
|
871
|
+
let n = start.nextSibling;
|
|
872
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
|
|
873
|
+
const next = n.nextSibling;
|
|
874
|
+
cb(n);
|
|
875
|
+
n = next;
|
|
876
|
+
}
|
|
877
|
+
return n;
|
|
878
|
+
}
|
|
879
|
+
function clearStreamRecords(records, root) {
|
|
880
|
+
for (const key in records) {
|
|
881
|
+
if (key.startsWith("seg:") || key === ":error" || root && key === "") delete records[key];
|
|
882
|
+
}
|
|
883
|
+
}
|
|
927
884
|
function argsEquivalent(a, b) {
|
|
928
885
|
if (a === b) return true;
|
|
929
886
|
if (!a || !b) return false;
|
|
@@ -934,9 +891,7 @@ function argsEquivalent(a, b) {
|
|
|
934
891
|
const va = a[key];
|
|
935
892
|
const vb = b[key];
|
|
936
893
|
if (va === vb) continue;
|
|
937
|
-
if (va &&
|
|
938
|
-
continue;
|
|
939
|
-
}
|
|
894
|
+
if (isFrameRef(va) && va.$frame === vb?.$frame) continue;
|
|
940
895
|
return false;
|
|
941
896
|
}
|
|
942
897
|
return true;
|
|
@@ -986,11 +941,11 @@ function morphAttributes(oldEl, newEl, claim) {
|
|
|
986
941
|
}
|
|
987
942
|
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
988
943
|
}
|
|
989
|
-
function morphNode(oldNode, newNode, claim, ranges) {
|
|
944
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
990
945
|
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
991
946
|
if (oldNode.hasAttribute("data-preserve")) return;
|
|
992
947
|
morphAttributes(oldNode, newNode, claim);
|
|
993
|
-
reconcileChildren(oldNode, newNode, null, null, claim, ranges);
|
|
948
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
994
949
|
} else if (oldNode.data !== newNode.data) {
|
|
995
950
|
oldNode.data = newNode.data;
|
|
996
951
|
}
|
|
@@ -1024,6 +979,13 @@ function moveRangeBefore(parent, start, id, ref) {
|
|
|
1024
979
|
n = next;
|
|
1025
980
|
}
|
|
1026
981
|
}
|
|
982
|
+
function placeRange(parent, range, id, ref) {
|
|
983
|
+
if (range.nodeType === 11 ) {
|
|
984
|
+
parent.insertBefore(range, ref);
|
|
985
|
+
} else {
|
|
986
|
+
moveRangeBefore(parent, range, id, ref);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
1027
989
|
function adoptRange(parent, start, id, ref, claim) {
|
|
1028
990
|
const end = slotEnd(id);
|
|
1029
991
|
let n = start;
|
|
@@ -1041,7 +1003,7 @@ function adoptRange(parent, start, id, ref, claim) {
|
|
|
1041
1003
|
}
|
|
1042
1004
|
return after;
|
|
1043
1005
|
}
|
|
1044
|
-
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null) {
|
|
1006
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1045
1007
|
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1046
1008
|
let newChild = source.firstChild;
|
|
1047
1009
|
while (newChild) {
|
|
@@ -1057,11 +1019,7 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1057
1019
|
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1058
1020
|
if (existing) {
|
|
1059
1021
|
if (ranges) ranges.delete(pid);
|
|
1060
|
-
|
|
1061
|
-
parent.insertBefore(existing, old ?? boundEnd);
|
|
1062
|
-
} else {
|
|
1063
|
-
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1064
|
-
}
|
|
1022
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1065
1023
|
newChild = afterRange(newChild, pid);
|
|
1066
1024
|
} else {
|
|
1067
1025
|
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
@@ -1072,17 +1030,19 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1072
1030
|
if (!old) {
|
|
1073
1031
|
parent.insertBefore(newChild, boundEnd);
|
|
1074
1032
|
if (claim) claim(newChild);
|
|
1033
|
+
if (grafts) grafts.push(newChild);
|
|
1075
1034
|
newChild = nextNew;
|
|
1076
1035
|
continue;
|
|
1077
1036
|
}
|
|
1078
1037
|
if (isSlotMarker(old)) {
|
|
1079
1038
|
parent.insertBefore(newChild, old);
|
|
1080
1039
|
if (claim) claim(newChild);
|
|
1040
|
+
if (grafts) grafts.push(newChild);
|
|
1081
1041
|
newChild = nextNew;
|
|
1082
1042
|
continue;
|
|
1083
1043
|
}
|
|
1084
1044
|
if (compatible(old, newChild)) {
|
|
1085
|
-
morphNode(old, newChild, claim, ranges);
|
|
1045
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1086
1046
|
oldChild = old.nextSibling;
|
|
1087
1047
|
newChild = nextNew;
|
|
1088
1048
|
continue;
|
|
@@ -1095,13 +1055,14 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1095
1055
|
}
|
|
1096
1056
|
if (ahead && ahead !== boundEnd) {
|
|
1097
1057
|
parent.insertBefore(ahead, old);
|
|
1098
|
-
morphNode(ahead, newChild, claim, ranges);
|
|
1058
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1099
1059
|
newChild = nextNew;
|
|
1100
1060
|
continue;
|
|
1101
1061
|
}
|
|
1102
1062
|
}
|
|
1103
1063
|
parent.insertBefore(newChild, old);
|
|
1104
1064
|
if (claim) claim(newChild);
|
|
1065
|
+
if (grafts) grafts.push(newChild);
|
|
1105
1066
|
newChild = nextNew;
|
|
1106
1067
|
}
|
|
1107
1068
|
while (oldChild && oldChild !== boundEnd) {
|
|
@@ -1118,20 +1079,24 @@ function reconcileChildren(parent, source, boundStart = null, boundEnd = null, c
|
|
|
1118
1079
|
oldChild = next;
|
|
1119
1080
|
}
|
|
1120
1081
|
}
|
|
1121
|
-
function
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const
|
|
1126
|
-
if (
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1082
|
+
function flushGrafts(node, ranges) {
|
|
1083
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1084
|
+
let n = node.firstChild;
|
|
1085
|
+
while (n) {
|
|
1086
|
+
const id = slotStartId(n);
|
|
1087
|
+
if (id !== null) {
|
|
1088
|
+
const next = afterRange(n, id);
|
|
1089
|
+
const displaced = ranges.get(id);
|
|
1090
|
+
if (displaced) {
|
|
1091
|
+
ranges.delete(id);
|
|
1092
|
+
placeRange(node, displaced, id, n);
|
|
1093
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1094
|
+
}
|
|
1095
|
+
n = next;
|
|
1096
|
+
continue;
|
|
1133
1097
|
}
|
|
1134
|
-
|
|
1098
|
+
flushGrafts(n, ranges);
|
|
1099
|
+
n = n.nextSibling;
|
|
1135
1100
|
}
|
|
1136
1101
|
}
|
|
1137
1102
|
function stashRange(frag, start, id) {
|
|
@@ -1163,7 +1128,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1163
1128
|
if (chunk.type === "outcome") {
|
|
1164
1129
|
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1165
1130
|
} else {
|
|
1166
|
-
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1131
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1167
1132
|
if (perFrame) {
|
|
1168
1133
|
let v = perFrame.get(chunk.id);
|
|
1169
1134
|
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
@@ -1177,7 +1142,7 @@ async function applyFrameResponse(response, host, options = {}) {
|
|
|
1177
1142
|
}
|
|
1178
1143
|
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1179
1144
|
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1180
|
-
const
|
|
1145
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1181
1146
|
let resolveServerComponent;
|
|
1182
1147
|
function parseServerComponent(value, ctx) {
|
|
1183
1148
|
return {
|
|
@@ -1201,7 +1166,8 @@ const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
|
1201
1166
|
stream: parseServerComponent
|
|
1202
1167
|
},
|
|
1203
1168
|
serialize(node, ctx) {
|
|
1204
|
-
|
|
1169
|
+
const registry = "self._$SC";
|
|
1170
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1205
1171
|
},
|
|
1206
1172
|
deserialize(node, ctx) {
|
|
1207
1173
|
const id = ctx.deserialize(node.id);
|
|
@@ -1226,120 +1192,79 @@ function createServerComponentHandler({
|
|
|
1226
1192
|
host,
|
|
1227
1193
|
component,
|
|
1228
1194
|
onStream,
|
|
1229
|
-
documentComponent,
|
|
1230
1195
|
intercept,
|
|
1231
1196
|
consumer = getFlightDataConsumer,
|
|
1232
1197
|
codec = getServerFunctionsCodec
|
|
1233
1198
|
}) {
|
|
1234
|
-
const
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if (brandable && !comp[COMPONENT_HANDOFF]) {
|
|
1239
|
-
comp[COMPONENT_HANDOFF] = {
|
|
1240
|
-
fnId,
|
|
1241
|
-
frameId,
|
|
1242
|
-
take(prev) {
|
|
1243
|
-
const meta = prev !== null && (typeof prev === "function" || typeof prev === "object") && prev[COMPONENT_HANDOFF];
|
|
1244
|
-
if (!meta || meta.fnId !== fnId) return false;
|
|
1245
|
-
const root = meta.frameId;
|
|
1246
|
-
let cur = forwards.get(root) ?? root;
|
|
1247
|
-
if (cur !== root && !host.get(cur)) {
|
|
1248
|
-
forwards.delete(root);
|
|
1249
|
-
cur = root;
|
|
1250
|
-
}
|
|
1251
|
-
if (cur === frameId) return true;
|
|
1252
|
-
let frame = host.get(cur);
|
|
1253
|
-
if (!frame) return false;
|
|
1254
|
-
while (frame) {
|
|
1255
|
-
frame.rebind(frameId);
|
|
1256
|
-
frame = host.get(cur);
|
|
1257
|
-
}
|
|
1258
|
-
if (frameId === root) forwards.delete(root);else forwards.set(root, frameId);
|
|
1259
|
-
return true;
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1199
|
+
const byFn = new Map();
|
|
1200
|
+
const componentFor = fnId => {
|
|
1201
|
+
let comp = byFn.get(fnId);
|
|
1202
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1263
1203
|
return comp;
|
|
1264
1204
|
};
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1205
|
+
const byAddress = new Map();
|
|
1206
|
+
const bindingFor = (address, fnId) => {
|
|
1207
|
+
let binding = byAddress.get(address);
|
|
1208
|
+
if (!binding) {
|
|
1209
|
+
const comp = componentFor(fnId);
|
|
1210
|
+
binding = props => comp(props, () => address);
|
|
1211
|
+
binding[COMPONENT_BINDING] = {
|
|
1212
|
+
component: comp,
|
|
1213
|
+
address
|
|
1271
1214
|
};
|
|
1272
|
-
byAddress.set(address,
|
|
1215
|
+
byAddress.set(address, binding);
|
|
1273
1216
|
}
|
|
1274
|
-
return
|
|
1217
|
+
return binding;
|
|
1275
1218
|
};
|
|
1276
|
-
|
|
1277
|
-
resolveServerComponent = resolveAddress;
|
|
1219
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1278
1220
|
const versions = new Map();
|
|
1279
|
-
const bump =
|
|
1280
|
-
const version = (versions.get(
|
|
1281
|
-
versions.set(
|
|
1221
|
+
const bump = address => {
|
|
1222
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1223
|
+
versions.set(address, version);
|
|
1282
1224
|
return version;
|
|
1283
1225
|
};
|
|
1284
1226
|
return {
|
|
1285
1227
|
intercept: intercept && (info => {
|
|
1286
1228
|
const hit = intercept(info);
|
|
1287
|
-
if (hit
|
|
1288
|
-
|
|
1289
|
-
byAddress.set(address, {
|
|
1290
|
-
frameId: info.id,
|
|
1291
|
-
component: brand(hit, info.id, info.id)
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
return hit;
|
|
1229
|
+
if (hit === undefined) return undefined;
|
|
1230
|
+
return bindingFor(frameAddress(info.id, info.args), info.id);
|
|
1295
1231
|
}),
|
|
1296
1232
|
handle(response, ctx) {
|
|
1297
1233
|
if (!isFrameStreamResponse(response)) return undefined;
|
|
1298
1234
|
const address = frameAddress(ctx.id, ctx.args);
|
|
1299
|
-
|
|
1300
|
-
if (!entry) {
|
|
1301
|
-
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1302
|
-
if (adopted) {
|
|
1303
|
-
entry = {
|
|
1304
|
-
frameId: ctx.id,
|
|
1305
|
-
component: brand(adopted, ctx.id, ctx.id)
|
|
1306
|
-
};
|
|
1307
|
-
byAddress.set(address, entry);
|
|
1308
|
-
} else {
|
|
1309
|
-
entry = boundaryFor(address, ctx.id);
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1235
|
+
const binding = bindingFor(address, ctx.id);
|
|
1312
1236
|
if (response.headers.has(SINGLE_FLIGHT_HEADER)) {
|
|
1313
|
-
return applyFlightResponse(response,
|
|
1237
|
+
return applyFlightResponse(response, address, binding);
|
|
1314
1238
|
}
|
|
1315
|
-
const version = bump(
|
|
1316
|
-
if (onStream) onStream(
|
|
1239
|
+
const version = bump(address);
|
|
1240
|
+
if (onStream) onStream(address, version, response);
|
|
1317
1241
|
applyFrameResponse(response, host, {
|
|
1318
|
-
as:
|
|
1242
|
+
as: address,
|
|
1319
1243
|
version
|
|
1320
1244
|
}).catch(err => host.apply({
|
|
1321
1245
|
type: "error",
|
|
1322
|
-
id:
|
|
1246
|
+
id: address,
|
|
1323
1247
|
version,
|
|
1324
1248
|
error: {
|
|
1325
1249
|
message: String(err && err.message)
|
|
1326
1250
|
}
|
|
1327
1251
|
}));
|
|
1328
|
-
return
|
|
1252
|
+
return binding;
|
|
1329
1253
|
},
|
|
1330
|
-
showing(address, functionId
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1254
|
+
showing(address, functionId) {
|
|
1255
|
+
bindingFor(address, functionId);
|
|
1256
|
+
const comp = componentFor(functionId);
|
|
1257
|
+
if (comp && (typeof comp === "function" || typeof comp === "object") && !comp[COMPONENT_BINDING]) {
|
|
1258
|
+
comp[COMPONENT_BINDING] = {
|
|
1259
|
+
component: comp,
|
|
1335
1260
|
address
|
|
1336
|
-
}
|
|
1261
|
+
};
|
|
1337
1262
|
}
|
|
1338
1263
|
}
|
|
1339
1264
|
};
|
|
1340
|
-
async function applyFlightResponse(response,
|
|
1265
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1341
1266
|
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1342
|
-
const as = rootId ?
|
|
1267
|
+
const as = rootId ? address : undefined;
|
|
1343
1268
|
let feed;
|
|
1344
1269
|
const source = new ReadableStream({
|
|
1345
1270
|
start(controller) {
|
|
@@ -1350,10 +1275,6 @@ function createServerComponentHandler({
|
|
|
1350
1275
|
let carried = false;
|
|
1351
1276
|
await applyFrameResponse(response, host, {
|
|
1352
1277
|
as,
|
|
1353
|
-
route: id => {
|
|
1354
|
-
const local = byAddress.get(id);
|
|
1355
|
-
return local ? local.frameId : id;
|
|
1356
|
-
},
|
|
1357
1278
|
version: frameId => {
|
|
1358
1279
|
const version = bump(frameId);
|
|
1359
1280
|
if (onStream) onStream(frameId, version, response);
|
|
@@ -1374,7 +1295,7 @@ function createServerComponentHandler({
|
|
|
1374
1295
|
if (response.headers.has(ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(REVALIDATE_HEADER)) {
|
|
1375
1296
|
throw envelope.value;
|
|
1376
1297
|
}
|
|
1377
|
-
return rootId ?
|
|
1298
|
+
return rootId ? binding : envelope.value;
|
|
1378
1299
|
}
|
|
1379
1300
|
}
|
|
1380
1301
|
|
|
@@ -1425,6 +1346,9 @@ function createJSONDataTable(options) {
|
|
|
1425
1346
|
};
|
|
1426
1347
|
}
|
|
1427
1348
|
|
|
1349
|
+
function asyncArg(value) {
|
|
1350
|
+
return value;
|
|
1351
|
+
}
|
|
1428
1352
|
let sharedHost;
|
|
1429
1353
|
const tables = new Map();
|
|
1430
1354
|
function tableFor(id) {
|
|
@@ -1501,8 +1425,26 @@ function claimRender(prefix, existing, render) {
|
|
|
1501
1425
|
function liveSlotProps(initial, ctx) {
|
|
1502
1426
|
const [args, setArgs] = createSignal(initial);
|
|
1503
1427
|
ctx.onUpdate(next => setArgs(() => next));
|
|
1428
|
+
return slotArgsProxy(args);
|
|
1429
|
+
}
|
|
1430
|
+
function isAsyncValue(v) {
|
|
1431
|
+
return v !== null && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
1432
|
+
}
|
|
1433
|
+
function slotArgsProxy(args) {
|
|
1434
|
+
const owner = getOwner();
|
|
1435
|
+
const asyncReads = new Map();
|
|
1504
1436
|
return new Proxy({}, {
|
|
1505
|
-
get: (_, key) =>
|
|
1437
|
+
get: (_, key) => {
|
|
1438
|
+
const v = args()[key];
|
|
1439
|
+
if (!isAsyncValue(v)) return v;
|
|
1440
|
+
let read = asyncReads.get(key);
|
|
1441
|
+
if (!read) {
|
|
1442
|
+
const make = () => createMemo(() => args()[key]);
|
|
1443
|
+
read = owner ? runWithOwner(owner, make) : make();
|
|
1444
|
+
asyncReads.set(key, read);
|
|
1445
|
+
}
|
|
1446
|
+
return read();
|
|
1447
|
+
},
|
|
1506
1448
|
has: (_, key) => key in args(),
|
|
1507
1449
|
ownKeys: () => Reflect.ownKeys(args()),
|
|
1508
1450
|
getOwnPropertyDescriptor: (_, key) => key in args() ? {
|
|
@@ -1520,6 +1462,7 @@ function isReactiveContent(value) {
|
|
|
1520
1462
|
}
|
|
1521
1463
|
function slotsFor(props) {
|
|
1522
1464
|
const bindings = new Map();
|
|
1465
|
+
const fillScopes = new Map();
|
|
1523
1466
|
return new Proxy({}, {
|
|
1524
1467
|
get(_, prop) {
|
|
1525
1468
|
if (typeof prop !== "string" || !(prop in props)) return undefined;
|
|
@@ -1530,6 +1473,19 @@ function slotsFor(props) {
|
|
|
1530
1473
|
bindings.delete(key);
|
|
1531
1474
|
prev.dispose();
|
|
1532
1475
|
}
|
|
1476
|
+
const prevFill = key !== undefined && fillScopes.get(key);
|
|
1477
|
+
if (prevFill) {
|
|
1478
|
+
fillScopes.delete(key);
|
|
1479
|
+
prevFill.dispose();
|
|
1480
|
+
}
|
|
1481
|
+
const fillOwner = streamInvoke ? createOwner() : null;
|
|
1482
|
+
if (fillOwner && key !== undefined && ctx) {
|
|
1483
|
+
fillScopes.set(key, fillOwner);
|
|
1484
|
+
ctx.onCleanup(() => {
|
|
1485
|
+
if (fillScopes.get(key) === fillOwner) fillScopes.delete(key);
|
|
1486
|
+
fillOwner.dispose();
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1533
1489
|
const settle = out => {
|
|
1534
1490
|
const existing = ctx && ctx.existing || [];
|
|
1535
1491
|
if (existing.length) {
|
|
@@ -1542,26 +1498,18 @@ function slotsFor(props) {
|
|
|
1542
1498
|
const evaluate = () => {
|
|
1543
1499
|
const v = props[prop];
|
|
1544
1500
|
if (typeof v === "function" && ctx && ctx.invoked) {
|
|
1545
|
-
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotProps);
|
|
1501
|
+
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotArgsProxy(() => slotProps));
|
|
1546
1502
|
}
|
|
1547
1503
|
return v;
|
|
1548
1504
|
};
|
|
1549
1505
|
const adopted = !!(ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length);
|
|
1550
1506
|
const prefix = ctx && ctx.frame ? `sc-${ctx.frame}-${ctx.key}-` : "";
|
|
1551
|
-
const value = adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1507
|
+
const value = fillOwner ? runWithOwner(fillOwner, () => adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate()) : adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1552
1508
|
if (!isReactiveContent(value)) {
|
|
1553
1509
|
return settle(normalizeSlotContent(value));
|
|
1554
1510
|
}
|
|
1555
1511
|
if (ctx && ctx.range) {
|
|
1556
|
-
let claim = adopted;
|
|
1557
1512
|
const source = value;
|
|
1558
|
-
const accessor = () => {
|
|
1559
|
-
if (claim) {
|
|
1560
|
-
claim = false;
|
|
1561
|
-
return claimRender(prefix, ctx.existing, () => typeof source === "function" ? source() : source);
|
|
1562
|
-
}
|
|
1563
|
-
return typeof source === "function" ? source() : source;
|
|
1564
|
-
};
|
|
1565
1513
|
const owner = createOwner();
|
|
1566
1514
|
bindings.set(key, owner);
|
|
1567
1515
|
ctx.onCleanup(() => {
|
|
@@ -1569,7 +1517,8 @@ function slotsFor(props) {
|
|
|
1569
1517
|
owner.dispose();
|
|
1570
1518
|
});
|
|
1571
1519
|
const end = ctx.range.end;
|
|
1572
|
-
|
|
1520
|
+
const bind = () => insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1521
|
+
runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1573
1522
|
return undefined;
|
|
1574
1523
|
}
|
|
1575
1524
|
return settle(normalizeSlotContent(value));
|
|
@@ -1580,24 +1529,61 @@ function slotsFor(props) {
|
|
|
1580
1529
|
function revealSeam(owner) {
|
|
1581
1530
|
return seam => runWithOwner(owner, () => insert(seam.before.parentNode, createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
|
|
1582
1531
|
}
|
|
1532
|
+
let streamInvoke = false;
|
|
1583
1533
|
function boundaryScope(owner) {
|
|
1584
|
-
return fn =>
|
|
1534
|
+
return fn => {
|
|
1535
|
+
if (getOwner()) return fn();
|
|
1536
|
+
streamInvoke = true;
|
|
1537
|
+
try {
|
|
1538
|
+
return runWithOwner(owner, fn);
|
|
1539
|
+
} finally {
|
|
1540
|
+
streamInvoke = false;
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1585
1543
|
}
|
|
1586
|
-
function boundaryComponent(host,
|
|
1587
|
-
return props => {
|
|
1544
|
+
function boundaryComponent(host, fnId) {
|
|
1545
|
+
return (props, binding) => {
|
|
1588
1546
|
const owner = getOwner();
|
|
1547
|
+
const id = binding ? binding() : fnId;
|
|
1548
|
+
let applied = !tables.has(id);
|
|
1549
|
+
let release;
|
|
1550
|
+
const arm = () => new Promise(r => release = r);
|
|
1551
|
+
const mountGate = applied ? undefined : arm();
|
|
1552
|
+
let setGate;
|
|
1589
1553
|
const {
|
|
1590
1554
|
element,
|
|
1555
|
+
frame,
|
|
1591
1556
|
dispose
|
|
1592
1557
|
} = createFrameElement({
|
|
1593
1558
|
host,
|
|
1594
1559
|
id,
|
|
1595
1560
|
slots: slotsFor(props),
|
|
1596
1561
|
ownerScope: boundaryScope(owner),
|
|
1597
|
-
reveal: revealSeam(owner)
|
|
1562
|
+
reveal: revealSeam(owner),
|
|
1563
|
+
onApply: () => {
|
|
1564
|
+
applied = true;
|
|
1565
|
+
if (release) {
|
|
1566
|
+
release();
|
|
1567
|
+
release = undefined;
|
|
1568
|
+
}
|
|
1569
|
+
setGate && setGate(undefined);
|
|
1570
|
+
}
|
|
1598
1571
|
});
|
|
1572
|
+
const [gatePromise, setGatePromise] = createSignal(applied ? undefined : mountGate);
|
|
1573
|
+
setGate = setGatePromise;
|
|
1574
|
+
if (binding) {
|
|
1575
|
+
createRenderEffect(binding, (address, prev) => {
|
|
1576
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1577
|
+
applied = false;
|
|
1578
|
+
setGatePromise(arm());
|
|
1579
|
+
}
|
|
1580
|
+
frame.rebind(address);
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1599
1583
|
onCleanup(dispose);
|
|
1600
|
-
return element;
|
|
1584
|
+
if (applied && !binding) return element;
|
|
1585
|
+
const gate = createMemo(() => gatePromise());
|
|
1586
|
+
return createMemo(() => (gate(), element));
|
|
1601
1587
|
};
|
|
1602
1588
|
}
|
|
1603
1589
|
const claimedBoundaries = new Set();
|
|
@@ -1617,51 +1603,76 @@ function findBoundaryElement(id) {
|
|
|
1617
1603
|
return boundaryIndex.get(id);
|
|
1618
1604
|
}
|
|
1619
1605
|
const boundaryWaiters = new Map();
|
|
1620
|
-
function
|
|
1606
|
+
function boundaryMayArrive() {
|
|
1621
1607
|
const hy = globalThis._$HY;
|
|
1622
|
-
|
|
1608
|
+
if (!hy) return false;
|
|
1609
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1623
1610
|
}
|
|
1624
1611
|
function installRevealHook() {
|
|
1625
1612
|
const hy = globalThis._$HY;
|
|
1626
|
-
if (!hy || hy.$sc) return;
|
|
1613
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1627
1614
|
hy.$sc = true;
|
|
1628
|
-
|
|
1629
|
-
hy.fe = (fragmentId, parent) => {
|
|
1630
|
-
if (prev) prev(fragmentId, parent);
|
|
1615
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1631
1616
|
if (!boundaryIndex) return;
|
|
1632
1617
|
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1618
|
+
if (root) indexBoundaries(root);
|
|
1619
|
+
if (!boundaryWaiters.size) return;
|
|
1620
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1635
1621
|
for (const [id, notify] of boundaryWaiters) {
|
|
1636
|
-
const el = boundaryIndex.get(id);
|
|
1637
|
-
if (!el) continue;
|
|
1622
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1623
|
+
if (!el && !exhausted) continue;
|
|
1638
1624
|
boundaryWaiters.delete(id);
|
|
1639
1625
|
notify(el);
|
|
1640
1626
|
}
|
|
1641
|
-
};
|
|
1627
|
+
});
|
|
1642
1628
|
}
|
|
1643
|
-
function documentBoundary(host, id, props) {
|
|
1629
|
+
function documentBoundary(host, id, props, binding) {
|
|
1630
|
+
installRevealHook();
|
|
1644
1631
|
const claimed = claimedBoundaries.has(id);
|
|
1645
1632
|
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1646
|
-
if (el) return adoptBoundary(host, id, el, props);
|
|
1647
|
-
if (!claimed && !boundaryWaiters.has(id) &&
|
|
1633
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1634
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1648
1635
|
const owner = getOwner();
|
|
1649
1636
|
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1650
1637
|
onCleanup(() => boundaryWaiters.delete(id));
|
|
1651
|
-
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1638
|
+
return createMemo(() => arrival.then(node => runWithOwner(owner, () =>
|
|
1639
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1652
1640
|
}
|
|
1653
|
-
return boundaryComponent(host, id)(props);
|
|
1641
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1654
1642
|
}
|
|
1655
|
-
function
|
|
1643
|
+
function documentAddress(id) {
|
|
1644
|
+
const records = globalThis._$SC?.a;
|
|
1645
|
+
if (records) {
|
|
1646
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1647
|
+
}
|
|
1648
|
+
return id;
|
|
1649
|
+
}
|
|
1650
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1656
1651
|
claimedBoundaries.add(id);
|
|
1657
|
-
const
|
|
1658
|
-
|
|
1652
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1653
|
+
const appliedRecords = new Set();
|
|
1654
|
+
const claimedFragments = new Set();
|
|
1655
|
+
const claimRegionFragments = root => {
|
|
1656
|
+
const fr = globalThis._$HY?.fr;
|
|
1657
|
+
if (!fr || !fr.claim) return;
|
|
1658
|
+
root.querySelectorAll('template[id^="pl-"]').forEach(tpl => {
|
|
1659
|
+
const fragId = tpl.id.slice(3);
|
|
1660
|
+
if (claimedFragments.has(fragId)) return;
|
|
1661
|
+
claimedFragments.add(fragId);
|
|
1662
|
+
fr.claim(fragId);
|
|
1663
|
+
});
|
|
1664
|
+
};
|
|
1665
|
+
const drainRecords = () => {
|
|
1666
|
+
const hy = globalThis._$HY;
|
|
1667
|
+
if (!hy || !hy.r) return;
|
|
1659
1668
|
const slotPrefix = `sc:slot:${id}:`;
|
|
1660
1669
|
for (const key of Object.keys(hy.r)) {
|
|
1670
|
+
if (appliedRecords.has(key)) continue;
|
|
1661
1671
|
if (key.startsWith(slotPrefix)) {
|
|
1672
|
+
appliedRecords.add(key);
|
|
1662
1673
|
host.apply({
|
|
1663
1674
|
type: "slot",
|
|
1664
|
-
id,
|
|
1675
|
+
id: address,
|
|
1665
1676
|
version: 0,
|
|
1666
1677
|
key: key.slice(slotPrefix.length),
|
|
1667
1678
|
args: hy.r[key]
|
|
@@ -1669,6 +1680,7 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1669
1680
|
} else if (key.startsWith("sc:region:")) {
|
|
1670
1681
|
const childId = key.slice("sc:region:".length);
|
|
1671
1682
|
if (childId.startsWith(id + ".")) {
|
|
1683
|
+
appliedRecords.add(key);
|
|
1672
1684
|
const val = hy.r[key];
|
|
1673
1685
|
const apply = html => host.apply({
|
|
1674
1686
|
type: "html",
|
|
@@ -1680,16 +1692,58 @@ function adoptBoundary(host, id, el, props) {
|
|
|
1680
1692
|
}
|
|
1681
1693
|
}
|
|
1682
1694
|
}
|
|
1683
|
-
}
|
|
1695
|
+
};
|
|
1696
|
+
claimRegionFragments(el);
|
|
1697
|
+
const fr = globalThis._$HY?.fr;
|
|
1698
|
+
const unsubscribe = fr ? fr.subscribe((_fragId, parent) => {
|
|
1699
|
+
if (fr.claim && parent && el.contains(parent)) claimRegionFragments(parent);
|
|
1700
|
+
drainRecords();
|
|
1701
|
+
}) : undefined;
|
|
1702
|
+
onCleanup(() => {
|
|
1703
|
+
unsubscribe && unsubscribe();
|
|
1704
|
+
if (fr && fr.release) for (const fragId of claimedFragments) fr.release(fragId);
|
|
1705
|
+
});
|
|
1706
|
+
drainRecords();
|
|
1684
1707
|
const owner = getOwner();
|
|
1708
|
+
let release;
|
|
1709
|
+
let setGate;
|
|
1685
1710
|
const frame = createFrame(el, {
|
|
1686
1711
|
adopt: true,
|
|
1687
1712
|
host,
|
|
1688
|
-
id,
|
|
1713
|
+
id: address,
|
|
1689
1714
|
slots: slotsFor(props),
|
|
1690
1715
|
ownerScope: boundaryScope(owner),
|
|
1691
|
-
reveal: revealSeam(owner)
|
|
1716
|
+
reveal: revealSeam(owner),
|
|
1717
|
+
onApply: () => {
|
|
1718
|
+
if (release) {
|
|
1719
|
+
release();
|
|
1720
|
+
release = undefined;
|
|
1721
|
+
}
|
|
1722
|
+
setGate && setGate(undefined);
|
|
1723
|
+
},
|
|
1724
|
+
...{
|
|
1725
|
+
recordsPending: () => {
|
|
1726
|
+
if (document.readyState === "loading") return true;
|
|
1727
|
+
const hy = globalThis._$HY;
|
|
1728
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1729
|
+
},
|
|
1730
|
+
drainRecords,
|
|
1731
|
+
claimScope: id
|
|
1732
|
+
}
|
|
1692
1733
|
});
|
|
1734
|
+
if (binding) {
|
|
1735
|
+
const arm = () => new Promise(r => release = r);
|
|
1736
|
+
const [gatePromise, setGatePromise] = createSignal(undefined);
|
|
1737
|
+
setGate = setGatePromise;
|
|
1738
|
+
const gate = createMemo(() => gatePromise());
|
|
1739
|
+
createRenderEffect(binding, (address, prev) => {
|
|
1740
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1741
|
+
setGatePromise(arm());
|
|
1742
|
+
}
|
|
1743
|
+
frame.rebind(address);
|
|
1744
|
+
});
|
|
1745
|
+
createRenderEffect(() => (gate(), undefined), () => {});
|
|
1746
|
+
}
|
|
1693
1747
|
onCleanup(() => frame.dispose());
|
|
1694
1748
|
return el;
|
|
1695
1749
|
}
|
|
@@ -1704,17 +1758,16 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1704
1758
|
g._$SC.a[a] = i;
|
|
1705
1759
|
g._$SC.reg && g._$SC.reg(a, i);
|
|
1706
1760
|
}
|
|
1707
|
-
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1761
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1708
1762
|
}
|
|
1709
1763
|
};
|
|
1710
1764
|
}
|
|
1711
|
-
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1765
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1712
1766
|
installRevealHook();
|
|
1713
1767
|
const handler = createServerComponentHandler({
|
|
1714
1768
|
host,
|
|
1715
|
-
component:
|
|
1716
|
-
onStream:
|
|
1717
|
-
documentComponent: functionId => claimedBoundaries.has(functionId) ? undefined : g._$SC.c[functionId],
|
|
1769
|
+
component: fnId => g._$SC.r(fnId),
|
|
1770
|
+
onStream: address => beginStream(address),
|
|
1718
1771
|
intercept: ({
|
|
1719
1772
|
id
|
|
1720
1773
|
}) => {
|
|
@@ -1722,7 +1775,7 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1722
1775
|
return g._$SC.r(id);
|
|
1723
1776
|
}
|
|
1724
1777
|
});
|
|
1725
|
-
const showing = (address, id) => handler.showing(address, id
|
|
1778
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1726
1779
|
const records = g._$SC.a || (g._$SC.a = {});
|
|
1727
1780
|
for (const address in records) showing(address, records[address]);
|
|
1728
1781
|
g._$SC.reg = showing;
|
|
@@ -1731,4 +1784,4 @@ function installServerComponents(host = getFrameHost()) {
|
|
|
1731
1784
|
});
|
|
1732
1785
|
}
|
|
1733
1786
|
|
|
1734
|
-
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, createFrame, createFrameElement, createFrameHost,
|
|
1787
|
+
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, asyncArg, createFrame, createFrameElement, createFrameHost, createServerComponentHandler, getFrameHost, installServerComponents, isFrameStreamResponse };
|