@solidjs/signals 2.0.0-beta.17 → 2.0.0-beta.19

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 (69) hide show
  1. package/README.md +4 -3
  2. package/dist/dev.js +2956 -646
  3. package/dist/node.cjs +6396 -3974
  4. package/dist/prod/affects.js +222 -0
  5. package/dist/prod/boundaries.js +568 -0
  6. package/dist/prod/core/action.js +83 -0
  7. package/dist/prod/core/async.js +394 -0
  8. package/dist/prod/core/constants.js +78 -0
  9. package/dist/prod/core/context.js +67 -0
  10. package/dist/prod/core/core.js +772 -0
  11. package/dist/prod/core/dev.js +3 -0
  12. package/dist/prod/core/effect.js +145 -0
  13. package/dist/prod/core/error.js +59 -0
  14. package/dist/prod/core/external.js +98 -0
  15. package/dist/prod/core/graph.js +91 -0
  16. package/dist/prod/core/heap.js +132 -0
  17. package/dist/prod/core/invariants.js +42 -0
  18. package/dist/prod/core/lanes.js +130 -0
  19. package/dist/prod/core/optimistic.js +265 -0
  20. package/dist/prod/core/owner.js +293 -0
  21. package/dist/prod/core/scheduler.js +689 -0
  22. package/dist/prod/core/verdict.js +293 -0
  23. package/dist/prod/index.js +45 -0
  24. package/dist/prod/map.js +264 -0
  25. package/dist/prod/signals.js +389 -0
  26. package/dist/prod/store/optimistic.js +149 -0
  27. package/dist/prod/store/projection.js +184 -0
  28. package/dist/prod/store/reconcile.js +392 -0
  29. package/dist/prod/store/store.js +739 -0
  30. package/dist/prod/store/storePath.js +103 -0
  31. package/dist/prod/store/utils.js +297 -0
  32. package/dist/types/affects.d.ts +47 -0
  33. package/dist/types/boundaries.d.ts +8 -8
  34. package/dist/types/core/async.d.ts +5 -2
  35. package/dist/types/core/constants.d.ts +8 -0
  36. package/dist/types/core/core.d.ts +12 -69
  37. package/dist/types/core/dev.d.ts +1 -1
  38. package/dist/types/core/external.d.ts +0 -30
  39. package/dist/types/core/heap.d.ts +8 -0
  40. package/dist/types/core/index.d.ts +3 -2
  41. package/dist/types/core/invariants.d.ts +10 -0
  42. package/dist/types/core/optimistic.d.ts +6 -0
  43. package/dist/types/core/owner.d.ts +8 -0
  44. package/dist/types/core/scheduler.d.ts +53 -5
  45. package/dist/types/core/types.d.ts +22 -5
  46. package/dist/types/core/verdict.d.ts +2 -0
  47. package/dist/types/index.d.ts +1 -0
  48. package/dist/types/store/projection.d.ts +0 -1
  49. package/dist/types/store/store.d.ts +32 -14
  50. package/dist/types-cjs/affects.d.cts +47 -0
  51. package/dist/types-cjs/boundaries.d.cts +8 -8
  52. package/dist/types-cjs/core/async.d.cts +5 -2
  53. package/dist/types-cjs/core/constants.d.cts +8 -0
  54. package/dist/types-cjs/core/core.d.cts +12 -69
  55. package/dist/types-cjs/core/dev.d.cts +1 -1
  56. package/dist/types-cjs/core/external.d.cts +0 -30
  57. package/dist/types-cjs/core/heap.d.cts +8 -0
  58. package/dist/types-cjs/core/index.d.cts +3 -2
  59. package/dist/types-cjs/core/invariants.d.cts +10 -0
  60. package/dist/types-cjs/core/optimistic.d.cts +6 -0
  61. package/dist/types-cjs/core/owner.d.cts +8 -0
  62. package/dist/types-cjs/core/scheduler.d.cts +53 -5
  63. package/dist/types-cjs/core/types.d.cts +22 -5
  64. package/dist/types-cjs/core/verdict.d.cts +2 -0
  65. package/dist/types-cjs/index.d.cts +1 -0
  66. package/dist/types-cjs/store/projection.d.cts +0 -1
  67. package/dist/types-cjs/store/store.d.cts +32 -14
  68. package/package.json +8 -6
  69. package/dist/prod.js +0 -4406
