@vidact/runtime 0.2.0-beta.6 → 0.2.0-beta.8

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 (51) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/actions.js +1 -1
  3. package/dist/compiled/core.d.ts +17 -5
  4. package/dist/compiled/core.d.ts.map +1 -1
  5. package/dist/compiled/core.js +545 -155
  6. package/dist/compiled/core.js.map +1 -1
  7. package/dist/direct-dom.d.ts.map +1 -1
  8. package/dist/direct-dom.js +102 -11
  9. package/dist/direct-dom.js.map +1 -1
  10. package/dist/dom/events.d.ts +4 -1
  11. package/dist/dom/events.d.ts.map +1 -1
  12. package/dist/dom/events.js +66 -1
  13. package/dist/dom/events.js.map +1 -1
  14. package/dist/dom/namespace.js +1 -1
  15. package/dist/hydration-bridge.d.ts +4 -4
  16. package/dist/hydration-bridge.d.ts.map +1 -1
  17. package/dist/hydration-bridge.js.map +1 -1
  18. package/dist/hydration.d.ts +2 -2
  19. package/dist/hydration.d.ts.map +1 -1
  20. package/dist/hydration.js.map +1 -1
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +3 -3
  23. package/dist/keyed-list.d.ts +6 -2
  24. package/dist/keyed-list.d.ts.map +1 -1
  25. package/dist/keyed-list.js +122 -11
  26. package/dist/keyed-list.js.map +1 -1
  27. package/dist/metadata.js +1 -1
  28. package/dist/renderable.d.ts +2 -1
  29. package/dist/renderable.d.ts.map +1 -1
  30. package/dist/renderable.js +12 -1
  31. package/dist/renderable.js.map +1 -1
  32. package/dist/source-mask.d.ts +2 -1
  33. package/dist/source-mask.d.ts.map +1 -1
  34. package/dist/source-mask.js +16 -1
  35. package/dist/source-mask.js.map +1 -1
  36. package/dist/spread.js +2 -2
  37. package/dist/state-slot.d.ts +12 -1
  38. package/dist/state-slot.d.ts.map +1 -1
  39. package/dist/state-slot.js +54 -24
  40. package/dist/state-slot.js.map +1 -1
  41. package/package.json +3 -3
  42. package/src/compiled/core.ts +785 -179
  43. package/src/direct-dom.ts +136 -10
  44. package/src/dom/events.ts +86 -0
  45. package/src/hydration-bridge.ts +10 -4
  46. package/src/hydration.ts +5 -3
  47. package/src/index.ts +2 -0
  48. package/src/keyed-list.ts +168 -22
  49. package/src/renderable.ts +30 -0
  50. package/src/source-mask.ts +20 -0
  51. package/src/state-slot.ts +83 -27
@@ -1,11 +1,12 @@
1
- import { currentIntrinsicNamespace, withIntrinsicNamespace } from "../dom/intrinsic.js";
2
1
  import { HydrationMismatch, beginHydration, borrowHydrationSlotRange, claimHydrationArrayRange, claimHydrationComponentMount, claimHydrationComponentRange, claimHydrationNode, claimHydrationSlotRange, claimHydrationSuspenseFallback, claimHydrationText, claimHydrationTextRange, finishHydration, finishHydrationArrayRange, hydrationCursor, hydrationFragmentChildren, hydrationInsertionPoint, hydrationRangeParent, hydrationRootMarkers, isHydrating, isHydrationMismatch, noteHydrationStructuralParent, skipHydrationRange, withHydrationComponentRange, withHydrationCursor, withHydrationInsertion, withoutHydration } from "../hydration-bridge.js";
2
+ import { COMPILED_DELEGATED_EVENT_INVOKE, retainCompiledEventRoot } from "../dom/events.js";
3
+ import { currentIntrinsicNamespace, withIntrinsicNamespace } from "../dom/intrinsic.js";
3
4
  import { createKeyedList } from "../keyed-list.js";
4
5
  import { createIndexedList } from "../indexed-list.js";
5
6
  import { RENDERABLE, canReconcileRenderable, isRenderableProtocol, materializeRenderable, materializeRenderableWithInput, renderableIdentity, renderablePropsSnapshot } from "../renderable-protocol.js";
6
7
  import { scheduleDeferredTask, scheduleTask } from "../scheduler.js";
7
- import { intersectsSources, isEmptySources, unionSources } from "../source-mask.js";
8
- import { createStateSlot } from "../state-slot.js";
8
+ import { forEachSource, intersectsSources, isEmptySources, unionSources } from "../source-mask.js";
9
+ import { createReadOnlyStateSlot, createStateSlot, replaceReadOnlyStateSlot } from "../state-slot.js";
9
10
  import { BINDING, COMPONENT_SPREAD_SOURCE as COMPONENT_SPREAD_SOURCE$1, CONTEXT, STRUCTURAL } from "./types.js";
10
11
  import { isSuspension, subscribeResource, useAsync } from "./async-resource.js";
11
12
  import { hasInvalidChild } from "./validation.js";
@@ -17,24 +18,40 @@ let retainedUiEnabled = typeof __VIDACT_RETAINED_UI__ !== "undefined" && __VIDAC
17
18
  let profilingEnabled = false;
18
19
  let activeOwnerCount = 0;
19
20
  let createdOwnerCount = 0;
21
+ let createdUpdaterCount = 0;
22
+ let createdSchedulerPlanCount = 0;
20
23
  const noop = () => {};
24
+ const COMPILED_EVENT_HANDLER = Symbol("vidact.compiled-event");
25
+ const COMPILED_INLINE_EVENT_OWNER = Symbol("vidact.compiled-event.owner");
26
+ const UNSET_BINDING = Symbol(DEV ? "Vidact.UnsetBinding" : void 0);
21
27
  const wideSourceOperations = [
22
28
  isEmptySources,
23
29
  intersectsSources,
24
- unionSources
30
+ unionSources,
31
+ forEachSource
25
32
  ];
26
33
  const narrowSourceOperations = [
27
34
  (mask) => mask === 0,
28
35
  (left, right) => (left & right) !== 0,
29
- (left, right) => (left | right) >>> 0
36
+ (left, right) => (left | right) >>> 0,
37
+ (mask, visitor) => forEachSource(mask, visitor)
30
38
  ];
31
39
  function deferred(render) {
32
40
  return [
33
41
  STRUCTURAL,
34
42
  (parent, before) => {
35
- const hydrated = claimHydrationSlotRange(parent);
36
- if (hydrated === void 0) insertValue(parent, render(), before);
37
- else insertValue(parent, render(), hydrated[1]);
43
+ const value = render();
44
+ if (ownedStructuralBinding(value)?.[2] === "slot") {
45
+ insertValue(parent, value, before);
46
+ return;
47
+ }
48
+ const hydrated = borrowHydrationSlotRange(parent, true);
49
+ if (hydrated === void 0) {
50
+ insertValue(parent, value, before);
51
+ return;
52
+ }
53
+ claimHydrationSlotRange(parent);
54
+ insertValue(parent, value, hydrated[1]);
38
55
  },
39
56
  "slot"
40
57
  ];
@@ -241,7 +258,7 @@ function recordCompiledDebugValue(valueInput, format) {
241
258
  const remove = subscribeBinding(valueInput, () => {
242
259
  frame.values[index] = read();
243
260
  });
244
- owner[1].add(remove);
261
+ owner[1].push(remove);
245
262
  }
246
263
  }
247
264
  /** @internal */
