sinwan 0.1.0 → 1.1.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 +66 -39
- package/dist/cjs/index.development.js +2373 -842
- package/dist/cjs/index.development.js.map +22 -18
- package/dist/cjs/index.production.min.js +2 -2
- package/dist/cjs/index.production.min.js.map +22 -18
- package/dist/cjs/jsx/jsx-dev-runtime.development.js +6 -16
- package/dist/cjs/jsx/jsx-dev-runtime.development.js.map +3 -3
- package/dist/cjs/jsx/jsx-dev-runtime.production.min.js +2 -2
- package/dist/cjs/jsx/jsx-dev-runtime.production.min.js.map +3 -3
- package/dist/cjs/jsx/jsx-runtime.development.js +6 -16
- package/dist/cjs/jsx/jsx-runtime.development.js.map +3 -3
- package/dist/cjs/jsx/jsx-runtime.production.min.js +2 -2
- package/dist/cjs/jsx/jsx-runtime.production.min.js.map +3 -3
- package/dist/cjs/renderer/index.development.js +1581 -0
- package/dist/cjs/renderer/index.development.js.map +25 -0
- package/dist/cjs/renderer/index.production.min.js +3 -0
- package/dist/cjs/renderer/index.production.min.js.map +25 -0
- package/dist/cjs/server/index.development.js +1210 -362
- package/dist/cjs/server/index.development.js.map +13 -10
- package/dist/cjs/server/index.production.min.js +2 -2
- package/dist/cjs/server/index.production.min.js.map +13 -10
- package/dist/component/control-flow.d.ts +71 -0
- package/dist/component/control-flow.d.ts.map +1 -0
- package/dist/component/index.d.ts +3 -1
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/instance.d.ts +7 -1
- package/dist/component/instance.d.ts.map +1 -1
- package/dist/component/lifecycle.d.ts +2 -1
- package/dist/component/lifecycle.d.ts.map +1 -1
- package/dist/component/provide-inject.d.ts +11 -5
- package/dist/component/provide-inject.d.ts.map +1 -1
- package/dist/esm/index.development.js +2253 -744
- package/dist/esm/index.development.js.map +22 -18
- package/dist/esm/index.production.min.js +2 -2
- package/dist/esm/index.production.min.js.map +22 -18
- package/dist/esm/jsx/jsx-dev-runtime.development.js +6 -16
- package/dist/esm/jsx/jsx-dev-runtime.development.js.map +3 -3
- package/dist/esm/jsx/jsx-dev-runtime.production.min.js +2 -2
- package/dist/esm/jsx/jsx-dev-runtime.production.min.js.map +3 -3
- package/dist/esm/jsx/jsx-runtime.development.js +6 -16
- package/dist/esm/jsx/jsx-runtime.development.js.map +3 -3
- package/dist/esm/jsx/jsx-runtime.production.min.js +2 -2
- package/dist/esm/jsx/jsx-runtime.production.min.js.map +3 -3
- package/dist/esm/renderer/index.development.js +1530 -0
- package/dist/esm/renderer/index.development.js.map +25 -0
- package/dist/esm/renderer/index.production.min.js +4 -0
- package/dist/esm/renderer/index.production.min.js.map +25 -0
- package/dist/esm/server/index.development.js +1210 -362
- package/dist/esm/server/index.development.js.map +13 -10
- package/dist/esm/server/index.production.min.js +2 -2
- package/dist/esm/server/index.production.min.js.map +13 -10
- package/dist/hydration/walk.d.ts.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/jsx/jsx-runtime.d.ts +13 -0
- package/dist/jsx/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx/jsx-types.d.ts +122 -57
- package/dist/jsx/jsx-types.d.ts.map +1 -1
- package/dist/renderer/attributes.d.ts +11 -0
- package/dist/renderer/attributes.d.ts.map +1 -1
- package/dist/renderer/dom-ops.d.ts +4 -1
- package/dist/renderer/dom-ops.d.ts.map +1 -1
- package/dist/renderer/index.d.ts +2 -2
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/mount.d.ts +2 -5
- package/dist/renderer/mount.d.ts.map +1 -1
- package/dist/renderer/render-children.d.ts +2 -2
- package/dist/renderer/render-children.d.ts.map +1 -1
- package/dist/renderer/render-control-flow.d.ts +13 -0
- package/dist/renderer/render-control-flow.d.ts.map +1 -0
- package/dist/renderer/render-element.d.ts +1 -1
- package/dist/renderer/render-element.d.ts.map +1 -1
- package/dist/renderer/types.d.ts +10 -1
- package/dist/renderer/types.d.ts.map +1 -1
- package/dist/renderer/unmount.d.ts +20 -0
- package/dist/renderer/unmount.d.ts.map +1 -0
- package/dist/renderer.d.ts +1 -0
- package/dist/renderer.js +7 -0
- package/dist/renderer.mjs +4 -0
- package/dist/server/attribute-utils.d.ts +2 -0
- package/dist/server/attribute-utils.d.ts.map +1 -0
- package/dist/server/hydration-markers.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/renderer.d.ts.map +1 -1
- package/dist/server/stream.d.ts +9 -1
- package/dist/server/stream.d.ts.map +1 -1
- package/dist/types.d.ts +8 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -5
|
@@ -40,22 +40,12 @@ function buildElement(type, props, children) {
|
|
|
40
40
|
if (type === Fragment) {
|
|
41
41
|
return { tag: "", props: {}, children };
|
|
42
42
|
}
|
|
43
|
-
if (typeof type === "function") {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return result2;
|
|
48
|
-
}
|
|
49
|
-
return { tag: "", props: {}, children: normalizeChildren(result2) };
|
|
50
|
-
}
|
|
51
|
-
const result = type(props);
|
|
52
|
-
if (result && typeof result === "object" && "tag" in result) {
|
|
53
|
-
return result;
|
|
43
|
+
if (typeof type === "function" || typeof type === "string") {
|
|
44
|
+
const finalProps = props ?? {};
|
|
45
|
+
if (children.length > 0 && finalProps.children === undefined) {
|
|
46
|
+
finalProps.children = children.length === 1 ? children[0] : children;
|
|
54
47
|
}
|
|
55
|
-
return { tag:
|
|
56
|
-
}
|
|
57
|
-
if (typeof type === "string") {
|
|
58
|
-
return { tag: type, props: props || {}, children };
|
|
48
|
+
return { tag: type, props: finalProps, children };
|
|
59
49
|
}
|
|
60
50
|
return { tag: "", props: {}, children };
|
|
61
51
|
}
|
|
@@ -109,221 +99,37 @@ function isSafeHtml(value) {
|
|
|
109
99
|
return value instanceof HtmlEscapedString;
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
// src/server/
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return pageRegistry.has(name);
|
|
123
|
-
}
|
|
124
|
-
async function renderPage(name, data) {
|
|
125
|
-
const page = getPage(name);
|
|
126
|
-
if (!page) {
|
|
127
|
-
throw new Error(`Page "${name}" not found in registry`);
|
|
128
|
-
}
|
|
129
|
-
const element = await page(data);
|
|
130
|
-
return renderToString(element);
|
|
131
|
-
}
|
|
132
|
-
async function renderToString(node) {
|
|
133
|
-
if (node == null || typeof node === "boolean") {
|
|
102
|
+
// src/server/attribute-utils.ts
|
|
103
|
+
var PROP_ALIASES = {
|
|
104
|
+
className: "class",
|
|
105
|
+
htmlFor: "for",
|
|
106
|
+
tabIndex: "tabindex",
|
|
107
|
+
crossOrigin: "crossorigin"
|
|
108
|
+
};
|
|
109
|
+
function renderServerAttribute(key, value) {
|
|
110
|
+
const attrName = PROP_ALIASES[key] ?? key;
|
|
111
|
+
if (value == null || value === false) {
|
|
134
112
|
return "";
|
|
135
113
|
}
|
|
136
|
-
if (
|
|
137
|
-
return
|
|
138
|
-
}
|
|
139
|
-
if (typeof node === "number") {
|
|
140
|
-
return String(node);
|
|
141
|
-
}
|
|
142
|
-
if (node instanceof HtmlEscapedString) {
|
|
143
|
-
return node.value;
|
|
144
|
-
}
|
|
145
|
-
if (Array.isArray(node)) {
|
|
146
|
-
const results = await Promise.all(node.map((child) => renderToString(child)));
|
|
147
|
-
return results.join("");
|
|
148
|
-
}
|
|
149
|
-
if (node instanceof Promise) {
|
|
150
|
-
return renderElement(await node);
|
|
151
|
-
}
|
|
152
|
-
return renderElement(node);
|
|
153
|
-
}
|
|
154
|
-
async function renderElement(element) {
|
|
155
|
-
const { tag, props, children } = element;
|
|
156
|
-
if (typeof tag === "function") {
|
|
157
|
-
const result = await tag(props);
|
|
158
|
-
return renderToString(result);
|
|
159
|
-
}
|
|
160
|
-
if (typeof tag === "string") {
|
|
161
|
-
return renderIntrinsicElement(tag, props, children);
|
|
162
|
-
}
|
|
163
|
-
return renderToString(children);
|
|
164
|
-
}
|
|
165
|
-
var VOID_ELEMENTS2 = new Set([
|
|
166
|
-
"area",
|
|
167
|
-
"base",
|
|
168
|
-
"br",
|
|
169
|
-
"col",
|
|
170
|
-
"embed",
|
|
171
|
-
"hr",
|
|
172
|
-
"img",
|
|
173
|
-
"input",
|
|
174
|
-
"link",
|
|
175
|
-
"meta",
|
|
176
|
-
"param",
|
|
177
|
-
"source",
|
|
178
|
-
"track",
|
|
179
|
-
"wbr"
|
|
180
|
-
]);
|
|
181
|
-
async function renderIntrinsicElement(tag, props, children) {
|
|
182
|
-
const attrs = renderAttributes(props);
|
|
183
|
-
if (VOID_ELEMENTS2.has(tag)) {
|
|
184
|
-
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
185
|
-
}
|
|
186
|
-
const childrenHtml = await renderChildren(children, props);
|
|
187
|
-
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
188
|
-
}
|
|
189
|
-
function renderAttributes(props) {
|
|
190
|
-
let attrs = "";
|
|
191
|
-
for (const [key, value] of Object.entries(props)) {
|
|
192
|
-
if (key === "children")
|
|
193
|
-
continue;
|
|
194
|
-
if (value == null || value === false)
|
|
195
|
-
continue;
|
|
196
|
-
if (value === true) {
|
|
197
|
-
attrs += ` ${key}`;
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
if (key === "dangerouslySetInnerHTML") {
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
const attrName = key === "className" ? "class" : key;
|
|
204
|
-
const finalName = attrName === "htmlFor" ? "for" : attrName;
|
|
205
|
-
const attrValue = escapeHtml(String(value));
|
|
206
|
-
attrs += ` ${finalName}="${attrValue}"`;
|
|
207
|
-
}
|
|
208
|
-
return attrs;
|
|
209
|
-
}
|
|
210
|
-
async function renderChildren(children, props) {
|
|
211
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
212
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
213
|
-
return dangerous.__html;
|
|
214
|
-
}
|
|
215
|
-
return renderToString(children);
|
|
216
|
-
}
|
|
217
|
-
function isSlots(children) {
|
|
218
|
-
return children != null && typeof children === "object" && !Array.isArray(children) && !(children instanceof HtmlEscapedString);
|
|
219
|
-
}
|
|
220
|
-
// src/server/stream.ts
|
|
221
|
-
var VOID_ELEMENTS3 = new Set([
|
|
222
|
-
"area",
|
|
223
|
-
"base",
|
|
224
|
-
"br",
|
|
225
|
-
"col",
|
|
226
|
-
"embed",
|
|
227
|
-
"hr",
|
|
228
|
-
"img",
|
|
229
|
-
"input",
|
|
230
|
-
"link",
|
|
231
|
-
"meta",
|
|
232
|
-
"param",
|
|
233
|
-
"source",
|
|
234
|
-
"track",
|
|
235
|
-
"wbr"
|
|
236
|
-
]);
|
|
237
|
-
function streamPage(page, data) {
|
|
238
|
-
const encoder = new TextEncoder;
|
|
239
|
-
return new ReadableStream({
|
|
240
|
-
async start(controller) {
|
|
241
|
-
try {
|
|
242
|
-
const element = await page(data);
|
|
243
|
-
await streamNode(element, controller, encoder);
|
|
244
|
-
controller.close();
|
|
245
|
-
} catch (error) {
|
|
246
|
-
controller.error(error);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
async function streamNode(node, controller, encoder) {
|
|
252
|
-
if (node == null || typeof node === "boolean") {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (typeof node === "string") {
|
|
256
|
-
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
if (typeof node === "number") {
|
|
260
|
-
controller.enqueue(encoder.encode(String(node)));
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (node instanceof HtmlEscapedString) {
|
|
264
|
-
controller.enqueue(encoder.encode(node.value));
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
if (Array.isArray(node)) {
|
|
268
|
-
for (const child of node) {
|
|
269
|
-
await streamNode(child, controller, encoder);
|
|
270
|
-
}
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
if (node instanceof Promise) {
|
|
274
|
-
const resolved = await node;
|
|
275
|
-
await streamElement(resolved, controller, encoder);
|
|
276
|
-
return;
|
|
114
|
+
if (value === true) {
|
|
115
|
+
return ` ${attrName}`;
|
|
277
116
|
}
|
|
278
|
-
|
|
117
|
+
const attrValue = attrName === "class" && typeof value === "object" ? stringifyClass(value) : attrName === "style" && typeof value === "object" ? stringifyStyle(value) : String(value);
|
|
118
|
+
return ` ${attrName}="${escapeHtml(attrValue)}"`;
|
|
279
119
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const result = await tag(props);
|
|
284
|
-
await streamNode(result, controller, encoder);
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
if (typeof tag === "string") {
|
|
288
|
-
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
289
|
-
return;
|
|
120
|
+
function stringifyClass(value) {
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
return value.filter(Boolean).join(" ");
|
|
290
123
|
}
|
|
291
|
-
|
|
124
|
+
return Object.entries(value).filter(([, enabled]) => Boolean(enabled)).map(([name]) => name).join(" ");
|
|
292
125
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const dangerous = props.dangerouslySetInnerHTML;
|
|
296
|
-
if (VOID_ELEMENTS3.has(tag)) {
|
|
297
|
-
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
298
|
-
controller.enqueue(encoder.encode(html));
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
302
|
-
controller.enqueue(encoder.encode(openTag));
|
|
303
|
-
if (dangerous && typeof dangerous.__html === "string") {
|
|
304
|
-
controller.enqueue(encoder.encode(dangerous.__html));
|
|
305
|
-
} else {
|
|
306
|
-
await streamNode(children, controller, encoder);
|
|
307
|
-
}
|
|
308
|
-
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
126
|
+
function stringifyStyle(value) {
|
|
127
|
+
return Object.entries(value).filter(([, val]) => val != null && val !== false).map(([prop, val]) => `${toKebabCase(prop)}:${String(val)}`).join(";");
|
|
309
128
|
}
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
for (const [key, value] of Object.entries(props)) {
|
|
313
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
314
|
-
continue;
|
|
315
|
-
if (value == null || value === false)
|
|
316
|
-
continue;
|
|
317
|
-
if (value === true) {
|
|
318
|
-
attrs += ` ${key}`;
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
322
|
-
const attrValue = escapeHtml(String(value));
|
|
323
|
-
attrs += ` ${attrName}="${attrValue}"`;
|
|
324
|
-
}
|
|
325
|
-
return attrs;
|
|
129
|
+
function toKebabCase(value) {
|
|
130
|
+
return value.includes("-") ? value : value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
|
|
326
131
|
}
|
|
132
|
+
|
|
327
133
|
// src/reactivity/scheduler.ts
|
|
328
134
|
var pendingEffects = new Set;
|
|
329
135
|
var flushScheduled = false;
|
|
@@ -566,79 +372,68 @@ function isComputed(value) {
|
|
|
566
372
|
return value != null && typeof value === "object" && COMPUTED_BRAND in value;
|
|
567
373
|
}
|
|
568
374
|
|
|
569
|
-
// src/
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
|
|
375
|
+
// src/renderer/dom-ops.ts
|
|
376
|
+
function createDefaultDOMOps() {
|
|
377
|
+
return {
|
|
378
|
+
createElement(tag) {
|
|
379
|
+
return document.createElement(tag);
|
|
380
|
+
},
|
|
381
|
+
createElementNS(namespace, tag) {
|
|
382
|
+
return document.createElementNS(namespace, tag);
|
|
383
|
+
},
|
|
384
|
+
createTextNode(text) {
|
|
385
|
+
return document.createTextNode(text);
|
|
386
|
+
},
|
|
387
|
+
createComment(text) {
|
|
388
|
+
return document.createComment(text);
|
|
389
|
+
},
|
|
390
|
+
setAttribute(el, key, value) {
|
|
391
|
+
el.setAttribute(key, value);
|
|
392
|
+
},
|
|
393
|
+
removeAttribute(el, key) {
|
|
394
|
+
el.removeAttribute(key);
|
|
395
|
+
},
|
|
396
|
+
setProperty(el, key, value) {
|
|
397
|
+
el[key] = value;
|
|
398
|
+
},
|
|
399
|
+
insertBefore(parent, child, anchor) {
|
|
400
|
+
parent.insertBefore(child, anchor);
|
|
401
|
+
},
|
|
402
|
+
appendChild(parent, child) {
|
|
403
|
+
parent.appendChild(child);
|
|
404
|
+
},
|
|
405
|
+
remove(node) {
|
|
406
|
+
node.parentNode?.removeChild(node);
|
|
407
|
+
},
|
|
408
|
+
setTextContent(node, text) {
|
|
409
|
+
node.data = text;
|
|
410
|
+
},
|
|
411
|
+
addEventListener(el, event, handler) {
|
|
412
|
+
el.addEventListener(event, handler);
|
|
413
|
+
},
|
|
414
|
+
removeEventListener(el, event, handler) {
|
|
415
|
+
el.removeEventListener(event, handler);
|
|
416
|
+
},
|
|
417
|
+
parentNode(node) {
|
|
418
|
+
return node.parentNode;
|
|
419
|
+
},
|
|
420
|
+
nextSibling(node) {
|
|
421
|
+
return node.nextSibling;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
580
424
|
}
|
|
581
|
-
|
|
582
|
-
|
|
425
|
+
var defaultDOMOps = createDefaultDOMOps();
|
|
426
|
+
var domOps = { ...defaultDOMOps };
|
|
427
|
+
function setDOMOps(overrides) {
|
|
428
|
+
Object.assign(domOps, overrides);
|
|
583
429
|
}
|
|
584
|
-
function
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
588
|
-
return Number.isNaN(idx) ? -1 : idx;
|
|
430
|
+
function resetDOMOps() {
|
|
431
|
+
for (const key of Object.keys(domOps)) {
|
|
432
|
+
delete domOps[key];
|
|
589
433
|
}
|
|
590
|
-
|
|
591
|
-
}
|
|
592
|
-
function isTextCloseMarker(node) {
|
|
593
|
-
return node.data === TEXT_MARKER_CLOSE;
|
|
434
|
+
Object.assign(domOps, defaultDOMOps);
|
|
594
435
|
}
|
|
595
436
|
|
|
596
|
-
// src/renderer/dom-ops.ts
|
|
597
|
-
var domOps = {
|
|
598
|
-
createElement(tag) {
|
|
599
|
-
return document.createElement(tag);
|
|
600
|
-
},
|
|
601
|
-
createTextNode(text) {
|
|
602
|
-
return document.createTextNode(text);
|
|
603
|
-
},
|
|
604
|
-
createComment(text) {
|
|
605
|
-
return document.createComment(text);
|
|
606
|
-
},
|
|
607
|
-
setAttribute(el, key, value) {
|
|
608
|
-
el.setAttribute(key, value);
|
|
609
|
-
},
|
|
610
|
-
removeAttribute(el, key) {
|
|
611
|
-
el.removeAttribute(key);
|
|
612
|
-
},
|
|
613
|
-
setProperty(el, key, value) {
|
|
614
|
-
el[key] = value;
|
|
615
|
-
},
|
|
616
|
-
insertBefore(parent, child, anchor) {
|
|
617
|
-
parent.insertBefore(child, anchor);
|
|
618
|
-
},
|
|
619
|
-
appendChild(parent, child) {
|
|
620
|
-
parent.appendChild(child);
|
|
621
|
-
},
|
|
622
|
-
remove(node) {
|
|
623
|
-
node.parentNode?.removeChild(node);
|
|
624
|
-
},
|
|
625
|
-
setTextContent(node, text) {
|
|
626
|
-
node.data = text;
|
|
627
|
-
},
|
|
628
|
-
addEventListener(el, event, handler) {
|
|
629
|
-
el.addEventListener(event, handler);
|
|
630
|
-
},
|
|
631
|
-
removeEventListener(el, event, handler) {
|
|
632
|
-
el.removeEventListener(event, handler);
|
|
633
|
-
},
|
|
634
|
-
parentNode(node) {
|
|
635
|
-
return node.parentNode;
|
|
636
|
-
},
|
|
637
|
-
nextSibling(node) {
|
|
638
|
-
return node.nextSibling;
|
|
639
|
-
}
|
|
640
|
-
};
|
|
641
|
-
|
|
642
437
|
// src/renderer/events.ts
|
|
643
438
|
function isEventProp(key) {
|
|
644
439
|
return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
|
|
@@ -665,77 +460,991 @@ function bindEvents(el, props) {
|
|
|
665
460
|
}
|
|
666
461
|
return cleanups;
|
|
667
462
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
463
|
+
// src/reactivity/batch.ts
|
|
464
|
+
var batchDepth = 0;
|
|
465
|
+
function batch(fn) {
|
|
466
|
+
batchDepth++;
|
|
467
|
+
try {
|
|
468
|
+
fn();
|
|
469
|
+
} finally {
|
|
470
|
+
batchDepth--;
|
|
471
|
+
if (batchDepth === 0) {
|
|
472
|
+
flushSync();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// src/component/control-flow.ts
|
|
477
|
+
var SHOW_TYPE = Symbol.for("Sinwan.Show");
|
|
478
|
+
var FOR_TYPE = Symbol.for("Sinwan.For");
|
|
479
|
+
var SWITCH_TYPE = Symbol.for("Sinwan.Switch");
|
|
480
|
+
var MATCH_TYPE = Symbol.for("Sinwan.Match");
|
|
481
|
+
var INDEX_TYPE = Symbol.for("Sinwan.Index");
|
|
482
|
+
var KEY_TYPE = Symbol.for("Sinwan.Key");
|
|
483
|
+
var DYNAMIC_TYPE = Symbol.for("Sinwan.Dynamic");
|
|
484
|
+
var PORTAL_TYPE = Symbol.for("Sinwan.Portal");
|
|
485
|
+
function Show(props) {
|
|
672
486
|
return {
|
|
673
|
-
|
|
674
|
-
component,
|
|
487
|
+
tag: SHOW_TYPE,
|
|
675
488
|
props,
|
|
676
|
-
|
|
677
|
-
parent,
|
|
678
|
-
children: [],
|
|
679
|
-
effects: [],
|
|
680
|
-
_mountedHooks: [],
|
|
681
|
-
_unmountedHooks: [],
|
|
682
|
-
_updatedHooks: [],
|
|
683
|
-
_errorHooks: [],
|
|
684
|
-
provides: parent ? Object.create(parent.provides) : Object.create(null),
|
|
685
|
-
isMounted: false,
|
|
686
|
-
isUnmounted: false
|
|
489
|
+
children: []
|
|
687
490
|
};
|
|
688
491
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
492
|
+
function For(props) {
|
|
493
|
+
return {
|
|
494
|
+
tag: FOR_TYPE,
|
|
495
|
+
props,
|
|
496
|
+
children: []
|
|
497
|
+
};
|
|
692
498
|
}
|
|
693
|
-
function
|
|
499
|
+
function Switch(props) {
|
|
500
|
+
return {
|
|
501
|
+
tag: SWITCH_TYPE,
|
|
502
|
+
props,
|
|
503
|
+
children: []
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function Match(props) {
|
|
507
|
+
return {
|
|
508
|
+
tag: MATCH_TYPE,
|
|
509
|
+
props,
|
|
510
|
+
children: []
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function Index(props) {
|
|
514
|
+
return {
|
|
515
|
+
tag: INDEX_TYPE,
|
|
516
|
+
props,
|
|
517
|
+
children: []
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function Key(props) {
|
|
521
|
+
return {
|
|
522
|
+
tag: KEY_TYPE,
|
|
523
|
+
props,
|
|
524
|
+
children: []
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function Dynamic(props) {
|
|
528
|
+
return {
|
|
529
|
+
tag: DYNAMIC_TYPE,
|
|
530
|
+
props,
|
|
531
|
+
children: []
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function Visible(props) {
|
|
535
|
+
const {
|
|
536
|
+
when,
|
|
537
|
+
as = "span",
|
|
538
|
+
style,
|
|
539
|
+
children,
|
|
540
|
+
...rest
|
|
541
|
+
} = props;
|
|
542
|
+
const visibleStyle = computed(() => {
|
|
543
|
+
const base = readReactive(style);
|
|
544
|
+
const visible = Boolean(readReactive(when));
|
|
545
|
+
if (typeof base === "string") {
|
|
546
|
+
return visible ? base : appendHiddenDisplay(base);
|
|
547
|
+
}
|
|
548
|
+
const styleObject = base && typeof base === "object" ? { ...base } : {};
|
|
549
|
+
styleObject.display = visible ? styleObject.display : "none";
|
|
550
|
+
return styleObject;
|
|
551
|
+
});
|
|
552
|
+
return {
|
|
553
|
+
tag: as,
|
|
554
|
+
props: {
|
|
555
|
+
...rest,
|
|
556
|
+
style: visibleStyle,
|
|
557
|
+
children
|
|
558
|
+
},
|
|
559
|
+
children: normalizeChildren2(children)
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
function Portal(props) {
|
|
563
|
+
return {
|
|
564
|
+
tag: PORTAL_TYPE,
|
|
565
|
+
props,
|
|
566
|
+
children: []
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
function isShowElement(element) {
|
|
570
|
+
return element.tag === SHOW_TYPE;
|
|
571
|
+
}
|
|
572
|
+
function isForElement(element) {
|
|
573
|
+
return element.tag === FOR_TYPE;
|
|
574
|
+
}
|
|
575
|
+
function isSwitchElement(element) {
|
|
576
|
+
return element.tag === SWITCH_TYPE;
|
|
577
|
+
}
|
|
578
|
+
function isMatchElement(element) {
|
|
579
|
+
return element.tag === MATCH_TYPE;
|
|
580
|
+
}
|
|
581
|
+
function isIndexElement(element) {
|
|
582
|
+
return element.tag === INDEX_TYPE;
|
|
583
|
+
}
|
|
584
|
+
function isKeyElement(element) {
|
|
585
|
+
return element.tag === KEY_TYPE;
|
|
586
|
+
}
|
|
587
|
+
function isDynamicElement(element) {
|
|
588
|
+
return element.tag === DYNAMIC_TYPE;
|
|
589
|
+
}
|
|
590
|
+
function isPortalElement(element) {
|
|
591
|
+
return element.tag === PORTAL_TYPE;
|
|
592
|
+
}
|
|
593
|
+
function normalizeChildren2(children) {
|
|
594
|
+
if (children == null || typeof children === "boolean") {
|
|
595
|
+
return [];
|
|
596
|
+
}
|
|
597
|
+
return Array.isArray(children) ? children : [children];
|
|
598
|
+
}
|
|
599
|
+
function readReactive(value) {
|
|
600
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
601
|
+
}
|
|
602
|
+
function appendHiddenDisplay(style) {
|
|
603
|
+
const trimmed = style.trim();
|
|
604
|
+
const separator = trimmed.length > 0 && !trimmed.endsWith(";") ? ";" : "";
|
|
605
|
+
return `${trimmed}${separator}display:none`;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// src/server/renderer.ts
|
|
609
|
+
var componentCache = new WeakMap;
|
|
610
|
+
var pageRegistry = new Map;
|
|
611
|
+
function registerPage(name, page) {
|
|
612
|
+
pageRegistry.set(name, page);
|
|
613
|
+
}
|
|
614
|
+
function getPage(name) {
|
|
615
|
+
return pageRegistry.get(name);
|
|
616
|
+
}
|
|
617
|
+
function hasPage(name) {
|
|
618
|
+
return pageRegistry.has(name);
|
|
619
|
+
}
|
|
620
|
+
async function renderPage(name, data) {
|
|
621
|
+
const page = getPage(name);
|
|
622
|
+
if (!page) {
|
|
623
|
+
throw new Error(`Page "${name}" not found in registry`);
|
|
624
|
+
}
|
|
625
|
+
const element = await page(data);
|
|
626
|
+
return renderToString(element);
|
|
627
|
+
}
|
|
628
|
+
async function renderToString(node) {
|
|
629
|
+
if (node == null || typeof node === "boolean") {
|
|
630
|
+
return "";
|
|
631
|
+
}
|
|
632
|
+
if (typeof node === "string") {
|
|
633
|
+
return escapeHtml(node);
|
|
634
|
+
}
|
|
635
|
+
if (typeof node === "number") {
|
|
636
|
+
return String(node);
|
|
637
|
+
}
|
|
638
|
+
if (node instanceof HtmlEscapedString) {
|
|
639
|
+
return node.value;
|
|
640
|
+
}
|
|
641
|
+
if (isSignal(node) || isComputed(node)) {
|
|
642
|
+
return escapeHtml(String(node.value));
|
|
643
|
+
}
|
|
644
|
+
if (Array.isArray(node)) {
|
|
645
|
+
const results = await Promise.all(node.map((child) => renderToString(child)));
|
|
646
|
+
return results.join("");
|
|
647
|
+
}
|
|
648
|
+
if (node instanceof Promise) {
|
|
649
|
+
return renderElement(await node);
|
|
650
|
+
}
|
|
651
|
+
return renderElement(node);
|
|
652
|
+
}
|
|
653
|
+
async function renderElement(element) {
|
|
654
|
+
const { tag, props, children } = element;
|
|
655
|
+
if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
|
|
656
|
+
return renderElement(tag(props));
|
|
657
|
+
}
|
|
658
|
+
if (tag === Visible) {
|
|
659
|
+
return renderElement(tag(props));
|
|
660
|
+
}
|
|
661
|
+
if (isShowElement(element)) {
|
|
662
|
+
const when = readReactive2(props.when);
|
|
663
|
+
return renderToString(when ? resolveShowChildren(element, when) : props.fallback);
|
|
664
|
+
}
|
|
665
|
+
if (isForElement(element)) {
|
|
666
|
+
return renderForElement(element);
|
|
667
|
+
}
|
|
668
|
+
if (isSwitchElement(element)) {
|
|
669
|
+
return renderToString(resolveSwitchContent(element));
|
|
670
|
+
}
|
|
671
|
+
if (isMatchElement(element)) {
|
|
672
|
+
const when = readReactive2(props.when);
|
|
673
|
+
return renderToString(when ? resolveMatchChildren(element, when) : null);
|
|
674
|
+
}
|
|
675
|
+
if (isIndexElement(element)) {
|
|
676
|
+
return renderIndexElement(element);
|
|
677
|
+
}
|
|
678
|
+
if (isKeyElement(element)) {
|
|
679
|
+
const key = readReactive2(props.when);
|
|
680
|
+
return renderToString(resolveKeyChildren(element, key));
|
|
681
|
+
}
|
|
682
|
+
if (isDynamicElement(element)) {
|
|
683
|
+
const tag2 = readReactive2(props.component);
|
|
684
|
+
const dynamic = createDynamicElement(element, tag2);
|
|
685
|
+
return dynamic ? renderElement(dynamic) : "";
|
|
686
|
+
}
|
|
687
|
+
if (isPortalElement(element)) {
|
|
688
|
+
return "";
|
|
689
|
+
}
|
|
690
|
+
if (typeof tag === "function") {
|
|
691
|
+
const result = await tag(props);
|
|
692
|
+
return renderToString(result);
|
|
693
|
+
}
|
|
694
|
+
if (typeof tag === "string") {
|
|
695
|
+
return renderIntrinsicElement(tag, props, children);
|
|
696
|
+
}
|
|
697
|
+
return renderToString(children);
|
|
698
|
+
}
|
|
699
|
+
var VOID_ELEMENTS2 = new Set([
|
|
700
|
+
"area",
|
|
701
|
+
"base",
|
|
702
|
+
"br",
|
|
703
|
+
"col",
|
|
704
|
+
"embed",
|
|
705
|
+
"hr",
|
|
706
|
+
"img",
|
|
707
|
+
"input",
|
|
708
|
+
"link",
|
|
709
|
+
"meta",
|
|
710
|
+
"param",
|
|
711
|
+
"source",
|
|
712
|
+
"track",
|
|
713
|
+
"wbr"
|
|
714
|
+
]);
|
|
715
|
+
async function renderIntrinsicElement(tag, props, children) {
|
|
716
|
+
const attrs = renderAttributes(props);
|
|
717
|
+
if (VOID_ELEMENTS2.has(tag)) {
|
|
718
|
+
return attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
719
|
+
}
|
|
720
|
+
const childrenHtml = await renderChildren(children, props);
|
|
721
|
+
return attrs ? `<${tag}${attrs}>${childrenHtml}</${tag}>` : `<${tag}>${childrenHtml}</${tag}>`;
|
|
722
|
+
}
|
|
723
|
+
function renderAttributes(props) {
|
|
724
|
+
let attrs = "";
|
|
725
|
+
for (const [key, value] of Object.entries(props)) {
|
|
726
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
const resolvedValue = readReactive2(value);
|
|
730
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
731
|
+
continue;
|
|
732
|
+
attrs += renderServerAttribute(key, resolvedValue);
|
|
733
|
+
}
|
|
734
|
+
return attrs;
|
|
735
|
+
}
|
|
736
|
+
async function renderChildren(children, props) {
|
|
737
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
738
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
739
|
+
return dangerous.__html;
|
|
740
|
+
}
|
|
741
|
+
return renderToString(children);
|
|
742
|
+
}
|
|
743
|
+
function isSlots(children) {
|
|
744
|
+
return children != null && typeof children === "object" && !Array.isArray(children) && !(children instanceof HtmlEscapedString);
|
|
745
|
+
}
|
|
746
|
+
async function renderForElement(element) {
|
|
747
|
+
const props = element.props;
|
|
748
|
+
const each = readReactive2(props.each);
|
|
749
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
750
|
+
return props.fallback ? renderToString(props.fallback) : "";
|
|
751
|
+
}
|
|
752
|
+
if (each.length === 0) {
|
|
753
|
+
return props.fallback ? renderToString(props.fallback) : "";
|
|
754
|
+
}
|
|
755
|
+
const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
|
|
756
|
+
return rendered.join("");
|
|
757
|
+
}
|
|
758
|
+
async function renderIndexElement(element) {
|
|
759
|
+
const props = element.props;
|
|
760
|
+
const each = readReactive2(props.each);
|
|
761
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
762
|
+
return props.fallback ? renderToString(props.fallback) : "";
|
|
763
|
+
}
|
|
764
|
+
if (each.length === 0) {
|
|
765
|
+
return props.fallback ? renderToString(props.fallback) : "";
|
|
766
|
+
}
|
|
767
|
+
const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(() => item, index))));
|
|
768
|
+
return rendered.join("");
|
|
769
|
+
}
|
|
770
|
+
function resolveSwitchContent(element) {
|
|
771
|
+
const props = element.props;
|
|
772
|
+
const children = normalizeContent(props.children ?? element.children);
|
|
773
|
+
for (const child of children) {
|
|
774
|
+
const match = getMatchElement(child);
|
|
775
|
+
if (!match) {
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
const when = readReactive2(match.props.when);
|
|
779
|
+
if (when) {
|
|
780
|
+
return resolveMatchChildren(match, when);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return props.fallback;
|
|
784
|
+
}
|
|
785
|
+
function resolveMatchChildren(element, value) {
|
|
786
|
+
const children = element.props.children ?? element.children;
|
|
787
|
+
if (typeof children === "function") {
|
|
788
|
+
return children(value);
|
|
789
|
+
}
|
|
790
|
+
return children;
|
|
791
|
+
}
|
|
792
|
+
function resolveKeyChildren(element, value) {
|
|
793
|
+
const children = element.props.children ?? element.children;
|
|
794
|
+
if (typeof children === "function") {
|
|
795
|
+
return children(value);
|
|
796
|
+
}
|
|
797
|
+
return children;
|
|
798
|
+
}
|
|
799
|
+
function createDynamicElement(element, tag) {
|
|
800
|
+
if (typeof tag !== "string" && typeof tag !== "function") {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
const { component, ...props } = element.props;
|
|
804
|
+
const children = normalizeContent(props.children ?? element.children);
|
|
805
|
+
return {
|
|
806
|
+
tag,
|
|
807
|
+
props,
|
|
808
|
+
children
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function resolveShowChildren(element, value) {
|
|
812
|
+
const children = element.props.children ?? element.children;
|
|
813
|
+
if (typeof children === "function") {
|
|
814
|
+
return children(value);
|
|
815
|
+
}
|
|
816
|
+
return children;
|
|
817
|
+
}
|
|
818
|
+
function readReactive2(value) {
|
|
819
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
820
|
+
}
|
|
821
|
+
function normalizeContent(content) {
|
|
822
|
+
if (content == null || typeof content === "boolean") {
|
|
823
|
+
return [];
|
|
824
|
+
}
|
|
825
|
+
return Array.isArray(content) ? content : [content];
|
|
826
|
+
}
|
|
827
|
+
function isElementLike(value) {
|
|
828
|
+
return value != null && typeof value === "object" && "tag" in value;
|
|
829
|
+
}
|
|
830
|
+
function getMatchElement(value) {
|
|
831
|
+
if (!isElementLike(value)) {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
if (isMatchElement(value)) {
|
|
835
|
+
return value;
|
|
836
|
+
}
|
|
837
|
+
return value.tag === Match ? Match(value.props) : null;
|
|
838
|
+
}
|
|
839
|
+
// src/component/instance.ts
|
|
840
|
+
var uidCounter = 0;
|
|
841
|
+
function createComponentInstance(component, props, parent) {
|
|
842
|
+
return {
|
|
843
|
+
uid: uidCounter++,
|
|
844
|
+
component,
|
|
845
|
+
props,
|
|
846
|
+
element: null,
|
|
847
|
+
parent,
|
|
848
|
+
children: [],
|
|
849
|
+
effects: [],
|
|
850
|
+
_mountedHooks: [],
|
|
851
|
+
_unmountedHooks: [],
|
|
852
|
+
_updatedHooks: [],
|
|
853
|
+
_errorHooks: [],
|
|
854
|
+
provides: parent ? Object.create(parent.provides) : Object.create(null),
|
|
855
|
+
isMounted: false,
|
|
856
|
+
isUnmounted: false
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
var currentInstance = null;
|
|
860
|
+
function getCurrentInstance() {
|
|
861
|
+
return currentInstance;
|
|
862
|
+
}
|
|
863
|
+
function setCurrentInstance(instance) {
|
|
694
864
|
const prev = currentInstance;
|
|
695
865
|
currentInstance = instance;
|
|
696
866
|
return prev;
|
|
697
867
|
}
|
|
698
|
-
function
|
|
699
|
-
|
|
700
|
-
|
|
868
|
+
function withInstance(instance, fn) {
|
|
869
|
+
const prev = setCurrentInstance(instance);
|
|
870
|
+
try {
|
|
871
|
+
return fn();
|
|
872
|
+
} finally {
|
|
873
|
+
setCurrentInstance(prev);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
function fireMountedHooks(instance) {
|
|
877
|
+
if (instance.isUnmounted) {
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
for (const child of instance.children) {
|
|
881
|
+
fireMountedHooks(child);
|
|
882
|
+
}
|
|
883
|
+
if (!instance.isMounted) {
|
|
884
|
+
instance.isMounted = true;
|
|
885
|
+
for (const hook of instance._mountedHooks) {
|
|
886
|
+
hook();
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
function fireUnmountedHooks(instance) {
|
|
891
|
+
for (const child of instance.children) {
|
|
892
|
+
fireUnmountedHooks(child);
|
|
893
|
+
}
|
|
894
|
+
if (instance.isMounted && !instance.isUnmounted) {
|
|
895
|
+
instance.isUnmounted = true;
|
|
896
|
+
instance.isMounted = false;
|
|
897
|
+
for (const hook of instance._unmountedHooks) {
|
|
898
|
+
hook();
|
|
899
|
+
}
|
|
900
|
+
for (const dispose of instance.effects) {
|
|
901
|
+
dispose();
|
|
902
|
+
}
|
|
903
|
+
instance.effects.length = 0;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function fireUpdatedHooks(instance) {
|
|
907
|
+
for (const hook of instance._updatedHooks) {
|
|
908
|
+
hook();
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
var queuedUpdatedHooks = new Set;
|
|
912
|
+
function queueUpdatedHooks(instance) {
|
|
913
|
+
if (!instance || !instance.isMounted || instance.isUnmounted || instance._updatedHooks.length === 0 || queuedUpdatedHooks.has(instance)) {
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
queuedUpdatedHooks.add(instance);
|
|
917
|
+
nextTick(() => {
|
|
918
|
+
queuedUpdatedHooks.delete(instance);
|
|
919
|
+
if (instance.isMounted && !instance.isUnmounted) {
|
|
920
|
+
fireUpdatedHooks(instance);
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
function handleComponentError(instance, err) {
|
|
925
|
+
let current = instance;
|
|
926
|
+
while (current) {
|
|
927
|
+
if (current._errorHooks.length > 0) {
|
|
928
|
+
for (const hook of current._errorHooks) {
|
|
929
|
+
hook(err);
|
|
930
|
+
}
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
current = current.parent;
|
|
934
|
+
}
|
|
935
|
+
console.error("[Sinwan] Unhandled component error:", err);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// src/hydration/markers.ts
|
|
939
|
+
var COMP_ID_ATTR = "data-sinwan-id";
|
|
940
|
+
var COMP_ID_PREFIX = "c";
|
|
941
|
+
var TEXT_MARKER_OPEN = "sinwan-t:";
|
|
942
|
+
var TEXT_MARKER_CLOSE = "/sinwan-t";
|
|
943
|
+
var EVENT_ATTR = "data-sinwan-ev";
|
|
944
|
+
function compId(index) {
|
|
945
|
+
return `${COMP_ID_PREFIX}${index}`;
|
|
946
|
+
}
|
|
947
|
+
function textMarkerOpen(index) {
|
|
948
|
+
return `<!--${TEXT_MARKER_OPEN}${index}-->`;
|
|
949
|
+
}
|
|
950
|
+
function textMarkerCloseStr() {
|
|
951
|
+
return `<!--${TEXT_MARKER_CLOSE}-->`;
|
|
952
|
+
}
|
|
953
|
+
function parseTextOpenMarker(node) {
|
|
954
|
+
const data = node.data;
|
|
955
|
+
if (data.startsWith(TEXT_MARKER_OPEN)) {
|
|
956
|
+
const idx = parseInt(data.slice(TEXT_MARKER_OPEN.length), 10);
|
|
957
|
+
return Number.isNaN(idx) ? -1 : idx;
|
|
958
|
+
}
|
|
959
|
+
return -1;
|
|
960
|
+
}
|
|
961
|
+
function isTextCloseMarker(node) {
|
|
962
|
+
return node.data === TEXT_MARKER_CLOSE;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// src/server/stream.ts
|
|
966
|
+
function createHydratableStreamContext() {
|
|
967
|
+
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
968
|
+
}
|
|
969
|
+
var VOID_ELEMENTS3 = new Set([
|
|
970
|
+
"area",
|
|
971
|
+
"base",
|
|
972
|
+
"br",
|
|
973
|
+
"col",
|
|
974
|
+
"embed",
|
|
975
|
+
"hr",
|
|
976
|
+
"img",
|
|
977
|
+
"input",
|
|
978
|
+
"link",
|
|
979
|
+
"meta",
|
|
980
|
+
"param",
|
|
981
|
+
"source",
|
|
982
|
+
"track",
|
|
983
|
+
"wbr"
|
|
984
|
+
]);
|
|
985
|
+
function streamPage(page, data) {
|
|
986
|
+
const encoder = new TextEncoder;
|
|
987
|
+
return new ReadableStream({
|
|
988
|
+
async start(controller) {
|
|
989
|
+
try {
|
|
990
|
+
const element = await page(data);
|
|
991
|
+
await streamNode(element, controller, encoder);
|
|
992
|
+
controller.close();
|
|
993
|
+
} catch (error) {
|
|
994
|
+
controller.error(error);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
function streamHydratablePage(component, props) {
|
|
1000
|
+
const encoder = new TextEncoder;
|
|
1001
|
+
const ctx = createHydratableStreamContext();
|
|
1002
|
+
return new ReadableStream({
|
|
1003
|
+
async start(controller) {
|
|
1004
|
+
try {
|
|
1005
|
+
await streamHydratableComponent(component, props ?? {}, controller, encoder, ctx, true);
|
|
1006
|
+
controller.close();
|
|
1007
|
+
} catch (error) {
|
|
1008
|
+
controller.error(error);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
function streamHydratableNode(node) {
|
|
1014
|
+
const encoder = new TextEncoder;
|
|
1015
|
+
const ctx = createHydratableStreamContext();
|
|
1016
|
+
return new ReadableStream({
|
|
1017
|
+
async start(controller) {
|
|
1018
|
+
try {
|
|
1019
|
+
await streamHydratableNodeToController(node, controller, encoder, ctx);
|
|
1020
|
+
controller.close();
|
|
1021
|
+
} catch (error) {
|
|
1022
|
+
controller.error(error);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
async function streamNode(node, controller, encoder) {
|
|
1028
|
+
if (node == null || typeof node === "boolean") {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
if (typeof node === "string") {
|
|
1032
|
+
controller.enqueue(encoder.encode(escapeHtml(node)));
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
if (typeof node === "number") {
|
|
1036
|
+
controller.enqueue(encoder.encode(String(node)));
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
if (node instanceof HtmlEscapedString) {
|
|
1040
|
+
controller.enqueue(encoder.encode(node.value));
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1044
|
+
controller.enqueue(encoder.encode(escapeHtml(String(node.value))));
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
if (Array.isArray(node)) {
|
|
1048
|
+
for (const child of node) {
|
|
1049
|
+
await streamNode(child, controller, encoder);
|
|
1050
|
+
}
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
if (node instanceof Promise) {
|
|
1054
|
+
const resolved = await node;
|
|
1055
|
+
await streamElement(resolved, controller, encoder);
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
await streamElement(node, controller, encoder);
|
|
1059
|
+
}
|
|
1060
|
+
async function streamElement(element, controller, encoder) {
|
|
1061
|
+
const { tag, props, children } = element;
|
|
1062
|
+
if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
|
|
1063
|
+
await streamElement(tag(props), controller, encoder);
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
if (tag === Visible) {
|
|
1067
|
+
await streamElement(tag(props), controller, encoder);
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
if (isShowElement(element)) {
|
|
1071
|
+
const when = readReactive3(props.when);
|
|
1072
|
+
await streamNode(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder);
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (isForElement(element)) {
|
|
1076
|
+
await streamForElement(element, controller, encoder);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
if (isSwitchElement(element)) {
|
|
1080
|
+
await streamNode(resolveSwitchContent2(element), controller, encoder);
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
if (isMatchElement(element)) {
|
|
1084
|
+
const when = readReactive3(props.when);
|
|
1085
|
+
await streamNode(when ? resolveMatchChildren2(element, when) : null, controller, encoder);
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
if (isIndexElement(element)) {
|
|
1089
|
+
await streamIndexElement(element, controller, encoder);
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
if (isKeyElement(element)) {
|
|
1093
|
+
const key = readReactive3(props.when);
|
|
1094
|
+
await streamNode(resolveKeyChildren2(element, key), controller, encoder);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
if (isDynamicElement(element)) {
|
|
1098
|
+
const dynamicTag = readReactive3(props.component);
|
|
1099
|
+
const dynamic = createDynamicElement2(element, dynamicTag);
|
|
1100
|
+
if (dynamic) {
|
|
1101
|
+
await streamElement(dynamic, controller, encoder);
|
|
1102
|
+
}
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
if (isPortalElement(element)) {
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
if (typeof tag === "function") {
|
|
1109
|
+
const result = await tag(props);
|
|
1110
|
+
await streamNode(result, controller, encoder);
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (typeof tag === "string") {
|
|
1114
|
+
await streamIntrinsicElement(tag, props, children, controller, encoder);
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
await streamNode(children, controller, encoder);
|
|
1118
|
+
}
|
|
1119
|
+
async function streamIntrinsicElement(tag, props, children, controller, encoder) {
|
|
1120
|
+
const attrs = renderAttributes2(props);
|
|
1121
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1122
|
+
if (VOID_ELEMENTS3.has(tag)) {
|
|
1123
|
+
const html = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
1124
|
+
controller.enqueue(encoder.encode(html));
|
|
1125
|
+
return;
|
|
701
1126
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1127
|
+
const openTag = attrs ? `<${tag}${attrs}>` : `<${tag}>`;
|
|
1128
|
+
controller.enqueue(encoder.encode(openTag));
|
|
1129
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1130
|
+
controller.enqueue(encoder.encode(dangerous.__html));
|
|
1131
|
+
} else {
|
|
1132
|
+
await streamNode(children, controller, encoder);
|
|
1133
|
+
}
|
|
1134
|
+
controller.enqueue(encoder.encode(`</${tag}>`));
|
|
1135
|
+
}
|
|
1136
|
+
function renderAttributes2(props) {
|
|
1137
|
+
let attrs = "";
|
|
1138
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1139
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
|
|
1140
|
+
continue;
|
|
706
1141
|
}
|
|
1142
|
+
const resolvedValue = readReactive3(value);
|
|
1143
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
1144
|
+
continue;
|
|
1145
|
+
attrs += renderServerAttribute(key, resolvedValue);
|
|
707
1146
|
}
|
|
1147
|
+
return attrs;
|
|
708
1148
|
}
|
|
709
|
-
function
|
|
710
|
-
|
|
711
|
-
|
|
1149
|
+
async function streamHydratableNodeToController(node, controller, encoder, ctx, isComponentRoot = false) {
|
|
1150
|
+
if (node == null || typeof node === "boolean") {
|
|
1151
|
+
return;
|
|
712
1152
|
}
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
1153
|
+
if (typeof node === "string") {
|
|
1154
|
+
enqueue(controller, encoder, escapeHtml(node));
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
if (typeof node === "number") {
|
|
1158
|
+
enqueue(controller, encoder, String(node));
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
if (node instanceof HtmlEscapedString) {
|
|
1162
|
+
enqueue(controller, encoder, node.value);
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
if (isSignal(node) || isComputed(node)) {
|
|
1166
|
+
const idx = ctx.textIndex++;
|
|
1167
|
+
enqueue(controller, encoder, `${textMarkerOpen(idx)}${escapeHtml(String(node.value))}${textMarkerCloseStr()}`);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
if (Array.isArray(node)) {
|
|
1171
|
+
for (const child of node) {
|
|
1172
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
718
1173
|
}
|
|
719
|
-
|
|
720
|
-
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (node instanceof Promise) {
|
|
1177
|
+
await streamHydratableElement(await node, controller, encoder, ctx, isComponentRoot);
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
await streamHydratableElement(node, controller, encoder, ctx, isComponentRoot);
|
|
1181
|
+
}
|
|
1182
|
+
async function streamHydratableElement(element, controller, encoder, ctx, isComponentRoot) {
|
|
1183
|
+
const { tag, props, children } = element;
|
|
1184
|
+
if (tag === "") {
|
|
1185
|
+
for (const child of children) {
|
|
1186
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
721
1187
|
}
|
|
722
|
-
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
|
|
1191
|
+
await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
if (tag === Visible) {
|
|
1195
|
+
await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (isShowElement(element)) {
|
|
1199
|
+
const when = readReactive3(props.when);
|
|
1200
|
+
await streamHydratableNodeToController(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
if (isForElement(element)) {
|
|
1204
|
+
await streamHydratableForElement(element, controller, encoder, ctx);
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
if (isSwitchElement(element)) {
|
|
1208
|
+
await streamHydratableNodeToController(resolveSwitchContent2(element), controller, encoder, ctx, isComponentRoot);
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
if (isMatchElement(element)) {
|
|
1212
|
+
const when = readReactive3(props.when);
|
|
1213
|
+
await streamHydratableNodeToController(when ? resolveMatchChildren2(element, when) : null, controller, encoder, ctx, isComponentRoot);
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
if (isIndexElement(element)) {
|
|
1217
|
+
await streamHydratableIndexElement(element, controller, encoder, ctx);
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
if (isKeyElement(element)) {
|
|
1221
|
+
const key = readReactive3(props.when);
|
|
1222
|
+
await streamHydratableNodeToController(resolveKeyChildren2(element, key), controller, encoder, ctx, isComponentRoot);
|
|
1223
|
+
return;
|
|
723
1224
|
}
|
|
1225
|
+
if (isDynamicElement(element)) {
|
|
1226
|
+
const dynamicTag = readReactive3(props.component);
|
|
1227
|
+
const dynamic = createDynamicElement2(element, dynamicTag);
|
|
1228
|
+
if (dynamic) {
|
|
1229
|
+
await streamHydratableElement(dynamic, controller, encoder, ctx, isComponentRoot);
|
|
1230
|
+
}
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
if (isPortalElement(element)) {
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
if (typeof tag === "function") {
|
|
1237
|
+
await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (typeof tag === "string") {
|
|
1241
|
+
await streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot);
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
await streamHydratableNodeToController(children, controller, encoder, ctx);
|
|
724
1245
|
}
|
|
725
|
-
function
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1246
|
+
async function streamHydratableComponent(component, props, controller, encoder, ctx, isComponentRoot) {
|
|
1247
|
+
const parentInstance = getCurrentInstance();
|
|
1248
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
1249
|
+
if (parentInstance) {
|
|
1250
|
+
parentInstance.children.push(instance);
|
|
1251
|
+
}
|
|
1252
|
+
const prev = setCurrentInstance(instance);
|
|
1253
|
+
try {
|
|
1254
|
+
const result = await component(props);
|
|
1255
|
+
await streamHydratableNodeToController(result, controller, encoder, ctx, isComponentRoot);
|
|
1256
|
+
} finally {
|
|
1257
|
+
setCurrentInstance(prev);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
async function streamHydratableIntrinsic(tag, props, children, controller, encoder, ctx, isComponentRoot) {
|
|
1261
|
+
const attrs = renderHydratableAttributes(props, ctx, isComponentRoot);
|
|
1262
|
+
const dangerous = props.dangerouslySetInnerHTML;
|
|
1263
|
+
enqueue(controller, encoder, attrs ? `<${tag}${attrs}>` : `<${tag}>`);
|
|
1264
|
+
if (VOID_ELEMENTS3.has(tag)) {
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
if (dangerous && typeof dangerous.__html === "string") {
|
|
1268
|
+
enqueue(controller, encoder, dangerous.__html);
|
|
1269
|
+
} else {
|
|
1270
|
+
for (const child of children) {
|
|
1271
|
+
await streamHydratableNodeToController(child, controller, encoder, ctx);
|
|
733
1272
|
}
|
|
734
|
-
current = current.parent;
|
|
735
1273
|
}
|
|
736
|
-
|
|
1274
|
+
enqueue(controller, encoder, `</${tag}>`);
|
|
1275
|
+
}
|
|
1276
|
+
async function streamHydratableForElement(element, controller, encoder, ctx) {
|
|
1277
|
+
const props = element.props;
|
|
1278
|
+
const each = readReactive3(props.each);
|
|
1279
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1280
|
+
if (props.fallback) {
|
|
1281
|
+
await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
|
|
1282
|
+
}
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
if (each.length === 0) {
|
|
1286
|
+
if (props.fallback) {
|
|
1287
|
+
await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
|
|
1288
|
+
}
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
for (let index = 0;index < each.length; index++) {
|
|
1292
|
+
await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
async function streamHydratableIndexElement(element, controller, encoder, ctx) {
|
|
1296
|
+
const props = element.props;
|
|
1297
|
+
const each = readReactive3(props.each);
|
|
1298
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1299
|
+
if (props.fallback) {
|
|
1300
|
+
await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
|
|
1301
|
+
}
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
if (each.length === 0) {
|
|
1305
|
+
if (props.fallback) {
|
|
1306
|
+
await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
|
|
1307
|
+
}
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
for (let index = 0;index < each.length; index++) {
|
|
1311
|
+
await streamHydratableNodeToController(props.children(() => each[index], index), controller, encoder, ctx);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
function renderHydratableAttributes(props, ctx, isComponentRoot) {
|
|
1315
|
+
let attrs = "";
|
|
1316
|
+
if (isComponentRoot) {
|
|
1317
|
+
attrs += ` ${COMP_ID_ATTR}="${compId(ctx.componentIndex++)}"`;
|
|
1318
|
+
}
|
|
1319
|
+
const eventParts = [];
|
|
1320
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1321
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
1322
|
+
continue;
|
|
1323
|
+
}
|
|
1324
|
+
if (isEventProp(key)) {
|
|
1325
|
+
eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
|
|
1326
|
+
continue;
|
|
1327
|
+
}
|
|
1328
|
+
const resolvedValue = readReactive3(value);
|
|
1329
|
+
if (resolvedValue == null || resolvedValue === false)
|
|
1330
|
+
continue;
|
|
1331
|
+
attrs += renderServerAttribute(key, resolvedValue);
|
|
1332
|
+
}
|
|
1333
|
+
if (eventParts.length > 0) {
|
|
1334
|
+
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
1335
|
+
}
|
|
1336
|
+
return attrs;
|
|
1337
|
+
}
|
|
1338
|
+
function enqueue(controller, encoder, html) {
|
|
1339
|
+
controller.enqueue(encoder.encode(html));
|
|
1340
|
+
}
|
|
1341
|
+
async function streamForElement(element, controller, encoder) {
|
|
1342
|
+
const props = element.props;
|
|
1343
|
+
const each = readReactive3(props.each);
|
|
1344
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1345
|
+
if (props.fallback) {
|
|
1346
|
+
await streamNode(props.fallback, controller, encoder);
|
|
1347
|
+
}
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (each.length === 0) {
|
|
1351
|
+
if (props.fallback) {
|
|
1352
|
+
await streamNode(props.fallback, controller, encoder);
|
|
1353
|
+
}
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
for (let index = 0;index < each.length; index++) {
|
|
1357
|
+
await streamNode(props.children(each[index], () => index), controller, encoder);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
async function streamIndexElement(element, controller, encoder) {
|
|
1361
|
+
const props = element.props;
|
|
1362
|
+
const each = readReactive3(props.each);
|
|
1363
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1364
|
+
if (props.fallback) {
|
|
1365
|
+
await streamNode(props.fallback, controller, encoder);
|
|
1366
|
+
}
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
if (each.length === 0) {
|
|
1370
|
+
if (props.fallback) {
|
|
1371
|
+
await streamNode(props.fallback, controller, encoder);
|
|
1372
|
+
}
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
for (let index = 0;index < each.length; index++) {
|
|
1376
|
+
await streamNode(props.children(() => each[index], index), controller, encoder);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
function resolveShowChildren2(element, value) {
|
|
1380
|
+
const children = element.props.children ?? element.children;
|
|
1381
|
+
if (typeof children === "function") {
|
|
1382
|
+
return children(value);
|
|
1383
|
+
}
|
|
1384
|
+
return children;
|
|
1385
|
+
}
|
|
1386
|
+
function resolveSwitchContent2(element) {
|
|
1387
|
+
const props = element.props;
|
|
1388
|
+
const children = normalizeContent2(props.children ?? element.children);
|
|
1389
|
+
for (const child of children) {
|
|
1390
|
+
const match = getMatchElement2(child);
|
|
1391
|
+
if (!match) {
|
|
1392
|
+
continue;
|
|
1393
|
+
}
|
|
1394
|
+
const when = readReactive3(match.props.when);
|
|
1395
|
+
if (when) {
|
|
1396
|
+
return resolveMatchChildren2(match, when);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
return props.fallback;
|
|
1400
|
+
}
|
|
1401
|
+
function resolveMatchChildren2(element, value) {
|
|
1402
|
+
const children = element.props.children ?? element.children;
|
|
1403
|
+
if (typeof children === "function") {
|
|
1404
|
+
return children(value);
|
|
1405
|
+
}
|
|
1406
|
+
return children;
|
|
1407
|
+
}
|
|
1408
|
+
function resolveKeyChildren2(element, value) {
|
|
1409
|
+
const children = element.props.children ?? element.children;
|
|
1410
|
+
if (typeof children === "function") {
|
|
1411
|
+
return children(value);
|
|
1412
|
+
}
|
|
1413
|
+
return children;
|
|
1414
|
+
}
|
|
1415
|
+
function createDynamicElement2(element, tag) {
|
|
1416
|
+
if (typeof tag !== "string" && typeof tag !== "function") {
|
|
1417
|
+
return null;
|
|
1418
|
+
}
|
|
1419
|
+
const { component, ...props } = element.props;
|
|
1420
|
+
const children = normalizeContent2(props.children ?? element.children);
|
|
1421
|
+
return {
|
|
1422
|
+
tag,
|
|
1423
|
+
props,
|
|
1424
|
+
children
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
function readReactive3(value) {
|
|
1428
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1429
|
+
}
|
|
1430
|
+
function normalizeContent2(content) {
|
|
1431
|
+
if (content == null || typeof content === "boolean") {
|
|
1432
|
+
return [];
|
|
1433
|
+
}
|
|
1434
|
+
return Array.isArray(content) ? content : [content];
|
|
1435
|
+
}
|
|
1436
|
+
function isElementLike2(value) {
|
|
1437
|
+
return value != null && typeof value === "object" && "tag" in value;
|
|
1438
|
+
}
|
|
1439
|
+
function getMatchElement2(value) {
|
|
1440
|
+
if (!isElementLike2(value)) {
|
|
1441
|
+
return null;
|
|
1442
|
+
}
|
|
1443
|
+
if (isMatchElement(value)) {
|
|
1444
|
+
return value;
|
|
1445
|
+
}
|
|
1446
|
+
return value.tag === Match ? Match(value.props) : null;
|
|
737
1447
|
}
|
|
738
|
-
|
|
739
1448
|
// src/server/hydration-markers.ts
|
|
740
1449
|
function createHydrationContext() {
|
|
741
1450
|
return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
|
|
@@ -744,13 +1453,16 @@ async function renderToHydratableString(component, props) {
|
|
|
744
1453
|
const ctx = createHydrationContext();
|
|
745
1454
|
const mergedProps = props ?? {};
|
|
746
1455
|
const instance = createComponentInstance(component, mergedProps, null);
|
|
747
|
-
setCurrentInstance(instance);
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1456
|
+
const prev = setCurrentInstance(instance);
|
|
1457
|
+
try {
|
|
1458
|
+
const result = await component(mergedProps);
|
|
1459
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
1460
|
+
return renderElementH(result, ctx, true);
|
|
1461
|
+
}
|
|
1462
|
+
return renderNodeH(result, ctx);
|
|
1463
|
+
} finally {
|
|
1464
|
+
setCurrentInstance(prev);
|
|
752
1465
|
}
|
|
753
|
-
return renderNodeH(result, ctx);
|
|
754
1466
|
}
|
|
755
1467
|
async function renderNodeToHydratableString(node) {
|
|
756
1468
|
const ctx = createHydrationContext();
|
|
@@ -802,6 +1514,42 @@ function renderElementH(element, ctx, isComponentRoot) {
|
|
|
802
1514
|
if (tag === "") {
|
|
803
1515
|
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
804
1516
|
}
|
|
1517
|
+
if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
|
|
1518
|
+
return renderElementH(tag(props), ctx, isComponentRoot);
|
|
1519
|
+
}
|
|
1520
|
+
if (tag === Visible) {
|
|
1521
|
+
return renderElementH(tag(props), ctx, isComponentRoot);
|
|
1522
|
+
}
|
|
1523
|
+
if (isShowElement(element)) {
|
|
1524
|
+
const when = readReactive4(props.when);
|
|
1525
|
+
const content = when ? resolveShowChildren3(element, when) : props.fallback;
|
|
1526
|
+
return renderNodeMaybeRoot(content, ctx, isComponentRoot);
|
|
1527
|
+
}
|
|
1528
|
+
if (isForElement(element)) {
|
|
1529
|
+
return renderForElementH(element, ctx);
|
|
1530
|
+
}
|
|
1531
|
+
if (isSwitchElement(element)) {
|
|
1532
|
+
return renderNodeMaybeRoot(resolveSwitchContent3(element), ctx, isComponentRoot);
|
|
1533
|
+
}
|
|
1534
|
+
if (isMatchElement(element)) {
|
|
1535
|
+
const when = readReactive4(props.when);
|
|
1536
|
+
return renderNodeMaybeRoot(when ? resolveMatchChildren3(element, when) : null, ctx, isComponentRoot);
|
|
1537
|
+
}
|
|
1538
|
+
if (isIndexElement(element)) {
|
|
1539
|
+
return renderIndexElementH(element, ctx);
|
|
1540
|
+
}
|
|
1541
|
+
if (isKeyElement(element)) {
|
|
1542
|
+
const key = readReactive4(props.when);
|
|
1543
|
+
return renderNodeMaybeRoot(resolveKeyChildren3(element, key), ctx, isComponentRoot);
|
|
1544
|
+
}
|
|
1545
|
+
if (isDynamicElement(element)) {
|
|
1546
|
+
const dynamicTag = readReactive4(props.component);
|
|
1547
|
+
const dynamic = createDynamicElement3(element, dynamicTag);
|
|
1548
|
+
return dynamic ? renderElementH(dynamic, ctx, isComponentRoot) : "";
|
|
1549
|
+
}
|
|
1550
|
+
if (isPortalElement(element)) {
|
|
1551
|
+
return "";
|
|
1552
|
+
}
|
|
805
1553
|
if (typeof tag === "function") {
|
|
806
1554
|
return renderComponentH(tag, props, ctx);
|
|
807
1555
|
}
|
|
@@ -811,15 +1559,21 @@ function renderElementH(element, ctx, isComponentRoot) {
|
|
|
811
1559
|
return children.map((child) => renderNodeH(child, ctx)).join("");
|
|
812
1560
|
}
|
|
813
1561
|
function renderComponentH(component, props, ctx) {
|
|
814
|
-
const parentInstance =
|
|
815
|
-
const instance = createComponentInstance(component, props,
|
|
1562
|
+
const parentInstance = getCurrentInstance();
|
|
1563
|
+
const instance = createComponentInstance(component, props, parentInstance);
|
|
1564
|
+
if (parentInstance) {
|
|
1565
|
+
parentInstance.children.push(instance);
|
|
1566
|
+
}
|
|
816
1567
|
const prev = setCurrentInstance(instance);
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1568
|
+
try {
|
|
1569
|
+
const result = component(props);
|
|
1570
|
+
if (result && typeof result === "object" && "tag" in result) {
|
|
1571
|
+
return renderElementH(result, ctx, true);
|
|
1572
|
+
}
|
|
1573
|
+
return renderNodeH(result, ctx);
|
|
1574
|
+
} finally {
|
|
1575
|
+
setCurrentInstance(prev);
|
|
821
1576
|
}
|
|
822
|
-
return renderNodeH(result, ctx);
|
|
823
1577
|
}
|
|
824
1578
|
function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
825
1579
|
let attrs = "";
|
|
@@ -828,8 +1582,9 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
|
828
1582
|
}
|
|
829
1583
|
const eventParts = [];
|
|
830
1584
|
for (const [key, value] of Object.entries(props)) {
|
|
831
|
-
if (key === "children" || key === "dangerouslySetInnerHTML")
|
|
1585
|
+
if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML") {
|
|
832
1586
|
continue;
|
|
1587
|
+
}
|
|
833
1588
|
if (isEventProp(key)) {
|
|
834
1589
|
const eventName = toEventName(key);
|
|
835
1590
|
eventParts.push(`${eventName}:${ctx.eventIndex++}`);
|
|
@@ -841,13 +1596,7 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
|
841
1596
|
if (isSignal(value) || isComputed(value)) {
|
|
842
1597
|
resolvedValue = value.value;
|
|
843
1598
|
}
|
|
844
|
-
|
|
845
|
-
const attrName2 = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
846
|
-
attrs += ` ${attrName2}`;
|
|
847
|
-
continue;
|
|
848
|
-
}
|
|
849
|
-
const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
850
|
-
attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
|
|
1599
|
+
attrs += renderServerAttribute(key, resolvedValue);
|
|
851
1600
|
}
|
|
852
1601
|
if (eventParts.length > 0) {
|
|
853
1602
|
attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
|
|
@@ -862,8 +1611,107 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
|
|
|
862
1611
|
const childrenHtml = children.map((child) => renderNodeH(child, ctx)).join("");
|
|
863
1612
|
return `<${tag}${attrs}>${childrenHtml}</${tag}>`;
|
|
864
1613
|
}
|
|
1614
|
+
function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
|
|
1615
|
+
if (isComponentRoot && node && typeof node === "object" && !Array.isArray(node) && "tag" in node) {
|
|
1616
|
+
return renderElementH(node, ctx, true);
|
|
1617
|
+
}
|
|
1618
|
+
return renderNodeH(node, ctx);
|
|
1619
|
+
}
|
|
1620
|
+
function renderForElementH(element, ctx) {
|
|
1621
|
+
const props = element.props;
|
|
1622
|
+
const each = readReactive4(props.each);
|
|
1623
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1624
|
+
return props.fallback ? renderNodeH(props.fallback, ctx) : "";
|
|
1625
|
+
}
|
|
1626
|
+
if (each.length === 0) {
|
|
1627
|
+
return props.fallback ? renderNodeH(props.fallback, ctx) : "";
|
|
1628
|
+
}
|
|
1629
|
+
return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
|
|
1630
|
+
}
|
|
1631
|
+
function renderIndexElementH(element, ctx) {
|
|
1632
|
+
const props = element.props;
|
|
1633
|
+
const each = readReactive4(props.each);
|
|
1634
|
+
if (!Array.isArray(each) || typeof props.children !== "function") {
|
|
1635
|
+
return props.fallback ? renderNodeH(props.fallback, ctx) : "";
|
|
1636
|
+
}
|
|
1637
|
+
if (each.length === 0) {
|
|
1638
|
+
return props.fallback ? renderNodeH(props.fallback, ctx) : "";
|
|
1639
|
+
}
|
|
1640
|
+
return each.map((item, index) => renderNodeH(props.children(() => item, index), ctx)).join("");
|
|
1641
|
+
}
|
|
1642
|
+
function resolveShowChildren3(element, value) {
|
|
1643
|
+
const children = element.props.children ?? element.children;
|
|
1644
|
+
if (typeof children === "function") {
|
|
1645
|
+
return children(value);
|
|
1646
|
+
}
|
|
1647
|
+
return children;
|
|
1648
|
+
}
|
|
1649
|
+
function resolveSwitchContent3(element) {
|
|
1650
|
+
const props = element.props;
|
|
1651
|
+
const children = normalizeContent3(props.children ?? element.children);
|
|
1652
|
+
for (const child of children) {
|
|
1653
|
+
const match = getMatchElement3(child);
|
|
1654
|
+
if (!match) {
|
|
1655
|
+
continue;
|
|
1656
|
+
}
|
|
1657
|
+
const when = readReactive4(match.props.when);
|
|
1658
|
+
if (when) {
|
|
1659
|
+
return resolveMatchChildren3(match, when);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return props.fallback;
|
|
1663
|
+
}
|
|
1664
|
+
function resolveMatchChildren3(element, value) {
|
|
1665
|
+
const children = element.props.children ?? element.children;
|
|
1666
|
+
if (typeof children === "function") {
|
|
1667
|
+
return children(value);
|
|
1668
|
+
}
|
|
1669
|
+
return children;
|
|
1670
|
+
}
|
|
1671
|
+
function resolveKeyChildren3(element, value) {
|
|
1672
|
+
const children = element.props.children ?? element.children;
|
|
1673
|
+
if (typeof children === "function") {
|
|
1674
|
+
return children(value);
|
|
1675
|
+
}
|
|
1676
|
+
return children;
|
|
1677
|
+
}
|
|
1678
|
+
function createDynamicElement3(element, tag) {
|
|
1679
|
+
if (typeof tag !== "string" && typeof tag !== "function") {
|
|
1680
|
+
return null;
|
|
1681
|
+
}
|
|
1682
|
+
const { component, ...props } = element.props;
|
|
1683
|
+
const children = normalizeContent3(props.children ?? element.children);
|
|
1684
|
+
return {
|
|
1685
|
+
tag,
|
|
1686
|
+
props,
|
|
1687
|
+
children
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
function readReactive4(value) {
|
|
1691
|
+
return isSignal(value) || isComputed(value) ? value.value : value;
|
|
1692
|
+
}
|
|
1693
|
+
function normalizeContent3(content) {
|
|
1694
|
+
if (content == null || typeof content === "boolean") {
|
|
1695
|
+
return [];
|
|
1696
|
+
}
|
|
1697
|
+
return Array.isArray(content) ? content : [content];
|
|
1698
|
+
}
|
|
1699
|
+
function isElementLike3(value) {
|
|
1700
|
+
return value != null && typeof value === "object" && "tag" in value;
|
|
1701
|
+
}
|
|
1702
|
+
function getMatchElement3(value) {
|
|
1703
|
+
if (!isElementLike3(value)) {
|
|
1704
|
+
return null;
|
|
1705
|
+
}
|
|
1706
|
+
if (isMatchElement(value)) {
|
|
1707
|
+
return value;
|
|
1708
|
+
}
|
|
1709
|
+
return value.tag === Match ? Match(value.props) : null;
|
|
1710
|
+
}
|
|
865
1711
|
export {
|
|
866
1712
|
streamPage,
|
|
1713
|
+
streamHydratablePage,
|
|
1714
|
+
streamHydratableNode,
|
|
867
1715
|
renderToString,
|
|
868
1716
|
renderToHydratableString,
|
|
869
1717
|
renderPage,
|
|
@@ -874,5 +1722,5 @@ export {
|
|
|
874
1722
|
getPage
|
|
875
1723
|
};
|
|
876
1724
|
|
|
877
|
-
//# debugId=
|
|
1725
|
+
//# debugId=46896ED83A2048E464756E2164756E21
|
|
878
1726
|
//# sourceMappingURL=index.development.js.map
|