@vobs/runtime 1.7.8 → 1.8.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.
Files changed (127) hide show
  1. package/README.md +1 -1
  2. package/dist/async-boundary.cjs +14 -4
  3. package/dist/async-boundary.cjs.map +1 -1
  4. package/dist/async-boundary.js +17 -7
  5. package/dist/async-boundary.js.map +1 -1
  6. package/dist/bind.cjs +43 -3
  7. package/dist/bind.cjs.map +1 -1
  8. package/dist/bind.js +48 -8
  9. package/dist/bind.js.map +1 -1
  10. package/dist/boundary.cjs +159 -84
  11. package/dist/boundary.cjs.map +1 -1
  12. package/dist/boundary.js +162 -87
  13. package/dist/boundary.js.map +1 -1
  14. package/dist/client-only.cjs +323 -0
  15. package/dist/client-only.cjs.map +1 -0
  16. package/dist/client-only.d.cts +42 -0
  17. package/dist/client-only.d.ts +42 -0
  18. package/dist/client-only.js +299 -0
  19. package/dist/client-only.js.map +1 -0
  20. package/dist/debug.cjs.map +1 -1
  21. package/dist/debug.d.cts +12 -2
  22. package/dist/debug.d.ts +12 -2
  23. package/dist/debug.js.map +1 -1
  24. package/dist/dom-events.cjs +46 -0
  25. package/dist/dom-events.cjs.map +1 -0
  26. package/dist/dom-events.d.cts +23 -0
  27. package/dist/dom-events.d.ts +23 -0
  28. package/dist/dom-events.js +21 -0
  29. package/dist/dom-events.js.map +1 -0
  30. package/dist/dom-props.cjs +154 -0
  31. package/dist/dom-props.cjs.map +1 -0
  32. package/dist/dom-props.d.cts +21 -0
  33. package/dist/dom-props.d.ts +21 -0
  34. package/dist/dom-props.js +128 -0
  35. package/dist/dom-props.js.map +1 -0
  36. package/dist/dynamic.cjs +68 -14
  37. package/dist/dynamic.cjs.map +1 -1
  38. package/dist/dynamic.js +73 -19
  39. package/dist/dynamic.js.map +1 -1
  40. package/dist/error-boundary.cjs +159 -84
  41. package/dist/error-boundary.cjs.map +1 -1
  42. package/dist/error-boundary.js +162 -87
  43. package/dist/error-boundary.js.map +1 -1
  44. package/dist/error.cjs +52 -20
  45. package/dist/error.cjs.map +1 -1
  46. package/dist/error.d.cts +8 -0
  47. package/dist/error.d.ts +8 -0
  48. package/dist/error.js +52 -20
  49. package/dist/error.js.map +1 -1
  50. package/dist/fragment.cjs.map +1 -1
  51. package/dist/fragment.js +1 -1
  52. package/dist/fragment.js.map +1 -1
  53. package/dist/hmr.cjs +137 -1
  54. package/dist/hmr.cjs.map +1 -1
  55. package/dist/hmr.js +135 -1
  56. package/dist/hmr.js.map +1 -1
  57. package/dist/index.cjs +713 -236
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.d.cts +5 -2
  60. package/dist/index.d.ts +5 -2
  61. package/dist/index.js +715 -245
  62. package/dist/index.js.map +1 -1
  63. package/dist/ops.cjs +561 -107
  64. package/dist/ops.cjs.map +1 -1
  65. package/dist/ops.d.cts +49 -4
  66. package/dist/ops.d.ts +49 -4
  67. package/dist/ops.js +557 -108
  68. package/dist/ops.js.map +1 -1
  69. package/dist/profiler.cjs +14 -4
  70. package/dist/profiler.cjs.map +1 -1
  71. package/dist/profiler.js +17 -7
  72. package/dist/profiler.js.map +1 -1
  73. package/dist/ref.cjs +160 -5
  74. package/dist/ref.cjs.map +1 -1
  75. package/dist/ref.js +160 -5
  76. package/dist/ref.js.map +1 -1
  77. package/dist/renderer.cjs.map +1 -1
  78. package/dist/renderer.d.cts +2 -0
  79. package/dist/renderer.d.ts +2 -0
  80. package/dist/show.cjs +196 -0
  81. package/dist/show.cjs.map +1 -0
  82. package/dist/show.d.cts +54 -0
  83. package/dist/show.d.ts +54 -0
  84. package/dist/show.js +171 -0
  85. package/dist/show.js.map +1 -0
  86. package/dist/svg.cjs +102 -0
  87. package/dist/svg.cjs.map +1 -0
  88. package/dist/svg.d.cts +21 -0
  89. package/dist/svg.d.ts +21 -0
  90. package/dist/svg.js +76 -0
  91. package/dist/svg.js.map +1 -0
  92. package/package.json +20 -2
  93. package/src/bind.ts +30 -2
  94. package/src/boundaries.test.ts +54 -1
  95. package/src/boundary.ts +24 -8
  96. package/src/clear-remove.test.ts +85 -0
  97. package/src/client-only.test.ts +140 -0
  98. package/src/client-only.ts +65 -0
  99. package/src/component-empty-return.test.ts +123 -0
  100. package/src/debug.ts +12 -1
  101. package/src/dom-events.ts +32 -0
  102. package/src/dom-props-consistency.test.ts +149 -0
  103. package/src/dom-props.test.ts +70 -0
  104. package/src/dom-props.ts +107 -0
  105. package/src/dynamic.ts +91 -14
  106. package/src/error.test.ts +76 -1
  107. package/src/error.ts +87 -22
  108. package/src/event-cleanup-growth.test.ts +128 -0
  109. package/src/events.test.ts +16 -3
  110. package/src/hmr.ts +8 -2
  111. package/src/index.ts +13 -1
  112. package/src/invariants.test.ts +252 -0
  113. package/src/list-fast-path.test.ts +83 -0
  114. package/src/list-reactive-item.test.ts +77 -0
  115. package/src/ops.ts +419 -60
  116. package/src/props.test.ts +61 -1
  117. package/src/ref-cleanup.test.ts +144 -0
  118. package/src/ref.ts +57 -8
  119. package/src/remove-listener-identity.test.ts +97 -0
  120. package/src/renderer.ts +3 -1
  121. package/src/select-hidden-subscription.test.ts +104 -0
  122. package/src/show-classlist.test.ts +205 -0
  123. package/src/show.ts +107 -0
  124. package/src/spread-stable-shape.test.ts +109 -0
  125. package/src/spread.test.ts +86 -0
  126. package/src/svg.test.ts +28 -1
  127. package/src/svg.ts +34 -0
package/dist/index.cjs CHANGED
@@ -23,12 +23,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
23
23
  var src_exports = {};
