@solidjs/signals 2.0.0-rc.2 → 2.0.0-rc.20

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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,172 +0,0 @@
1
- import { computed, suppressComputedRecompute } from "../../core/core.js";
2
-
3
- import { getOwner } from "../../core/owner.js";
4
-
5
- import { setProjectionWriteActive, projectionWriteActive } from "../../core/scheduler.js";
6
-
7
- import { handleAsync } from "../../core/async.js";
8
-
9
- import "../../core/verdict.js";
10
-
11
- import "../../core/effect.js";
12
-
13
- import { CONFIG_AUTO_DISPOSE } from "../../core/constants.js";
14
-
15
- import { $TARGET, markRawIngest, STORE_VALUE, setWriteOverride } from "../store.js";
16
-
17
- import { reconcileNextState } from "./reconcile.js";
18
-
19
- import { wrapNext, storeSetterNext } from "./store.js";
20
-
21
- /**
22
- * Store rewrite — projections (§7/§7b): a projection is a computed store.
23
- * The derive runs inside a computed whose recompute merges its output into
24
- * the projection's backing through the adoption channel (replace-mode root:
25
- * entity changes merge in place, the root proxy is stable for life). Children
26
- * wrap into the projection's own FAMILY (writes land here, never in a source
27
- * family), and every family node carries the projection computed as its
28
- * firewall — reads link the derive's status and lifecycle natively. The §6c
29
- * status gate in the traps makes an uninitialized async derive's seed
30
- * unobservable through every read surface.
31
- *
32
- * Mirrors the legacy runProjectionComputed shape (shadow runs for open
33
- * loading windows, handleAsync landings, commit-through-setter) on next
34
- * primitives; the generic draft write-traps are reused from the legacy
35
- * module unchanged.
36
- */ function createWriteTraps(e, t) {
37
- // Save/restore, never hard-reset: the draft can be driven from inside an
38
- // enclosing authoritative-write scope (next-store optimistic derives), and
39
- // a hard `false` would clobber it mid-derive.
40
- const r = {
41
- get(e, t) {
42
- let o;
43
- const i = projectionWriteActive;
44
- setWriteOverride(true);
45
- setProjectionWriteActive(true);
46
- try {
47
- o = e[t];
48
- } finally {
49
- setWriteOverride(false);
50
- setProjectionWriteActive(i);
51
- }
52
- if (t === $TARGET) return o;
53
- return typeof o === "object" && o !== null ? new Proxy(o, r) : o;
54
- },
55
- has(e, t) {
56
- let r;
57
- const o = projectionWriteActive;
58
- setWriteOverride(true);
59
- setProjectionWriteActive(true);
60
- try {
61
- r = t in e;
62
- } finally {
63
- setWriteOverride(false);
64
- setProjectionWriteActive(o);
65
- }
66
- return r;
67
- },
68
- set(r, o, i) {
69
- if (e && !e()) return true;
70
- const n = projectionWriteActive;
71
- setWriteOverride(true);
72
- setProjectionWriteActive(true);
73
- try {
74
- r[o] = i;
75
- t?.();
76
- } finally {
77
- setWriteOverride(false);
78
- setProjectionWriteActive(n);
79
- }
80
- return true;
81
- },
82
- deleteProperty(r, o) {
83
- if (e && !e()) return true;
84
- const i = projectionWriteActive;
85
- setWriteOverride(true);
86
- setProjectionWriteActive(true);
87
- try {
88
- delete r[o];
89
- t?.();
90
- } finally {
91
- setWriteOverride(false);
92
- setProjectionWriteActive(i);
93
- }
94
- return true;
95
- }
96
- };
97
- return r;
98
- }
99
-
100
- function createProjectionNextInternal(e, t, r) {
101
- const o = {
102
- map: new WeakMap,
103
- node: null,
104
- shallow: !!r?.shallow
105
- };
106
- const i = wrapNext(t, null, null, o);
107
- if (o.shallow) {
108
- // Shallow projection: the root is the only wrapped level — slot values
109
- // serve raw, ingests sticky raw-mark (same t.s machinery as plain).
110
- i[$TARGET].s = true;
111
- markRawIngest(t);
112
- }
113
- let n;
114
- if (r?.seedLoadingValue) n = {
115
- loadingValue: undefined
116
- };
117
- const c = computed(() => {
118
- if (!o.node) o.node = getOwner();
119
- runProjectionComputedNext(i, e, r?.key === undefined ? "id" : r.key);
120
- }, n);
121
- c.T &= ~CONFIG_AUTO_DISPOSE;
122
- o.node = c;
123
- return {
124
- store: i,
125
- node: c
126
- };
127
- }
128
-
129
- function createProjectionNext(e, t, r) {
130
- return createProjectionNextInternal(e, t, r).store;
131
- }
132
-
133
- /** Derived writable store (legacy parity): a projection whose public setter
134
- * masks the recompute for the tick (core R31 — the manual write wins over a
135
- * same-flush dependency change). */ function createStoreDerivedNext(e, t, r) {
136
- const {store: o, node: i} = createProjectionNextInternal(e, t, r);
137
- return [ o, e => {
138
- // Mark the projection as manually written before notifying nodes.
139
- suppressComputedRecompute(i);
140
- storeSetterNext(o, e);
141
- } ];
142
- }
143
-
144
- function runProjectionComputedNext(e, t, r, o, i) {
145
- const n = getOwner();
146
- let c = false;
147
- let s;
148
- // Open loading window (seedLoadingValue): the observable store IS commit #0
149
- // for the whole first flight — the derive works a detached shadow of the
150
- // seed so draft writes cannot tear through to readers (#2988). Every commit
151
- // point reconciles the shadow through the normal commit path.
152
- const u = n.Ie ? JSON.parse(JSON.stringify(e[$TARGET][STORE_VALUE])) : null;
153
- const l = new Proxy(e, createWriteTraps(() => !c || n.o?.Ee === s, i));
154
- storeSetterNext(l, i => {
155
- s = t(u ?? i);
156
- c = true;
157
- const commit = t => {
158
- // Shadow run: commit a detached snapshot, never the shadow itself
159
- // (adoption takes the value by identity — handing it the live shadow
160
- // would fuse the draft to the observable store).
161
- if (u && (t === undefined || t === u)) t = JSON.parse(JSON.stringify(u));
162
- if (t === i || t === undefined) return;
163
- const write = () => storeSetterNext(e, e => reconcileNextState(t, e, r, true), false);
164
- o ? o(write) : write();
165
- };
166
- const l = handleAsync(n, s, commit);
167
- if (!n.Ie) commit(l);
168
- }, false);
169
- return n;
170
- }
171
-
172
- export { createProjectionNext, createStoreDerivedNext, runProjectionComputedNext };
@@ -1,331 +0,0 @@
1
- import { isEqual } from "../../core/core.js";
2
-
3
- import { projectionWriteActive } from "../../core/scheduler.js";
4
-
5
- import "../../core/invariants.js";
6
-
7
- import "../../core/verdict.js";
8
-
9
- import "../../core/effect.js";
10
-
11
- import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue, getWriteOverride } from "../store.js";
12
-
13
- import { materializePB, adoptPB, unwrapValue, notifyFold, targetsEqual, bumpDeep, notifyKeyValue, notifyKeyDiff, notifyFoldTail, hasAccessorFlag } from "./store.js";
14
-
15
- import { storeNextLookup, optHooks, ownedRaw } from "./target.js";
16
-
17
- /**
18
- * Store rewrite — reconcile, the adoption channel (INTERNALS-STORE-STATE.md
19
- * §3, decision 2026-08-16c). Reconcile never merge-writes: it adopts `next`
20
- * as the authoritative pending backing at every proxied level (pointer swap
21
- * folded at flush commit), notification riding the fold's descriptor diff.
22
- *
23
- * Structural optimizations (all kept, per 2026-08-17 morning ruling):
24
- * - Identity skip with completed proof: `incoming === backing && !owned` —
25
- * sound because input is immutable by convention (R2a) and ownership marks
26
- * the only writer the convention doesn't cover (us). Fixes FINDING-1.
27
- * - Reachability pruning: descent happens only where a child TARGET exists
28
- * (proxies exist only where read) — never-subscribed subtrees are never
29
- * walked (recon-snap R17), while a subscriber deep below an untracked path
30
- * keeps its chain walkable because wrapping created the intermediate
31
- * targets (recon-snap R16).
32
- * - Keyed matching ported semantics: key-matched rows keep proxy identity;
33
- * key mismatch detaches (fresh proxy on next read, recon-snap R18);
34
- * keyless items fall back positional; null/primitive slots are legal
35
- * members (R11). Kind changes replace wholesale (R10).
36
- */ function reconcileNextState(e, t, n, o = false) {
37
- if (t == null) throw new Error("");
38
- const l = t?.[$TARGET];
39
- if (l === undefined || l.px !== t) throw new Error("");
40
- // Reconcile's diff walks need a REAL pending container — a prototype
41
- // overlay (#3044) materializes to the clone path first (edge: reconcile
42
- // inside a setter that already wrote this target).
43
- if (l.ovl) materializePB(l);
44
- let f = n === null ? null : typeof n === "string" ? e => e?.[n] : n;
45
- // §7b chained backing: a projection derive returning a LIVE store proxy
46
- // adopts the proxy itself as the backing — reads flow through the inner
47
- // store's traps, so consumers subscribe to the inner graph and updates
48
- // flow with no re-derive (#2941). The adoption diff still notifies THIS
49
- // store's existing subscribers of the swap.
50
- if (o && e !== t && e?.[$TARGET] !== undefined) {
51
- const t = l.pb ?? l.v;
52
- if (t === e) return;
53
- // already chained to this store
54
- adoptPB(l, e);
55
- return;
56
- }
57
- const i = unwrapValue(e);
58
- if (f) {
59
- // Root identity precondition — checked before ANY mutation, so a throwing
60
- // reconcile is atomic by construction (RUL-12 ruling). Projections
61
- // (replace=true) relax it: a root entity change merges in place — the
62
- // root proxy is stable for life (proj R5/R11) — and children are NOT
63
- // key-matched across the entity change (proj R7: keyFn drops to
64
- // positional so old-entity subtrees never merge into the new entity's).
65
- const e = l.pb ?? l.v;
66
- const t = f(e);
67
- if (t !== undefined && f(i) !== t) {
68
- if (!o) throw new Error("");
69
- // Entity change: wholesale swap. The root proxy is stable for life
70
- // (proj R5) but NOTHING below survives — children are never matched
71
- // across an entity change even when their own keys align (proj R7).
72
- // Displaced-raw unregistration (proj R10): the outgoing raw stops
73
- // resolving to this proxy; re-handed later it wraps fresh.
74
- (l.fam?.map ?? storeNextLookup).delete(l.pb ?? l.v);
75
- adoptPB(l, i);
76
- return;
77
- }
78
- }
79
- // Tentative channel (§6b, RUL-5): a user-context reconcile on an optimistic
80
- // family parks as engine overrides — values, membership, and length ride
81
- // armed nodes (reverting with their transaction); committed raw is never
82
- // touched. Key-matched rows keep proxy identity by descending into the
83
- // existing child targets instead of overriding their parent slots.
84
- if (l.fam?.opt === true && !projectionWriteActive && !getWriteOverride()) {
85
- optHooks.applyTentative(l, i, f);
86
- return;
87
- }
88
- applyAdopt(l, i, f, o);
89
- }
90
-
91
- function applyAdopt(e, t, n, o = false) {
92
- const l = e.pb ?? e.v;
93
- // The sound identity skip (O7): same reference AND we never diverged it.
94
- if (t === l && !ownedRaw.has(l)) return;
95
- const f = e.fam;
96
- // §6b (R28): the diff's previous-arrangement baseline is the LANE VIEW —
97
- // optimistic rows must be visible to key matching so a landing carrying the
98
- // same key recycles their proxies. Raw `prev` keeps the identity/ownership
99
- // roles above; only matching reads the view.
100
- const i = f?.opt === true ? optHooks.optimisticView(e, l) : l;
101
- const r = Array.isArray(t);
102
- // Plain stores notify inline AFTER the descent (child registrations feed
103
- // the fold diff's identity-preservation check); projections keep deferred
104
- // folds (downstream holds can form later in the flush).
105
- const u = f === null;
106
- const s = e.s === true;
107
- const a = e.v;
108
- adoptPB(e, t, u);
109
- // Shallow adoption: records are slot values — sticky raw-mark the incoming
110
- // set (R41) and never descend; slot notification is the positional diff.
111
- if (s) markRawIngest(t);
112
- if (Array.isArray(i) !== r) {
113
- if (u) notifyFold(e, a, t);
114
- return;
115
- }
116
- if (r) {
117
- const l = i;
118
- const r = t;
119
- // Fused array walk (eager mode): per-index notification rides the same
120
- // loop as the descent (descend first — targetsEqual needs the child's
121
- // re-registration, R9). Length, trailing removed indexes, and any other
122
- // unvisited node keys land in the counted sweep below.
123
- const c = u ? e.n : null;
124
- let p = 0;
125
- if (n && !s) {
126
- // Positional-prefix fast path (legacy keyedMatch-walk parity): while
127
- // rows key-match in place — the steady-state polling shape — descend
128
- // directly with zero staging. The prevByKey map is built only for the
129
- // misaligned remainder, and never at all on aligned ticks.
130
- const i = l.length;
131
- const u = r.length;
132
- let s = false;
133
- let d = 0;
134
- for (const y = Math.min(i, u); d < y; d++) {
135
- const i = r[d];
136
- const u = l[d];
137
- // Routing heuristic only (aligned vs keyed remainder) — both routes
138
- // notify identically and descend() is the one authoritative
139
- // validator, so bare typeof gates suffice here; full isWrappable
140
- // per row was the walk's dominant residual cost.
141
- if (u !== i && !(u !== null && typeof u === "object" && i !== null && typeof i === "object" && n(u) === n(i))) break;
142
- // misaligned: fall to the keyed remainder below
143
- // Identity skip inline (FINDING-1 guard), then descend the pair.
144
- if ((u !== i || i !== null && typeof i === "object" && ownedRaw.has(i)) && i !== null && typeof i === "object") descend(unwrapValue(u), i, n, f, o);
145
- if (e.dk !== null && !s && !(i !== null && typeof i === "object" ? targetsEqual(u, i) : isEqual(u, i))) {
146
- bumpDeep(e);
147
- s = true;
148
- }
149
- if (c !== null) {
150
- const e = c[d];
151
- if (e !== undefined) {
152
- p++;
153
- notifyKeyValue(e, d, a[d], i, a, t);
154
- }
155
- }
156
- }
157
- if (e.dk !== null && !s && d < r.length) bumpDeep(e);
158
- let y = null;
159
- for (;d < r.length; d++) {
160
- const e = r[d];
161
- // typeof gates route; descend validates (same contract as the prefix).
162
- if (e !== null && typeof e === "object") {
163
- const t = n(e);
164
- let i;
165
- if (t !== undefined) {
166
- if (y === null) {
167
- y = new Map;
168
- for (let e = 0; e < l.length; e++) {
169
- const t = unwrapValue(l[e]);
170
- if (t !== null && typeof t === "object") {
171
- const e = n(t);
172
- if (e !== undefined && !y.has(e)) y.set(e, t);
173
- }
174
- }
175
- }
176
- i = y.get(t);
177
- } else {
178
- i = unwrapValue(l[d]);
179
- // keyless item: positional fallback
180
- }
181
- descend(i, e, n, f, o);
182
- }
183
- if (c !== null) {
184
- const e = c[d];
185
- if (e !== undefined) {
186
- p++;
187
- notifyKeyDiff(e, d, a, t, false);
188
- }
189
- }
190
- }
191
- } else {
192
- const i = Math.min(l.length, r.length);
193
- const u = r.length;
194
- let d = false;
195
- for (let y = 0; y < u; y++) {
196
- const u = r[y];
197
- if (!s && y < i && u !== null && typeof u === "object") descend(unwrapValue(l[y]), u, n, f, o);
198
- if (e.dk !== null && !d && !(u !== null && typeof u === "object" ? targetsEqual(l[y], u) : isEqual(l[y], u))) {
199
- bumpDeep(e);
200
- d = true;
201
- }
202
- if (c !== null) {
203
- const e = c[y];
204
- if (e !== undefined) {
205
- p++;
206
- notifyKeyDiff(e, y, a, t, false);
207
- }
208
- }
209
- }
210
- }
211
- if (u) {
212
- if (c !== null && p < e.nc) {
213
- for (const e of Reflect.ownKeys(c)) {
214
- // visited indexes are < nextRows.length; everything else sweeps
215
- const n = typeof e === "string" ? +e : NaN;
216
- if (!(n >= 0 && n < r.length)) notifyKeyDiff(c[e], e, a, t, false);
217
- }
218
- }
219
- notifyFoldTail(e, a, t);
220
- }
221
- return;
222
- } else {
223
- // FUSED adoption walk (eager mode): one pass fetches each key's pair,
224
- // descends, then notifies its node inline — descend runs FIRST so the
225
- // child's re-registration is visible to targetsEqual (identity-preserved
226
- // slots must not notify, R9). This replaces the notifyFold re-walk that
227
- // doubled dbmon's diff cost. for-in covers own enumerable string keys
228
- // with no key-array allocation; symbols get a pass only when present.
229
- const l = u ? e.n : null;
230
- let r = 0;
231
- let c = false;
232
- // The per-key body is inlined on purpose (legacy applyStateFast parity:
233
- // an extracted helper costs a call per key on the hottest object-diff
234
- // site). Reference-identical values early-continue BEFORE any other
235
- // work — sound only with the ownership guard (FINDING-1: an owned
236
- // backing is setter-diverged and must still diff).
237
- for (const u in t) {
238
- const p = t[u];
239
- const d = a[u];
240
- const y = p !== null && typeof p === "object";
241
- if (d === p && (!y || !ownedRaw.has(p)) && (l === null || l[u] === undefined || !hasAccessorFlag(l[u]))) {
242
- if (l !== null && l[u] !== undefined) r++;
243
- continue;
244
- }
245
- if (y && !s) descend(unwrapValue(i[u]), p, n, f, o);
246
- // Deep-witness (dk): value changes must notify even with NO per-key
247
- // node — deep() subscribes one node per record. Checked after descend
248
- // so in-place adoptions (same logical slot) don't bump; child records
249
- // carry their own witness. One flag + null check when unused.
250
- if (e.dk !== null && !c && !(y ? targetsEqual(d, p) : isEqual(d, p))) {
251
- bumpDeep(e);
252
- c = true;
253
- }
254
- if (l !== null) {
255
- const e = l[u];
256
- if (e !== undefined) {
257
- r++;
258
- notifyKeyValue(e, u, d, p, a, t);
259
- }
260
- }
261
- }
262
- const p = Object.getOwnPropertySymbols(t);
263
- for (let e = 0; e < p.length; e++) {
264
- const u = p[e];
265
- const c = t[u];
266
- if (!s && c !== null && typeof c === "object") descend(unwrapValue(i[u]), c, n, f, o);
267
- if (l !== null) {
268
- const e = l[u];
269
- if (e !== undefined) {
270
- r++;
271
- notifyKeyValue(e, u, a[u], c, a, t);
272
- }
273
- }
274
- }
275
- if (u) {
276
- // Deleted-key nodes (in the map but absent from incoming) — counted
277
- // fast-out: when every node was visited, skip the sweep entirely.
278
- if (l !== null && r < e.nc) {
279
- for (const e of Reflect.ownKeys(l)) {
280
- if (!hasOwnP.call(t, e)) notifyKeyDiff(l[e], e, a, t, false);
281
- }
282
- }
283
- notifyFoldTail(e, a, t);
284
- }
285
- return;
286
- }
287
- }
288
-
289
- const hasOwnP = Object.prototype.hasOwnProperty;
290
-
291
- function descend(e, t, n, o, l = false) {
292
- if (e === null || typeof e !== "object" || t === null || typeof t !== "object") return;
293
- // Lookup FIRST: a hit implies pv was wrappable and never raw-marked (only
294
- // wrappables acquire targets; rawValues never wrap) — one WeakMap get
295
- // replaces isWrappable(pv) + isRawValue(pv), and a miss prunes untracked
296
- // subtrees before any further checks.
297
- const f = (o?.map ?? storeNextLookup).get(e);
298
- if (f === undefined) return;
299
- // nothing proxied below this pair
300
- // The NEW side still validates fully: a frozen/platform/markRaw'd incoming
301
- // value is a leaf for reconcile — replaced by reference, never recursed
302
- // into (R42); the parent's slot notification covers the change.
303
- if (!isWrappable(t)) return;
304
- if (rawValuesUsed && isRawValue(t)) return;
305
- t = unwrapValue(t);
306
- // Kind change replaces wholesale, never merges (R10): a target's carrier
307
- // class (array vs object) is fixed at creation, so the slot detaches and a
308
- // fresh proxy of the right kind wraps the incoming value on next read.
309
- if (Array.isArray(e) !== Array.isArray(t)) return;
310
- if (n) {
311
- const o = n(e);
312
- const l = n(t);
313
- // Key mismatch detaches: the slot takes the new entity; the old proxy
314
- // keeps its (old) backing and a fresh proxy wraps the new value on read.
315
- if (o !== undefined && l !== undefined && o !== l) return;
316
- }
317
- // Reachability pruning (§6d) is MODE-dependent, both pinned:
318
- // - keyed matching descends only where subscriptions exist at/below (`d`) —
319
- // captured-but-unobserved proxies deliberately detach and go stale
320
- // (recon-snap R18; subscribing is what buys liveness);
321
- // - positional (key: null) pairing preserves slot identity unconditionally
322
- // (recon-snap R8 — the fixed-shape dashboard pattern).
323
- // Projection merges (replace mode) preserve key-matched identity
324
- // UNCONDITIONALLY (proj R6: the slot keeps its proxy without needing a
325
- // subscriber below); plain keyed reconcile detaches unobserved captures
326
- // (recon-snap R18 — staleness is the pinned pruning contract).
327
- if (!l && n !== null && !f.d) return;
328
- applyAdopt(f, t, n, l);
329
- }
330
-
331
- export { reconcileNextState };