@solidjs/web 2.0.0-beta.22 → 2.0.0-beta.23
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/dist/dev.cjs +25 -1
- package/dist/dev.js +25 -2
- package/dist/server.cjs +79 -33
- package/dist/server.js +79 -34
- package/dist/web.cjs +25 -1
- package/dist/web.js +25 -2
- package/frames/dist/client.cjs +1442 -0
- package/frames/dist/client.js +1430 -0
- package/frames/dist/server.cjs +1705 -0
- package/frames/dist/server.js +1694 -0
- package/frames/package.json +30 -0
- package/package.json +78 -5
- package/serialization/dist/serialization.cjs +83 -0
- package/serialization/dist/serialization.js +82 -1
- package/serialization/types/index.d.ts +12 -0
- package/serialization/types-cjs/index.d.cts +12 -0
- package/server-functions/dist/client.cjs +82 -55
- package/server-functions/dist/client.js +83 -56
- package/server-functions/dist/server.cjs +20 -3
- package/server-functions/dist/server.js +20 -3
- package/types/client.d.ts +8 -0
- package/types/core.d.ts +2 -1
- package/types/frames/client.d.ts +53 -0
- package/types/frames/frame-client.d.ts +205 -0
- package/types/frames/frame-sink.d.ts +145 -0
- package/types/frames/frame-transport.d.ts +105 -0
- package/types/frames/serializer.d.ts +151 -0
- package/types/frames/server.d.ts +21 -0
- package/types/serializer.d.ts +12 -0
- package/types/server-functions/client.d.ts +24 -0
- package/types/server.d.ts +2 -0
- package/types-cjs/client.d.cts +8 -0
- package/types-cjs/core.d.cts +2 -1
- package/types-cjs/frames/client.d.cts +53 -0
- package/types-cjs/frames/frame-client.d.cts +205 -0
- package/types-cjs/frames/frame-sink.d.cts +145 -0
- package/types-cjs/frames/frame-transport.d.cts +105 -0
- package/types-cjs/frames/serializer.d.cts +151 -0
- package/types-cjs/frames/server.d.cts +21 -0
- package/types-cjs/serializer.d.cts +12 -0
- package/types-cjs/server-functions/client.d.cts +24 -0
- package/types-cjs/server.d.cts +2 -0
|
@@ -0,0 +1,1430 @@
|
|
|
1
|
+
import { getOwner, onCleanup, runWithOwner, sharedConfig, createOwner } from 'solid-js';
|
|
2
|
+
import { fromCrossJSON, Feature } from 'seroval';
|
|
3
|
+
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
4
|
+
|
|
5
|
+
const ELEMENT_NODE = 1;
|
|
6
|
+
const TEXT_NODE = 3;
|
|
7
|
+
const COMMENT_NODE = 8;
|
|
8
|
+
const CLAIM_SEAM = Symbol.for("dom-expressions.element-claims");
|
|
9
|
+
const CLAIMED_ELEMENTS = "a[href], form[action]";
|
|
10
|
+
function claimHandlers() {
|
|
11
|
+
const handlers = globalThis[CLAIM_SEAM];
|
|
12
|
+
return handlers !== undefined && handlers.length !== 0 ? handlers : undefined;
|
|
13
|
+
}
|
|
14
|
+
function claimNode(handlers, el) {
|
|
15
|
+
for (let i = 0; i < handlers.length; i++) handlers[i](el);
|
|
16
|
+
}
|
|
17
|
+
const claimedAttr = name => name === "href" || name === "action";
|
|
18
|
+
function claimTree(handlers, root) {
|
|
19
|
+
const isElement = root.nodeType === ELEMENT_NODE;
|
|
20
|
+
if (!isElement && root.nodeType !== 11 ) return;
|
|
21
|
+
if (isElement && root.matches(CLAIMED_ELEMENTS)) claimNode(handlers, root);
|
|
22
|
+
const found = root.querySelectorAll(CLAIMED_ELEMENTS);
|
|
23
|
+
for (let i = 0; i < found.length; i++) claimNode(handlers, found[i]);
|
|
24
|
+
}
|
|
25
|
+
const placeholderId = name => `pl-${name}`;
|
|
26
|
+
const SLOT_START = /^slot:(.+):start$/;
|
|
27
|
+
const SLOT_END = /^slot:(.+):end$/;
|
|
28
|
+
const slotEnd = id => `slot:${id}:end`;
|
|
29
|
+
function chunkToRecords(chunk) {
|
|
30
|
+
switch (chunk.type) {
|
|
31
|
+
case "start":
|
|
32
|
+
case "data":
|
|
33
|
+
return {};
|
|
34
|
+
case "html":
|
|
35
|
+
return {
|
|
36
|
+
"": {
|
|
37
|
+
kind: "html",
|
|
38
|
+
value: chunk.html
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
case "fragment":
|
|
42
|
+
return {
|
|
43
|
+
[`seg:${chunk.key}`]: {
|
|
44
|
+
kind: "html",
|
|
45
|
+
value: chunk.html
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
case "reveal":
|
|
49
|
+
{
|
|
50
|
+
const records = {};
|
|
51
|
+
const gate = chunk.fallback ? "fallback" : "reveal";
|
|
52
|
+
for (const key of chunk.keys) records[`seg:${key}:${gate}`] = true;
|
|
53
|
+
return records;
|
|
54
|
+
}
|
|
55
|
+
case "assets":
|
|
56
|
+
return {
|
|
57
|
+
[`seg:${chunk.key}:assets`]: chunk
|
|
58
|
+
};
|
|
59
|
+
case "slot":
|
|
60
|
+
return {
|
|
61
|
+
[`slot:${chunk.key}`]: {
|
|
62
|
+
kind: "slot",
|
|
63
|
+
args: chunk.args
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
case "template":
|
|
67
|
+
return {
|
|
68
|
+
[`tpl:${chunk.key}`]: {
|
|
69
|
+
kind: "template",
|
|
70
|
+
html: chunk.html,
|
|
71
|
+
fields: chunk.fields
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
case "block":
|
|
75
|
+
return {
|
|
76
|
+
[`seg:${chunk.key}`]: {
|
|
77
|
+
kind: "block",
|
|
78
|
+
template: `tpl:${chunk.template}`,
|
|
79
|
+
values: chunk.values
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
case "complete":
|
|
83
|
+
return {
|
|
84
|
+
":complete": true
|
|
85
|
+
};
|
|
86
|
+
case "error":
|
|
87
|
+
return chunk.key ? {
|
|
88
|
+
[`seg:${chunk.key}:error`]: chunk.error
|
|
89
|
+
} : {
|
|
90
|
+
":error": chunk.error
|
|
91
|
+
};
|
|
92
|
+
default:
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function createFrameHost(options = {}) {
|
|
97
|
+
const frames = new Map();
|
|
98
|
+
const pending = new Map();
|
|
99
|
+
const deliver = (frame, chunk) => {
|
|
100
|
+
if (chunk.type === "data") {
|
|
101
|
+
options.applyData && options.applyData(chunk);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
frame.apply({
|
|
105
|
+
version: chunk.version,
|
|
106
|
+
r: chunkToRecords(chunk)
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
register(id, frame) {
|
|
111
|
+
let set = frames.get(id);
|
|
112
|
+
if (!set) frames.set(id, set = new Set());
|
|
113
|
+
const sibling = set.size ? set.values().next().value : undefined;
|
|
114
|
+
set.add(frame);
|
|
115
|
+
if (sibling) {
|
|
116
|
+
if (sibling.version !== undefined) {
|
|
117
|
+
frame.apply({
|
|
118
|
+
version: sibling.version,
|
|
119
|
+
r: sibling.store
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const buffered = pending.get(id);
|
|
125
|
+
if (buffered) {
|
|
126
|
+
pending.delete(id);
|
|
127
|
+
for (const chunk of buffered) deliver(frame, chunk);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
unregister(id, frame) {
|
|
131
|
+
const set = frames.get(id);
|
|
132
|
+
if (set && frame) set.delete(frame);
|
|
133
|
+
if (!set || !frame || !set.size) {
|
|
134
|
+
frames.delete(id);
|
|
135
|
+
pending.delete(id);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
apply(chunk) {
|
|
139
|
+
if (chunk.type === "data") {
|
|
140
|
+
options.applyData && options.applyData(chunk);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const set = frames.get(chunk.id);
|
|
144
|
+
if (set && set.size) {
|
|
145
|
+
for (const frame of set) deliver(frame, chunk);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const buffered = pending.get(chunk.id) ?? [];
|
|
149
|
+
const maxVersion = buffered.reduce((m, c) => Math.max(m, c.version), chunk.version);
|
|
150
|
+
if (chunk.version < maxVersion) return;
|
|
151
|
+
const kept = buffered.filter(c => c.version >= chunk.version);
|
|
152
|
+
kept.push(chunk);
|
|
153
|
+
pending.set(chunk.id, kept);
|
|
154
|
+
},
|
|
155
|
+
get(id) {
|
|
156
|
+
const set = frames.get(id);
|
|
157
|
+
return set && set.values().next().value;
|
|
158
|
+
},
|
|
159
|
+
serialize(value) {
|
|
160
|
+
if (!options.serialize) throw new Error("host has no serializer");
|
|
161
|
+
return options.serialize(value);
|
|
162
|
+
},
|
|
163
|
+
resolve(ref, frameId) {
|
|
164
|
+
return options.resolve ? options.resolve(ref, frameId) : undefined;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const FRAME_APPLIED_EVENT = "frame:applied";
|
|
169
|
+
class FrameImpl {
|
|
170
|
+
#element;
|
|
171
|
+
#start;
|
|
172
|
+
#end;
|
|
173
|
+
#options;
|
|
174
|
+
#version;
|
|
175
|
+
#store = Object.create(null);
|
|
176
|
+
#appliedRootValue;
|
|
177
|
+
#hasContent = false;
|
|
178
|
+
#revealed = new Set();
|
|
179
|
+
#fallbackShown = new Set();
|
|
180
|
+
#slots;
|
|
181
|
+
#mountedSlots = new Set();
|
|
182
|
+
#slotCleanups = new Map();
|
|
183
|
+
#slotArgs = new Map();
|
|
184
|
+
#slotRegions = new Map();
|
|
185
|
+
#slotResolvedRefs = new Map();
|
|
186
|
+
#slotNodes = new Map();
|
|
187
|
+
#processedAssets = new Set();
|
|
188
|
+
#disposed = false;
|
|
189
|
+
#styleFlush = () => {
|
|
190
|
+
if (!this.#disposed) this.#flush();
|
|
191
|
+
};
|
|
192
|
+
#claimTree = (node, direct) => {
|
|
193
|
+
const handlers = claimHandlers();
|
|
194
|
+
if (!handlers) return;
|
|
195
|
+
const run = () => direct ? claimNode(handlers, node) : claimTree(handlers, node);
|
|
196
|
+
const scope = this.#options.ownerScope;
|
|
197
|
+
scope ? scope(run) : run();
|
|
198
|
+
};
|
|
199
|
+
constructor(element, start, end, options = {}) {
|
|
200
|
+
this.#element = element;
|
|
201
|
+
this.#start = start;
|
|
202
|
+
this.#end = end;
|
|
203
|
+
this.#options = options;
|
|
204
|
+
this.#slots = options.slots;
|
|
205
|
+
if (options.adopt) {
|
|
206
|
+
this.#hasContent = true;
|
|
207
|
+
this.#claimContent();
|
|
208
|
+
}
|
|
209
|
+
if (options.host && options.id !== undefined) {
|
|
210
|
+
options.host.register(options.id, this);
|
|
211
|
+
}
|
|
212
|
+
if (options.adopt) this.#syncSlots();
|
|
213
|
+
}
|
|
214
|
+
#parent() {
|
|
215
|
+
return this.#element ?? this.#start.parentNode;
|
|
216
|
+
}
|
|
217
|
+
#applied(version, reason) {
|
|
218
|
+
this.#options.onApply?.({
|
|
219
|
+
version,
|
|
220
|
+
reason
|
|
221
|
+
});
|
|
222
|
+
const parent = this.#parent();
|
|
223
|
+
const Ev = parent && (parent.ownerDocument || parent).defaultView?.CustomEvent;
|
|
224
|
+
if (Ev) {
|
|
225
|
+
parent.dispatchEvent(new Ev(FRAME_APPLIED_EVENT, {
|
|
226
|
+
bubbles: true,
|
|
227
|
+
detail: {
|
|
228
|
+
id: this.#options.id,
|
|
229
|
+
version,
|
|
230
|
+
reason
|
|
231
|
+
}
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
#firstContent() {
|
|
236
|
+
return this.#start ? this.#start.nextSibling : this.#parent().firstChild;
|
|
237
|
+
}
|
|
238
|
+
get version() {
|
|
239
|
+
return this.#version;
|
|
240
|
+
}
|
|
241
|
+
get store() {
|
|
242
|
+
return this.#store;
|
|
243
|
+
}
|
|
244
|
+
isRevealed(segment) {
|
|
245
|
+
return this.#revealed.has(segment);
|
|
246
|
+
}
|
|
247
|
+
get error() {
|
|
248
|
+
return this.#store[":error"];
|
|
249
|
+
}
|
|
250
|
+
apply(write) {
|
|
251
|
+
if (this.#disposed) return;
|
|
252
|
+
const v = write.version;
|
|
253
|
+
if (this.#version === undefined) {
|
|
254
|
+
this.#version = v;
|
|
255
|
+
} else if (v < this.#version) {
|
|
256
|
+
return;
|
|
257
|
+
} else if (v > this.#version) {
|
|
258
|
+
this.#version = v;
|
|
259
|
+
this.#revealed.clear();
|
|
260
|
+
this.#fallbackShown.clear();
|
|
261
|
+
for (const key of Object.keys(this.#store)) {
|
|
262
|
+
if (key.startsWith("seg:") || key.startsWith("tpl:") || key === ":error") {
|
|
263
|
+
delete this.#store[key];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
for (const key of Object.keys(write.r)) {
|
|
268
|
+
const incoming = write.r[key];
|
|
269
|
+
if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
|
|
270
|
+
const existing = this.#store[key];
|
|
271
|
+
if (existing && existing.kind === "slot" && argsEquivalent(existing.args, incoming.args)) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
this.#store[key] = incoming;
|
|
276
|
+
}
|
|
277
|
+
this.#flush();
|
|
278
|
+
}
|
|
279
|
+
#flush() {
|
|
280
|
+
if (this.#disposed) return;
|
|
281
|
+
const version = this.#version;
|
|
282
|
+
const root = this.#store[""];
|
|
283
|
+
if (root && root.kind === "html" && root.value !== this.#appliedRootValue) {
|
|
284
|
+
const reason = this.#hasContent ? "morph" : "materialize";
|
|
285
|
+
this.#applyRoot(root.value);
|
|
286
|
+
this.#appliedRootValue = root.value;
|
|
287
|
+
this.#applied(version, reason);
|
|
288
|
+
}
|
|
289
|
+
let progressed = true;
|
|
290
|
+
while (progressed) {
|
|
291
|
+
progressed = false;
|
|
292
|
+
for (const key of Object.keys(this.#store)) {
|
|
293
|
+
const name = segmentName(key);
|
|
294
|
+
if (name === null || this.#revealed.has(name)) continue;
|
|
295
|
+
if (this.#segmentReady(name)) {
|
|
296
|
+
this.#revealSegment(name);
|
|
297
|
+
this.#applied(version, "reveal");
|
|
298
|
+
progressed = true;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
for (const key of Object.keys(this.#store)) {
|
|
302
|
+
const m = /^seg:([^:]+):fallback$/.exec(key);
|
|
303
|
+
if (!m) continue;
|
|
304
|
+
const name = m[1];
|
|
305
|
+
if (this.#revealed.has(name) || this.#fallbackShown.has(name)) continue;
|
|
306
|
+
if (this.#showFallback(name)) {
|
|
307
|
+
this.#fallbackShown.add(name);
|
|
308
|
+
this.#applied(version, "reveal");
|
|
309
|
+
progressed = true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (const key of Object.keys(this.#store)) {
|
|
314
|
+
if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
|
|
315
|
+
this.#processedAssets.add(key);
|
|
316
|
+
const record = this.#store[key];
|
|
317
|
+
if (record && record.modules) {
|
|
318
|
+
for (const href of record.modules) ensureModulePreload(href);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
this.#syncSlots();
|
|
322
|
+
}
|
|
323
|
+
#resolveSlot(prop) {
|
|
324
|
+
return this.#slots?.[prop] ?? this.#options.resolveSlot?.(prop);
|
|
325
|
+
}
|
|
326
|
+
#resolveSlotRecord(occurrence) {
|
|
327
|
+
const record = this.#store[`slot:${occurrence}`];
|
|
328
|
+
if (record !== undefined) return record;
|
|
329
|
+
return this.#options.resolveSlotRecord?.(occurrence);
|
|
330
|
+
}
|
|
331
|
+
#syncSlots() {
|
|
332
|
+
if (!this.#slots && !this.#options.resolveSlot) return;
|
|
333
|
+
const found = new Map();
|
|
334
|
+
this.#collectSlots(found);
|
|
335
|
+
for (const [occurrence, start] of found) {
|
|
336
|
+
const callback = this.#resolveSlot(propOf(occurrence));
|
|
337
|
+
if (!callback) continue;
|
|
338
|
+
const record = this.#resolveSlotRecord(occurrence);
|
|
339
|
+
const prev = this.#slotNodes.get(occurrence);
|
|
340
|
+
const prevFirst = Array.isArray(prev) ? prev[0] : prev;
|
|
341
|
+
const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
|
|
342
|
+
if (zombie) {
|
|
343
|
+
this.#mountedSlots.delete(occurrence);
|
|
344
|
+
this.#runSlotCleanups(occurrence);
|
|
345
|
+
}
|
|
346
|
+
if (!this.#mountedSlots.has(occurrence)) {
|
|
347
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
348
|
+
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
349
|
+
this.#slotNodes.set(occurrence, nodes);
|
|
350
|
+
this.#mountedSlots.add(occurrence);
|
|
351
|
+
if (!record) this.#discoverRegions(occurrence, start);
|
|
352
|
+
this.#bindRegions(occurrence);
|
|
353
|
+
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
354
|
+
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
355
|
+
this.#slotArgs.set(occurrence, record);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
359
|
+
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
360
|
+
this.#slotNodes.set(occurrence, nodes);
|
|
361
|
+
this.#bindRegions(occurrence);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
for (const occurrence of [...this.#mountedSlots]) {
|
|
365
|
+
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
#invokeSlot(occurrence, callback, record, start) {
|
|
369
|
+
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
370
|
+
const ctx = {
|
|
371
|
+
frame: this.#options.claimScope ?? this.#options.id,
|
|
372
|
+
key: occurrence,
|
|
373
|
+
onCleanup: fn => cleanups.push(fn),
|
|
374
|
+
existing: start ? rangeInterior(start, slotEnd(occurrence)) : []
|
|
375
|
+
};
|
|
376
|
+
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
377
|
+
const content = callback(props, ctx);
|
|
378
|
+
this.#slotArgs.set(occurrence, record);
|
|
379
|
+
if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
|
|
380
|
+
if (content == null) return null;
|
|
381
|
+
return Array.isArray(content) ? content : [content];
|
|
382
|
+
}
|
|
383
|
+
#replaceRange(key, start, nodes) {
|
|
384
|
+
const end = slotEnd(key);
|
|
385
|
+
const parent = start.parentNode;
|
|
386
|
+
let n = start.nextSibling;
|
|
387
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
|
|
388
|
+
const next = n.nextSibling;
|
|
389
|
+
parent.removeChild(n);
|
|
390
|
+
n = next;
|
|
391
|
+
}
|
|
392
|
+
for (const node of nodes) parent.insertBefore(node, n);
|
|
393
|
+
}
|
|
394
|
+
#unmountSlot(key) {
|
|
395
|
+
this.#mountedSlots.delete(key);
|
|
396
|
+
this.#slotNodes.delete(key);
|
|
397
|
+
this.#slotArgs.delete(key);
|
|
398
|
+
this.#slotResolvedRefs.delete(key);
|
|
399
|
+
delete this.#store[`slot:${key}`];
|
|
400
|
+
this.#runSlotCleanups(key);
|
|
401
|
+
const regions = this.#slotRegions.get(key);
|
|
402
|
+
if (regions) {
|
|
403
|
+
for (const {
|
|
404
|
+
frame
|
|
405
|
+
} of regions.values()) frame?.dispose();
|
|
406
|
+
this.#slotRegions.delete(key);
|
|
407
|
+
}
|
|
408
|
+
this.#slotArgs.delete(key);
|
|
409
|
+
}
|
|
410
|
+
#runSlotCleanups(key) {
|
|
411
|
+
const cleanups = this.#slotCleanups.get(key);
|
|
412
|
+
if (!cleanups) return;
|
|
413
|
+
this.#slotCleanups.delete(key);
|
|
414
|
+
for (const fn of cleanups) fn();
|
|
415
|
+
}
|
|
416
|
+
#resolveArgs(slotKey, args) {
|
|
417
|
+
const host = this.#options.host;
|
|
418
|
+
let regions = this.#slotRegions.get(slotKey);
|
|
419
|
+
if (!regions) {
|
|
420
|
+
regions = new Map();
|
|
421
|
+
this.#slotRegions.set(slotKey, regions);
|
|
422
|
+
}
|
|
423
|
+
const props = {};
|
|
424
|
+
for (const key of Object.keys(args)) {
|
|
425
|
+
const value = args[key];
|
|
426
|
+
if (isDataRef(value)) {
|
|
427
|
+
const resolved = host ? host.resolve(value, this.#options.id) : undefined;
|
|
428
|
+
let cache = this.#slotResolvedRefs.get(slotKey);
|
|
429
|
+
if (!cache) this.#slotResolvedRefs.set(slotKey, cache = {});
|
|
430
|
+
cache[key] = resolved;
|
|
431
|
+
props[key] = resolved;
|
|
432
|
+
} else if (isFrameRef(value)) {
|
|
433
|
+
const fragment = document.createDocumentFragment();
|
|
434
|
+
let entry = regions.get(value.$frame);
|
|
435
|
+
if (!entry) {
|
|
436
|
+
const start = document.createComment(`frame:${value.$frame}:start`);
|
|
437
|
+
const end = document.createComment(`frame:${value.$frame}:end`);
|
|
438
|
+
entry = {
|
|
439
|
+
childId: value.$frame,
|
|
440
|
+
start,
|
|
441
|
+
end,
|
|
442
|
+
frame: undefined
|
|
443
|
+
};
|
|
444
|
+
regions.set(value.$frame, entry);
|
|
445
|
+
fragment.append(start, end);
|
|
446
|
+
} else {
|
|
447
|
+
let n = entry.start;
|
|
448
|
+
while (n) {
|
|
449
|
+
const next = n.nextSibling;
|
|
450
|
+
fragment.append(n);
|
|
451
|
+
if (n === entry.end) break;
|
|
452
|
+
n = next;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
props[key] = fragment;
|
|
456
|
+
} else {
|
|
457
|
+
props[key] = value;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return props;
|
|
461
|
+
}
|
|
462
|
+
#discoverRegions(slotKey, start) {
|
|
463
|
+
if (!start) return;
|
|
464
|
+
let regions = this.#slotRegions.get(slotKey);
|
|
465
|
+
if (!regions) {
|
|
466
|
+
regions = new Map();
|
|
467
|
+
this.#slotRegions.set(slotKey, regions);
|
|
468
|
+
}
|
|
469
|
+
const doc = start.ownerDocument;
|
|
470
|
+
const endData = slotEnd(slotKey);
|
|
471
|
+
const comments = [];
|
|
472
|
+
let n = start.nextSibling;
|
|
473
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
474
|
+
if (n.nodeType === COMMENT_NODE) comments.push(n);else if (n.nodeType === 1) {
|
|
475
|
+
const walker = doc.createTreeWalker(n, 128 );
|
|
476
|
+
let c;
|
|
477
|
+
while (c = walker.nextNode()) comments.push(c);
|
|
478
|
+
}
|
|
479
|
+
n = n.nextSibling;
|
|
480
|
+
}
|
|
481
|
+
let depth = 0;
|
|
482
|
+
let openId = null;
|
|
483
|
+
let openStart = null;
|
|
484
|
+
for (const c of comments) {
|
|
485
|
+
const data = c.data;
|
|
486
|
+
if (!data.startsWith("frame:")) continue;
|
|
487
|
+
if (data.endsWith(":start")) {
|
|
488
|
+
const childId = data.slice(6, -6);
|
|
489
|
+
if (!childId) continue;
|
|
490
|
+
if (depth === 0) {
|
|
491
|
+
openId = childId;
|
|
492
|
+
openStart = c;
|
|
493
|
+
}
|
|
494
|
+
depth++;
|
|
495
|
+
} else if (data.endsWith(":end")) {
|
|
496
|
+
const childId = data.slice(6, -4);
|
|
497
|
+
if (!childId) continue;
|
|
498
|
+
if (depth > 0) {
|
|
499
|
+
depth--;
|
|
500
|
+
if (depth === 0 && childId === openId && !regions.has(openId)) {
|
|
501
|
+
regions.set(openId, {
|
|
502
|
+
childId: openId,
|
|
503
|
+
start: openStart,
|
|
504
|
+
end: c,
|
|
505
|
+
frame: undefined,
|
|
506
|
+
adopt: true
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
#refArgsUnchanged(occurrence, record) {
|
|
514
|
+
const old = this.#slotArgs.get(occurrence);
|
|
515
|
+
if (!old || old.kind !== "slot" || !record || record.kind !== "slot") return false;
|
|
516
|
+
const a = old.args || {};
|
|
517
|
+
const b = record.args || {};
|
|
518
|
+
const ka = Object.keys(a);
|
|
519
|
+
if (ka.length !== Object.keys(b).length) return false;
|
|
520
|
+
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
521
|
+
for (const key of ka) {
|
|
522
|
+
const va = a[key];
|
|
523
|
+
const vb = b[key];
|
|
524
|
+
if (va === vb) continue;
|
|
525
|
+
if (!va || !vb || typeof va !== "object" || typeof vb !== "object") return false;
|
|
526
|
+
if (typeof va.$frame === "string" && va.$frame === vb.$frame) continue;
|
|
527
|
+
if (typeof va.$ref === "string" && typeof vb.$ref === "string" && cache && key in cache) {
|
|
528
|
+
const host = this.#options.host;
|
|
529
|
+
const next = host ? host.resolve(vb, this.#options.id) : undefined;
|
|
530
|
+
try {
|
|
531
|
+
if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
|
|
532
|
+
} catch (e) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
#bindRegions(slotKey) {
|
|
541
|
+
const regions = this.#slotRegions.get(slotKey);
|
|
542
|
+
if (!regions) return;
|
|
543
|
+
for (const entry of regions.values()) {
|
|
544
|
+
if (!entry.frame && entry.start.parentNode) {
|
|
545
|
+
entry.frame = new FrameImpl(null, entry.start, entry.end, {
|
|
546
|
+
id: entry.childId,
|
|
547
|
+
host: this.#options.host,
|
|
548
|
+
adopt: entry.adopt,
|
|
549
|
+
claimScope: this.#options.claimScope ?? this.#options.id,
|
|
550
|
+
ownerScope: this.#options.ownerScope,
|
|
551
|
+
resolveSlot: prop => this.#resolveSlot(prop),
|
|
552
|
+
resolveSlotRecord: occurrence => this.#resolveSlotRecord(occurrence)
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
#collectSlots(found) {
|
|
558
|
+
let n = this.#firstContent();
|
|
559
|
+
const end = this.#end;
|
|
560
|
+
while (n && n !== end) {
|
|
561
|
+
const id = slotStartId(n);
|
|
562
|
+
if (id !== null) {
|
|
563
|
+
if (!found.has(id)) found.set(id, n);
|
|
564
|
+
n = afterRange(n, id);
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
const regionId = frameRegionStartId(n);
|
|
568
|
+
if (regionId !== null) {
|
|
569
|
+
n = afterFrameRegion(n, regionId);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
if (n.nodeType === ELEMENT_NODE) collectSlots(n, found);
|
|
573
|
+
n = n.nextSibling;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
#findPlaceholder(name) {
|
|
577
|
+
const id = placeholderId(name);
|
|
578
|
+
let n = this.#firstContent();
|
|
579
|
+
const end = this.#end;
|
|
580
|
+
while (n && n !== end) {
|
|
581
|
+
if (isPlaceholderStart(n, id)) return n;
|
|
582
|
+
if (n.nodeType === ELEMENT_NODE) {
|
|
583
|
+
const found = findPlaceholder(n, id);
|
|
584
|
+
if (found) return found;
|
|
585
|
+
}
|
|
586
|
+
n = n.nextSibling;
|
|
587
|
+
}
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
dispose() {
|
|
591
|
+
if (this.#disposed) return;
|
|
592
|
+
this.#disposed = true;
|
|
593
|
+
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
594
|
+
for (const regions of this.#slotRegions.values()) {
|
|
595
|
+
for (const {
|
|
596
|
+
frame
|
|
597
|
+
} of regions.values()) frame?.dispose();
|
|
598
|
+
}
|
|
599
|
+
this.#slotRegions.clear();
|
|
600
|
+
this.#mountedSlots.clear();
|
|
601
|
+
const {
|
|
602
|
+
host,
|
|
603
|
+
id
|
|
604
|
+
} = this.#options;
|
|
605
|
+
if (host && id !== undefined) host.unregister(id, this);
|
|
606
|
+
}
|
|
607
|
+
#applyRoot(html) {
|
|
608
|
+
const fragment = parseFragment(html);
|
|
609
|
+
const parent = this.#parent();
|
|
610
|
+
if (!this.#hasContent) {
|
|
611
|
+
this.#clearContent();
|
|
612
|
+
this.#claimTree(fragment);
|
|
613
|
+
parent.insertBefore(fragment, this.#end);
|
|
614
|
+
this.#hasContent = true;
|
|
615
|
+
} else {
|
|
616
|
+
const claim = claimHandlers() ? this.#claimTree : null;
|
|
617
|
+
reconcileChildren(parent, fragment, this.#start, this.#end, claim);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
#clearContent() {
|
|
621
|
+
const parent = this.#parent();
|
|
622
|
+
let n = this.#firstContent();
|
|
623
|
+
while (n && n !== this.#end) {
|
|
624
|
+
const next = n.nextSibling;
|
|
625
|
+
parent.removeChild(n);
|
|
626
|
+
n = next;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
#claimContent() {
|
|
630
|
+
if (!claimHandlers()) return;
|
|
631
|
+
let n = this.#firstContent();
|
|
632
|
+
while (n && n !== this.#end) {
|
|
633
|
+
this.#claimTree(n);
|
|
634
|
+
n = n.nextSibling;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
#segmentReady(name) {
|
|
638
|
+
const content = this.#store[`seg:${name}`];
|
|
639
|
+
if (!content) return false;
|
|
640
|
+
if (content.kind === "block") {
|
|
641
|
+
const template = this.#store[content.template];
|
|
642
|
+
if (!template || template.kind !== "template") return false;
|
|
643
|
+
} else if (content.kind !== "html") {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
if (!this.#store[`seg:${name}:reveal`]) return false;
|
|
647
|
+
const assets = this.#store[`seg:${name}:assets`];
|
|
648
|
+
if (assets && assets.styles) {
|
|
649
|
+
let ready = true;
|
|
650
|
+
for (const href of assets.styles) {
|
|
651
|
+
if (!ensureStylesheet(href, this.#styleFlush)) ready = false;
|
|
652
|
+
}
|
|
653
|
+
if (!ready) return false;
|
|
654
|
+
}
|
|
655
|
+
if (!this.#findPlaceholder(name)) return false;
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
#revealSegment(name) {
|
|
659
|
+
const tpl = this.#findPlaceholder(name);
|
|
660
|
+
if (!tpl) return;
|
|
661
|
+
const assets = this.#store[`seg:${name}:assets`];
|
|
662
|
+
if (assets && assets.inlineStyles) applyInlineStyles(assets.inlineStyles);
|
|
663
|
+
const content = this.#store[`seg:${name}`];
|
|
664
|
+
const closing = rangeClose(tpl, placeholderId(name));
|
|
665
|
+
const parent = tpl.parentNode;
|
|
666
|
+
let n = tpl.nextSibling;
|
|
667
|
+
while (n && n !== closing) {
|
|
668
|
+
const next = n.nextSibling;
|
|
669
|
+
parent.removeChild(n);
|
|
670
|
+
n = next;
|
|
671
|
+
}
|
|
672
|
+
const materialized = this.#materialize(content);
|
|
673
|
+
this.#claimTree(materialized);
|
|
674
|
+
parent.insertBefore(materialized, closing);
|
|
675
|
+
tpl.remove();
|
|
676
|
+
closing && closing.remove();
|
|
677
|
+
this.#revealed.add(name);
|
|
678
|
+
}
|
|
679
|
+
#showFallback(name) {
|
|
680
|
+
const tpl = this.#findPlaceholder(name);
|
|
681
|
+
if (!tpl) return false;
|
|
682
|
+
const closing = rangeClose(tpl, placeholderId(name));
|
|
683
|
+
if (!closing) return false;
|
|
684
|
+
const fallback = tpl.content.cloneNode(true);
|
|
685
|
+
this.#claimTree(fallback);
|
|
686
|
+
closing.parentNode.insertBefore(fallback, closing);
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
#materialize(record) {
|
|
690
|
+
if (record.kind === "html") return parseFragment(record.value);
|
|
691
|
+
if (record.kind === "block") {
|
|
692
|
+
const template = this.#store[record.template];
|
|
693
|
+
if (!template || template.kind !== "template") return parseFragment("");
|
|
694
|
+
return materializeBlock(template, record.values);
|
|
695
|
+
}
|
|
696
|
+
return parseFragment("");
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
function materializeBlock(template, values) {
|
|
700
|
+
const fragment = parseFragment(template.html);
|
|
701
|
+
for (let i = 0; i < template.fields.length; i++) {
|
|
702
|
+
const marker = `field:${template.fields[i]}`;
|
|
703
|
+
const value = values[i] == null ? "" : String(values[i]);
|
|
704
|
+
let hole = findComment(fragment, marker);
|
|
705
|
+
while (hole) {
|
|
706
|
+
hole.replaceWith(document.createTextNode(value));
|
|
707
|
+
hole = findComment(fragment, marker);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
return fragment;
|
|
711
|
+
}
|
|
712
|
+
function createFrame(boundary, options) {
|
|
713
|
+
return new FrameImpl(boundary, null, null, options);
|
|
714
|
+
}
|
|
715
|
+
function adoptFrameRange(start, end, options) {
|
|
716
|
+
return new FrameImpl(null, start, end, {
|
|
717
|
+
...options,
|
|
718
|
+
adopt: true
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
const FRAME = Symbol.for("dom-expressions.frame");
|
|
722
|
+
function createFrameInsertable(options) {
|
|
723
|
+
let frame = null;
|
|
724
|
+
let start = null;
|
|
725
|
+
let end = null;
|
|
726
|
+
return {
|
|
727
|
+
get frame() {
|
|
728
|
+
return frame;
|
|
729
|
+
},
|
|
730
|
+
dispose() {
|
|
731
|
+
if (!frame) return;
|
|
732
|
+
frame.dispose();
|
|
733
|
+
frame = null;
|
|
734
|
+
const parent = start.parentNode;
|
|
735
|
+
if (!parent) return;
|
|
736
|
+
let n = start;
|
|
737
|
+
while (n) {
|
|
738
|
+
const next = n.nextSibling;
|
|
739
|
+
parent.removeChild(n);
|
|
740
|
+
if (n === end) break;
|
|
741
|
+
n = next;
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
[FRAME](parent, marker) {
|
|
745
|
+
if (frame) return;
|
|
746
|
+
start = document.createComment("frame:start");
|
|
747
|
+
end = document.createComment("frame:end");
|
|
748
|
+
parent.insertBefore(start, marker);
|
|
749
|
+
parent.insertBefore(end, marker);
|
|
750
|
+
frame = new FrameImpl(null, start, end, options);
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
function segmentName(key) {
|
|
755
|
+
const m = /^seg:([^:]+)$/.exec(key);
|
|
756
|
+
return m ? m[1] : null;
|
|
757
|
+
}
|
|
758
|
+
function propOf(occurrence) {
|
|
759
|
+
const hash = occurrence.indexOf("#");
|
|
760
|
+
return hash === -1 ? occurrence : occurrence.slice(0, hash);
|
|
761
|
+
}
|
|
762
|
+
function isDataRef(value) {
|
|
763
|
+
return typeof value === "object" && value !== null && typeof value.$ref === "string";
|
|
764
|
+
}
|
|
765
|
+
function isFrameRef(value) {
|
|
766
|
+
return typeof value === "object" && value !== null && typeof value.$frame === "string";
|
|
767
|
+
}
|
|
768
|
+
function parseFragment(html) {
|
|
769
|
+
const template = document.createElement("template");
|
|
770
|
+
template.innerHTML = html;
|
|
771
|
+
return template.content;
|
|
772
|
+
}
|
|
773
|
+
function findHeadElement(selector, attr, value) {
|
|
774
|
+
const nodes = document.head.querySelectorAll(selector);
|
|
775
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
776
|
+
if (nodes[i].getAttribute(attr) === value) return nodes[i];
|
|
777
|
+
}
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
function ensureStylesheet(href, onSettle) {
|
|
781
|
+
let link = findHeadElement('link[rel="stylesheet"]', "href", href);
|
|
782
|
+
if (!link) {
|
|
783
|
+
link = document.createElement("link");
|
|
784
|
+
link.rel = "stylesheet";
|
|
785
|
+
link.href = href;
|
|
786
|
+
const waiters = new Set();
|
|
787
|
+
link._$frWaiters = waiters;
|
|
788
|
+
const settle = () => {
|
|
789
|
+
link._$frWaiters = null;
|
|
790
|
+
for (const fn of waiters) fn();
|
|
791
|
+
};
|
|
792
|
+
link.addEventListener("load", settle);
|
|
793
|
+
link.addEventListener("error", settle);
|
|
794
|
+
document.head.appendChild(link);
|
|
795
|
+
}
|
|
796
|
+
const waiters = link._$frWaiters;
|
|
797
|
+
if (waiters == null) return true;
|
|
798
|
+
waiters.add(onSettle);
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
function ensureModulePreload(href) {
|
|
802
|
+
if (findHeadElement('link[rel="modulepreload"]', "href", href)) return;
|
|
803
|
+
const link = document.createElement("link");
|
|
804
|
+
link.rel = "modulepreload";
|
|
805
|
+
link.href = href;
|
|
806
|
+
document.head.appendChild(link);
|
|
807
|
+
}
|
|
808
|
+
function applyInlineStyles(inlineStyles) {
|
|
809
|
+
for (const entry of inlineStyles) {
|
|
810
|
+
if (findHeadElement("style[data-asset]", "data-asset", entry.id)) continue;
|
|
811
|
+
const el = document.createElement("style");
|
|
812
|
+
el.setAttribute("data-asset", entry.id);
|
|
813
|
+
if (entry.attrs) {
|
|
814
|
+
for (const name in entry.attrs) el.setAttribute(name, entry.attrs[name]);
|
|
815
|
+
}
|
|
816
|
+
el.textContent = entry.content || "";
|
|
817
|
+
document.head.appendChild(el);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
function isPlaceholderStart(node, id) {
|
|
821
|
+
return node.nodeType === ELEMENT_NODE && node.tagName === "TEMPLATE" && node.getAttribute("id") === id;
|
|
822
|
+
}
|
|
823
|
+
function rangeClose(start, id) {
|
|
824
|
+
let n = start.nextSibling;
|
|
825
|
+
while (n) {
|
|
826
|
+
if (n.nodeType === COMMENT_NODE && n.data === id) return n;
|
|
827
|
+
n = n.nextSibling;
|
|
828
|
+
}
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
function findPlaceholder(root, id) {
|
|
832
|
+
let n = root.firstChild;
|
|
833
|
+
while (n) {
|
|
834
|
+
if (isPlaceholderStart(n, id)) return n;
|
|
835
|
+
if (n.nodeType === ELEMENT_NODE) {
|
|
836
|
+
const found = findPlaceholder(n, id);
|
|
837
|
+
if (found) return found;
|
|
838
|
+
}
|
|
839
|
+
n = n.nextSibling;
|
|
840
|
+
}
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
function collectSlots(root, out) {
|
|
844
|
+
let n = root.firstChild;
|
|
845
|
+
while (n) {
|
|
846
|
+
const id = slotStartId(n);
|
|
847
|
+
if (id !== null) {
|
|
848
|
+
if (!out.has(id)) out.set(id, n);
|
|
849
|
+
n = afterRange(n, id);
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
const regionId = frameRegionStartId(n);
|
|
853
|
+
if (regionId !== null) {
|
|
854
|
+
n = afterFrameRegion(n, regionId);
|
|
855
|
+
continue;
|
|
856
|
+
}
|
|
857
|
+
if (n.nodeType === ELEMENT_NODE) collectSlots(n, out);
|
|
858
|
+
n = n.nextSibling;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const FRAME_REGION_START = /^frame:(.+):start$/;
|
|
862
|
+
function frameRegionStartId(node) {
|
|
863
|
+
if (node.nodeType !== COMMENT_NODE) return null;
|
|
864
|
+
const m = FRAME_REGION_START.exec(node.data);
|
|
865
|
+
return m ? m[1] : null;
|
|
866
|
+
}
|
|
867
|
+
function afterFrameRegion(start, id) {
|
|
868
|
+
const end = `frame:${id}:end`;
|
|
869
|
+
let n = start.nextSibling;
|
|
870
|
+
while (n) {
|
|
871
|
+
if (n.nodeType === COMMENT_NODE && n.data === end) return n.nextSibling;
|
|
872
|
+
n = n.nextSibling;
|
|
873
|
+
}
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
function argsEquivalent(a, b) {
|
|
877
|
+
if (a === b) return true;
|
|
878
|
+
if (!a || !b) return false;
|
|
879
|
+
const ka = Object.keys(a);
|
|
880
|
+
const kb = Object.keys(b);
|
|
881
|
+
if (ka.length !== kb.length) return false;
|
|
882
|
+
for (const key of ka) {
|
|
883
|
+
const va = a[key];
|
|
884
|
+
const vb = b[key];
|
|
885
|
+
if (va === vb) continue;
|
|
886
|
+
if (va && vb && typeof va === "object" && typeof vb === "object" && typeof va.$frame === "string" && va.$frame === vb.$frame) {
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
889
|
+
return false;
|
|
890
|
+
}
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
function rangeInterior(start, endData) {
|
|
894
|
+
const nodes = [];
|
|
895
|
+
let n = start.nextSibling;
|
|
896
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === endData)) {
|
|
897
|
+
nodes.push(n);
|
|
898
|
+
n = n.nextSibling;
|
|
899
|
+
}
|
|
900
|
+
return nodes;
|
|
901
|
+
}
|
|
902
|
+
function findComment(root, data) {
|
|
903
|
+
const children = root.childNodes;
|
|
904
|
+
for (let i = 0; i < children.length; i++) {
|
|
905
|
+
const node = children[i];
|
|
906
|
+
if (node.nodeType === COMMENT_NODE && node.data === data) return node;
|
|
907
|
+
if (node.nodeType === ELEMENT_NODE) {
|
|
908
|
+
const found = findComment(node, data);
|
|
909
|
+
if (found) return found;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return null;
|
|
913
|
+
}
|
|
914
|
+
function slotStartId(node) {
|
|
915
|
+
if (node.nodeType !== COMMENT_NODE) return null;
|
|
916
|
+
const m = SLOT_START.exec(node.data);
|
|
917
|
+
return m ? m[1] : null;
|
|
918
|
+
}
|
|
919
|
+
function isSlotMarker(node) {
|
|
920
|
+
if (node.nodeType !== COMMENT_NODE) return false;
|
|
921
|
+
const data = node.data;
|
|
922
|
+
return SLOT_START.test(data) || SLOT_END.test(data);
|
|
923
|
+
}
|
|
924
|
+
function compatible(a, b) {
|
|
925
|
+
if (a.nodeType !== b.nodeType) return false;
|
|
926
|
+
if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName;
|
|
927
|
+
return a.nodeType === TEXT_NODE || a.nodeType === COMMENT_NODE;
|
|
928
|
+
}
|
|
929
|
+
function morphAttributes(oldEl, newEl, claim) {
|
|
930
|
+
let reclaim = false;
|
|
931
|
+
let changed = false;
|
|
932
|
+
const oldAttrs = oldEl.attributes;
|
|
933
|
+
for (let i = oldAttrs.length - 1; i >= 0; i--) {
|
|
934
|
+
const name = oldAttrs[i].name;
|
|
935
|
+
if (!newEl.hasAttribute(name)) {
|
|
936
|
+
oldEl.removeAttribute(name);
|
|
937
|
+
changed = true;
|
|
938
|
+
reclaim ||= claimedAttr(name);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
const newAttrs = newEl.attributes;
|
|
942
|
+
for (let i = 0; i < newAttrs.length; i++) {
|
|
943
|
+
const attr = newAttrs[i];
|
|
944
|
+
if (oldEl.getAttribute(attr.name) !== attr.value) {
|
|
945
|
+
oldEl.setAttribute(attr.name, attr.value);
|
|
946
|
+
changed = true;
|
|
947
|
+
reclaim ||= claimedAttr(attr.name);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
951
|
+
}
|
|
952
|
+
function morphNode(oldNode, newNode, claim) {
|
|
953
|
+
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
954
|
+
morphAttributes(oldNode, newNode, claim);
|
|
955
|
+
reconcileChildren(oldNode, newNode, null, null, claim);
|
|
956
|
+
} else if (oldNode.data !== newNode.data) {
|
|
957
|
+
oldNode.data = newNode.data;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function afterRange(start, id) {
|
|
961
|
+
const end = slotEnd(id);
|
|
962
|
+
let n = start.nextSibling;
|
|
963
|
+
while (n) {
|
|
964
|
+
if (n.nodeType === COMMENT_NODE && n.data === end) return n.nextSibling;
|
|
965
|
+
n = n.nextSibling;
|
|
966
|
+
}
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
function skipRange(start, id) {
|
|
970
|
+
return afterRange(start, id);
|
|
971
|
+
}
|
|
972
|
+
function findRangeStart(from, id, bound) {
|
|
973
|
+
const target = `slot:${id}:start`;
|
|
974
|
+
let n = from;
|
|
975
|
+
while (n && n !== bound) {
|
|
976
|
+
if (n.nodeType === COMMENT_NODE && n.data === target) return n;
|
|
977
|
+
n = n.nextSibling;
|
|
978
|
+
}
|
|
979
|
+
return null;
|
|
980
|
+
}
|
|
981
|
+
function moveRangeBefore(parent, start, id, ref) {
|
|
982
|
+
const end = slotEnd(id);
|
|
983
|
+
let n = start;
|
|
984
|
+
while (n) {
|
|
985
|
+
const next = n.nextSibling;
|
|
986
|
+
const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
|
|
987
|
+
parent.insertBefore(n, ref);
|
|
988
|
+
if (isEnd) break;
|
|
989
|
+
n = next;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
function adoptRange(parent, start, id, ref, claim) {
|
|
993
|
+
const end = slotEnd(id);
|
|
994
|
+
let n = start;
|
|
995
|
+
let after = null;
|
|
996
|
+
while (n) {
|
|
997
|
+
const next = n.nextSibling;
|
|
998
|
+
const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
|
|
999
|
+
parent.insertBefore(n, ref);
|
|
1000
|
+
if (claim) claim(n);
|
|
1001
|
+
if (isEnd) {
|
|
1002
|
+
after = next;
|
|
1003
|
+
break;
|
|
1004
|
+
}
|
|
1005
|
+
n = next;
|
|
1006
|
+
}
|
|
1007
|
+
return after;
|
|
1008
|
+
}
|
|
1009
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null) {
|
|
1010
|
+
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1011
|
+
let newChild = source.firstChild;
|
|
1012
|
+
while (newChild) {
|
|
1013
|
+
const nextNew = newChild.nextSibling;
|
|
1014
|
+
const pid = slotStartId(newChild);
|
|
1015
|
+
const old = oldChild === boundEnd ? null : oldChild;
|
|
1016
|
+
if (pid !== null) {
|
|
1017
|
+
if (old && slotStartId(old) === pid) {
|
|
1018
|
+
oldChild = afterRange(old, pid);
|
|
1019
|
+
newChild = skipRange(newChild, pid);
|
|
1020
|
+
} else {
|
|
1021
|
+
const existing = findRangeStart(old, pid, boundEnd);
|
|
1022
|
+
if (existing) {
|
|
1023
|
+
moveRangeBefore(parent, existing, pid, old ?? boundEnd);
|
|
1024
|
+
newChild = skipRange(newChild, pid);
|
|
1025
|
+
} else {
|
|
1026
|
+
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
if (!old) {
|
|
1032
|
+
parent.insertBefore(newChild, boundEnd);
|
|
1033
|
+
if (claim) claim(newChild);
|
|
1034
|
+
newChild = nextNew;
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
if (isSlotMarker(old)) {
|
|
1038
|
+
parent.insertBefore(newChild, old);
|
|
1039
|
+
if (claim) claim(newChild);
|
|
1040
|
+
newChild = nextNew;
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
if (compatible(old, newChild)) {
|
|
1044
|
+
morphNode(old, newChild, claim);
|
|
1045
|
+
oldChild = old.nextSibling;
|
|
1046
|
+
newChild = nextNew;
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
if (newChild.nodeType === 1) {
|
|
1050
|
+
let ahead = old.nextSibling;
|
|
1051
|
+
while (ahead && ahead !== boundEnd && !compatible(ahead, newChild)) {
|
|
1052
|
+
const aheadPid = slotStartId(ahead);
|
|
1053
|
+
ahead = aheadPid !== null ? afterRange(ahead, aheadPid) : ahead.nextSibling;
|
|
1054
|
+
}
|
|
1055
|
+
if (ahead && ahead !== boundEnd) {
|
|
1056
|
+
parent.insertBefore(ahead, old);
|
|
1057
|
+
morphNode(ahead, newChild, claim);
|
|
1058
|
+
newChild = nextNew;
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
parent.insertBefore(newChild, old);
|
|
1063
|
+
if (claim) claim(newChild);
|
|
1064
|
+
newChild = nextNew;
|
|
1065
|
+
}
|
|
1066
|
+
while (oldChild && oldChild !== boundEnd) {
|
|
1067
|
+
const next = oldChild.nextSibling;
|
|
1068
|
+
parent.removeChild(oldChild);
|
|
1069
|
+
oldChild = next;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
Feature.AggregateError | Feature.BigIntTypedArray;
|
|
1074
|
+
const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
|
|
1075
|
+
CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
|
|
1076
|
+
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
|
|
1077
|
+
function resolveSerializerPlugins(customPlugins) {
|
|
1078
|
+
return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
|
|
1079
|
+
}
|
|
1080
|
+
const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
|
|
1081
|
+
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
1082
|
+
function resolveCodecOptions({
|
|
1083
|
+
plugins,
|
|
1084
|
+
disabledFeatures,
|
|
1085
|
+
depthLimit
|
|
1086
|
+
} = {}) {
|
|
1087
|
+
return {
|
|
1088
|
+
plugins: resolveSerializerPlugins(plugins),
|
|
1089
|
+
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
1090
|
+
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
function createJSONDeserializer(options) {
|
|
1094
|
+
const refs = new Map();
|
|
1095
|
+
const resolved = resolveCodecOptions(options);
|
|
1096
|
+
return function deserializeJSONChunk(node) {
|
|
1097
|
+
return fromCrossJSON(node, {
|
|
1098
|
+
refs,
|
|
1099
|
+
...resolved
|
|
1100
|
+
});
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function createJSONDataTable(options) {
|
|
1104
|
+
const deserialize = createJSONDeserializer(options);
|
|
1105
|
+
const table = new Map();
|
|
1106
|
+
return {
|
|
1107
|
+
apply(record) {
|
|
1108
|
+
const value = deserialize(record.node);
|
|
1109
|
+
if (record.initial) table.set(record.key, value);
|
|
1110
|
+
},
|
|
1111
|
+
get(key) {
|
|
1112
|
+
return table.get(key);
|
|
1113
|
+
},
|
|
1114
|
+
resolve(ref) {
|
|
1115
|
+
return table.get(ref.$ref);
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
class ChunkReader {
|
|
1121
|
+
constructor(stream) {
|
|
1122
|
+
this.reader = stream.getReader();
|
|
1123
|
+
this.buffer = new Uint8Array(0);
|
|
1124
|
+
this.done = false;
|
|
1125
|
+
}
|
|
1126
|
+
async readChunk() {
|
|
1127
|
+
const chunk = await this.reader.read();
|
|
1128
|
+
if (!chunk.done) {
|
|
1129
|
+
const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
|
|
1130
|
+
newBuffer.set(this.buffer);
|
|
1131
|
+
newBuffer.set(chunk.value, this.buffer.length);
|
|
1132
|
+
this.buffer = newBuffer;
|
|
1133
|
+
} else {
|
|
1134
|
+
this.done = true;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
async next() {
|
|
1138
|
+
if (this.buffer.length === 0) {
|
|
1139
|
+
if (this.done) {
|
|
1140
|
+
return {
|
|
1141
|
+
done: true,
|
|
1142
|
+
value: undefined
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
await this.readChunk();
|
|
1146
|
+
return await this.next();
|
|
1147
|
+
}
|
|
1148
|
+
const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
|
|
1149
|
+
const bytes = Number.parseInt(head, 16);
|
|
1150
|
+
if (Number.isNaN(bytes)) {
|
|
1151
|
+
throw new Error("Malformed server function stream.");
|
|
1152
|
+
}
|
|
1153
|
+
while (bytes > this.buffer.length - 12) {
|
|
1154
|
+
if (this.done) {
|
|
1155
|
+
throw new Error("Malformed server function stream.");
|
|
1156
|
+
}
|
|
1157
|
+
await this.readChunk();
|
|
1158
|
+
}
|
|
1159
|
+
const partial = new TextDecoder().decode(this.buffer.subarray(12, 12 + bytes));
|
|
1160
|
+
this.buffer = this.buffer.subarray(12 + bytes);
|
|
1161
|
+
return {
|
|
1162
|
+
done: false,
|
|
1163
|
+
value: partial
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
async drain(interpret) {
|
|
1167
|
+
while (true) {
|
|
1168
|
+
const result = await this.next();
|
|
1169
|
+
if (result.done) {
|
|
1170
|
+
break;
|
|
1171
|
+
}
|
|
1172
|
+
interpret(result.value);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
const FRAME_STREAM_HEADER = "X-Frame-Stream";
|
|
1178
|
+
function isFrameStreamResponse(response) {
|
|
1179
|
+
return response.headers.has(FRAME_STREAM_HEADER);
|
|
1180
|
+
}
|
|
1181
|
+
async function applyFrameResponse(response, host, options = {}) {
|
|
1182
|
+
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1183
|
+
const as = options.as;
|
|
1184
|
+
const version = options.version;
|
|
1185
|
+
const reader = new ChunkReader(response.body);
|
|
1186
|
+
let result = await reader.next();
|
|
1187
|
+
while (!result.done) {
|
|
1188
|
+
const chunk = JSON.parse(result.value);
|
|
1189
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1190
|
+
if (version !== undefined) chunk.version = version;
|
|
1191
|
+
host.apply(chunk);
|
|
1192
|
+
result = await reader.next();
|
|
1193
|
+
}
|
|
1194
|
+
return as !== undefined ? as : rootId;
|
|
1195
|
+
}
|
|
1196
|
+
function createServerComponentHandler({
|
|
1197
|
+
host,
|
|
1198
|
+
component,
|
|
1199
|
+
capture,
|
|
1200
|
+
onStream,
|
|
1201
|
+
documentComponent,
|
|
1202
|
+
intercept
|
|
1203
|
+
}) {
|
|
1204
|
+
const byContext = new WeakMap();
|
|
1205
|
+
const byFunction = new Map();
|
|
1206
|
+
let boundary = 0;
|
|
1207
|
+
return {
|
|
1208
|
+
capture,
|
|
1209
|
+
intercept,
|
|
1210
|
+
handle(response, ctx) {
|
|
1211
|
+
if (!isFrameStreamResponse(response)) return undefined;
|
|
1212
|
+
const key = ctx.context;
|
|
1213
|
+
const keyed = key !== null && typeof key === "object";
|
|
1214
|
+
let entry = keyed ? byContext.get(key) : byFunction.get(ctx.id);
|
|
1215
|
+
if (!entry) {
|
|
1216
|
+
const adopted = documentComponent && documentComponent(ctx.id);
|
|
1217
|
+
if (adopted) {
|
|
1218
|
+
entry = {
|
|
1219
|
+
frameId: ctx.id,
|
|
1220
|
+
version: 0,
|
|
1221
|
+
component: adopted
|
|
1222
|
+
};
|
|
1223
|
+
} else {
|
|
1224
|
+
const frameId = `sc:${boundary++}`;
|
|
1225
|
+
entry = {
|
|
1226
|
+
frameId,
|
|
1227
|
+
version: 0,
|
|
1228
|
+
component: component(frameId)
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
keyed ? byContext.set(key, entry) : byFunction.set(ctx.id, entry);
|
|
1232
|
+
}
|
|
1233
|
+
const version = ++entry.version;
|
|
1234
|
+
if (onStream) onStream(entry.frameId, version, response);
|
|
1235
|
+
applyFrameResponse(response, host, {
|
|
1236
|
+
as: entry.frameId,
|
|
1237
|
+
version
|
|
1238
|
+
}).catch(err => host.apply({
|
|
1239
|
+
type: "error",
|
|
1240
|
+
id: entry.frameId,
|
|
1241
|
+
version,
|
|
1242
|
+
error: {
|
|
1243
|
+
message: String(err && err.message)
|
|
1244
|
+
}
|
|
1245
|
+
}));
|
|
1246
|
+
return entry.component;
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
let sharedHost;
|
|
1252
|
+
const tables = new Map();
|
|
1253
|
+
function tableFor(id) {
|
|
1254
|
+
const table = tables.get(id);
|
|
1255
|
+
if (table) return table;
|
|
1256
|
+
for (const [root, t] of tables) if (id.startsWith(root + ".")) return t;
|
|
1257
|
+
return undefined;
|
|
1258
|
+
}
|
|
1259
|
+
function getFrameHost() {
|
|
1260
|
+
if (!sharedHost) {
|
|
1261
|
+
sharedHost = createFrameHost({
|
|
1262
|
+
applyData: c => tableFor(c.id)?.apply(c),
|
|
1263
|
+
resolve: (ref, id) => tableFor(id)?.resolve(ref)
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
return sharedHost;
|
|
1267
|
+
}
|
|
1268
|
+
function normalizeSlotContent(value) {
|
|
1269
|
+
while (typeof value === "function") value = value();
|
|
1270
|
+
if (Array.isArray(value)) {
|
|
1271
|
+
const out = [];
|
|
1272
|
+
for (const v of value) {
|
|
1273
|
+
const n = normalizeSlotContent(v);
|
|
1274
|
+
Array.isArray(n) ? out.push(...n) : out.push(n);
|
|
1275
|
+
}
|
|
1276
|
+
return out;
|
|
1277
|
+
}
|
|
1278
|
+
if (value == null || typeof value === "boolean") return document.createTextNode("");
|
|
1279
|
+
return value instanceof Node ? value : document.createTextNode(String(value));
|
|
1280
|
+
}
|
|
1281
|
+
function claimRender(prefix, existing, render) {
|
|
1282
|
+
const sc = sharedConfig;
|
|
1283
|
+
if (!sc.getNextContextId) return render();
|
|
1284
|
+
const registry = new Map();
|
|
1285
|
+
for (const n of existing) {
|
|
1286
|
+
const el = n;
|
|
1287
|
+
if (el.nodeType !== 1) continue;
|
|
1288
|
+
if (el.hasAttribute("_hk")) registry.set(el.getAttribute("_hk"), el);
|
|
1289
|
+
el.querySelectorAll("*[_hk]").forEach(child => registry.set(child.getAttribute("_hk"), child));
|
|
1290
|
+
}
|
|
1291
|
+
if (!registry.size) return render();
|
|
1292
|
+
const prevRegistry = sc.registry;
|
|
1293
|
+
const prevHydrating = sc.hydrating;
|
|
1294
|
+
sc.registry = registry;
|
|
1295
|
+
sc.hydrating = true;
|
|
1296
|
+
try {
|
|
1297
|
+
return runWithOwner(createOwner({
|
|
1298
|
+
id: prefix
|
|
1299
|
+
}), render);
|
|
1300
|
+
} finally {
|
|
1301
|
+
sc.registry = prevRegistry;
|
|
1302
|
+
sc.hydrating = prevHydrating;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
function slotsFor(props) {
|
|
1306
|
+
return new Proxy({}, {
|
|
1307
|
+
get(_, prop) {
|
|
1308
|
+
if (typeof prop !== "string" || !(prop in props)) return undefined;
|
|
1309
|
+
return (slotProps, ctx) => {
|
|
1310
|
+
const settle = out => {
|
|
1311
|
+
const existing = ctx && ctx.existing || [];
|
|
1312
|
+
if (existing.length) {
|
|
1313
|
+
const list = Array.isArray(out) ? out : [out];
|
|
1314
|
+
const inPlace = list.every(n => existing.some(e => e === n || e.nodeType === 1 && e.contains(n)));
|
|
1315
|
+
if (inPlace) return undefined;
|
|
1316
|
+
}
|
|
1317
|
+
return out;
|
|
1318
|
+
};
|
|
1319
|
+
const render = () => {
|
|
1320
|
+
const v = props[prop];
|
|
1321
|
+
return settle(normalizeSlotContent(typeof v === "function" ? v(slotProps) : v));
|
|
1322
|
+
};
|
|
1323
|
+
if (ctx && ctx.frame && ctx.existing && ctx.existing.length) {
|
|
1324
|
+
return claimRender(`sc-${ctx.frame}-${ctx.key}-`, ctx.existing, render);
|
|
1325
|
+
}
|
|
1326
|
+
return render();
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
function boundaryComponent(host, id) {
|
|
1332
|
+
return props => {
|
|
1333
|
+
const owner = getOwner();
|
|
1334
|
+
const insertable = createFrameInsertable({
|
|
1335
|
+
host,
|
|
1336
|
+
id,
|
|
1337
|
+
slots: slotsFor(props),
|
|
1338
|
+
ownerScope: fn => runWithOwner(owner, fn)
|
|
1339
|
+
});
|
|
1340
|
+
onCleanup(() => insertable.dispose());
|
|
1341
|
+
return insertable;
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
const claimedBoundaries = new Set();
|
|
1345
|
+
let boundaryIndex = null;
|
|
1346
|
+
function findBoundaryRange(id) {
|
|
1347
|
+
if (!boundaryIndex) {
|
|
1348
|
+
boundaryIndex = new Map();
|
|
1349
|
+
if (typeof document !== "undefined" && document.body) {
|
|
1350
|
+
const walker = document.createTreeWalker(document.body, 128 );
|
|
1351
|
+
const opens = {};
|
|
1352
|
+
let c;
|
|
1353
|
+
while (c = walker.nextNode()) {
|
|
1354
|
+
const d = c.data;
|
|
1355
|
+
if (!d.startsWith("frame:")) continue;
|
|
1356
|
+
if (d.endsWith(":start")) {
|
|
1357
|
+
const key = d.slice(6, -6);
|
|
1358
|
+
if (key && !(key in opens)) opens[key] = c;
|
|
1359
|
+
} else if (d.endsWith(":end")) {
|
|
1360
|
+
const key = d.slice(6, -4);
|
|
1361
|
+
if (key && opens[key] && !boundaryIndex.has(key)) {
|
|
1362
|
+
boundaryIndex.set(key, [opens[key], c]);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return boundaryIndex.get(id);
|
|
1369
|
+
}
|
|
1370
|
+
function documentBoundary(host, id, props) {
|
|
1371
|
+
const range = !claimedBoundaries.has(id) && findBoundaryRange(id);
|
|
1372
|
+
if (!range) return boundaryComponent(host, id)(props);
|
|
1373
|
+
claimedBoundaries.add(id);
|
|
1374
|
+
const [start, end] = range;
|
|
1375
|
+
const hy = globalThis._$HY;
|
|
1376
|
+
if (hy && hy.r) {
|
|
1377
|
+
const slotPrefix = `sc:slot:${id}:`;
|
|
1378
|
+
for (const key of Object.keys(hy.r)) {
|
|
1379
|
+
if (key.startsWith(slotPrefix)) {
|
|
1380
|
+
host.apply({
|
|
1381
|
+
type: "slot",
|
|
1382
|
+
id,
|
|
1383
|
+
version: 0,
|
|
1384
|
+
key: key.slice(slotPrefix.length),
|
|
1385
|
+
args: hy.r[key]
|
|
1386
|
+
});
|
|
1387
|
+
} else if (key.startsWith("sc:region:")) {
|
|
1388
|
+
const childId = key.slice("sc:region:".length);
|
|
1389
|
+
if (childId.startsWith(id + ".")) {
|
|
1390
|
+
const val = hy.r[key];
|
|
1391
|
+
const apply = html => host.apply({
|
|
1392
|
+
type: "html",
|
|
1393
|
+
id: childId,
|
|
1394
|
+
version: 0,
|
|
1395
|
+
html
|
|
1396
|
+
});
|
|
1397
|
+
val && typeof val.then === "function" ? val.then(apply) : apply(val);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
const owner = getOwner();
|
|
1403
|
+
const frame = adoptFrameRange(start, end, {
|
|
1404
|
+
host,
|
|
1405
|
+
id,
|
|
1406
|
+
slots: slotsFor(props),
|
|
1407
|
+
ownerScope: fn => runWithOwner(owner, fn)
|
|
1408
|
+
});
|
|
1409
|
+
onCleanup(() => frame.dispose());
|
|
1410
|
+
const nodes = [];
|
|
1411
|
+
for (let n = start; n; n = n.nextSibling) {
|
|
1412
|
+
nodes.push(n);
|
|
1413
|
+
if (n === end) break;
|
|
1414
|
+
}
|
|
1415
|
+
return nodes;
|
|
1416
|
+
}
|
|
1417
|
+
function installServerComponents(host = getFrameHost()) {
|
|
1418
|
+
const g = globalThis;
|
|
1419
|
+
if (!g._$SC) {
|
|
1420
|
+
g._$SC = {
|
|
1421
|
+
c: {},
|
|
1422
|
+
r(i) {
|
|
1423
|
+
return g._$SC.c[i] || (g._$SC.c[i] = p => g._$SC.impl(i, p));
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
g._$SC.impl = (id, props) => documentBoundary(host, id, props);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
export { FRAME_APPLIED_EVENT, FRAME_STREAM_HEADER, applyFrameResponse, createFrame, createFrameHost, createFrameInsertable, createJSONDataTable, createServerComponentHandler, getFrameHost, installServerComponents, isFrameStreamResponse };
|