24
24
  __export(src_exports, {
25
25
  AsyncBoundary: () => AsyncBoundary,
26
+ ClientOnly: () => ClientOnly,
26
27
  ErrorBoundary: () => ErrorBoundary,
27
28
  Profiler: () => Profiler,
29
+ Show: () => Show,
28
30
  VobsError: () => VobsError,
29
31
  addEventListener: () => addEventListener,
32
+ applyClassList: () => applyClassList,
30
33
  bindAttribute: () => bindAttribute,
31
34
  bindProperty: () => bindProperty,
35
+ bindSpreadProps: () => bindSpreadProps,
32
36
  bindText: () => bindText,
33
37
  clear: () => clear,
34
38
  cloneTemplate: () => cloneTemplate,
@@ -38,6 +42,7 @@ __export(src_exports, {
38
42
  createElement: () => createElement,
39
43
  createFragment: () => createFragment,
40
44
  createHmrStateStore: () => createHmrStateStore,
45
+ createSvgElement: () => createSvgElement,
41
46
  createTemplate: () => createTemplate,
42
47
  createText: () => createText,
43
48
  createVobsError: () => createVobsError,
@@ -63,9 +68,11 @@ __export(src_exports, {
63
68
  markHmrInstanceMounted: () => markHmrInstanceMounted,
64
69
  normalizeDynamicChild: () => normalizeDynamicChild,
65
70
  normalizeVobsError: () => normalizeVobsError,
71
+ parseClassList: () => parseClassList,
66
72
  pushRuntimeDebugContext: () => pushRuntimeDebugContext,
67
73
  ref: () => ref,
68
74
  registerHmrInstance: () => registerHmrInstance,
75
+ removeAttribute: () => removeAttribute,
69
76
  removeChild: () => removeChild,
70
77
  removeEventListener: () => removeEventListener,
71
78
  resolveComponent: () => resolveComponent,
@@ -167,6 +174,340 @@ var import_reactivity3 = require("@vobs/reactivity");
167
174
  // packages/runtime/src/ops.ts
168
175
  var import_reactivity2 = require("@vobs/reactivity");
169
176
 
177
+ // packages/runtime/src/dom-props.ts
178
+ var PROPERTY_NAMES = /* @__PURE__ */ new Set([
179
+ // 表单状态
180
+ "value",
181
+ "checked",
182
+ "selected",
183
+ "disabled",
184
+ "multiple",
185
+ "readOnly",
186
+ "required",
187
+ "defaultValue",
188
+ "defaultChecked",
189
+ "indeterminate",
190
+ /*
191
+ * `autoFocus` 用**驼峰**(与同表 readOnly/tabIndex/defaultChecked 一致),且必须走
192
+ * **property 通道**:`autofocus` 是**布尔属性**(只看存在与否、与值无关),
193
+ * 所以 `autoFocus={false}` 必须"移除属性"而不是写 `autofocus="false"`
194
+ * (attribute 通道只能把 false 序列化成字符串,属性照样存在 = 仍然聚焦)。
195
+ *
196
+ * ⚠️ 但 `setProperty` 必须把它映射成 **IDL 名 `autofocus`(全小写)** ——
197
+ * `Reflect.set(el, 'autoFocus', …)` 只会挂一个不反射的 expando,**静默无效**。
198
+ * 映射表见 ops.ts 的 `PROPERTY_IDL_NAMES`。实测(jsdom,与真实 DOM 同语义):
199
+ * IDL `autofocus` → 写 true 得 has=true/idl=true;写 false 得 has=false/idl=false ✓
200
+ * JSX `autoFocus` → 属性与 IDL 都不变(只是 expando) ✗
201
+ */
202
+ "autoFocus",
203
+ "hidden",
204
+ "tabIndex",
205
+ "colSpan",
206
+ "rowSpan",
207
+ "open",
208
+ // 只能走 property 的(attribute 路径会静默无效)
209
+ "innerHTML",
210
+ "innerText",
211
+ "textContent",
212
+ // 媒体
213
+ "muted",
214
+ "volume",
215
+ "currentTime",
216
+ "playbackRate"
217
+ ]);
218
+ var ATTRIBUTE_ALIASES = {
219
+ className: "class",
220
+ htmlFor: "for",
221
+ autoComplete: "autocomplete",
222
+ spellCheck: "spellcheck"
223
+ };
224
+ var SVG_KEBAB_ATTRIBUTES = /* @__PURE__ */ new Set([
225
+ // stroke
226
+ "strokeWidth",
227
+ "strokeLinecap",
228
+ "strokeLinejoin",
229
+ "strokeDasharray",
230
+ "strokeDashoffset",
231
+ "strokeMiterlimit",
232
+ "strokeOpacity",
233
+ // fill
234
+ "fillOpacity",
235
+ "fillRule",
236
+ // clip(注意 clipPathUnits 是结构属性,不在这里)
237
+ "clipPath",
238
+ "clipRule",
239
+ // 文本对齐
240
+ "textAnchor",
241
+ "dominantBaseline",
242
+ "alignmentBaseline",
243
+ "baselineShift",
244
+ // 字体
245
+ "fontFamily",
246
+ "fontSize",
247
+ "fontSizeAdjust",
248
+ "fontStretch",
249
+ "fontStyle",
250
+ "fontVariant",
251
+ "fontWeight",
252
+ "letterSpacing",
253
+ "wordSpacing",
254
+ // marker 的表现属性(markerWidth / markerHeight / markerUnits 是结构属性,不在这里)
255
+ "markerStart",
256
+ "markerMid",
257
+ "markerEnd",
258
+ // 颜色
259
+ "colorInterpolation",
260
+ "colorInterpolationFilters",
261
+ "colorProfile",
262
+ "colorRendering",
263
+ "floodColor",
264
+ "floodOpacity",
265
+ "lightingColor",
266
+ "stopColor",
267
+ "stopOpacity",
268
+ "glyphOrientationHorizontal",
269
+ "glyphOrientationVertical",
270
+ // 渲染与合成
271
+ "imageRendering",
272
+ "paintOrder",
273
+ "pointerEvents",
274
+ "shapeRendering",
275
+ "textDecoration",
276
+ "textRendering",
277
+ "transformOrigin",
278
+ "vectorEffect",
279
+ "writingMode"
280
+ ]);
281
+ function isPropertyName(name) {
282
+ return PROPERTY_NAMES.has(name);
283
+ }
284
+ __name(isPropertyName, "isPropertyName");
285
+ function domAttributeName(name) {
286
+ const alias = ATTRIBUTE_ALIASES[name];
287
+ if (alias !== void 0) return alias;
288
+ if (SVG_KEBAB_ATTRIBUTES.has(name)) return name.replace(/[A-Z]/gu, (letter) => `-${letter.toLowerCase()}`);
289
+ return name;
290
+ }
291
+ __name(domAttributeName, "domAttributeName");
292
+
293
+ // packages/runtime/src/dom-events.ts
294
+ var EVENT_NAME_ALIASES = {
295
+ // React 风格的 onDoubleClick 对应的 DOM 事件是 dblclick
296
+ doubleclick: "dblclick",
297
+ // 少数人按 addEventListener 的写法写成 onDblClick
298
+ dblclick: "dblclick"
299
+ };
300
+ function resolveEventName(attributeName) {
301
+ if (!attributeName.startsWith("on") || attributeName.length <= 2) return void 0;
302
+ const lowered = attributeName.slice(2).toLowerCase();
303
+ return EVENT_NAME_ALIASES[lowered] ?? lowered;
304
+ }
305
+ __name(resolveEventName, "resolveEventName");
306
+
307
+ // packages/runtime/src/svg.ts
308
+ var SVG_TAGS = /* @__PURE__ */ new Set([
309
+ "animate",
310
+ "animateMotion",
311
+ "animateTransform",
312
+ "circle",
313
+ "clipPath",
314
+ "defs",
315
+ "desc",
316
+ "ellipse",
317
+ "feBlend",
318
+ "feColorMatrix",
319
+ "feComponentTransfer",
320
+ "feComposite",
321
+ "feConvolveMatrix",
322
+ "feDiffuseLighting",
323
+ "feDisplacementMap",
324
+ "feDistantLight",
325
+ "feDropShadow",
326
+ "feFlood",
327
+ "feFuncA",
328
+ "feFuncB",
329
+ "feFuncG",
330
+ "feFuncR",
331
+ "feGaussianBlur",
332
+ "feImage",
333
+ "feMerge",
334
+ "feMergeNode",
335
+ "feMorphology",
336
+ "feOffset",
337
+ "fePointLight",
338
+ "feSpecularLighting",
339
+ "feSpotLight",
340
+ "feTile",
341
+ "feTurbulence",
342
+ "filter",
343
+ "foreignObject",
344
+ "g",
345
+ "image",
346
+ "line",
347
+ "linearGradient",
348
+ "marker",
349
+ "mask",
350
+ "metadata",
351
+ "mpath",
352
+ "path",
353
+ "pattern",
354
+ "polygon",
355
+ "polyline",
356
+ "radialGradient",
357
+ "rect",
358
+ "set",
359
+ "stop",
360
+ "svg",
361
+ "switch",
362
+ "symbol",
363
+ "text",
364
+ "textPath",
365
+ "tspan",
366
+ "use",
367
+ "view"
368
+ ]);
369
+ function isSvgTag(tag) {
370
+ return SVG_TAGS.has(tag);
371
+ }
372
+ __name(isSvgTag, "isSvgTag");
373
+
374
+ // packages/runtime/src/error.ts
375
+ var _VobsError = class _VobsError extends Error {
376
+ constructor(options) {
377
+ super(options.message);
378
+ this.name = "VobsError";
379
+ this.code = options.code;
380
+ this.severity = options.severity ?? "error";
381
+ this.layer = options.layer ?? "runtime";
382
+ this.cause = options.cause;
383
+ this.fix = options.fix;
384
+ this.location = options.location;
385
+ this.trace = options.trace;
386
+ this.example = options.example;
387
+ this.docs = options.docs;
388
+ this.codeFrame = options.codeFrame;
389
+ }
390
+ };
391
+ __name(_VobsError, "VobsError");
392
+ var VobsError = _VobsError;
393
+ function createVobsError(options) {
394
+ return new VobsError(options);
395
+ }
396
+ __name(createVobsError, "createVobsError");
397
+ function isVobsError(value) {
398
+ return value instanceof VobsError || Boolean(value && typeof value === "object" && typeof value.code === "string" && typeof value.message === "string");
399
+ }
400
+ __name(isVobsError, "isVobsError");
401
+ function isForeignVobsError(value) {
402
+ return value instanceof Error && value.name === "VobsError" && typeof value.code === "string";
403
+ }
404
+ __name(isForeignVobsError, "isForeignVobsError");
405
+ function describeUnknown(value) {
406
+ if (value === null || value === void 0) return String(value);
407
+ if (typeof value === "string") return value;
408
+ if (typeof value === "object") {
409
+ const message = value.message;
410
+ if (typeof message === "string" && message !== "") return message;
411
+ try {
412
+ return JSON.stringify(value) ?? String(value);
413
+ } catch {
414
+ return String(value);
415
+ }
416
+ }
417
+ return String(value);
418
+ }
419
+ __name(describeUnknown, "describeUnknown");
420
+ function adoptVobsError(value, defaults) {
421
+ return new VobsError({
422
+ code: value.code,
423
+ message: value.message,
424
+ severity: value.severity ?? defaults.severity,
425
+ layer: value.layer ?? defaults.layer,
426
+ cause: value.cause ?? (value instanceof Error ? value : void 0),
427
+ fix: value.fix ?? defaults.fix,
428
+ location: value.location,
429
+ trace: value.trace,
430
+ example: value.example,
431
+ docs: value.docs,
432
+ codeFrame: value.codeFrame
433
+ });
434
+ }
435
+ __name(adoptVobsError, "adoptVobsError");
436
+ function normalizeVobsError(value, defaults = {}) {
437
+ if (value instanceof VobsError) return value;
438
+ if (isForeignVobsError(value)) return adoptVobsError(value, defaults);
439
+ if (value instanceof Error) {
440
+ const metadata = value;
441
+ const code = defaults.code ?? (typeof metadata.vobsCode === "string" ? metadata.vobsCode : void 0);
442
+ if (code) {
443
+ defineErrorMetadata(value, "code", code);
444
+ if (value.code !== code) {
445
+ return new VobsError({
446
+ code,
447
+ message: value.message,
448
+ severity: defaults.severity ?? "error",
449
+ layer: defaults.layer ?? "runtime",
450
+ cause: value,
451
+ fix: defaults.fix ?? (typeof metadata.vobsHint === "string" ? metadata.vobsHint : void 0)
452
+ });
453
+ }
454
+ }
455
+ defineErrorMetadata(value, "severity", defaults.severity ?? "error");
456
+ defineErrorMetadata(value, "layer", defaults.layer ?? "runtime");
457
+ const fix = defaults.fix ?? (typeof metadata.vobsHint === "string" ? metadata.vobsHint : void 0);
458
+ if (fix) defineErrorMetadata(value, "fix", fix);
459
+ const source = metadata.vobsSource;
460
+ if (source && typeof source === "object" && typeof source.file === "string" && typeof source.line === "number" && typeof source.column === "number") {
461
+ defineErrorMetadata(value, "location", source);
462
+ }
463
+ return value;
464
+ }
465
+ if (isVobsError(value)) return adoptVobsError(value, defaults);
466
+ return new VobsError({
467
+ code: defaults.code ?? "VOBS_UNKNOWN",
468
+ message: describeUnknown(value),
469
+ severity: defaults.severity ?? "error",
470
+ layer: defaults.layer ?? "runtime",
471
+ cause: void 0,
472
+ fix: defaults.fix
473
+ });
474
+ }
475
+ __name(normalizeVobsError, "normalizeVobsError");
476
+ function defineErrorMetadata(target, key, value) {
477
+ if (key in target) return;
478
+ try {
479
+ Object.defineProperty(target, key, { configurable: true, enumerable: false, value, writable: true });
480
+ } catch {
481
+ }
482
+ }
483
+ __name(defineErrorMetadata, "defineErrorMetadata");
484
+ function formatVobsError(value, options = {}) {
485
+ const error = normalizeVobsError(value);
486
+ const code = error.code || "VOBS_UNKNOWN";
487
+ const severity = error.severity || "error";
488
+ if (options.environment === "production") return `[Vobs ${code}] ${error.message}`;
489
+ const lines = [`[Vobs ${capitalize(severity)}] ${error.message}`, `Code: ${code}`];
490
+ if (error.location) lines.push(`Location: ${error.location.file}:${error.location.line}:${error.location.column}`);
491
+ if (error.codeFrame) lines.push("", error.codeFrame);
492
+ if (error.cause !== void 0) lines.push(`Cause: ${formatCause(error.cause)}`);
493
+ if (error.trace?.length) lines.push("", `Trace: ${error.trace.join(" \u2192 ")}`);
494
+ if (error.fix) lines.push("", `Fix: ${error.fix}`);
495
+ if (error.example) lines.push("", `Example:
496
+ ${error.example}`);
497
+ if (error.docs) lines.push(`Docs: ${error.docs}`);
498
+ if (options.includeStack && error.stack) lines.push("", error.stack);
499
+ return lines.join("\n");
500
+ }
501
+ __name(formatVobsError, "formatVobsError");
502
+ function formatCause(value) {
503
+ return value instanceof Error ? `${value.name}: ${value.message}` : String(value);
504
+ }
505
+ __name(formatCause, "formatCause");
506
+ function capitalize(value) {
507
+ return value.slice(0, 1).toUpperCase() + value.slice(1);
508
+ }
509
+ __name(capitalize, "capitalize");
510
+
170
511
  // packages/runtime/src/hmr.ts
171
512
  var globalTarget = globalThis;
172
513
  var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map(), states: /* @__PURE__ */ new Map() };
@@ -205,7 +546,8 @@ function updateHmrModule(moduleId, nextModule) {
205
546
  for (const instance of instances) {
206
547
  try {
207
548
  instance.refresh();
208
- } catch {
549
+ } catch (error) {
550
+ console.error(formatVobsError(error, { includeStack: true }));
209
551
  }
210
552
  }
211
553
  }
@@ -214,21 +556,21 @@ function disposeHmrModule(_moduleId) {
214
556
  }
215
557
  __name(disposeHmrModule, "disposeHmrModule");
216
558
  function createHmrStateStore(moduleId) {
217
- const state4 = getModule(moduleId).state;
559
+ const state5 = getModule(moduleId).state;
218
560
  return {
219
561
  get(key, initial) {
220
- if (!state4.has(key)) state4.set(key, typeof initial === "function" ? initial() : initial);
221
- return state4.get(key);
562
+ if (!state5.has(key)) state5.set(key, typeof initial === "function" ? initial() : initial);
563
+ return state5.get(key);
222
564
  },
223
565
  set(key, value) {
224
- state4.set(key, value);
566
+ state5.set(key, value);
225
567
  },
226
- has: /* @__PURE__ */ __name((key) => state4.has(key), "has"),
568
+ has: /* @__PURE__ */ __name((key) => state5.has(key), "has"),
227
569
  delete: /* @__PURE__ */ __name((key) => {
228
- state4.delete(key);
570
+ state5.delete(key);
229
571
  }, "delete"),
230
572
  clear: /* @__PURE__ */ __name(() => {
231
- state4.clear();
573
+ state5.clear();
232
574
  }, "clear")
233
575
  };
234
576
  }
@@ -273,15 +615,34 @@ function ref(initialValue = null) {
273
615
  return { current: initialValue };
274
616
  }
275
617
  __name(ref, "ref");
618
+ var refCleanups = /* @__PURE__ */ new WeakMap();
619
+ function rememberRefCleanup(owner, target, cleanup) {
620
+ let byTarget = refCleanups.get(owner);
621
+ if (!byTarget) {
622
+ byTarget = /* @__PURE__ */ new WeakMap();
623
+ refCleanups.set(owner, byTarget);
624
+ }
625
+ const previous = byTarget.get(target);
626
+ if (previous) owner.removeCleanup(previous);
627
+ byTarget.set(target, cleanup);
628
+ }
629
+ __name(rememberRefCleanup, "rememberRefCleanup");
276
630
  function setRef(node, target) {
277
631
  if (!isRefTarget(target)) return;
278
632
  if (isSSRNode(node)) return;
279
633
  const owner = (0, import_reactivity.getCurrentOwner)();
280
634
  assignRef(target, node);
281
- owner?.onDispose(() => {
282
- if (isObjectRef(target) && target.current !== node) return;
283
- assignRef(target, null);
284
- });
635
+ if (!owner) return;
636
+ const cleanup = /* @__PURE__ */ __name(() => {
637
+ try {
638
+ if (isObjectRef(target) && target.current !== node) return;
639
+ assignRef(target, null);
640
+ } catch (error) {
641
+ console.error(formatVobsError(error, { includeStack: true }));
642
+ }
643
+ }, "cleanup");
644
+ rememberRefCleanup(owner, target, cleanup);
645
+ owner.onDispose(cleanup);
285
646
  }
286
647
  __name(setRef, "setRef");
287
648
  function isSSRNode(value) {
@@ -301,7 +662,8 @@ function assignRef(target, value) {
301
662
  try {
302
663
  if (typeof target === "function") target(value);
303
664
  else target.current = value;
304
- } catch {
665
+ } catch (error) {
666
+ console.error(formatVobsError(error, { includeStack: true }));
305
667
  }
306
668
  }
307
669
  __name(assignRef, "assignRef");
@@ -310,8 +672,22 @@ __name(assignRef, "assignRef");
310
672
  var currentRenderer = null;
311
673
  var nodeOwners = /* @__PURE__ */ new WeakMap();
312
674
  var eventBindings = /* @__PURE__ */ new WeakMap();
675
+ var eventCleanupSlots = /* @__PURE__ */ new WeakMap();
676
+ var eventCleanupNodeIds = /* @__PURE__ */ new WeakMap();
677
+ var nextEventCleanupNodeId = 0;
678
+ function eventCleanupKey(node, event) {
679
+ let id = eventCleanupNodeIds.get(node);
680
+ if (id === void 0) {
681
+ id = ++nextEventCleanupNodeId;
682
+ eventCleanupNodeIds.set(node, id);
683
+ }
684
+ return `${id}:${event}`;
685
+ }
686
+ __name(eventCleanupKey, "eventCleanupKey");
313
687
  function setRenderer(renderer) {
314
- currentRenderer = renderer;
688
+ const previous = currentRenderer;
689
+ currentRenderer = renderer ?? null;
690
+ return previous;
315
691
  }
316
692
  __name(setRenderer, "setRenderer");
317
693
  function getRenderer() {
@@ -325,75 +701,20 @@ function createText(content) {
325
701
  return getRenderer().createText(content);
326
702
  }
327
703
  __name(createText, "createText");
328
- var SVG_TAGS = /* @__PURE__ */ new Set([
329
- "animate",
330
- "animateMotion",
331
- "animateTransform",
332
- "circle",
333
- "clipPath",
334
- "defs",
335
- "desc",
336
- "ellipse",
337
- "feBlend",
338
- "feColorMatrix",
339
- "feComponentTransfer",
340
- "feComposite",
341
- "feConvolveMatrix",
342
- "feDiffuseLighting",
343
- "feDisplacementMap",
344
- "feDistantLight",
345
- "feDropShadow",
346
- "feFlood",
347
- "feFuncA",
348
- "feFuncB",
349
- "feFuncG",
350
- "feFuncR",
351
- "feGaussianBlur",
352
- "feImage",
353
- "feMerge",
354
- "feMergeNode",
355
- "feMorphology",
356
- "feOffset",
357
- "fePointLight",
358
- "feSpecularLighting",
359
- "feSpotLight",
360
- "feTile",
361
- "feTurbulence",
362
- "filter",
363
- "foreignObject",
364
- "g",
365
- "image",
366
- "line",
367
- "linearGradient",
368
- "marker",
369
- "mask",
370
- "metadata",
371
- "mpath",
372
- "path",
373
- "pattern",
374
- "polygon",
375
- "polyline",
376
- "radialGradient",
377
- "rect",
378
- "set",
379
- "stop",
380
- "svg",
381
- "switch",
382
- "symbol",
383
- "text",
384
- "textPath",
385
- "tspan",
386
- "use",
387
- "view"
388
- ]);
389
704
  function createElement(tag) {
390
- if (SVG_TAGS.has(tag)) {
705
+ if (isSvgTag(tag)) {
391
706
  const renderer = getRenderer();
392
707
  if (renderer.createSvgElement) return renderer.createSvgElement(tag);
393
708
  }
394
709
  return getRenderer().createElement(tag);
395
710
  }
396
711
  __name(createElement, "createElement");
712
+ function createSvgElement(tag) {
713
+ const renderer = getRenderer();
714
+ if (renderer.createSvgElement) return renderer.createSvgElement(tag);
715
+ return renderer.createElement(tag);
716
+ }
717
+ __name(createSvgElement, "createSvgElement");
397
718
  function createComment(content) {
398
719
  return getRenderer().createComment(content);
399
720
  }
@@ -427,7 +748,7 @@ function syncSelectValue(parent) {
427
748
  while (current !== null) {
428
749
  if (current.nodeName === "SELECT") {
429
750
  const read = selectValueReaders.get(current);
430
- if (read !== void 0) setProperty(current, "value", read());
751
+ if (read !== void 0) setProperty(current, "value", (0, import_reactivity2.untrack)(read));
431
752
  return;
432
753
  }
433
754
  current = current.parentNode;
@@ -435,9 +756,9 @@ function syncSelectValue(parent) {
435
756
  }
436
757
  __name(syncSelectValue, "syncSelectValue");
437
758
  function removeChild(parent, child) {
438
- disposeNodeOwner(child);
439
759
  if (isVobsFragment(child)) {
440
760
  child.unmount(parent);
761
+ disposeNodeOwner(child);
441
762
  return;
442
763
  }
443
764
  getRenderer().removeChild(parent, child);
@@ -448,6 +769,7 @@ function removeChild(parent, child) {
448
769
  parent: describeDebugNode(parent)
449
770
  });
450
771
  }
772
+ disposeNodeOwner(child);
451
773
  }
452
774
  __name(removeChild, "removeChild");
453
775
  function setTextContent(node, content) {
@@ -465,7 +787,7 @@ function setTextContent(node, content) {
465
787
  __name(setTextContent, "setTextContent");
466
788
  function setProperty(node, key, value) {
467
789
  const previousValue = getRuntimeDebugHooks() ? readDebugValue(() => Reflect.get(node, key)) : void 0;
468
- getRenderer().setProperty(node, key, value);
790
+ getRenderer().setProperty(node, PROPERTY_IDL_NAMES[key] ?? key, value);
469
791
  if (key === "value" && node.tagName === "SELECT") {
470
792
  scheduleSelectValueSync(node, value);
471
793
  }
@@ -486,12 +808,13 @@ function scheduleSelectValueSync(node, value) {
486
808
  pendingSelectValues.set(node, value);
487
809
  if (selectSyncScheduled.has(node)) return;
488
810
  selectSyncScheduled.add(node);
811
+ const renderer = getRenderer();
489
812
  queueMicrotask(() => {
490
813
  selectSyncScheduled.delete(node);
491
814
  if (!pendingSelectValues.has(node)) return;
492
815
  const pending = pendingSelectValues.get(node);
493
816
  pendingSelectValues.delete(node);
494
- getRenderer().setProperty(node, "value", pending);
817
+ renderer.setProperty(node, "value", pending);
495
818
  });
496
819
  }
497
820
  __name(scheduleSelectValueSync, "scheduleSelectValueSync");
@@ -510,48 +833,131 @@ function setAttribute(node, key, value) {
510
833
  }
511
834
  __name(setAttribute, "setAttribute");
512
835
  function spreadProps(node, props) {
513
- for (const [key, value] of Object.entries(props)) {
514
- if (key === "key" || value === null || value === void 0) continue;
836
+ applySpreadProps(node, null, props);
837
+ }
838
+ __name(spreadProps, "spreadProps");
839
+ function removeAttribute(node, key) {
840
+ const renderer = getRenderer();
841
+ if (renderer.removeAttribute) {
842
+ renderer.removeAttribute(node, key);
843
+ return;
844
+ }
845
+ renderer.setAttribute(node, key, "");
846
+ }
847
+ __name(removeAttribute, "removeAttribute");
848
+ var BOOLEAN_PROPERTIES = /* @__PURE__ */ new Set([
849
+ "checked",
850
+ "selected",
851
+ "disabled",
852
+ "multiple",
853
+ "readOnly",
854
+ "required",
855
+ "hidden",
856
+ "open",
857
+ "indeterminate",
858
+ "defaultChecked",
859
+ "muted",
860
+ "autoFocus"
861
+ ]);
862
+ var PROPERTY_IDL_NAMES = {
863
+ autoFocus: "autofocus"
864
+ };
865
+ function applySpreadProps(node, previous, next) {
866
+ for (const [key, value] of Object.entries(next)) {
867
+ if (key === "key") continue;
868
+ if (previous !== null && Object.is(previous[key], value)) continue;
869
+ if (key.startsWith("on")) {
870
+ const eventName = resolveEventName(key) ?? key.slice(2).toLowerCase();
871
+ const previousHandler = previous?.[key];
872
+ if (typeof previousHandler === "function") {
873
+ removeEventListener(node, eventName, previousHandler);
874
+ }
875
+ if (typeof value === "function") {
876
+ addEventListener(node, eventName, value);
877
+ }
878
+ continue;
879
+ }
515
880
  if (key === "ref") {
516
881
  setRef(node, value);
517
882
  continue;
518
883
  }
519
- if (key.startsWith("on") && typeof value === "function") addEventListener(node, key.slice(2).toLowerCase(), value);
520
- else if (isPropertyKey(key)) setProperty(node, key, value);
884
+ if (value === null || value === void 0) continue;
885
+ else if (isClassListKey(key)) applyClassList(node, value);
886
+ else if (isPropertyName(key)) setProperty(node, key, value);
521
887
  else if (value === false) continue;
522
888
  else setAttribute(node, domAttributeName(key), key === "style" && isStyleObject(value) ? formatStyle(value) : String(value));
523
889
  }
890
+ if (previous === null) return;
891
+ for (const key of Object.keys(previous)) {
892
+ if (key in next || key === "key") continue;
893
+ if (key.startsWith("on")) {
894
+ const eventName = resolveEventName(key) ?? key.slice(2).toLowerCase();
895
+ const previousHandler = previous[key];
896
+ if (typeof previousHandler === "function") {
897
+ removeEventListener(node, eventName, previousHandler);
898
+ }
899
+ continue;
900
+ }
901
+ if (key === "ref") continue;
902
+ if (isPropertyName(key)) setProperty(node, key, BOOLEAN_PROPERTIES.has(key) ? false : "");
903
+ else removeAttribute(node, domAttributeName(key));
904
+ }
524
905
  }
525
- __name(spreadProps, "spreadProps");
906
+ __name(applySpreadProps, "applySpreadProps");
907
+ var classListContributions = /* @__PURE__ */ new WeakMap();
908
+ function parseClassList(value) {
909
+ const names = [];
910
+ const push = /* @__PURE__ */ __name((candidate) => {
911
+ if (typeof candidate === "string") {
912
+ for (const name of candidate.split(/\s+/u)) if (name !== "") names.push(name);
913
+ }
914
+ }, "push");
915
+ if (Array.isArray(value)) {
916
+ for (const entry of value) {
917
+ if (entry !== null && typeof entry === "object") {
918
+ for (const [name, on] of Object.entries(entry)) if (on) push(name);
919
+ } else push(entry);
920
+ }
921
+ } else if (value !== null && typeof value === "object") {
922
+ for (const [name, on] of Object.entries(value)) if (on) push(name);
923
+ } else push(value);
924
+ return names;
925
+ }
926
+ __name(parseClassList, "parseClassList");
927
+ function applyClassList(node, value) {
928
+ const next = parseClassList(value);
929
+ const previous = classListContributions.get(node) ?? [];
930
+ classListContributions.set(node, next);
931
+ const base = (node.getAttribute("class") ?? "").split(/\s+/u).filter((name) => name !== "" && !previous.includes(name));
932
+ const merged = [.../* @__PURE__ */ new Set([...base, ...next])];
933
+ setAttribute(node, "class", merged.join(" "));
934
+ }
935
+ __name(applyClassList, "applyClassList");
936
+ function isClassListKey(key) {
937
+ return key === "classList";
938
+ }
939
+ __name(isClassListKey, "isClassListKey");
940
+ function bindSpreadProps(node, source) {
941
+ let previous = null;
942
+ (0, import_reactivity2.effect)(() => {
943
+ const next = source() ?? {};
944
+ const snapshot = { ...next };
945
+ applySpreadProps(node, previous, next);
946
+ previous = snapshot;
947
+ });
948
+ }
949
+ __name(bindSpreadProps, "bindSpreadProps");
526
950
  function setStaticProps(node, props) {
527
951
  for (const [key, value] of Object.entries(props)) {
528
952
  if (key === "key" || key === "ref" || key.startsWith("on")) continue;
529
953
  if (value === null || value === void 0) continue;
530
- if (isPropertyKey(key)) setProperty(node, key, value);
954
+ if (isClassListKey(key)) applyClassList(node, value);
955
+ else if (isPropertyName(key)) setProperty(node, key, value);
531
956
  else if (value === false) continue;
532
957
  else setAttribute(node, domAttributeName(key), key === "style" && isStyleObject(value) ? formatStyle(value) : String(value));
533
958
  }
534
959
  }
535
960
  __name(setStaticProps, "setStaticProps");
536
- function isPropertyKey(key) {
537
- return key === "value" || key === "checked" || key === "selected" || key === "disabled" || key === "multiple" || key === "readOnly" || key === "required" || key === "autofocus" || key === "hidden" || key === "tabIndex" || key === "colSpan" || key === "rowSpan";
538
- }
539
- __name(isPropertyKey, "isPropertyKey");
540
- function domAttributeName(key) {
541
- switch (key) {
542
- case "className":
543
- return "class";
544
- case "htmlFor":
545
- return "for";
546
- case "autoComplete":
547
- return "autocomplete";
548
- case "spellCheck":
549
- return "spellcheck";
550
- default:
551
- return key;
552
- }
553
- }
554
- __name(domAttributeName, "domAttributeName");
555
961
  function isStyleObject(value) {
556
962
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
557
963
  }
@@ -570,7 +976,9 @@ function addEventListener(node, event, handler) {
570
976
  }
571
977
  const previous = bindings.get(event);
572
978
  if (previous && previous.original === handler && previous.owner === owner) return;
573
- if (previous) renderer.removeEventListener(node, event, previous.handler);
979
+ if (previous) {
980
+ renderer.removeEventListener(node, event, previous.handler);
981
+ }
574
982
  const listener = owner ? (reason) => {
575
983
  if (owner.disposed) return;
576
984
  try {
@@ -584,28 +992,66 @@ function addEventListener(node, event, handler) {
584
992
  handled,
585
993
  recovery: handled ? "handled" : "propagated"
586
994
  });
995
+ if (handled && getRuntimeDebugHooks()?.error === void 0) {
996
+ console.error(formatVobsError(error, { includeStack: true }));
997
+ }
587
998
  if (!handled) throw error;
588
999
  }
589
1000
  } : handler;
590
1001
  const binding = { handler: listener, owner, original: handler };
591
1002
  bindings.set(event, binding);
592
1003
  renderer.addEventListener(node, event, listener);
593
- owner?.onDispose(() => {
594
- if (bindings?.get(event) !== binding) return;
595
- bindings.delete(event);
596
- renderer.removeEventListener(node, event, listener);
1004
+ if (!owner) return;
1005
+ const key = eventCleanupKey(node, event);
1006
+ let slots = eventCleanupSlots.get(owner);
1007
+ if (!slots) {
1008
+ slots = /* @__PURE__ */ new Map();
1009
+ eventCleanupSlots.set(owner, slots);
1010
+ }
1011
+ const hasSlot = slots.has(key);
1012
+ slots.set(key, binding);
1013
+ if (hasSlot) return;
1014
+ owner.onDispose(() => {
1015
+ const current = eventCleanupSlots.get(owner)?.get(key);
1016
+ if (!current) return;
1017
+ eventCleanupSlots.get(owner)?.delete(key);
1018
+ const map = eventBindings.get(node);
1019
+ if (map?.get(event) === current) map.delete(event);
1020
+ renderer.removeEventListener(node, event, current.handler);
597
1021
  });
598
1022
  }
599
1023
  __name(addEventListener, "addEventListener");
600
1024
  function removeEventListener(node, event, handler) {
601
1025
  const renderer = getRenderer();
602
- const binding = eventBindings.get(node)?.get(event);
1026
+ const map = eventBindings.get(node);
1027
+ const binding = map?.get(event);
1028
+ if (binding) {
1029
+ if (binding.handler !== handler) return;
1030
+ map?.delete(event);
1031
+ }
603
1032
  renderer.removeEventListener(node, event, binding?.handler ?? handler);
604
- eventBindings.get(node)?.delete(event);
605
1033
  }
606
1034
  __name(removeEventListener, "removeEventListener");
607
1035
  function clear(container) {
1036
+ let firstError;
1037
+ const walk = /* @__PURE__ */ __name((node) => {
1038
+ try {
1039
+ disposeNodeOwner(node);
1040
+ } catch (error) {
1041
+ firstError ?? (firstError = error);
1042
+ }
1043
+ for (const child of Array.from(node.childNodes)) walk(child);
1044
+ }, "walk");
1045
+ for (const child of Array.from(container.childNodes)) walk(child);
608
1046
  getRenderer().clear(container);
1047
+ if (getRuntimeDebugHooks()) {
1048
+ invokeRuntimeDebug("domMutation", {
1049
+ operation: "clear",
1050
+ target: describeDebugNode(container),
1051
+ parent: describeDebugNode(container)
1052
+ });
1053
+ }
1054
+ if (firstError) throw firstError;
609
1055
  }
610
1056
  __name(clear, "clear");
611
1057
  function createComponent(component, props, source) {
@@ -627,15 +1073,16 @@ function createComponent(component, props, source) {
627
1073
  owner.onDispose(cleanup);
628
1074
  }
629
1075
  const renderScope = owner.mark();
630
- let node;
1076
+ let rendered;
631
1077
  try {
632
- node = owner.run(() => (0, import_reactivity2.untrack)(() => component(props)));
1078
+ rendered = owner.run(() => (0, import_reactivity2.untrack)(() => component(props)));
633
1079
  } catch (error) {
634
1080
  owner.dispose();
635
1081
  attachSourceLocation(error, source);
636
1082
  attachComponentContext(error, componentName, owner.id);
637
1083
  throw error;
638
1084
  }
1085
+ const node = isRenderableNode(rendered) ? rendered : createComment("vobs:empty");
639
1086
  associateNodeOwner(node, owner);
640
1087
  if (instance) {
641
1088
  instance.node = node;
@@ -706,7 +1153,16 @@ function createBlock(factory) {
706
1153
  return node;
707
1154
  }
708
1155
  __name(createBlock, "createBlock");
1156
+ function isRenderableNode(value) {
1157
+ return typeof value === "object" && value !== null || typeof value === "function";
1158
+ }
1159
+ __name(isRenderableNode, "isRenderableNode");
709
1160
  function associateNodeOwner(node, owner) {
1161
+ if (node === null || node === void 0 || typeof node !== "object" && typeof node !== "function") {
1162
+ throw new Error(
1163
+ `Vobs: associateNodeOwner \u6536\u5230\u975E\u8282\u70B9\u503C\uFF08${String(node)}\uFF09\u3002\u7EC4\u4EF6\u5FC5\u987B\u8FD4\u56DE VobsNode\uFF1B\u8FD4\u56DE null/undefined \u7531 createComponent \u8F6C\u6210\u7A7A\u6CE8\u91CA\u8282\u70B9\u3002`
1164
+ );
1165
+ }
710
1166
  nodeOwners.set(node, owner);
711
1167
  }
712
1168
  __name(associateNodeOwner, "associateNodeOwner");
@@ -801,6 +1257,11 @@ __name(bindText, "bindText");
801
1257
  function bindAttribute(node, key, source) {
802
1258
  (0, import_reactivity4.effect)(() => {
803
1259
  const value = readSource(source);
1260
+ if (value === null || value === void 0) return;
1261
+ if (key === "classList") {
1262
+ applyClassList(node, value);
1263
+ return;
1264
+ }
804
1265
  setAttribute(node, key, key === "style" && value && typeof value === "object" && !Array.isArray(value) ? Object.entries(value).filter(([, entry]) => entry !== null && entry !== void 0 && entry !== false).map(([name, entry]) => `${name.replace(/[A-Z]/gu, (match) => `-${match.toLowerCase()}`)}:${String(entry)}`).join(";") : String(value));
805
1266
  });
806
1267
  }
@@ -810,7 +1271,9 @@ function bindProperty(node, key, source) {
810
1271
  registerSelectValueBinding(node, () => readSource(source));
811
1272
  }
812
1273
  (0, import_reactivity4.effect)(() => {
813
- setProperty(node, key, readSource(source));
1274
+ const value = readSource(source);
1275
+ if (value === null || value === void 0) return;
1276
+ setProperty(node, key, value);
814
1277
  });
815
1278
  }
816
1279
  __name(bindProperty, "bindProperty");
@@ -920,6 +1383,32 @@ function insertList(parent, anchor, source, renderItem, keyOf) {
920
1383
  }
921
1384
  if (!allKeyed) keys = null;
922
1385
  }
1386
+ if (keys !== null && entries.length === items.length) {
1387
+ let fast = true;
1388
+ for (let index = 0; index < keys.length; index++) {
1389
+ if (!Object.is(entries[index].key, keys[index])) {
1390
+ fast = false;
1391
+ break;
1392
+ }
1393
+ const item = items[index];
1394
+ if (isPrimitiveItem(item) && !Object.is(entries[index].current, item)) {
1395
+ fast = false;
1396
+ break;
1397
+ }
1398
+ }
1399
+ if (fast) {
1400
+ for (let index = 0; index < items.length; index++) {
1401
+ const entry = entries[index];
1402
+ entry.index = index;
1403
+ const item = items[index];
1404
+ if (!Object.is(entry.current, item)) {
1405
+ entry.item.value = item;
1406
+ entry.current = item;
1407
+ }
1408
+ }
1409
+ return;
1410
+ }
1411
+ }
923
1412
  const nextEntries = keys ? reconcileKeyed(items, keys, entries, renderItem) : reconcileIndexed(items, entries, renderItem);
924
1413
  const refreshed = tracksIndex ? /* @__PURE__ */ new Set() : null;
925
1414
  for (let index = 0; index < nextEntries.length; index++) {
@@ -1008,7 +1497,8 @@ function computeKeptByLis(seq) {
1008
1497
  }
1009
1498
  __name(computeKeptByLis, "computeKeptByLis");
1010
1499
  function reconcileKeyed(items, keys, entries, renderItem) {
1011
- const previous = new Map(entries.map((entry) => [entry.key, entry]));
1500
+ const previous = /* @__PURE__ */ new Map();
1501
+ for (const entry of entries) previous.set(entry.key, entry);
1012
1502
  const seen = /* @__PURE__ */ new Set();
1013
1503
  const nextEntries = [];
1014
1504
  for (let index = 0; index < items.length; index++) {
@@ -1021,12 +1511,12 @@ function reconcileKeyed(items, keys, entries, renderItem) {
1021
1511
  const entry = previous.get(key);
1022
1512
  if (entry) {
1023
1513
  previous.delete(key);
1024
- if (isPrimitiveItem(item) && !Object.is(entry.value, item)) {
1514
+ if (isPrimitiveItem(item) && !Object.is(entry.current, item)) {
1025
1515
  nextEntries.push(createListEntry(item, index, key, renderItem));
1026
1516
  continue;
1027
1517
  }
1028
1518
  entry.item.value = item;
1029
- entry.value = item;
1519
+ entry.current = item;
1030
1520
  nextEntries.push(entry);
1031
1521
  continue;
1032
1522
  }
@@ -1040,13 +1530,13 @@ function reconcileIndexed(items, entries, renderItem) {
1040
1530
  for (let index = 0; index < items.length; index++) {
1041
1531
  const item = items[index];
1042
1532
  const entry = entries[index];
1043
- if (entry && isPrimitiveItem(item) && !Object.is(entry.value, item)) {
1533
+ if (entry && isPrimitiveItem(item) && !Object.is(entry.current, item)) {
1044
1534
  nextEntries.push(createListEntry(item, index, index, renderItem));
1045
1535
  continue;
1046
1536
  }
1047
1537
  if (entry) {
1048
1538
  entry.item.value = item;
1049
- entry.value = item;
1539
+ entry.current = item;
1050
1540
  nextEntries.push(entry);
1051
1541
  continue;
1052
1542
  }
@@ -1070,7 +1560,7 @@ function createListEntry(item, index, key, renderItem) {
1070
1560
  node = viewOwner.run(() => renderItem(toReactiveItem(itemSignal, item), index));
1071
1561
  });
1072
1562
  associateNodeOwner(node, viewOwner);
1073
- return { key, node, owner, viewOwner, item: itemSignal, value: item, index };
1563
+ return { key, node, owner, viewOwner, item: itemSignal, current: item, index };
1074
1564
  }
1075
1565
  __name(createListEntry, "createListEntry");
1076
1566
  function refreshListEntry(parent, entry, index, renderItem) {
@@ -1080,7 +1570,7 @@ function refreshListEntry(parent, entry, index, renderItem) {
1080
1570
  entry.owner.run(() => {
1081
1571
  entry.viewOwner = (0, import_reactivity5.createOwner)();
1082
1572
  entry.node = entry.viewOwner.run(() => renderItem(
1083
- toReactiveItem(entry.item, entry.value),
1573
+ toReactiveItem(entry.item, entry.current),
1084
1574
  index
1085
1575
  ));
1086
1576
  });
@@ -1092,7 +1582,7 @@ function toReactiveItem(item, initialValue) {
1092
1582
  if (typeof initialValue !== "object" || initialValue === null) {
1093
1583
  return initialValue;
1094
1584
  }
1095
- return new Proxy(initialValue, {
1585
+ return new Proxy(reactiveProxyTarget(initialValue), {
1096
1586
  get(_target, property, receiver) {
1097
1587
  return Reflect.get(item.value, property, receiver);
1098
1588
  },
@@ -1102,12 +1592,29 @@ function toReactiveItem(item, initialValue) {
1102
1592
  ownKeys() {
1103
1593
  return Reflect.ownKeys(item.value);
1104
1594
  },
1105
- getOwnPropertyDescriptor(_target, property) {
1106
- return Object.getOwnPropertyDescriptor(item.value, property);
1595
+ getOwnPropertyDescriptor(target, property) {
1596
+ const descriptor = Object.getOwnPropertyDescriptor(item.value, property);
1597
+ if (!descriptor) return void 0;
1598
+ const own = Object.getOwnPropertyDescriptor(target, property);
1599
+ return { ...descriptor, configurable: own ? own.configurable : true };
1107
1600
  }
1108
1601
  });
1109
1602
  }
1110
1603
  __name(toReactiveItem, "toReactiveItem");
1604
+ function reactiveProxyTarget(value) {
1605
+ if (Object.isExtensible(value)) {
1606
+ let allConfigurable = true;
1607
+ for (const key of Reflect.ownKeys(value)) {
1608
+ if (Object.getOwnPropertyDescriptor(value, key)?.configurable === false) {
1609
+ allConfigurable = false;
1610
+ break;
1611
+ }
1612
+ }
1613
+ if (allConfigurable) return value;
1614
+ }
1615
+ return Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
1616
+ }
1617
+ __name(reactiveProxyTarget, "reactiveProxyTarget");
1111
1618
  function disposeEntry(parent, entry) {
1112
1619
  removeChild(parent, entry.node);
1113
1620
  entry.owner.dispose();
@@ -1133,113 +1640,15 @@ function cloneTemplate(template) {
1133
1640
  }
1134
1641
  __name(cloneTemplate, "cloneTemplate");
1135
1642
 
1136
- // packages/runtime/src/error.ts
1137
- var _VobsError = class _VobsError extends Error {
1138
- constructor(options) {
1139
- super(options.message);
1140
- this.name = "VobsError";
1141
- this.code = options.code;
1142
- this.severity = options.severity ?? "error";
1143
- this.layer = options.layer ?? "runtime";
1144
- this.cause = options.cause;
1145
- this.fix = options.fix;
1146
- this.location = options.location;
1147
- this.trace = options.trace;
1148
- this.example = options.example;
1149
- this.docs = options.docs;
1150
- this.codeFrame = options.codeFrame;
1151
- }
1152
- };
1153
- __name(_VobsError, "VobsError");
1154
- var VobsError = _VobsError;
1155
- function createVobsError(options) {
1156
- return new VobsError(options);
1157
- }
1158
- __name(createVobsError, "createVobsError");
1159
- function isVobsError(value) {
1160
- return value instanceof VobsError || Boolean(value && typeof value === "object" && typeof value.code === "string" && typeof value.message === "string" && typeof value.layer === "string");
1161
- }
1162
- __name(isVobsError, "isVobsError");
1163
- function normalizeVobsError(value, defaults = {}) {
1164
- if (value instanceof VobsError) return value;
1165
- if (value instanceof Error) {
1166
- const metadata = value;
1167
- const code = defaults.code ?? (typeof metadata.vobsCode === "string" ? metadata.vobsCode : void 0);
1168
- if (code) defineErrorMetadata(value, "code", code);
1169
- defineErrorMetadata(value, "severity", defaults.severity ?? "error");
1170
- defineErrorMetadata(value, "layer", defaults.layer ?? "runtime");
1171
- const fix = defaults.fix ?? (typeof metadata.vobsHint === "string" ? metadata.vobsHint : void 0);
1172
- if (fix) defineErrorMetadata(value, "fix", fix);
1173
- const source = metadata.vobsSource;
1174
- if (source && typeof source === "object" && typeof source.file === "string" && typeof source.line === "number" && typeof source.column === "number") {
1175
- defineErrorMetadata(value, "location", source);
1176
- }
1177
- return value;
1178
- }
1179
- if (isVobsError(value)) {
1180
- const candidate = value;
1181
- return new VobsError({
1182
- code: candidate.code,
1183
- message: candidate.message,
1184
- severity: candidate.severity ?? defaults.severity,
1185
- layer: candidate.layer ?? defaults.layer,
1186
- cause: candidate.cause,
1187
- fix: candidate.fix ?? defaults.fix,
1188
- location: candidate.location,
1189
- trace: candidate.trace,
1190
- example: candidate.example,
1191
- docs: candidate.docs,
1192
- codeFrame: candidate.codeFrame
1193
- });
1194
- }
1195
- const message = String(value);
1196
- return new VobsError({
1197
- code: defaults.code ?? "VOBS_UNKNOWN",
1198
- message,
1199
- severity: defaults.severity ?? "error",
1200
- layer: defaults.layer ?? "runtime",
1201
- cause: void 0,
1202
- fix: defaults.fix
1203
- });
1204
- }
1205
- __name(normalizeVobsError, "normalizeVobsError");
1206
- function defineErrorMetadata(target, key, value) {
1207
- if (key in target) return;
1208
- try {
1209
- Object.defineProperty(target, key, { configurable: true, enumerable: false, value, writable: true });
1210
- } catch {
1211
- }
1212
- }
1213
- __name(defineErrorMetadata, "defineErrorMetadata");
1214
- function formatVobsError(value, options = {}) {
1215
- const error = normalizeVobsError(value);
1216
- const code = error.code || "VOBS_UNKNOWN";
1217
- const severity = error.severity || "error";
1218
- if (options.environment === "production") return `[Vobs ${code}] ${error.message}`;
1219
- const lines = [`[Vobs ${capitalize(severity)}] ${error.message}`, `Code: ${code}`];
1220
- if (error.location) lines.push(`Location: ${error.location.file}:${error.location.line}:${error.location.column}`);
1221
- if (error.codeFrame) lines.push("", error.codeFrame);
1222
- if (error.cause !== void 0) lines.push(`Cause: ${formatCause(error.cause)}`);
1223
- if (error.trace?.length) lines.push("", `Trace: ${error.trace.join(" \u2192 ")}`);
1224
- if (error.fix) lines.push("", `Fix: ${error.fix}`);
1225
- if (error.example) lines.push("", `Example:
1226
- ${error.example}`);
1227
- if (error.docs) lines.push(`Docs: ${error.docs}`);
1228
- if (options.includeStack && error.stack) lines.push("", error.stack);
1229
- return lines.join("\n");
1230
- }
1231
- __name(formatVobsError, "formatVobsError");
1232
- function formatCause(value) {
1233
- return value instanceof Error ? `${value.name}: ${value.message}` : String(value);
1234
- }
1235
- __name(formatCause, "formatCause");
1236
- function capitalize(value) {
1237
- return value.slice(0, 1).toUpperCase() + value.slice(1);
1238
- }
1239
- __name(capitalize, "capitalize");
1240
-
1241
1643
  // packages/runtime/src/boundary.ts
1242
1644
  var import_reactivity6 = require("@vobs/reactivity");
1645
+ function reportBoundaryError(event, loud) {
1646
+ invokeRuntimeDebug("error", event);
1647
+ if (loud && getRuntimeDebugHooks()?.error === void 0) {
1648
+ console.error(formatVobsError(event.error, { includeStack: true }));
1649
+ }
1650
+ }
1651
+ __name(reportBoundaryError, "reportBoundaryError");
1243
1652
  function insertBoundary(parent, anchor, options) {
1244
1653
  const boundary = (0, import_reactivity6.createOwner)();
1245
1654
  boundary.run(() => {
@@ -1256,24 +1665,24 @@ function insertBoundary(parent, anchor, options) {
1256
1665
  fix: "\u68C0\u67E5\u7EC4\u4EF6\u6E32\u67D3\u903B\u8F91\uFF0C\u6216\u5728\u8FB9\u754C fallback \u4E2D\u63D0\u4F9B\u6062\u590D\u64CD\u4F5C\u3002"
1257
1666
  });
1258
1667
  lastError = normalized;
1259
- invokeRuntimeDebug("error", {
1668
+ reportBoundaryError({
1260
1669
  error: normalized,
1261
1670
  owner: boundary,
1262
1671
  phase: "boundary",
1263
1672
  handled: true,
1264
1673
  recovery: "fallback"
1265
- });
1674
+ }, true);
1266
1675
  error.value = normalized;
1267
1676
  });
1268
1677
  const retry = /* @__PURE__ */ __name(() => {
1269
1678
  if (error.value) {
1270
- invokeRuntimeDebug("error", {
1679
+ reportBoundaryError({
1271
1680
  error: error.value,
1272
1681
  owner: boundary,
1273
1682
  phase: "boundary",
1274
1683
  handled: true,
1275
1684
  recovery: "retrying"
1276
- });
1685
+ }, false);
1277
1686
  }
1278
1687
  error.value = null;
1279
1688
  return options.onRetry?.();
@@ -1288,13 +1697,13 @@ function insertBoundary(parent, anchor, options) {
1288
1697
  const currentError = error.value;
1289
1698
  if (!currentError) {
1290
1699
  if (fallbackActive && lastError) {
1291
- invokeRuntimeDebug("error", {
1700
+ reportBoundaryError({
1292
1701
  error: lastError,
1293
1702
  owner: boundary,
1294
1703
  phase: "boundary",
1295
1704
  handled: true,
1296
1705
  recovery: "recovered"
1297
- });
1706
+ }, false);
1298
1707
  lastError = null;
1299
1708
  }
1300
1709
  fallbackActive = false;
@@ -1438,15 +1847,80 @@ function now() {
1438
1847
  return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
1439
1848
  }
1440
1849
  __name(now, "now");
1850
+
1851
+ // packages/runtime/src/show.ts
1852
+ var import_reactivity9 = require("@vobs/reactivity");
1853
+ function Show(props) {
1854
+ const resolved = typeof props.children === "function" ? props.children() : props.children;
1855
+ if (resolved === null || resolved === void 0 || resolved === false) {
1856
+ throw new Error("Vobs Show: children \u4E0D\u80FD\u4E3A\u7A7A \u2014\u2014 \u5B83\u9700\u8981\u4E00\u4E2A\u5BBF\u4E3B\u5143\u7D20\u6765\u6302 hidden/inert\u3002");
1857
+ }
1858
+ const node = resolved;
1859
+ if (isVobsFragment(node) || node.nodeType !== 1) {
1860
+ throw new Error(
1861
+ "Vobs Show: children \u5FC5\u987B\u662F\u5355\u4E2A\u5143\u7D20\u3002\u300C\u4FDD\u7559\u6302\u8F7D + \u5207\u53EF\u89C1\u6027\u300D\u9700\u8981\u5BBF\u4E3B\u5143\u7D20\uFF0C\u800C\u6846\u67B6\u4E0D\u4F1A\u66FF\u4F60\u63D2\u5305\u88F9\u5C42\uFF08\u4F1A\u6539\u5E03\u5C40\uFF09\u3002\u8BF7\u628A\u5185\u5BB9\u5305\u8FDB\u4E00\u4E2A\u5143\u7D20\uFF0C\u4F8B\u5982 <Show when={\u2026}><div>\u2026</div></Show>\uFF1B\u82E5\u786E\u5B9E\u9700\u8981\u5378\u8F7D\u8BED\u4E49\uFF0C\u8BF7\u6539\u7528 JSX \u6761\u4EF6\u8868\u8FBE\u5F0F {cond ? <A/> : <B/>}\u3002"
1862
+ );
1863
+ }
1864
+ const element = node;
1865
+ (0, import_reactivity9.effect)(() => {
1866
+ const visible = Boolean(readMaybeGetter(props.when));
1867
+ setProperty(element, "hidden", !visible);
1868
+ if (visible) removeAttribute(element, "inert");
1869
+ else setAttribute(element, "inert", "");
1870
+ if (props.hiddenClass !== void 0) applyExtraClass(element, props.hiddenClass, !visible);
1871
+ });
1872
+ return element;
1873
+ }
1874
+ __name(Show, "Show");
1875
+ function readMaybeGetter(value) {
1876
+ return typeof value === "function" ? value() : value;
1877
+ }
1878
+ __name(readMaybeGetter, "readMaybeGetter");
1879
+ function applyExtraClass(element, className, on) {
1880
+ const names = element.getAttribute("class")?.split(/\s+/u).filter(Boolean) ?? [];
1881
+ if (on) {
1882
+ if (names.includes(className)) return;
1883
+ setAttribute(element, "class", [...names, className].join(" "));
1884
+ return;
1885
+ }
1886
+ if (!names.includes(className)) return;
1887
+ setAttribute(element, "class", names.filter((name) => name !== className).join(" "));
1888
+ }
1889
+ __name(applyExtraClass, "applyExtraClass");
1890
+
1891
+ // packages/runtime/src/client-only.ts
1892
+ var import_reactivity10 = require("@vobs/reactivity");
1893
+ function ClientOnly(props = {}) {
1894
+ return createFragment((parent, anchor) => {
1895
+ const ready = (0, import_reactivity10.state)(false);
1896
+ if (typeof document !== "undefined") {
1897
+ const owner = (0, import_reactivity10.getCurrentOwner)();
1898
+ queueMicrotask(() => {
1899
+ if (owner?.disposed) return;
1900
+ ready.value = true;
1901
+ });
1902
+ }
1903
+ insertDynamic(parent, anchor, () => {
1904
+ const slot = ready.value ? props.children : props.fallback;
1905
+ const value = typeof slot === "function" ? slot() : slot;
1906
+ return value === void 0 || value === null || value === false ? null : value;
1907
+ });
1908
+ });
1909
+ }
1910
+ __name(ClientOnly, "ClientOnly");
1441
1911
  // Annotate the CommonJS export names for ESM import in node:
1442
1912
  0 && (module.exports = {
1443
1913
  AsyncBoundary,
1914
+ ClientOnly,
1444
1915
  ErrorBoundary,
1445
1916
  Profiler,
1917
+ Show,
1446
1918
  VobsError,
1447
1919
  addEventListener,
1920
+ applyClassList,
1448
1921
  bindAttribute,
1449
1922
  bindProperty,
1923
+ bindSpreadProps,
1450
1924
  bindText,
1451
1925
  clear,
1452
1926
  cloneTemplate,
@@ -1456,6 +1930,7 @@ __name(now, "now");
1456
1930
  createElement,
1457
1931
  createFragment,
1458
1932
  createHmrStateStore,
1933
+ createSvgElement,
1459
1934
  createTemplate,
1460
1935
  createText,
1461
1936
  createVobsError,
@@ -1481,9 +1956,11 @@ __name(now, "now");
1481
1956
  markHmrInstanceMounted,
1482
1957
  normalizeDynamicChild,
1483
1958
  normalizeVobsError,
1959
+ parseClassList,
1484
1960
  pushRuntimeDebugContext,
1485
1961
  ref,
1486
1962
  registerHmrInstance,
1963
+ removeAttribute,
1487
1964
  removeChild,
1488
1965
  removeEventListener,
1489
1966
  resolveComponent,