@askrjs/askr 0.3.0 → 0.4.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/CHANGELOG.md +874 -0
- package/README.md +61 -29
- package/capabilities.json +19 -9
- package/dist/actions/index.js +56 -12
- package/dist/benchmark.js +10 -15
- package/dist/boot/index.d.ts +3 -2
- package/dist/boot/index.js +1 -1
- package/dist/boot-DaoTYoCw.js +3989 -0
- package/dist/browser-activity-CB8e-V4f.js +220 -0
- package/dist/components/index.d.ts +8 -1
- package/dist/components/index.js +1 -43
- package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -1
- package/dist/control-nfpT2fbK.js +209 -0
- package/dist/core.d.ts +5 -9
- package/dist/csp-nonce-DwGw1A6Q.js +35 -0
- package/dist/data/index.js +3 -3
- package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
- package/dist/data-runtime-C1bFAlba.js +242 -0
- package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
- package/dist/domains/actions.d.ts +8 -3
- package/dist/domains/component.d.ts +1 -107
- package/dist/domains/context.d.ts +0 -15
- package/dist/domains/control.d.ts +36 -249
- package/dist/domains/data.d.ts +31 -13
- package/dist/domains/diagnostics.d.ts +1 -2
- package/dist/domains/lifecycle.d.ts +2 -5
- package/dist/domains/refs.d.ts +0 -2
- package/dist/domains/routing.d.ts +43 -8
- package/dist/domains/scheduler.d.ts +1 -76
- package/dist/domains/server.d.ts +5 -2
- package/dist/domains/state.d.ts +2 -5
- package/dist/domains/telemetry.d.ts +0 -2
- package/dist/elements.d.ts +214 -51
- package/dist/error-boundary-Bpwofwps.js +293 -0
- package/dist/foundations/icon/index.d.ts +0 -58
- package/dist/foundations/icon/index.js +2 -2
- package/dist/foundations/index.js +2 -1
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/foundations/state/index.d.ts +3 -3
- package/dist/foundations/state/index.js +5 -3
- package/dist/foundations/structures/index.js +2 -1
- package/dist/foundations/utilities/index.d.ts +2 -0
- package/dist/foundations/utilities/index.js +1 -2
- package/dist/fx/index.d.ts +31 -58
- package/dist/fx/index.js +313 -195
- package/dist/hooks-BimKStr4.js +202 -0
- package/dist/index.d.ts +11 -74
- package/dist/index.js +8 -447
- package/dist/instance-BAnfmXOR.js +988 -0
- package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
- package/dist/jsx-dev-runtime.d.ts +41 -18
- package/dist/jsx-dev-runtime.js +1 -6
- package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
- package/dist/jsx-runtime.js +1 -1
- package/dist/jsx.d.ts +61 -37
- package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
- package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
- package/dist/navigation.d.ts +12 -3
- package/dist/peer-types.d.ts +8 -0
- package/dist/portal-DuOKfnLa.js +349 -0
- package/dist/promise-Dz8iIHAm.js +16 -0
- package/dist/query-registry-WMCN0BJL.js +320 -0
- package/dist/readable-DFWOsTac.js +21 -0
- package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
- package/dist/render-sync-IC5lMFpq.js +1240 -0
- package/dist/resolution-Cx82-xjW.js +1244 -0
- package/dist/resource-CLjB7RBQ.js +377 -0
- package/dist/resources/index.d.ts +21 -11
- package/dist/resources/index.js +45 -244
- package/dist/router/index.d.ts +14 -5
- package/dist/router/index.js +22 -53
- package/dist/scope-CwpVSHVf.js +55 -0
- package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
- package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
- package/dist/ssg/index.d.ts +1 -2
- package/dist/ssg/index.js +5 -13
- package/dist/ssr/index.d.ts +26 -28
- package/dist/ssr/index.js +4 -4
- package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
- package/dist/ssr-DoV-vJ-5.js +229 -0
- package/dist/state-DWO1KzkX.js +232 -0
- package/dist/structures-D4dDMqHX.js +231 -0
- package/dist/testing/index.d.ts +8 -4
- package/dist/testing/index.js +29 -34
- package/dist/url-CnbfpX0K.js +185 -0
- package/dist/utilities.d.ts +48 -2
- package/dist/verify-hydration-DpVaDnqz.js +152 -0
- package/package.json +19 -9
- package/dist/access-CEA2pOry.js +0 -1046
- package/dist/activity-oy2YFTFF.js +0 -201
- package/dist/boot-BMBMWUGI.js +0 -1084
- package/dist/capabilities-Bbf0mlp9.js +0 -42
- package/dist/compose-ref-v0qGlHoN.js +0 -26
- package/dist/control-BR_mrX__.js +0 -173
- package/dist/control-C-ApnFs1.js +0 -20
- package/dist/csp-nonce-BfFWcd0w.js +0 -173
- package/dist/data-runtime-CxoY98lX.js +0 -149
- package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
- package/dist/dom-renderer.d.ts +0 -77
- package/dist/domains/renderer.d.ts +0 -127
- package/dist/eager-control.d.ts +0 -8
- package/dist/effect-C3Zsc1k6.js +0 -292
- package/dist/for-state-BDykeOJL.js +0 -1753
- package/dist/instance-VAFYVJOa.js +0 -1027
- package/dist/notify-DxxuDPeY.js +0 -266
- package/dist/portal-w3oQ6oQU.js +0 -29
- package/dist/query-registry-LrYpQsDJ.js +0 -83
- package/dist/render-resolved-BC0W7_5b.js +0 -1123
- package/dist/renderer-CT0HeY58.js +0 -8623
- package/dist/resolution-3DskUkjG.js +0 -577
- package/dist/resource-18-sFRl9.js +0 -344
- package/dist/route-matching-CUzZ31gT.js +0 -551
- package/dist/router-internal-7nuNEHfG.js +0 -36
- package/dist/scope-Cq_iYbTR.js +0 -403
- package/dist/selector-BSPVkjKP.js +0 -311
- package/dist/ssr-EPjwJH5R.js +0 -29
- package/dist/state-BXJfudq1.js +0 -91
- package/dist/structures-CjEzfj4h.js +0 -654
- package/dist/timer-C7uqnJVt.js +0 -85
- package/dist/verify-hydration-ikaxotf7.js +0 -27
- package/dist/vnode-D24p6IW2.js +0 -7
|
@@ -1,1123 +0,0 @@
|
|
|
1
|
-
import { v as logger } from "./access-CEA2pOry.js";
|
|
2
|
-
import { P as isPromiseLike, S as markVNodeTreeWithContextFrame, T as cleanupComponent, g as getExecutionContextFrame, n as createComponentInstance, p as callWithContext, x as getVNodeContextFrame } from "./instance-VAFYVJOa.js";
|
|
3
|
-
import { s as endComponentScope, u as enterRenderScopedComponent } from "./scope-Cq_iYbTR.js";
|
|
4
|
-
import { t as __CONTROL_BOUNDARY__ } from "./control-C-ApnFs1.js";
|
|
5
|
-
import { t as __ERROR_BOUNDARY__ } from "./vnode-D24p6IW2.js";
|
|
6
|
-
import { i as isFragmentType, n as Fragment, t as ELEMENT_TYPE } from "./jsx-DRS-qjiN.js";
|
|
7
|
-
import { _ as setControlBoundaryContextFrame, g as evaluateShowState, h as evaluateCaseState, i as evaluateForState, o as rollbackForStateTransaction, r as commitForStateTransaction } from "./for-state-BDykeOJL.js";
|
|
8
|
-
import { C as SSRDataMissingError, _ as isEmptyPageRenderEnvelope, f as stopRenderPhase$1, h as createPageRenderEnvelope, t as configureRenderContextProvider, u as startRenderPhase$1, v as isPageRenderEnvelope, x as withHydrationRenderUrl } from "./render-context-B7ohlh6t.js";
|
|
9
|
-
import { a as booleanAttributeValue, c as normalizeStylePropertyName, i as sanitizeCssValue, l as getPublicAttributeName, o as isAriaAttribute, r as validateCspNonce, s as isSkippedProp, t as CspNonceScope } from "./csp-nonce-BfFWcd0w.js";
|
|
10
|
-
import { r as isUnsafeUrlAttribute } from "./router-internal-7nuNEHfG.js";
|
|
11
|
-
import { n as SSR_PORTAL_HOST, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
|
|
12
|
-
import { t as createDataRuntime } from "./data-runtime-CxoY98lX.js";
|
|
13
|
-
import { i as dehydrateDataRuntime } from "./query-registry-LrYpQsDJ.js";
|
|
14
|
-
import { n as disposeRegisteredDefaultPortalScope, r as getDefaultPortalHost } from "./default-portal-runtime-DvMvWJVp.js";
|
|
15
|
-
import { S as isDeferred, b as DEFERRED_BOUNDARY, h as getRouteHydrationMetadata, v as validateRouteHydrationData } from "./resolution-3DskUkjG.js";
|
|
16
|
-
import { a as resolveRouteFromRoutes, c as removeRouteBasePath, s as normalizeRouteBasePath } from "./route-matching-CUzZ31gT.js";
|
|
17
|
-
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-EPjwJH5R.js";
|
|
18
|
-
//#region src/ssr/escape.ts
|
|
19
|
-
/**
|
|
20
|
-
* HTML escaping utilities for SSR
|
|
21
|
-
*
|
|
22
|
-
* Centralizes text and attribute escaping to avoid duplication
|
|
23
|
-
* between sync and streaming SSR renderers.
|
|
24
|
-
*/
|
|
25
|
-
const VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
26
|
-
"area",
|
|
27
|
-
"base",
|
|
28
|
-
"br",
|
|
29
|
-
"col",
|
|
30
|
-
"embed",
|
|
31
|
-
"hr",
|
|
32
|
-
"img",
|
|
33
|
-
"input",
|
|
34
|
-
"link",
|
|
35
|
-
"meta",
|
|
36
|
-
"param",
|
|
37
|
-
"source",
|
|
38
|
-
"track",
|
|
39
|
-
"wbr"
|
|
40
|
-
]);
|
|
41
|
-
const escapeCache = /* @__PURE__ */ new Map();
|
|
42
|
-
const MAX_CACHE_SIZE = 256;
|
|
43
|
-
const STYLE_PROP_CACHE = /* @__PURE__ */ new Map();
|
|
44
|
-
const MAX_STYLE_PROP_CACHE_SIZE = 512;
|
|
45
|
-
function toKebabCached(prop) {
|
|
46
|
-
const cached = STYLE_PROP_CACHE.get(prop);
|
|
47
|
-
if (cached !== void 0) return cached;
|
|
48
|
-
const kebab = normalizeStylePropertyName(prop);
|
|
49
|
-
if (STYLE_PROP_CACHE.size < MAX_STYLE_PROP_CACHE_SIZE) STYLE_PROP_CACHE.set(prop, kebab);
|
|
50
|
-
return kebab;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Clear the escape cache. Call between SSR requests in long-running servers
|
|
54
|
-
* to prevent memory buildup from unique strings.
|
|
55
|
-
*/
|
|
56
|
-
function clearEscapeCache() {
|
|
57
|
-
escapeCache.clear();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Fast check if a string needs text escaping.
|
|
61
|
-
* Used to skip the full escape call when not needed.
|
|
62
|
-
*/
|
|
63
|
-
function needsEscapeText(text) {
|
|
64
|
-
for (let i = 0; i < text.length; i++) {
|
|
65
|
-
const ch = text.charCodeAt(i);
|
|
66
|
-
if (ch === 38 || ch === 60 || ch === 62) return true;
|
|
67
|
-
}
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Fast check if a string needs attribute escaping.
|
|
72
|
-
* Checks for & " ' < > characters.
|
|
73
|
-
*/
|
|
74
|
-
function needsEscapeAttr(value) {
|
|
75
|
-
for (let i = 0; i < value.length; i++) {
|
|
76
|
-
const ch = value.charCodeAt(i);
|
|
77
|
-
if (ch === 38 || ch === 34 || ch === 39 || ch === 60 || ch === 62) return true;
|
|
78
|
-
}
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Escape HTML special characters in text content
|
|
83
|
-
* Fast-path: cache first, then scan-then-escape for new strings
|
|
84
|
-
*/
|
|
85
|
-
function escapeText(text) {
|
|
86
|
-
const useCache = text.length <= 64;
|
|
87
|
-
if (useCache) {
|
|
88
|
-
const cached = escapeCache.get(text);
|
|
89
|
-
if (cached !== void 0) return cached;
|
|
90
|
-
}
|
|
91
|
-
if (!needsEscapeText(text)) {
|
|
92
|
-
if (useCache && escapeCache.size < MAX_CACHE_SIZE) escapeCache.set(text, text);
|
|
93
|
-
return text;
|
|
94
|
-
}
|
|
95
|
-
let escaped = "";
|
|
96
|
-
let lastIndex = 0;
|
|
97
|
-
for (let i = 0; i < text.length; i++) {
|
|
98
|
-
const ch = text.charCodeAt(i);
|
|
99
|
-
let entity;
|
|
100
|
-
if (ch === 38) entity = "&";
|
|
101
|
-
else if (ch === 60) entity = "<";
|
|
102
|
-
else if (ch === 62) entity = ">";
|
|
103
|
-
else continue;
|
|
104
|
-
escaped += text.slice(lastIndex, i) + entity;
|
|
105
|
-
lastIndex = i + 1;
|
|
106
|
-
}
|
|
107
|
-
const result = escaped + text.slice(lastIndex);
|
|
108
|
-
if (useCache && escapeCache.size < MAX_CACHE_SIZE) escapeCache.set(text, result);
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Escape HTML special characters in attribute values.
|
|
113
|
-
* Single-pass scan: returns the original string unchanged when no special
|
|
114
|
-
* characters are found, so callers can drop separate needsEscapeAttr checks.
|
|
115
|
-
*/
|
|
116
|
-
function escapeAttr(value) {
|
|
117
|
-
let escaped = "";
|
|
118
|
-
let lastIndex = 0;
|
|
119
|
-
for (let i = 0; i < value.length; i++) {
|
|
120
|
-
const ch = value.charCodeAt(i);
|
|
121
|
-
let entity;
|
|
122
|
-
if (ch === 38) entity = "&";
|
|
123
|
-
else if (ch === 34) entity = """;
|
|
124
|
-
else if (ch === 39) entity = "'";
|
|
125
|
-
else if (ch === 60) entity = "<";
|
|
126
|
-
else if (ch === 62) entity = ">";
|
|
127
|
-
else continue;
|
|
128
|
-
escaped += value.slice(lastIndex, i) + entity;
|
|
129
|
-
lastIndex = i + 1;
|
|
130
|
-
}
|
|
131
|
-
return lastIndex === 0 ? value : escaped + value.slice(lastIndex);
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Convert a style object to a CSS string, omitting unsafe values.
|
|
135
|
-
* Optimized to avoid Object.entries allocation
|
|
136
|
-
*/
|
|
137
|
-
function styleObjToCss(value) {
|
|
138
|
-
if (!value || typeof value !== "object") return null;
|
|
139
|
-
const styleObj = value;
|
|
140
|
-
let result = "";
|
|
141
|
-
for (const k in styleObj) {
|
|
142
|
-
const v = styleObj[k];
|
|
143
|
-
if (v === null || v === void 0 || v === false) continue;
|
|
144
|
-
const prop = toKebabCached(k);
|
|
145
|
-
const safeValue = sanitizeCssValue(String(v));
|
|
146
|
-
if (safeValue) result += `${prop}:${safeValue};`;
|
|
147
|
-
}
|
|
148
|
-
return result || null;
|
|
149
|
-
}
|
|
150
|
-
//#endregion
|
|
151
|
-
//#region src/ssr/context.ts
|
|
152
|
-
/**
|
|
153
|
-
* SSR Context Management
|
|
154
|
-
*
|
|
155
|
-
* Provides render-context storage for server-side rendering.
|
|
156
|
-
* Node SSR lazily installs AsyncLocalStorage on first use; browser builds use
|
|
157
|
-
* the fallback stack.
|
|
158
|
-
*/
|
|
159
|
-
const FALLBACK_ASYNC_CONTEXT_ERROR = "[Askr] async SSR render context fallback is unsupported in this environment. Use synchronous SSR rendering or a runtime with AsyncLocalStorage.";
|
|
160
|
-
let renderContextAccessor = null;
|
|
161
|
-
let renderContextAccessorInitialized = false;
|
|
162
|
-
let asyncRenderContextAccessor = null;
|
|
163
|
-
let fallbackStack = null;
|
|
164
|
-
function ensureRenderContextAccessor() {
|
|
165
|
-
if (renderContextAccessorInitialized) return;
|
|
166
|
-
renderContextAccessorInitialized = true;
|
|
167
|
-
if (typeof process === "undefined" || !process.versions?.node) return;
|
|
168
|
-
try {
|
|
169
|
-
const asyncHooks = new Function("return require(" + JSON.stringify("async_hooks") + ");")();
|
|
170
|
-
if (asyncHooks.AsyncLocalStorage) {
|
|
171
|
-
const asyncLocalStorage = new asyncHooks.AsyncLocalStorage();
|
|
172
|
-
renderContextAccessor = {
|
|
173
|
-
getStore() {
|
|
174
|
-
return asyncLocalStorage.getStore();
|
|
175
|
-
},
|
|
176
|
-
run(store, fn) {
|
|
177
|
-
return asyncLocalStorage.run(store, fn);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
} catch {}
|
|
182
|
-
}
|
|
183
|
-
/** Build a fresh SSR render context (data cache, routes, seed) for a render pass. */
|
|
184
|
-
function createRenderContext(seed = 12345, opts = {}) {
|
|
185
|
-
clearEscapeCache();
|
|
186
|
-
const queryCache = /* @__PURE__ */ new Map();
|
|
187
|
-
const envelope = opts.envelope ?? createPageRenderEnvelope({
|
|
188
|
-
resources: opts.data,
|
|
189
|
-
framework: opts.framework
|
|
190
|
-
});
|
|
191
|
-
const hydrationEnvelope = opts.url ? withHydrationRenderUrl(envelope, opts.url) : envelope;
|
|
192
|
-
return {
|
|
193
|
-
url: opts.url ?? "",
|
|
194
|
-
seed,
|
|
195
|
-
data: opts.data,
|
|
196
|
-
params: opts.params,
|
|
197
|
-
routes: opts.routes,
|
|
198
|
-
routeAuth: opts.routeAuth,
|
|
199
|
-
authContext: opts.authContext,
|
|
200
|
-
basePath: opts.basePath,
|
|
201
|
-
signal: opts.signal,
|
|
202
|
-
dataRuntime: opts.dataRuntime ?? createDataRuntime({ queryCache }),
|
|
203
|
-
mode: opts.mode ?? "ssr",
|
|
204
|
-
queryPrefetch: opts.queryPrefetch,
|
|
205
|
-
queryCache,
|
|
206
|
-
resourceDataProvided: opts.envelope ? Object.keys(envelope.resources).some((key) => key.startsWith("r:")) : opts.data !== void 0,
|
|
207
|
-
ssrCleanupFns: [],
|
|
208
|
-
keyCounter: 0,
|
|
209
|
-
renderData: envelope,
|
|
210
|
-
hydrationData: hydrationEnvelope,
|
|
211
|
-
deferredBoundaries: [],
|
|
212
|
-
ssrStyles: /* @__PURE__ */ new Map(),
|
|
213
|
-
ssrPortals: {
|
|
214
|
-
slots: /* @__PURE__ */ new Map(),
|
|
215
|
-
nextHostId: 0
|
|
216
|
-
},
|
|
217
|
-
cspNonce: opts.cspNonce
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Run a function with the given render context.
|
|
222
|
-
* Concurrency-safe in Node.js via AsyncLocalStorage.
|
|
223
|
-
*/
|
|
224
|
-
function withRenderContext(ctx, fn) {
|
|
225
|
-
ensureRenderContextProvider();
|
|
226
|
-
ensureRenderContextAccessor();
|
|
227
|
-
if (renderContextAccessor) return renderContextAccessor.run(ctx, fn);
|
|
228
|
-
const prev = fallbackStack;
|
|
229
|
-
fallbackStack = ctx;
|
|
230
|
-
try {
|
|
231
|
-
const result = fn();
|
|
232
|
-
if (isPromiseLike(result)) throw new Error(FALLBACK_ASYNC_CONTEXT_ERROR);
|
|
233
|
-
return result;
|
|
234
|
-
} finally {
|
|
235
|
-
fallbackStack = prev;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
async function getAsyncRenderContextAccessor() {
|
|
239
|
-
ensureRenderContextAccessor();
|
|
240
|
-
if (renderContextAccessor) return renderContextAccessor;
|
|
241
|
-
if (typeof process === "undefined" || !process.versions?.node) return null;
|
|
242
|
-
asyncRenderContextAccessor ??= (async () => {
|
|
243
|
-
try {
|
|
244
|
-
const module = await import(
|
|
245
|
-
/* @vite-ignore */
|
|
246
|
-
"node:async_hooks"
|
|
247
|
-
);
|
|
248
|
-
if (!module.AsyncLocalStorage) return null;
|
|
249
|
-
const storage = new module.AsyncLocalStorage();
|
|
250
|
-
renderContextAccessor = {
|
|
251
|
-
getStore: () => storage.getStore(),
|
|
252
|
-
run: (store, fn) => storage.run(store, fn)
|
|
253
|
-
};
|
|
254
|
-
return renderContextAccessor;
|
|
255
|
-
} catch {
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
})();
|
|
259
|
-
return asyncRenderContextAccessor;
|
|
260
|
-
}
|
|
261
|
-
/** Run `fn` with `ctx` as the active SSR render context, using async-local storage. */
|
|
262
|
-
async function withRenderContextAsync(ctx, fn) {
|
|
263
|
-
ensureRenderContextProvider();
|
|
264
|
-
const accessor = await getAsyncRenderContextAccessor();
|
|
265
|
-
if (accessor) return accessor.run(ctx, () => Promise.resolve(fn()));
|
|
266
|
-
throw new Error(FALLBACK_ASYNC_CONTEXT_ERROR);
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Get the current render context.
|
|
270
|
-
* Returns null if not inside a render.
|
|
271
|
-
*/
|
|
272
|
-
function getRenderContext() {
|
|
273
|
-
ensureRenderContextAccessor();
|
|
274
|
-
if (renderContextAccessor) return renderContextAccessor.getStore() ?? null;
|
|
275
|
-
return fallbackStack;
|
|
276
|
-
}
|
|
277
|
-
let renderContextProvided = false;
|
|
278
|
-
/**
|
|
279
|
-
* Publish this module's render-context accessor to `common/render-context`.
|
|
280
|
-
*
|
|
281
|
-
* Runtime code (resources, portals, deferred routes) asks that module for the
|
|
282
|
-
* active SSR context, and it cannot import SSR. Installing the accessor at
|
|
283
|
-
* module scope meant the answer depended on whether anything had imported this
|
|
284
|
-
* module; entering a render context composes it instead. Consumers only ever
|
|
285
|
-
* observe a context from inside one, so this covers every reader.
|
|
286
|
-
*/
|
|
287
|
-
function ensureRenderContextProvider() {
|
|
288
|
-
if (renderContextProvided) return;
|
|
289
|
-
renderContextProvided = true;
|
|
290
|
-
configureRenderContextProvider({ getRenderContext });
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Centralized SSR enforcement helper — throws a consistent error when async
|
|
294
|
-
* data is encountered during synchronous SSR.
|
|
295
|
-
*/
|
|
296
|
-
function throwSSRDataMissing() {
|
|
297
|
-
throw new SSRDataMissingError();
|
|
298
|
-
}
|
|
299
|
-
//#endregion
|
|
300
|
-
//#region src/ssr/sink.ts
|
|
301
|
-
var StringSink = class StringSink {
|
|
302
|
-
constructor() {
|
|
303
|
-
this.chunks = [];
|
|
304
|
-
this.bufferChunks = [];
|
|
305
|
-
this.bufferLen = 0;
|
|
306
|
-
}
|
|
307
|
-
static {
|
|
308
|
-
this.FLUSH_THRESHOLD = 32768;
|
|
309
|
-
}
|
|
310
|
-
write(html) {
|
|
311
|
-
if (!html) return;
|
|
312
|
-
this.bufferChunks.push(html);
|
|
313
|
-
this.bufferLen += html.length;
|
|
314
|
-
if (this.bufferLen >= StringSink.FLUSH_THRESHOLD) {
|
|
315
|
-
this.chunks.push(this.bufferChunks.join(""));
|
|
316
|
-
this.bufferChunks.length = 0;
|
|
317
|
-
this.bufferLen = 0;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
write2(a, b) {
|
|
321
|
-
if (a) {
|
|
322
|
-
this.bufferChunks.push(a);
|
|
323
|
-
this.bufferLen += a.length;
|
|
324
|
-
}
|
|
325
|
-
if (b) {
|
|
326
|
-
this.bufferChunks.push(b);
|
|
327
|
-
this.bufferLen += b.length;
|
|
328
|
-
}
|
|
329
|
-
if (this.bufferLen >= StringSink.FLUSH_THRESHOLD) {
|
|
330
|
-
this.chunks.push(this.bufferChunks.join(""));
|
|
331
|
-
this.bufferChunks.length = 0;
|
|
332
|
-
this.bufferLen = 0;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
write3(a, b, c) {
|
|
336
|
-
if (a) {
|
|
337
|
-
this.bufferChunks.push(a);
|
|
338
|
-
this.bufferLen += a.length;
|
|
339
|
-
}
|
|
340
|
-
if (b) {
|
|
341
|
-
this.bufferChunks.push(b);
|
|
342
|
-
this.bufferLen += b.length;
|
|
343
|
-
}
|
|
344
|
-
if (c) {
|
|
345
|
-
this.bufferChunks.push(c);
|
|
346
|
-
this.bufferLen += c.length;
|
|
347
|
-
}
|
|
348
|
-
if (this.bufferLen >= StringSink.FLUSH_THRESHOLD) {
|
|
349
|
-
this.chunks.push(this.bufferChunks.join(""));
|
|
350
|
-
this.bufferChunks.length = 0;
|
|
351
|
-
this.bufferLen = 0;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
end() {
|
|
355
|
-
if (this.bufferLen) {
|
|
356
|
-
this.chunks.push(this.bufferChunks.join(""));
|
|
357
|
-
this.bufferChunks.length = 0;
|
|
358
|
-
this.bufferLen = 0;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
toString() {
|
|
362
|
-
if (this.bufferLen) {
|
|
363
|
-
this.chunks.push(this.bufferChunks.join(""));
|
|
364
|
-
this.bufferChunks.length = 0;
|
|
365
|
-
this.bufferLen = 0;
|
|
366
|
-
}
|
|
367
|
-
return this.chunks.join("");
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
var StreamSink = class {
|
|
371
|
-
constructor(onChunk, onComplete) {
|
|
372
|
-
this.onChunk = onChunk;
|
|
373
|
-
this.onComplete = onComplete;
|
|
374
|
-
}
|
|
375
|
-
write(html) {
|
|
376
|
-
if (html) this.onChunk(html);
|
|
377
|
-
}
|
|
378
|
-
end() {
|
|
379
|
-
this.onComplete();
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
//#endregion
|
|
383
|
-
//#region src/ssr/component-runtime.ts
|
|
384
|
-
function executeComponentSync(component, props, ctx, ownerFrame = null) {
|
|
385
|
-
try {
|
|
386
|
-
const temp = createComponentInstance("ssr-temp", component, props || {}, null, null);
|
|
387
|
-
temp.ssr = true;
|
|
388
|
-
temp.ownerFrame = ownerFrame;
|
|
389
|
-
temp.portalScope = temp;
|
|
390
|
-
ctx.ssrCleanupFns.push(() => {
|
|
391
|
-
let cleanupError = null;
|
|
392
|
-
try {
|
|
393
|
-
cleanupComponent(temp);
|
|
394
|
-
} catch (error) {
|
|
395
|
-
cleanupError = error;
|
|
396
|
-
}
|
|
397
|
-
try {
|
|
398
|
-
disposeRegisteredDefaultPortalScope(temp);
|
|
399
|
-
} catch (error) {
|
|
400
|
-
if (cleanupError) throw new AggregateError([cleanupError, error], "SSR temporary owner cleanup failed");
|
|
401
|
-
throw error;
|
|
402
|
-
}
|
|
403
|
-
if (cleanupError) throw cleanupError;
|
|
404
|
-
});
|
|
405
|
-
const previous = enterRenderScopedComponent(temp, 0);
|
|
406
|
-
try {
|
|
407
|
-
const executionFrame = getExecutionContextFrame(ownerFrame);
|
|
408
|
-
const result = callWithContext(executionFrame, component, props || {}, { ssr: ctx });
|
|
409
|
-
if (isPromiseLike(result)) throwSSRDataMissing();
|
|
410
|
-
if (typeof result === "string" || typeof result === "number" || typeof result === "boolean" || result === null || result === void 0) {
|
|
411
|
-
const inner = result === null || result === void 0 || result === false ? "" : String(result);
|
|
412
|
-
return {
|
|
413
|
-
$$typeof: ELEMENT_TYPE,
|
|
414
|
-
type: Fragment,
|
|
415
|
-
props: { children: inner ? [inner] : [] }
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
return markVNodeTreeWithContextFrame(result, ownerFrame);
|
|
419
|
-
} finally {
|
|
420
|
-
endComponentScope(previous);
|
|
421
|
-
}
|
|
422
|
-
} finally {}
|
|
423
|
-
}
|
|
424
|
-
function disposeSSRTemporaryOwners(ctx) {
|
|
425
|
-
const cleanupFns = ctx.ssrCleanupFns;
|
|
426
|
-
ctx.ssrCleanupFns = [];
|
|
427
|
-
const cleanupErrors = [];
|
|
428
|
-
for (let index = cleanupFns.length - 1; index >= 0; index -= 1) try {
|
|
429
|
-
cleanupFns[index]();
|
|
430
|
-
} catch (error) {
|
|
431
|
-
cleanupErrors.push(error);
|
|
432
|
-
}
|
|
433
|
-
if (cleanupErrors.length === 1) throw cleanupErrors[0];
|
|
434
|
-
if (cleanupErrors.length > 1) throw new AggregateError(cleanupErrors, "SSR temporary owner cleanup failed");
|
|
435
|
-
}
|
|
436
|
-
function wrapWithDefaultPortal(out) {
|
|
437
|
-
if (isPromiseLike(out)) throwSSRDataMissing();
|
|
438
|
-
const portalVNode = {
|
|
439
|
-
$$typeof: ELEMENT_TYPE,
|
|
440
|
-
type: getDefaultPortalHost(),
|
|
441
|
-
props: { __askrAutoDefaultPortal: true },
|
|
442
|
-
key: "__default_portal"
|
|
443
|
-
};
|
|
444
|
-
if (out == null) return {
|
|
445
|
-
$$typeof: ELEMENT_TYPE,
|
|
446
|
-
type: Fragment,
|
|
447
|
-
props: { children: [portalVNode] }
|
|
448
|
-
};
|
|
449
|
-
return {
|
|
450
|
-
$$typeof: ELEMENT_TYPE,
|
|
451
|
-
type: Fragment,
|
|
452
|
-
props: { children: [out, portalVNode] }
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
function renderSyncComponentRoot(component, props, ctx) {
|
|
456
|
-
const wrapped = (p, c) => wrapWithDefaultPortal(component(p ?? {}, c));
|
|
457
|
-
return executeComponentSync(wrapped, props || {}, ctx);
|
|
458
|
-
}
|
|
459
|
-
//#endregion
|
|
460
|
-
//#region src/ssr/boundaries.ts
|
|
461
|
-
function normalizeRenderableChildren(value) {
|
|
462
|
-
if (value === null || value === void 0 || value === false) return [];
|
|
463
|
-
return Array.isArray(value) ? value : [value];
|
|
464
|
-
}
|
|
465
|
-
function getRenderableChildren(node) {
|
|
466
|
-
if (Array.isArray(node.children)) return node.children;
|
|
467
|
-
if (Array.isArray(node.props?.children)) return node.props.children;
|
|
468
|
-
if (node.props?.children !== void 0 && node.props.children !== null && node.props.children !== false) return [node.props.children];
|
|
469
|
-
}
|
|
470
|
-
function getErrorBoundaryState(node) {
|
|
471
|
-
return node.__instance?.errorBoundaryState ?? null;
|
|
472
|
-
}
|
|
473
|
-
function resetErrorBoundaryState(node) {
|
|
474
|
-
const state = node.__instance?.errorBoundaryState;
|
|
475
|
-
if (state) {
|
|
476
|
-
state.error = null;
|
|
477
|
-
state.notified = false;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
function createErrorBoundaryReset(node) {
|
|
481
|
-
return () => resetErrorBoundaryState(node);
|
|
482
|
-
}
|
|
483
|
-
function createDefaultErrorBoundaryFallbackVNode(error) {
|
|
484
|
-
const message = error instanceof Error ? error.stack || error.message || error.name : typeof error === "string" ? error : (() => {
|
|
485
|
-
try {
|
|
486
|
-
return JSON.stringify(error);
|
|
487
|
-
} catch {
|
|
488
|
-
return String(error);
|
|
489
|
-
}
|
|
490
|
-
})();
|
|
491
|
-
return {
|
|
492
|
-
$$typeof: ELEMENT_TYPE,
|
|
493
|
-
type: "div",
|
|
494
|
-
props: {
|
|
495
|
-
role: "alert",
|
|
496
|
-
"data-askr-error-boundary": "true",
|
|
497
|
-
style: {
|
|
498
|
-
boxSizing: "border-box",
|
|
499
|
-
padding: "1rem",
|
|
500
|
-
border: "1px solid currentColor",
|
|
501
|
-
borderRadius: "0.75rem",
|
|
502
|
-
display: "grid",
|
|
503
|
-
gap: "0.75rem",
|
|
504
|
-
maxWidth: "100%"
|
|
505
|
-
},
|
|
506
|
-
children: [
|
|
507
|
-
{
|
|
508
|
-
$$typeof: ELEMENT_TYPE,
|
|
509
|
-
type: "strong",
|
|
510
|
-
props: { children: ["Something went wrong while rendering this view."] }
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
$$typeof: ELEMENT_TYPE,
|
|
514
|
-
type: "p",
|
|
515
|
-
props: {
|
|
516
|
-
style: { margin: "0" },
|
|
517
|
-
children: ["The app recovered into a visible fallback so the error is not hidden in the console."]
|
|
518
|
-
}
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
$$typeof: ELEMENT_TYPE,
|
|
522
|
-
type: "details",
|
|
523
|
-
props: {
|
|
524
|
-
open: false,
|
|
525
|
-
children: [{
|
|
526
|
-
$$typeof: ELEMENT_TYPE,
|
|
527
|
-
type: "summary",
|
|
528
|
-
props: { children: ["Error details"] }
|
|
529
|
-
}, {
|
|
530
|
-
$$typeof: ELEMENT_TYPE,
|
|
531
|
-
type: "pre",
|
|
532
|
-
props: {
|
|
533
|
-
style: {
|
|
534
|
-
margin: "0",
|
|
535
|
-
whiteSpace: "pre-wrap",
|
|
536
|
-
wordBreak: "break-word"
|
|
537
|
-
},
|
|
538
|
-
children: [message]
|
|
539
|
-
}
|
|
540
|
-
}]
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
]
|
|
544
|
-
},
|
|
545
|
-
key: null
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
function resolveErrorBoundaryFallbackNode(fallback, error, reset) {
|
|
549
|
-
return typeof fallback === "function" ? fallback(error, reset) : fallback !== void 0 ? fallback : createDefaultErrorBoundaryFallbackVNode(error);
|
|
550
|
-
}
|
|
551
|
-
function getControlBoundaryState(node) {
|
|
552
|
-
const boundaryNode = node;
|
|
553
|
-
const controlState = boundaryNode._controlState ?? null;
|
|
554
|
-
const frame = getVNodeContextFrame(boundaryNode);
|
|
555
|
-
if (controlState && frame) setControlBoundaryContextFrame(controlState, frame);
|
|
556
|
-
return controlState;
|
|
557
|
-
}
|
|
558
|
-
function evaluateControlBoundaryChildren(node) {
|
|
559
|
-
if (node.type !== __CONTROL_BOUNDARY__) return;
|
|
560
|
-
const controlState = getControlBoundaryState(node);
|
|
561
|
-
if (!controlState) return [];
|
|
562
|
-
if (controlState.kind === "for") return evaluateForState(controlState);
|
|
563
|
-
if (controlState.kind === "show") return evaluateShowState(controlState);
|
|
564
|
-
return evaluateCaseState(controlState);
|
|
565
|
-
}
|
|
566
|
-
function withControlBoundaryChildren(node, render) {
|
|
567
|
-
const controlState = getControlBoundaryState(node);
|
|
568
|
-
if (!controlState || controlState.kind !== "for") return render(evaluateControlBoundaryChildren(node));
|
|
569
|
-
const children = evaluateForState(controlState);
|
|
570
|
-
try {
|
|
571
|
-
const result = render(children);
|
|
572
|
-
commitForStateTransaction(controlState);
|
|
573
|
-
return result;
|
|
574
|
-
} catch (error) {
|
|
575
|
-
rollbackForStateTransaction(controlState);
|
|
576
|
-
throw error;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
//#endregion
|
|
580
|
-
//#region src/ssr/attrs.ts
|
|
581
|
-
const ESCAPED_ATTR_VALUE_CACHE_LIMIT = 512;
|
|
582
|
-
const escapedAttrValueCache = /* @__PURE__ */ new Map();
|
|
583
|
-
function isEventHandler(key) {
|
|
584
|
-
return key.length >= 2 && key.slice(0, 2).toLowerCase() === "on";
|
|
585
|
-
}
|
|
586
|
-
function assertAttributeName(name) {
|
|
587
|
-
if (!/^[A-Za-z_:][A-Za-z0-9_.:-]*$/.test(name)) throw new TypeError(`Invalid SSR attribute name: ${JSON.stringify(name)}`);
|
|
588
|
-
}
|
|
589
|
-
function getEscapedAttrValue(value) {
|
|
590
|
-
if (value.length > 64) return escapeAttr(value);
|
|
591
|
-
const cached = escapedAttrValueCache.get(value);
|
|
592
|
-
if (cached !== void 0) return cached;
|
|
593
|
-
const escaped = escapeAttr(value);
|
|
594
|
-
if (escaped === value) return value;
|
|
595
|
-
if (escapedAttrValueCache.size >= ESCAPED_ATTR_VALUE_CACHE_LIMIT) escapedAttrValueCache.clear();
|
|
596
|
-
escapedAttrValueCache.set(value, escaped);
|
|
597
|
-
return escaped;
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* Render attributes directly to a sink without intermediate string allocations.
|
|
601
|
-
* This is the hot path for streaming SSR.
|
|
602
|
-
*/
|
|
603
|
-
function renderAttrsDirect(props, sink) {
|
|
604
|
-
if (!props || typeof props !== "object") return;
|
|
605
|
-
const propsObj = props;
|
|
606
|
-
for (const key in propsObj) {
|
|
607
|
-
const value = propsObj[key];
|
|
608
|
-
if (isSkippedProp(key) || key === "dangerouslySetInnerHTML") continue;
|
|
609
|
-
if (isEventHandler(key)) continue;
|
|
610
|
-
if (key.charCodeAt(0) === 95) continue;
|
|
611
|
-
const attrName = getPublicAttributeName(key);
|
|
612
|
-
assertAttributeName(attrName);
|
|
613
|
-
if (attrName === "style") {
|
|
614
|
-
const css = typeof value === "string" ? value : styleObjToCss(value);
|
|
615
|
-
if (!css) continue;
|
|
616
|
-
sink.write(" style=\"");
|
|
617
|
-
if (needsEscapeAttr(css)) sink.write(getEscapedAttrValue(css));
|
|
618
|
-
else sink.write(css);
|
|
619
|
-
sink.write("\"");
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
if (value === true) {
|
|
623
|
-
sink.write(" ");
|
|
624
|
-
sink.write(attrName);
|
|
625
|
-
const booleanValue = booleanAttributeValue(attrName);
|
|
626
|
-
if (booleanValue) {
|
|
627
|
-
sink.write("=\"");
|
|
628
|
-
sink.write(booleanValue);
|
|
629
|
-
sink.write("\"");
|
|
630
|
-
}
|
|
631
|
-
continue;
|
|
632
|
-
}
|
|
633
|
-
if (value === null || value === void 0 || value === false && !isAriaAttribute(attrName)) continue;
|
|
634
|
-
const strValue = String(value);
|
|
635
|
-
if (isUnsafeUrlAttribute(attrName, strValue)) continue;
|
|
636
|
-
sink.write(" ");
|
|
637
|
-
sink.write(attrName);
|
|
638
|
-
sink.write("=\"");
|
|
639
|
-
sink.write(getEscapedAttrValue(strValue));
|
|
640
|
-
sink.write("\"");
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
//#endregion
|
|
644
|
-
//#region src/ssr/hydration-data.ts
|
|
645
|
-
const DEFERRED_PAYLOAD = "__askr_deferred__";
|
|
646
|
-
function hydrationReplacer(_key, value) {
|
|
647
|
-
if (!isDeferred(value)) return value;
|
|
648
|
-
if (value.state === "fulfilled") return {
|
|
649
|
-
[DEFERRED_PAYLOAD]: "fulfilled",
|
|
650
|
-
value: value.value
|
|
651
|
-
};
|
|
652
|
-
if (value.state === "rejected") return {
|
|
653
|
-
[DEFERRED_PAYLOAD]: "rejected",
|
|
654
|
-
error: value.error instanceof Error ? value.error.message : String(value.error)
|
|
655
|
-
};
|
|
656
|
-
return { [DEFERRED_PAYLOAD]: "pending" };
|
|
657
|
-
}
|
|
658
|
-
function serializeHydrationRenderData(data, runtime) {
|
|
659
|
-
const queryCache = runtime ? dehydrateDataRuntime(runtime) : void 0;
|
|
660
|
-
const current = isPageRenderEnvelope(data) ? data : createPageRenderEnvelope({ resources: data });
|
|
661
|
-
const payload = createPageRenderEnvelope({
|
|
662
|
-
resources: {
|
|
663
|
-
...current.resources,
|
|
664
|
-
...queryCache
|
|
665
|
-
},
|
|
666
|
-
route: current.route,
|
|
667
|
-
framework: current.framework
|
|
668
|
-
});
|
|
669
|
-
const routeHydration = getRouteHydrationMetadata(payload.framework);
|
|
670
|
-
if (routeHydration) validateRouteHydrationData(payload.route, routeHydration.r);
|
|
671
|
-
if (isEmptyPageRenderEnvelope(payload)) return "";
|
|
672
|
-
return `<script type="application/json" ${SSR_RENDER_DATA_ATTR}="true">${JSON.stringify(payload, hydrationReplacer).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")}<\/script>`;
|
|
673
|
-
}
|
|
674
|
-
//#endregion
|
|
675
|
-
//#region src/ssr/render-keys.ts
|
|
676
|
-
/**
|
|
677
|
-
* SSR Data Management
|
|
678
|
-
*
|
|
679
|
-
* Manages render-phase keying for deterministic SSR data lookup.
|
|
680
|
-
* All state is stored in the per-render context for concurrency safety.
|
|
681
|
-
*/
|
|
682
|
-
function startRenderPhase(data) {
|
|
683
|
-
startRenderPhase$1(data === null ? null : isPageRenderEnvelope(data) ? data : createPageRenderEnvelope({ resources: data }));
|
|
684
|
-
}
|
|
685
|
-
function stopRenderPhase() {
|
|
686
|
-
stopRenderPhase$1();
|
|
687
|
-
}
|
|
688
|
-
//#endregion
|
|
689
|
-
//#region src/ssr/render-sync.ts
|
|
690
|
-
const RANGE_START = "<!--askr-range-start-->";
|
|
691
|
-
const RANGE_END = "<!--askr-range-end-->";
|
|
692
|
-
function isMultiRangeChild(child) {
|
|
693
|
-
if (Array.isArray(child)) return true;
|
|
694
|
-
if (!child || typeof child !== "object" || !("type" in child)) return false;
|
|
695
|
-
return isFragmentType(child.type);
|
|
696
|
-
}
|
|
697
|
-
function inheritRenderableKey(source, result) {
|
|
698
|
-
const inheritedKey = source.key;
|
|
699
|
-
if (inheritedKey === void 0 || inheritedKey === null) return result;
|
|
700
|
-
if (!result || typeof result !== "object" || !("type" in result)) return result;
|
|
701
|
-
const resultVNode = result;
|
|
702
|
-
if (resultVNode.key === void 0 || resultVNode.key === null) resultVNode.key = inheritedKey;
|
|
703
|
-
if (typeof resultVNode.type === "string") {
|
|
704
|
-
if (!resultVNode.props) resultVNode.props = {};
|
|
705
|
-
if (resultVNode.props["data-key"] === void 0) resultVNode.props["data-key"] = String(inheritedKey);
|
|
706
|
-
if (resultVNode.props["data-askr-key-kind"] === void 0) resultVNode.props["data-askr-key-kind"] = typeof inheritedKey;
|
|
707
|
-
}
|
|
708
|
-
return result;
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Render a value to a string through the streaming renderer.
|
|
712
|
-
*
|
|
713
|
-
* Portal resolution splices content into the finished document by token, so it
|
|
714
|
-
* genuinely needs a string — but it gets one from the same renderer everything
|
|
715
|
-
* else uses rather than from a second implementation.
|
|
716
|
-
*/
|
|
717
|
-
function renderRenderableToString(value, ctx) {
|
|
718
|
-
const sink = new StringSink();
|
|
719
|
-
renderRenderableSyncToSink(value, sink, ctx);
|
|
720
|
-
sink.end();
|
|
721
|
-
return sink.toString();
|
|
722
|
-
}
|
|
723
|
-
function resolveSSRPortals(html, ctx) {
|
|
724
|
-
let resolved = html;
|
|
725
|
-
const renderedHosts = /* @__PURE__ */ new Set();
|
|
726
|
-
for (;;) {
|
|
727
|
-
let foundHost = false;
|
|
728
|
-
for (const slot of ctx.ssrPortals.slots.values()) {
|
|
729
|
-
const explicitHosts = slot.hosts.filter((host) => !host.automatic);
|
|
730
|
-
const activeHosts = explicitHosts.length > 0 ? new Set(explicitHosts.map((host) => host.token)) : new Set(slot.hosts.map((host) => host.token));
|
|
731
|
-
for (const host of slot.hosts) {
|
|
732
|
-
if (renderedHosts.has(host.token)) continue;
|
|
733
|
-
foundHost = true;
|
|
734
|
-
const content = activeHosts.has(host.token) && slot.hasValue ? renderRenderableToString(slot.value, ctx) : "";
|
|
735
|
-
resolved = resolved.replace(host.token, () => host.automatic && content === "" && slot.hasValue && explicitHosts.length === 0 ? host.token : content);
|
|
736
|
-
renderedHosts.add(host.token);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
if (!foundHost) return resolved;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
var SSRPortalSink = class {
|
|
743
|
-
constructor(sink) {
|
|
744
|
-
this.sink = sink;
|
|
745
|
-
this.bufferedChunks = null;
|
|
746
|
-
}
|
|
747
|
-
write(html) {
|
|
748
|
-
if (!html) return;
|
|
749
|
-
if (this.bufferedChunks) {
|
|
750
|
-
this.bufferedChunks.push(html);
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
this.sink.write(html);
|
|
754
|
-
}
|
|
755
|
-
writePortalHost(token) {
|
|
756
|
-
this.bufferedChunks ??= [];
|
|
757
|
-
this.bufferedChunks.push(token);
|
|
758
|
-
}
|
|
759
|
-
flush(ctx) {
|
|
760
|
-
if (!this.bufferedChunks) return;
|
|
761
|
-
this.sink.write(resolveSSRPortals(this.bufferedChunks.join(""), ctx));
|
|
762
|
-
}
|
|
763
|
-
};
|
|
764
|
-
/**
|
|
765
|
-
* Collects writes so they can be published to a real sink, or dropped.
|
|
766
|
-
*
|
|
767
|
-
* An ErrorBoundary is transactional: markup its subtree produced before a
|
|
768
|
-
* descendant threw must never reach the response, or the fallback lands inside
|
|
769
|
-
* a half-written element. A sink cannot take output back, so the protected
|
|
770
|
-
* subtree renders into one of these first.
|
|
771
|
-
*
|
|
772
|
-
* Portal host writes are recorded rather than flattened, because reaching the
|
|
773
|
-
* real sink through `writePortalHost` is what puts it into portal-resolving
|
|
774
|
-
* mode; replaying them preserves both that signal and the original order.
|
|
775
|
-
*/
|
|
776
|
-
var BufferedSink = class {
|
|
777
|
-
constructor() {
|
|
778
|
-
this.operations = [];
|
|
779
|
-
}
|
|
780
|
-
write(html) {
|
|
781
|
-
if (html) this.operations.push({
|
|
782
|
-
portalHost: false,
|
|
783
|
-
text: html
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
writePortalHost(token) {
|
|
787
|
-
this.operations.push({
|
|
788
|
-
portalHost: true,
|
|
789
|
-
text: token
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
publishTo(sink) {
|
|
793
|
-
for (const operation of this.operations) if (operation.portalHost && sink.writePortalHost) sink.writePortalHost(operation.text);
|
|
794
|
-
else sink.write(operation.text);
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
function renderRenderableSyncToSink(value, sink, ctx) {
|
|
798
|
-
if (value === null || value === void 0 || value === false) return;
|
|
799
|
-
if (typeof value === "string") {
|
|
800
|
-
sink.write(escapeText(value));
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
if (typeof value === "number") {
|
|
804
|
-
sink.write(escapeText(String(value)));
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
|
-
if (Array.isArray(value)) {
|
|
808
|
-
renderChildrenSyncToSink(value, sink, ctx);
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
if (value && typeof value === "object" && "type" in value) renderNodeSyncToSink(value, sink, ctx);
|
|
812
|
-
}
|
|
813
|
-
function renderChildSyncToSink(child, sink, ctx) {
|
|
814
|
-
renderRenderableSyncToSink(child, sink, ctx);
|
|
815
|
-
}
|
|
816
|
-
/**
|
|
817
|
-
* Write a deferred boundary's pending content inside its resolve wrapper.
|
|
818
|
-
*
|
|
819
|
-
* The wrapper is known from the node's props, so the children stream into the
|
|
820
|
-
* sink between the two markers rather than being rendered to a string first.
|
|
821
|
-
*/
|
|
822
|
-
function renderDeferredBoundaryToSink(node, sink, ctx) {
|
|
823
|
-
const id = String(node.props?.["id"] ?? "");
|
|
824
|
-
sink.write(`<askr-resolve data-askr-deferred="${id}">`);
|
|
825
|
-
renderRenderableSyncToSink(node.props?.["pending"], sink, ctx);
|
|
826
|
-
sink.write("</askr-resolve>");
|
|
827
|
-
}
|
|
828
|
-
/** Write one `For` row, bracketing it with range markers when it spans several nodes. */
|
|
829
|
-
function renderForRangeChildToSink(child, sink, ctx) {
|
|
830
|
-
if (child && typeof child === "object" && "type" in child && typeof child.type === "function") {
|
|
831
|
-
const vnode = child;
|
|
832
|
-
renderForRangeChildToSink(inheritRenderableKey(vnode, executeComponentSync(vnode.type, vnode.props, ctx, getVNodeContextFrame(vnode) ?? null)), sink, ctx);
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
const spansRange = isMultiRangeChild(child);
|
|
836
|
-
if (spansRange) sink.write(RANGE_START);
|
|
837
|
-
renderChildSyncToSink(child, sink, ctx);
|
|
838
|
-
if (spansRange) sink.write(RANGE_END);
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* Write a control boundary's children.
|
|
842
|
-
*
|
|
843
|
-
* Whether the boundary needs range markers is decided from the children
|
|
844
|
-
* themselves, before any of them render, so the decision costs nothing and the
|
|
845
|
-
* subtree can stream out as it is produced.
|
|
846
|
-
*/
|
|
847
|
-
function renderControlChildrenToSink(node, sink, ctx) {
|
|
848
|
-
const controlState = getControlBoundaryState(node);
|
|
849
|
-
withControlBoundaryChildren(node, (children) => {
|
|
850
|
-
const values = children ?? [];
|
|
851
|
-
if (controlState?.kind === "for") {
|
|
852
|
-
for (let index = 0; index < values.length; index += 1) renderForRangeChildToSink(values[index], sink, ctx);
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
const spansRange = values.length !== 1 || isMultiRangeChild(values[0]);
|
|
856
|
-
if (spansRange) sink.write(RANGE_START);
|
|
857
|
-
renderChildrenSyncToSink(values, sink, ctx);
|
|
858
|
-
if (spansRange) sink.write(RANGE_END);
|
|
859
|
-
});
|
|
860
|
-
}
|
|
861
|
-
function renderErrorBoundaryFallbackValueToSink(fallback, error, reset, sink, ctx) {
|
|
862
|
-
const nextValue = resolveErrorBoundaryFallbackNode(fallback, error, reset);
|
|
863
|
-
if (Array.isArray(nextValue)) {
|
|
864
|
-
renderChildrenSyncToSink(normalizeRenderableChildren(nextValue), sink, ctx);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
renderChildSyncToSink(nextValue, sink, ctx);
|
|
868
|
-
}
|
|
869
|
-
function renderChildrenSyncToSink(children, sink, ctx) {
|
|
870
|
-
if (!children || !Array.isArray(children) || children.length === 0) return;
|
|
871
|
-
if (children.length >= 32) {
|
|
872
|
-
for (let i = 0; i < children.length; i++) renderRenderableSyncToSink(children[i], sink, ctx);
|
|
873
|
-
return;
|
|
874
|
-
}
|
|
875
|
-
for (let i = 0; i < children.length; i++) renderChildSyncToSink(children[i], sink, ctx);
|
|
876
|
-
}
|
|
877
|
-
function sinkWrite2(sink, a, b) {
|
|
878
|
-
if (typeof sink.write2 === "function") {
|
|
879
|
-
sink.write2(a, b);
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
sink.write(a);
|
|
883
|
-
sink.write(b);
|
|
884
|
-
}
|
|
885
|
-
function sinkWrite3(sink, a, b, c) {
|
|
886
|
-
if (typeof sink.write3 === "function") {
|
|
887
|
-
sink.write3(a, b, c);
|
|
888
|
-
return;
|
|
889
|
-
}
|
|
890
|
-
sink.write(a);
|
|
891
|
-
sink.write(b);
|
|
892
|
-
sink.write(c);
|
|
893
|
-
}
|
|
894
|
-
function renderNodeSyncToSink(node, sink, ctx) {
|
|
895
|
-
const { type, props } = node;
|
|
896
|
-
if (typeof type === "function") {
|
|
897
|
-
renderRenderableSyncToSink(inheritRenderableKey(node, executeComponentSync(type, props, ctx, getVNodeContextFrame(node) ?? null)), sink, ctx);
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
if (typeof type === "symbol") {
|
|
901
|
-
if (type === SSR_PORTAL_HOST) {
|
|
902
|
-
const token = String(props?.token ?? "");
|
|
903
|
-
const portalSink = sink;
|
|
904
|
-
if (portalSink.writePortalHost) portalSink.writePortalHost(token);
|
|
905
|
-
else sink.write(token);
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
if (type === SSR_PORTAL_ANCHOR) {
|
|
909
|
-
sink.write(String(props?.token ?? ""));
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
if (isFragmentType(type)) {
|
|
913
|
-
renderChildrenSyncToSink(getRenderableChildren(node), sink, ctx);
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
if (type === __CONTROL_BOUNDARY__) {
|
|
917
|
-
renderControlChildrenToSink(node, sink, ctx);
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
if (type === DEFERRED_BOUNDARY) {
|
|
921
|
-
renderDeferredBoundaryToSink(node, sink, ctx);
|
|
922
|
-
return;
|
|
923
|
-
}
|
|
924
|
-
if (type === __ERROR_BOUNDARY__) {
|
|
925
|
-
const boundaryState = getErrorBoundaryState(node);
|
|
926
|
-
const fallback = props?.fallback;
|
|
927
|
-
const reset = createErrorBoundaryReset(node);
|
|
928
|
-
if (boundaryState?.error != null) {
|
|
929
|
-
renderErrorBoundaryFallbackValueToSink(fallback, boundaryState.error, reset, sink, ctx);
|
|
930
|
-
return;
|
|
931
|
-
}
|
|
932
|
-
const protectedOutput = new BufferedSink();
|
|
933
|
-
try {
|
|
934
|
-
renderChildrenSyncToSink(normalizeRenderableChildren(props?.children), protectedOutput, ctx);
|
|
935
|
-
} catch (error) {
|
|
936
|
-
if (boundaryState) {
|
|
937
|
-
boundaryState.error = error;
|
|
938
|
-
boundaryState.notified = true;
|
|
939
|
-
}
|
|
940
|
-
logger.error("[Askr] ErrorBoundary caught render error:", error);
|
|
941
|
-
renderErrorBoundaryFallbackValueToSink(fallback, error, reset, sink, ctx);
|
|
942
|
-
return;
|
|
943
|
-
}
|
|
944
|
-
protectedOutput.publishTo(sink);
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
throw new Error(`renderNodeSyncToSink: unsupported VNode symbol type: ${String(type)}`);
|
|
948
|
-
}
|
|
949
|
-
const typeStr = type;
|
|
950
|
-
assertElementName(typeStr);
|
|
951
|
-
if (VOID_ELEMENTS.has(typeStr)) {
|
|
952
|
-
sinkWrite2(sink, "<", typeStr);
|
|
953
|
-
renderAttrsDirect(props, sink);
|
|
954
|
-
sink.write(" />");
|
|
955
|
-
return;
|
|
956
|
-
}
|
|
957
|
-
const maybeDangerous = props ? props?.dangerouslySetInnerHTML : void 0;
|
|
958
|
-
if (maybeDangerous !== void 0 && maybeDangerous !== null) {
|
|
959
|
-
const dangerousHtml = typeof maybeDangerous === "object" && "__html" in maybeDangerous ? String(maybeDangerous.__html) : void 0;
|
|
960
|
-
sinkWrite2(sink, "<", typeStr);
|
|
961
|
-
renderAttrsDirect(props, sink);
|
|
962
|
-
sink.write(">");
|
|
963
|
-
if (dangerousHtml !== void 0) sink.write(dangerousHtml);
|
|
964
|
-
else renderChildrenSyncToSink(getRenderableChildren(node), sink, ctx);
|
|
965
|
-
sinkWrite3(sink, "</", typeStr, ">");
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
const children = getRenderableChildren(node);
|
|
969
|
-
if (!children || Array.isArray(children) && children.length === 0) {
|
|
970
|
-
sinkWrite2(sink, "<", typeStr);
|
|
971
|
-
renderAttrsDirect(props, sink);
|
|
972
|
-
sink.write(">");
|
|
973
|
-
sinkWrite3(sink, "</", typeStr, ">");
|
|
974
|
-
return;
|
|
975
|
-
}
|
|
976
|
-
if (Array.isArray(children) && children.length === 1) {
|
|
977
|
-
const only = children[0];
|
|
978
|
-
if (typeof only === "string") {
|
|
979
|
-
const content = escapeText(only);
|
|
980
|
-
sinkWrite2(sink, "<", typeStr);
|
|
981
|
-
renderAttrsDirect(props, sink);
|
|
982
|
-
sink.write(">");
|
|
983
|
-
sink.write(content);
|
|
984
|
-
sinkWrite3(sink, "</", typeStr, ">");
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
if (typeof only === "number") {
|
|
988
|
-
const content = escapeText(String(only));
|
|
989
|
-
sinkWrite2(sink, "<", typeStr);
|
|
990
|
-
renderAttrsDirect(props, sink);
|
|
991
|
-
sink.write(">");
|
|
992
|
-
sink.write(content);
|
|
993
|
-
sinkWrite3(sink, "</", typeStr, ">");
|
|
994
|
-
return;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
sinkWrite2(sink, "<", typeStr);
|
|
998
|
-
renderAttrsDirect(props, sink);
|
|
999
|
-
sink.write(">");
|
|
1000
|
-
renderChildrenSyncToSink(children, sink, ctx);
|
|
1001
|
-
sinkWrite3(sink, "</", typeStr, ">");
|
|
1002
|
-
}
|
|
1003
|
-
/** Synchronously render a component to an HTML string, without route resolution. */
|
|
1004
|
-
function renderToStringSync(component, props, options) {
|
|
1005
|
-
const seed = options?.seed ?? 12345;
|
|
1006
|
-
const nonce = validateCspNonce(options?.cspNonce);
|
|
1007
|
-
const ctx = createRenderContext(seed, {
|
|
1008
|
-
data: options?.data,
|
|
1009
|
-
envelope: options?.envelope,
|
|
1010
|
-
cspNonce: nonce,
|
|
1011
|
-
authContext: options?.authContext
|
|
1012
|
-
});
|
|
1013
|
-
return withRenderContext(ctx, () => {
|
|
1014
|
-
startRenderPhase(ctx.renderData);
|
|
1015
|
-
try {
|
|
1016
|
-
const node = renderSyncComponentRoot(nonce === void 0 ? component : () => CspNonceScope({
|
|
1017
|
-
value: nonce,
|
|
1018
|
-
children: () => component(props)
|
|
1019
|
-
}), props || {}, ctx);
|
|
1020
|
-
if (!node) throw new Error("renderToStringSync: wrapped component returned empty");
|
|
1021
|
-
const sink = new StringSink();
|
|
1022
|
-
renderNodeSyncToSink(node, sink, ctx);
|
|
1023
|
-
sink.end();
|
|
1024
|
-
const html = resolveSSRPortals(sink.toString(), ctx);
|
|
1025
|
-
options?.onContext?.(ctx);
|
|
1026
|
-
return html + serializeHydrationRenderData(ctx.hydrationData ?? void 0, ctx.dataRuntime);
|
|
1027
|
-
} finally {
|
|
1028
|
-
try {
|
|
1029
|
-
stopRenderPhase();
|
|
1030
|
-
} finally {
|
|
1031
|
-
disposeSSRTemporaryOwners(ctx);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
function renderSSRRouteAppToSink(input) {
|
|
1037
|
-
const { ctx, data, route, params, sink } = input;
|
|
1038
|
-
withRenderContext(ctx, () => {
|
|
1039
|
-
startRenderPhase(ctx.renderData);
|
|
1040
|
-
try {
|
|
1041
|
-
const app = executeComponentSync(ctx.cspNonce === void 0 ? route.handler : () => CspNonceScope({
|
|
1042
|
-
value: ctx.cspNonce,
|
|
1043
|
-
children: () => route.handler(params)
|
|
1044
|
-
}), params, ctx);
|
|
1045
|
-
const appSink = new SSRPortalSink(sink);
|
|
1046
|
-
renderRenderableSyncToSink(wrapWithDefaultPortal(app), appSink, ctx);
|
|
1047
|
-
appSink.flush(ctx);
|
|
1048
|
-
if (ctx.deferredBoundaries.length === 0) sink.write(serializeHydrationRenderData(ctx.hydrationData ?? data, ctx.dataRuntime));
|
|
1049
|
-
} finally {
|
|
1050
|
-
try {
|
|
1051
|
-
stopRenderPhase();
|
|
1052
|
-
} finally {
|
|
1053
|
-
disposeSSRTemporaryOwners(ctx);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
function assertElementName(name) {
|
|
1059
|
-
if (!/^[A-Za-z][A-Za-z0-9._:-]*$/.test(name)) throw new TypeError(`Invalid SSR element name: ${JSON.stringify(name)}`);
|
|
1060
|
-
}
|
|
1061
|
-
//#endregion
|
|
1062
|
-
//#region src/ssr/render-resolved.ts
|
|
1063
|
-
function sameRouteParams(left, right) {
|
|
1064
|
-
if (!left || !right) return !left && !right;
|
|
1065
|
-
const leftKeys = Object.keys(left);
|
|
1066
|
-
const rightKeys = Object.keys(right);
|
|
1067
|
-
if (leftKeys.length !== rightKeys.length) return false;
|
|
1068
|
-
for (const key of leftKeys) if (left[key] !== right[key]) return false;
|
|
1069
|
-
return true;
|
|
1070
|
-
}
|
|
1071
|
-
/** Synchronously render an already-resolved route handler to an HTML string. */
|
|
1072
|
-
function renderResolvedToStringSync(opts) {
|
|
1073
|
-
return renderResolvedRouteToStringSync(opts);
|
|
1074
|
-
}
|
|
1075
|
-
function renderResolvedRouteToStringSync(opts, authContext) {
|
|
1076
|
-
const { url, registry, handler, params, options } = opts;
|
|
1077
|
-
const routes = registry.routes;
|
|
1078
|
-
const requestUrl = new URL(url, "http://localhost");
|
|
1079
|
-
const logicalTarget = removeRouteBasePath(`${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`, normalizeRouteBasePath(registry.manifest.basePath));
|
|
1080
|
-
const matchedIndex = routes.findIndex((route) => {
|
|
1081
|
-
if (logicalTarget === void 0) return false;
|
|
1082
|
-
const resolved = resolveRouteFromRoutes(new URL(logicalTarget, "http://localhost").pathname, [route]);
|
|
1083
|
-
return resolved !== null && resolved.handler === route.handler && sameRouteParams(resolved.params, params);
|
|
1084
|
-
});
|
|
1085
|
-
if (matchedIndex < 0) throw new Error(`renderResolvedToStringSync: no route found for url: ${url}`);
|
|
1086
|
-
const effectiveRoutes = routes.map((route, index) => index === matchedIndex ? {
|
|
1087
|
-
...route,
|
|
1088
|
-
handler
|
|
1089
|
-
} : route);
|
|
1090
|
-
const matchedRoute = routes[matchedIndex];
|
|
1091
|
-
const cspNonce = validateCspNonce(options?.cspNonce);
|
|
1092
|
-
const ctx = createRenderContext(options?.seed, {
|
|
1093
|
-
url,
|
|
1094
|
-
basePath: registry.manifest.basePath,
|
|
1095
|
-
data: options?.data,
|
|
1096
|
-
params,
|
|
1097
|
-
routes: effectiveRoutes,
|
|
1098
|
-
routeAuth: registry.manifest.auth,
|
|
1099
|
-
authContext,
|
|
1100
|
-
dataRuntime: options?.dataRuntime,
|
|
1101
|
-
envelope: options?.envelope,
|
|
1102
|
-
cspNonce
|
|
1103
|
-
});
|
|
1104
|
-
const sink = new StringSink();
|
|
1105
|
-
renderSSRRouteAppToSink({
|
|
1106
|
-
route: {
|
|
1107
|
-
...matchedRoute,
|
|
1108
|
-
handler
|
|
1109
|
-
},
|
|
1110
|
-
params: params ?? {},
|
|
1111
|
-
data: options?.data,
|
|
1112
|
-
ctx,
|
|
1113
|
-
sink
|
|
1114
|
-
});
|
|
1115
|
-
sink.end();
|
|
1116
|
-
return sink.toString();
|
|
1117
|
-
}
|
|
1118
|
-
/** @internal Render the resolved hydration route with its request-local auth context. */
|
|
1119
|
-
function renderResolvedForHydrationSync(opts, authContext) {
|
|
1120
|
-
return renderResolvedRouteToStringSync(opts, authContext);
|
|
1121
|
-
}
|
|
1122
|
-
//#endregion
|
|
1123
|
-
export { serializeHydrationRenderData as a, createRenderContext as c, withRenderContext as d, withRenderContextAsync as f, renderToStringSync as i, getRenderContext as l, renderResolvedToStringSync as n, StreamSink as o, renderSSRRouteAppToSink as r, StringSink as s, renderResolvedForHydrationSync as t, throwSSRDataMissing as u };
|