voodoojs 0.12.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-XGZ7SXD3.js → chunk-2LGAXVD7.js} +4 -4
  3. package/dist/{chunk-XIMSOXWF.js → chunk-4IJE5BWY.js} +5 -5
  4. package/dist/{chunk-FAWOJTRM.js → chunk-FMDHZ5GI.js} +139 -9
  5. package/dist/{chunk-OHISQWSW.js → chunk-GE4JWATC.js} +5 -5
  6. package/dist/{chunk-2GSZT3CX.js → chunk-H2NGDLMD.js} +363 -76
  7. package/dist/{chunk-AR6WDY7K.js → chunk-IBIZ6OUI.js} +4 -4
  8. package/dist/{chunk-7XRFOONN.js → chunk-IJQ2PFXU.js} +3 -3
  9. package/dist/{chunk-ELIX2DRQ.js → chunk-JBUNTP7F.js} +19 -7
  10. package/dist/{chunk-NKQGUWVF.js → chunk-MV73OSCS.js} +4 -4
  11. package/dist/{chunk-3MPIJH5X.js → chunk-OIH4BR2H.js} +6 -6
  12. package/dist/{chunk-FNTYILLW.js → chunk-TEVCUTTC.js} +3 -3
  13. package/dist/essential.cjs +508 -74
  14. package/dist/essential.d.cts +1 -1
  15. package/dist/essential.d.ts +1 -1
  16. package/dist/essential.js +10 -10
  17. package/dist/gpu.cjs +7 -1
  18. package/dist/gpu.js +10 -10
  19. package/dist/http.cjs +1 -1
  20. package/dist/http.js +5 -5
  21. package/dist/index.cjs +556 -122
  22. package/dist/index.d.cts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +20 -20
  25. package/dist/reactivity.cjs +138 -5
  26. package/dist/reactivity.d.cts +32 -1
  27. package/dist/reactivity.d.ts +32 -1
  28. package/dist/reactivity.js +2 -2
  29. package/dist/socket.cjs +115 -5
  30. package/dist/socket.d.cts +1 -1
  31. package/dist/socket.d.ts +1 -1
  32. package/dist/socket.js +9 -9
  33. package/dist/style-E22XVZ33.js +5 -0
  34. package/dist/utils.cjs +1 -1
  35. package/dist/utils.js +2 -2
  36. package/dist/voodoo.core.js +572 -72
  37. package/dist/voodoo.core.min.js +17 -17
  38. package/dist/voodoo.full.js +621 -121
  39. package/dist/voodoo.full.min.js +62 -62
  40. package/dist/voodoo.js +575 -75
  41. package/dist/voodoo.min.js +26 -26
  42. package/package.json +1 -1
  43. package/dist/style-DA6RFLKO.js +0 -5
  44. package/dist/{query-XooOh4vB.d.cts → query-D_BGQw8m.d.cts} +28 -28
  45. package/dist/{query-DzHfm8Kg.d.ts → query-Dl6Urlwd.d.ts} +28 -28
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Voodoo.js v0.12.4
2
+ * Voodoo.js v0.13.0
3
3
  * JavaScript feels like magic.
4
4
  * (c) 2026 Voodoo.js contributors. MIT License.
5
5
  */
