@reckona/mreact-reactive-core 0.0.152 → 0.0.154

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.
package/src/tracking.ts CHANGED
@@ -14,25 +14,49 @@ export function trackSource(source: Source): void {
14
14
  return;
15
15
  }
16
16
 
17
- if (source.singleSubscriber === tracker) {
18
- tracker.deps.add(source);
19
- return;
17
+ addSourceSubscriber(source, tracker);
18
+ tracker.deps.add(source);
19
+ }
20
+
21
+ function addSourceSubscriber(source: Source, computation: ReactiveComputation): void {
22
+ const subscribers = source.subscribers;
23
+
24
+ if (subscribers === null) {
25
+ source.subscribers = computation;
26
+ } else if (subscribers instanceof Set) {
27
+ subscribers.add(computation);
28
+ } else if (subscribers !== computation) {
29
+ source.subscribers = new Set([subscribers, computation]);
20
30
  }
31
+ }
21
32
 
22
- const previousSize = source.subscribers.size;
23
- source.subscribers.add(tracker);
24
- tracker.deps.add(source);
33
+ function removeSourceSubscriber(source: Source, computation: ReactiveComputation): boolean {
34
+ const subscribers = source.subscribers;
35
+
36
+ if (subscribers === computation) {
37
+ source.subscribers = null;
38
+ return true;
39
+ }
25
40
 
26
- if (previousSize === 0) {
27
- source.singleSubscriber = tracker;
28
- } else if (source.subscribers.size > 1) {
29
- source.singleSubscriber = undefined;
41
+ if (subscribers instanceof Set && subscribers.delete(computation)) {
42
+ if (subscribers.size === 0) {
43
+ source.subscribers = null;
44
+ }
45
+ return true;
30
46
  }
47
+
48
+ return false;
49
+ }
50
+
51
+ export function sourceSubscriberCount(source: Source): number {
52
+ const subscribers = source.subscribers;
53
+
54
+ return subscribers === null ? 0 : subscribers instanceof Set ? subscribers.size : 1;
31
55
  }
32
56
 
33
57
  export function cleanupDeps(computation: ReactiveComputation): void {
34
58
  for (const dep of computation.deps) {
35
- if (!dep.subscribers.delete(computation)) {
59
+ if (!removeSourceSubscriber(dep, computation)) {
36
60
  continue;
37
61
  }
38
62
 
@@ -40,15 +64,25 @@ export function cleanupDeps(computation: ReactiveComputation): void {
40
64
  dep.trackedBy = undefined;
41
65
  dep.trackedVersion = undefined;
42
66
  }
67
+ }
68
+
69
+ computation.deps.clear();
70
+ }
43
71
 
44
- if (dep.subscribers.size === 0) {
45
- dep.singleSubscriber = undefined;
46
- } else if (dep.subscribers.size === 1) {
47
- dep.singleSubscriber = dep.subscribers.values().next().value;
72
+ export function nextTrackingVersionFor(computation: ReactiveComputation): number {
73
+ const nextTrackingVersion = (computation.trackingVersion ?? 0) + 1;
74
+
75
+ if (Number.isSafeInteger(nextTrackingVersion)) {
76
+ return nextTrackingVersion;
77
+ }
78
+
79
+ for (const dep of computation.deps) {
80
+ if (dep.trackedBy === computation) {
81
+ dep.trackedVersion = undefined;
48
82
  }
49
83
  }
50
84
 
51
- computation.deps.clear();
85
+ return 1;
52
86
  }
53
87
 
54
88
  export function trackIncrementalSource(
@@ -75,16 +109,9 @@ export function trackIncrementalSource(
75
109
  return;
76
110
  }
77
111
 
78
- const previousSize = source.subscribers.size;
79
- source.subscribers.add(computation);
112
+ addSourceSubscriber(source, computation);
80
113
  computation.deps.add(source);
81
114
  computation.trackingAddedDeps?.push(source);
82
-
83
- if (previousSize === 0) {
84
- source.singleSubscriber = computation;
85
- } else if (source.subscribers.size > 1) {
86
- source.singleSubscriber = undefined;
87
- }
88
115
  }
89
116
 
90
117
  export function preserveIncrementalTracking(computation: ReactiveComputation): void {
@@ -122,7 +149,7 @@ export function cleanupUntrackedDeps(
122
149
  continue;
123
150
  }
124
151
 
125
- if (!dep.subscribers.delete(computation)) {
152
+ if (!removeSourceSubscriber(dep, computation)) {
126
153
  continue;
127
154
  }
128
155
 
@@ -132,12 +159,6 @@ export function cleanupUntrackedDeps(
132
159
  }
133
160
 
134
161
  computation.deps.delete(dep);
135
-
136
- if (dep.subscribers.size === 0) {
137
- dep.singleSubscriber = undefined;
138
- } else if (dep.subscribers.size === 1) {
139
- dep.singleSubscriber = dep.subscribers.values().next().value;
140
- }
141
162
  }
142
163
  }
143
164
 
@@ -149,7 +170,7 @@ export function cleanupAddedDeps(computation: ReactiveComputation): void {
149
170
  }
150
171
 
151
172
  for (const dep of addedDeps) {
152
- if (!dep.subscribers.delete(computation)) {
173
+ if (!removeSourceSubscriber(dep, computation)) {
153
174
  continue;
154
175
  }
155
176
 
@@ -159,30 +180,23 @@ export function cleanupAddedDeps(computation: ReactiveComputation): void {
159
180
  }
160
181
 
161
182
  computation.deps.delete(dep);
162
-
163
- if (dep.subscribers.size === 0) {
164
- dep.singleSubscriber = undefined;
165
- } else if (dep.subscribers.size === 1) {
166
- dep.singleSubscriber = dep.subscribers.values().next().value;
167
- }
168
183
  }
169
184
  }
170
185
 
171
186
  export function notifySubscribers(source: Source): void {
172
- if (source.subscribers.size === 0) {
187
+ const subscribers = source.subscribers;
188
+
189
+ if (subscribers === null) {
173
190
  return;
174
191
  }
175
192
 
176
- const cachedSingleSubscriber = source.singleSubscriber;
177
- if (cachedSingleSubscriber !== undefined) {
178
- if (cachedSingleSubscriber.disposed || cachedSingleSubscriber.queued) {
179
- return;
180
- }
181
-
193
+ if (!(subscribers instanceof Set)) {
182
194
  runtimeState.notificationDepth += 1;
183
195
 
184
196
  try {
185
- cachedSingleSubscriber.markDirty();
197
+ if (!subscribers.disposed && !subscribers.queued) {
198
+ subscribers.markDirty();
199
+ }
186
200
  } finally {
187
201
  runtimeState.notificationDepth -= 1;
188
202
 
@@ -197,18 +211,14 @@ export function notifySubscribers(source: Source): void {
197
211
 
198
212
  try {
199
213
  const singleSubscriber =
200
- source.subscribers.size === 1
201
- ? source.subscribers.values().next().value
202
- : undefined;
214
+ subscribers.size === 1 ? subscribers.values().next().value : undefined;
203
215
 
204
216
  if (singleSubscriber !== undefined) {
205
217
  if (!singleSubscriber.disposed && !singleSubscriber.queued) {
206
218
  singleSubscriber.markDirty();
207
219
  }
208
220
  } else {
209
- const subscribers = orderedComputations(source.subscribers);
210
-
211
- for (const subscriber of subscribers) {
221
+ for (const subscriber of orderedComputations(subscribers)) {
212
222
  if (!subscriber.disposed && !subscriber.queued) {
213
223
  subscriber.markDirty();
214
224
  }