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