@vmz/core 0.1.32 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-nav.d.ts → browser/client-nav.d.ts} +4 -13
- package/dist/{client-nav.js → browser/client-nav.js} +16 -74
- package/dist/browser/direct-api.types.d.ts +141 -0
- package/dist/browser/direct-api.types.js +4 -0
- package/dist/browser/direct-host-box.d.ts +11 -0
- package/dist/{direct-host-box.js → browser/direct-host-box.js} +2 -18
- package/dist/{dom-core.d.ts → browser/dom-core.d.ts} +67 -220
- package/dist/browser/dom-core.js +2484 -0
- package/dist/browser/dom-core.types.d.ts +127 -0
- package/dist/browser/dom-core.types.js +4 -0
- package/dist/{position-context.js → browser/position-context.js} +1 -1
- package/dist/browser/unknown-component.d.ts +14 -0
- package/dist/{unknown-component.js → browser/unknown-component.js} +5 -30
- package/dist/{dom.browser.d.ts → faces/dom.browser.d.ts} +2 -2
- package/dist/{dom.browser.js → faces/dom.browser.js} +2 -3
- package/dist/faces/dom.client.d.ts +4 -0
- package/dist/faces/dom.client.js +4 -0
- package/dist/faces/dom.d.ts +6 -0
- package/dist/faces/dom.js +6 -0
- package/dist/faces/http.d.ts +6 -0
- package/dist/{http.js → faces/http.js} +0 -1
- package/dist/faces/server.d.ts +30 -0
- package/dist/{server.js → faces/server.js} +27 -149
- package/dist/{vmz-dom.d.ts → faces/vmz-dom.d.ts} +1 -1
- package/dist/{vmz-dom.js → faces/vmz-dom.js} +1 -2
- package/dist/{vmz-runtime.d.ts → faces/vmz-runtime.d.ts} +1 -1
- package/dist/{vmz-runtime.js → faces/vmz-runtime.js} +1 -2
- package/dist/host/deployment-registry.d.ts +16 -0
- package/dist/{deployment-registry.js → host/deployment-registry.js} +1 -68
- package/dist/host/list-client-components.d.ts +14 -0
- package/dist/{list-client-components.js → host/list-client-components.js} +0 -37
- package/dist/{localize-body-links.js → host/localize-body-links.js} +0 -1
- package/dist/host/native-addon.d.ts +6 -0
- package/dist/{native-addon.js → host/native-addon.js} +0 -20
- package/dist/host/render-host.d.ts +20 -0
- package/dist/{render-host.js → host/render-host.js} +1 -17
- package/dist/{serve-host.d.ts → host/serve-host.d.ts} +3 -3
- package/dist/{serve-host.mjs → host/serve-host.mjs} +45 -168
- package/dist/shared/dom-attr-normalize.d.ts +8 -0
- package/dist/shared/dom-attr-normalize.js +71 -0
- package/dist/shared/host.types.d.ts +113 -0
- package/dist/shared/host.types.js +4 -0
- package/dist/shared/server.types.d.ts +67 -0
- package/dist/shared/server.types.js +4 -0
- package/dist/{dom-ssr.d.ts → ssr/dom-ssr.d.ts} +8 -37
- package/dist/{dom-ssr.js → ssr/dom-ssr.js} +189 -217
- package/package.json +34 -34
- package/dist/deployment-registry.d.ts +0 -70
- package/dist/direct-host-box.d.ts +0 -26
- package/dist/dom-core.js +0 -4815
- package/dist/dom.client.d.ts +0 -4
- package/dist/dom.client.js +0 -5
- package/dist/dom.d.ts +0 -6
- package/dist/dom.js +0 -7
- package/dist/http.d.ts +0 -6
- package/dist/list-client-components.d.ts +0 -62
- package/dist/native-addon.d.ts +0 -12
- package/dist/render-host.d.ts +0 -32
- package/dist/server.d.ts +0 -46
- package/dist/unknown-component.d.ts +0 -40
- /package/dist/{position-context.d.ts → browser/position-context.d.ts} +0 -0
- /package/dist/{index.d.ts → faces/index.d.ts} +0 -0
- /package/dist/{index.js → faces/index.js} +0 -0
- /package/dist/{localize-body-links.d.ts → host/localize-body-links.d.ts} +0 -0
- /package/dist/{route-layout-chain.d.ts → host/route-layout-chain.d.ts} +0 -0
- /package/dist/{route-layout-chain.js → host/route-layout-chain.js} +0 -0
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
|
-
* VMZ DOM SSR / hydrate / resume
|
|
2
|
+
* VMZ DOM SSR / hydrate / resume ??precise patches, no VDOM diff.
|
|
4
3
|
* Imports client DOM primitives from ./dom-core.js for tree-shakeable browser entry.
|
|
5
4
|
*/
|
|
6
|
-
import { applyDirectHostBox, directHostBoxStyleAttr } from '
|
|
7
|
-
import { applyPreservedState, BOOLEAN_HTML_ATTRS, createInstance, destroy, directApi, eventPropHandlerName, findOwnedDefaultSlot, getRegisteredComponent, hasMeaningfulChild, isEventEntryStrategy, mount, noteDomCreate, resolveComponent, runDirectCreate, scheduleClientOn, settlePendingChildMounts, snapshotInstanceState, stripFns, } from '
|
|
8
|
-
import { markUnknownComponentHost, serializeUnknownComponentNode } from '
|
|
9
|
-
/** @type {Error | null} last linkedom resolve failure (for clear SSR errors) */
|
|
5
|
+
import { applyDirectHostBox, directHostBoxStyleAttr } from '../browser/direct-host-box.js';
|
|
6
|
+
import { applyPreservedState, BOOLEAN_HTML_ATTRS, createInstance, destroy, directApi, eventPropHandlerName, findOwnedDefaultSlot, getRegisteredComponent, hasMeaningfulChild, isEventEntryStrategy, mergeClassParts, mergeStyleParts, mount, noteDomCreate, resolveComponent, runDirectCreate, scheduleClientOn, settlePendingChildMounts, snapshotInstanceState, stripFns, } from '../browser/dom-core.js';
|
|
7
|
+
import { markUnknownComponentHost, serializeUnknownComponentNode } from '../browser/unknown-component.js';
|
|
10
8
|
let _ssrDocumentLastError = null;
|
|
11
9
|
/**
|
|
12
10
|
* Node SSR has no browser `document`. rowKernel prefers document-free HTML fill;
|
|
@@ -16,7 +14,7 @@ let _ssrDocumentLastError = null;
|
|
|
16
14
|
* and browser hosts load that barrel.
|
|
17
15
|
*
|
|
18
16
|
* When this file is copied into an app `dist/`, `createRequire(import.meta.url)` cannot
|
|
19
|
-
* see `@vmz/core`'s dependency tree
|
|
17
|
+
* see `@vmz/core`'s dependency tree ??resolve linkedom from cwd / `@vmz/core` as well.
|
|
20
18
|
*/
|
|
21
19
|
function ensureSsrDocument() {
|
|
22
20
|
if (typeof globalThis.document !== 'undefined' && typeof globalThis.document.createElement === 'function') {
|
|
@@ -36,13 +34,11 @@ function ensureSsrDocument() {
|
|
|
36
34
|
}
|
|
37
35
|
const pathMod = typeof proc.getBuiltinModule === 'function' ? proc.getBuiltinModule('path') : null;
|
|
38
36
|
const createRequire = mod.createRequire;
|
|
39
|
-
/** @type {string[]} */
|
|
40
37
|
const bases = [];
|
|
41
38
|
bases.push(import.meta.url);
|
|
42
39
|
if (pathMod && typeof proc.cwd === 'function') {
|
|
43
40
|
bases.push(pathMod.join(proc.cwd(), 'package.json'));
|
|
44
41
|
}
|
|
45
|
-
/** @type {string[]} */
|
|
46
42
|
const errors = [];
|
|
47
43
|
let parseHTML = null;
|
|
48
44
|
for (const base of bases) {
|
|
@@ -59,7 +55,7 @@ function ensureSsrDocument() {
|
|
|
59
55
|
break;
|
|
60
56
|
}
|
|
61
57
|
catch (e) {
|
|
62
|
-
errors.push(`${base}
|
|
58
|
+
errors.push(`${base} ??linkedom: ${e && e.message ? e.message : e}`);
|
|
63
59
|
}
|
|
64
60
|
// Walk into @vmz/core's dependency tree (linkedom is declared there).
|
|
65
61
|
for (const coreId of ['@vmz/core', '@vmz/core/dom', '@vmz/core/server']) {
|
|
@@ -69,7 +65,7 @@ function ensureSsrDocument() {
|
|
|
69
65
|
break;
|
|
70
66
|
}
|
|
71
67
|
catch (e) {
|
|
72
|
-
errors.push(`${base}
|
|
68
|
+
errors.push(`${base} ??${coreId}/linkedom: ${e && e.message ? e.message : e}`);
|
|
73
69
|
}
|
|
74
70
|
}
|
|
75
71
|
if (parseHTML)
|
|
@@ -101,7 +97,7 @@ export async function renderToString(Component, props = {}, opts = {}) {
|
|
|
101
97
|
}
|
|
102
98
|
if (signal && signal.aborted)
|
|
103
99
|
return '';
|
|
104
|
-
// production Direct emit: SSR only via Direct serialize schedule
|
|
100
|
+
// production Direct emit: SSR only via Direct serialize schedule ??never `render`.
|
|
105
101
|
if (!(Component && Component.__vmzDirect && typeof Component.__vmzCreate === 'function')) {
|
|
106
102
|
throw new Error(`vmz:dom renderToString() requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
|
|
107
103
|
}
|
|
@@ -112,12 +108,8 @@ export async function renderToString(Component, props = {}, opts = {}) {
|
|
|
112
108
|
}
|
|
113
109
|
/**
|
|
114
110
|
* Stream SSR via the same Direct serialize schedule as `renderToString`.
|
|
115
|
-
* Yields HTML chunks (open tag
|
|
111
|
+
* Yields HTML chunks (open tag ??children ??close). Joining chunks equals `renderToString`.
|
|
116
112
|
* Supports AbortSignal for cancel; consumers should respect backpressure (await between chunks).
|
|
117
|
-
* @param {new (props?: object) => any} Component
|
|
118
|
-
* @param {object} [props]
|
|
119
|
-
* @param {{ signal?: AbortSignal, slotHtml?: string }} [opts]
|
|
120
|
-
* @returns {AsyncGenerator<string, void, void>}
|
|
121
113
|
*/
|
|
122
114
|
export async function* renderToStream(Component, props = {}, opts = {}) {
|
|
123
115
|
ensureSsrDocument();
|
|
@@ -155,11 +147,9 @@ export async function* renderToStream(Component, props = {}, opts = {}) {
|
|
|
155
147
|
}
|
|
156
148
|
/**
|
|
157
149
|
* Fill the layout-owned default `<slot>` with pre-rendered HTML (layout SSR wrap).
|
|
158
|
-
* Skips nested component hosts (`data-vmz`)
|
|
159
|
-
* (e.g. Button label), not the page outlet. Without this, DFS hits LocaleToggle
|
|
150
|
+
* Skips nested component hosts (`data-vmz`) ??their slots are for child projection
|
|
151
|
+
* (e.g. Button label), not the page outlet. Without this, DFS hits LocaleToggle?Button
|
|
160
152
|
* before Layout's `<main><slot>`, and the entire page HTML lands inside a button.
|
|
161
|
-
* @param {any} node
|
|
162
|
-
* @param {string} html
|
|
163
153
|
*/
|
|
164
154
|
function injectDefaultSlotHtml(node, html) {
|
|
165
155
|
if (!node || typeof node !== 'object')
|
|
@@ -169,7 +159,7 @@ function injectDefaultSlotHtml(node, html) {
|
|
|
169
159
|
node.children = [];
|
|
170
160
|
return true;
|
|
171
161
|
}
|
|
172
|
-
// Nested Direct component wrapper from serializeApi.component
|
|
162
|
+
// Nested Direct component wrapper from serializeApi.component ??do not search inside.
|
|
173
163
|
if (node.__kind === 'el' && node.attrs && node.attrs['data-vmz'] != null) {
|
|
174
164
|
return false;
|
|
175
165
|
}
|
|
@@ -186,20 +176,13 @@ function injectDefaultSlotHtml(node, html) {
|
|
|
186
176
|
* Live-DOM counterpart: first default `<slot>` owned by this tree, not by a nested
|
|
187
177
|
* `[data-vmz]` component (Button/Link labels, etc.).
|
|
188
178
|
* Re-exported from dom-core (single implementation).
|
|
189
|
-
* @param {Element | null | undefined} root
|
|
190
|
-
* @returns {Element | null}
|
|
191
179
|
*/
|
|
192
180
|
export { findOwnedDefaultSlot };
|
|
193
181
|
/**
|
|
194
|
-
* Hydrate/mount a file-route page inside an optional layout chain (outer
|
|
182
|
+
* Hydrate/mount a file-route page inside an optional layout chain (outer ??inner).
|
|
195
183
|
* Mirrors SSR `slotHtml` wrapping: each layout's owned default slot becomes the
|
|
196
184
|
* outlet for the next layout or the page. Retains layout instances on `container`
|
|
197
185
|
* so SPA transitions can dispose only the page host.
|
|
198
|
-
* @param {new (props?: object) => any} Page
|
|
199
|
-
* @param {Element} container
|
|
200
|
-
* @param {object} [props]
|
|
201
|
-
* @param {Array<new (props?: object) => any>} [layoutCtors] outer → inner
|
|
202
|
-
* @param {{ preserveState?: boolean | Record<string, unknown>, skipOnMount?: boolean }} [opts]
|
|
203
186
|
*/
|
|
204
187
|
export async function hydrateRoute(Page, container, props = {}, layoutCtors = [], opts = {}) {
|
|
205
188
|
if (typeof document === 'undefined') {
|
|
@@ -211,7 +194,6 @@ export async function hydrateRoute(Page, container, props = {}, layoutCtors = []
|
|
|
211
194
|
}
|
|
212
195
|
container.__vmzPageHost = null;
|
|
213
196
|
container.__vmzLayoutInsts = null;
|
|
214
|
-
/** @type {object[]} */
|
|
215
197
|
const layoutInsts = [];
|
|
216
198
|
let host = container;
|
|
217
199
|
const ctors = Array.isArray(layoutCtors) ? layoutCtors.filter(Boolean) : [];
|
|
@@ -241,10 +223,6 @@ export async function hydrateRoute(Page, container, props = {}, layoutCtors = []
|
|
|
241
223
|
/**
|
|
242
224
|
* SPA same-layout transition: dispose only the page host, keep layout instances.
|
|
243
225
|
* Callers must verify `data-vmz-layout` is unchanged before using this.
|
|
244
|
-
* @param {new (props?: object) => any} Page
|
|
245
|
-
* @param {Element} container `#app` that already has `__vmzPageHost` / `__vmzLayoutInsts`
|
|
246
|
-
* @param {object} [props]
|
|
247
|
-
* @param {{ preserveState?: boolean | Record<string, unknown>, skipOnMount?: boolean }} [opts]
|
|
248
226
|
*/
|
|
249
227
|
export async function hydrateRoutePage(Page, container, props = {}, opts = {}) {
|
|
250
228
|
if (typeof document === 'undefined') {
|
|
@@ -265,8 +243,6 @@ export async function hydrateRoutePage(Page, container, props = {}, opts = {}) {
|
|
|
265
243
|
}
|
|
266
244
|
/**
|
|
267
245
|
* SSR: run the same __vmzCreate schedule against a serialize host (no render).
|
|
268
|
-
* @param {new (props?: object) => any} Component
|
|
269
|
-
* @param {object} inst
|
|
270
246
|
*/
|
|
271
247
|
function runDirectSerializeTree(Component, inst) {
|
|
272
248
|
serializeApi._inst = inst;
|
|
@@ -279,14 +255,10 @@ function runDirectSerializeTree(Component, inst) {
|
|
|
279
255
|
}
|
|
280
256
|
/**
|
|
281
257
|
* SSR child onMount: sync `__vmzCreate` cannot await nested mounts.
|
|
282
|
-
* Expand rounds
|
|
283
|
-
* @param {new (props?: object) => any} Component
|
|
284
|
-
* @param {object} inst
|
|
258
|
+
* Expand rounds ??reuse prior child instances, await newly discovered onMounts, re-emit.
|
|
285
259
|
*/
|
|
286
260
|
async function runDirectSerializeTreeWithMounts(Component, inst) {
|
|
287
|
-
/** @type {object[]} */
|
|
288
261
|
let preMounted = [];
|
|
289
|
-
/** @type {any} */
|
|
290
262
|
let tree = null;
|
|
291
263
|
for (let round = 0; round < 32; round++) {
|
|
292
264
|
serializeApi._ssrPreMounted = preMounted;
|
|
@@ -330,6 +302,8 @@ function flattenSerializeNode(node) {
|
|
|
330
302
|
return escapeHtml(node);
|
|
331
303
|
if (node.__kind === 'text')
|
|
332
304
|
return escapeHtml(node.value);
|
|
305
|
+
if (node.__kind === 'comment')
|
|
306
|
+
return '';
|
|
333
307
|
if (node.__kind === 'frag') {
|
|
334
308
|
if (node.__rawHtml != null)
|
|
335
309
|
return String(node.__rawHtml);
|
|
@@ -356,8 +330,6 @@ function flattenSerializeNode(node) {
|
|
|
356
330
|
}
|
|
357
331
|
/**
|
|
358
332
|
* Progressive HTML chunks from a serialize tree (same nodes as flattenSerializeNode).
|
|
359
|
-
* @param {any} node
|
|
360
|
-
* @returns {Generator<string, void, void>}
|
|
361
333
|
*/
|
|
362
334
|
function* streamSerializeChunks(node) {
|
|
363
335
|
if (node == null || node === false)
|
|
@@ -370,6 +342,8 @@ function* streamSerializeChunks(node) {
|
|
|
370
342
|
yield escapeHtml(node.value);
|
|
371
343
|
return;
|
|
372
344
|
}
|
|
345
|
+
if (node.__kind === 'comment')
|
|
346
|
+
return;
|
|
373
347
|
if (node.__kind === 'frag') {
|
|
374
348
|
if (node.__rawHtml != null) {
|
|
375
349
|
yield String(node.__rawHtml);
|
|
@@ -409,19 +383,14 @@ function* streamSerializeChunks(node) {
|
|
|
409
383
|
/**
|
|
410
384
|
* Document-free rowKernel SSR fill (transitional / pre-0.1.7 emit only).
|
|
411
385
|
* Prefer `serializeItem` (IR schedule). Do not treat this as the long-term contract.
|
|
412
|
-
* @param {{ html: string, textSlots?: Record<string, number>, hostFields?: string[] }} rk
|
|
413
|
-
* @param {any} item
|
|
414
|
-
* @param {any} key
|
|
415
|
-
* @returns {string | null} filled outer HTML, or null if shape is not fillable
|
|
416
386
|
*/
|
|
417
387
|
function fillRowKernelHtml(rk, item, key) {
|
|
418
388
|
const slots = rk.textSlots;
|
|
419
389
|
if (!slots || typeof slots !== 'object')
|
|
420
390
|
return null;
|
|
421
|
-
/** @type {string[]} */
|
|
422
391
|
const fields = Object.entries(slots)
|
|
423
392
|
.filter(([, i]) => typeof i === 'number' && Number.isFinite(i))
|
|
424
|
-
.sort((a, b) =>
|
|
393
|
+
.sort((a, b) => Number(a[1]) - Number(b[1]))
|
|
425
394
|
.map(([f]) => f);
|
|
426
395
|
if (!fields.length)
|
|
427
396
|
return null;
|
|
@@ -446,10 +415,6 @@ function fillRowKernelHtml(rk, item, key) {
|
|
|
446
415
|
* SSR row when `createItem` was omitted (rowKernel client emit).
|
|
447
416
|
* Prefer document-free fill from `html` + `textSlots`; fall back to linkedom + hydrate
|
|
448
417
|
* when host class ternaries need live DOM, or when placeholders cannot be string-filled.
|
|
449
|
-
* @param {object} inst
|
|
450
|
-
* @param {{ html: string, hydrate?: Function, textSlots?: Record<string, number>, hostFields?: string[] }} rk
|
|
451
|
-
* @param {{ item: any, index: number }} box
|
|
452
|
-
* @param {any} key
|
|
453
418
|
*/
|
|
454
419
|
function serializeRowFromKernel(inst, rk, box, key) {
|
|
455
420
|
const item = box.item;
|
|
@@ -508,24 +473,71 @@ function serializeRowFromKernel(inst, rk, box, key) {
|
|
|
508
473
|
appendChild() { },
|
|
509
474
|
};
|
|
510
475
|
}
|
|
511
|
-
|
|
476
|
+
function virtualLink(parent, child) {
|
|
477
|
+
if (child != null && typeof child === 'object')
|
|
478
|
+
child.parentNode = parent;
|
|
479
|
+
}
|
|
480
|
+
function virtualAppend(parent, child) {
|
|
481
|
+
if (parent == null || child == null)
|
|
482
|
+
return;
|
|
483
|
+
if (!Array.isArray(parent.children))
|
|
484
|
+
parent.children = [];
|
|
485
|
+
parent.children.push(child);
|
|
486
|
+
virtualLink(parent, child);
|
|
487
|
+
}
|
|
488
|
+
function virtualInsertBefore(parent, node, ref) {
|
|
489
|
+
if (parent == null || node == null)
|
|
490
|
+
return;
|
|
491
|
+
if (!Array.isArray(parent.children))
|
|
492
|
+
parent.children = [];
|
|
493
|
+
if (ref == null) {
|
|
494
|
+
virtualAppend(parent, node);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const idx = parent.children.indexOf(ref);
|
|
498
|
+
if (idx < 0)
|
|
499
|
+
virtualAppend(parent, node);
|
|
500
|
+
else {
|
|
501
|
+
parent.children.splice(idx, 0, node);
|
|
502
|
+
virtualLink(parent, node);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function virtualRemove(node) {
|
|
506
|
+
const p = node && node.parentNode;
|
|
507
|
+
if (!p || !Array.isArray(p.children))
|
|
508
|
+
return;
|
|
509
|
+
const idx = p.children.indexOf(node);
|
|
510
|
+
if (idx >= 0)
|
|
511
|
+
p.children.splice(idx, 1);
|
|
512
|
+
node.parentNode = null;
|
|
513
|
+
}
|
|
514
|
+
function makeVirtualEl(tag) {
|
|
515
|
+
return {
|
|
516
|
+
__kind: 'el',
|
|
517
|
+
tag: tag || 'div',
|
|
518
|
+
attrs: {},
|
|
519
|
+
children: [],
|
|
520
|
+
style: {},
|
|
521
|
+
parentNode: null,
|
|
522
|
+
setAttribute(name, value) {
|
|
523
|
+
applySerializeAttr(this, name, value);
|
|
524
|
+
},
|
|
525
|
+
appendChild(c) {
|
|
526
|
+
virtualAppend(this, c);
|
|
527
|
+
},
|
|
528
|
+
insertBefore(node, ref) {
|
|
529
|
+
virtualInsertBefore(this, node, ref);
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
}
|
|
512
533
|
const serializeApi = {
|
|
513
|
-
/** @type {object | null} */
|
|
514
534
|
_inst: null,
|
|
515
|
-
/** @type {null} */
|
|
516
535
|
_branchBinds: null,
|
|
517
|
-
/** @type {null} */
|
|
518
536
|
_itemPatches: null,
|
|
519
|
-
|
|
537
|
+
_eachCtx: null,
|
|
520
538
|
_ssrPreMounted: null,
|
|
521
|
-
/** @type {number} */
|
|
522
539
|
_ssrPreIdx: 0,
|
|
523
|
-
/** @type {object[] | null} newly created child instances this round */
|
|
524
540
|
_ssrCollected: null,
|
|
525
|
-
/**
|
|
526
|
-
* @param {new (props?: object) => any} Ctor
|
|
527
|
-
* @param {object} resolved
|
|
528
|
-
*/
|
|
529
541
|
_ssrChildInstance(Ctor, resolved) {
|
|
530
542
|
const pre = serializeApi._ssrPreMounted;
|
|
531
543
|
if (pre && serializeApi._ssrPreIdx < pre.length) {
|
|
@@ -537,35 +549,96 @@ const serializeApi = {
|
|
|
537
549
|
return child;
|
|
538
550
|
},
|
|
539
551
|
el(tag) {
|
|
540
|
-
return
|
|
541
|
-
__kind: 'el',
|
|
542
|
-
tag: tag || 'div',
|
|
543
|
-
attrs: {},
|
|
544
|
-
children: [],
|
|
545
|
-
appendChild(c) {
|
|
546
|
-
if (c != null)
|
|
547
|
-
this.children.push(c);
|
|
548
|
-
},
|
|
549
|
-
};
|
|
552
|
+
return makeVirtualEl(tag);
|
|
550
553
|
},
|
|
551
554
|
text(value) {
|
|
552
|
-
|
|
555
|
+
const node = { __kind: 'text', value: value == null ? '' : String(value), parentNode: null };
|
|
556
|
+
// Generated Direct patches use DOM `textContent`; virtual text uses `value`.
|
|
557
|
+
Object.defineProperty(node, 'textContent', {
|
|
558
|
+
configurable: true,
|
|
559
|
+
enumerable: false,
|
|
560
|
+
get() {
|
|
561
|
+
return node.value;
|
|
562
|
+
},
|
|
563
|
+
set(v) {
|
|
564
|
+
node.value = v == null ? '' : String(v);
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
return node;
|
|
568
|
+
},
|
|
569
|
+
comment(value) {
|
|
570
|
+
return { __kind: 'comment', value: value == null ? '' : String(value), parentNode: null };
|
|
553
571
|
},
|
|
554
572
|
frag() {
|
|
555
573
|
return {
|
|
556
574
|
__kind: 'frag',
|
|
557
575
|
children: [],
|
|
576
|
+
parentNode: null,
|
|
558
577
|
appendChild(c) {
|
|
559
|
-
|
|
560
|
-
|
|
578
|
+
virtualAppend(this, c);
|
|
579
|
+
},
|
|
580
|
+
insertBefore(node, ref) {
|
|
581
|
+
virtualInsertBefore(this, node, ref);
|
|
561
582
|
},
|
|
562
583
|
};
|
|
563
584
|
},
|
|
585
|
+
insertBefore(parent, node, ref) {
|
|
586
|
+
virtualInsertBefore(parent, node, ref);
|
|
587
|
+
},
|
|
588
|
+
removeNode(node) {
|
|
589
|
+
virtualRemove(node);
|
|
590
|
+
},
|
|
591
|
+
trackPatch(inst, deps, patch, bindingId = null) {
|
|
592
|
+
if (typeof patch !== 'function')
|
|
593
|
+
return;
|
|
594
|
+
if (serializeApi._branchBinds) {
|
|
595
|
+
serializeApi._branchBinds.push({ deps: deps || [], fn: patch, bindingId });
|
|
596
|
+
try {
|
|
597
|
+
patch.call(inst);
|
|
598
|
+
}
|
|
599
|
+
catch (err) {
|
|
600
|
+
console.error('vmz:ssr trackPatch branch', err);
|
|
601
|
+
}
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (serializeApi._itemPatches) {
|
|
605
|
+
patch.__vmzItemLocal = true;
|
|
606
|
+
serializeApi._itemPatches.push(patch);
|
|
607
|
+
if (serializeApi._eachCtx) {
|
|
608
|
+
serializeApi._eachCtx.noteItemBind(bindingId, deps || [], patch);
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
patch.call(inst);
|
|
612
|
+
}
|
|
613
|
+
catch (err) {
|
|
614
|
+
console.error('vmz:ssr trackPatch item', err);
|
|
615
|
+
}
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
try {
|
|
619
|
+
patch.call(inst);
|
|
620
|
+
}
|
|
621
|
+
catch (err) {
|
|
622
|
+
console.error('vmz:ssr trackPatch', err);
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
untrackPatch() {
|
|
626
|
+
/* SSR one-shot schedule ??no reactive unregister */
|
|
627
|
+
},
|
|
628
|
+
disposeTree() {
|
|
629
|
+
/* SSR one-shot schedule */
|
|
630
|
+
},
|
|
564
631
|
attr(el, name, value) {
|
|
565
632
|
if (!el || el.__kind !== 'el')
|
|
566
633
|
return;
|
|
567
634
|
applySerializeAttr(el, name, value);
|
|
568
635
|
},
|
|
636
|
+
mergeClass(...parts) {
|
|
637
|
+
return mergeClassParts(...parts);
|
|
638
|
+
},
|
|
639
|
+
mergeStyle(...parts) {
|
|
640
|
+
return mergeStyleParts(...parts);
|
|
641
|
+
},
|
|
569
642
|
on() {
|
|
570
643
|
/* events are no-ops during SSR */
|
|
571
644
|
},
|
|
@@ -581,16 +654,6 @@ const serializeApi = {
|
|
|
581
654
|
onComponentEvent() {
|
|
582
655
|
/* component events attach only on the client */
|
|
583
656
|
},
|
|
584
|
-
bindText(inst, bindingId, deps, get, textNode) {
|
|
585
|
-
let raw = '';
|
|
586
|
-
try {
|
|
587
|
-
raw = get.call(inst);
|
|
588
|
-
}
|
|
589
|
-
catch {
|
|
590
|
-
raw = '';
|
|
591
|
-
}
|
|
592
|
-
textNode.value = String(raw ?? '');
|
|
593
|
-
},
|
|
594
657
|
specFieldText(inst, _bindingId, fieldName, textNode) {
|
|
595
658
|
let raw;
|
|
596
659
|
try {
|
|
@@ -601,16 +664,6 @@ const serializeApi = {
|
|
|
601
664
|
}
|
|
602
665
|
textNode.value = String(raw ?? '');
|
|
603
666
|
},
|
|
604
|
-
bindAttr(inst, bindingId, deps, get, el, name) {
|
|
605
|
-
let raw;
|
|
606
|
-
try {
|
|
607
|
-
raw = get.call(inst);
|
|
608
|
-
}
|
|
609
|
-
catch {
|
|
610
|
-
raw = null;
|
|
611
|
-
}
|
|
612
|
-
applySerializeAttr(el, name, raw);
|
|
613
|
-
},
|
|
614
667
|
specFieldAttr(inst, _bindingId, fieldName, el, name) {
|
|
615
668
|
let raw;
|
|
616
669
|
try {
|
|
@@ -619,6 +672,14 @@ const serializeApi = {
|
|
|
619
672
|
catch {
|
|
620
673
|
raw = null;
|
|
621
674
|
}
|
|
675
|
+
if (name === 'class' || name === 'className') {
|
|
676
|
+
applySerializeAttr(el, 'class', mergeClassParts(raw));
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
if (name === 'style') {
|
|
680
|
+
applySerializeAttr(el, 'style', mergeStyleParts(raw));
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
622
683
|
applySerializeAttr(el, name, raw);
|
|
623
684
|
},
|
|
624
685
|
bindComponentProp() {
|
|
@@ -660,7 +721,7 @@ const serializeApi = {
|
|
|
660
721
|
slot.__rawHtml = null;
|
|
661
722
|
if (!Array.isArray(slot.children))
|
|
662
723
|
slot.children = [];
|
|
663
|
-
// Append
|
|
724
|
+
// Append ??multiple projectDefaultSlot calls must accumulate (SSR).
|
|
664
725
|
// Client path replaces the live <slot> then appends siblings; serialize must push.
|
|
665
726
|
slot.children.push(node);
|
|
666
727
|
return;
|
|
@@ -675,85 +736,16 @@ const serializeApi = {
|
|
|
675
736
|
el.children = [];
|
|
676
737
|
},
|
|
677
738
|
bindHtml(inst, bindingId, deps, get, el) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
raw = get.call(inst);
|
|
681
|
-
}
|
|
682
|
-
catch {
|
|
683
|
-
raw = '';
|
|
684
|
-
}
|
|
685
|
-
el.__rawHtml = raw == null ? '' : String(raw);
|
|
686
|
-
el.children = [];
|
|
687
|
-
},
|
|
688
|
-
ifBlock(inst, bindingId, deps, branches) {
|
|
689
|
-
// No empty `span[data-vmz-if]` box (`ui-vif-dom`): false → empty frag.
|
|
690
|
-
const frag = serializeApi.frag();
|
|
691
|
-
let idx = -1;
|
|
692
|
-
for (let i = 0; i < branches.length; i++) {
|
|
693
|
-
const b = branches[i];
|
|
694
|
-
if (!b.cond) {
|
|
695
|
-
idx = i;
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
739
|
+
serializeApi.trackPatch(inst, deps || [], function bindHtmlPatch() {
|
|
740
|
+
let raw;
|
|
698
741
|
try {
|
|
699
|
-
|
|
700
|
-
idx = i;
|
|
701
|
-
break;
|
|
702
|
-
}
|
|
742
|
+
raw = get.call(inst);
|
|
703
743
|
}
|
|
704
744
|
catch {
|
|
705
|
-
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
if (idx >= 0 && branches[idx].create) {
|
|
709
|
-
const created = branches[idx].create.call(inst, serializeApi);
|
|
710
|
-
if (created)
|
|
711
|
-
frag.appendChild(created);
|
|
712
|
-
}
|
|
713
|
-
return frag;
|
|
714
|
-
},
|
|
715
|
-
eachBlock(inst, bindingId, deps, spec) {
|
|
716
|
-
const frag = serializeApi.frag();
|
|
717
|
-
let list = [];
|
|
718
|
-
try {
|
|
719
|
-
list = spec.list.call(inst) || [];
|
|
720
|
-
}
|
|
721
|
-
catch {
|
|
722
|
-
list = [];
|
|
723
|
-
}
|
|
724
|
-
if (!Array.isArray(list))
|
|
725
|
-
list = [...list];
|
|
726
|
-
for (let i = 0; i < list.length; i++) {
|
|
727
|
-
const box = { item: list[i], index: i };
|
|
728
|
-
let k = i;
|
|
729
|
-
if (typeof spec.key === 'function') {
|
|
730
|
-
try {
|
|
731
|
-
k = spec.key.call(inst, box);
|
|
732
|
-
}
|
|
733
|
-
catch {
|
|
734
|
-
k = i;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
let dom = null;
|
|
738
|
-
if (typeof spec.createItem === 'function') {
|
|
739
|
-
dom = spec.createItem.call(inst, serializeApi, box);
|
|
740
|
-
}
|
|
741
|
-
else if (typeof spec.serializeItem === 'function') {
|
|
742
|
-
// IR-homologous schedule (v0.1.7): same Direct body as fat createItem.
|
|
743
|
-
dom = spec.serializeItem.call(inst, serializeApi, box);
|
|
745
|
+
raw = '';
|
|
744
746
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
dom = serializeRowFromKernel(inst, spec.rowKernel, box, k);
|
|
748
|
-
}
|
|
749
|
-
if (dom) {
|
|
750
|
-
// SSR only: serialize key into HTML for hydrate/debug. Direct client does not write this attr.
|
|
751
|
-
if (dom.__kind === 'el' && !dom.__rawOuter)
|
|
752
|
-
serializeApi.attr(dom, 'data-vmz-key', String(k));
|
|
753
|
-
frag.appendChild(dom);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
return frag;
|
|
747
|
+
serializeApi.setHtml(el, raw);
|
|
748
|
+
}, bindingId);
|
|
757
749
|
},
|
|
758
750
|
component(hostInst, nameOrCtor, props, client) {
|
|
759
751
|
const name = typeof nameOrCtor === 'function' ? nameOrCtor.__vmzTag || nameOrCtor.name || 'Component' : nameOrCtor;
|
|
@@ -761,7 +753,6 @@ const serializeApi = {
|
|
|
761
753
|
if (!Ctor) {
|
|
762
754
|
return serializeUnknownComponentNode(name);
|
|
763
755
|
}
|
|
764
|
-
/** @type {Record<string, any>} */
|
|
765
756
|
const resolved = {};
|
|
766
757
|
for (const [k, v] of Object.entries(props || {})) {
|
|
767
758
|
const onKey = typeof v === 'function' ? eventPropHandlerName(k) : null;
|
|
@@ -797,7 +788,6 @@ const serializeApi = {
|
|
|
797
788
|
planSchema: plan?.schema || null,
|
|
798
789
|
planRootIds: plan?.root_ids || [],
|
|
799
790
|
};
|
|
800
|
-
/** @type {Record<string, string>} */
|
|
801
791
|
const attrs = {
|
|
802
792
|
'data-vmz': name,
|
|
803
793
|
'data-vmz-island': name,
|
|
@@ -828,7 +818,6 @@ const serializeApi = {
|
|
|
828
818
|
serializeApi._inst = child;
|
|
829
819
|
try {
|
|
830
820
|
const node = Ctor.__vmzCreate.call(child, serializeApi);
|
|
831
|
-
/** @type {Record<string, string>} */
|
|
832
821
|
const attrs = { 'data-vmz': name };
|
|
833
822
|
const boxStyle = directHostBoxStyleAttr(name, Ctor);
|
|
834
823
|
if (boxStyle)
|
|
@@ -853,14 +842,27 @@ const serializeApi = {
|
|
|
853
842
|
};
|
|
854
843
|
/**
|
|
855
844
|
* Serialize-tree attr write (SSR).
|
|
856
|
-
* @param {any} el
|
|
857
|
-
* @param {string} name
|
|
858
|
-
* @param {any} value
|
|
859
845
|
*/
|
|
860
846
|
function applySerializeAttr(el, name, value) {
|
|
861
847
|
if (!el || el.__kind !== 'el')
|
|
862
848
|
return;
|
|
863
849
|
const key = name === 'className' ? 'class' : name;
|
|
850
|
+
if (key === 'class') {
|
|
851
|
+
const s = mergeClassParts(value);
|
|
852
|
+
if (s)
|
|
853
|
+
el.attrs[key] = s;
|
|
854
|
+
else
|
|
855
|
+
delete el.attrs[key];
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
if (key === 'style') {
|
|
859
|
+
const s = mergeStyleParts(value);
|
|
860
|
+
if (s)
|
|
861
|
+
el.attrs[key] = s;
|
|
862
|
+
else
|
|
863
|
+
delete el.attrs[key];
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
864
866
|
if (BOOLEAN_HTML_ATTRS.has(String(key).toLowerCase())) {
|
|
865
867
|
if (value === false || value == null || value === '')
|
|
866
868
|
delete el.attrs[key];
|
|
@@ -876,9 +878,6 @@ function applySerializeAttr(el, name, value) {
|
|
|
876
878
|
/**
|
|
877
879
|
* resume: attach to existing Island DOM without re-running construct structure or onMount.
|
|
878
880
|
* Consumes ResumeEntry product (`data-vmz-resume`) derived from the same Execution Plan.
|
|
879
|
-
* @param {new (props?: object) => any} Component
|
|
880
|
-
* @param {HTMLElement} container
|
|
881
|
-
* @param {{ props?: object, state?: Record<string, unknown>, strategy?: string } | null} [slice]
|
|
882
881
|
*/
|
|
883
882
|
export async function resume(Component, container, slice = null) {
|
|
884
883
|
if (typeof document === 'undefined') {
|
|
@@ -916,7 +915,7 @@ export async function resume(Component, container, slice = null) {
|
|
|
916
915
|
const inst = createInstance(Component, props);
|
|
917
916
|
if (parsed.state)
|
|
918
917
|
applyPreservedState(inst, parsed.state);
|
|
919
|
-
// Intentionally never call onMount
|
|
918
|
+
// Intentionally never call onMount ??SSR already completed that work.
|
|
920
919
|
if (Component.__vmzDirect && typeof Component.__vmzCreate === 'function') {
|
|
921
920
|
if (!hasMeaningfulChild(container)) {
|
|
922
921
|
const node = runDirectCreate(Component, inst);
|
|
@@ -942,7 +941,6 @@ export async function resume(Component, container, slice = null) {
|
|
|
942
941
|
/**
|
|
943
942
|
* Resume all `[data-vmz-island]` hosts (prefer ResumeEntry / EventEntry over mount).
|
|
944
943
|
* Event strategy islands wait for the DOM event before attach (lazy EventEntry).
|
|
945
|
-
* @param {ParentNode} [root]
|
|
946
944
|
*/
|
|
947
945
|
export function resumeIslands(root = globalThis.document) {
|
|
948
946
|
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
@@ -965,7 +963,6 @@ export function resumeIslands(root = globalThis.document) {
|
|
|
965
963
|
/**
|
|
966
964
|
* EventEntry attach: only wire `client:event` / `client:event:*` islands.
|
|
967
965
|
* Idle/load/visible ResumeEntries are left alone (static shell can defer framework work).
|
|
968
|
-
* @param {ParentNode} [root]
|
|
969
966
|
*/
|
|
970
967
|
export function attachEventEntries(root = globalThis.document) {
|
|
971
968
|
if (!root || typeof root.querySelectorAll !== 'function') {
|
|
@@ -1001,22 +998,15 @@ export function attachEventEntries(root = globalThis.document) {
|
|
|
1001
998
|
* - `beginBranchScope()` moves one top-level SSR node into an isolated pool so
|
|
1002
999
|
* ifBlock branch create cannot steal parent siblings (Drawer / Button hosts).
|
|
1003
1000
|
*
|
|
1004
|
-
* @param {DocumentFragment} pool
|
|
1005
|
-
* @param {Element} rootEl
|
|
1006
1001
|
*/
|
|
1007
1002
|
function createResumeAdopt(pool, rootEl) {
|
|
1008
1003
|
const used = new WeakSet();
|
|
1009
|
-
/** @type {DocumentFragment[]} */
|
|
1010
1004
|
const scopeStack = [pool];
|
|
1011
|
-
/**
|
|
1012
|
-
* @param {Node} root
|
|
1013
|
-
* @param {(n: Text) => void} visit
|
|
1014
|
-
*/
|
|
1015
1005
|
const walkTexts = (root, visit) => {
|
|
1016
1006
|
if (!root)
|
|
1017
1007
|
return;
|
|
1018
1008
|
if (root.nodeType === 3) {
|
|
1019
|
-
visit(
|
|
1009
|
+
visit(root);
|
|
1020
1010
|
return;
|
|
1021
1011
|
}
|
|
1022
1012
|
if (root.nodeType !== 1)
|
|
@@ -1032,7 +1022,7 @@ function createResumeAdopt(pool, rootEl) {
|
|
|
1032
1022
|
if (k != null && n.__vmzKey == null)
|
|
1033
1023
|
n.__vmzKey = k;
|
|
1034
1024
|
}
|
|
1035
|
-
// Private child pool
|
|
1025
|
+
// Private child pool ??never dump into the parent/global pool (that let
|
|
1036
1026
|
// if branches reclaim Drawer/sibling hosts parked as uncles).
|
|
1037
1027
|
const childPool = document.createDocumentFragment();
|
|
1038
1028
|
while (n.firstChild)
|
|
@@ -1040,25 +1030,22 @@ function createResumeAdopt(pool, rootEl) {
|
|
|
1040
1030
|
n.__vmzResumePool = childPool;
|
|
1041
1031
|
return n;
|
|
1042
1032
|
};
|
|
1043
|
-
/** @returns {Generator<Element>} */
|
|
1044
1033
|
function* elementCandidates() {
|
|
1045
1034
|
const scope = currentScope();
|
|
1046
1035
|
if (scope === pool && rootEl && !used.has(rootEl))
|
|
1047
1036
|
yield rootEl;
|
|
1048
|
-
// Snapshot
|
|
1037
|
+
// Snapshot ??adopt may move nodes out of scope while iterating.
|
|
1049
1038
|
const kids = [...scope.childNodes];
|
|
1050
1039
|
for (const n of kids) {
|
|
1051
|
-
if (n.nodeType === 1 && !used.has(
|
|
1052
|
-
yield
|
|
1040
|
+
if (n.nodeType === 1 && !used.has(n)) {
|
|
1041
|
+
yield n;
|
|
1053
1042
|
}
|
|
1054
1043
|
}
|
|
1055
1044
|
}
|
|
1056
|
-
/** @returns {Generator<Text>} */
|
|
1057
1045
|
function* textCandidates() {
|
|
1058
1046
|
const scope = currentScope();
|
|
1059
1047
|
const kids = [...scope.childNodes];
|
|
1060
1048
|
for (const n of kids) {
|
|
1061
|
-
/** @type {Text[]} */
|
|
1062
1049
|
const found = [];
|
|
1063
1050
|
walkTexts(n, (t) => {
|
|
1064
1051
|
if (!used.has(t))
|
|
@@ -1087,7 +1074,6 @@ function createResumeAdopt(pool, rootEl) {
|
|
|
1087
1074
|
noteDomCreate();
|
|
1088
1075
|
return document.createTextNode(value == null ? '' : String(value));
|
|
1089
1076
|
};
|
|
1090
|
-
/** Reclaim SSR `<div data-vmz="Name">` hosts for nested Direct components. */
|
|
1091
1077
|
const componentHost = (name) => {
|
|
1092
1078
|
const want = String(name || '');
|
|
1093
1079
|
for (const el of elementCandidates()) {
|
|
@@ -1119,13 +1105,12 @@ function createResumeAdopt(pool, rootEl) {
|
|
|
1119
1105
|
/**
|
|
1120
1106
|
* Isolate the next top-level SSR sibling as the only candidates for an
|
|
1121
1107
|
* if/else branch create (commercial Card: Empty branch must not adopt Drawer).
|
|
1122
|
-
* @returns {() => void} end callback
|
|
1123
1108
|
*/
|
|
1124
1109
|
const beginBranchScope = () => {
|
|
1125
1110
|
const parent = currentScope();
|
|
1126
1111
|
const branchPool = document.createDocumentFragment();
|
|
1127
1112
|
for (const n of [...parent.childNodes]) {
|
|
1128
|
-
if (n.nodeType === 1 && !used.has(
|
|
1113
|
+
if (n.nodeType === 1 && !used.has(n)) {
|
|
1129
1114
|
branchPool.appendChild(n);
|
|
1130
1115
|
break;
|
|
1131
1116
|
}
|
|
@@ -1151,9 +1136,6 @@ function createResumeAdopt(pool, rootEl) {
|
|
|
1151
1136
|
}
|
|
1152
1137
|
/**
|
|
1153
1138
|
* Adopt existing Island DOM while running the same `__vmzCreate` schedule (resume).
|
|
1154
|
-
* @param {new (props?: object) => any} Component
|
|
1155
|
-
* @param {object} inst
|
|
1156
|
-
* @param {Element} container
|
|
1157
1139
|
*/
|
|
1158
1140
|
function runDirectResume(Component, inst, container) {
|
|
1159
1141
|
const rootEl = [...container.childNodes].find((n) => n.nodeType === 1 || (n.nodeType === 3 && String(n.textContent).trim() !== ''));
|
|
@@ -1187,17 +1169,10 @@ function runDirectResume(Component, inst, container) {
|
|
|
1187
1169
|
pool.removeChild(pool.firstChild);
|
|
1188
1170
|
}
|
|
1189
1171
|
}
|
|
1190
|
-
/**
|
|
1191
|
-
* @param {new (props?: object) => any} Component
|
|
1192
|
-
* @param {HTMLElement} container
|
|
1193
|
-
* @param {object} [props]
|
|
1194
|
-
* @param {{ preserveState?: boolean | Record<string, unknown>, skipOnMount?: boolean }} [opts]
|
|
1195
|
-
*/
|
|
1196
1172
|
export async function hydrate(Component, container, props = {}, opts = {}) {
|
|
1197
1173
|
if (typeof document === 'undefined') {
|
|
1198
1174
|
throw new Error('vmz:dom hydrate() requires a document (browser)');
|
|
1199
1175
|
}
|
|
1200
|
-
/** @type {Record<string, unknown> | null} */
|
|
1201
1176
|
let preserved = null;
|
|
1202
1177
|
if (opts.preserveState && typeof opts.preserveState === 'object') {
|
|
1203
1178
|
preserved = opts.preserveState;
|
|
@@ -1241,9 +1216,6 @@ export async function hydrate(Component, container, props = {}, opts = {}) {
|
|
|
1241
1216
|
}
|
|
1242
1217
|
return inst;
|
|
1243
1218
|
}
|
|
1244
|
-
/**
|
|
1245
|
-
* @param {ParentNode} [root]
|
|
1246
|
-
*/
|
|
1247
1219
|
export function hydrateIslands(root = globalThis.document) {
|
|
1248
1220
|
// resume: hydrateIslands is an alias for resumeIslands (same Plan attach).
|
|
1249
1221
|
return resumeIslands(root);
|