@vmz/core 0.0.2 → 0.0.3

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 CHANGED
@@ -31,7 +31,8 @@ state write
31
31
  -> direct patch / switch / reconcile
32
32
  ```
33
33
 
34
- There is no default detour through “execute every component that might matter, build virtual nodes, then compare them.” If analysis must widen, it widens to a safe region and should preserve the reason.
34
+ There is no default detour through “execute every component that might matter, build virtual nodes, then compare them.”
35
+ If analysis must widen, it widens to a safe region and should preserve the reason.
35
36
 
36
37
  ## More than DOM updates
37
38
 
@@ -41,7 +42,8 @@ There is no default detour through “execute every component that might matter,
41
42
  - **Resumption:** the browser attaches to server-produced work at the smallest reachable boundary.
42
43
  - **Zero-JS delivery:** pages with no interactive requirement do not need an eager framework shell.
43
44
 
44
- The runtime should not grow a second compiler made of reflection, string dependencies, or generic proxies. Its quality comes from faithfully executing the generated plan while keeping the production surface focused.
45
+ The runtime should not grow a second compiler made of reflection, string dependencies, or generic proxies. Its quality
46
+ comes from faithfully executing the generated plan while keeping the production surface focused.
45
47
 
46
48
  ## License
47
49
 
package/dist/dom.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * VMZ DOM / SSR runtime — precise patches, no VDOM diff.
3
3
  *
4
- * Design: 规划设计/vmz/04 · Gate 3 (no production `render()`)
5
4
  *
6
5
  * Direct components expose `__vmzCreate` / `__vmzSerialize` / `__vmzPlan`.
7
6
  * Mount, SSR, hydrate, and resume all run that same schedule.
@@ -14,7 +13,7 @@ export declare function __vmzTraceEnable(on?: boolean): void;
14
13
  export declare function __vmzPrecisionReset(): void;
15
14
  export declare function __vmzTraceReset(): void;
16
15
  /**
17
- * X5 StableId event snapshot (`vmz.dx.trace.v0` shape without schema stamp —
16
+ * StableId event snapshot (`vmz.dx.trace.v0` shape without schema stamp —
18
17
  * host may wrap via ingestRuntimeTrace).
19
18
  * @returns {{ schema: string, events: typeof traceBuf.events, status: string }}
20
19
  */
@@ -58,14 +57,14 @@ export declare function renderToString(Component: any, props?: {}): Promise<any>
58
57
  export declare function renderToStream(Component: any, props?: {}, opts?: {}): AsyncGenerator<any, void, unknown>;
59
58
  /**
60
59
  * Mount once; later updates are dep patches only (never re-run structure).
61
- * Requires compiler `__vmzCreate` (Gate 3 — no blueprint fallback).
60
+ * Requires compiler `__vmzCreate` (production Direct emit — no blueprint fallback).
62
61
  * @param {new (props?: object) => any} Component
63
62
  * @param {Element} container
64
63
  * @param {object} [props]
65
64
  */
66
65
  export declare function mount(Component: any, container: any, props?: {}): Promise<any>;
67
66
  /**
68
- * Snapshot plain state/prop field values for Island HMR (N4.3).
67
+ * Snapshot plain state/prop field values for Island HMR (session).
69
68
  * @param {object} inst
70
69
  * @returns {Record<string, unknown> | null}
71
70
  */
@@ -76,7 +75,7 @@ export declare function snapshotInstanceState(inst: any): {};
76
75
  */
77
76
  export declare function applyPreservedState(inst: any, state: any): void;
78
77
  /**
79
- * L5: attach to existing Island DOM without re-running construct structure or onMount.
78
+ * resume: attach to existing Island DOM without re-running construct structure or onMount.
80
79
  * Consumes ResumeEntry product (`data-vmz-resume`) derived from the same Execution Plan.
81
80
  * @param {new (props?: object) => any} Component
82
81
  * @param {HTMLElement} container
@@ -105,12 +104,12 @@ export declare function hydrate(Component: any, container: any, props?: {}, opts
105
104
  /**
106
105
  * Tear down binders and stop patches. Safe to call more than once.
107
106
  * Field writes after destroy no longer update DOM (values may still change).
108
- * L4: also dispose owned DOM trees (child __vmzInst / region __vmzDispose).
107
+ *: also dispose owned DOM trees (child __vmzInst / region __vmzDispose).
109
108
  * @param {object} inst
110
109
  */
111
110
  export declare function destroy(inst: any): void;
112
111
  /**
113
- * L4: walk a DOM subtree and run lifetime dispose hooks + nested instance destroy.
112
+ *: walk a DOM subtree and run lifetime dispose hooks + nested instance destroy.
114
113
  * Does not mark the *calling* parent destroyed; safe from destroy(inst).
115
114
  * @param {Node | null | undefined} root
116
115
  */
@@ -135,7 +134,6 @@ export declare function __vmzCancelTasks(inst: any): void;
135
134
  export declare function __vmzTaskStatus(inst: any, key: any): any;
136
135
  /**
137
136
  * Mark a plain object as intentionally shared across ownership boundaries.
138
- * Suppresses cross-component shared diagnostics (规划设计/vmz/13 §7.3).
139
137
  * @param {any} value
140
138
  */
141
139
  export declare function __vmzAllowShared(value: any): any;
@@ -167,7 +165,6 @@ export declare function __vmzReadPath(inst: any, root: any, segs: any): any;
167
165
  */
168
166
  export declare function __vmzWritePathLogical(inst: any, root: any, segs: any, kind: any, rhs: any): any;
169
167
  /**
170
- * Compiler-inserted path write barrier (规划设计/vmz/13 §7.3).
171
168
  * Mutates a plain owned object/array and schedules the same path notice Proxy would.
172
169
  *
173
170
  * Root-array index assigns (`tags[0] = x`) notify as field replace (structural),
@@ -193,7 +190,7 @@ export declare function __vmzWritePath(inst: any, root: any, segs: any, value: a
193
190
  */
194
191
  export declare function __vmzArrayMutate(inst: any, root: any, baseSegs: any, method: any, args: any): any;
195
192
  /**
196
- * L4 WriteBarrier: true when value is an owned plain object with path barriers (no Proxy).
193
+ * WriteBarrier: true when value is an owned plain object with path barriers (no Proxy).
197
194
  * @param {any} value
198
195
  */
199
196
  export declare function __vmzIsWriteBarrierOwned(value: any): boolean;
package/dist/dom.js CHANGED
@@ -2,7 +2,6 @@
2
2
  /**
3
3
  * VMZ DOM / SSR runtime — precise patches, no VDOM diff.
4
4
  *
5
- * Design: 规划设计/vmz/04 · Gate 3 (no production `render()`)
6
5
  *
7
6
  * Direct components expose `__vmzCreate` / `__vmzSerialize` / `__vmzPlan`.
8
7
  * Mount, SSR, hydrate, and resume all run that same schedule.
@@ -12,7 +11,6 @@
12
11
  const components = Object.create(null);
13
12
  /**
14
13
  * Precision lab counters (test / MCP / benchmarks — not a user API).
15
- * Design: 规划设计/vmz/12 §7
16
14
  * Primary keys: BindingId (IR). `*ByDep` is transitional stable-string adapter.
17
15
  */
18
16
  const precision = {
@@ -35,7 +33,7 @@ const precision = {
35
33
  /** @type {Record<string, number>} BindingId → count */
36
34
  patchesByBinding: Object.create(null),
37
35
  };
38
- /** X5: optional StableId event ring (enabled with precision or __vmzTraceEnable). */
36
+ /** optional StableId event ring (enabled with precision or __vmzTraceEnable). */
39
37
  const TRACE_CAP = 256;
40
38
  /** @type {{ enabled: boolean, events: Array<{ kind: string, stableId: { kind: string, id: string }, dep?: string|null, t?: number, chunkId?: string|null }> }} */
41
39
  const traceBuf = {
@@ -86,7 +84,7 @@ export function __vmzTraceReset() {
86
84
  traceBuf.events = [];
87
85
  }
88
86
  /**
89
- * X5 StableId event snapshot (`vmz.dx.trace.v0` shape without schema stamp —
87
+ * StableId event snapshot (`vmz.dx.trace.v0` shape without schema stamp —
90
88
  * host may wrap via ingestRuntimeTrace).
91
89
  * @returns {{ schema: string, events: typeof traceBuf.events, status: string }}
92
90
  */
@@ -117,7 +115,7 @@ export function __vmzPrecisionSnapshot() {
117
115
  };
118
116
  }
119
117
  /**
120
- * @param {() => any} fn
118
+ * @param { => any} fn
121
119
  * @param {string | null} [depKey]
122
120
  * @param {number | string | null} [bindingId]
123
121
  */
@@ -173,9 +171,9 @@ export async function renderToString(Component, props = {}) {
173
171
  if (typeof inst.onMount === 'function') {
174
172
  await inst.onMount();
175
173
  }
176
- // Gate 3: SSR only via Direct serialize schedule — never `render()`.
174
+ // production Direct emit: SSR only via Direct serialize schedule — never `render`.
177
175
  if (!(Component && Component.__vmzDirect && typeof Component.__vmzCreate === 'function')) {
178
- throw new Error(`vmz:dom renderToString() requires __vmzCreate (Direct); blueprint render() removed (Gate 3)`);
176
+ throw new Error(`vmz:dom renderToString() requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
179
177
  }
