@solidjs/web 2.0.0-experimental.8 → 2.0.0-rc.0
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 +22 -4
- package/dist/dev.cjs +1585 -225
- package/dist/dev.js +1510 -201
- package/dist/server.cjs +2642 -264
- package/dist/server.js +2542 -217
- package/dist/web.cjs +1523 -218
- package/dist/web.js +1448 -194
- package/frames/dist/client.cjs +1916 -0
- package/frames/dist/client.dev.cjs +1933 -0
- package/frames/dist/client.dev.js +1921 -0
- package/frames/dist/client.js +1904 -0
- package/frames/dist/server.cjs +3667 -0
- package/frames/dist/server.js +3654 -0
- package/frames/package.json +30 -0
- package/package.json +349 -37
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +110 -0
- package/serialization/dist/decode.js +104 -0
- package/serialization/dist/serialization.cjs +232 -0
- package/serialization/dist/serialization.js +215 -0
- package/serialization/package.json +20 -0
- package/serialization/types/index.d.ts +182 -0
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +182 -0
- package/serialization/types-cjs/package.json +3 -0
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +646 -0
- package/server-functions/dist/client.js +617 -0
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +1077 -0
- package/server-functions/dist/server.dev.cjs +1077 -0
- package/server-functions/dist/server.dev.js +1045 -0
- package/server-functions/dist/server.js +1045 -0
- package/server-functions/package.json +40 -0
- package/server-functions/rich-args/package.json +20 -0
- package/storage/package.json +8 -3
- package/storage/types/index.d.ts +26 -0
- package/storage/types-cjs/index.d.cts +28 -0
- package/storage/types-cjs/package.json +3 -0
- package/types/client.d.ts +290 -27
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +6 -2
- package/types/frames/client.d.ts +36 -0
- package/types/frames/frame-client.d.ts +338 -0
- package/types/frames/frame-sink.d.ts +194 -0
- package/types/frames/frame-transport.d.ts +222 -0
- package/types/frames/serializer.d.ts +182 -0
- package/types/frames/server.d.ts +52 -0
- package/types/index.d.ts +209 -24
- package/types/jsx-properties.d.ts +93 -0
- package/types/jsx.d.ts +4150 -1
- package/types/response.d.ts +174 -0
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +182 -0
- package/types/server-functions/client.d.ts +201 -0
- package/types/server-functions/flash.d.ts +38 -0
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +588 -0
- package/types/server-functions/shared.d.ts +523 -0
- package/types/server-mock.d.ts +249 -12
- package/types/server.d.ts +424 -51
- package/types-cjs/client.d.cts +337 -0
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +6 -0
- package/types-cjs/frames/client.d.cts +36 -0
- package/types-cjs/frames/frame-client.d.cts +338 -0
- package/types-cjs/frames/frame-sink.d.cts +194 -0
- package/types-cjs/frames/frame-transport.d.cts +222 -0
- package/types-cjs/frames/serializer.d.cts +182 -0
- package/types-cjs/frames/server.d.cts +52 -0
- package/types-cjs/index.d.cts +230 -0
- package/types-cjs/jsx-properties.d.cts +93 -0
- package/types-cjs/jsx.d.cts +4150 -0
- package/types-cjs/package.json +3 -0
- package/types-cjs/response.d.cts +174 -0
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +182 -0
- package/types-cjs/server-functions/client.d.cts +201 -0
- package/types-cjs/server-functions/flash.d.cts +38 -0
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +588 -0
- package/types-cjs/server-functions/shared.d.cts +523 -0
- package/types-cjs/server-mock.d.cts +277 -0
- package/types-cjs/server.d.cts +523 -0
|
@@ -0,0 +1,1916 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var solidJs = require('solid-js');
|
|
4
|
+
var web = require('@solidjs/web');
|
|
5
|
+
var client = require('@solidjs/web/server-functions/client');
|
|
6
|
+
|
|
7
|
+
const ELEMENT_NODE = 1;
|
|
8
|
+
const TEXT_NODE = 3;
|
|
9
|
+
const COMMENT_NODE = 8;
|
|
10
|
+
const CLAIM_SEAM = Symbol.for("dom-expressions.element-claims");
|
|
11
|
+
const CLAIMED_ELEMENTS = "a[href], form[action]";
|
|
12
|
+
function claimHandlers() {
|
|
13
|
+
const handlers = globalThis[CLAIM_SEAM];
|
|
14
|
+
return handlers !== undefined && handlers.length !== 0 ? handlers : undefined;
|
|
15
|
+
}
|
|
16
|
+
function claimNode(handlers, el) {
|
|
17
|
+
for (let i = 0; i < handlers.length; i++) handlers[i](el);
|
|
18
|
+
}
|
|
19
|
+
const claimedAttr = name => name === "href" || name === "action";
|
|
20
|
+
function claimTree(handlers, root) {
|
|
21
|
+
const isElement = root.nodeType === ELEMENT_NODE;
|
|
22
|
+
if (!isElement && root.nodeType !== 11 ) return;
|
|
23
|
+
if (isElement && root.matches(CLAIMED_ELEMENTS)) claimNode(handlers, root);
|
|
24
|
+
const found = root.querySelectorAll(CLAIMED_ELEMENTS);
|
|
25
|
+
for (let i = 0; i < found.length; i++) claimNode(handlers, found[i]);
|
|
26
|
+
}
|
|
27
|
+
const placeholderId = name => `pl-${name}`;
|
|
28
|
+
const SLOT_START = /^slot:(.+):start$/;
|
|
29
|
+
const SLOT_END = /^slot:(.+):end$/;
|
|
30
|
+
const slotEnd = id => `slot:${id}:end`;
|
|
31
|
+
function chunkToRecords(chunk) {
|
|
32
|
+
switch (chunk.type) {
|
|
33
|
+
case "start":
|
|
34
|
+
case "data":
|
|
35
|
+
return {};
|
|
36
|
+
case "html":
|
|
37
|
+
return {
|
|
38
|
+
"": {
|
|
39
|
+
kind: "html",
|
|
40
|
+
value: chunk.html
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
case "fragment":
|
|
44
|
+
return {
|
|
45
|
+
[`seg:${chunk.key}`]: {
|
|
46
|
+
kind: "html",
|
|
47
|
+
value: chunk.html
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
case "reveal":
|
|
51
|
+
{
|
|
52
|
+
const records = {};
|
|
53
|
+
const gate = chunk.fallback ? "fallback" : "reveal";
|
|
54
|
+
for (const key of chunk.keys) records[`seg:${key}:${gate}`] = true;
|
|
55
|
+
return records;
|
|
56
|
+
}
|
|
57
|
+
case "assets":
|
|
58
|
+
return {
|
|
59
|
+
[`seg:${chunk.key}:assets`]: chunk
|
|
60
|
+
};
|
|
61
|
+
case "slot":
|
|
62
|
+
return {
|
|
63
|
+
[`slot:${chunk.key}`]: {
|
|
64
|
+
kind: "slot",
|
|
65
|
+
args: chunk.args
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
case "hole":
|
|
69
|
+
return {
|
|
70
|
+
[`hole:${chunk.key}`]: {
|
|
71
|
+
kind: "html",
|
|
72
|
+
value: chunk.html
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
case "attr":
|
|
76
|
+
return {
|
|
77
|
+
[`attr:${chunk.key}`]: {
|
|
78
|
+
kind: "attrs",
|
|
79
|
+
value: chunk.attrs,
|
|
80
|
+
removed: chunk.removed
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
case "complete":
|
|
84
|
+
return {
|
|
85
|
+
":complete": true
|
|
86
|
+
};
|
|
87
|
+
case "error":
|
|
88
|
+
if (!chunk.key) return {
|
|
89
|
+
":error": chunk.error
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
[`${/^lha?:/.test(chunk.key) ? "hole" : "seg"}:${chunk.key}:error`]: chunk.error
|
|
93
|
+
};
|
|
94
|
+
default:
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function createFrameHost(options = {}) {
|
|
99
|
+
const frames = new Map();
|
|
100
|
+
const stores = new Map();
|
|
101
|
+
const storeFor = id => {
|
|
102
|
+
let store = stores.get(id);
|
|
103
|
+
if (!store) stores.set(id, store = {
|
|
104
|
+
version: undefined,
|
|
105
|
+
records: {}
|
|
106
|
+
});
|
|
107
|
+
return store;
|
|
108
|
+
};
|
|
109
|
+
const write = (store, version, records) => {
|
|
110
|
+
if (store.version !== undefined && version < store.version) return false;
|
|
111
|
+
if (store.version === undefined || version > store.version) {
|
|
112
|
+
store.version = version;
|
|
113
|
+
clearStreamRecords(store.records);
|
|
114
|
+
}
|
|
115
|
+
Object.assign(store.records, records);
|
|
116
|
+
return true;
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
register(id, frame) {
|
|
120
|
+
let set = frames.get(id);
|
|
121
|
+
if (!set) frames.set(id, set = new Set());
|
|
122
|
+
set.add(frame);
|
|
123
|
+
const store = stores.get(id);
|
|
124
|
+
if (store && store.version !== undefined) {
|
|
125
|
+
frame.apply({
|
|
126
|
+
version: store.version,
|
|
127
|
+
r: store.records
|
|
128
|
+
});
|
|
129
|
+
frame.rebase && frame.rebase();
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
unregister(id, frame) {
|
|
133
|
+
const set = frames.get(id);
|
|
134
|
+
if (set && frame) set.delete(frame);
|
|
135
|
+
if (!set || !frame || !set.size) {
|
|
136
|
+
frames.delete(id);
|
|
137
|
+
if (frame && frame.contentHTML) {
|
|
138
|
+
const store = storeFor(id);
|
|
139
|
+
if (!store.records[""]) {
|
|
140
|
+
const html = frame.contentHTML();
|
|
141
|
+
if (html != null) {
|
|
142
|
+
store.records[""] = {
|
|
143
|
+
kind: "html",
|
|
144
|
+
value: html
|
|
145
|
+
};
|
|
146
|
+
if (store.version === undefined) store.version = 0;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (!frame) stores.delete(id);
|
|
152
|
+
},
|
|
153
|
+
apply(chunk) {
|
|
154
|
+
if (chunk.type === "data") {
|
|
155
|
+
options.applyData && options.applyData(chunk);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const records = chunkToRecords(chunk);
|
|
159
|
+
if (!write(storeFor(chunk.id), chunk.version, records)) return;
|
|
160
|
+
const set = frames.get(chunk.id);
|
|
161
|
+
if (set) {
|
|
162
|
+
for (const frame of set) frame.apply({
|
|
163
|
+
version: chunk.version,
|
|
164
|
+
r: records
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
get(id) {
|
|
169
|
+
const set = frames.get(id);
|
|
170
|
+
return set && set.values().next().value;
|
|
171
|
+
},
|
|
172
|
+
serialize(value) {
|
|
173
|
+
if (!options.serialize) throw new Error("host has no serializer");
|
|
174
|
+
return options.serialize(value);
|
|
175
|
+
},
|
|
176
|
+
resolve(ref, frameId) {
|
|
177
|
+
return options.resolve ? options.resolve(ref, frameId) : undefined;
|
|
178
|
+
},
|
|
179
|
+
revive: options.revive,
|
|
180
|
+
isContainer: options.isContainer,
|
|
181
|
+
prepareData: options.prepareData
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const FRAME_APPLIED_EVENT = "frame:applied";
|
|
185
|
+
class FrameImpl {
|
|
186
|
+
#element;
|
|
187
|
+
#start;
|
|
188
|
+
#end;
|
|
189
|
+
#options;
|
|
190
|
+
#version;
|
|
191
|
+
#store = Object.create(null);
|
|
192
|
+
#appliedRootValue;
|
|
193
|
+
#hasContent = false;
|
|
194
|
+
#errorNotified = false;
|
|
195
|
+
#revealed = new Set();
|
|
196
|
+
#fallbackShown = new Set();
|
|
197
|
+
#appliedHoles = new Map();
|
|
198
|
+
#slots;
|
|
199
|
+
#mountedSlots = new Set();
|
|
200
|
+
#slotCleanups = new Map();
|
|
201
|
+
#slotArgs = new Map();
|
|
202
|
+
#slotUpdaters = new Map();
|
|
203
|
+
#slotRegions = new Map();
|
|
204
|
+
#slotResolvedRefs = new Map();
|
|
205
|
+
#slotNodes = new Map();
|
|
206
|
+
#processedAssets = new Set();
|
|
207
|
+
#recordRefresh = null;
|
|
208
|
+
#disposed = false;
|
|
209
|
+
#styleFlush = () => {
|
|
210
|
+
if (!this.#disposed) this.#flush();
|
|
211
|
+
};
|
|
212
|
+
#claimTree = (node, direct) => {
|
|
213
|
+
const handlers = claimHandlers();
|
|
214
|
+
if (!handlers) return;
|
|
215
|
+
this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
|
|
216
|
+
};
|
|
217
|
+
#scoped(fn) {
|
|
218
|
+
const scope = this.#options.ownerScope;
|
|
219
|
+
return scope ? scope(fn) : fn();
|
|
220
|
+
}
|
|
221
|
+
constructor(element, start, end, options = {}) {
|
|
222
|
+
this.#element = element;
|
|
223
|
+
this.#start = start;
|
|
224
|
+
this.#end = end;
|
|
225
|
+
this.#options = options;
|
|
226
|
+
this.#slots = options.slots;
|
|
227
|
+
if (options.adopt) {
|
|
228
|
+
this.#hasContent = true;
|
|
229
|
+
this.#claimContent();
|
|
230
|
+
}
|
|
231
|
+
if (options.host && options.id !== undefined) {
|
|
232
|
+
options.host.register(options.id, this);
|
|
233
|
+
}
|
|
234
|
+
if (options.adopt && this.#version === undefined) this.#syncSlots();
|
|
235
|
+
}
|
|
236
|
+
#parent() {
|
|
237
|
+
return this.#element ?? this.#start.parentNode;
|
|
238
|
+
}
|
|
239
|
+
#applied(version, reason) {
|
|
240
|
+
this.#options.onApply?.({
|
|
241
|
+
version,
|
|
242
|
+
reason
|
|
243
|
+
});
|
|
244
|
+
const parent = this.#parent();
|
|
245
|
+
const Ev = parent && (parent.ownerDocument || parent).defaultView?.CustomEvent;
|
|
246
|
+
if (Ev) {
|
|
247
|
+
parent.dispatchEvent(new Ev(FRAME_APPLIED_EVENT, {
|
|
248
|
+
bubbles: true,
|
|
249
|
+
detail: {
|
|
250
|
+
id: this.#options.id,
|
|
251
|
+
version,
|
|
252
|
+
reason
|
|
253
|
+
}
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
#firstContent() {
|
|
258
|
+
return this.#start ? this.#start.nextSibling : this.#parent().firstChild;
|
|
259
|
+
}
|
|
260
|
+
get version() {
|
|
261
|
+
return this.#version;
|
|
262
|
+
}
|
|
263
|
+
get store() {
|
|
264
|
+
return this.#store;
|
|
265
|
+
}
|
|
266
|
+
isRevealed(segment) {
|
|
267
|
+
return this.#revealed.has(segment);
|
|
268
|
+
}
|
|
269
|
+
get error() {
|
|
270
|
+
return this.#store[":error"];
|
|
271
|
+
}
|
|
272
|
+
apply(write) {
|
|
273
|
+
if (this.#disposed) return;
|
|
274
|
+
const v = write.version;
|
|
275
|
+
if (this.#version === undefined) {
|
|
276
|
+
this.#version = v;
|
|
277
|
+
} else if (v < this.#version) {
|
|
278
|
+
return;
|
|
279
|
+
} else if (v > this.#version) {
|
|
280
|
+
this.#version = v;
|
|
281
|
+
this.#resetStreamState();
|
|
282
|
+
}
|
|
283
|
+
for (const key in write.r) {
|
|
284
|
+
const incoming = write.r[key];
|
|
285
|
+
if (incoming && incoming.kind === "slot" && key.charCodeAt(0) === 115 && key.startsWith("slot:")) {
|
|
286
|
+
const existing = this.#store[key];
|
|
287
|
+
if (existing && existing.kind === "slot" && argsEquivalent(existing.args, incoming.args)) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
this.#store[key] = incoming;
|
|
292
|
+
}
|
|
293
|
+
this.#flush();
|
|
294
|
+
}
|
|
295
|
+
#resetStreamState(root) {
|
|
296
|
+
this.#revealed.clear();
|
|
297
|
+
this.#fallbackShown.clear();
|
|
298
|
+
this.#appliedHoles.clear();
|
|
299
|
+
this.#errorNotified = false;
|
|
300
|
+
clearStreamRecords(this.#store, root);
|
|
301
|
+
}
|
|
302
|
+
#flush() {
|
|
303
|
+
if (this.#disposed) return;
|
|
304
|
+
const version = this.#version;
|
|
305
|
+
const root = this.#store[""];
|
|
306
|
+
if (root && root.kind === "html" && root.value !== this.#appliedRootValue) {
|
|
307
|
+
const reason = this.#hasContent ? "morph" : "materialize";
|
|
308
|
+
this.#applyRoot(root.value);
|
|
309
|
+
this.#appliedRootValue = root.value;
|
|
310
|
+
this.#applied(version, reason);
|
|
311
|
+
}
|
|
312
|
+
if (this.#store[":error"] && !this.#errorNotified) {
|
|
313
|
+
this.#errorNotified = true;
|
|
314
|
+
this.#applied(version, "error");
|
|
315
|
+
}
|
|
316
|
+
let progressed = true;
|
|
317
|
+
while (progressed) {
|
|
318
|
+
progressed = false;
|
|
319
|
+
for (const key in this.#store) {
|
|
320
|
+
const name = segmentName(key);
|
|
321
|
+
if (name === null || this.#revealed.has(name)) continue;
|
|
322
|
+
if (this.#segmentReady(name)) {
|
|
323
|
+
this.#revealSegment(name);
|
|
324
|
+
this.#applied(version, "reveal");
|
|
325
|
+
progressed = true;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
for (const key in this.#store) {
|
|
329
|
+
const m = /^seg:([^:]+):fallback$/.exec(key);
|
|
330
|
+
if (!m) continue;
|
|
331
|
+
const name = m[1];
|
|
332
|
+
if (this.#revealed.has(name) || this.#fallbackShown.has(name)) continue;
|
|
333
|
+
if (this.#showFallback(name)) {
|
|
334
|
+
this.#fallbackShown.add(name);
|
|
335
|
+
this.#applied(version, "reveal");
|
|
336
|
+
progressed = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
for (const key in this.#store) {
|
|
341
|
+
const record = this.#store[key];
|
|
342
|
+
if (!record || this.#appliedHoles.get(key) === record) continue;
|
|
343
|
+
if (key.startsWith("hole:")) {
|
|
344
|
+
if (key.endsWith(":error")) {
|
|
345
|
+
this.#appliedHoles.set(key, record);
|
|
346
|
+
} else if (this.#applyHole(key.slice(5), record.value)) {
|
|
347
|
+
this.#appliedHoles.set(key, record);
|
|
348
|
+
this.#applied(version, "morph");
|
|
349
|
+
}
|
|
350
|
+
} else if (key.startsWith("attr:")) {
|
|
351
|
+
if (this.#applyAttrs(key.slice(5), record.value, record.removed)) {
|
|
352
|
+
this.#appliedHoles.set(key, record);
|
|
353
|
+
this.#applied(version, "morph");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
for (const key in this.#store) {
|
|
358
|
+
if (this.#processedAssets.has(key) || !key.endsWith(":assets")) continue;
|
|
359
|
+
this.#processedAssets.add(key);
|
|
360
|
+
const record = this.#store[key];
|
|
361
|
+
if (record && record.modules) {
|
|
362
|
+
for (const href of record.modules) ensureModulePreload(href);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
this.#syncSlots();
|
|
366
|
+
}
|
|
367
|
+
#resolveSlot(prop) {
|
|
368
|
+
return this.#slots?.[prop] ?? this.#options.resolveSlot?.(prop);
|
|
369
|
+
}
|
|
370
|
+
#resolveSlotRecord(occurrence) {
|
|
371
|
+
const record = this.#store[`slot:${occurrence}`];
|
|
372
|
+
if (record !== undefined) return record;
|
|
373
|
+
return this.#options.resolveSlotRecord?.(occurrence);
|
|
374
|
+
}
|
|
375
|
+
#removeSlotRecord(occurrence) {
|
|
376
|
+
const key = `slot:${occurrence}`;
|
|
377
|
+
if (key in this.#store) {
|
|
378
|
+
if (!this.#mountedSlots.has(occurrence)) delete this.#store[key];
|
|
379
|
+
} else this.#options.removeSlotRecord?.(occurrence);
|
|
380
|
+
}
|
|
381
|
+
#syncSlots(root) {
|
|
382
|
+
if (!this.#slots && !this.#options.resolveSlot) return;
|
|
383
|
+
const found = new Map();
|
|
384
|
+
if (root) collectSlots(root.firstChild, null, found);else this.#collectSlots(found);
|
|
385
|
+
for (const [occurrence, start] of found) {
|
|
386
|
+
const callback = this.#resolveSlot(propOf(occurrence));
|
|
387
|
+
if (!callback) continue;
|
|
388
|
+
const record = this.#resolveSlotRecord(occurrence);
|
|
389
|
+
if (record && record.kind === "slot" && this.#refsUnresolved(record.args)) continue;
|
|
390
|
+
const prev = this.#slotNodes.get(occurrence);
|
|
391
|
+
const prevFirst = Array.isArray(prev) ? prev[0] : prev;
|
|
392
|
+
const zombie = this.#mountedSlots.has(occurrence) && prevFirst && !prevFirst.parentNode;
|
|
393
|
+
if (zombie) {
|
|
394
|
+
this.#mountedSlots.delete(occurrence);
|
|
395
|
+
this.#runSlotCleanups(occurrence);
|
|
396
|
+
}
|
|
397
|
+
if (!this.#mountedSlots.has(occurrence)) {
|
|
398
|
+
if (record === undefined && !root && this.#options.adopt && this.#options.recordsPending?.()) {
|
|
399
|
+
this.#recordRefresh ??= setTimeout(() => {
|
|
400
|
+
this.#recordRefresh = null;
|
|
401
|
+
if (this.#disposed) return;
|
|
402
|
+
this.#options.drainRecords?.();
|
|
403
|
+
this.#syncSlots();
|
|
404
|
+
});
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
if (this.#options.adopt) this.#discoverRegions(occurrence, start);
|
|
408
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start, this.#options.adopt);
|
|
409
|
+
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
410
|
+
this.#slotNodes.set(occurrence, nodes);
|
|
411
|
+
this.#mountedSlots.add(occurrence);
|
|
412
|
+
if (!this.#options.adopt || nodes) this.#discoverRegions(occurrence, start);
|
|
413
|
+
this.#bindRegions(occurrence);
|
|
414
|
+
} else if (record !== this.#slotArgs.get(occurrence)) {
|
|
415
|
+
if (this.#refArgsUnchanged(occurrence, record)) {
|
|
416
|
+
this.#slotArgs.set(occurrence, record);
|
|
417
|
+
this.#reconcileRegions(occurrence, record);
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const update = this.#slotUpdaters.get(occurrence);
|
|
421
|
+
if (update) {
|
|
422
|
+
const props = this.#resolveArgs(occurrence, record.args);
|
|
423
|
+
this.#slotArgs.set(occurrence, record);
|
|
424
|
+
update(props);
|
|
425
|
+
this.#bindRegions(occurrence);
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
const nodes = this.#invokeSlot(occurrence, callback, record, start);
|
|
429
|
+
if (nodes) this.#replaceRange(occurrence, start, nodes);
|
|
430
|
+
this.#slotNodes.set(occurrence, nodes);
|
|
431
|
+
this.#bindRegions(occurrence);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (!root) {
|
|
435
|
+
for (const occurrence of [...this.#mountedSlots]) {
|
|
436
|
+
if (!found.has(occurrence)) this.#unmountSlot(occurrence);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
#invokeSlot(occurrence, callback, record, start, adopted) {
|
|
441
|
+
this.#slotUpdaters.delete(occurrence);
|
|
442
|
+
const cleanups = this.#slotCleanups.get(occurrence) ?? [];
|
|
443
|
+
let existing = [];
|
|
444
|
+
let end = null;
|
|
445
|
+
if (start) end = eachInRange(start, occurrence, n => existing.push(n));
|
|
446
|
+
const ctx = {
|
|
447
|
+
frame: this.#options.claimScope ?? this.#options.id,
|
|
448
|
+
key: occurrence,
|
|
449
|
+
adopted: !!adopted,
|
|
450
|
+
invoked: !!(record && record.kind === "slot"),
|
|
451
|
+
onCleanup: fn => cleanups.push(fn),
|
|
452
|
+
onUpdate: fn => this.#slotUpdaters.set(occurrence, fn),
|
|
453
|
+
existing,
|
|
454
|
+
range: end ? {
|
|
455
|
+
start,
|
|
456
|
+
end
|
|
457
|
+
} : undefined
|
|
458
|
+
};
|
|
459
|
+
const props = record && record.kind === "slot" ? this.#resolveArgs(occurrence, record.args) : {};
|
|
460
|
+
const content = this.#scoped(() => callback(props, ctx));
|
|
461
|
+
this.#slotArgs.set(occurrence, record);
|
|
462
|
+
if (cleanups.length) this.#slotCleanups.set(occurrence, cleanups);
|
|
463
|
+
if (content == null) return null;
|
|
464
|
+
return Array.isArray(content) ? content : [content];
|
|
465
|
+
}
|
|
466
|
+
#replaceRange(key, start, nodes) {
|
|
467
|
+
const parent = start.parentNode;
|
|
468
|
+
const end = eachInRange(start, key, n => parent.removeChild(n));
|
|
469
|
+
for (const node of nodes) parent.insertBefore(node, end);
|
|
470
|
+
}
|
|
471
|
+
#unmountSlot(key) {
|
|
472
|
+
this.#mountedSlots.delete(key);
|
|
473
|
+
this.#slotNodes.delete(key);
|
|
474
|
+
this.#slotArgs.delete(key);
|
|
475
|
+
this.#slotUpdaters.delete(key);
|
|
476
|
+
this.#slotResolvedRefs.delete(key);
|
|
477
|
+
this.#removeSlotRecord(key);
|
|
478
|
+
this.#runSlotCleanups(key);
|
|
479
|
+
const regions = this.#slotRegions.get(key);
|
|
480
|
+
if (regions) {
|
|
481
|
+
disposeRegions(regions);
|
|
482
|
+
this.#slotRegions.delete(key);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
#runSlotCleanups(key) {
|
|
486
|
+
const cleanups = this.#slotCleanups.get(key);
|
|
487
|
+
if (!cleanups) return;
|
|
488
|
+
this.#slotCleanups.delete(key);
|
|
489
|
+
for (const fn of cleanups) fn();
|
|
490
|
+
}
|
|
491
|
+
#refsUnresolved(args) {
|
|
492
|
+
const {
|
|
493
|
+
host,
|
|
494
|
+
id
|
|
495
|
+
} = this.#options;
|
|
496
|
+
if (host) for (const key in args) {
|
|
497
|
+
if (isDataRef(args[key]) && host.resolve(args[key], id) === undefined) return true;
|
|
498
|
+
}
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
#regionsFor(slotKey) {
|
|
502
|
+
let regions = this.#slotRegions.get(slotKey);
|
|
503
|
+
if (!regions) this.#slotRegions.set(slotKey, regions = new Map());
|
|
504
|
+
return regions;
|
|
505
|
+
}
|
|
506
|
+
#resolveArgs(slotKey, args) {
|
|
507
|
+
const host = this.#options.host;
|
|
508
|
+
const regions = this.#regionsFor(slotKey);
|
|
509
|
+
const props = {};
|
|
510
|
+
for (const key in args) {
|
|
511
|
+
const value = args[key];
|
|
512
|
+
if (isDataRef(value)) {
|
|
513
|
+
const resolved = host ? host.resolve(value, this.#options.id) : undefined;
|
|
514
|
+
let cache = this.#slotResolvedRefs.get(slotKey);
|
|
515
|
+
if (!cache) this.#slotResolvedRefs.set(slotKey, cache = {});
|
|
516
|
+
cache[key] = resolved;
|
|
517
|
+
props[key] = resolved;
|
|
518
|
+
} else if (isFrameRef(value)) {
|
|
519
|
+
let entry = regions.get(key);
|
|
520
|
+
if (!entry) {
|
|
521
|
+
const element = makeFrameElement(value.$frame);
|
|
522
|
+
entry = {
|
|
523
|
+
childId: value.$frame,
|
|
524
|
+
element,
|
|
525
|
+
frame: undefined
|
|
526
|
+
};
|
|
527
|
+
regions.set(key, entry);
|
|
528
|
+
} else if (entry.childId !== value.$frame) {
|
|
529
|
+
renameRegion(entry, value.$frame);
|
|
530
|
+
}
|
|
531
|
+
props[key] = entry.element;
|
|
532
|
+
} else {
|
|
533
|
+
props[key] = host && host.revive ? host.revive(value) : value;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return props;
|
|
537
|
+
}
|
|
538
|
+
#discoverRegions(slotKey, start) {
|
|
539
|
+
if (!start) return;
|
|
540
|
+
const regions = this.#regionsFor(slotKey);
|
|
541
|
+
eachInRange(start, slotKey, n => collectRegionElements(n, regions));
|
|
542
|
+
}
|
|
543
|
+
#refArgsUnchanged(occurrence, record) {
|
|
544
|
+
const old = this.#slotArgs.get(occurrence);
|
|
545
|
+
if (!record || record.kind !== "slot") return false;
|
|
546
|
+
if (old && old.kind !== "slot") return false;
|
|
547
|
+
const a = old && old.args || {};
|
|
548
|
+
const b = record.args || {};
|
|
549
|
+
const ka = Object.keys(a);
|
|
550
|
+
const kb = Object.keys(b);
|
|
551
|
+
if (kb.length !== ka.length) return false;
|
|
552
|
+
const cache = this.#slotResolvedRefs.get(occurrence);
|
|
553
|
+
for (const key of ka) {
|
|
554
|
+
const va = a[key];
|
|
555
|
+
const vb = b[key];
|
|
556
|
+
if (va === vb) continue;
|
|
557
|
+
if (isFrameRef(va) && isFrameRef(vb)) continue;
|
|
558
|
+
if (isDataRef(va) && isDataRef(vb) && cache && key in cache) {
|
|
559
|
+
const host = this.#options.host;
|
|
560
|
+
const next = host ? host.resolve(vb, this.#options.id) : undefined;
|
|
561
|
+
if (host && host.isContainer && (host.isContainer(next) || host.isContainer(cache[key]))) {
|
|
562
|
+
if (next === cache[key]) continue;
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
if (isAsyncLike(next) || isAsyncLike(cache[key])) return false;
|
|
566
|
+
try {
|
|
567
|
+
if (JSON.stringify(next) === JSON.stringify(cache[key])) continue;
|
|
568
|
+
} catch (e) {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
#reconcileRegions(occurrence, record) {
|
|
577
|
+
const args = record && record.args;
|
|
578
|
+
if (!args) return;
|
|
579
|
+
const regions = this.#slotRegions.get(occurrence);
|
|
580
|
+
if (!regions) return;
|
|
581
|
+
for (const key in args) {
|
|
582
|
+
const value = args[key];
|
|
583
|
+
if (!isFrameRef(value)) continue;
|
|
584
|
+
const entry = regions.get(key);
|
|
585
|
+
if (entry && entry.childId !== value.$frame) renameRegion(entry, value.$frame);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
#bindRegions(slotKey) {
|
|
589
|
+
const regions = this.#slotRegions.get(slotKey);
|
|
590
|
+
if (!regions) return;
|
|
591
|
+
for (const entry of regions.values()) {
|
|
592
|
+
if (!entry.frame) {
|
|
593
|
+
entry.frame = new FrameImpl(entry.element, null, null, {
|
|
594
|
+
id: entry.childId,
|
|
595
|
+
host: this.#options.host,
|
|
596
|
+
adopt: entry.adopt,
|
|
597
|
+
claimScope: this.#options.claimScope ?? this.#options.id,
|
|
598
|
+
ownerScope: this.#options.ownerScope,
|
|
599
|
+
resolveSlot: prop => this.#resolveSlot(prop),
|
|
600
|
+
resolveSlotRecord: occurrence => this.#resolveSlotRecord(occurrence),
|
|
601
|
+
removeSlotRecord: occurrence => this.#removeSlotRecord(occurrence)
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
#collectSlots(found) {
|
|
607
|
+
collectSlots(this.#firstContent(), this.#end, found);
|
|
608
|
+
}
|
|
609
|
+
#findPlaceholder(name) {
|
|
610
|
+
return findPlaceholder(this.#firstContent(), this.#end, placeholderId(name));
|
|
611
|
+
}
|
|
612
|
+
contentHTML() {
|
|
613
|
+
if (this.#disposed || !this.#element || !this.#hasContent) return null;
|
|
614
|
+
return this.#element.innerHTML;
|
|
615
|
+
}
|
|
616
|
+
rebind(id) {
|
|
617
|
+
if (this.#disposed || id === this.#options.id) return;
|
|
618
|
+
const {
|
|
619
|
+
host,
|
|
620
|
+
id: oldId
|
|
621
|
+
} = this.#options;
|
|
622
|
+
if (host && oldId !== undefined) host.unregister(oldId, this);
|
|
623
|
+
this.#options = {
|
|
624
|
+
...this.#options,
|
|
625
|
+
id
|
|
626
|
+
};
|
|
627
|
+
if (this.#element && this.#element.nodeType === ELEMENT_NODE) {
|
|
628
|
+
this.#element.setAttribute(FRAME_ID_ATTR, id);
|
|
629
|
+
}
|
|
630
|
+
this.#version = undefined;
|
|
631
|
+
this.#appliedRootValue = undefined;
|
|
632
|
+
this.#resetStreamState(true);
|
|
633
|
+
if (host) host.register(id, this);
|
|
634
|
+
}
|
|
635
|
+
rebase() {
|
|
636
|
+
this.#version = undefined;
|
|
637
|
+
}
|
|
638
|
+
dispose() {
|
|
639
|
+
if (this.#disposed) return;
|
|
640
|
+
const {
|
|
641
|
+
host,
|
|
642
|
+
id
|
|
643
|
+
} = this.#options;
|
|
644
|
+
if (host && id !== undefined) host.unregister(id, this);
|
|
645
|
+
this.#disposed = true;
|
|
646
|
+
if (this.#recordRefresh) {
|
|
647
|
+
clearTimeout(this.#recordRefresh);
|
|
648
|
+
this.#recordRefresh = null;
|
|
649
|
+
}
|
|
650
|
+
for (const key of [...this.#slotCleanups.keys()]) this.#runSlotCleanups(key);
|
|
651
|
+
for (const key of this.#mountedSlots) this.#removeSlotRecord(key);
|
|
652
|
+
for (const regions of this.#slotRegions.values()) disposeRegions(regions);
|
|
653
|
+
this.#slotRegions.clear();
|
|
654
|
+
this.#mountedSlots.clear();
|
|
655
|
+
}
|
|
656
|
+
#applyRoot(html) {
|
|
657
|
+
const fragment = parseFragment(html);
|
|
658
|
+
const parent = this.#parent();
|
|
659
|
+
if (!this.#hasContent) {
|
|
660
|
+
this.#clearContent();
|
|
661
|
+
this.#claimTree(fragment);
|
|
662
|
+
parent.insertBefore(fragment, this.#end);
|
|
663
|
+
this.#hasContent = true;
|
|
664
|
+
} else {
|
|
665
|
+
const claim = claimHandlers() ? this.#claimTree : null;
|
|
666
|
+
const ranges = new Map();
|
|
667
|
+
this.#collectSlots(ranges);
|
|
668
|
+
const grafts = [];
|
|
669
|
+
reconcileChildren(parent, fragment, this.#start, this.#end, claim, ranges, grafts);
|
|
670
|
+
if (ranges.size) for (const root of grafts) flushGrafts(root, ranges);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
#applyHole(marker, html) {
|
|
674
|
+
if (!this.#hasContent) return false;
|
|
675
|
+
const open = findLiveTarget(this.#firstContent(), this.#end, n => n.nodeType === COMMENT_NODE && n.data === marker);
|
|
676
|
+
if (!open) return false;
|
|
677
|
+
const close = rangeClose(open, "lh:/" + marker.slice(3));
|
|
678
|
+
if (!close) {
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
const claim = claimHandlers() ? this.#claimTree : null;
|
|
682
|
+
reconcileChildren(open.parentNode, parseFragment(html), open, close, claim);
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
#applyAttrs(addr, text, removed) {
|
|
686
|
+
if (!this.#hasContent) return false;
|
|
687
|
+
const el = findLiveTarget(this.#firstContent(), this.#end, n => n.nodeType === ELEMENT_NODE && n.getAttribute("data-lha") === addr);
|
|
688
|
+
if (!el) return false;
|
|
689
|
+
const parsed = parseFragment(`<i${text}></i>`).firstChild;
|
|
690
|
+
if (parsed) {
|
|
691
|
+
for (let i = 0; i < parsed.attributes.length; i++) {
|
|
692
|
+
const {
|
|
693
|
+
name,
|
|
694
|
+
value
|
|
695
|
+
} = parsed.attributes[i];
|
|
696
|
+
if (el.getAttribute(name) !== value) el.setAttribute(name, value);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (removed) for (const name of removed) el.removeAttribute(name);
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
#clearContent() {
|
|
703
|
+
removeUntil(this.#parent(), this.#firstContent(), this.#end);
|
|
704
|
+
}
|
|
705
|
+
#claimContent() {
|
|
706
|
+
if (!claimHandlers()) return;
|
|
707
|
+
let n = this.#firstContent();
|
|
708
|
+
while (n && n !== this.#end) {
|
|
709
|
+
this.#claimTree(n);
|
|
710
|
+
n = n.nextSibling;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
#segmentReady(name) {
|
|
714
|
+
const content = this.#store[`seg:${name}`];
|
|
715
|
+
if (!content || content.kind !== "html") return false;
|
|
716
|
+
if (!this.#store[`seg:${name}:reveal`]) return false;
|
|
717
|
+
const assets = this.#store[`seg:${name}:assets`];
|
|
718
|
+
if (assets && assets.styles) {
|
|
719
|
+
let ready = true;
|
|
720
|
+
for (const entry of assets.styles) ready = ensureStylesheet(entry, this.#styleFlush) && ready;
|
|
721
|
+
if (!ready) return false;
|
|
722
|
+
}
|
|
723
|
+
if (!this.#findPlaceholder(name)) return false;
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
#revealSegment(name) {
|
|
727
|
+
const tpl = this.#findPlaceholder(name);
|
|
728
|
+
if (!tpl) return;
|
|
729
|
+
const assets = this.#store[`seg:${name}:assets`];
|
|
730
|
+
if (assets && assets.inlineStyles) applyInlineStyles(assets.inlineStyles);
|
|
731
|
+
const content = this.#store[`seg:${name}`];
|
|
732
|
+
const closing = rangeClose(tpl, placeholderId(name));
|
|
733
|
+
const parent = tpl.parentNode;
|
|
734
|
+
removeUntil(parent, tpl.nextSibling, closing);
|
|
735
|
+
if (this.#options.reveal) {
|
|
736
|
+
const fallbackFrag = tpl.content.cloneNode(true);
|
|
737
|
+
this.#claimTree(fallbackFrag);
|
|
738
|
+
this.#options.reveal({
|
|
739
|
+
before: closing,
|
|
740
|
+
fallback: [...fallbackFrag.childNodes],
|
|
741
|
+
content: () => {
|
|
742
|
+
const materialized = this.#materialize(content);
|
|
743
|
+
this.#syncSlots(materialized);
|
|
744
|
+
this.#claimTree(materialized);
|
|
745
|
+
return materialized;
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
tpl.remove();
|
|
749
|
+
this.#revealed.add(name);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const materialized = this.#materialize(content);
|
|
753
|
+
this.#claimTree(materialized);
|
|
754
|
+
parent.insertBefore(materialized, closing);
|
|
755
|
+
tpl.remove();
|
|
756
|
+
closing && closing.remove();
|
|
757
|
+
this.#revealed.add(name);
|
|
758
|
+
}
|
|
759
|
+
#showFallback(name) {
|
|
760
|
+
const tpl = this.#findPlaceholder(name);
|
|
761
|
+
if (!tpl) return false;
|
|
762
|
+
const closing = rangeClose(tpl, placeholderId(name));
|
|
763
|
+
if (!closing) return false;
|
|
764
|
+
const fallback = tpl.content.cloneNode(true);
|
|
765
|
+
this.#claimTree(fallback);
|
|
766
|
+
closing.parentNode.insertBefore(fallback, closing);
|
|
767
|
+
return true;
|
|
768
|
+
}
|
|
769
|
+
#materialize(record) {
|
|
770
|
+
return record.kind === "html" ? parseFragment(record.value) : parseFragment("");
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
function createFrame(boundary, options) {
|
|
774
|
+
return new FrameImpl(boundary, null, null, options);
|
|
775
|
+
}
|
|
776
|
+
const FRAME_TAG = "dx-frame";
|
|
777
|
+
const FRAME_ID_ATTR = "data-fid";
|
|
778
|
+
function createFrameElement(options) {
|
|
779
|
+
const el = makeFrameElement(options.id);
|
|
780
|
+
const frame = new FrameImpl(el, null, null, options);
|
|
781
|
+
return {
|
|
782
|
+
element: el,
|
|
783
|
+
frame,
|
|
784
|
+
dispose() {
|
|
785
|
+
frame.dispose();
|
|
786
|
+
el.remove();
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
function makeFrameElement(id) {
|
|
791
|
+
const el = document.createElement(FRAME_TAG);
|
|
792
|
+
el.style.display = "contents";
|
|
793
|
+
if (id !== undefined) el.setAttribute(FRAME_ID_ATTR, id);
|
|
794
|
+
return el;
|
|
795
|
+
}
|
|
796
|
+
function isFrameElement(node) {
|
|
797
|
+
return node.nodeType === ELEMENT_NODE && node.hasAttribute(FRAME_ID_ATTR);
|
|
798
|
+
}
|
|
799
|
+
function segmentName(key) {
|
|
800
|
+
const m = /^seg:([^:]+)$/.exec(key);
|
|
801
|
+
return m ? m[1] : null;
|
|
802
|
+
}
|
|
803
|
+
function isAsyncLike(v) {
|
|
804
|
+
return !!v && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
805
|
+
}
|
|
806
|
+
function propOf(occurrence) {
|
|
807
|
+
const hash = occurrence.indexOf("#");
|
|
808
|
+
return hash === -1 ? occurrence : occurrence.slice(0, hash);
|
|
809
|
+
}
|
|
810
|
+
function isDataRef(value) {
|
|
811
|
+
return !!value && typeof value.$ref === "string";
|
|
812
|
+
}
|
|
813
|
+
function isFrameRef(value) {
|
|
814
|
+
return !!value && typeof value.$frame === "string";
|
|
815
|
+
}
|
|
816
|
+
function disposeRegions(regions) {
|
|
817
|
+
for (const {
|
|
818
|
+
frame
|
|
819
|
+
} of regions.values()) frame?.dispose();
|
|
820
|
+
}
|
|
821
|
+
function removeUntil(parent, n, stop) {
|
|
822
|
+
while (n && n !== stop) {
|
|
823
|
+
const next = n.nextSibling;
|
|
824
|
+
parent.removeChild(n);
|
|
825
|
+
n = next;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
function parseFragment(html) {
|
|
829
|
+
const template = document.createElement("template");
|
|
830
|
+
template.innerHTML = html;
|
|
831
|
+
return template.content;
|
|
832
|
+
}
|
|
833
|
+
function findHeadElement(selector, attr, value) {
|
|
834
|
+
for (const node of document.head.querySelectorAll(selector)) {
|
|
835
|
+
if (node.getAttribute(attr) === value) return node;
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
function ensureStylesheet(entry, onSettle) {
|
|
840
|
+
const href = typeof entry === "string" ? entry : entry.href;
|
|
841
|
+
let link = findHeadElement('link[rel="stylesheet"]', "href", href);
|
|
842
|
+
if (!link) {
|
|
843
|
+
link = document.createElement("link");
|
|
844
|
+
link.rel = "stylesheet";
|
|
845
|
+
if (typeof entry !== "string" && entry.attrs) {
|
|
846
|
+
for (const name in entry.attrs) link.setAttribute(name, entry.attrs[name]);
|
|
847
|
+
}
|
|
848
|
+
link.href = href;
|
|
849
|
+
const waiters = new Set();
|
|
850
|
+
link._$frWaiters = waiters;
|
|
851
|
+
const settle = () => {
|
|
852
|
+
link._$frWaiters = null;
|
|
853
|
+
for (const fn of waiters) fn();
|
|
854
|
+
};
|
|
855
|
+
link.addEventListener("load", settle);
|
|
856
|
+
link.addEventListener("error", settle);
|
|
857
|
+
document.head.appendChild(link);
|
|
858
|
+
}
|
|
859
|
+
const waiters = link._$frWaiters;
|
|
860
|
+
if (waiters == null) return true;
|
|
861
|
+
waiters.add(onSettle);
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
function ensureModulePreload(href) {
|
|
865
|
+
if (findHeadElement('link[rel="modulepreload"]', "href", href)) return;
|
|
866
|
+
const link = document.createElement("link");
|
|
867
|
+
link.rel = "modulepreload";
|
|
868
|
+
link.href = href;
|
|
869
|
+
document.head.appendChild(link);
|
|
870
|
+
}
|
|
871
|
+
function applyInlineStyles(inlineStyles) {
|
|
872
|
+
for (const entry of inlineStyles) {
|
|
873
|
+
if (findHeadElement("style[data-asset]", "data-asset", entry.id)) continue;
|
|
874
|
+
const el = document.createElement("style");
|
|
875
|
+
el.setAttribute("data-asset", entry.id);
|
|
876
|
+
if (entry.attrs) {
|
|
877
|
+
for (const name in entry.attrs) el.setAttribute(name, entry.attrs[name]);
|
|
878
|
+
}
|
|
879
|
+
el.textContent = entry.content || "";
|
|
880
|
+
document.head.appendChild(el);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
function isPlaceholderStart(node, id) {
|
|
884
|
+
return node.tagName === "TEMPLATE" && node.id === id;
|
|
885
|
+
}
|
|
886
|
+
function rangeClose(start, id) {
|
|
887
|
+
let n = start.nextSibling;
|
|
888
|
+
while (n) {
|
|
889
|
+
if (n.nodeType === COMMENT_NODE && n.data === id) return n;
|
|
890
|
+
n = n.nextSibling;
|
|
891
|
+
}
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
function findLiveTarget(n, end, test) {
|
|
895
|
+
while (n && n !== end) {
|
|
896
|
+
if (n.nodeType === ELEMENT_NODE) {
|
|
897
|
+
const fid = isFrameElement(n) ? n.getAttribute(FRAME_ID_ATTR) : null;
|
|
898
|
+
if (fid === null || fid.includes(".")) {
|
|
899
|
+
if (test(n)) return n;
|
|
900
|
+
const found = findLiveTarget(n.firstChild, null, test);
|
|
901
|
+
if (found) return found;
|
|
902
|
+
}
|
|
903
|
+
} else if (test(n)) return n;
|
|
904
|
+
n = n.nextSibling;
|
|
905
|
+
}
|
|
906
|
+
return null;
|
|
907
|
+
}
|
|
908
|
+
function findPlaceholder(n, end, id) {
|
|
909
|
+
while (n && n !== end) {
|
|
910
|
+
if (isPlaceholderStart(n, id)) return n;
|
|
911
|
+
if (n.nodeType === ELEMENT_NODE) {
|
|
912
|
+
const found = findPlaceholder(n.firstChild, null, id);
|
|
913
|
+
if (found) return found;
|
|
914
|
+
}
|
|
915
|
+
n = n.nextSibling;
|
|
916
|
+
}
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
function collectSlots(n, end, out) {
|
|
920
|
+
while (n && n !== end) {
|
|
921
|
+
const id = slotStartId(n);
|
|
922
|
+
if (id !== null) {
|
|
923
|
+
if (!out.has(id)) out.set(id, n);
|
|
924
|
+
n = afterRange(n, id);
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (n.nodeType === ELEMENT_NODE && !isFrameElement(n)) collectSlots(n.firstChild, null, out);
|
|
928
|
+
n = n.nextSibling;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
function collectRegionElements(node, regions) {
|
|
932
|
+
if (node.nodeType !== ELEMENT_NODE) return;
|
|
933
|
+
if (isFrameElement(node)) {
|
|
934
|
+
const childId = node.getAttribute(FRAME_ID_ATTR);
|
|
935
|
+
if (childId && childId.includes(".")) {
|
|
936
|
+
const argKey = childId.slice(childId.lastIndexOf(".") + 1);
|
|
937
|
+
if (!regions.has(argKey)) {
|
|
938
|
+
regions.set(argKey, {
|
|
939
|
+
childId,
|
|
940
|
+
element: node,
|
|
941
|
+
frame: undefined,
|
|
942
|
+
adopt: true
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
for (let c = node.firstChild; c; c = c.nextSibling) collectRegionElements(c, regions);
|
|
949
|
+
}
|
|
950
|
+
function renameRegion(entry, childId) {
|
|
951
|
+
entry.childId = childId;
|
|
952
|
+
if (entry.frame) entry.frame.rebind(childId);else entry.element.setAttribute(FRAME_ID_ATTR, childId);
|
|
953
|
+
}
|
|
954
|
+
function eachInRange(start, key, cb) {
|
|
955
|
+
const end = slotEnd(key);
|
|
956
|
+
let n = start.nextSibling;
|
|
957
|
+
while (n && !(n.nodeType === COMMENT_NODE && n.data === end)) {
|
|
958
|
+
const next = n.nextSibling;
|
|
959
|
+
cb(n);
|
|
960
|
+
n = next;
|
|
961
|
+
}
|
|
962
|
+
return n;
|
|
963
|
+
}
|
|
964
|
+
function clearStreamRecords(records, root) {
|
|
965
|
+
for (const key in records) {
|
|
966
|
+
if (/^(seg|hole|attr):/.test(key) || key === ":error" || root && key === "") {
|
|
967
|
+
delete records[key];
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function argsEquivalent(a, b) {
|
|
972
|
+
if (a === b) return true;
|
|
973
|
+
if (!a || !b) return false;
|
|
974
|
+
const ka = Object.keys(a);
|
|
975
|
+
const kb = Object.keys(b);
|
|
976
|
+
if (ka.length !== kb.length) return false;
|
|
977
|
+
for (const key of ka) {
|
|
978
|
+
const va = a[key];
|
|
979
|
+
const vb = b[key];
|
|
980
|
+
if (va === vb) continue;
|
|
981
|
+
if (isFrameRef(va) && va.$frame === vb?.$frame) continue;
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
return true;
|
|
985
|
+
}
|
|
986
|
+
function slotStartId(node) {
|
|
987
|
+
if (node.nodeType !== COMMENT_NODE) return null;
|
|
988
|
+
const m = SLOT_START.exec(node.data);
|
|
989
|
+
return m ? m[1] : null;
|
|
990
|
+
}
|
|
991
|
+
function isSlotMarker(node) {
|
|
992
|
+
if (node.nodeType !== COMMENT_NODE) return false;
|
|
993
|
+
const data = node.data;
|
|
994
|
+
return SLOT_START.test(data) || SLOT_END.test(data);
|
|
995
|
+
}
|
|
996
|
+
function compatible(a, b) {
|
|
997
|
+
if (a.nodeType !== b.nodeType) return false;
|
|
998
|
+
if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName;
|
|
999
|
+
return a.nodeType === TEXT_NODE || a.nodeType === COMMENT_NODE;
|
|
1000
|
+
}
|
|
1001
|
+
function preservesOpen(el) {
|
|
1002
|
+
const t = el.tagName;
|
|
1003
|
+
return t === "DETAILS" || t === "DIALOG";
|
|
1004
|
+
}
|
|
1005
|
+
function morphAttributes(oldEl, newEl, claim) {
|
|
1006
|
+
let reclaim = false;
|
|
1007
|
+
let changed = false;
|
|
1008
|
+
const keepOpen = preservesOpen(oldEl);
|
|
1009
|
+
const oldAttrs = oldEl.attributes;
|
|
1010
|
+
for (let i = oldAttrs.length - 1; i >= 0; i--) {
|
|
1011
|
+
const name = oldAttrs[i].name;
|
|
1012
|
+
if (keepOpen && name === "open") continue;
|
|
1013
|
+
if (!newEl.hasAttribute(name)) {
|
|
1014
|
+
oldEl.removeAttribute(name);
|
|
1015
|
+
changed = true;
|
|
1016
|
+
reclaim ||= claimedAttr(name);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
const newAttrs = newEl.attributes;
|
|
1020
|
+
for (let i = 0; i < newAttrs.length; i++) {
|
|
1021
|
+
const attr = newAttrs[i];
|
|
1022
|
+
if (keepOpen && attr.name === "open") continue;
|
|
1023
|
+
if (oldEl.getAttribute(attr.name) !== attr.value) {
|
|
1024
|
+
oldEl.setAttribute(attr.name, attr.value);
|
|
1025
|
+
changed = true;
|
|
1026
|
+
reclaim ||= claimedAttr(attr.name);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (claim && (reclaim || changed && oldEl.matches(CLAIMED_ELEMENTS))) claim(oldEl, true);
|
|
1030
|
+
}
|
|
1031
|
+
function morphNode(oldNode, newNode, claim, ranges, grafts) {
|
|
1032
|
+
if (oldNode.nodeType === ELEMENT_NODE) {
|
|
1033
|
+
if (oldNode.hasAttribute("data-preserve")) return;
|
|
1034
|
+
morphAttributes(oldNode, newNode, claim);
|
|
1035
|
+
reconcileChildren(oldNode, newNode, null, null, claim, ranges, grafts);
|
|
1036
|
+
} else if (oldNode.data !== newNode.data) {
|
|
1037
|
+
oldNode.data = newNode.data;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
function afterRange(start, id) {
|
|
1041
|
+
const end = slotEnd(id);
|
|
1042
|
+
let n = start.nextSibling;
|
|
1043
|
+
while (n) {
|
|
1044
|
+
if (n.nodeType === COMMENT_NODE && n.data === end) return n.nextSibling;
|
|
1045
|
+
n = n.nextSibling;
|
|
1046
|
+
}
|
|
1047
|
+
return null;
|
|
1048
|
+
}
|
|
1049
|
+
function findRangeStart(from, id, bound) {
|
|
1050
|
+
const target = `slot:${id}:start`;
|
|
1051
|
+
let n = from;
|
|
1052
|
+
while (n && n !== bound) {
|
|
1053
|
+
if (n.nodeType === COMMENT_NODE && n.data === target) return n;
|
|
1054
|
+
n = n.nextSibling;
|
|
1055
|
+
}
|
|
1056
|
+
return null;
|
|
1057
|
+
}
|
|
1058
|
+
function moveRangeBefore(parent, start, id, ref) {
|
|
1059
|
+
const end = slotEnd(id);
|
|
1060
|
+
let n = start;
|
|
1061
|
+
while (n) {
|
|
1062
|
+
const next = n.nextSibling;
|
|
1063
|
+
const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
|
|
1064
|
+
parent.insertBefore(n, ref);
|
|
1065
|
+
if (isEnd) break;
|
|
1066
|
+
n = next;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
function placeRange(parent, range, id, ref) {
|
|
1070
|
+
if (range.nodeType === 11 ) {
|
|
1071
|
+
parent.insertBefore(range, ref);
|
|
1072
|
+
} else {
|
|
1073
|
+
moveRangeBefore(parent, range, id, ref);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
function adoptRange(parent, start, id, ref, claim) {
|
|
1077
|
+
const end = slotEnd(id);
|
|
1078
|
+
let n = start;
|
|
1079
|
+
let after = null;
|
|
1080
|
+
while (n) {
|
|
1081
|
+
const next = n.nextSibling;
|
|
1082
|
+
const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
|
|
1083
|
+
parent.insertBefore(n, ref);
|
|
1084
|
+
if (claim) claim(n);
|
|
1085
|
+
if (isEnd) {
|
|
1086
|
+
after = next;
|
|
1087
|
+
break;
|
|
1088
|
+
}
|
|
1089
|
+
n = next;
|
|
1090
|
+
}
|
|
1091
|
+
return after;
|
|
1092
|
+
}
|
|
1093
|
+
function reconcileChildren(parent, source, boundStart = null, boundEnd = null, claim = null, ranges = null, grafts = null) {
|
|
1094
|
+
let oldChild = boundStart ? boundStart.nextSibling : parent.firstChild;
|
|
1095
|
+
let newChild = source.firstChild;
|
|
1096
|
+
while (newChild) {
|
|
1097
|
+
const nextNew = newChild.nextSibling;
|
|
1098
|
+
const pid = slotStartId(newChild);
|
|
1099
|
+
const old = oldChild === boundEnd ? null : oldChild;
|
|
1100
|
+
if (pid !== null) {
|
|
1101
|
+
if (old && slotStartId(old) === pid) {
|
|
1102
|
+
oldChild = afterRange(old, pid);
|
|
1103
|
+
newChild = afterRange(newChild, pid);
|
|
1104
|
+
} else {
|
|
1105
|
+
const displaced = ranges && ranges.get(pid);
|
|
1106
|
+
const existing = displaced || findRangeStart(old, pid, boundEnd);
|
|
1107
|
+
if (existing) {
|
|
1108
|
+
if (ranges) ranges.delete(pid);
|
|
1109
|
+
placeRange(parent, existing, pid, old ?? boundEnd);
|
|
1110
|
+
newChild = afterRange(newChild, pid);
|
|
1111
|
+
} else {
|
|
1112
|
+
newChild = adoptRange(parent, newChild, pid, old ?? boundEnd, claim);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
if (!old) {
|
|
1118
|
+
parent.insertBefore(newChild, boundEnd);
|
|
1119
|
+
if (claim) claim(newChild);
|
|
1120
|
+
if (grafts) grafts.push(newChild);
|
|
1121
|
+
newChild = nextNew;
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
if (isSlotMarker(old)) {
|
|
1125
|
+
parent.insertBefore(newChild, old);
|
|
1126
|
+
if (claim) claim(newChild);
|
|
1127
|
+
if (grafts) grafts.push(newChild);
|
|
1128
|
+
newChild = nextNew;
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
if (compatible(old, newChild)) {
|
|
1132
|
+
morphNode(old, newChild, claim, ranges, grafts);
|
|
1133
|
+
oldChild = old.nextSibling;
|
|
1134
|
+
newChild = nextNew;
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
if (newChild.nodeType === 1) {
|
|
1138
|
+
let ahead = old.nextSibling;
|
|
1139
|
+
while (ahead && ahead !== boundEnd && !compatible(ahead, newChild)) {
|
|
1140
|
+
const aheadPid = slotStartId(ahead);
|
|
1141
|
+
ahead = aheadPid !== null ? afterRange(ahead, aheadPid) : ahead.nextSibling;
|
|
1142
|
+
}
|
|
1143
|
+
if (ahead && ahead !== boundEnd) {
|
|
1144
|
+
parent.insertBefore(ahead, old);
|
|
1145
|
+
morphNode(ahead, newChild, claim, ranges, grafts);
|
|
1146
|
+
newChild = nextNew;
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
parent.insertBefore(newChild, old);
|
|
1151
|
+
if (claim) claim(newChild);
|
|
1152
|
+
if (grafts) grafts.push(newChild);
|
|
1153
|
+
newChild = nextNew;
|
|
1154
|
+
}
|
|
1155
|
+
while (oldChild && oldChild !== boundEnd) {
|
|
1156
|
+
const next = oldChild.nextSibling;
|
|
1157
|
+
const pid = ranges ? slotStartId(oldChild) : null;
|
|
1158
|
+
if (pid !== null && ranges.get(pid) === oldChild) {
|
|
1159
|
+
const frag = document.createDocumentFragment();
|
|
1160
|
+
const after = stashRange(frag, oldChild, pid);
|
|
1161
|
+
ranges.set(pid, frag);
|
|
1162
|
+
oldChild = after;
|
|
1163
|
+
continue;
|
|
1164
|
+
}
|
|
1165
|
+
parent.removeChild(oldChild);
|
|
1166
|
+
oldChild = next;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
function flushGrafts(node, ranges) {
|
|
1170
|
+
if (node.nodeType !== ELEMENT_NODE || isFrameElement(node)) return;
|
|
1171
|
+
let n = node.firstChild;
|
|
1172
|
+
while (n) {
|
|
1173
|
+
const id = slotStartId(n);
|
|
1174
|
+
if (id !== null) {
|
|
1175
|
+
const next = afterRange(n, id);
|
|
1176
|
+
const displaced = ranges.get(id);
|
|
1177
|
+
if (displaced) {
|
|
1178
|
+
ranges.delete(id);
|
|
1179
|
+
placeRange(node, displaced, id, n);
|
|
1180
|
+
stashRange(document.createDocumentFragment(), n, id);
|
|
1181
|
+
}
|
|
1182
|
+
n = next;
|
|
1183
|
+
continue;
|
|
1184
|
+
}
|
|
1185
|
+
flushGrafts(n, ranges);
|
|
1186
|
+
n = n.nextSibling;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
function stashRange(frag, start, id) {
|
|
1190
|
+
const end = slotEnd(id);
|
|
1191
|
+
let n = start;
|
|
1192
|
+
while (n) {
|
|
1193
|
+
const next = n.nextSibling;
|
|
1194
|
+
const isEnd = n.nodeType === COMMENT_NODE && n.data === end;
|
|
1195
|
+
frag.appendChild(n);
|
|
1196
|
+
if (isEnd) return next;
|
|
1197
|
+
n = next;
|
|
1198
|
+
}
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
const FRAME_STREAM_HEADER = "X-Frame-Stream";
|
|
1203
|
+
function isFrameStreamResponse(response) {
|
|
1204
|
+
return response.headers.has(FRAME_STREAM_HEADER);
|
|
1205
|
+
}
|
|
1206
|
+
async function applyFrameResponse(response, host, options = {}) {
|
|
1207
|
+
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1208
|
+
const as = options.as;
|
|
1209
|
+
const version = options.version;
|
|
1210
|
+
const perFrame = typeof version === "function" ? new Map() : null;
|
|
1211
|
+
const reader = new client.ChunkReader(response.body);
|
|
1212
|
+
let result = await reader.next();
|
|
1213
|
+
while (!result.done) {
|
|
1214
|
+
const chunk = JSON.parse(result.value);
|
|
1215
|
+
if (chunk.type === "outcome") {
|
|
1216
|
+
if (options.onOutcome) options.onOutcome(chunk.payload);
|
|
1217
|
+
} else {
|
|
1218
|
+
if (as !== undefined && chunk.id === rootId) chunk.id = as;
|
|
1219
|
+
if (perFrame) {
|
|
1220
|
+
let v = perFrame.get(chunk.id);
|
|
1221
|
+
if (v === undefined) perFrame.set(chunk.id, v = version(chunk.id));
|
|
1222
|
+
chunk.version = v;
|
|
1223
|
+
} else if (version !== undefined) chunk.version = version;
|
|
1224
|
+
if (chunk.type === "data" && host.prepareData) await host.prepareData();
|
|
1225
|
+
host.apply(chunk);
|
|
1226
|
+
}
|
|
1227
|
+
result = await reader.next();
|
|
1228
|
+
}
|
|
1229
|
+
return as !== undefined ? as : rootId;
|
|
1230
|
+
}
|
|
1231
|
+
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
1232
|
+
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
1233
|
+
const COMPONENT_BINDING = /*#__PURE__*/Symbol.for("dom-expressions.component-binding");
|
|
1234
|
+
let resolveServerComponent;
|
|
1235
|
+
function parseServerComponent(value, ctx) {
|
|
1236
|
+
return {
|
|
1237
|
+
id: ctx.parse(value[SERVER_COMPONENT]),
|
|
1238
|
+
address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
const ServerComponentPlugin = {
|
|
1242
|
+
tag: "dom-expressions/server-component",
|
|
1243
|
+
test(value) {
|
|
1244
|
+
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
1245
|
+
},
|
|
1246
|
+
parse: {
|
|
1247
|
+
sync: parseServerComponent,
|
|
1248
|
+
async async(value, ctx) {
|
|
1249
|
+
return {
|
|
1250
|
+
id: await ctx.parse(value[SERVER_COMPONENT]),
|
|
1251
|
+
address: await ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1252
|
+
};
|
|
1253
|
+
},
|
|
1254
|
+
stream: parseServerComponent
|
|
1255
|
+
},
|
|
1256
|
+
serialize(node, ctx) {
|
|
1257
|
+
const registry = "self._$SC";
|
|
1258
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
1259
|
+
},
|
|
1260
|
+
deserialize(node, ctx) {
|
|
1261
|
+
const id = ctx.deserialize(node.id);
|
|
1262
|
+
const address = ctx.deserialize(node.address);
|
|
1263
|
+
if (address !== undefined && resolveServerComponent) {
|
|
1264
|
+
return resolveServerComponent(id, address);
|
|
1265
|
+
}
|
|
1266
|
+
return globalThis._$SC.r(id);
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
function flightCodec(codec) {
|
|
1270
|
+
const plugins = codec && codec.plugins || [];
|
|
1271
|
+
if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
|
|
1272
|
+
return {
|
|
1273
|
+
...codec,
|
|
1274
|
+
plugins: [...plugins, ServerComponentPlugin]
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
function createServerComponentHandler({
|
|
1278
|
+
host,
|
|
1279
|
+
component,
|
|
1280
|
+
onStream,
|
|
1281
|
+
intercept,
|
|
1282
|
+
consumer = client.getFlightDataConsumer,
|
|
1283
|
+
codec = client.getServerFunctionsCodec
|
|
1284
|
+
}) {
|
|
1285
|
+
const byFn = new Map();
|
|
1286
|
+
const componentFor = fnId => {
|
|
1287
|
+
let comp = byFn.get(fnId);
|
|
1288
|
+
if (comp === undefined) byFn.set(fnId, comp = component(fnId));
|
|
1289
|
+
return comp;
|
|
1290
|
+
};
|
|
1291
|
+
const byAddress = new Map();
|
|
1292
|
+
const bindingFor = (address, fnId) => {
|
|
1293
|
+
let binding = byAddress.get(address);
|
|
1294
|
+
if (!binding) {
|
|
1295
|
+
const comp = componentFor(fnId);
|
|
1296
|
+
binding = props => comp(props, () => address);
|
|
1297
|
+
binding[COMPONENT_BINDING] = {
|
|
1298
|
+
component: comp,
|
|
1299
|
+
address
|
|
1300
|
+
};
|
|
1301
|
+
byAddress.set(address, binding);
|
|
1302
|
+
}
|
|
1303
|
+
return binding;
|
|
1304
|
+
};
|
|
1305
|
+
resolveServerComponent = (id, address) => bindingFor(address, id);
|
|
1306
|
+
const versions = new Map();
|
|
1307
|
+
const bump = address => {
|
|
1308
|
+
const version = (versions.get(address) || 0) + 1;
|
|
1309
|
+
versions.set(address, version);
|
|
1310
|
+
return version;
|
|
1311
|
+
};
|
|
1312
|
+
return {
|
|
1313
|
+
intercept: intercept && (info => {
|
|
1314
|
+
const hit = intercept(info);
|
|
1315
|
+
if (hit === undefined) return undefined;
|
|
1316
|
+
return bindingFor(client.frameAddress(info.id, info.args), info.id);
|
|
1317
|
+
}),
|
|
1318
|
+
handle(response, ctx) {
|
|
1319
|
+
if (!isFrameStreamResponse(response)) return undefined;
|
|
1320
|
+
const address = client.frameAddress(ctx.id, ctx.args);
|
|
1321
|
+
const binding = bindingFor(address, ctx.id);
|
|
1322
|
+
if (response.headers.has(client.SINGLE_FLIGHT_HEADER)) {
|
|
1323
|
+
return applyFlightResponse(response, address, binding);
|
|
1324
|
+
}
|
|
1325
|
+
const version = bump(address);
|
|
1326
|
+
if (onStream) onStream(address, version, response);
|
|
1327
|
+
applyFrameResponse(response, host, {
|
|
1328
|
+
as: address,
|
|
1329
|
+
version
|
|
1330
|
+
}).catch(err => host.apply({
|
|
1331
|
+
type: "error",
|
|
1332
|
+
id: address,
|
|
1333
|
+
version,
|
|
1334
|
+
error: {
|
|
1335
|
+
message: String(err && err.message)
|
|
1336
|
+
}
|
|
1337
|
+
}));
|
|
1338
|
+
return binding;
|
|
1339
|
+
},
|
|
1340
|
+
showing(address, functionId) {
|
|
1341
|
+
bindingFor(address, functionId);
|
|
1342
|
+
const comp = componentFor(functionId);
|
|
1343
|
+
if (comp && (typeof comp === "function" || typeof comp === "object") && !comp[COMPONENT_BINDING]) {
|
|
1344
|
+
comp[COMPONENT_BINDING] = {
|
|
1345
|
+
component: comp,
|
|
1346
|
+
address
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
async function applyFlightResponse(response, address, binding) {
|
|
1352
|
+
const rootId = response.headers.get(FRAME_STREAM_HEADER) ?? "";
|
|
1353
|
+
const as = rootId ? address : undefined;
|
|
1354
|
+
let feed;
|
|
1355
|
+
const source = new ReadableStream({
|
|
1356
|
+
start(controller) {
|
|
1357
|
+
feed = controller;
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
const payload = client.deserializeStream(new Response(source), flightCodec(codec()));
|
|
1361
|
+
let carried = false;
|
|
1362
|
+
await applyFrameResponse(response, host, {
|
|
1363
|
+
as,
|
|
1364
|
+
version: frameId => {
|
|
1365
|
+
const version = bump(frameId);
|
|
1366
|
+
if (onStream) onStream(frameId, version, response);
|
|
1367
|
+
return version;
|
|
1368
|
+
},
|
|
1369
|
+
onOutcome: text => {
|
|
1370
|
+
carried = true;
|
|
1371
|
+
feed.enqueue(client.createChunk(text));
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
feed.close();
|
|
1375
|
+
if (!carried) throw new Error("Single-flight frame response carried no outcome");
|
|
1376
|
+
const envelope = await payload;
|
|
1377
|
+
const deliver = consumer();
|
|
1378
|
+
if (deliver) await deliver(envelope.data, {
|
|
1379
|
+
response
|
|
1380
|
+
});
|
|
1381
|
+
if (response.headers.has(client.ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has(client.REVALIDATE_HEADER)) {
|
|
1382
|
+
throw envelope.value;
|
|
1383
|
+
}
|
|
1384
|
+
return rootId ? binding : envelope.value;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
const STATE = Symbol.for("dom-expressions.container-trace-state");
|
|
1389
|
+
const state = globalThis[STATE] || (globalThis[STATE] = {
|
|
1390
|
+
materialized: new WeakMap(),
|
|
1391
|
+
materializedValues: new WeakSet()
|
|
1392
|
+
});
|
|
1393
|
+
function setContainerTraceMaterializer(fn) {
|
|
1394
|
+
state.materializeTrace = fn;
|
|
1395
|
+
}
|
|
1396
|
+
function materialize(marker) {
|
|
1397
|
+
let value = state.materialized.get(marker.$tr);
|
|
1398
|
+
if (value === undefined) {
|
|
1399
|
+
value = state.materializeTrace(marker);
|
|
1400
|
+
state.materialized.set(marker.$tr, value);
|
|
1401
|
+
if (value !== null && typeof value === "object") state.materializedValues.add(value);
|
|
1402
|
+
}
|
|
1403
|
+
return value;
|
|
1404
|
+
}
|
|
1405
|
+
function isMaterializedContainer(value) {
|
|
1406
|
+
return value !== null && typeof value === "object" && state.materializedValues.has(value);
|
|
1407
|
+
}
|
|
1408
|
+
function isContainerTraceMarker(value) {
|
|
1409
|
+
return value != null && typeof value === "object" && value.$tr != null && typeof value.$tr[Symbol.asyncIterator] === "function";
|
|
1410
|
+
}
|
|
1411
|
+
function reviveContainerTraces(value) {
|
|
1412
|
+
if (!state.materializeTrace || value == null || typeof value !== "object") return value;
|
|
1413
|
+
if (isContainerTraceMarker(value)) return materialize(value);
|
|
1414
|
+
if (Array.isArray(value)) {
|
|
1415
|
+
for (let i = 0; i < value.length; i++) value[i] = reviveContainerTraces(value[i]);
|
|
1416
|
+
} else if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
1417
|
+
for (const key of Object.keys(value)) value[key] = reviveContainerTraces(value[key]);
|
|
1418
|
+
}
|
|
1419
|
+
return value;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
setContainerTraceMaterializer(solidJs.materializeContainerTrace);
|
|
1423
|
+
function asyncArg(value) {
|
|
1424
|
+
return value;
|
|
1425
|
+
}
|
|
1426
|
+
let sharedHost;
|
|
1427
|
+
let codec;
|
|
1428
|
+
let codecLoading;
|
|
1429
|
+
function loadCodec() {
|
|
1430
|
+
return codecLoading ??= import('@solidjs/web/serialization/decode').then(m => {
|
|
1431
|
+
codec = m;
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
const tables = new Map();
|
|
1435
|
+
function ensureTable(root) {
|
|
1436
|
+
let table = tables.get(root);
|
|
1437
|
+
if (!table && codec) tables.set(root, table = codec.createJSONDataTable());
|
|
1438
|
+
return table;
|
|
1439
|
+
}
|
|
1440
|
+
function tableFor(id) {
|
|
1441
|
+
if (tables.has(id)) return ensureTable(id);
|
|
1442
|
+
for (const root of tables.keys()) if (id.startsWith(root + ".")) return ensureTable(root);
|
|
1443
|
+
return undefined;
|
|
1444
|
+
}
|
|
1445
|
+
function beginStream(frameId) {
|
|
1446
|
+
tables.set(frameId, undefined);
|
|
1447
|
+
}
|
|
1448
|
+
function getFrameHost() {
|
|
1449
|
+
if (!sharedHost) {
|
|
1450
|
+
sharedHost = createFrameHost({
|
|
1451
|
+
prepareData: loadCodec,
|
|
1452
|
+
applyData: c => tableFor(c.id)?.apply(c),
|
|
1453
|
+
resolve: (ref, id) => tableFor(id)?.resolve(ref),
|
|
1454
|
+
revive: reviveContainerTraces,
|
|
1455
|
+
isContainer: isMaterializedContainer
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
return sharedHost;
|
|
1459
|
+
}
|
|
1460
|
+
function normalizeSlotContent(value) {
|
|
1461
|
+
while (typeof value === "function") value = value();
|
|
1462
|
+
if (Array.isArray(value)) {
|
|
1463
|
+
const out = [];
|
|
1464
|
+
for (const v of value) {
|
|
1465
|
+
const n = normalizeSlotContent(v);
|
|
1466
|
+
Array.isArray(n) ? out.push(...n) : out.push(n);
|
|
1467
|
+
}
|
|
1468
|
+
return out;
|
|
1469
|
+
}
|
|
1470
|
+
if (value == null || typeof value === "boolean") return document.createTextNode("");
|
|
1471
|
+
return value instanceof Node ? value : document.createTextNode(String(value));
|
|
1472
|
+
}
|
|
1473
|
+
function gatherClaims(el, registry) {
|
|
1474
|
+
if (el.hasAttribute("_hk")) registry.set(el.getAttribute("_hk"), el);
|
|
1475
|
+
if (el.hasAttribute(FRAME_ID_ATTR)) return;
|
|
1476
|
+
for (let c = el.firstElementChild; c; c = c.nextElementSibling) gatherClaims(c, registry);
|
|
1477
|
+
}
|
|
1478
|
+
function hasPendingFragment(existing) {
|
|
1479
|
+
for (const n of existing) {
|
|
1480
|
+
if (n.nodeType !== 1) continue;
|
|
1481
|
+
const el = n;
|
|
1482
|
+
if (el.tagName === "TEMPLATE" && el.id.startsWith("pl-")) return true;
|
|
1483
|
+
if (el.querySelector?.('template[id^="pl-"]')) return true;
|
|
1484
|
+
}
|
|
1485
|
+
return false;
|
|
1486
|
+
}
|
|
1487
|
+
function claimRender(prefix, existing, render) {
|
|
1488
|
+
const sc = solidJs.sharedConfig;
|
|
1489
|
+
if (!sc.getNextContextId) return render();
|
|
1490
|
+
const registry = new Map();
|
|
1491
|
+
for (const n of existing) {
|
|
1492
|
+
if (n.nodeType !== 1) continue;
|
|
1493
|
+
gatherClaims(n, registry);
|
|
1494
|
+
}
|
|
1495
|
+
if (!registry.size && !hasPendingFragment(existing)) return render();
|
|
1496
|
+
const prevRegistry = sc.registry;
|
|
1497
|
+
const prevHydrating = sc.hydrating;
|
|
1498
|
+
const prevClaimRoots = sc.claimRoots;
|
|
1499
|
+
if (prevRegistry) for (const key of registry.keys()) prevRegistry.delete(key);
|
|
1500
|
+
sc.registry = registry;
|
|
1501
|
+
sc.hydrating = true;
|
|
1502
|
+
sc.claimRoots = existing;
|
|
1503
|
+
try {
|
|
1504
|
+
return solidJs.runWithOwner(solidJs.createOwner({
|
|
1505
|
+
id: prefix
|
|
1506
|
+
}), render);
|
|
1507
|
+
} finally {
|
|
1508
|
+
sc.registry = prevRegistry;
|
|
1509
|
+
sc.hydrating = prevHydrating;
|
|
1510
|
+
sc.claimRoots = prevClaimRoots;
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
function liveSlotProps(initial, ctx) {
|
|
1514
|
+
const [args, setArgs] = solidJs.createSignal(initial);
|
|
1515
|
+
ctx.onUpdate(next => setArgs(() => next));
|
|
1516
|
+
return slotArgsProxy(args);
|
|
1517
|
+
}
|
|
1518
|
+
function isAsyncValue(v) {
|
|
1519
|
+
return v !== null && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
1520
|
+
}
|
|
1521
|
+
function slotArgsProxy(args) {
|
|
1522
|
+
const owner = solidJs.getOwner();
|
|
1523
|
+
const asyncReads = new Map();
|
|
1524
|
+
return new Proxy({}, {
|
|
1525
|
+
get: (_, key) => {
|
|
1526
|
+
const v = args()[key];
|
|
1527
|
+
if (isMaterializedContainer(v)) return v;
|
|
1528
|
+
if (!isAsyncValue(v)) return v;
|
|
1529
|
+
let read = asyncReads.get(key);
|
|
1530
|
+
if (!read) {
|
|
1531
|
+
const make = () => solidJs.createMemo(() => args()[key]);
|
|
1532
|
+
read = owner ? solidJs.runWithOwner(owner, make) : make();
|
|
1533
|
+
asyncReads.set(key, read);
|
|
1534
|
+
}
|
|
1535
|
+
return read();
|
|
1536
|
+
},
|
|
1537
|
+
has: (_, key) => key in args(),
|
|
1538
|
+
ownKeys: () => Reflect.ownKeys(args()),
|
|
1539
|
+
getOwnPropertyDescriptor: (_, key) => key in args() ? {
|
|
1540
|
+
enumerable: true,
|
|
1541
|
+
configurable: true
|
|
1542
|
+
} : undefined
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
function isReactiveContent(value) {
|
|
1546
|
+
if (typeof value === "function") return true;
|
|
1547
|
+
if (Array.isArray(value)) {
|
|
1548
|
+
for (const v of value) if (isReactiveContent(v)) return true;
|
|
1549
|
+
}
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1552
|
+
function slotsFor(props) {
|
|
1553
|
+
const bindings = new Map();
|
|
1554
|
+
const fillScopes = new Map();
|
|
1555
|
+
return new Proxy({}, {
|
|
1556
|
+
get(_, prop) {
|
|
1557
|
+
if (typeof prop !== "string" || !(prop in props)) return undefined;
|
|
1558
|
+
return (slotProps, ctx) => {
|
|
1559
|
+
const key = ctx && ctx.key;
|
|
1560
|
+
const prev = key !== undefined && bindings.get(key);
|
|
1561
|
+
if (prev) {
|
|
1562
|
+
bindings.delete(key);
|
|
1563
|
+
prev.dispose();
|
|
1564
|
+
}
|
|
1565
|
+
const prevFill = key !== undefined && fillScopes.get(key);
|
|
1566
|
+
if (prevFill) {
|
|
1567
|
+
fillScopes.delete(key);
|
|
1568
|
+
prevFill.dispose();
|
|
1569
|
+
}
|
|
1570
|
+
const fillOwner = streamInvoke ? solidJs.createOwner() : null;
|
|
1571
|
+
if (fillOwner && key !== undefined && ctx) {
|
|
1572
|
+
fillScopes.set(key, fillOwner);
|
|
1573
|
+
ctx.onCleanup(() => {
|
|
1574
|
+
if (fillScopes.get(key) === fillOwner) fillScopes.delete(key);
|
|
1575
|
+
fillOwner.dispose();
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
const settle = out => {
|
|
1579
|
+
const existing = ctx && ctx.existing || [];
|
|
1580
|
+
if (existing.length) {
|
|
1581
|
+
const list = Array.isArray(out) ? out : [out];
|
|
1582
|
+
const inPlace = list.every(n => existing.some(e => e === n || e.nodeType === 1 && e.contains(n)));
|
|
1583
|
+
if (inPlace) return undefined;
|
|
1584
|
+
}
|
|
1585
|
+
return out;
|
|
1586
|
+
};
|
|
1587
|
+
const evaluate = () => {
|
|
1588
|
+
const v = props[prop];
|
|
1589
|
+
if (typeof v === "function" && ctx && ctx.invoked) {
|
|
1590
|
+
return v(ctx.onUpdate ? liveSlotProps(slotProps, ctx) : slotArgsProxy(() => slotProps));
|
|
1591
|
+
}
|
|
1592
|
+
return v;
|
|
1593
|
+
};
|
|
1594
|
+
const adopted = !!(ctx && ctx.frame && ctx.adopted && ctx.existing && ctx.existing.length);
|
|
1595
|
+
const prefix = ctx && ctx.frame ? `sc-${ctx.frame}-${ctx.key}-` : "";
|
|
1596
|
+
const value = fillOwner ? solidJs.runWithOwner(fillOwner, () => adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate()) : adopted ? claimRender(prefix, ctx.existing, evaluate) : evaluate();
|
|
1597
|
+
if (!isReactiveContent(value)) {
|
|
1598
|
+
return settle(normalizeSlotContent(value));
|
|
1599
|
+
}
|
|
1600
|
+
if (ctx && ctx.range) {
|
|
1601
|
+
const source = value;
|
|
1602
|
+
const owner = solidJs.createOwner();
|
|
1603
|
+
bindings.set(key, owner);
|
|
1604
|
+
ctx.onCleanup(() => {
|
|
1605
|
+
if (bindings.get(key) === owner) bindings.delete(key);
|
|
1606
|
+
owner.dispose();
|
|
1607
|
+
});
|
|
1608
|
+
const end = ctx.range.end;
|
|
1609
|
+
const bind = () => web.insert(end.parentNode, () => typeof source === "function" ? source() : source, end, [...ctx.existing]);
|
|
1610
|
+
solidJs.runWithOwner(owner, () => adopted ? claimRender(prefix, ctx.existing, bind) : bind());
|
|
1611
|
+
return undefined;
|
|
1612
|
+
}
|
|
1613
|
+
return settle(normalizeSlotContent(value));
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
function revealSeam(owner) {
|
|
1619
|
+
return seam => solidJs.runWithOwner(owner, () => web.insert(seam.before.parentNode, solidJs.createLoadingBoundary(() => seam.content(), () => seam.fallback), seam.before));
|
|
1620
|
+
}
|
|
1621
|
+
let streamInvoke = false;
|
|
1622
|
+
function boundaryScope(owner) {
|
|
1623
|
+
return fn => {
|
|
1624
|
+
if (solidJs.getOwner()) return fn();
|
|
1625
|
+
streamInvoke = true;
|
|
1626
|
+
try {
|
|
1627
|
+
return solidJs.runWithOwner(owner, fn);
|
|
1628
|
+
} finally {
|
|
1629
|
+
streamInvoke = false;
|
|
1630
|
+
}
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
function boundaryComponent(host, fnId) {
|
|
1634
|
+
return (props, binding) => {
|
|
1635
|
+
const owner = solidJs.getOwner();
|
|
1636
|
+
const id = binding ? binding() : fnId;
|
|
1637
|
+
let applied = !tables.has(id);
|
|
1638
|
+
let release;
|
|
1639
|
+
const arm = () => new Promise(r => release = r);
|
|
1640
|
+
const mountGate = applied ? undefined : arm();
|
|
1641
|
+
let setGate;
|
|
1642
|
+
const {
|
|
1643
|
+
element,
|
|
1644
|
+
frame,
|
|
1645
|
+
dispose
|
|
1646
|
+
} = createFrameElement({
|
|
1647
|
+
host,
|
|
1648
|
+
id,
|
|
1649
|
+
slots: slotsFor(props),
|
|
1650
|
+
ownerScope: boundaryScope(owner),
|
|
1651
|
+
reveal: revealSeam(owner),
|
|
1652
|
+
onApply: () => {
|
|
1653
|
+
applied = true;
|
|
1654
|
+
if (release) {
|
|
1655
|
+
release();
|
|
1656
|
+
release = undefined;
|
|
1657
|
+
}
|
|
1658
|
+
setGate && setGate(undefined);
|
|
1659
|
+
}
|
|
1660
|
+
});
|
|
1661
|
+
const [gatePromise, setGatePromise] = solidJs.createSignal(applied ? undefined : mountGate);
|
|
1662
|
+
setGate = setGatePromise;
|
|
1663
|
+
if (binding) {
|
|
1664
|
+
solidJs.createRenderEffect(binding, (address, prev) => {
|
|
1665
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1666
|
+
applied = false;
|
|
1667
|
+
setGatePromise(arm());
|
|
1668
|
+
}
|
|
1669
|
+
frame.rebind(address);
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
solidJs.onCleanup(dispose);
|
|
1673
|
+
if (applied && !binding) return element;
|
|
1674
|
+
const gate = solidJs.createMemo(() => gatePromise());
|
|
1675
|
+
return solidJs.createMemo(() => (gate(), element));
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
const claimedBoundaries = new Set();
|
|
1679
|
+
const liveOps = new Map();
|
|
1680
|
+
const liveAppliers = new Set();
|
|
1681
|
+
let livePumped = null;
|
|
1682
|
+
function pumpLiveChannel() {
|
|
1683
|
+
const stream = globalThis._$HY?.r?.["sc:live"];
|
|
1684
|
+
if (!stream || stream === livePumped || typeof stream.getReader !== "function") return;
|
|
1685
|
+
livePumped = stream;
|
|
1686
|
+
const reader = stream.getReader();
|
|
1687
|
+
const pump = () => reader.read().then(r => {
|
|
1688
|
+
if (r.done) return;
|
|
1689
|
+
const op = r.value;
|
|
1690
|
+
liveOps.set(`${op.type}:${op.fid || ""}:${op.key || ""}`, op);
|
|
1691
|
+
for (const apply of liveAppliers) apply(op);
|
|
1692
|
+
return pump();
|
|
1693
|
+
});
|
|
1694
|
+
pump().catch(() => {
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
let boundaryIndex = null;
|
|
1698
|
+
const isBoundaryId = id => !id.includes(".");
|
|
1699
|
+
function indexBoundaries(root) {
|
|
1700
|
+
root.querySelectorAll(`[${FRAME_ID_ATTR}]`).forEach(el => {
|
|
1701
|
+
const key = el.getAttribute(FRAME_ID_ATTR);
|
|
1702
|
+
if (key && isBoundaryId(key) && !boundaryIndex.has(key)) boundaryIndex.set(key, el);
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
function findBoundaryElement(id) {
|
|
1706
|
+
if (!boundaryIndex) {
|
|
1707
|
+
boundaryIndex = new Map();
|
|
1708
|
+
if (typeof document !== "undefined" && document.body) indexBoundaries(document.body);
|
|
1709
|
+
}
|
|
1710
|
+
return boundaryIndex.get(id);
|
|
1711
|
+
}
|
|
1712
|
+
const boundaryWaiters = new Map();
|
|
1713
|
+
function boundaryMayArrive() {
|
|
1714
|
+
const hy = globalThis._$HY;
|
|
1715
|
+
if (!hy) return false;
|
|
1716
|
+
return !hy.done || !!(hy.fr && hy.fr.pending());
|
|
1717
|
+
}
|
|
1718
|
+
function installRevealHook() {
|
|
1719
|
+
const hy = globalThis._$HY;
|
|
1720
|
+
if (!hy || hy.$sc || !hy.fr) return;
|
|
1721
|
+
hy.$sc = true;
|
|
1722
|
+
hy.fr.subscribe((_id, parent) => {
|
|
1723
|
+
if (!boundaryIndex) return;
|
|
1724
|
+
const root = parent || (typeof document !== "undefined" ? document.body : null);
|
|
1725
|
+
if (root) indexBoundaries(root);
|
|
1726
|
+
if (!boundaryWaiters.size) return;
|
|
1727
|
+
const exhausted = hy.done && !hy.fr.pending();
|
|
1728
|
+
for (const [id, notify] of boundaryWaiters) {
|
|
1729
|
+
const el = boundaryIndex && boundaryIndex.get(id);
|
|
1730
|
+
if (!el && !exhausted) continue;
|
|
1731
|
+
boundaryWaiters.delete(id);
|
|
1732
|
+
notify(el);
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
function documentBoundary(host, id, props, binding) {
|
|
1737
|
+
installRevealHook();
|
|
1738
|
+
const claimed = claimedBoundaries.has(id);
|
|
1739
|
+
const el = !claimed ? findBoundaryElement(id) : undefined;
|
|
1740
|
+
if (el) return adoptBoundary(host, id, el, props, binding);
|
|
1741
|
+
if (!claimed && !boundaryWaiters.has(id) && boundaryMayArrive()) {
|
|
1742
|
+
const owner = solidJs.getOwner();
|
|
1743
|
+
const arrival = new Promise(resolve => boundaryWaiters.set(id, resolve));
|
|
1744
|
+
solidJs.onCleanup(() => boundaryWaiters.delete(id));
|
|
1745
|
+
return solidJs.createMemo(() => arrival.then(node => solidJs.runWithOwner(owner, () =>
|
|
1746
|
+
node ? adoptBoundary(host, id, node, props, binding) : boundaryComponent(host, id)(props, binding))));
|
|
1747
|
+
}
|
|
1748
|
+
return boundaryComponent(host, id)(props, binding);
|
|
1749
|
+
}
|
|
1750
|
+
function documentAddress(id) {
|
|
1751
|
+
const records = globalThis._$SC?.a;
|
|
1752
|
+
if (records) {
|
|
1753
|
+
for (const address in records) if (records[address] === id) return address;
|
|
1754
|
+
}
|
|
1755
|
+
return id;
|
|
1756
|
+
}
|
|
1757
|
+
function adoptBoundary(host, id, el, props, binding) {
|
|
1758
|
+
claimedBoundaries.add(id);
|
|
1759
|
+
const address = binding ? binding() : documentAddress(id);
|
|
1760
|
+
const appliedRecords = new Set();
|
|
1761
|
+
const claimedFragments = new Set();
|
|
1762
|
+
const claimRegionFragments = root => {
|
|
1763
|
+
const fr = globalThis._$HY?.fr;
|
|
1764
|
+
if (!fr || !fr.claim) return;
|
|
1765
|
+
root.querySelectorAll('template[id^="pl-"]').forEach(tpl => {
|
|
1766
|
+
const fragId = tpl.id.slice(3);
|
|
1767
|
+
if (claimedFragments.has(fragId)) return;
|
|
1768
|
+
claimedFragments.add(fragId);
|
|
1769
|
+
fr.claim(fragId);
|
|
1770
|
+
});
|
|
1771
|
+
};
|
|
1772
|
+
const drainRecords = () => {
|
|
1773
|
+
const hy = globalThis._$HY;
|
|
1774
|
+
if (!hy || !hy.r) return;
|
|
1775
|
+
pumpLiveChannel();
|
|
1776
|
+
const slotPrefix = `sc:slot:${id}:`;
|
|
1777
|
+
for (const key of Object.keys(hy.r)) {
|
|
1778
|
+
if (appliedRecords.has(key)) continue;
|
|
1779
|
+
if (key.startsWith(slotPrefix)) {
|
|
1780
|
+
appliedRecords.add(key);
|
|
1781
|
+
host.apply({
|
|
1782
|
+
type: "slot",
|
|
1783
|
+
id: address,
|
|
1784
|
+
version: 0,
|
|
1785
|
+
key: key.slice(slotPrefix.length),
|
|
1786
|
+
args: hy.r[key]
|
|
1787
|
+
});
|
|
1788
|
+
} else if (key.startsWith("sc:region:")) {
|
|
1789
|
+
const childId = key.slice("sc:region:".length);
|
|
1790
|
+
if (childId.startsWith(id + ".")) {
|
|
1791
|
+
appliedRecords.add(key);
|
|
1792
|
+
const val = hy.r[key];
|
|
1793
|
+
const apply = html => host.apply({
|
|
1794
|
+
type: "html",
|
|
1795
|
+
id: childId,
|
|
1796
|
+
version: 0,
|
|
1797
|
+
html
|
|
1798
|
+
});
|
|
1799
|
+
val && typeof val.then === "function" ? val.then(apply) : apply(val);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
claimRegionFragments(el);
|
|
1805
|
+
const fr = globalThis._$HY?.fr;
|
|
1806
|
+
const unsubscribe = fr ? fr.subscribe((_fragId, parent) => {
|
|
1807
|
+
if (fr.claim && parent && el.contains(parent)) claimRegionFragments(parent);
|
|
1808
|
+
drainRecords();
|
|
1809
|
+
}) : undefined;
|
|
1810
|
+
const applyLiveOp = op => {
|
|
1811
|
+
if (op.type === "slot" && op.fid !== id) return;
|
|
1812
|
+
host.apply({
|
|
1813
|
+
...op,
|
|
1814
|
+
id: address,
|
|
1815
|
+
version: 0
|
|
1816
|
+
});
|
|
1817
|
+
};
|
|
1818
|
+
liveAppliers.add(applyLiveOp);
|
|
1819
|
+
solidJs.onCleanup(() => {
|
|
1820
|
+
liveAppliers.delete(applyLiveOp);
|
|
1821
|
+
unsubscribe && unsubscribe();
|
|
1822
|
+
if (fr && fr.release) for (const fragId of claimedFragments) fr.release(fragId);
|
|
1823
|
+
});
|
|
1824
|
+
drainRecords();
|
|
1825
|
+
for (const op of liveOps.values()) applyLiveOp(op);
|
|
1826
|
+
const owner = solidJs.getOwner();
|
|
1827
|
+
let release;
|
|
1828
|
+
let setGate;
|
|
1829
|
+
const frame = createFrame(el, {
|
|
1830
|
+
adopt: true,
|
|
1831
|
+
host,
|
|
1832
|
+
id: address,
|
|
1833
|
+
slots: slotsFor(props),
|
|
1834
|
+
ownerScope: boundaryScope(owner),
|
|
1835
|
+
reveal: revealSeam(owner),
|
|
1836
|
+
onApply: () => {
|
|
1837
|
+
if (release) {
|
|
1838
|
+
release();
|
|
1839
|
+
release = undefined;
|
|
1840
|
+
}
|
|
1841
|
+
setGate && setGate(undefined);
|
|
1842
|
+
},
|
|
1843
|
+
...{
|
|
1844
|
+
recordsPending: () => {
|
|
1845
|
+
if (document.readyState === "loading") return true;
|
|
1846
|
+
const hy = globalThis._$HY;
|
|
1847
|
+
return !!(hy && hy.fr && hy.fr.pending());
|
|
1848
|
+
},
|
|
1849
|
+
drainRecords,
|
|
1850
|
+
claimScope: id
|
|
1851
|
+
}
|
|
1852
|
+
});
|
|
1853
|
+
if (binding) {
|
|
1854
|
+
const arm = () => new Promise(r => release = r);
|
|
1855
|
+
const [gatePromise, setGatePromise] = solidJs.createSignal(undefined);
|
|
1856
|
+
setGate = setGatePromise;
|
|
1857
|
+
const gate = solidJs.createMemo(() => gatePromise());
|
|
1858
|
+
solidJs.createRenderEffect(binding, (address, prev) => {
|
|
1859
|
+
if (prev !== undefined && address !== prev && tables.has(address)) {
|
|
1860
|
+
setGatePromise(arm());
|
|
1861
|
+
}
|
|
1862
|
+
frame.rebind(address);
|
|
1863
|
+
});
|
|
1864
|
+
solidJs.createRenderEffect(() => (gate(), undefined), () => {});
|
|
1865
|
+
}
|
|
1866
|
+
solidJs.onCleanup(() => frame.dispose());
|
|
1867
|
+
return el;
|
|
1868
|
+
}
|
|
1869
|
+
function installServerComponents(host = getFrameHost()) {
|
|
1870
|
+
const g = globalThis;
|
|
1871
|
+
if (!g._$SC) {
|
|
1872
|
+
g._$SC = {
|
|
1873
|
+
c: {},
|
|
1874
|
+
a: {},
|
|
1875
|
+
r(i, a) {
|
|
1876
|
+
if (a) {
|
|
1877
|
+
g._$SC.a[a] = i;
|
|
1878
|
+
g._$SC.reg && g._$SC.reg(a, i);
|
|
1879
|
+
}
|
|
1880
|
+
return g._$SC.c[i] || (g._$SC.c[i] = (p, b) => g._$SC.impl(i, p, b));
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
g._$SC.impl = (id, props, binding) => documentBoundary(host, id, props, binding);
|
|
1885
|
+
installRevealHook();
|
|
1886
|
+
const handler = createServerComponentHandler({
|
|
1887
|
+
host,
|
|
1888
|
+
component: fnId => g._$SC.r(fnId),
|
|
1889
|
+
onStream: address => beginStream(address),
|
|
1890
|
+
intercept: ({
|
|
1891
|
+
id
|
|
1892
|
+
}) => {
|
|
1893
|
+
if (claimedBoundaries.has(id) || !findBoundaryElement(id)) return undefined;
|
|
1894
|
+
return g._$SC.r(id);
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
const showing = (address, id) => handler.showing(address, id);
|
|
1898
|
+
const records = g._$SC.a || (g._$SC.a = {});
|
|
1899
|
+
for (const address in records) showing(address, records[address]);
|
|
1900
|
+
g._$SC.reg = showing;
|
|
1901
|
+
client.configureServerFunctionsClient({
|
|
1902
|
+
responseHandler: handler
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
exports.FRAME_APPLIED_EVENT = FRAME_APPLIED_EVENT;
|
|
1907
|
+
exports.FRAME_STREAM_HEADER = FRAME_STREAM_HEADER;
|
|
1908
|
+
exports.applyFrameResponse = applyFrameResponse;
|
|
1909
|
+
exports.asyncArg = asyncArg;
|
|
1910
|
+
exports.createFrame = createFrame;
|
|
1911
|
+
exports.createFrameElement = createFrameElement;
|
|
1912
|
+
exports.createFrameHost = createFrameHost;
|
|
1913
|
+
exports.createServerComponentHandler = createServerComponentHandler;
|
|
1914
|
+
exports.getFrameHost = getFrameHost;
|
|
1915
|
+
exports.installServerComponents = installServerComponents;
|
|
1916
|
+
exports.isFrameStreamResponse = isFrameStreamResponse;
|