@@ -503,6 +520,7 @@ function createPortalStructural(children, container) {
503
520
  const fragment = document.createDocumentFragment();
504
521
  fragment.append(start, end);
505
522
  const portalOwner = withRootIdentity(rootIdentity, () => withContextFrame(context, createOwner));
523
+ let releaseEventRoot;
506
524
  try {
507
525
  withOwner(portalOwner, () => insertValue(fragment, children, end));
508
526
  } catch (error) {
@@ -511,11 +529,14 @@ function createPortalStructural(children, container) {
511
529
  throw error;
512
530
  }
513
531
  const rollback = () => {
532
+ releaseEventRoot?.();
533
+ releaseEventRoot = void 0;
514
534
  removeBetween(start, end);
515
535
  start.remove();
516
536
  end.remove();
517
537
  };
518
538
  const publication = [() => {
539
+ releaseEventRoot = retainCompiledEventRoot(container);
519
540
  container.insertBefore(fragment, null);
520
541
  try {
521
542
  commitRangeRefs(start, end);
@@ -571,12 +592,151 @@ const componentCommitOwners = /* @__PURE__ */ new WeakMap();
571
592
  const pendingInsertionCommits = /* @__PURE__ */ new WeakMap();
572
593
  const pendingOwnerCommits = /* @__PURE__ */ new WeakMap();
573
594
  const pendingRootPortals = /* @__PURE__ */ new WeakMap();
595
+ let pendingRefCount = 0;
596
+ let pendingInsertionOwnerCount = 0;
597
+ let pendingOwnerCommitCount = 0;
598
+ let visitedPublishedNodeCount = 0;
599
+ function setPendingRef(element, pending) {
600
+ if (!pendingRefs.has(element)) pendingRefCount += 1;
601
+ pendingRefs.set(element, pending);
602
+ }
603
+ function deletePendingRef(element, expected) {
604
+ if (expected !== void 0 && pendingRefs.get(element) !== expected) return false;
605
+ if (!pendingRefs.delete(element)) return false;
606
+ pendingRefCount -= 1;
607
+ return true;
608
+ }
574
609
  function createCompiledScope() {
575
610
  return createScope(wideSourceOperations);
576
611
  }
577
612
  function createNarrowCompiledScope() {
578
613
  return createScope(narrowSourceOperations);
579
614
  }
615
+ /** Compiler-emitted map callbacks only need a compact, narrow row scheduler. */
616
+ var CompilerKeyedScope = class {
617
+ owner = createOwner();
618
+ updaters = [];
619
+ pending = 0;
620
+ batchDepth = 0;
621
+ flushing = false;
622
+ hasWriter = false;
623
+ cachedUpdaterOrder;
624
+ [1](sources) {
625
+ if (this.owner[0]) return;
626
+ if (sources === void 0) {
627
+ this.flush();
628
+ return;
629
+ }
630
+ if (narrowSourceOperations[0](sources)) return;
631
+ const wasIdle = narrowSourceOperations[0](this.pending);
632
+ this.pending = narrowSourceOperations[2](this.pending, sources);
633
+ if (wasIdle && this.batchDepth === 0) this.schedule();
634
+ }
635
+ [3]() {
636
+ if (this.owner[0]) return;
637
+ try {
638
+ disposeOwner(this.owner);
639
+ } finally {
640
+ this.pending = 0;
641
+ for (const updater of this.updaters) if (updater !== void 0) updater[3] = false;
642
+ this.updaters.length = 0;
643
+ this.cachedUpdaterOrder = void 0;
644
+ }
645
+ }
646
+ constructor() {
647
+ const scope = this;
648
+ scopeOwners.set(scope, this.owner);
649
+ scopeNamespaces.set(scope, currentIntrinsicNamespace());
650
+ activeScopeCollector?.add(scope);
651
+ if (activeScopeCollector !== null) activeConstructionOwner = this.owner;
652
+ }
653
+ [0](reads, run, writes) {
654
+ if (this.owner[0]) throw new Error(DEV ? "cannot add an updater to a disposed scope" : "V002");
655
+ const errorOwner = activeOwner ?? this.owner;
656
+ const entry = [
657
+ reads,
658
+ writes,
659
+ run,
660
+ true,
661
+ errorOwner,
662
+ activeContextFrame ?? errorOwner[2]
663
+ ];
664
+ if (DEV) createdUpdaterCount += 1;
665
+ const index = this.updaters.length;
666
+ this.updaters.push(entry);
667
+ this.hasWriter ||= writes !== void 0;
668
+ this.cachedUpdaterOrder = void 0;
669
+ if (activeOwner === this.owner) return noop;
670
+ const remove = () => {
671
+ if (this.updaters[index] !== entry) return;
672
+ entry[3] = false;
673
+ this.updaters[index] = void 0;
674
+ this.cachedUpdaterOrder = void 0;
675
+ };
676
+ activeOwner?.[1].push(remove);
677
+ return remove;
678
+ }
679
+ [2](operation) {
680
+ this.batchDepth += 1;
681
+ transactionDepth += 1;
682
+ try {
683
+ return operation();
684
+ } finally {
685
+ this.batchDepth -= 1;
686
+ if (this.batchDepth === 0 && !narrowSourceOperations[0](this.pending)) this.schedule();
687
+ transactionDepth -= 1;
688
+ if (transactionDepth === 0) drainFlushes();
689
+ }
690
+ }
691
+ schedule() {
692
+ if (retainedUiEnabled) scheduleOwnerFlush(this.owner, this);
693
+ else scheduleFlush(this);
694
+ }
695
+ flush() {
696
+ if (this.flushing || narrowSourceOperations[0](this.pending)) return;
697
+ const operation = () => {
698
+ this.flushing = true;
699
+ try {
700
+ let pass = 0;
701
+ while (!narrowSourceOperations[0](this.pending)) {
702
+ pass += 1;
703
+ if (pass > MAX_FLUSH_PASSES) {
704
+ this.pending = 0;
705
+ throw new Error(DEV ? "Vidact compiled scope did not stabilize" : "V001");
706
+ }
707
+ let active = this.pending;
708
+ this.pending = 0;
709
+ const order = this.hasWriter ? this.cachedUpdaterOrder ??= topologicalUpdaterOrder(this.updaters, narrowSourceOperations) : void 0;
710
+ const count = order?.length ?? this.updaters.length;
711
+ for (let position = 0; position < count; position += 1) {
712
+ const index = order?.[position] ?? position;
713
+ const updater = this.updaters[index];
714
+ if (updater === void 0 || !updater[3] || !narrowSourceOperations[1](active, updater[0])) continue;
715
+ try {
716
+ const invoke = () => withOwner(updater[4], () => withContextFrame(updater[5], () => withScopeNamespace(this, () => updater[2](active))));
717
+ if (profilingEnabled) measureProfileWork(this.owner, "updater", invoke);
718
+ else invoke();
719
+ } catch (error) {
720
+ if (!routeOwnerError(updater[4], error)) {
721
+ failedOwner = updater[4];
722
+ throw error;
723
+ }
724
+ }
725
+ if (updater[1] !== void 0) active = narrowSourceOperations[2](active, updater[1]);
726
+ }
727
+ }
728
+ } finally {
729
+ this.flushing = false;
730
+ }
731
+ if (retainedUiEnabled) notifyRetainedFlush(this.owner[5] ?? null);
732
+ };
733
+ if (profilingEnabled) measureProfileWork(this.owner, "scheduler", operation, true);
734
+ else operation();
735
+ }
736
+ };
737
+ function createCompilerKeyedScope() {
738
+ return new CompilerKeyedScope();
739
+ }
580
740
  function runCompiledTransaction(operation) {
581
741
  transactionDepth += 1;
582
742
  try {
@@ -590,19 +750,20 @@ function createScope(operations) {
590
750
  const namespace = currentIntrinsicNamespace();
591
751
  const owner = createOwner();
592
752
  const updaters = [];
593
- const freeUpdaterIndexes = [];
594
- const addedDuringFlush = /* @__PURE__ */ new Set();
753
+ let freeUpdaterIndexes;
754
+ let addedDuringFlush;
595
755
  let batchDepth = 0;
596
756
  let flushing = false;
597
757
  let pending = 0;
598
758
  let cachedUpdaterOrder;
759
+ let hasWriter = false;
599
760
  const flush = () => {
600
761
  if (owner[0] || flushing) return;
601
762
  const operation = () => {
602
763
  flushing = true;
603
764
  try {
604
765
  let pass = 0;
605
- const updaterOrder = cachedUpdaterOrder ??= topologicalUpdaterOrder(updaters, operations);
766
+ const updaterOrder = hasWriter ? cachedUpdaterOrder ??= topologicalUpdaterOrder(updaters, operations) : void 0;
606
767
  while (!operations[0](pending)) {
607
768
  pass += 1;
608
769
  if (pass > MAX_FLUSH_PASSES) {
@@ -611,17 +772,19 @@ function createScope(operations) {
611
772
  }
612
773
  let active = pending;
613
774
  pending = 0;
614
- for (const index of updaterOrder) {
775
+ const updaterCount = updaterOrder?.length ?? updaters.length;
776
+ for (let position = 0; position < updaterCount; position += 1) {
777
+ const index = updaterOrder?.[position] ?? position;
615
778
  const updater = updaters[index];
616
- if (updater === void 0 || addedDuringFlush.has(updater) || !updater[3] || !operations[1](active, updater[0])) continue;
779
+ if (updater === void 0 || addedDuringFlush?.has(updater) || !updater[3] || !operations[1](active, updater[0])) continue;
617
780
  if (profilingEnabled) measureProfileWork(owner, "updater", () => updater[2](active));
618
781
  else updater[2](active);
619
782
  if (updater[1] !== void 0) active = operations[2](active, updater[1]);
620
783
  }
621
- addedDuringFlush.clear();
784
+ addedDuringFlush?.clear();
622
785
  }
623
786
  } finally {
624
- addedDuringFlush.clear();
787
+ addedDuringFlush?.clear();
625
788
  flushing = false;
626
789
  }
627
790
  if (retainedUiEnabled) notifyRetainedFlush(owner[5] ?? null);
@@ -649,24 +812,27 @@ function createScope(operations) {
649
812
  },
650
813
  true
651
814
  ];
652
- const index = freeUpdaterIndexes.pop() ?? updaters.length;
815
+ if (DEV) createdUpdaterCount += 1;
816
+ const index = freeUpdaterIndexes?.pop() ?? updaters.length;
653
817
  updaters[index] = entry;
818
+ hasWriter ||= writes !== void 0;
654
819
  cachedUpdaterOrder = void 0;
655
- if (flushing) addedDuringFlush.add(entry);
820
+ if (flushing) (addedDuringFlush ??= /* @__PURE__ */ new Set()).add(entry);
656
821
  const remove = () => {
657
822
  if (updaters[index] !== entry) return;
658
823
  entry[3] = false;
659
824
  updaters[index] = void 0;
660
825
  cachedUpdaterOrder = void 0;
661
- freeUpdaterIndexes.push(index);
826
+ (freeUpdaterIndexes ??= []).push(index);
662
827
  };
663
- if (activeOwner !== null && activeOwner !== owner) activeOwner[1].add(remove);
828
+ if (activeOwner !== null && activeOwner !== owner) activeOwner[1].push(remove);
664
829
  return remove;
665
830
  },
666
831
  (sources) => {
667
832
  if (owner[0] || operations[0](sources)) return;
833
+ const wasIdle = operations[0](pending);
668
834
  pending = operations[2](pending, sources);
669
- if (batchDepth === 0) {
835
+ if (wasIdle && batchDepth === 0) {
670
836
  if (retainedUiEnabled) scheduleOwnerFlush(owner, flush);
671
837
  else scheduleFlush(flush);
672
838
  }
@@ -694,8 +860,9 @@ function createScope(operations) {
694
860
  pending = 0;
695
861
  for (const updater of updaters) if (updater !== void 0) updater[3] = false;
696
862
  updaters.length = 0;
697
- freeUpdaterIndexes.length = 0;
698
- addedDuringFlush.clear();
863
+ hasWriter = false;
864
+ if (freeUpdaterIndexes !== void 0) freeUpdaterIndexes.length = 0;
865
+ addedDuringFlush?.clear();
699
866
  }
700
867
  }
701
868
  ];
@@ -706,14 +873,31 @@ function createScope(operations) {
706
873
  return scope;
707
874
  }
708
875
  function topologicalUpdaterOrder(updaters, operations) {
709
- const activeIndexes = updaters.flatMap((updater, index) => updater === void 0 || !updater[3] ? [] : [index]);
876
+ if (DEV) createdSchedulerPlanCount += 1;
877
+ const activeIndexes = [];
878
+ let hasWriter = false;
879
+ for (let index = 0; index < updaters.length; index += 1) {
880
+ const updater = updaters[index];
881
+ if (updater === void 0 || !updater[3]) continue;
882
+ activeIndexes.push(index);
883
+ if (updater[1] !== void 0) hasWriter = true;
884
+ }
885
+ if (!hasWriter) return activeIndexes;
886
+ const readersBySource = /* @__PURE__ */ new Map();
887
+ for (const readerIndex of activeIndexes) operations[3](updaters[readerIndex][0], (sourceIndex) => {
888
+ const readers = readersBySource.get(sourceIndex);
889
+ if (readers === void 0) readersBySource.set(sourceIndex, [readerIndex]);
890
+ else readers.push(readerIndex);
891
+ });
710
892
  const edges = /* @__PURE__ */ new Map();
711
893
  for (const writerIndex of activeIndexes) {
712
894
  const writes = updaters[writerIndex][1];
713
895
  if (writes === void 0) continue;
714
- const readers = [];
715
- for (const readerIndex of activeIndexes) if (writerIndex !== readerIndex && operations[1](writes, updaters[readerIndex][0])) readers.push(readerIndex);
716
- if (readers.length > 0) edges.set(writerIndex, readers);
896
+ const readers = /* @__PURE__ */ new Set();
897
+ operations[3](writes, (sourceIndex) => {
898
+ for (const readerIndex of readersBySource.get(sourceIndex) ?? []) if (writerIndex !== readerIndex) readers.add(readerIndex);
899
+ });
900
+ if (readers.size > 0) edges.set(writerIndex, [...readers].toSorted((left, right) => left - right));
717
901
  }
718
902
  const visitIndexes = new Int32Array(updaters.length).fill(-1);
719
903
  const lowLinks = new Int32Array(updaters.length);
@@ -798,7 +982,7 @@ function createCompiledMemo(scope, reads, writes, evaluate, readDependencies) {
798
982
  removeUpdater();
799
983
  throw new Error(DEV ? "createCompiledMemo received an unknown scope" : "V003");
800
984
  }
801
- owner[1].add(removeUpdater);
985
+ owner[1].push(removeUpdater);
802
986
  return slot;
803
987
  }
804
988
  function createContext(defaultValue) {
@@ -879,7 +1063,7 @@ function createCompiledExternalStore(scope, sourceMask, storeSubscribe, getSnaps
879
1063
  removeStoreUpdater();
880
1064
  throw error;
881
1065
  }
882
- owner[1].add(() => {
1066
+ owner[1].push(() => {
883
1067
  removeStoreUpdater();
884
1068
  deactivateStore();
885
1069
  });
@@ -892,7 +1076,7 @@ function createCompiledExternalStore(scope, sourceMask, storeSubscribe, getSnaps
892
1076
  disposeResource();
893
1077
  throw error;
894
1078
  }
895
- owner[1].add(() => {
1079
+ owner[1].push(() => {
896
1080
  removeStoreUpdater();
897
1081
  disposeResource();
898
1082
  });
@@ -951,26 +1135,59 @@ function useMemo(factory, _dependencies) {
951
1135
  function useCallback(callback, _dependencies) {
952
1136
  return callback;
953
1137
  }
1138
+ const ownedBlockFacades = /* @__PURE__ */ new WeakMap();
1139
+ const ownedFacadeBlocks = /* @__PURE__ */ new WeakMap();
1140
+ function ownedStructuralBinding(value) {
1141
+ if (isStructuralBinding(value)) return value;
1142
+ return isRenderableProtocol(value) ? ownedFacadeBlocks.get(value) : void 0;
1143
+ }
1144
+ /**
1145
+ * Owned blocks are arrays internally, which user-level data flow must never
1146
+ * observe: dependency code inspects children with `Array.isArray` and spreads
1147
+ * them. Prop reads wrap a block in a stable renderable facade that
1148
+ * materializes back to the block when rendered.
1149
+ */
1150
+ function sanitizeCompiledPropValue(value) {
1151
+ if (!isStructuralBinding(value)) return value;
1152
+ let facade = ownedBlockFacades.get(value);
1153
+ if (facade === void 0) {
1154
+ const capability = { props: {} };
1155
+ Object.defineProperty(capability, RENDERABLE, {
1156
+ configurable: false,
1157
+ enumerable: false,
1158
+ value: {
1159
+ identity: value,
1160
+ input: {},
1161
+ reconcile: false,
1162
+ construct: () => value
1163
+ }
1164
+ });
1165
+ facade = capability;
1166
+ ownedBlockFacades.set(value, facade);
1167
+ ownedFacadeBlocks.set(facade, value);
1168
+ }
1169
+ return facade;
1170
+ }
954
1171
  function createCompiledProp(scope, sourceMask, input, fallback) {
955
1172
  const assertWritable = stateWriteGuard(scope);
956
1173
  const upstream = isCompiledBinding(input) ? input : void 0;
957
1174
  const read = () => {
958
1175
  const value = upstream === void 0 ? input : upstream[1]();
959
- return value === void 0 && fallback !== void 0 ? fallback() : value;
1176
+ return sanitizeCompiledPropValue(value === void 0 && fallback !== void 0 ? fallback() : value);
960
1177
  };
961
1178
  const slot = createStateSlot(scope[1], sourceMask, read(), assertWritable);
962
1179
  if (upstream !== void 0) {
963
1180
  const remove = subscribeBinding(upstream, () => slot.replace(read()));
964
1181
  const owner = scopeOwners.get(scope);
965
1182
  if (owner === void 0) throw new Error(DEV ? "createCompiledProp received an unknown scope" : "V003");
966
- owner[1].add(remove);
1183
+ owner[1].push(remove);
967
1184
  }
968
1185
  return slot;
969
1186
  }
970
1187
  function createCompiledRestProp(scope, sourceMask, input, excludedNames) {
971
1188
  const excluded = new Set(excludedNames);
972
1189
  const entries = () => Object.entries(input).filter(([name]) => !excluded.has(name));
973
- const read = () => Object.fromEntries(entries().map(([name, value]) => [name, isCompiledBinding(value) ? value[1]() : value]));
1190
+ const read = () => Object.fromEntries(entries().map(([name, value]) => [name, sanitizeCompiledPropValue(isCompiledBinding(value) ? value[1]() : value)]));
974
1191
  const slot = createStateSlot(scope[1], sourceMask, read(), stateWriteGuard(scope));
975
1192
  const publish = () => {
976
1193
  const previous = slot.get();
@@ -985,7 +1202,7 @@ function createCompiledRestProp(scope, sourceMask, input, excludedNames) {
985
1202
  const removers = [...upstreams].map((upstream) => subscribeBinding(upstream, publish));
986
1203
  const owner = scopeOwners.get(scope);
987
1204
  if (owner === void 0) throw new Error(DEV ? "createCompiledRestProp received an unknown scope" : "V003");
988
- owner[1].add(() => {
1205
+ owner[1].push(() => {
989
1206
  for (const remove of removers) remove();
990
1207
  });
991
1208
  return slot;
@@ -1026,11 +1243,34 @@ function compiledEvent(scope, handler) {
1026
1243
  const owner = scopeOwners.get(scope);
1027
1244
  if (owner === void 0) throw new Error(DEV ? "compiledEvent received an unknown scope" : "V003");
1028
1245
  const errorOwner = activeOwner ?? owner;
1029
- return (...arguments_) => runOwnerTask(errorOwner, () => withOwner(errorOwner, () => scope[2](() => {
1030
- const current = isCompiledBinding(handler) ? handler[1]() : handler;
1031
- if (typeof current !== "function") return;
1032
- return current(...arguments_);
1033
- })));
1246
+ const listener = (...arguments_) => {
1247
+ if (errorOwner[0]) return;
1248
+ return runOwnerTask(errorOwner, () => withOwner(errorOwner, () => scope[2](() => {
1249
+ const current = isCompiledBinding(handler) ? handler[1]() : handler;
1250
+ if (typeof current !== "function") return;
1251
+ return current(...arguments_);
1252
+ })));
1253
+ };
1254
+ listener[COMPILED_EVENT_HANDLER] = true;
1255
+ return listener;
1256
+ }
1257
+ function compiledInlineEvent(scope, handler) {
1258
+ const owner = scopeOwners.get(scope);
1259
+ if (owner === void 0) throw new Error(DEV ? "compiledInlineEvent received an unknown scope" : "V003");
1260
+ const listener = handler;
1261
+ listener[COMPILED_INLINE_EVENT_OWNER] = activeOwner ?? owner;
1262
+ listener[COMPILED_DELEGATED_EVENT_INVOKE] = invokeCompiledInlineEvent;
1263
+ return listener;
1264
+ }
1265
+ function invokeCompiledInlineEvent(...arguments_) {
1266
+ const owner = this[COMPILED_INLINE_EVENT_OWNER];
1267
+ if (owner[0]) return;
1268
+ return runOwnerTask(owner, () => withOwner(owner, () => runCompiledTransaction(() => this(...arguments_))));
1269
+ }
1270
+ function isCompiledEventHandler(value) {
1271
+ if (typeof value !== "function") return false;
1272
+ const handler = value;
1273
+ return handler[COMPILED_EVENT_HANDLER] === true || typeof handler[COMPILED_DELEGATED_EVENT_INVOKE] === "function";
1034
1274
  }
1035
1275
  function captureCompiledTask(scope) {
1036
1276
  const owner = scope === void 0 ? activeOwner : scopeOwners.get(scope);
@@ -1092,7 +1332,12 @@ function when(scope, reads, condition, render, additionalScope, additionalReads)
1092
1332
  }
1093
1333
  function choose(scope, reads, mode, select, consequent, alternate, additionalScope, additionalReads) {
1094
1334
  return structural(scope, (parent, before) => {
1095
- const [start, end, hydrated] = structuralRange(parent, before, "choice");
1335
+ const range = structuralRange(parent, before, "choice", true, true);
1336
+ const markerlessHydration = range === void 0;
1337
+ const start = range?.[0] ?? document.createComment(DEV ? "vidact:choice" : "");
1338
+ const end = range?.[1] ?? document.createComment(DEV ? "/vidact:choice" : "");
1339
+ const hydrated = range?.[2] ?? true;
1340
+ const ownsMarkers = range?.[3] ?? true;
1096
1341
  let selected = -1;
1097
1342
  let branchOwner = null;
1098
1343
  let branchNodes = [];
@@ -1100,10 +1345,20 @@ function choose(scope, reads, mode, select, consequent, alternate, additionalSco
1100
1345
  const value = select();
1101
1346
  const next = mode === "not-nullish" ? value === null || value === void 0 ? 1 : 0 : value ? 0 : 1;
1102
1347
  if (next === selected) return;
1103
- const currentParent = rangeParent(start, end, "choice block");
1104
1348
  const nextOwner = createOwner();
1105
- const [fragment, nodes] = hydrated && selected === -1 ? withHydrationInsertion(currentParent, end, () => stageRender(next === 0 ? consequent : alternate, nextOwner)) : stageRender(next === 0 ? consequent : alternate, nextOwner);
1106
- currentParent.insertBefore(fragment, end);
1349
+ const render = next === 0 ? consequent : alternate;
1350
+ let nodes;
1351
+ if (markerlessHydration && selected === -1) {
1352
+ const [first, after, hydratedNodes] = stageMarkerlessHydrationRender(parent, before, render, nextOwner);
1353
+ parent.insertBefore(start, first);
1354
+ parent.insertBefore(end, after);
1355
+ nodes = hydratedNodes;
1356
+ } else {
1357
+ const currentParent = rangeParent(start, end, "choice block");
1358
+ const [fragment, stagedNodes] = hydrated && selected === -1 ? withHydrationInsertion(currentParent, end, () => stageRender(render, nextOwner)) : stageRender(render, nextOwner);
1359
+ currentParent.insertBefore(fragment, end);
1360
+ nodes = stagedNodes;
1361
+ }
1107
1362
  try {
1108
1363
  commitPublishedNodes(nodes);
1109
1364
  } catch (error) {
@@ -1129,8 +1384,10 @@ function choose(scope, reads, mode, select, consequent, alternate, additionalSco
1129
1384
  try {
1130
1385
  disposePublished(branchOwner, branchNodes);
1131
1386
  } finally {
1132
- start.remove();
1133
- end.remove();
1387
+ if (ownsMarkers) {
1388
+ start.remove();
1389
+ end.remove();
1390
+ }
1134
1391
  }
1135
1392
  });
1136
1393
  }, "slot");
@@ -1183,33 +1440,43 @@ function dispatch(scope, reads, type, key, render, additionalScope, additionalRe
1183
1440
  });
1184
1441
  }, "slot");
1185
1442
  }
1186
- function keyed(scope, reads, values, key, render, additionalScope, additionalReads) {
1443
+ function keyed(scope, reads, values, key, render, trackIndexOrAdditionalScope, additionalScopeOrReads, additionalReads) {
1444
+ const compilerManaged = typeof trackIndexOrAdditionalScope === "boolean";
1445
+ const trackIndex = typeof trackIndexOrAdditionalScope === "boolean" ? trackIndexOrAdditionalScope : true;
1446
+ const additionalScope = typeof trackIndexOrAdditionalScope === "boolean" ? additionalScopeOrReads : trackIndexOrAdditionalScope;
1447
+ const resolvedAdditionalReads = typeof trackIndexOrAdditionalScope === "boolean" ? additionalReads : additionalScopeOrReads;
1187
1448
  return structural(scope, (parent, before) => {
1188
1449
  const itemSource = 1;
1189
1450
  const indexSource = 2;
1190
1451
  const list = createKeyedList(parent, {
1191
1452
  key,
1192
1453
  render(value, index) {
1193
- const owner = createOwner();
1194
- const itemScope = createNarrowCompiledScope();
1195
- const valueSlot = createCompiledState(itemScope, itemSource, value);
1196
- const indexSlot = createCompiledState(itemScope, indexSource, index);
1454
+ const itemScope = compilerManaged ? createCompilerKeyedScope() : createNarrowCompiledScope();
1455
+ const owner = scopeOwners.get(itemScope);
1456
+ const valueSlot = compilerManaged ? createReadOnlyStateSlot(itemScope, itemSource, value) : createCompiledState(itemScope, itemSource, value);
1457
+ const indexSlot = trackIndex ? compilerManaged ? createReadOnlyStateSlot(itemScope, indexSource, index) : createCompiledState(itemScope, indexSource, index) : void 0;
1197
1458
  try {
1198
1459
  return [
1199
1460
  withOwner(owner, () => {
1200
- onCleanup(itemScope[3]);
1201
- return materialize(render(valueSlot, indexSlot, itemScope));
1461
+ const rendered = render(valueSlot, indexSlot, itemScope);
1462
+ return !isHydrating() && rendered instanceof Node && !(rendered instanceof DocumentFragment) ? [rendered] : materialize(rendered);
1202
1463
  }),
1203
1464
  (nextValue, nextIndex) => {
1465
+ if (Object.is(valueSlot.get(), nextValue) && (!trackIndex || indexSlot.get() === nextIndex)) return;
1204
1466
  itemScope[2](() => {
1205
- valueSlot.set(nextValue);
1206
- indexSlot.set(nextIndex);
1467
+ if (compilerManaged) {
1468
+ replaceReadOnlyStateSlot(valueSlot, nextValue);
1469
+ if (indexSlot !== void 0) replaceReadOnlyStateSlot(indexSlot, nextIndex);
1470
+ } else {
1471
+ valueSlot.set(nextValue);
1472
+ indexSlot?.set(nextIndex);
1473
+ }
1207
1474
  });
1208
1475
  },
1209
- () => disposeOwner(owner)
1476
+ itemScope
1210
1477
  ];
1211
1478
  } catch (error) {
1212
- disposeOwner(owner);
1479
+ itemScope[3]();
1213
1480
  throw error;
1214
1481
  }
1215
1482
  }
@@ -1224,7 +1491,7 @@ function keyed(scope, reads, values, key, render, additionalScope, additionalRea
1224
1491
  }
1225
1492
  };
1226
1493
  update();
1227
- const removeUpdater = subscribe(scope, reads, update, additionalScope, additionalReads);
1494
+ const removeUpdater = subscribe(scope, reads, update, additionalScope, resolvedAdditionalReads);
1228
1495
  onCleanup(() => {
1229
1496
  removeUpdater();
1230
1497
  list.dispose();
@@ -1285,7 +1552,7 @@ function compiledRoot(scope, render) {
1285
1552
  componentCommitOwners.set(end, owner);
1286
1553
  const fragment = document.createDocumentFragment();
1287
1554
  if (hydratedRange === void 0) fragment.append(start, end);
1288
- owner[1].add(() => {
1555
+ owner[1].push(() => {
1289
1556
  try {
1290
1557
  removeBetween(start, end);
1291
1558
  } finally {
@@ -1334,7 +1601,7 @@ function adoptCompiledRoot(root) {
1334
1601
  const range = componentRanges.get(root);
1335
1602
  if (range === void 0) return;
1336
1603
  const owner = scopeOwners.get(range[2]);
1337
- if (activeOwner !== null && owner !== void 0 && activeOwner !== owner) activeOwner[1].add(range[2][3]);
1604
+ if (activeOwner !== null && owner !== void 0 && activeOwner !== owner) activeOwner[1].push(range[2][3]);
1338
1605
  }
1339
1606
  function constructCompiledComponent(component, componentType) {
1340
1607
  const previousCollector = activeScopeCollector;
@@ -1360,14 +1627,16 @@ function constructCompiledComponent(component, componentType) {
1360
1627
  }
1361
1628
  function queueElementRef(element, value) {
1362
1629
  if (!isRefValue(value)) throw new TypeError(DEV ? "ref must be a callback or an object with current" : "V006");
1363
- pendingRefs.set(element, [activeOwner, value]);
1630
+ const pending = [activeOwner, value];
1631
+ setPendingRef(element, pending);
1632
+ activeOwner?.[1].push(() => deletePendingRef(element, pending));
1364
1633
  }
1365
1634
  function useImperativeHandle(ref, create, dependencies) {
1366
1635
  const owner = activeConstructionOwner;
1367
1636
  if (owner === null) throw new Error(DEV ? "useImperativeHandle must run during compiled component construction" : "V013");
1368
1637
  if (!isRefValue(ref)) throw new TypeError(DEV ? "imperative ref must be null, a callback, or an object with current" : "V006");
1369
1638
  if (dependencies !== void 0 && dependencies.length !== 0) throw new Error(DEV ? "reactive useImperativeHandle dependencies are not supported yet" : "V014");
1370
- queueOwnerCommit(owner, () => owner[1].add(attachRef(ref, create())));
1639
+ queueOwnerCommit(owner, () => owner[1].push(attachRef(ref, create())));
1371
1640
  }
1372
1641
  function useLayoutEffect(create, dependencies) {
1373
1642
  registerEffect(create, dependencies, false);
@@ -1384,7 +1653,7 @@ function useInsertionEffect(create, dependencies) {
1384
1653
  cleanup();
1385
1654
  cleanup = profilingEnabled ? readProfiledEffectCleanup(owner, create) : readEffectCleanup(create());
1386
1655
  });
1387
- lifetimeOwner[1].add(() => cleanup());
1656
+ lifetimeOwner[1].push(() => cleanup());
1388
1657
  return;
1389
1658
  }
1390
1659
  let cleanup = noop;
@@ -1405,7 +1674,7 @@ function useInsertionEffect(create, dependencies) {
1405
1674
  queueInsertionCommit(owner, () => {
1406
1675
  if (!lifetimeOwner[0]) activate();
1407
1676
  });
1408
- lifetimeOwner[1].add(disposeResource);
1677
+ lifetimeOwner[1].push(disposeResource);
1409
1678
  }
1410
1679
  function useEffect(create, dependencies) {
1411
1680
  registerEffect(create, dependencies, true);
@@ -1431,7 +1700,7 @@ function registerEffect(create, dependencies, passive) {
1431
1700
  });
1432
1701
  } else run();
1433
1702
  });
1434
- lifetimeOwner[1].add(() => {
1703
+ lifetimeOwner[1].push(() => {
1435
1704
  generation += 1;
1436
1705
  if (passive) (DEV ? scheduleTask : queueMicrotask)(() => runOwnerTask(lifetimeOwner, cleanup));
1437
1706
  else cleanup();
@@ -1467,7 +1736,7 @@ function registerEffect(create, dependencies, passive) {
1467
1736
  queueOwnerCommit(owner, () => {
1468
1737
  if (!lifetimeOwner[0]) activate();
1469
1738
  });
1470
- lifetimeOwner[1].add(disposeResource);
1739
+ lifetimeOwner[1].push(disposeResource);
1471
1740
  }
1472
1741
  function compiledLayoutEffect(scope, reads, readCreate, readDependencies) {
1473
1742
  compiledEffect(scope, reads, readCreate, readDependencies, false);
@@ -1498,7 +1767,7 @@ function compiledInsertionEffect(scope, reads, readCreate, readDependencies) {
1498
1767
  run,
1499
1768
  -20
1500
1769
  ]));
1501
- lifetimeOwner[1].add(() => {
1770
+ lifetimeOwner[1].push(() => {
1502
1771
  removeUpdater();
1503
1772
  cleanup();
1504
1773
  });
@@ -1545,7 +1814,7 @@ function compiledInsertionEffect(scope, reads, readCreate, readDependencies) {
1545
1814
  -20
1546
1815
  ]);
1547
1816
  });
1548
- lifetimeOwner[1].add(() => {
1817
+ lifetimeOwner[1].push(() => {
1549
1818
  removeUpdater();
1550
1819
  disposeResource();
1551
1820
  });
@@ -1590,7 +1859,7 @@ function compiledEffect(scope, reads, readCreate, readDependencies, passive = tr
1590
1859
  20
1591
1860
  ]);
1592
1861
  });
1593
- lifetimeOwner[1].add(() => {
1862
+ lifetimeOwner[1].push(() => {
1594
1863
  generation += 1;
1595
1864
  removeUpdater();
1596
1865
  if (passive) (DEV ? scheduleTask : queueMicrotask)(() => runOwnerTask(lifetimeOwner, cleanup));
@@ -1656,7 +1925,7 @@ function compiledEffect(scope, reads, readCreate, readDependencies, passive = tr
1656
1925
  20
1657
1926
  ]);
1658
1927
  });
1659
- lifetimeOwner[1].add(() => {
1928
+ lifetimeOwner[1].push(() => {
1660
1929
  removeUpdater();
1661
1930
  disposeResource();
1662
1931
  });
@@ -1746,7 +2015,7 @@ function compiledImperativeHandle(scope, reads, readRef, create, readDependencie
1746
2015
  ]);
1747
2016
  };
1748
2017
  const removeUpdater = subscribe(scope, reads, update);
1749
- owner[1].add(() => {
2018
+ owner[1].push(() => {
1750
2019
  removeUpdater();
1751
2020
  cleanup();
1752
2021
  });
@@ -1756,6 +2025,7 @@ function queueOwnerCommit(owner, commit) {
1756
2025
  if (commits === void 0) {
1757
2026
  commits = /* @__PURE__ */ new Set();
1758
2027
  pendingOwnerCommits.set(owner, commits);
2028
+ pendingOwnerCommitCount += 1;
1759
2029
  }
1760
2030
  commits.add(commit);
1761
2031
  }
@@ -1764,6 +2034,7 @@ function queueInsertionCommit(owner, commit) {
1764
2034
  if (commits === void 0) {
1765
2035
  commits = /* @__PURE__ */ new Set();
1766
2036
  pendingInsertionCommits.set(owner, commits);
2037
+ pendingInsertionOwnerCount += 1;
1767
2038
  }
1768
2039
  commits.add(commit);
1769
2040
  }
@@ -1785,7 +2056,7 @@ function mountCompiledRef(element, value) {
1785
2056
  current,
1786
2057
  (attached) => cleanup = attached
1787
2058
  ];
1788
- pendingRefs.set(element, pending);
2059
+ setPendingRef(element, pending);
1789
2060
  const removeUpdater = subscribeBinding(value, () => {
1790
2061
  const next = value[1]();
1791
2062
  if (Object.is(next, current)) return;
@@ -1834,7 +2105,7 @@ function mountCompiledRef(element, value) {
1834
2105
  });
1835
2106
  onCleanup(() => {
1836
2107
  removeUpdater();
1837
- if (pendingRefs.get(element) === pending) pendingRefs.delete(element);
2108
+ deletePendingRef(element, pending);
1838
2109
  cleanup();
1839
2110
  });
1840
2111
  }
@@ -1891,6 +2162,7 @@ function mountCompiled(component, host, options) {
1891
2162
  const range = componentRanges.get(root);
1892
2163
  if (range === void 0) throw new Error(DEV ? "mountCompiled received an unknown component result" : "V007");
1893
2164
  const previous = [...host.childNodes];
2165
+ const releaseEventRoot = retainCompiledEventRoot(host);
1894
2166
  try {
1895
2167
  root[1](host, previous[0] ?? null);
1896
2168
  const rootOwner = scopeOwners.get(range[2]);
@@ -1904,6 +2176,7 @@ function mountCompiled(component, host, options) {
1904
2176
  commitOwnerResources(rootOwner);
1905
2177
  if (!hydrating) for (const node of previous) host.removeChild(node);
1906
2178
  } catch (error) {
2179
+ releaseEventRoot();
1907
2180
  try {
1908
2181
  range[2][3]();
1909
2182
  } catch {}
@@ -1911,7 +2184,16 @@ function mountCompiled(component, host, options) {
1911
2184
  rootIdentity.onUncaughtError(error);
1912
2185
  return { dispose: noop };
1913
2186
  }
1914
- return { dispose: range[2][3] };
2187
+ let disposed = false;
2188
+ return { dispose: () => {
2189
+ if (disposed) return;
2190
+ disposed = true;
2191
+ try {
2192
+ range[2][3]();
2193
+ } finally {
2194
+ releaseEventRoot();
2195
+ }
2196
+ } };
1915
2197
  }
1916
2198
  function isCompiledBinding(value) {
1917
2199
  return Array.isArray(value) && value[0] === BINDING;
@@ -1925,9 +2207,12 @@ function isCompiledComponentResult(value) {
1925
2207
  function mountCompiledBinding(parent, value) {
1926
2208
  mountCompiledBindingBefore(parent, value, null);
1927
2209
  }
1928
- function mountCompiledProp(value, apply) {
2210
+ function applyCompiledPropValue(apply, element, name, next) {
2211
+ return element === void 0 ? apply(next) : apply(element, name, next);
2212
+ }
2213
+ function mountCompiledProp(value, apply, element, name) {
1929
2214
  let current = value[1]();
1930
- let cleanup = apply(current);
2215
+ let cleanup = applyCompiledPropValue(apply, element, name, current);
1931
2216
  const removeUpdater = subscribeBinding(value, () => {
1932
2217
  const next = value[1]();
1933
2218
  if (Object.is(next, current)) return;
@@ -1936,10 +2221,10 @@ function mountCompiledProp(value, apply) {
1936
2221
  let committedNext = false;
1937
2222
  stagePublication([() => {
1938
2223
  try {
1939
- nextCleanup = apply(next);
2224
+ nextCleanup = applyCompiledPropValue(apply, element, name, next);
1940
2225
  } catch (error) {
1941
2226
  try {
1942
- apply(previous);
2227
+ applyCompiledPropValue(apply, element, name, previous);
1943
2228
  } catch {}
1944
2229
  throw error;
1945
2230
  }
@@ -1950,7 +2235,7 @@ function mountCompiledProp(value, apply) {
1950
2235
  }, () => {
1951
2236
  if (!committedNext) return;
1952
2237
  nextCleanup?.();
1953
- cleanup = apply(previous);
2238
+ cleanup = applyCompiledPropValue(apply, element, name, previous);
1954
2239
  current = previous;
1955
2240
  committedNext = false;
1956
2241
  }]);
@@ -2008,11 +2293,32 @@ function structural(scope, mount, hydrationKind) {
2008
2293
  hydrationKind
2009
2294
  ];
2010
2295
  }
2011
- function structuralRange(parent, before, label) {
2296
+ function structuralRange(parent, before, label, borrowOuter = false, allowMarkerlessHydration = false) {
2297
+ const current = borrowHydrationSlotRange(parent, true);
2298
+ if (current !== void 0) {
2299
+ claimHydrationSlotRange(parent);
2300
+ return [
2301
+ current[0],
2302
+ current[1],
2303
+ true,
2304
+ true
2305
+ ];
2306
+ }
2307
+ if (borrowOuter) {
2308
+ const outer = borrowHydrationSlotRange(parent, false);
2309
+ if (outer !== void 0) return [
2310
+ outer[0],
2311
+ outer[1],
2312
+ true,
2313
+ false
2314
+ ];
2315
+ }
2316
+ if (allowMarkerlessHydration && hydrationCursor(parent) !== void 0) return void 0;
2012
2317
  const hydrated = claimHydrationSlotRange(parent);
2013
2318
  if (hydrated !== void 0) return [
2014
2319
  hydrated[0],
2015
2320
  hydrated[1],
2321
+ true,
2016
2322
  true
2017
2323
  ];
2018
2324
  const start = document.createComment(DEV ? `vidact:${label}` : "");
@@ -2022,14 +2328,27 @@ function structuralRange(parent, before, label) {
2022
2328
  return [
2023
2329
  start,
2024
2330
  end,
2025
- false
2331
+ false,
2332
+ true
2026
2333
  ];
2027
2334
  }
2028
2335
  function subscribe(scope, reads, run, additionalScope, additionalReads) {
2029
- const removers = [scope[0](reads, run)];
2030
- if (additionalScope !== void 0 && additionalReads !== void 0) removers.push(additionalScope[0](additionalReads, () => withScopeNamespace(scope, run)));
2336
+ let first;
2337
+ if (!isEmptySources(reads)) {
2338
+ const remove = scope[0](reads, run);
2339
+ if (remove !== noop) first = remove;
2340
+ }
2341
+ let second;
2342
+ if (additionalScope !== void 0 && additionalReads !== void 0 && !isEmptySources(additionalReads)) {
2343
+ const additionalRun = scopeNamespaces.get(additionalScope) === scopeNamespaces.get(scope) ? run : () => withScopeNamespace(scope, run);
2344
+ const remove = additionalScope[0](additionalReads, additionalRun);
2345
+ if (remove !== noop) second = remove;
2346
+ }
2347
+ if (first === void 0) return second ?? noop;
2348
+ if (second === void 0) return first;
2031
2349
  return () => {
2032
- for (const remove of removers) remove();
2350
+ first();
2351
+ second();
2033
2352
  };
2034
2353
  }
2035
2354
  function subscribeBinding(compiledBinding, run) {
@@ -2055,7 +2374,7 @@ function createOwner(context = activeContextFrame ?? activeOwner?.[2] ?? null, r
2055
2374
  if (profilingEnabled) {
2056
2375
  const owner = [
2057
2376
  false,
2058
- /* @__PURE__ */ new Set(),
2377
+ [],
2059
2378
  context,
2060
2379
  rootIdentity,
2061
2380
  boundary,
@@ -2067,14 +2386,14 @@ function createOwner(context = activeContextFrame ?? activeOwner?.[2] ?? null, r
2067
2386
  }
2068
2387
  const owner = retainedUiEnabled ? [
2069
2388
  false,
2070
- /* @__PURE__ */ new Set(),
2389
+ [],
2071
2390
  context,
2072
2391
  rootIdentity,
2073
2392
  boundary,
2074
2393
  retainedConnection
2075
2394
  ] : [
2076
2395
  false,
2077
- /* @__PURE__ */ new Set(),
2396
+ [],
2078
2397
  context,
2079
2398
  rootIdentity,
2080
2399
  boundary
@@ -2332,7 +2651,7 @@ function withRootIdentity(rootIdentity, operation) {
2332
2651
  }
2333
2652
  }
2334
2653
  function onCleanup(cleanup) {
2335
- activeOwner?.[1].add(cleanup);
2654
+ activeOwner?.[1].push(cleanup);
2336
2655
  }
2337
2656
  function disposeOwner(owner) {
2338
2657
  if (owner[0]) return;
@@ -2340,19 +2659,21 @@ function disposeOwner(owner) {
2340
2659
  disposalCascadeDepth += 1;
2341
2660
  disposalCascadeOwners.add(owner);
2342
2661
  if (DEV) activeOwnerCount -= 1;
2343
- pendingInsertionCommits.delete(owner);
2344
- pendingOwnerCommits.delete(owner);
2345
- const cleanups = [...owner[1]];
2346
- owner[1].clear();
2662
+ if (pendingInsertionCommits.delete(owner)) pendingInsertionOwnerCount -= 1;
2663
+ if (pendingOwnerCommits.delete(owner)) pendingOwnerCommitCount -= 1;
2347
2664
  let firstError;
2348
2665
  let hasError = false;
2349
2666
  try {
2350
- for (let index = cleanups.length - 1; index >= 0; index -= 1) try {
2351
- cleanups[index]?.();
2352
- } catch (error) {
2353
- if (!hasError) firstError = error;
2354
- hasError = true;
2667
+ for (let remaining = owner[1].length; remaining > 0; remaining -= 1) {
2668
+ const cleanup = owner[1].pop();
2669
+ try {
2670
+ cleanup?.();
2671
+ } catch (error) {
2672
+ if (!hasError) firstError = error;
2673
+ hasError = true;
2674
+ }
2355
2675
  }
2676
+ owner[1].length = 0;
2356
2677
  } finally {
2357
2678
  disposalCascadeDepth -= 1;
2358
2679
  if (disposalCascadeDepth === 0) disposalCascadeOwners.clear();
@@ -2363,103 +2684,141 @@ function disposeOwner(owner) {
2363
2684
  function readCompiledOwnerMetrics() {
2364
2685
  return {
2365
2686
  active: activeOwnerCount,
2366
- created: createdOwnerCount
2687
+ created: createdOwnerCount,
2688
+ updaters: createdUpdaterCount,
2689
+ schedulerPlans: createdSchedulerPlanCount
2367
2690
  };
2368
2691
  }
2692
+ /** @internal Test-only publication traversal evidence. */
2693
+ function readCompiledPublicationMetrics() {
2694
+ return { visitedNodes: visitedPublishedNodeCount };
2695
+ }
2696
+ function ensureMountedBindingRange(state) {
2697
+ if (state.start !== null && state.end !== null) return [state.start, state.end];
2698
+ const anchor = state.text;
2699
+ const parent = anchor?.parentNode;
2700
+ if (anchor === null || parent === null || parent === void 0) throw new Error(DEV ? "markerless binding text is detached" : "V010");
2701
+ state.start = document.createComment(DEV ? "vidact:binding" : "");
2702
+ state.end = document.createComment(DEV ? "/vidact:binding" : "");
2703
+ parent.insertBefore(state.start, anchor);
2704
+ parent.insertBefore(state.end, anchor.nextSibling);
2705
+ return [state.start, state.end];
2706
+ }
2707
+ function clearMountedBinding(state) {
2708
+ const [start, end] = ensureMountedBindingRange(state);
2709
+ const owner = state.currentOwner;
2710
+ state.currentOwner = null;
2711
+ state.text = null;
2712
+ disposeRange(owner, start, end);
2713
+ }
2369
2714
  function mountCompiledBindingBefore(parent, value, before) {
2370
- const unset = Symbol(DEV ? "Vidact.UnsetBinding" : void 0);
2371
2715
  const initial = value[1]();
2372
2716
  const scalarInitial = isScalarRenderValue(initial);
2717
+ const structuralInitial = ownedStructuralBinding(initial);
2373
2718
  const hydratedTextRange = scalarInitial ? claimHydrationTextRange(parent, toText(initial)) : void 0;
2374
- const borrowedHydrationRange = isHydrating() && !scalarInitial ? borrowHydrationSlotRange(parent, isStructuralBinding(initial) && initial[2] === "slot") : void 0;
2719
+ const borrowedHydrationRange = isHydrating() && !scalarInitial ? borrowHydrationSlotRange(parent, structuralInitial?.[2] === "slot") : void 0;
2375
2720
  const hydratedStructuralRange = isHydrating() && !scalarInitial ? borrowedHydrationRange ?? claimHydrationSlotRange(parent) : void 0;
2376
2721
  const hydratedRange = hydratedTextRange ?? hydratedStructuralRange;
2377
- const start = hydratedRange?.[0] ?? document.createComment(DEV ? "vidact:binding" : "");
2378
- const end = hydratedRange?.[1] ?? document.createComment(DEV ? "/vidact:binding" : "");
2379
- if (hydratedRange === void 0) {
2722
+ const markerlessScalar = hydratedRange === void 0 && scalarInitial && !isHydrating();
2723
+ let start = hydratedRange?.[0] ?? null;
2724
+ let end = hydratedRange?.[1] ?? null;
2725
+ if (!markerlessScalar && hydratedRange === void 0) {
2726
+ start = document.createComment(DEV ? "vidact:binding" : "");
2727
+ end = document.createComment(DEV ? "/vidact:binding" : "");
2380
2728
  parent.insertBefore(start, before);
2381
2729
  parent.insertBefore(end, before);
2382
2730
  }
2383
- let current = hydratedTextRange === void 0 ? unset : initial;
2384
- let currentOwner = null;
2385
- let text = hydratedTextRange?.[2] ?? null;
2386
- const stableRenderable = (renderable) => {
2387
- const identity = renderableIdentity(renderable);
2388
- let previous = renderablePropsSnapshot(renderable);
2389
- const input = binding(value[2], value[3], () => {
2390
- const next = value[1]();
2391
- if (!isRenderableProtocol(next) || !Object.is(renderableIdentity(next), identity)) return previous;
2392
- previous = renderablePropsSnapshot(next);
2393
- return previous;
2394
- }, value[4], value[5]);
2395
- return materializeRenderableWithInput(renderable, input);
2396
- };
2397
- const clear = () => {
2398
- const owner = currentOwner;
2399
- currentOwner = null;
2400
- text = null;
2401
- disposeRange(owner, start, end);
2731
+ const state = {
2732
+ start,
2733
+ end,
2734
+ current: hydratedTextRange === void 0 && !markerlessScalar ? UNSET_BINDING : initial,
2735
+ currentOwner: null,
2736
+ text: hydratedTextRange?.[2] ?? null
2402
2737
  };
2738
+ if (markerlessScalar) {
2739
+ state.text = document.createTextNode(toText(initial));
2740
+ parent.insertBefore(state.text, before);
2741
+ }
2403
2742
  const update = () => {
2404
2743
  const next = value[1]();
2405
- if (current !== unset && Object.is(next, current)) return;
2406
- if (current !== unset && isRenderableProtocol(current) && isRenderableProtocol(next) && canReconcileRenderable(current) && canReconcileRenderable(next) && Object.is(renderableIdentity(current), renderableIdentity(next))) {
2407
- current = next;
2744
+ if (state.current !== UNSET_BINDING && Object.is(next, state.current)) return;
2745
+ if (state.current !== UNSET_BINDING && isRenderableProtocol(state.current) && isRenderableProtocol(next) && canReconcileRenderable(state.current) && canReconcileRenderable(next) && Object.is(renderableIdentity(state.current), renderableIdentity(next))) {
2746
+ state.current = next;
2408
2747
  return;
2409
2748
  }
2410
- const currentParent = rangeParent(start, end, "binding range");
2411
2749
  if (isScalarRenderValue(next)) {
2412
2750
  const content = toText(next);
2413
- if (text !== null) {
2414
- const target = text;
2751
+ if (state.text !== null) {
2752
+ const target = state.text;
2415
2753
  const previousContent = target.data;
2416
- const previous = current;
2754
+ const previous = state.current;
2417
2755
  stagePublication([() => {
2418
2756
  if (target.data !== content) target.data = content;
2419
- current = next;
2757
+ state.current = next;
2420
2758
  }, () => {
2421
2759
  if (target.data !== previousContent) target.data = previousContent;
2422
- current = previous;
2760
+ state.current = previous;
2423
2761
  }]);
2424
2762
  return;
2425
2763
  }
2426
- clear();
2427
- text = document.createTextNode(content);
2428
- currentParent.insertBefore(text, end);
2429
- current = next;
2764
+ clearMountedBinding(state);
2765
+ const [rangeStart, rangeEnd] = ensureMountedBindingRange(state);
2766
+ const currentParent = rangeParent(rangeStart, rangeEnd, "binding range");
2767
+ state.text = document.createTextNode(content);
2768
+ currentParent.insertBefore(state.text, rangeEnd);
2769
+ state.current = next;
2430
2770
  return;
2431
2771
  }
2772
+ const [rangeStart, rangeEnd] = ensureMountedBindingRange(state);
2773
+ const currentParent = rangeParent(rangeStart, rangeEnd, "binding range");
2432
2774
  const nextOwner = createOwner();
2433
- const [fragment, staged] = stageValue(isRenderableProtocol(next) && canReconcileRenderable(next) ? stableRenderable(next) : next, nextOwner);
2775
+ const [fragment, staged] = stageValue(isRenderableProtocol(next) && canReconcileRenderable(next) ? stableRenderableBinding(value, next) : next, nextOwner);
2434
2776
  try {
2435
- clear();
2777
+ clearMountedBinding(state);
2436
2778
  } catch (error) {
2437
2779
  disposeOwner(nextOwner);
2438
2780
  throw error;
2439
2781
  }
2440
- currentOwner = nextOwner;
2441
- currentParent.insertBefore(fragment, end);
2782
+ state.currentOwner = nextOwner;
2783
+ currentParent.insertBefore(fragment, rangeEnd);
2442
2784
  commitPublishedNodes(staged);
2443
- current = next;
2785
+ state.current = next;
2444
2786
  };
2445
2787
  if (hydratedStructuralRange !== void 0) {
2788
+ const rangeEnd = hydratedStructuralRange[1];
2446
2789
  const nextOwner = createOwner();
2447
- const [fragment, staged] = withHydrationInsertion(parent, end, () => stageRender(() => isRenderableProtocol(initial) && canReconcileRenderable(initial) ? stableRenderable(initial) : initial, nextOwner));
2448
- parent.insertBefore(fragment, end);
2790
+ const [fragment, staged] = withHydrationInsertion(parent, rangeEnd, () => stageRender(() => isRenderableProtocol(initial) && canReconcileRenderable(initial) ? stableRenderableBinding(value, initial) : initial, nextOwner));
2791
+ parent.insertBefore(fragment, rangeEnd);
2449
2792
  commitPublishedNodes(staged);
2450
- currentOwner = nextOwner;
2451
- current = initial;
2452
- } else if (hydratedRange === void 0) update();
2793
+ state.currentOwner = nextOwner;
2794
+ state.current = initial;
2795
+ } else if (hydratedRange === void 0 && !markerlessScalar) update();
2453
2796
  const removeUpdater = subscribeBinding(value, update);
2454
2797
  onCleanup(() => {
2455
2798
  removeUpdater();
2456
- clear();
2799
+ if (state.start === null || state.end === null) {
2800
+ state.text?.remove();
2801
+ state.text = null;
2802
+ return;
2803
+ }
2804
+ clearMountedBinding(state);
2457
2805
  if (borrowedHydrationRange === void 0) {
2458
- start.remove();
2459
- end.remove();
2806
+ state.start.remove();
2807
+ state.end.remove();
2460
2808
  }
2461
2809
  });
2462
2810
  }
2811
+ function stableRenderableBinding(value, renderable) {
2812
+ const identity = renderableIdentity(renderable);
2813
+ let previous = renderablePropsSnapshot(renderable);
2814
+ const input = binding(value[2], value[3], () => {
2815
+ const next = value[1]();
2816
+ if (!isRenderableProtocol(next) || !Object.is(renderableIdentity(next), identity)) return previous;
2817
+ previous = renderablePropsSnapshot(next);
2818
+ return previous;
2819
+ }, value[4], value[5]);
2820
+ return materializeRenderableWithInput(renderable, input);
2821
+ }
2463
2822
  function materialize(value) {
2464
2823
  const insertionPoint = hydrationInsertionPoint();
2465
2824
  if (insertionPoint !== void 0) {
@@ -2516,6 +2875,30 @@ function stageRender(render, owner) {
2516
2875
  throw error;
2517
2876
  }
2518
2877
  }
2878
+ function stageMarkerlessHydrationRender(parent, before, render, owner) {
2879
+ const first = hydrationCursor(parent);
2880
+ if (first === void 0) throw new Error("markerless hydration render requires active hydration");
2881
+ try {
2882
+ withHydrationInsertion(parent, before, () => withOwner(owner, () => insertValue(parent, render(), before)));
2883
+ } catch (error) {
2884
+ try {
2885
+ disposeOwner(owner);
2886
+ } catch {}
2887
+ throw error;
2888
+ }
2889
+ const after = hydrationCursor(parent);
2890
+ if (after === void 0) {
2891
+ disposeOwner(owner);
2892
+ throw new Error("markerless hydration render lost its hydration cursor");
2893
+ }
2894
+ const nodes = [];
2895
+ for (let node = first; node !== null && node !== after; node = node.nextSibling) nodes.push(node);
2896
+ return [
2897
+ first,
2898
+ after,
2899
+ nodes
2900
+ ];
2901
+ }
2519
2902
  function insertValue(parent, value, before, moves) {
2520
2903
  if (value === null || value === void 0 || typeof value === "boolean") {
2521
2904
  claimHydrationText(parent, "");
@@ -2621,10 +3004,13 @@ function isRefValue(value) {
2621
3004
  return value === null || value === void 0 || typeof value === "function" || typeof value === "object" && value !== null && "current" in value;
2622
3005
  }
2623
3006
  function claimPendingRefOwners(root) {
3007
+ if (pendingRefCount === 0) return;
2624
3008
  visitNodes(root, (node) => {
2625
3009
  if (!(node instanceof Element)) return;
2626
3010
  const pending = pendingRefs.get(node);
2627
- if (pending !== void 0 && pending[0] === null) pending[0] = activeOwner;
3011
+ if (pending === void 0 || pending[0] !== null) return;
3012
+ pending[0] = activeOwner;
3013
+ activeOwner?.[1].push(() => deletePendingRef(node, pending));
2628
3014
  });
2629
3015
  }
2630
3016
  function commitPendingRefs(root) {
@@ -2637,9 +3023,9 @@ function commitPublishedNodes(nodes) {
2637
3023
  function commitPublishedNodesNow(nodes) {
2638
3024
  const publicationRoot = nodes[0]?.getRootNode();
2639
3025
  if (publicationRoot instanceof DocumentFragment && !(publicationRoot instanceof ShadowRoot)) return;
2640
- for (const node of nodes) commitNodeInsertions(node);
2641
- for (const node of nodes) commitNodeRefs(node);
2642
- for (const node of nodes) commitNodeResources(node);
3026
+ if (pendingInsertionOwnerCount > 0) for (const node of nodes) commitNodeInsertions(node);
3027
+ if (pendingRefCount > 0) for (const node of nodes) commitNodeRefs(node);
3028
+ if (pendingOwnerCommitCount > 0) for (const node of nodes) commitNodeResources(node);
2643
3029
  }
2644
3030
  function commitNodeInsertions(root) {
2645
3031
  visitNodes(root, (node) => {
@@ -2651,12 +3037,12 @@ function commitNodeRefs(root) {
2651
3037
  if (node instanceof Element) {
2652
3038
  const pending = pendingRefs.get(node);
2653
3039
  if (pending !== void 0) {
2654
- pendingRefs.delete(node);
3040
+ deletePendingRef(node, pending);
2655
3041
  const owner = pending[0] ?? activeOwner;
2656
3042
  commitContextInsertions(owner?.[2] ?? null);
2657
3043
  commitOwnerInsertions(owner ?? void 0);
2658
3044
  const cleanup = attachRef(pending[1], node);
2659
- if (pending[2] === void 0) owner?.[1].add(cleanup);
3045
+ if (pending[2] === void 0) owner?.[1].push(cleanup);
2660
3046
  else pending[2](cleanup);
2661
3047
  }
2662
3048
  }
@@ -2677,6 +3063,7 @@ function commitOwnerInsertions(owner) {
2677
3063
  const commits = pendingInsertionCommits.get(owner);
2678
3064
  if (commits === void 0) return;
2679
3065
  pendingInsertionCommits.delete(owner);
3066
+ pendingInsertionOwnerCount -= 1;
2680
3067
  for (const commit of commits) commit();
2681
3068
  }
2682
3069
  function commitOwnerResources(owner) {
@@ -2684,6 +3071,7 @@ function commitOwnerResources(owner) {
2684
3071
  const commits = pendingOwnerCommits.get(owner);
2685
3072
  if (commits === void 0) return;
2686
3073
  pendingOwnerCommits.delete(owner);
3074
+ pendingOwnerCommitCount -= 1;
2687
3075
  for (const commit of commits) commit();
2688
3076
  }
2689
3077
  function commitRangeRefs(start, end) {
@@ -2696,6 +3084,7 @@ function commitRangeRefs(start, end) {
2696
3084
  commitPublishedNodesNow(nodes);
2697
3085
  }
2698
3086
  function visitNodes(root, visit) {
3087
+ visitedPublishedNodeCount += 1;
2699
3088
  visit(root);
2700
3089
  for (const child of root.childNodes) visitNodes(child, visit);
2701
3090
  }
@@ -2747,7 +3136,8 @@ function drainFlushes() {
2747
3136
  throw new Error(DEV ? "Vidact compiled scopes did not stabilize" : "V011");
2748
3137
  }
2749
3138
  runs.set(flush, runCount);
2750
- flush();
3139
+ if (typeof flush === "function") flush();
3140
+ else flush[1]();
2751
3141
  }
2752
3142
  activePublication = null;
2753
3143
  committing = true;
@@ -2852,6 +3242,6 @@ function abortPublication(operations) {
2852
3242
  } catch {}
2853
3243
  }
2854
3244
  //#endregion
2855
- export { COMPONENT_SPREAD_SOURCE, DEV, Suspense, adoptCompiledRoot, binding, captureCompiledOwnerStack, captureCompiledTask, choose, compiledEffect, compiledEvent, compiledImperativeHandle, compiledInsertionEffect, compiledLayoutEffect, compiledRoot, constructCompiledComponent, createCompiledAsync, createCompiledContext, createCompiledEffectEvent, createCompiledExternalStore, createCompiledId, createCompiledMemo, createCompiledProp, createCompiledReducer, createCompiledRestProp, createCompiledScope, createCompiledState, createContext, createNarrowCompiledScope, createPortal, deferred, dispatch, enableProfiling, enableRetainedUi, errorBoundary, hydrateCompiled, indexed, isCompiledBinding, isCompiledComponentResult, isCompiledContext, isStructuralBinding, keyed, mountCompiled, mountCompiledBinding, mountCompiledProp, mountCompiledPropTransition, mountCompiledRef, objectRest, profiled, queueElementRef, readCompiledOwnerMetrics, recordCompiledDebugValue, registerCompiledCleanup, retainedActivity, runCompiledTransaction, runWithCompiledContext, suspense, use, useCallback, useContext, useEffect, useEffectEvent, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useSyncExternalStore, when };
3245
+ export { COMPONENT_SPREAD_SOURCE, DEV, Suspense, adoptCompiledRoot, binding, captureCompiledOwnerStack, captureCompiledTask, choose, compiledEffect, compiledEvent, compiledImperativeHandle, compiledInlineEvent, compiledInsertionEffect, compiledLayoutEffect, compiledRoot, constructCompiledComponent, createCompiledAsync, createCompiledContext, createCompiledEffectEvent, createCompiledExternalStore, createCompiledId, createCompiledMemo, createCompiledProp, createCompiledReducer, createCompiledRestProp, createCompiledScope, createCompiledState, createContext, createNarrowCompiledScope, createPortal, deferred, dispatch, enableProfiling, enableRetainedUi, errorBoundary, hydrateCompiled, indexed, isCompiledBinding, isCompiledComponentResult, isCompiledContext, isCompiledEventHandler, isStructuralBinding, keyed, mountCompiled, mountCompiledBinding, mountCompiledProp, mountCompiledPropTransition, mountCompiledRef, objectRest, profiled, queueElementRef, readCompiledOwnerMetrics, readCompiledPublicationMetrics, recordCompiledDebugValue, registerCompiledCleanup, retainedActivity, runCompiledTransaction, runWithCompiledContext, suspense, use, useCallback, useContext, useEffect, useEffectEvent, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useSyncExternalStore, when };
2856
3246
 
2857
3247
  //# sourceMappingURL=core.js.map