@@ -0,0 +1,222 @@
1
+ import { forEachDependent, notifyStatus, addPendingSource, setPendingError, settlePendingSource } from "./core/async.js";
2
+
3
+ import { $REFRESH, STATUS_PENDING } from "./core/constants.js";
4
+
5
+ import { NotReadyError } from "./core/error.js";
6
+
7
+ import "./core/core.js";
8
+
9
+ import { globalQueue, schedule, GlobalQueue, shiftAffectsMarks } from "./core/scheduler.js";
10
+
11
+ import "./core/verdict.js";
12
+
13
+ import "./core/effect.js";
14
+
15
+ import "./core/invariants.js";
16
+
17
+ import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
18
+
19
+ /**
20
+ * The pending-source identity of a live `affects()` mark on `node` (lazy,
21
+ * one per node, shared by overlapping registrations via the refcount).
22
+ *
23
+ * A mark rides the SAME status rails as real in-flight async — downstream
24
+ * subscribers hold the sentinel in `_pendingSources` — but under its own
25
+ * identity so the two channels can't clear each other:
26
+ * - `_reask` is permanently `false`: a mark is by definition a declared
27
+ * value change, so `quietPending` never silences a window it participates
28
+ * in — even when the mark rides over an otherwise-quiet `refresh()`
29
+ * re-ask of the same node (the whole point of declaring one).
30
+ * - A landing on the marked node settles only the node's OWN source entry;
31
+ * the sentinel entry survives until the mark's transaction releases it.
32
+ * - The sentinel itself never carries `STATUS_PENDING`, so
33
+ * `transitionComplete` never counts a mark as a blocker of its own
34
+ * transaction (release happens AT settle — self-blocking would deadlock),
35
+ * and reads of the marked node never throw (marks are value-transparent
36
+ * at the source; pendingness is what propagates).
37
+ */ function getAffectsSentinel(e) {
38
+ return e.t ??= {
39
+ o: undefined,
40
+ // Brand + backref: lets the scheduler's settlement checks recognize
41
+ // mark-sourced pending (which must never block its own transaction —
42
+ // release happens AT settle).
43
+ l: e,
44
+ u: 0,
45
+ i: 0,
46
+ A: false,
47
+ k: undefined,
48
+ p: null,
49
+ S: null
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Push a live mark's pendingness downstream from the marked node through the
55
+ * normal status rails. Runs on every registration (dedup in `notifyStatus`
56
+ * stops re-descent at already-covered subscribers). Subscribers that
57
+ * recompute mid-window shed this via `clearStatus` and re-acquire it through
58
+ * the read path (`applyAffectsReads` for direct readers of the marked node,
59
+ * `collectMarkSources` transitively) — the mark analogue of real async's
60
+ * re-throw-on-read. Subscribers are deliberately NOT queued as pending nodes
61
+ * (#2893): they hold no value needing a transition-scheduled commit, and
62
+ * queueing would stamp the marking action's transaction onto them — from then
63
+ * on ANY write dirtying one of them (including writes to unmarked signals
64
+ * that merely share a downstream memo) would be captured and frozen until the
65
+ * action settles.
66
+ */ function propagateAffectsMark(e) {
67
+ if (!e.p && !e.G) return;
68
+ const t = getAffectsSentinel(e);
69
+ const r = new NotReadyError(t);
70
+ forEachDependent(e, e => {
71
+ if (e.m !== t && !e.M?.has(t)) {
72
+ notifyStatus(e, STATUS_PENDING, r);
73
+ }
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Re-establish mark pendingness on a computed that read marked sources
79
+ * during its recompute (`clearStatus` at the top of the commit path wiped
80
+ * any sentinel entries it held). Called by `recompute` after the commit —
81
+ * not before, because setting `_error` earlier would make the commit path
82
+ * treat the node as errored and skip the value write.
83
+ */ function applyAffectsReads(e, t) {
84
+ let r = false;
85
+ for (let f = 0; f < t.length; f++) {
86
+ const o = t[f];
87
+ if (!o.P) continue;
88
+ const s = getAffectsSentinel(o);
89
+ if (addPendingSource(e, s)) {
90
+ e.i |= STATUS_PENDING;
91
+ setPendingError(e, s);
92
+ r = true;
93
+ }
94
+ }
95
+ if (r && GlobalQueue._ !== null) GlobalQueue._(e);
96
+ }
97
+
98
+ /**
99
+ * The counting half of a mark, shared by direct registration and store-scope
100
+ * inheritance (a node created inside a live keyless mark's identity scope):
101
+ * bumps the refcount and pokes the node's verdict companions so an
102
+ * already-materialized `false` flips reactively.
103
+ */ function markAffects(e) {
104
+ e.P = (e.P || 0) + 1;
105
+ shiftAffectsMarks(1);
106
+ // Companions only exist once the verdict layer (isPending/latest) loaded;
107
+ // without them there is no materialized verdict to flip.
108
+ if (e.P === 1 && GlobalQueue._ !== null) GlobalQueue._(e);
109
+ }
110
+
111
+ /**
112
+ * Registers one `affects()` mark on a node: counts it, records the
113
+ * registration with the current transaction (after initTransition the queue's
114
+ * array aliases the active transition's, mirroring `_optimisticNodes`), and
115
+ * propagates STATUS_PENDING downstream on the status rails so everything
116
+ * DERIVED from the marked data reads pending too. Propagation runs on every
117
+ * registration (not just the first): subscribers gained since an earlier
118
+ * overlapping registration get covered, and dedup stops re-descent early.
119
+ */ function registerAffectsMark(e) {
120
+ markAffects(e);
121
+ globalQueue.N.push(e);
122
+ propagateAffectsMark(e);
123
+ schedule();
124
+ }
125
+
126
+ /**
127
+ * Releases one registration. When the node's last mark drops, settles the
128
+ * mark's sentinel out of every downstream `_pendingSources` (waking blocked
129
+ * nodes and re-deriving verdicts along the walk). Companion writes go through
130
+ * the settlement snap (committed, not transition-scoped) so releasing a mark
131
+ * can't open a fresh override window that would itself need settlement.
132
+ */ function releaseAffectsMark(e) {
133
+ shiftAffectsMarks(-1);
134
+ e.P--;
135
+ if (!e.P) {
136
+ const t = e.t;
137
+ if (t) settlePendingSource(e, t, true);
138
+ GlobalQueue.R !== null && GlobalQueue.R(e);
139
+ GlobalQueue.T?.(e);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Releases one batch of affects marks (a settling transaction's, or the
145
+ * ambient batch at a plain flush end).
146
+ */ function releaseAffectsMarks(e) {
147
+ for (let t = 0; t < e.length; t++) releaseAffectsMark(e[t]);
148
+ e.length = 0;
149
+ }
150
+
151
+ /**
152
+ * True when a node's pending status comes ONLY from affects() sentinels. A
153
+ * mark is a promise of change, not an absence of value: reads of mark-pended
154
+ * derived nodes stay value-transparent (verdicts report pending; the read
155
+ * path must not suspend). Any real async source among the pending sources
156
+ * keeps normal suspension semantics. Core's read path reaches this through
157
+ * `GlobalQueue._onlyMarkPending`, gated on the `activeAffectsMarks` counter.
158
+ */ function onlyMarkPending(e) {
159
+ const t = e.M;
160
+ if (t) {
161
+ for (const e of t) if (!e.l) return false;
162
+ return true;
163
+ }
164
+ return !!e.m?.l;
165
+ }
166
+
167
+ /**
168
+ * Collect the still-live marked nodes behind a pended owner's sentinel
169
+ * sources into a recompute's `affectsReads`. This is the transitive half of
170
+ * read-path re-establishment (#2893): real async re-establishes at every
171
+ * derivation level because its re-throw on read re-registers the source, but
172
+ * mark-pended reads are value-transparent — without this, pendingness dies on
173
+ * the first mid-window recompute past depth one, and the isPending() probe
174
+ * itself (whose prepare step recomputes retryable NotReady holders) strips
175
+ * the very status it reports on. Reached through
176
+ * `GlobalQueue._collectMarkSources`, gated on `activeAffectsMarks`.
177
+ */ function collectMarkSources(e, t) {
178
+ const r = e.m;
179
+ if (r) {
180
+ const e = r.l;
181
+ if (e && e.P) t.push(e);
182
+ } else if (e.M) {
183
+ for (const r of e.M) {
184
+ const e = r.l;
185
+ if (e && e.P) t.push(e);
186
+ }
187
+ }
188
+ }
189
+
190
+ // Late installation (same pattern as `GlobalQueue._update`): the mark engine
191
+ // lives with the feature so graphs that never declare a mark never ship it.
192
+ // Each call site is gated by state only this module creates (`markedReads`
193
+ // collection under `activeAffectsMarks`, a non-empty `_affectsNodes` batch,
194
+ // a live scope in the store's `affectsScopes`), so the hooks are installed
195
+ // before the first time any of them can fire.
196
+ GlobalQueue.j = applyAffectsReads;
197
+
198
+ GlobalQueue.h = releaseAffectsMarks;
199
+
200
+ GlobalQueue.D = markAffects;
201
+
202
+ GlobalQueue.F = releaseAffectsMark;
203
+
204
+ GlobalQueue.$ = onlyMarkPending;
205
+
206
+ GlobalQueue.I = collectMarkSources;
207
+
208
+ function affects(e, t) {
209
+ const r = e?.[$TARGET];
210
+ if (r) {
211
+ const e = getStoreAffectsNodes(r, t);
212
+ for (let t = 0; t < e.length; t++) registerAffectsMark(e[t]);
213
+ return;
214
+ }
215
+ const f = e?.[$REFRESH];
216
+ if (f) {
217
+ registerAffectsMark(f);
218
+ return;
219
+ }
220
+ }
221
+
222
+ export { affects };