@@ -31,10 +31,12 @@ var Voodoo = (() => {
31
31
  // src/reactivity/index.ts
32
32
  var reactivity_exports = {};
33
33
  __export(reactivity_exports, {
34
+ ArrayOp: () => ArrayOp,
34
35
  EffectScope: () => EffectScope,
35
36
  ITERATE_KEY: () => ITERATE_KEY,
36
37
  ReactiveEffect: () => ReactiveEffect,
37
38
  TriggerType: () => TriggerType,
39
+ arrayVersion: () => arrayVersion,
38
40
  computed: () => computed,
39
41
  effect: () => effect,
40
42
  effectScope: () => effectScope,
@@ -47,6 +49,7 @@ var Voodoo = (() => {
47
49
  isReactive: () => isReactive,
48
50
  isRef: () => isRef,
49
51
  markRaw: () => markRaw,
52
+ mutationsSince: () => mutationsSince,
50
53
  nextTick: () => nextTick,
51
54
  pauseTracking: () => pauseTracking,
52
55
  queueJob: () => queueJob,
@@ -210,7 +213,9 @@ var Voodoo = (() => {
210
213
  if (!isArr) add(depsMap.get(ITERATE_KEY));
211
214
  else if (isIntegerKey(key)) add(depsMap.get("length"));
212
215
  } else if (type === "delete" /* DELETE */) {
213
- if (!isArr) add(depsMap.get(ITERATE_KEY));
216
+ add(depsMap.get(ITERATE_KEY));
217
+ } else if (isArr && isIntegerKey(key)) {
218
+ add(depsMap.get(ITERATE_KEY));
214
219
  } else if (isArr && key === "length") {
215
220
  const newLen = Number(_newValue);
216
221
  depsMap.forEach((dep, k) => {
@@ -223,12 +228,61 @@ var Voodoo = (() => {
223
228
  else queueJob(e);
224
229
  }
225
230
  }
231
+ function triggerArrayRange(target, from) {
232
+ const depsMap = targetMap.get(target);
233
+ if (!depsMap) return;
234
+ const effects = /* @__PURE__ */ new Set();
235
+ const add = (dep) => {
236
+ if (!dep) return;
237
+ for (const e of dep) if (e !== activeEffect) effects.add(e);
238
+ };
239
+ add(depsMap.get("length"));
240
+ add(depsMap.get(ITERATE_KEY));
241
+ if (from >= 0) {
242
+ depsMap.forEach((dep, k) => {
243
+ if (typeof k === "string" && isIntegerKey(k) && Number(k) >= from) add(dep);
244
+ });
245
+ }
246
+ for (const e of effects) {
247
+ if (e.scheduler) e.scheduler();
248
+ else queueJob(e);
249
+ }
250
+ }
251
+ function record(target, type, index, removed, added) {
252
+ let log = mutationLogs.get(target);
253
+ if (!log) mutationLogs.set(target, log = { version: 0, ops: [] });
254
+ log.version++;
255
+ if (type === 3 /* RESET */) {
256
+ log.ops.length = 0;
257
+ return;
258
+ }
259
+ log.ops.push({ type, index, removed, added });
260
+ if (log.ops.length > LOG_LIMIT) log.ops.shift();
261
+ }
262
+ function arrayVersion(target) {
263
+ const log = mutationLogs.get(target);
264
+ return log ? log.version : 0;
265
+ }
266
+ function mutationsSince(target, since) {
267
+ const log = mutationLogs.get(target);
268
+ if (!log) return since === 0 ? NO_MUTATIONS : null;
269
+ if (since > log.version) return null;
270
+ const missing = log.version - since;
271
+ if (missing === 0) return NO_MUTATIONS;
272
+ if (missing > log.ops.length) return null;
273
+ return log.ops.slice(log.ops.length - missing);
274
+ }
226
275
  function isIntegerKey(key) {
227
276
  return typeof key === "string" && key !== "NaN" && key[0] !== "-" && String(parseInt(key, 10)) === key;
228
277
  }
229
278
  function isObject(val) {
230
279
  return val !== null && typeof val === "object";
231
280
  }
281
+ function spliceStart(raw, length) {
282
+ const n = Math.trunc(Number(raw)) || 0;
283
+ if (n < 0) return Math.max(length + n, 0);
284
+ return Math.min(n, length);
285
+ }
232
286
  function canObserve(value) {
233
287
  if (!isObject(value)) return false;
234
288
  if (value[SKIP]) return false;
@@ -238,6 +292,23 @@ var Voodoo = (() => {
238
292
  if (NON_REACTIVE.has(tag)) return false;
239
293
  return tag === "Object" || tag === "Array" || tag === "Map" || tag === "Set";
240
294
  }
295
+ function recordDirectWrite(target, key, lengthBefore, hadKey, oldValue, value) {
296
+ if (key === "length") {
297
+ const next = target.length;
298
+ if (next < lengthBefore) record(target, 1 /* SPLICE */, next, lengthBefore - next, 0);
299
+ else if (next > lengthBefore) record(target, 3 /* RESET */, 0, 0, 0);
300
+ return;
301
+ }
302
+ if (!isIntegerKey(key)) return;
303
+ const index = Number(key);
304
+ if (hadKey) {
305
+ if (hasChanged(value, oldValue)) record(target, 2 /* SET */, index, 1, 1);
306
+ } else if (index === lengthBefore) {
307
+ record(target, 1 /* SPLICE */, index, 0, 1);
308
+ } else {
309
+ record(target, 3 /* RESET */, 0, 0, 0);
310
+ }
311
+ }
241
312
  function markRaw(value) {
242
313
  Object.defineProperty(value, SKIP, { value: true, enumerable: false, configurable: true });
243
314
  return value;
@@ -360,7 +431,7 @@ var Voodoo = (() => {
360
431
  else for (const key of Object.keys(value)) traverse(value[key], seen);
361
432
  return value;
362
433
  }
363
- var resolvedPromise, queue, postQueue, isFlushing, isFlushPending, flushPromise, RECURSION_LIMIT, errorHandler, activeEffect, shouldTrack, trackStack, effectId, ReactiveEffect, activeScope, EffectScope, ITERATE_KEY, targetMap, TriggerType, RAW, IS_REACTIVE, SKIP, reactiveMap, arrayInstrumentations, NON_REACTIVE, baseHandlers, collectionHandlers, RefImpl, ComputedRefImpl;
434
+ var resolvedPromise, queue, postQueue, isFlushing, isFlushPending, flushPromise, RECURSION_LIMIT, errorHandler, activeEffect, shouldTrack, trackStack, effectId, ReactiveEffect, activeScope, EffectScope, ITERATE_KEY, targetMap, TriggerType, ArrayOp, LOG_LIMIT, mutationLogs, NO_MUTATIONS, RAW, IS_REACTIVE, SKIP, reactiveMap, arrayInstrumentations, NON_REACTIVE, baseHandlers, collectionHandlers, RefImpl, ComputedRefImpl;
364
435
  var init_reactivity = __esm({
365
436
  "src/reactivity/index.ts"() {
366
437
  "use strict";
@@ -490,6 +561,15 @@ var Voodoo = (() => {
490
561
  TriggerType2["CLEAR"] = "clear";
491
562
  return TriggerType2;
492
563
  })(TriggerType || {});
564
+ ArrayOp = /* @__PURE__ */ ((ArrayOp2) => {
565
+ ArrayOp2[ArrayOp2["SPLICE"] = 1] = "SPLICE";
566
+ ArrayOp2[ArrayOp2["SET"] = 2] = "SET";
567
+ ArrayOp2[ArrayOp2["RESET"] = 3] = "RESET";
568
+ return ArrayOp2;
569
+ })(ArrayOp || {});
570
+ LOG_LIMIT = 32;
571
+ mutationLogs = /* @__PURE__ */ new WeakMap();
572
+ NO_MUTATIONS = [];
493
573
  RAW = /* @__PURE__ */ Symbol("voodoo:raw");
494
574
  IS_REACTIVE = /* @__PURE__ */ Symbol("voodoo:isReactive");
495
575
  SKIP = /* @__PURE__ */ Symbol("voodoo:skip");
@@ -507,14 +587,61 @@ var Voodoo = (() => {
507
587
  return res;
508
588
  };
509
589
  }
510
- for (const key of ["push", "pop", "shift", "unshift", "splice"]) {
590
+ for (const key of ["push", "pop", "shift", "unshift", "splice", "reverse", "sort"]) {
511
591
  inst[key] = function(...args) {
592
+ const raw = toRaw(this);
593
+ const before = raw.length;
594
+ for (let i = 0; i < args.length; i++) args[i] = toRaw(args[i]);
512
595
  pauseTracking();
596
+ let result;
513
597
  try {
514
- return toRaw(this)[key].apply(this, args);
598
+ result = raw[key].apply(raw, args);
515
599
  } finally {
516
600
  resetTracking();
517
601
  }
602
+ const after = raw.length;
603
+ let from = -1;
604
+ if (key === "push") {
605
+ if (args.length) {
606
+ record(raw, 1 /* SPLICE */, before, 0, args.length);
607
+ from = before;
608
+ }
609
+ } else if (key === "unshift") {
610
+ if (args.length) {
611
+ record(raw, 1 /* SPLICE */, 0, 0, args.length);
612
+ from = 0;
613
+ }
614
+ } else if (key === "pop") {
615
+ if (before > 0) {
616
+ record(raw, 1 /* SPLICE */, after, 1, 0);
617
+ from = after;
618
+ }
619
+ } else if (key === "shift") {
620
+ if (before > 0) {
621
+ record(raw, 1 /* SPLICE */, 0, 1, 0);
622
+ from = 0;
623
+ }
624
+ } else if (key === "splice") {
625
+ const removed = result.length;
626
+ const added = args.length > 2 ? args.length - 2 : 0;
627
+ if (removed || added) {
628
+ record(raw, 1 /* SPLICE */, spliceStart(args[0], before), removed, added);
629
+ from = spliceStart(args[0], before);
630
+ }
631
+ } else {
632
+ if (before > 1) {
633
+ record(raw, 3 /* RESET */, 0, before, after);
634
+ from = 0;
635
+ }
636
+ }
637
+ if (from >= 0) triggerArrayRange(raw, from);
638
+ if (key === "pop" || key === "shift") return isObject(result) ? reactive(result) : result;
639
+ if (key === "splice") {
640
+ const out = result;
641
+ for (let i = 0; i < out.length; i++) if (isObject(out[i])) out[i] = reactive(out[i]);
642
+ return out;
643
+ }
644
+ return key === "reverse" || key === "sort" ? this : result;
518
645
  };
519
646
  }
520
647
  return inst;
@@ -556,8 +683,11 @@ var Voodoo = (() => {
556
683
  return true;
557
684
  }
558
685
  const hadKey = Array.isArray(target) && isIntegerKey(key) ? Number(key) < target.length : Object.prototype.hasOwnProperty.call(target, key);
686
+ const isArr = Array.isArray(target);
687
+ const arrayLength = isArr ? target.length : 0;
559
688
  const result = Reflect.set(target, key, value, receiver);
560
689
  if (target === toRaw(receiver)) {
690
+ if (isArr) recordDirectWrite(target, key, arrayLength, hadKey, oldValue, value);
561
691
  if (!hadKey) trigger(target, "add" /* ADD */, key, value);
562
692
  else if (hasChanged(value, oldValue)) trigger(target, "set" /* SET */, key, value);
563
693
  }
@@ -566,7 +696,10 @@ var Voodoo = (() => {
566
696
  deleteProperty(target, key) {
567
697
  const hadKey = Object.prototype.hasOwnProperty.call(target, key);
568
698
  const result = Reflect.deleteProperty(target, key);
569
- if (result && hadKey) trigger(target, "delete" /* DELETE */, key);
699
+ if (result && hadKey) {
700
+ if (Array.isArray(target)) record(target, 3 /* RESET */, 0, 0, 0);
701
+ trigger(target, "delete" /* DELETE */, key);
702
+ }
570
703
  return result;
571
704
  },
572
705
  has(target, key) {
@@ -2510,8 +2643,15 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2510
2643
  list.push(scope);
2511
2644
  }
2512
2645
  var ignoredRemovals = /* @__PURE__ */ new WeakSet();
2646
+ var detachedTemplates = /* @__PURE__ */ new WeakMap();
2513
2647
  function removeQuietly(node) {
2514
2648
  ignoredRemovals.add(node);
2649
+ const parent = node.parentNode;
2650
+ if (parent) {
2651
+ let kept = detachedTemplates.get(parent);
2652
+ if (!kept) detachedTemplates.set(parent, kept = /* @__PURE__ */ new Set());
2653
+ kept.add(node);
2654
+ }
2515
2655
  node.remove();
2516
2656
  }
2517
2657
  function addCleanup(node, fn) {
@@ -2527,6 +2667,11 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2527
2667
  }
2528
2668
  for (let i = children.length - 1; i >= 0; i--) destroy(children[i]);
2529
2669
  }
2670
+ const detached = detachedTemplates.get(node);
2671
+ if (detached) {
2672
+ detachedTemplates.delete(node);
2673
+ for (const template of detached) destroy(template);
2674
+ }
2530
2675
  const list = nodeCleanups.get(node);
2531
2676
  if (list) {
2532
2677
  nodeCleanups.delete(node);
@@ -5659,6 +5804,35 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5659
5804
  // src/directives/core.ts
5660
5805
  init_reactivity();
5661
5806
  init_registry();
5807
+
5808
+ // src/runtime/metrics.ts
5809
+ function blank() {
5810
+ return {
5811
+ on: false,
5812
+ itemsVisited: 0,
5813
+ keyEvaluations: 0,
5814
+ prefixScanned: 0,
5815
+ suffixScanned: 0,
5816
+ middleReconciled: 0,
5817
+ scopeAllocations: 0,
5818
+ proxyWrites: 0,
5819
+ arrayAllocations: 0,
5820
+ keyMapLookups: 0,
5821
+ domCreates: 0,
5822
+ domRemoves: 0,
5823
+ domMoves: 0,
5824
+ domInserts: 0,
5825
+ lisRuns: 0,
5826
+ lisElements: 0,
5827
+ paths: {}
5828
+ };
5829
+ }
5830
+ var metrics = /* @__PURE__ */ blank();
5831
+ function countPath(name) {
5832
+ metrics.paths[name] = (metrics.paths[name] || 0) + 1;
5833
+ }
5834
+
5835
+ // src/directives/core.ts
5662
5836
  function setValue(expression, scope, value) {
5663
5837
  try {
5664
5838
  const target = parse(expression);
@@ -5804,7 +5978,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5804
5978
  },
5805
5979
  { priority: PRIORITY.IF, terminal: true }
5806
5980
  );
5807
- function renderTemplate(source, anchor, scope, batch) {
5981
+ function renderTemplate(source, anchor, scope) {
5808
5982
  const parent = anchor.parentNode;
5809
5983
  if (!parent) return [];
5810
5984
  const nodes = [];
@@ -5821,21 +5995,64 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5821
5995
  }
5822
5996
  } else {
5823
5997
  const clone2 = source.cloneNode(true);
5998
+ if (metrics.on) metrics.domCreates++;
5824
5999
  nodes.push(clone2);
5825
6000
  markNodeScope(clone2, scope);
5826
- if (batch) {
5827
- batch.fragment.appendChild(clone2);
5828
- batch.pending.push([clone2, scope]);
5829
- } else {
5830
- parent.insertBefore(clone2, anchor);
5831
- walk(clone2, scope);
5832
- }
6001
+ parent.insertBefore(clone2, anchor);
6002
+ walk(clone2, scope);
5833
6003
  }
5834
6004
  return nodes;
5835
6005
  }
5836
6006
  defineDirective("else-if", () => void 0, { priority: PRIORITY.IF, terminal: true });
5837
6007
  defineDirective("else", () => void 0, { priority: PRIORITY.IF, terminal: true });
5838
6008
  var FOR_PATTERN = /^\s*\(?\s*([^)]*?)\s*\)?\s+(?:in|of)\s+(.+?)\s*$/;
6009
+ var KEY_PATH = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/;
6010
+ var NO_BLOCKS = [];
6011
+ function sameStored(stored, incoming) {
6012
+ if (stored === incoming) return true;
6013
+ return incoming !== null && typeof incoming === "object" && stored === toRaw(incoming);
6014
+ }
6015
+ function sameKey(a, b) {
6016
+ return a === b || a !== a && b !== b;
6017
+ }
6018
+ function longestIncreasing(arr) {
6019
+ const length = arr.length;
6020
+ const previous = new Int32Array(length);
6021
+ const tails = [];
6022
+ for (let i = 0; i < length; i++) {
6023
+ const value = arr[i];
6024
+ if (value === 0) continue;
6025
+ if (tails.length === 0) {
6026
+ tails.push(i);
6027
+ continue;
6028
+ }
6029
+ const last = tails[tails.length - 1];
6030
+ if (arr[last] < value) {
6031
+ previous[i] = last;
6032
+ tails.push(i);
6033
+ continue;
6034
+ }
6035
+ let low = 0;
6036
+ let high = tails.length - 1;
6037
+ while (low < high) {
6038
+ const mid = low + high >> 1;
6039
+ if (arr[tails[mid]] < value) low = mid + 1;
6040
+ else high = mid;
6041
+ }
6042
+ if (value < arr[tails[low]]) {
6043
+ if (low > 0) previous[i] = tails[low - 1];
6044
+ tails[low] = i;
6045
+ }
6046
+ }
6047
+ let cursor = tails.length;
6048
+ const out = new Int32Array(cursor);
6049
+ let node = tails[cursor - 1];
6050
+ while (cursor-- > 0) {
6051
+ out[cursor] = node;
6052
+ node = previous[node];
6053
+ }
6054
+ return out;
6055
+ }
5839
6056
  defineDirective(
5840
6057
  "for",
5841
6058
  ({ el, scope, expression, effect: effect2 }) => {
@@ -5861,78 +6078,361 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5861
6078
  template.removeAttribute(`${p2}bind:key`);
5862
6079
  template.removeAttribute(`${p2}key`);
5863
6080
  removeQuietly(el);
6081
+ const isTemplateRow = template.tagName === "TEMPLATE";
6082
+ let keyIsItem = false;
6083
+ let keyIsIndex = false;
6084
+ let keyProp = null;
6085
+ let keyPath = null;
6086
+ if (keyExpression && KEY_PATH.test(keyExpression)) {
6087
+ const parts = keyExpression.split(".");
6088
+ if (parts[0] === itemAlias) {
6089
+ if (parts.length === 1) keyIsItem = true;
6090
+ else if (parts.length === 2) keyProp = parts[1];
6091
+ else keyPath = parts.slice(1);
6092
+ } else if (indexAlias && parts.length === 1 && parts[0] === indexAlias) {
6093
+ keyIsIndex = true;
6094
+ }
6095
+ }
5864
6096
  let blocks = [];
5865
- const clearAll = () => {
5866
- for (const block2 of blocks) {
5867
- for (const node of block2.nodes) {
5868
- destroy(node);
5869
- node.remove();
6097
+ let rows = [];
6098
+ let entries = null;
6099
+ let count = 0;
6100
+ let keyScope = null;
6101
+ let lastSource = null;
6102
+ let lastVersion = 0;
6103
+ const pending = [];
6104
+ const pendingRuns = [];
6105
+ const varsAt = (i) => {
6106
+ if (entries) return entries[i];
6107
+ const vars = { [itemAlias]: rows[i] };
6108
+ if (indexAlias) vars[indexAlias] = i;
6109
+ return vars;
6110
+ };
6111
+ const keyAt = (i) => {
6112
+ if (metrics.on) metrics.keyEvaluations++;
6113
+ if (keyIsIndex) return i;
6114
+ if (!keyExpression) {
6115
+ return i;
6116
+ }
6117
+ const item = entries ? entries[i][itemAlias] : rows[i];
6118
+ if (keyIsItem) return item;
6119
+ if (keyProp !== null) return item == null ? void 0 : item[keyProp];
6120
+ if (keyPath !== null) {
6121
+ let value = item;
6122
+ for (let d = 0; d < keyPath.length; d++) {
6123
+ if (value == null) return void 0;
6124
+ value = value[keyPath[d]];
5870
6125
  }
6126
+ return value;
5871
6127
  }
5872
- blocks = [];
6128
+ if (!keyScope) keyScope = scope.child({});
6129
+ keyScope.data = varsAt(i);
6130
+ return evaluateIn(keyExpression, keyScope, ":key");
5873
6131
  };
5874
- addCleanup(anchor, clearAll);
5875
- effect2(() => {
5876
- var _a3, _b, _c;
5877
- const source = evaluateIn(sourceExpression, scope, "v-for");
5878
- const entries = normalizeSource(source, itemAlias, indexAlias, thirdAlias);
5879
- const previous = /* @__PURE__ */ new Map();
5880
- for (const block2 of blocks) previous.set(block2.key, block2);
5881
- const next = [];
5882
- const used = /* @__PURE__ */ new Set();
5883
- const batch = {
5884
- fragment: document.createDocumentFragment(),
5885
- pending: []
5886
- };
5887
- entries.forEach((vars, index) => {
5888
- const key = keyExpression ? evaluateIn(keyExpression, scope.child(vars), ":key") : `__index_${index}`;
5889
- if (keyExpression && used.has(key)) warnDuplicateKey(el, key, expression);
5890
- const existing = previous.get(key);
5891
- if (existing && !used.has(key)) {
5892
- used.add(key);
5893
- for (const [name, value] of Object.entries(vars)) existing.data[name] = value;
5894
- next.push(existing);
5895
- return;
6132
+ const syncData = (block2, i) => {
6133
+ const raw = toRaw(block2.data);
6134
+ if (entries) {
6135
+ const vars = entries[i];
6136
+ for (const name in vars) {
6137
+ if (!sameStored(raw[name], vars[name])) {
6138
+ if (metrics.on) metrics.proxyWrites++;
6139
+ block2.data[name] = vars[name];
6140
+ }
5896
6141
  }
5897
- const childScope = scope.reactiveChild(vars);
5898
- const nodes = renderTemplate(template, anchor, childScope, batch);
5899
- used.add(key);
5900
- next.push({ key, scope: childScope, nodes, data: childScope.data });
5901
- });
5902
- if (batch.fragment.firstChild) (_a3 = anchor.parentNode) == null ? void 0 : _a3.insertBefore(batch.fragment, anchor);
5903
- for (const [node, rowScope] of batch.pending) walk(node, rowScope);
5904
- const reused = new Set(next);
5905
- for (const block2 of blocks) {
5906
- if (used.has(block2.key) && reused.has(block2)) continue;
5907
- for (const node of block2.nodes) {
5908
- destroy(node);
5909
- node.remove();
6142
+ return;
6143
+ }
6144
+ const item = rows[i];
6145
+ if (!sameStored(raw[itemAlias], item)) {
6146
+ if (metrics.on) metrics.proxyWrites++;
6147
+ block2.data[itemAlias] = item;
6148
+ }
6149
+ if (indexAlias !== void 0 && raw[indexAlias] !== i) {
6150
+ if (metrics.on) metrics.proxyWrites++;
6151
+ block2.data[indexAlias] = i;
6152
+ }
6153
+ };
6154
+ const buildRange = (from, to, before, out) => {
6155
+ if (from >= to) return;
6156
+ const parent = anchor.parentNode;
6157
+ if (!parent) return;
6158
+ pendingRuns.push(pending.length);
6159
+ if (isTemplateRow) {
6160
+ for (let i = from; i < to; i++) {
6161
+ const childScope = scope.reactiveChild(varsAt(i));
6162
+ if (metrics.on) {
6163
+ metrics.scopeAllocations++;
6164
+ metrics.itemsVisited++;
6165
+ }
6166
+ const nodes = renderTemplate(template, before, childScope);
6167
+ out.push({ key: keyAt(i), scope: childScope, nodes, data: childScope.data });
5910
6168
  }
6169
+ return;
5911
6170
  }
5912
- let cursor = anchor;
5913
- for (let i = next.length - 1; i >= 0; i--) {
5914
- const block2 = next[i];
5915
- const last = block2.nodes[block2.nodes.length - 1];
5916
- if (last && last.nextSibling !== cursor) {
5917
- for (const node of block2.nodes) (_b = anchor.parentNode) == null ? void 0 : _b.insertBefore(node, cursor);
6171
+ const fragment = document.createDocumentFragment();
6172
+ for (let i = from; i < to; i++) {
6173
+ const childScope = scope.reactiveChild(varsAt(i));
6174
+ const clone2 = template.cloneNode(true);
6175
+ markNodeScope(clone2, childScope);
6176
+ fragment.appendChild(clone2);
6177
+ pending.push([clone2, childScope]);
6178
+ out.push({ key: keyAt(i), scope: childScope, nodes: [clone2], data: childScope.data });
6179
+ if (metrics.on) {
6180
+ metrics.scopeAllocations++;
6181
+ metrics.domCreates++;
6182
+ metrics.itemsVisited++;
5918
6183
  }
5919
- cursor = (_c = block2.nodes[0]) != null ? _c : cursor;
5920
6184
  }
5921
- blocks = next;
6185
+ if (metrics.on) metrics.domInserts++;
6186
+ parent.insertBefore(fragment, before);
6187
+ };
6188
+ const destroyBlock = (block2) => {
6189
+ const nodes = block2.nodes;
6190
+ for (let j = 0; j < nodes.length; j++) {
6191
+ if (metrics.on) metrics.domRemoves++;
6192
+ destroy(nodes[j]);
6193
+ nodes[j].remove();
6194
+ }
6195
+ };
6196
+ const moveBlock = (block2, before) => {
6197
+ const parent = anchor.parentNode;
6198
+ if (!parent) return;
6199
+ const nodes = block2.nodes;
6200
+ if (nodes[nodes.length - 1].nextSibling === before) return;
6201
+ for (let j = 0; j < nodes.length; j++) {
6202
+ if (metrics.on) metrics.domMoves++;
6203
+ parent.insertBefore(nodes[j], before);
6204
+ }
6205
+ };
6206
+ const nodeAfter = (oldIndex) => oldIndex < blocks.length ? blocks[oldIndex].nodes[0] : anchor;
6207
+ const spliceBlocks = (index, remove, added) => {
6208
+ const addCount = added.length;
6209
+ if (remove === 0 && addCount === 0) return;
6210
+ if (blocks.length === 0) {
6211
+ blocks = added;
6212
+ return;
6213
+ }
6214
+ if (addCount === 0) {
6215
+ blocks.splice(index, remove);
6216
+ return;
6217
+ }
6218
+ if (addCount <= 1024) {
6219
+ blocks.splice(index, remove, ...added);
6220
+ return;
6221
+ }
6222
+ const out = new Array(blocks.length - remove + addCount);
6223
+ let w = 0;
6224
+ for (let k = 0; k < index; k++) out[w++] = blocks[k];
6225
+ for (let k = 0; k < addCount; k++) out[w++] = added[k];
6226
+ for (let k = index + remove; k < blocks.length; k++) out[w++] = blocks[k];
6227
+ blocks = out;
6228
+ };
6229
+ const flushPending = () => {
6230
+ for (let r = pendingRuns.length - 1; r >= 0; r--) {
6231
+ const start2 = pendingRuns[r];
6232
+ const end = r + 1 < pendingRuns.length ? pendingRuns[r + 1] : pending.length;
6233
+ for (let k = start2; k < end; k++) walk(pending[k][0], pending[k][1]);
6234
+ }
6235
+ pending.length = 0;
6236
+ pendingRuns.length = 0;
6237
+ };
6238
+ let lo = 0;
6239
+ let oldHi = 0;
6240
+ let newHi = 0;
6241
+ const regionFromMutations = (source) => {
6242
+ const ops = mutationsSince(source, lastVersion);
6243
+ if (!ops) return false;
6244
+ const oldLen = blocks.length;
6245
+ lo = 0;
6246
+ oldHi = 0;
6247
+ newHi = 0;
6248
+ let current2 = oldLen;
6249
+ for (let k = 0; k < ops.length; k++) {
6250
+ const op = ops[k];
6251
+ const index = op.index;
6252
+ const removed = op.type === 2 /* SET */ ? 1 : op.removed;
6253
+ const added = op.type === 2 /* SET */ ? 1 : op.added;
6254
+ const end = index + removed;
6255
+ if (k === 0) {
6256
+ lo = index;
6257
+ oldHi = end;
6258
+ newHi = index + added;
6259
+ } else if (end <= newHi) {
6260
+ if (index < lo) lo = index;
6261
+ newHi += added - removed;
6262
+ } else {
6263
+ if (index < lo) lo = index;
6264
+ oldHi = end - newHi + oldHi;
6265
+ newHi = index + added;
6266
+ }
6267
+ if (oldHi < lo) oldHi = lo;
6268
+ if (newHi < lo) newHi = lo;
6269
+ current2 += added - removed;
6270
+ }
6271
+ if (current2 !== count) return false;
6272
+ if (lo > oldHi || lo > newHi) return false;
6273
+ if (oldHi > oldLen || newHi > count) return false;
6274
+ if (metrics.on) countPath(ops.length === 0 ? "unchanged" : "mutation");
6275
+ if (indexAlias !== void 0 && oldHi - newHi !== 0) {
6276
+ for (let i = newHi; i < count; i++) syncData(blocks[i - newHi + oldHi], i);
6277
+ }
6278
+ return true;
6279
+ };
6280
+ const regionFromScan = () => {
6281
+ const oldLen = blocks.length;
6282
+ const newLen = count;
6283
+ let i = 0;
6284
+ const shared = oldLen < newLen ? oldLen : newLen;
6285
+ while (i < shared) {
6286
+ const block2 = blocks[i];
6287
+ if (!sameKey(block2.key, keyAt(i))) break;
6288
+ syncData(block2, i);
6289
+ i++;
6290
+ }
6291
+ if (metrics.on) {
6292
+ metrics.prefixScanned += i;
6293
+ metrics.itemsVisited += i;
6294
+ }
6295
+ let oe = oldLen - 1;
6296
+ let ne = newLen - 1;
6297
+ while (oe >= i && ne >= i) {
6298
+ const block2 = blocks[oe];
6299
+ if (!sameKey(block2.key, keyAt(ne))) break;
6300
+ syncData(block2, ne);
6301
+ oe--;
6302
+ ne--;
6303
+ }
6304
+ if (metrics.on) {
6305
+ const scanned = oldLen - 1 - oe;
6306
+ metrics.suffixScanned += scanned;
6307
+ metrics.itemsVisited += scanned;
6308
+ countPath("scan");
6309
+ }
6310
+ lo = i;
6311
+ oldHi = oe + 1;
6312
+ newHi = ne + 1;
6313
+ };
6314
+ const reconcileRegion = () => {
6315
+ const toPatch = newHi - lo;
6316
+ if (lo >= oldHi) {
6317
+ if (toPatch > 0) {
6318
+ const created = [];
6319
+ buildRange(lo, newHi, nodeAfter(lo), created);
6320
+ spliceBlocks(lo, 0, created);
6321
+ }
6322
+ return;
6323
+ }
6324
+ if (toPatch === 0) {
6325
+ if (metrics.on) metrics.itemsVisited += oldHi - lo;
6326
+ for (let j = lo; j < oldHi; j++) destroyBlock(blocks[j]);
6327
+ spliceBlocks(lo, oldHi - lo, NO_BLOCKS);
6328
+ return;
6329
+ }
6330
+ if (metrics.on) {
6331
+ metrics.arrayAllocations += 3;
6332
+ metrics.middleReconciled += toPatch;
6333
+ metrics.itemsVisited += toPatch + (oldHi - lo);
6334
+ }
6335
+ const keyToNew = /* @__PURE__ */ new Map();
6336
+ for (let n = lo; n < newHi; n++) {
6337
+ const key = keyAt(n);
6338
+ if (keyExpression && keyToNew.has(key)) warnDuplicateKey(el, key, expression);
6339
+ keyToNew.set(key, n);
6340
+ }
6341
+ const oldOfNew = new Int32Array(toPatch);
6342
+ const reused = new Array(toPatch);
6343
+ let matched = 0;
6344
+ let moved = false;
6345
+ let highestSoFar = 0;
6346
+ for (let o = lo; o < oldHi; o++) {
6347
+ const block2 = blocks[o];
6348
+ if (metrics.on) metrics.keyMapLookups++;
6349
+ const target = matched >= toPatch ? void 0 : keyToNew.get(block2.key);
6350
+ if (target === void 0 || reused[target - lo] !== void 0) {
6351
+ destroyBlock(block2);
6352
+ continue;
6353
+ }
6354
+ oldOfNew[target - lo] = o + 1;
6355
+ reused[target - lo] = block2;
6356
+ if (target >= highestSoFar) highestSoFar = target;
6357
+ else moved = true;
6358
+ syncData(block2, target);
6359
+ matched++;
6360
+ }
6361
+ const stay = moved ? longestIncreasing(oldOfNew) : null;
6362
+ if (metrics.on && moved) {
6363
+ metrics.lisRuns++;
6364
+ metrics.lisElements += toPatch;
6365
+ }
6366
+ let s = stay ? stay.length - 1 : -1;
6367
+ const region = new Array(toPatch);
6368
+ let before = nodeAfter(oldHi);
6369
+ let runEnd = -1;
6370
+ for (let n = toPatch - 1; n >= 0; n--) {
6371
+ const newIndex = lo + n;
6372
+ const block2 = reused[n];
6373
+ if (block2 === void 0) {
6374
+ if (runEnd < 0) runEnd = newIndex + 1;
6375
+ continue;
6376
+ }
6377
+ if (runEnd >= 0) {
6378
+ const created = [];
6379
+ buildRange(newIndex + 1, runEnd, before, created);
6380
+ for (let c = 0; c < created.length; c++) region[n + 1 + c] = created[c];
6381
+ if (created.length) before = created[0].nodes[0];
6382
+ runEnd = -1;
6383
+ }
6384
+ region[n] = block2;
6385
+ if (moved && (s < 0 || n !== stay[s])) moveBlock(block2, before);
6386
+ else if (moved) s--;
6387
+ before = block2.nodes[0];
6388
+ }
6389
+ if (runEnd >= 0) {
6390
+ const created = [];
6391
+ buildRange(lo, runEnd, before, created);
6392
+ for (let c = 0; c < created.length; c++) region[c] = created[c];
6393
+ }
6394
+ spliceBlocks(lo, oldHi - lo, region);
6395
+ };
6396
+ const clearAll = () => {
6397
+ for (const block2 of blocks) destroyBlock(block2);
6398
+ blocks = [];
6399
+ lastSource = null;
6400
+ lastVersion = 0;
6401
+ };
6402
+ addCleanup(anchor, clearAll);
6403
+ effect2(() => {
6404
+ const source = evaluateIn(sourceExpression, scope, "v-for");
6405
+ const raw = toRaw(source);
6406
+ let fromMutations = false;
6407
+ if (Array.isArray(raw)) {
6408
+ track(raw, "length");
6409
+ track(raw, ITERATE_KEY);
6410
+ rows = raw;
6411
+ entries = null;
6412
+ count = raw.length;
6413
+ const version3 = arrayVersion(raw);
6414
+ if (raw === lastSource && keyExpression && !keyIsIndex) {
6415
+ fromMutations = regionFromMutations(raw);
6416
+ }
6417
+ lastSource = raw;
6418
+ lastVersion = version3;
6419
+ } else {
6420
+ entries = normalizeSource(source, itemAlias, indexAlias, thirdAlias);
6421
+ rows = entries;
6422
+ count = entries.length;
6423
+ lastSource = null;
6424
+ lastVersion = 0;
6425
+ if (metrics.on) metrics.arrayAllocations += count + 1;
6426
+ }
6427
+ if (!fromMutations) regionFromScan();
6428
+ reconcileRegion();
6429
+ flushPending();
5922
6430
  });
5923
6431
  },
5924
6432
  { priority: PRIORITY.FOR, terminal: true }
5925
6433
  );
5926
6434
  function normalizeSource(source, itemAlias, indexAlias, thirdAlias) {
5927
6435
  const out = [];
5928
- if (Array.isArray(source)) {
5929
- source.forEach((item, index) => {
5930
- const vars = { [itemAlias]: item };
5931
- if (indexAlias) vars[indexAlias] = index;
5932
- out.push(vars);
5933
- });
5934
- return out;
5935
- }
5936
6436
  if (typeof source === "number") {
5937
6437
  for (let i = 1; i <= source; i++) {
5938
6438
  const vars = { [itemAlias]: i };
@@ -7078,7 +7578,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
7078
7578
  Object.defineProperties(rootScope.data, Object.getOwnPropertyDescriptors(values));
7079
7579
  return rootScope.data;
7080
7580
  }
7081
- var version2 = "0.12.4";
7581
+ var version2 = "0.13.0";
7082
7582
  var core = {
7083
7583
  // Utilities first: Voodoo's own names can override.
7084
7584
  ...utils_exports,