180
178
  const root = await runDirectSerializeTreeWithMounts(Component, inst);
181
179
  return flattenSerializeNode(root);
@@ -202,7 +200,7 @@ export async function* renderToStream(Component, props = {}, opts = {}) {
202
200
  if (aborted())
203
201
  return;
204
202
  if (!(Component && Component.__vmzDirect && typeof Component.__vmzCreate === 'function')) {
205
- throw new Error(`vmz:dom renderToStream() requires __vmzCreate (Direct); blueprint render() removed (Gate 3)`);
203
+ throw new Error(`vmz:dom renderToStream() requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
206
204
  }
207
205
  const root = await runDirectSerializeTreeWithMounts(Component, inst);
208
206
  if (aborted())
@@ -216,13 +214,13 @@ export async function* renderToStream(Component, props = {}, opts = {}) {
216
214
  }
217
215
  }
218
216
  finally {
219
- // Abort and normal completion both dispose the SSR instance (L4 lifetime).
217
+ // Abort and normal completion both dispose the SSR instance (lifetime).
220
218
  destroy(inst);
221
219
  }
222
220
  }
223
221
  /**
224
222
  * Mount once; later updates are dep patches only (never re-run structure).
225
- * Requires compiler `__vmzCreate` (Gate 3 — no blueprint fallback).
223
+ * Requires compiler `__vmzCreate` (production Direct emit — no blueprint fallback).
226
224
  * @param {new (props?: object) => any} Component
227
225
  * @param {Element} container
228
226
  * @param {object} [props]
@@ -250,7 +248,7 @@ export async function mount(Component, container, props = {}) {
250
248
  return inst;
251
249
  }
252
250
  /**
253
- * Nested Direct `component()` schedules child onMount asynchronously; drain before return
251
+ * Nested Direct `component` schedules child onMount asynchronously; drain before return
254
252
  * so SSR/hydrate callers see post-mount DOM (e.g. UserCard Ada, not Loading…).
255
253
  * @param {object} inst
256
254
  */
@@ -275,7 +273,7 @@ async function settlePendingChildMounts(inst) {
275
273
  }
276
274
  }
277
275
  /**
278
- * Direct create only (Gate 3).
276
+ * Direct create only (production Direct emit).
279
277
  * @param {new (props?: object) => any} Component
280
278
  * @param {object} inst
281
279
  */
@@ -283,7 +281,7 @@ async function createFromComponent(Component, inst) {
283
281
  if (Component && Component.__vmzDirect && typeof Component.__vmzCreate === 'function') {
284
282
  return runDirectCreate(Component, inst);
285
283
  }
286
- throw new Error(`vmz:dom mount requires __vmzCreate (Direct); blueprint render() removed (Gate 3)`);
284
+ throw new Error(`vmz:dom mount requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
287
285
  }
288
286
  /**
289
287
  * @param {new (props?: object) => any} Component
@@ -299,7 +297,7 @@ function runDirectCreate(Component, inst) {
299
297
  }
300
298
  }
301
299
  /**
302
- * L3 SSR: run the same __vmzCreate schedule against a serialize host (no render()).
300
+ * SSR: run the same __vmzCreate schedule against a serialize host (no render).
303
301
  * @param {new (props?: object) => any} Component
304
302
  * @param {object} inst
305
303
  */
@@ -609,7 +607,7 @@ const serializeApi = {
609
607
  resolved[k] = v;
610
608
  }
611
609
  if (client) {
612
- // L5: Island SSR includes body + ResumeEntry slice (same Direct schedule).
610
+ // resume: Island SSR includes body + ResumeEntry slice (same Direct schedule).
613
611
  const child = serializeApi._ssrChildInstance(Ctor, resolved);
614
612
  let body = null;
615
613
  if (Ctor.__vmzDirect && typeof Ctor.__vmzCreate === 'function') {
@@ -683,15 +681,15 @@ const serializeApi = {
683
681
  const directApi = {
684
682
  /** @type {object | null} */
685
683
  _inst: null,
686
- /** @type {Array<{ deps: string[], fn: () => any, bindingId?: number|string|null }> | null} */
684
+ /** @type {Array<{ deps: string[], fn: => any, bindingId?: number|string|null }> | null} */
687
685
  _branchBinds: null,
688
- /** @type {Array<() => void> | null} */
686
+ /** @type {Array< => void> | null} */
689
687
  _itemPatches: null,
690
688
  /**
691
- * Active keyed-each context (P0/P1): item binds + event delegation.
689
+ * Active keyed-each context (/): item binds + event delegation.
692
690
  * @type {null | {
693
- * noteItemBind: (bindingId: number|string|null, deps: string[], fn: () => void) => void,
694
- * needDelegate: (type: string) => void,
691
+ * noteItemBind: (bindingId: number|string|null, deps: string[], fn: => void) => void,
692
+ * needDelegate: (type: string) => void,
695
693
  * }}
696
694
  */
697
695
  _eachCtx: null,
@@ -735,9 +733,9 @@ const directApi = {
735
733
  * @param {object} inst
736
734
  * @param {number|string|null} bindingId
737
735
  * @param {string[]} deps
738
- * @param {() => any} get
736
+ * @param { => any} get
739
737
  * @param {Text} textNode
740
- * @param {{ stable: string[], branches: Array<{ cond?: () => any, deps: string[] }> } | null | undefined} [cf]
738
+ * @param {{ stable: string[], branches: Array<{ cond?: => any, deps: string[] }> } | null | undefined} [cf]
741
739
  */
742
740
  bindText(inst, bindingId, deps, get, textNode, cf) {
743
741
  wireDirectBind(inst, bindingId, deps, get, (raw) => {
@@ -748,10 +746,10 @@ const directApi = {
748
746
  * @param {object} inst
749
747
  * @param {number|string|null} bindingId
750
748
  * @param {string[]} deps
751
- * @param {() => any} get
749
+ * @param { => any} get
752
750
  * @param {Element} el
753
751
  * @param {string} name
754
- * @param {{ stable: string[], branches: Array<{ cond?: () => any, deps: string[] }> } | null | undefined} [cf]
752
+ * @param {{ stable: string[], branches: Array<{ cond?: => any, deps: string[] }> } | null | undefined} [cf]
755
753
  */
756
754
  bindAttr(inst, bindingId, deps, get, el, name, cf) {
757
755
  wireDirectBind(inst, bindingId, deps, get, (raw) => {
@@ -774,9 +772,9 @@ const directApi = {
774
772
  * @param {object} inst
775
773
  * @param {number|string|null} bindingId
776
774
  * @param {string[]} deps
777
- * @param {() => any} get
775
+ * @param { => any} get
778
776
  * @param {Element} el
779
- * @param {{ stable: string[], branches: Array<{ cond?: () => any, deps: string[] }> } | null | undefined} [cf]
777
+ * @param {{ stable: string[], branches: Array<{ cond?: => any, deps: string[] }> } | null | undefined} [cf]
780
778
  */
781
779
  bindHtml(inst, bindingId, deps, get, el, cf) {
782
780
  wireDirectBind(inst, bindingId, deps, get, (raw) => {
@@ -811,7 +809,7 @@ const directApi = {
811
809
  if (isEventEntryStrategy(String(client))) {
812
810
  host.setAttribute('data-vmz-entry', 'event');
813
811
  }
814
- // L5: resume on schedule; EventEntry may lazy-load chunk via __vmzLoadComponent.
812
+ // resume: resume on schedule; EventEntry may lazy-load chunk via __vmzLoadComponent.
815
813
  scheduleClientOn(host, String(client), async () => {
816
814
  const Ctor = await resolveComponent(name);
817
815
  if (!Ctor)
@@ -848,7 +846,7 @@ const directApi = {
848
846
  * @param {object} inst
849
847
  * @param {number|string|null} bindingId
850
848
  * @param {string[]} deps
851
- * @param {Array<{ cond?: () => any, create: (api: typeof directApi) => Node }>} branches
849
+ * @param {Array<{ cond?: => any, create: (api: typeof directApi) => Node }>} branches
852
850
  * @param {number|string|null} [regionId]
853
851
  */
854
852
  ifBlock(inst, bindingId, deps, branches, regionId = null) {
@@ -859,7 +857,7 @@ const directApi = {
859
857
  host.setAttribute('data-vmz-region', String(regionId));
860
858
  /** @type {Array<Node | null>} */
861
859
  const cached = branches.map(() => null);
862
- /** @type {Array<Array<{ deps: string[], fn: () => any, bindingId?: number|string|null }>>} */
860
+ /** @type {Array<Array<{ deps: string[], fn: => any, bindingId?: number|string|null }>>} */
863
861
  const branchBinds = branches.map(() => []);
864
862
  let active = -1;
865
863
  let gen = 0;
@@ -945,7 +943,7 @@ const directApi = {
945
943
  registerBind(inst, deps || [], apply, bindingId);
946
944
  if (directApi._itemPatches)
947
945
  directApi._itemPatches.push(apply);
948
- // L4: parent destroy disposes all cached branch trees (pause ≠ destroy on switch).
946
+ // parent destroy disposes all cached branch trees (pause ≠ destroy on switch).
949
947
  host.__vmzDispose = () => {
950
948
  for (let i = 0; i < cached.length; i++) {
951
949
  unwireBranch(i);
@@ -960,11 +958,11 @@ const directApi = {
960
958
  },
961
959
  /**
962
960
  * Direct keyed each — no blueprint `kind: "each"` dispatch.
963
- * P0/P1: Set/Map + Fragment batch insert; item-local binds; host selected; event delegate.
961
+ * /: Set/Map + Fragment batch insert; item-local binds; host selected; event delegate.
964
962
  * @param {object} inst
965
963
  * @param {number|string|null} bindingId
966
964
  * @param {string[]} deps
967
- * @param {{ as?: string, list: () => any, key?: (box: {item:any,index:number}) => any, createItem: (api: typeof directApi, box: {item:any,index:number}) => Node }} spec
965
+ * @param {{ as?: string, list: => any, key?: (box: {item:any,index:number}) => any, createItem: (api: typeof directApi, box: {item:any,index:number}) => Node }} spec
968
966
  * @param {number|string|null} [regionId]
969
967
  */
970
968
  eachBlock(inst, bindingId, deps, spec, regionId = null) {
@@ -975,10 +973,10 @@ const directApi = {
975
973
  const frag = document.createDocumentFragment();
976
974
  frag.appendChild(start);
977
975
  frag.appendChild(end);
978
- /** @type {Map<any, { box: { item: any, index: number }, dom: Node, patches: Array<() => void> }>} */
976
+ /** @type {Map<any, { box: { item: any, index: number }, dom: Node, patches: Array< => void> }>} */
979
977
  const keyed = new Map();
980
978
  let gen = 0;
981
- /** @type {Map<string, () => void>} */
979
+ /** @type {Map<string, => void>} */
982
980
  const listDispatchers = new Map();
983
981
  /** @type {Set<string>} */
984
982
  const hostDispatchers = new Set();
@@ -1227,7 +1225,6 @@ const directApi = {
1227
1225
  const box = { item: list[i], index: i };
1228
1226
  const k = itemKey(box);
1229
1227
  if (seen.has(k)) {
1230
- console.error(`vmz:dom each: duplicate key ${String(k)} — undefined reuse; fix the key expression (规划设计/vmz/10 §7)`);
1231
1228
  }
1232
1229
  seen.add(k);
1233
1230
  let entry = keyed.get(k);
@@ -1318,7 +1315,7 @@ const directApi = {
1318
1315
  entry.box.index = i;
1319
1316
  tagItemPatches(entry.patches, i);
1320
1317
  for (const p of entry.patches) {
1321
- // Leaf BindingId patches are owned by list/host dispatchers (P1).
1318
+ // Leaf BindingId patches are owned by list/host dispatchers .
1322
1319
  if (p.__vmzBindingId != null)
1323
1320
  continue;
1324
1321
  if (patchHasBindingId(inst, p))
@@ -1340,7 +1337,7 @@ const directApi = {
1340
1337
  /**
1341
1338
  * @param {object} inst
1342
1339
  * @param {string[]} deps
1343
- * @param {() => any} fn
1340
+ * @param { => any} fn
1344
1341
  * @param {number|string|null|undefined} bindingId
1345
1342
  */
1346
1343
  function trackDirectBind(inst, deps, fn, bindingId = null) {
@@ -1350,7 +1347,7 @@ function trackDirectBind(inst, deps, fn, bindingId = null) {
1350
1347
  directApi._itemPatches.push(fn);
1351
1348
  return;
1352
1349
  }
1353
- // P1: item binds stay on entry.patches; eachBlock registers one dispatcher per BindingId.
1350
+ // item binds stay on entry.patches; eachBlock registers one dispatcher per BindingId.
1354
1351
  if (directApi._itemPatches) {
1355
1352
  fn.__vmzItemLocal = true;
1356
1353
  directApi._itemPatches.push(fn);
@@ -1365,9 +1362,9 @@ function trackDirectBind(inst, deps, fn, bindingId = null) {
1365
1362
  * @param {object} inst
1366
1363
  * @param {number|string|null} bindingId
1367
1364
  * @param {string[]} deps
1368
- * @param {() => any} get
1365
+ * @param { => any} get
1369
1366
  * @param {(raw: any) => void} write
1370
- * @param {{ stable: string[], branches: Array<{ cond?: () => any, deps: string[] }> } | null | undefined} [cf]
1367
+ * @param {{ stable: string[], branches: Array<{ cond?: => any, deps: string[] }> } | null | undefined} [cf]
1371
1368
  */
1372
1369
  function wireDirectBind(inst, bindingId, deps, get, write, cf) {
1373
1370
  let activeBranch = -1;
@@ -1416,7 +1413,7 @@ function wireDirectBind(inst, bindingId, deps, get, write, cf) {
1416
1413
  const branch = cf.branches[next];
1417
1414
  const nextDeps = [...(cf.stable || []), ...((branch && branch.deps) || [])];
1418
1415
  const uniq = [...new Set(nextDeps)];
1419
- // Item-local binds must never enter the global binder table (P1 / jfb select).
1416
+ // Item-local binds must never enter the global binder table ( / jfb select).
1420
1417
  if (apply.__vmzItemLocal) {
1421
1418
  liveDeps = uniq;
1422
1419
  return;
@@ -1475,7 +1472,7 @@ function eachHostApi(start, end) {
1475
1472
  };
1476
1473
  }
1477
1474
  /**
1478
- * Snapshot plain state/prop field values for Island HMR (N4.3).
1475
+ * Snapshot plain state/prop field values for Island HMR (session).
1479
1476
  * @param {object} inst
1480
1477
  * @returns {Record<string, unknown> | null}
1481
1478
  */
@@ -1515,7 +1512,7 @@ export function applyPreservedState(inst, state) {
1515
1512
  }
1516
1513
  }
1517
1514
  /**
1518
- * L5: attach to existing Island DOM without re-running construct structure or onMount.
1515
+ * resume: attach to existing Island DOM without re-running construct structure or onMount.
1519
1516
  * Consumes ResumeEntry product (`data-vmz-resume`) derived from the same Execution Plan.
1520
1517
  * @param {new (props?: object) => any} Component
1521
1518
  * @param {HTMLElement} container
@@ -1565,14 +1562,14 @@ export async function resume(Component, container, slice = null) {
1565
1562
  }
1566
1563
  }
1567
1564
  else {
1568
- // Island leaf adopt: preserve Element identity (L5 nodeIdentity).
1565
+ // Island leaf adopt: preserve Element identity (resume nodeIdentity).
1569
1566
  const node = runDirectResume(Component, inst, container);
1570
1567
  if (node)
1571
1568
  inst.__vmzDomRoot = node;
1572
1569
  }
1573
1570
  }
1574
1571
  else {
1575
- throw new Error(`vmz:dom resume() requires __vmzCreate (Direct); blueprint render() removed (Gate 3)`);
1572
+ throw new Error(`vmz:dom resume() requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
1576
1573
  }
1577
1574
  container.__vmzInst = inst;
1578
1575
  container.__vmzResumed = true;
@@ -1628,7 +1625,7 @@ export function attachEventEntries(root = globalThis.document) {
1628
1625
  }
1629
1626
  }
1630
1627
  /**
1631
- * Adopt existing Island DOM while running the same `__vmzCreate` schedule (L5).
1628
+ * Adopt existing Island DOM while running the same `__vmzCreate` schedule (resume).
1632
1629
  * @param {new (props?: object) => any} Component
1633
1630
  * @param {object} inst
1634
1631
  * @param {Element} container
@@ -1712,9 +1709,9 @@ export async function hydrate(Component, container, props = {}, opts = {}) {
1712
1709
  if (preserved) {
1713
1710
  applyPreservedState(inst, preserved);
1714
1711
  }
1715
- // Gate 3: hydrate uses the same Direct schedule as resume (no render()).
1712
+ // production Direct emit: hydrate uses the same Direct schedule as resume (no render).
1716
1713
  if (!(Component && Component.__vmzDirect && typeof Component.__vmzCreate === 'function')) {
1717
- throw new Error(`vmz:dom hydrate() requires __vmzCreate (Direct); blueprint render() removed (Gate 3)`);
1714
+ throw new Error(`vmz:dom hydrate() requires __vmzCreate (Direct); blueprint render() removed (production Direct emit)`);
1718
1715
  }
1719
1716
  // Wire DOM + events BEFORE awaiting onMount. SSR shell is already visible; if we
1720
1717
  // wait on RPC/bootstrap first, buttons look real but have no listeners (dead UI).
@@ -1747,7 +1744,7 @@ export async function hydrate(Component, container, props = {}, opts = {}) {
1747
1744
  /**
1748
1745
  * Tear down binders and stop patches. Safe to call more than once.
1749
1746
  * Field writes after destroy no longer update DOM (values may still change).
1750
- * L4: also dispose owned DOM trees (child __vmzInst / region __vmzDispose).
1747
+ *: also dispose owned DOM trees (child __vmzInst / region __vmzDispose).
1751
1748
  * @param {object} inst
1752
1749
  */
1753
1750
  export function destroy(inst) {
@@ -1755,7 +1752,7 @@ export function destroy(inst) {
1755
1752
  return;
1756
1753
  inst.__vmzDestroyed = true;
1757
1754
  inst.__vmzFlushScheduled = false;
1758
- // L4 async cancel: abort in-flight tasks before tearing down DOM.
1755
+ // async cancel: abort in-flight tasks before tearing down DOM.
1759
1756
  __vmzCancelTasks(inst);
1760
1757
  if (inst.__vmzDomRoot) {
1761
1758
  disposeDomTree(inst.__vmzDomRoot);
@@ -1780,7 +1777,7 @@ export function destroy(inst) {
1780
1777
  }
1781
1778
  }
1782
1779
  /**
1783
- * L4: walk a DOM subtree and run lifetime dispose hooks + nested instance destroy.
1780
+ *: walk a DOM subtree and run lifetime dispose hooks + nested instance destroy.
1784
1781
  * Does not mark the *calling* parent destroyed; safe from destroy(inst).
1785
1782
  * @param {Node | null | undefined} root
1786
1783
  */
@@ -1819,7 +1816,7 @@ export function disposeDomTree(root) {
1819
1816
  * @param {ParentNode} [root]
1820
1817
  */
1821
1818
  export function hydrateIslands(root = globalThis.document) {
1822
- // L5: hydrateIslands is an alias for resumeIslands (same Plan attach).
1819
+ // resume: hydrateIslands is an alias for resumeIslands (same Plan attach).
1823
1820
  return resumeIslands(root);
1824
1821
  }
1825
1822
  export function scheduleClient(strategy, fn) {
@@ -1841,7 +1838,7 @@ function eventEntryType(strategy) {
1841
1838
  }
1842
1839
  function scheduleClientOn(el, strategy, fn) {
1843
1840
  const run = () => {
1844
- Promise.resolve(fn()).catch((err) => console.error('vmz:dom island', err));
1841
+ Promise.resolve(fn).catch((err) => console.error('vmz:dom island', err));
1845
1842
  };
1846
1843
  if (isEventEntryStrategy(strategy)) {
1847
1844
  if (!el || typeof el.addEventListener !== 'function') {
@@ -1918,7 +1915,7 @@ export function __vmzRunTask(inst, key, fn) {
1918
1915
  status: 'pending',
1919
1916
  };
1920
1917
  inst.__vmzTasks[k] = entry;
1921
- // Invoke synchronously so event handlers can call preventDefault() before
1918
+ // Invoke synchronously so event handlers can call preventDefault before
1922
1919
  // the browser continues the default action (form submit → native navigation).
1923
1920
  // Async work still continues via the returned Promise.
1924
1921
  let syncResult;
@@ -1992,7 +1989,7 @@ function createInstance(Component, props = {}) {
1992
1989
  inst.__vmzDepToBindings = Object.create(null);
1993
1990
  makeReactive(inst, Component.__vmzState || []);
1994
1991
  makeReactive(inst, Component.__vmzProps || []);
1995
- // L4 WriteBarrier: path / array writes call Component helpers (no import needed).
1992
+ // WriteBarrier: path / array writes call Component helpers (no import needed).
1996
1993
  Component.__vmzWritePath = __vmzWritePath;
1997
1994
  Component.__vmzWritePathLogical = __vmzWritePathLogical;
1998
1995
  Component.__vmzReadPath = __vmzReadPath;
@@ -2003,13 +2000,12 @@ function createInstance(Component, props = {}) {
2003
2000
  }
2004
2001
  /** Shared plain-object owners under WriteBarrier (no Proxy). */
2005
2002
  const wbSharedOwners = new WeakMap();
2006
- /** Objects explicitly marked OK to share across component instances (13 §7.3). */
2003
+ /** Objects explicitly marked OK to share across component instances (13 ). */
2007
2004
  const wbAllowShared = new WeakSet();
2008
2005
  /** @type {Array<{ kind: string, message: string }>} */
2009
2006
  const wbCrossComponentDiags = [];
2010
2007
  /**
2011
2008
  * Mark a plain object as intentionally shared across ownership boundaries.
2012
- * Suppresses cross-component shared diagnostics (规划设计/vmz/13 §7.3).
2013
2009
  * @param {any} value
2014
2010
  */
2015
2011
  export function __vmzAllowShared(value) {
@@ -2056,11 +2052,10 @@ function registerWbOwner(value, report, baseSegs = [], inst = null) {
2056
2052
  return;
2057
2053
  }
2058
2054
  entry.owners.push({ report, baseSegs: baseSegs.slice(), inst });
2059
- // Cross-component share without explicit allow → diagnose (13 §7.3).
2055
+ // Cross-component share without explicit allow → diagnose (13 ).
2060
2056
  if (!wbAllowShared.has(value) && inst) {
2061
2057
  const other = entry.owners.find((o) => o.inst && o.inst !== inst);
2062
2058
  if (other) {
2063
- const msg = 'vmz: plain object shared across component instances without __vmzAllowShared (规划设计/vmz/13 §7.3)';
2064
2059
  if (!wbCrossComponentDiags.some((d) => d.message === msg)) {
2065
2060
  wbCrossComponentDiags.push({ kind: 'shared_cross_component', message: msg });
2066
2061
  }
@@ -2134,7 +2129,6 @@ export function __vmzWritePathLogical(inst, root, segs, kind, rhs) {
2134
2129
  return __vmzWritePath(inst, root, segs, rhs);
2135
2130
  }
2136
2131
  /**
2137
- * Compiler-inserted path write barrier (规划设计/vmz/13 §7.3).
2138
2132
  * Mutates a plain owned object/array and schedules the same path notice Proxy would.
2139
2133
  *
2140
2134
  * Root-array index assigns (`tags[0] = x`) notify as field replace (structural),
@@ -2273,7 +2267,7 @@ const reactiveProxies = new WeakMap();
2273
2267
  /** Plain objects using defineProperty write barriers (not Proxy). */
2274
2268
  const writeBarrierOwned = new WeakSet();
2275
2269
  /**
2276
- * L4 WriteBarrier: true when value is an owned plain object with path barriers (no Proxy).
2270
+ * WriteBarrier: true when value is an owned plain object with path barriers (no Proxy).
2277
2271
  * @param {any} value
2278
2272
  */
2279
2273
  export function __vmzIsWriteBarrierOwned(value) {
@@ -2331,7 +2325,7 @@ function notifyOwners(owners, localSegs) {
2331
2325
  }
2332
2326
  /**
2333
2327
  * Field-owned write traps for plain objects / arrays on state fields.
2334
- * Plain objects: WriteBarrier via defineProperty (no Proxy) — L4 / 13 §7.3.
2328
+ * Plain objects: WriteBarrier via defineProperty (no Proxy) — .
2335
2329
  * Arrays: transitional Proxy until keyed collection barriers land.
2336
2330
  * Shared raw objects notify **all** current owners.
2337
2331
  *
@@ -2532,11 +2526,10 @@ function wrapArray(arr, report, pathSegs) {
2532
2526
  * Still precise deps — never a full-tree re-render. Flush runs as a microtask;
2533
2527
  * call `await flushPending(inst)` to apply synchronously (tests / immediate UI).
2534
2528
  *
2535
- * Design: 规划设计/vmz/12 §6 — parent write covers children; siblings stay separate.
2536
2529
  *
2537
2530
  * @param {object} inst
2538
2531
  * @param {{ type: 'replace', root: string } | { type: 'path', root: string, segs: string[] } | string} notice
2539
- * string form is transitional field-root alias for replace.
2532
+ * string form is transitional field-root alias for replace.
2540
2533
  */
2541
2534
  function scheduleRefresh(inst, notice) {
2542
2535
  if (!inst || inst.__vmzDestroyed)
@@ -2822,7 +2815,6 @@ function pathDirtyCovers(node, depSegs) {
2822
2815
  }
2823
2816
  /**
2824
2817
  * Dual-track match retained for tests / tooling.
2825
- * Design: 规划设计/vmz/11 §2.2 + 12 §6 parent-covers-children.
2826
2818
  * @param {{ type: string, root: string, segs?: string[] }} notice
2827
2819
  * @param {string} key
2828
2820
  */
@@ -2971,7 +2963,7 @@ function reindexBindingDeps(inst, bindingId, deps) {
2971
2963
  /**
2972
2964
  * @param {object} inst
2973
2965
  * @param {string[]} deps
2974
- * @param {() => any} fn
2966
+ * @param { => any} fn
2975
2967
  * @param {number|string|null|undefined} [bindingId]
2976
2968
  */
2977
2969
  function registerBind(inst, deps, fn, bindingId = null) {
@@ -2998,7 +2990,7 @@ function registerBind(inst, deps, fn, bindingId = null) {
2998
2990
  /**
2999
2991
  * @param {object} inst
3000
2992
  * @param {string[]} deps
3001
- * @param {() => any} fn
2993
+ * @param { => any} fn
3002
2994
  * @param {number|string|null|undefined} [bindingId]
3003
2995
  */
3004
2996
  function unregisterBind(inst, deps, fn, bindingId = null) {
@@ -9,8 +9,8 @@
9
9
  *
10
10
  * `VMZ_DEV=1`: POST `/__vmz/reload` soft-reloads modules (cache-bust import);
11
11
  * GET `/__vmz/events` SSE notifies the browser:
12
- * - island HMR → re-import `entry-client.js` (no full document reload)
13
- * - otherwise → `location.reload()`
12
+ * - island HMR → re-import `entry-client.js` (no full document reload)
13
+ * - otherwise → `location.reload`
14
14
  */
15
15
  import http from 'node:http';
16
16
  import path from 'node:path';
package/dist/server.d.ts CHANGED
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * Minimal VMZ runtime — `#server` invoke + RPC/REST HTTP + optional static/SSR.
3
3
  *
4
- * Design: 规划设计/vmz/08-虚拟server.md, 07-REST接口.md
5
4
  *
6
5
  * Browser-safe: no static `node:*` imports. Node builtins are loaded only inside
7
6
  * Node/SSR request handlers so client bundles can `import { callServer }`.
8
7
  */
9
8
  /**
10
- * Map `#server/foo` → filesystem / URL the host can `import()`.
9
+ * Map `#server/foo` → filesystem / URL the host can `import`.
11
10
  * Only set this in Node/SSR hosts — browser bundles must omit it so RPC goes HTTP.
12
11
  */
13
12
  export declare function setServerModuleResolver(fn: any): void;
package/dist/server.js CHANGED
@@ -2,7 +2,6 @@
2
2
  /**
3
3
  * Minimal VMZ runtime — `#server` invoke + RPC/REST HTTP + optional static/SSR.
4
4
  *
5
- * Design: 规划设计/vmz/08-虚拟server.md, 07-REST接口.md
6
5
  *
7
6
  * Browser-safe: no static `node:*` imports. Node builtins are loaded only inside
8
7
  * Node/SSR request handlers so client bundles can `import { callServer }`.
@@ -11,12 +10,12 @@
11
10
  /** @typedef {{ verb: string, path: string, moduleId: string, method: string, className?: string }} Route */
12
11
  /**
13
12
  * @typedef {{
14
- * distDir?: string,
15
- * renderIndex?: () => Promise<string> | string,
16
- * renderIndexStream?: (opts?: { signal?: AbortSignal }) => AsyncIterable<string>,
17
- * renderPage?: (pathname: string) => Promise<string | null> | string | null,
18
- * renderPageStream?: (pathname: string, opts?: { signal?: AbortSignal, searchParams?: URLSearchParams, cookieHeader?: string }) => Promise<AsyncIterable<string> | null> | AsyncIterable<string> | null,
19
- * req?: import('node:http').IncomingMessage,
13
+ * distDir?: string,
14
+ * renderIndex?: => Promise<string> | string,
15
+ * renderIndexStream?: (opts?: { signal?: AbortSignal }) => AsyncIterable<string>,
16
+ * renderPage?: (pathname: string) => Promise<string | null> | string | null,
17
+ * renderPageStream?: (pathname: string, opts?: { signal?: AbortSignal, searchParams?: URLSearchParams, cookieHeader?: string }) => Promise<AsyncIterable<string> | null> | AsyncIterable<string> | null,
18
+ * req?: import('node:http').IncomingMessage,
20
19
  * }} NodeRequestOptions
21
20
  */
22
21
  const DEFAULT_RPC_PATH = '/__vmz/rpc';
@@ -25,7 +24,7 @@ let resolveServerModule = null;
25
24
  /** @type {Route[]} */
26
25
  let routes = [];
27
26
  /**
28
- * Map `#server/foo` → filesystem / URL the host can `import()`.
27
+ * Map `#server/foo` → filesystem / URL the host can `import`.
29
28
  * Only set this in Node/SSR hosts — browser bundles must omit it so RPC goes HTTP.
30
29
  */
31
30
  export function setServerModuleResolver(fn) {