@absolutejs/absolute 0.19.0-beta.367 → 0.19.0-beta.369
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/angular/browser.js +13 -8
- package/dist/angular/browser.js.map +4 -4
- package/dist/angular/components/core/streamingSlotRegistrar.js +4 -3
- package/dist/angular/components/core/streamingSlotRegistry.js +4 -3
- package/dist/angular/index.js +668 -622
- package/dist/angular/index.js.map +8 -8
- package/dist/build.js +24 -576
- package/dist/build.js.map +4 -10
- package/dist/client/index.js +45 -44
- package/dist/client/index.js.map +4 -4
- package/dist/index.js +1320 -1135
- package/dist/index.js.map +28 -22
- package/dist/react/components/browser/index.js +9 -20
- package/dist/react/components/index.js +17 -35
- package/dist/react/components/index.js.map +5 -6
- package/dist/react/index.js +1268 -1235
- package/dist/react/index.js.map +12 -12
- package/dist/react/server.js +3 -571
- package/dist/react/server.js.map +4 -11
- package/dist/src/core/pageHandlers.d.ts +1 -1
- package/dist/src/react/index.d.ts +1 -1
- package/dist/svelte/index.js +1506 -1460
- package/dist/svelte/index.js.map +8 -8
- package/dist/vue/components/index.js +13 -8
- package/dist/vue/components/index.js.map +5 -5
- package/dist/vue/index.js +667 -619
- package/dist/vue/index.js.map +8 -8
- package/package.json +1 -1
- package/dist/src/react/streamingSlotCollection.d.ts +0 -9
package/dist/react/server.js
CHANGED
|
@@ -221,554 +221,6 @@ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient", ISLAND_MARKER = 'data-island="tr
|
|
|
221
221
|
globalThis.__absoluteManifest = manifest;
|
|
222
222
|
};
|
|
223
223
|
|
|
224
|
-
// src/client/streamSwap.ts
|
|
225
|
-
var streamSwapRuntime = () => {
|
|
226
|
-
if (window.__ABS_SLOT_RUNTIME__ === true)
|
|
227
|
-
return;
|
|
228
|
-
window.__ABS_SLOT_RUNTIME__ = true;
|
|
229
|
-
window.__ABS_SLOT_PENDING__ = window.__ABS_SLOT_PENDING__ ?? {};
|
|
230
|
-
const pending = window.__ABS_SLOT_PENDING__;
|
|
231
|
-
const apply = (id, html) => {
|
|
232
|
-
const node = document.getElementById(`slot-${id}`);
|
|
233
|
-
if (!node) {
|
|
234
|
-
pending[id] = html;
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
node.innerHTML = html;
|
|
238
|
-
delete pending[id];
|
|
239
|
-
};
|
|
240
|
-
const flush = () => {
|
|
241
|
-
for (const id in pending) {
|
|
242
|
-
if (!Object.prototype.hasOwnProperty.call(pending, id))
|
|
243
|
-
continue;
|
|
244
|
-
apply(id, pending[id] ?? "");
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
window.__ABS_SLOT_ENQUEUE__ = (id, html) => {
|
|
248
|
-
apply(id, html);
|
|
249
|
-
};
|
|
250
|
-
if (typeof MutationObserver === "function") {
|
|
251
|
-
const observer = new MutationObserver(flush);
|
|
252
|
-
const root = document.documentElement ?? document.body ?? document;
|
|
253
|
-
observer.observe(root, { childList: true, subtree: true });
|
|
254
|
-
}
|
|
255
|
-
if (document.readyState === "loading") {
|
|
256
|
-
document.addEventListener("DOMContentLoaded", flush, { once: true });
|
|
257
|
-
}
|
|
258
|
-
flush();
|
|
259
|
-
}, stripFunctionWrapper = (value) => {
|
|
260
|
-
const start = value.indexOf("{");
|
|
261
|
-
const end = value.lastIndexOf("}");
|
|
262
|
-
if (start < 0 || end <= start)
|
|
263
|
-
return "";
|
|
264
|
-
return value.slice(start + 1, end);
|
|
265
|
-
}, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
|
|
266
|
-
|
|
267
|
-
// src/utils/escapeScriptContent.ts
|
|
268
|
-
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
269
|
-
const escaped = ESCAPE_LOOKUP[char];
|
|
270
|
-
return escaped !== undefined ? escaped : char;
|
|
271
|
-
});
|
|
272
|
-
var init_escapeScriptContent = __esm(() => {
|
|
273
|
-
ESCAPE_LOOKUP = {
|
|
274
|
-
"\u2028": "\\u2028",
|
|
275
|
-
"\u2029": "\\u2029",
|
|
276
|
-
"&": "\\u0026",
|
|
277
|
-
"<": "\\u003C",
|
|
278
|
-
">": "\\u003E"
|
|
279
|
-
};
|
|
280
|
-
ESCAPE_REGEX = /[&><\u2028\u2029]/g;
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
// src/utils/streamingSlots.ts
|
|
284
|
-
var SLOT_ID_PREFIX = "abs-slot-", SLOT_PLACEHOLDER_PREFIX = "slot-", CLOSING_HEAD_TAG2 = "</head>", CLOSING_HEAD_TAG_LENGTH, CLOSING_PAGE_TAG_REGEX, STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__", STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__", STREAM_TAIL_LOOKBEHIND = 128, STREAMING_SLOT_TIMEOUT_MS = 5000, STREAMING_SLOT_MAX_PER_RESPONSE = 128, STREAMING_SLOT_MAX_HTML_BYTES = 64000, createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`, createSlotPatchStatement = (id, html) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,h){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=h;})(${JSON.stringify(id)},${JSON.stringify(html)});`, createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "", createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(36).slice(2, 10)}`, getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript(), renderStreamingSlotsRuntimeTag = (nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(getStreamingSlotsRuntimeScript())}</script>`, renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${createSlotPlaceholderId(id)}" data-absolute-slot="true">${fallbackHtml}</div>`, renderStreamingSlotPatchTag = (id, html, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, html))}</script>`, injectHtmlIntoHead = (html, injection) => {
|
|
285
|
-
const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG2);
|
|
286
|
-
if (closingHeadIndex >= 0) {
|
|
287
|
-
return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
|
|
288
|
-
}
|
|
289
|
-
return `${html}${injection}`;
|
|
290
|
-
}, toUint8 = (value, encoder) => encoder.encode(value), currentStreamingSlotPolicy, clonePolicy = (policy) => ({
|
|
291
|
-
...policy
|
|
292
|
-
}), normalizeSlotBytes = (value, fallback) => {
|
|
293
|
-
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
294
|
-
return Math.floor(value);
|
|
295
|
-
}
|
|
296
|
-
return fallback;
|
|
297
|
-
}, normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback, normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback, hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key), applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
|
|
298
|
-
timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
|
|
299
|
-
fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
|
|
300
|
-
errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
|
|
301
|
-
maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
|
|
302
|
-
maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
|
|
303
|
-
onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
|
|
304
|
-
onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
|
|
305
|
-
}), createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
|
|
306
|
-
if (!policyOnError && !enhancerOnError)
|
|
307
|
-
return;
|
|
308
|
-
return (error, slot) => {
|
|
309
|
-
policyOnError?.(error, slot);
|
|
310
|
-
enhancerOnError?.(error, slot);
|
|
311
|
-
};
|
|
312
|
-
}, createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
|
|
313
|
-
if (!policyOnSlotMetric && !callOnSlotMetric)
|
|
314
|
-
return;
|
|
315
|
-
return (metric) => {
|
|
316
|
-
policyOnSlotMetric?.(metric);
|
|
317
|
-
callOnSlotMetric?.(metric);
|
|
318
|
-
};
|
|
319
|
-
}, resolveStreamingSlotPolicy = (overridePolicy = {}) => {
|
|
320
|
-
const base = getStreamingSlotPolicy();
|
|
321
|
-
return applyStreamingSlotPolicyOverrides(base, overridePolicy);
|
|
322
|
-
}, getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy), setStreamingSlotPolicy = (policy = {}) => {
|
|
323
|
-
const base = getStreamingSlotPolicy();
|
|
324
|
-
currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
|
|
325
|
-
}, withStreamingSlotPolicy = async (policy, callback) => {
|
|
326
|
-
const previous = getStreamingSlotPolicy();
|
|
327
|
-
setStreamingSlotPolicy(policy);
|
|
328
|
-
try {
|
|
329
|
-
return await callback();
|
|
330
|
-
} finally {
|
|
331
|
-
currentStreamingSlotPolicy = previous;
|
|
332
|
-
}
|
|
333
|
-
}, emitSlotMetric = (metric, onSlotMetric) => {
|
|
334
|
-
onSlotMetric?.(metric);
|
|
335
|
-
}, createTimeoutError = (slot, timeoutMs) => {
|
|
336
|
-
const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
|
|
337
|
-
error.__absTimeout = true;
|
|
338
|
-
return error;
|
|
339
|
-
}, toStreamingSlot = (slot, policy) => ({
|
|
340
|
-
errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
|
|
341
|
-
fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
|
|
342
|
-
id: slot.id ?? createStreamingSlotId(),
|
|
343
|
-
timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
|
|
344
|
-
resolve: slot.resolve
|
|
345
|
-
}), prepareSlots = ({
|
|
346
|
-
policy,
|
|
347
|
-
slots,
|
|
348
|
-
onError,
|
|
349
|
-
onSlotMetric
|
|
350
|
-
}) => {
|
|
351
|
-
const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
|
|
352
|
-
const maxSlotsPerResponse = policy.maxSlotsPerResponse;
|
|
353
|
-
if (maxSlotsPerResponse === 0) {
|
|
354
|
-
const error = new Error("Streaming slot limit is set to 0");
|
|
355
|
-
for (const slot of preparedSlots) {
|
|
356
|
-
onError?.(error, slot);
|
|
357
|
-
emitSlotMetric({
|
|
358
|
-
type: "dropped",
|
|
359
|
-
slotId: slot.id,
|
|
360
|
-
reason: "maxSlotsPerResponse is 0"
|
|
361
|
-
}, onSlotMetric);
|
|
362
|
-
}
|
|
363
|
-
return [];
|
|
364
|
-
}
|
|
365
|
-
if (preparedSlots.length <= maxSlotsPerResponse) {
|
|
366
|
-
preparedSlots.forEach((slot) => emitSlotMetric({
|
|
367
|
-
type: "prepared",
|
|
368
|
-
slotId: slot.id
|
|
369
|
-
}, onSlotMetric));
|
|
370
|
-
return preparedSlots;
|
|
371
|
-
}
|
|
372
|
-
const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
|
|
373
|
-
const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
|
|
374
|
-
droppedSlots.forEach((slot) => {
|
|
375
|
-
onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
|
|
376
|
-
emitSlotMetric({
|
|
377
|
-
type: "dropped",
|
|
378
|
-
slotId: slot.id,
|
|
379
|
-
reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
|
|
380
|
-
}, onSlotMetric);
|
|
381
|
-
});
|
|
382
|
-
keptSlots.forEach((slot) => emitSlotMetric({
|
|
383
|
-
type: "prepared",
|
|
384
|
-
slotId: slot.id
|
|
385
|
-
}, onSlotMetric));
|
|
386
|
-
return keptSlots;
|
|
387
|
-
}, htmlByteLength = (value, encoder) => encoder.encode(value).length, resolveSlot = async (slot, onError, policy, onSlotMetric) => {
|
|
388
|
-
const safePolicy = policy ?? getStreamingSlotPolicy();
|
|
389
|
-
const encoder = new TextEncoder;
|
|
390
|
-
const start = Date.now();
|
|
391
|
-
try {
|
|
392
|
-
const maybeAsyncValue = Promise.resolve(slot.resolve());
|
|
393
|
-
const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
|
|
394
|
-
maybeAsyncValue,
|
|
395
|
-
new Promise((_, reject) => setTimeout(() => {
|
|
396
|
-
reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
|
|
397
|
-
}, slot.timeoutMs))
|
|
398
|
-
]) : await maybeAsyncValue;
|
|
399
|
-
const html = typeof resolved === "string" ? resolved : `${resolved}`;
|
|
400
|
-
if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
|
|
401
|
-
const bytes2 = htmlByteLength(html, encoder);
|
|
402
|
-
const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
|
|
403
|
-
const durationMs2 = Date.now() - start;
|
|
404
|
-
onError?.(error, slot);
|
|
405
|
-
emitSlotMetric({
|
|
406
|
-
type: "size_exceeded",
|
|
407
|
-
slotId: slot.id,
|
|
408
|
-
durationMs: durationMs2,
|
|
409
|
-
bytes: bytes2,
|
|
410
|
-
error
|
|
411
|
-
}, onSlotMetric);
|
|
412
|
-
const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
|
|
413
|
-
return {
|
|
414
|
-
html: fallbackHtml,
|
|
415
|
-
id: slot.id,
|
|
416
|
-
durationMs: durationMs2,
|
|
417
|
-
bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
const durationMs = Date.now() - start;
|
|
421
|
-
const bytes = htmlByteLength(html, encoder);
|
|
422
|
-
emitSlotMetric({
|
|
423
|
-
type: "resolved",
|
|
424
|
-
slotId: slot.id,
|
|
425
|
-
durationMs,
|
|
426
|
-
bytes
|
|
427
|
-
}, onSlotMetric);
|
|
428
|
-
return {
|
|
429
|
-
html,
|
|
430
|
-
id: slot.id,
|
|
431
|
-
durationMs,
|
|
432
|
-
bytes
|
|
433
|
-
};
|
|
434
|
-
} catch (error) {
|
|
435
|
-
const durationMs = Date.now() - start;
|
|
436
|
-
onError?.(error, slot);
|
|
437
|
-
emitSlotMetric({
|
|
438
|
-
type: error?.__absTimeout === true ? "timeout" : "error",
|
|
439
|
-
slotId: slot.id,
|
|
440
|
-
durationMs,
|
|
441
|
-
error
|
|
442
|
-
}, onSlotMetric);
|
|
443
|
-
if (typeof slot.errorHtml === "string") {
|
|
444
|
-
const html = slot.errorHtml;
|
|
445
|
-
return {
|
|
446
|
-
html,
|
|
447
|
-
id: slot.id,
|
|
448
|
-
durationMs,
|
|
449
|
-
bytes: htmlByteLength(html, encoder)
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
return {
|
|
453
|
-
html: null,
|
|
454
|
-
id: slot.id,
|
|
455
|
-
durationMs,
|
|
456
|
-
bytes: 0
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
}, nextResolvedSlot = async (pending) => {
|
|
460
|
-
const wrapped = pending.map((promise) => promise.then((result) => ({
|
|
461
|
-
original: promise,
|
|
462
|
-
result
|
|
463
|
-
})));
|
|
464
|
-
return Promise.race(wrapped);
|
|
465
|
-
}, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), streamOutOfOrderSlots = ({
|
|
466
|
-
footerHtml = "",
|
|
467
|
-
headerHtml = "",
|
|
468
|
-
nonce,
|
|
469
|
-
policy,
|
|
470
|
-
onSlotMetric,
|
|
471
|
-
onError,
|
|
472
|
-
slots
|
|
473
|
-
}) => {
|
|
474
|
-
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
475
|
-
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
476
|
-
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
477
|
-
const effectivePolicy = {
|
|
478
|
-
...resolvedPolicy,
|
|
479
|
-
onSlotMetric: combinedOnSlotMetric
|
|
480
|
-
};
|
|
481
|
-
const preparedSlots = prepareSlots({
|
|
482
|
-
policy: effectivePolicy,
|
|
483
|
-
slots,
|
|
484
|
-
onError: combinedOnError,
|
|
485
|
-
onSlotMetric: combinedOnSlotMetric
|
|
486
|
-
});
|
|
487
|
-
const encoder = new TextEncoder;
|
|
488
|
-
return new ReadableStream({
|
|
489
|
-
async start(controller) {
|
|
490
|
-
try {
|
|
491
|
-
let header = headerHtml;
|
|
492
|
-
if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
|
|
493
|
-
header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
|
|
494
|
-
}
|
|
495
|
-
controller.enqueue(toUint8(header, encoder));
|
|
496
|
-
const pending = preparedSlots.map((slot) => {
|
|
497
|
-
const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
|
|
498
|
-
controller.enqueue(toUint8(fallback, encoder));
|
|
499
|
-
return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
|
|
500
|
-
});
|
|
501
|
-
while (pending.length > 0) {
|
|
502
|
-
const { original, result } = await nextResolvedSlot(pending);
|
|
503
|
-
const index = pending.indexOf(original);
|
|
504
|
-
if (index >= 0)
|
|
505
|
-
pending.splice(index, 1);
|
|
506
|
-
if (result.html === null)
|
|
507
|
-
continue;
|
|
508
|
-
emitSlotMetric({
|
|
509
|
-
type: "patched",
|
|
510
|
-
slotId: result.id,
|
|
511
|
-
durationMs: result.durationMs,
|
|
512
|
-
bytes: result.bytes
|
|
513
|
-
}, combinedOnSlotMetric);
|
|
514
|
-
controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
|
|
515
|
-
}
|
|
516
|
-
if (footerHtml.length > 0) {
|
|
517
|
-
controller.enqueue(toUint8(footerHtml, encoder));
|
|
518
|
-
}
|
|
519
|
-
controller.close();
|
|
520
|
-
} catch (error) {
|
|
521
|
-
controller.error(error);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
}, injectStreamingRuntimeIntoStream = (stream, nonce) => {
|
|
526
|
-
const runtimeTag = renderStreamingSlotsRuntimeTag(nonce);
|
|
527
|
-
const encoder = new TextEncoder;
|
|
528
|
-
const decoder = new TextDecoder;
|
|
529
|
-
const lookbehind = CLOSING_HEAD_TAG_LENGTH - 1;
|
|
530
|
-
return new ReadableStream({
|
|
531
|
-
async start(controller) {
|
|
532
|
-
const reader = stream.getReader();
|
|
533
|
-
let injected = false;
|
|
534
|
-
let pending = "";
|
|
535
|
-
try {
|
|
536
|
-
for (;; ) {
|
|
537
|
-
const { done, value } = await reader.read();
|
|
538
|
-
if (done)
|
|
539
|
-
break;
|
|
540
|
-
if (!value)
|
|
541
|
-
continue;
|
|
542
|
-
pending += streamChunkToString2(value, decoder);
|
|
543
|
-
if (injected) {
|
|
544
|
-
controller.enqueue(encoder.encode(pending));
|
|
545
|
-
pending = "";
|
|
546
|
-
continue;
|
|
547
|
-
}
|
|
548
|
-
const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
|
|
549
|
-
if (headIndex >= 0) {
|
|
550
|
-
const withRuntime = `${pending.slice(0, headIndex)}${runtimeTag}${pending.slice(headIndex)}`;
|
|
551
|
-
controller.enqueue(encoder.encode(withRuntime));
|
|
552
|
-
pending = "";
|
|
553
|
-
injected = true;
|
|
554
|
-
continue;
|
|
555
|
-
}
|
|
556
|
-
if (pending.length > lookbehind) {
|
|
557
|
-
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
558
|
-
controller.enqueue(encoder.encode(safeText));
|
|
559
|
-
pending = pending.slice(-lookbehind);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
pending += decoder.decode();
|
|
563
|
-
if (!injected) {
|
|
564
|
-
pending = injectHtmlIntoHead(pending, runtimeTag);
|
|
565
|
-
}
|
|
566
|
-
if (pending.length > 0) {
|
|
567
|
-
controller.enqueue(encoder.encode(pending));
|
|
568
|
-
}
|
|
569
|
-
controller.close();
|
|
570
|
-
} catch (error) {
|
|
571
|
-
controller.error(error);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
}, appendStreamingSlotPatchesToStream = (stream, slots = [], {
|
|
576
|
-
injectRuntime = true,
|
|
577
|
-
nonce,
|
|
578
|
-
onError,
|
|
579
|
-
onSlotMetric,
|
|
580
|
-
policy
|
|
581
|
-
} = {}) => {
|
|
582
|
-
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
583
|
-
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
584
|
-
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
585
|
-
const effectivePolicy = {
|
|
586
|
-
...resolvedPolicy,
|
|
587
|
-
onSlotMetric: combinedOnSlotMetric
|
|
588
|
-
};
|
|
589
|
-
const preparedSlots = prepareSlots({
|
|
590
|
-
policy: effectivePolicy,
|
|
591
|
-
slots,
|
|
592
|
-
onError: combinedOnError,
|
|
593
|
-
onSlotMetric: combinedOnSlotMetric
|
|
594
|
-
});
|
|
595
|
-
if (preparedSlots.length === 0)
|
|
596
|
-
return stream;
|
|
597
|
-
const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
|
|
598
|
-
const encoder = new TextEncoder;
|
|
599
|
-
const decoder = new TextDecoder;
|
|
600
|
-
const reader = source.getReader();
|
|
601
|
-
const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
|
|
602
|
-
return new ReadableStream({
|
|
603
|
-
async start(controller) {
|
|
604
|
-
let baseDone = false;
|
|
605
|
-
let baseRead = reader.read();
|
|
606
|
-
let tail = "";
|
|
607
|
-
let footer = "";
|
|
608
|
-
try {
|
|
609
|
-
while (!baseDone || pending.length > 0) {
|
|
610
|
-
const racers = [];
|
|
611
|
-
if (!baseDone) {
|
|
612
|
-
racers.push(baseRead.then(({ done, value }) => ({
|
|
613
|
-
done,
|
|
614
|
-
kind: "base",
|
|
615
|
-
value
|
|
616
|
-
})));
|
|
617
|
-
}
|
|
618
|
-
if (pending.length > 0) {
|
|
619
|
-
racers.push(nextResolvedSlot(pending).then((resolved) => ({
|
|
620
|
-
kind: "slot",
|
|
621
|
-
...resolved
|
|
622
|
-
})));
|
|
623
|
-
}
|
|
624
|
-
if (racers.length === 0)
|
|
625
|
-
break;
|
|
626
|
-
const winner = await Promise.race(racers);
|
|
627
|
-
if (winner.kind === "base") {
|
|
628
|
-
if (winner.done) {
|
|
629
|
-
baseDone = true;
|
|
630
|
-
tail += decoder.decode();
|
|
631
|
-
const footerStart = tail.search(CLOSING_PAGE_TAG_REGEX);
|
|
632
|
-
if (footerStart >= 0) {
|
|
633
|
-
const content = tail.slice(0, footerStart);
|
|
634
|
-
footer = tail.slice(footerStart);
|
|
635
|
-
if (content.length > 0) {
|
|
636
|
-
controller.enqueue(encoder.encode(content));
|
|
637
|
-
}
|
|
638
|
-
} else if (tail.length > 0) {
|
|
639
|
-
controller.enqueue(encoder.encode(tail));
|
|
640
|
-
}
|
|
641
|
-
tail = "";
|
|
642
|
-
} else if (winner.value) {
|
|
643
|
-
tail += streamChunkToString2(winner.value, decoder);
|
|
644
|
-
if (tail.length > STREAM_TAIL_LOOKBEHIND) {
|
|
645
|
-
const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
|
|
646
|
-
controller.enqueue(encoder.encode(content));
|
|
647
|
-
tail = tail.slice(-STREAM_TAIL_LOOKBEHIND);
|
|
648
|
-
}
|
|
649
|
-
baseRead = reader.read();
|
|
650
|
-
}
|
|
651
|
-
continue;
|
|
652
|
-
}
|
|
653
|
-
const index = pending.indexOf(winner.original);
|
|
654
|
-
if (index >= 0)
|
|
655
|
-
pending.splice(index, 1);
|
|
656
|
-
if (winner.result.html === null)
|
|
657
|
-
continue;
|
|
658
|
-
emitSlotMetric({
|
|
659
|
-
type: "patched",
|
|
660
|
-
slotId: winner.result.id,
|
|
661
|
-
durationMs: winner.result.durationMs,
|
|
662
|
-
bytes: winner.result.bytes
|
|
663
|
-
}, combinedOnSlotMetric);
|
|
664
|
-
controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
|
|
665
|
-
}
|
|
666
|
-
if (footer.length > 0)
|
|
667
|
-
controller.enqueue(encoder.encode(footer));
|
|
668
|
-
controller.close();
|
|
669
|
-
} catch (error) {
|
|
670
|
-
controller.error(error);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
});
|
|
674
|
-
};
|
|
675
|
-
var init_streamingSlots = __esm(() => {
|
|
676
|
-
init_escapeScriptContent();
|
|
677
|
-
CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG2.length;
|
|
678
|
-
CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
|
|
679
|
-
currentStreamingSlotPolicy = {
|
|
680
|
-
timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
|
|
681
|
-
fallbackHtml: "",
|
|
682
|
-
errorHtml: undefined,
|
|
683
|
-
maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
|
|
684
|
-
maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
|
|
685
|
-
};
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
// src/core/streamingSlotRegistrar.ts
|
|
689
|
-
var registrar = null, setStreamingSlotRegistrar = (nextRegistrar) => {
|
|
690
|
-
registrar = nextRegistrar;
|
|
691
|
-
}, registerStreamingSlot = (slot) => {
|
|
692
|
-
registrar?.(slot);
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
// src/core/streamingSlotRegistry.ts
|
|
696
|
-
var asyncLocalStorage, isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string", ensureAsyncLocalStorage = async () => {
|
|
697
|
-
if (typeof asyncLocalStorage !== "undefined")
|
|
698
|
-
return asyncLocalStorage;
|
|
699
|
-
if (!isServerRuntime()) {
|
|
700
|
-
asyncLocalStorage = null;
|
|
701
|
-
return asyncLocalStorage;
|
|
702
|
-
}
|
|
703
|
-
const mod = await import("async_hooks");
|
|
704
|
-
asyncLocalStorage = new mod.AsyncLocalStorage;
|
|
705
|
-
return asyncLocalStorage;
|
|
706
|
-
}, registerStreamingSlot2 = (slot) => {
|
|
707
|
-
if (!asyncLocalStorage)
|
|
708
|
-
return;
|
|
709
|
-
const store = asyncLocalStorage.getStore();
|
|
710
|
-
if (!store)
|
|
711
|
-
return;
|
|
712
|
-
store.set(slot.id, slot);
|
|
713
|
-
}, runWithStreamingSlotRegistry = async (task) => {
|
|
714
|
-
const storage = await ensureAsyncLocalStorage();
|
|
715
|
-
if (!storage) {
|
|
716
|
-
return {
|
|
717
|
-
result: await task(),
|
|
718
|
-
slots: []
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
return storage.run(new Map, async () => {
|
|
722
|
-
const result = await task();
|
|
723
|
-
const store = storage.getStore();
|
|
724
|
-
return {
|
|
725
|
-
result,
|
|
726
|
-
slots: store ? [...store.values()] : []
|
|
727
|
-
};
|
|
728
|
-
});
|
|
729
|
-
};
|
|
730
|
-
var init_streamingSlotRegistry = __esm(() => {
|
|
731
|
-
setStreamingSlotRegistrar(registerStreamingSlot2);
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
// src/core/responseEnhancers.ts
|
|
735
|
-
var toResponse = async (responseLike) => await responseLike, cloneHeaders = (response) => {
|
|
736
|
-
const headers = new Headers(response.headers);
|
|
737
|
-
return headers;
|
|
738
|
-
}, enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
|
|
739
|
-
if (!response.body || streamingSlots.length === 0) {
|
|
740
|
-
return response;
|
|
741
|
-
}
|
|
742
|
-
const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
|
|
743
|
-
nonce,
|
|
744
|
-
onError,
|
|
745
|
-
policy
|
|
746
|
-
});
|
|
747
|
-
return new Response(body, {
|
|
748
|
-
headers: cloneHeaders(response),
|
|
749
|
-
status: response.status,
|
|
750
|
-
statusText: response.statusText
|
|
751
|
-
});
|
|
752
|
-
}, withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options), mergeStreamingSlots = (registered, explicit) => {
|
|
753
|
-
const merged = new Map;
|
|
754
|
-
for (const slot of registered)
|
|
755
|
-
merged.set(slot.id, slot);
|
|
756
|
-
for (const slot of explicit)
|
|
757
|
-
merged.set(slot.id, slot);
|
|
758
|
-
return [...merged.values()];
|
|
759
|
-
}, withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
|
|
760
|
-
const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
|
|
761
|
-
const explicit = options.streamingSlots ?? [];
|
|
762
|
-
return withStreamingSlots(result, {
|
|
763
|
-
...options,
|
|
764
|
-
streamingSlots: mergeStreamingSlots(slots, explicit)
|
|
765
|
-
});
|
|
766
|
-
};
|
|
767
|
-
var init_responseEnhancers = __esm(() => {
|
|
768
|
-
init_streamingSlots();
|
|
769
|
-
init_streamingSlotRegistry();
|
|
770
|
-
});
|
|
771
|
-
|
|
772
224
|
// src/utils/ssrErrorPage.ts
|
|
773
225
|
var ssrErrorPage = (framework, error) => {
|
|
774
226
|
const frameworkColors = {
|
|
@@ -1021,20 +473,6 @@ var init_resolveConvention = __esm(() => {
|
|
|
1021
473
|
];
|
|
1022
474
|
});
|
|
1023
475
|
|
|
1024
|
-
// src/react/streamingSlotCollection.tsx
|
|
1025
|
-
import { createContext, useContext } from "react";
|
|
1026
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
1027
|
-
var StreamingSlotCollectorContext, StreamingSlotCollectorProvider = ({
|
|
1028
|
-
children,
|
|
1029
|
-
collector
|
|
1030
|
-
}) => /* @__PURE__ */ jsxDEV(StreamingSlotCollectorContext.Provider, {
|
|
1031
|
-
value: collector,
|
|
1032
|
-
children
|
|
1033
|
-
}, undefined, false, undefined, this), useStreamingSlotCollector = () => useContext(StreamingSlotCollectorContext);
|
|
1034
|
-
var init_streamingSlotCollection = __esm(() => {
|
|
1035
|
-
StreamingSlotCollectorContext = createContext(null);
|
|
1036
|
-
});
|
|
1037
|
-
|
|
1038
476
|
// src/react/pageHandler.ts
|
|
1039
477
|
var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
|
|
1040
478
|
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
@@ -1053,9 +491,7 @@ var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
|
|
|
1053
491
|
try {
|
|
1054
492
|
const { createElement } = await import("react");
|
|
1055
493
|
const { renderToReadableStream } = await import("react-dom/server");
|
|
1056
|
-
const
|
|
1057
|
-
const pageElement = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
|
|
1058
|
-
const element = createElement(StreamingSlotCollectorProvider, { collector: slotCollector }, pageElement);
|
|
494
|
+
const element = maybeProps !== undefined ? createElement(PageComponent, maybeProps) : createElement(PageComponent);
|
|
1059
495
|
const propsScript = maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)};` : "";
|
|
1060
496
|
const refreshSetup = "window.__REFRESH_BUFFER__=[];window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};window.$RefreshSig$=function(){return function(t){return t}};";
|
|
1061
497
|
const stream = await renderToReadableStream(element, {
|
|
@@ -1069,10 +505,8 @@ var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
|
|
|
1069
505
|
await stream.allReady;
|
|
1070
506
|
}
|
|
1071
507
|
const htmlStream = injectIslandPageContextStream(stream);
|
|
1072
|
-
return
|
|
508
|
+
return new Response(htmlStream, {
|
|
1073
509
|
headers: { "Content-Type": "text/html" }
|
|
1074
|
-
}), {
|
|
1075
|
-
streamingSlots: [...slotCollector.values()]
|
|
1076
510
|
});
|
|
1077
511
|
} catch (error) {
|
|
1078
512
|
console.error("[SSR] React render error:", error);
|
|
@@ -1089,9 +523,7 @@ var ssrDirty = false, buildDirtyResponse = (index, maybeProps) => {
|
|
|
1089
523
|
ssrDirty = true;
|
|
1090
524
|
};
|
|
1091
525
|
var init_pageHandler = __esm(() => {
|
|
1092
|
-
init_responseEnhancers();
|
|
1093
526
|
init_resolveConvention();
|
|
1094
|
-
init_streamingSlotCollection();
|
|
1095
527
|
});
|
|
1096
528
|
|
|
1097
529
|
// src/react/server.ts
|
|
@@ -1100,5 +532,5 @@ export {
|
|
|
1100
532
|
handleReactPageRequest
|
|
1101
533
|
};
|
|
1102
534
|
|
|
1103
|
-
//# debugId=
|
|
535
|
+
//# debugId=F80EF14E5F29CD9864756E2164756E21
|
|
1104
536
|
//# sourceMappingURL=server.js.map
|