bruh 2.0.0-beta.4 → 2.0.0-beta.5

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/dist/reactive.mjs CHANGED
@@ -1,192 +1,292 @@
1
- import { attempt } from './utils.mjs';
1
+ import { isSameValueZero, attempt } from './utils.mjs';
2
2
 
3
- const isReactiveSymbol = /* @__PURE__ */ Symbol.for("bruh reactive");
4
- const isReactive = (x) => (
5
- // @ts-ignore
6
- x?.[isReactiveSymbol] === true
7
- );
8
- class SimpleReactive {
9
- [isReactiveSymbol] = true;
3
+ let currentObserver;
4
+ const observerStack = [];
5
+ const pushObserver = (next) => {
6
+ observerStack.push(currentObserver);
7
+ currentObserver = next;
8
+ };
9
+ const popObserver = () => {
10
+ currentObserver = observerStack.pop();
11
+ };
12
+ const trackWith = (observer, f) => {
13
+ pushObserver(observer);
14
+ try {
15
+ return f();
16
+ } finally {
17
+ popObserver();
18
+ }
19
+ };
20
+ const untrack = (f) => {
21
+ return trackWith(void 0, f);
22
+ };
23
+ const dirtyEffects = /* @__PURE__ */ new Set();
24
+ let isFlushScheduled = false;
25
+ let isFlushing = false;
26
+ const scheduleFlush = () => {
27
+ if (isFlushScheduled || isFlushing)
28
+ return;
29
+ isFlushScheduled = true;
30
+ queueMicrotask(flush);
31
+ };
32
+ const flush = () => {
33
+ if (isFlushing)
34
+ return;
35
+ isFlushing = true;
36
+ isFlushScheduled = false;
37
+ try {
38
+ while (dirtyEffects.size) {
39
+ const wave = [...dirtyEffects];
40
+ dirtyEffects.clear();
41
+ for (const effect of wave)
42
+ if (!effect.isDisposed)
43
+ effect.run();
44
+ }
45
+ } finally {
46
+ isFlushing = false;
47
+ }
48
+ };
49
+ class Reactive {
50
+ static get context() {
51
+ return {
52
+ isTracking: currentObserver !== void 0,
53
+ dependencies: currentObserver ? [...currentObserver.dependencies] : [],
54
+ stackDepth: observerStack.length
55
+ };
56
+ }
10
57
  #value;
11
- #reactions = /* @__PURE__ */ new Set();
12
- constructor(value) {
13
- this.#value = value;
58
+ #getter;
59
+ #memoKey;
60
+ #lastMemoKey;
61
+ #isEqual = isSameValueZero;
62
+ #dependencies = /* @__PURE__ */ new Set();
63
+ #observers = /* @__PURE__ */ new Set();
64
+ #isDirty = false;
65
+ #isComputing = false;
66
+ #ownObserver;
67
+ constructor(options) {
68
+ this.#ownObserver = {
69
+ dependencies: this.#dependencies,
70
+ isDisposed: false,
71
+ weakRef: void 0,
72
+ markDirty: () => {
73
+ if (this.#isDirty)
74
+ return;
75
+ this.#isDirty = true;
76
+ this.#markObserversDirty();
77
+ }
78
+ };
79
+ this.#ownObserver.weakRef = new WeakRef(this.#ownObserver);
80
+ if ("getter" in options) {
81
+ this.#memoKey = options.memoKey;
82
+ this.#getter = options.getter;
83
+ this.#isDirty = true;
84
+ this.#value = void 0;
85
+ } else {
86
+ this.#value = options.value;
87
+ }
88
+ if (options.isEqual)
89
+ this.#isEqual = options.isEqual;
14
90
  }
15
- get value() {
91
+ static source(value, options) {
92
+ return new Reactive({
93
+ value,
94
+ isEqual: options?.isEqual
95
+ });
96
+ }
97
+ static derived(getter, options) {
98
+ const result = new Reactive({
99
+ getter,
100
+ memoKey: options?.memoKey,
101
+ isEqual: options?.isEqual
102
+ });
103
+ result.#compute();
104
+ return result;
105
+ }
106
+ peek() {
107
+ if (this.#isDirty)
108
+ this.#compute();
16
109
  return this.#value;
17
110
  }
18
- set value(newValue) {
19
- if (newValue === this.#value)
111
+ get value() {
112
+ this.#trackAccess();
113
+ return this.peek();
114
+ }
115
+ set value(next) {
116
+ if (this.#getter)
117
+ throw new Error("Reactive value is readonly");
118
+ if (this.#isEqual(this.#value, next))
20
119
  return;
21
- this.#value = newValue;
22
- for (const reaction of this.#reactions)
23
- attempt(reaction);
120
+ this.#value = next;
121
+ this.#markObserversDirty();
24
122
  }
25
123
  /**
26
- * @param reaction called every time that the value changes
27
- * @returns a function that stops the reactions
124
+ * @internal
28
125
  */
29
- addReaction(reaction) {
30
- this.#reactions.add(reaction);
31
- return () => this.#reactions.delete(reaction);
126
+ removeObserver(observer) {
127
+ this.#observers.delete(observer.weakRef);
32
128
  }
33
- }
34
- class FunctionalReactive {
35
- [isReactiveSymbol] = true;
36
- #weakRef = new WeakRef(this);
37
- // @ts-ignore
38
- #value;
39
- #reactions = /* @__PURE__ */ new Set();
40
- // For derived nodes, this is the derivation function
41
- // @ts-ignore
42
- #f;
43
- isEqual;
44
- // Source nodes are 0 deep in the derivation graph
45
- // This is for topological sort
46
- #depth = 0;
47
- // All nodes have a set of derivatives that update when the node changes
48
- #derivatives = /* @__PURE__ */ new Set();
49
- // Keep track of all the pending changes from the value setter
50
- static #settersQueue = /* @__PURE__ */ new Map();
51
- // A queue of derivatives to potentially update, sorted into sets by depth
52
- // This starts with depth 1 and can potentially have holes
53
- static #derivativesQueue = [];
54
- // A queue of reactions to run after the graph is fully updated
55
- static #reactionsQueue = [];
56
- constructor(xOrDependencies, optionsOrF, options) {
57
- if (typeof optionsOrF !== "function") {
58
- const this_2 = this;
59
- const value = xOrDependencies;
60
- const options2 = optionsOrF;
61
- this_2.#value = value;
62
- this_2.isEqual = options2?.isEqual;
129
+ #trackAccess() {
130
+ if (!currentObserver)
63
131
  return;
132
+ this.#observers.add(currentObserver.weakRef);
133
+ currentObserver.dependencies.add(this);
134
+ }
135
+ #markObserversDirty() {
136
+ for (const ref of this.#observers) {
137
+ const observer = ref.deref();
138
+ if (observer)
139
+ observer.markDirty();
140
+ else
141
+ this.#observers.delete(ref);
64
142
  }
65
- const this_ = this;
66
- const dependencies = xOrDependencies;
67
- const f = optionsOrF;
68
- this_.#value = attempt(f);
69
- this_.#f = f;
70
- this_.isEqual = options?.isEqual;
71
- this_.#depth = Math.max(0, ...dependencies.map((dependency) => dependency.#depth)) + 1;
72
- dependencies.forEach((dependency) => dependency.#derivatives.add(this_.#weakRef));
73
143
  }
74
- get value() {
75
- if (FunctionalReactive.#settersQueue.size) {
76
- if (this.#depth === 0) {
77
- const this_ = this;
78
- if (FunctionalReactive.#settersQueue.has(this_))
79
- return FunctionalReactive.#settersQueue.get(this_);
80
- } else {
81
- FunctionalReactive.applyUpdates();
144
+ #clearDependencies() {
145
+ for (const dependency of this.#dependencies)
146
+ dependency.removeObserver(this.#ownObserver);
147
+ this.#dependencies.clear();
148
+ }
149
+ #compute() {
150
+ if (!this.#getter || !this.#isDirty)
151
+ return;
152
+ if (this.#isComputing)
153
+ throw new Error("Cycle detected while computing derivation");
154
+ this.#isComputing = true;
155
+ this.#isDirty = false;
156
+ this.#clearDependencies();
157
+ try {
158
+ if (this.#memoKey) {
159
+ const key = trackWith(this.#ownObserver, this.#memoKey);
160
+ if (isSameValueZero(key, this.#lastMemoKey))
161
+ return;
162
+ this.#lastMemoKey = key;
82
163
  }
164
+ const next = trackWith(this.#ownObserver, this.#getter);
165
+ const changed = !this.#isEqual(this.#value, next);
166
+ if (changed)
167
+ this.#value = next;
168
+ } catch (e) {
169
+ console.error(e);
170
+ } finally {
171
+ this.#isComputing = false;
83
172
  }
84
- return this.#value;
85
173
  }
86
- set value(newValue) {
87
- if (this.#depth !== 0)
88
- return;
89
- const this_ = this;
90
- const isEqual = this.isEqual ? this.isEqual(newValue, this.#value) : newValue === this.#value;
91
- if (isEqual) {
92
- FunctionalReactive.#settersQueue.delete(this_);
174
+ }
175
+ const activeEffects = /* @__PURE__ */ new Set();
176
+ class Effect {
177
+ weakRef = new WeakRef(this);
178
+ dependencies = /* @__PURE__ */ new Set();
179
+ isDisposed = false;
180
+ #f;
181
+ #cleanup;
182
+ constructor(f) {
183
+ this.#f = f;
184
+ activeEffects.add(this);
185
+ this.markDirty();
186
+ }
187
+ markDirty() {
188
+ if (this.isDisposed)
93
189
  return;
94
- }
95
- if (!FunctionalReactive.#settersQueue.size)
96
- queueMicrotask(FunctionalReactive.applyUpdates);
97
- FunctionalReactive.#settersQueue.set(this_, newValue);
190
+ dirtyEffects.add(this);
191
+ scheduleFlush();
98
192
  }
99
- /**
100
- * @param reaction called every time that the value changes
101
- * @returns a function that stops the reactions
102
- */
103
- addReaction(reaction) {
104
- this.#reactions.add(reaction);
105
- return () => this.#reactions.delete(reaction);
106
- }
107
- // Apply an update for a node and queue its derivatives if it actually changed
108
- #applyUpdate(newValue) {
109
- const isEqual = this.isEqual ? this.isEqual(newValue, this.#value) : newValue === this.#value;
110
- if (isEqual)
193
+ run() {
194
+ if (this.isDisposed)
111
195
  return;
112
- this.#value = newValue;
113
- FunctionalReactive.#reactionsQueue.push(...this.#reactions);
114
- this.#derivatives.forEach((weakRef) => {
115
- const derivative = weakRef.deref();
116
- if (!derivative) {
117
- this.#derivatives.delete(weakRef);
118
- return;
119
- }
120
- const depthSet = FunctionalReactive.#derivativesQueue[derivative.#depth] ??= /* @__PURE__ */ new Set();
121
- depthSet.add(derivative);
122
- });
196
+ if (this.#cleanup) {
197
+ attempt(this.#cleanup);
198
+ this.#cleanup = void 0;
199
+ }
200
+ for (const dependency of this.dependencies)
201
+ dependency.removeObserver(this);
202
+ this.dependencies.clear();
203
+ const result = trackWith(this, () => attempt(this.#f));
204
+ if (typeof result === "function")
205
+ this.#cleanup = result;
123
206
  }
124
- /**
125
- * Apply pending updates from actually changed source nodes
126
- */
127
- static applyUpdates() {
128
- if (!FunctionalReactive.#settersQueue.size)
207
+ dispose() {
208
+ if (this.isDisposed)
129
209
  return;
130
- for (const [sourceNode, newValue] of FunctionalReactive.#settersQueue.entries())
131
- sourceNode.#applyUpdate(newValue);
132
- FunctionalReactive.#settersQueue.clear();
133
- for (const depthSet of FunctionalReactive.#derivativesQueue) if (depthSet)
134
- for (const derivative of depthSet)
135
- derivative.#applyUpdate(
136
- attempt(
137
- () => derivative.#f()
138
- )
139
- );
140
- FunctionalReactive.#derivativesQueue.length = 0;
141
- for (const reaction of FunctionalReactive.#reactionsQueue)
142
- attempt(reaction);
143
- FunctionalReactive.#reactionsQueue.length = 0;
210
+ this.isDisposed = true;
211
+ activeEffects.delete(this);
212
+ dirtyEffects.delete(this);
213
+ if (this.#cleanup)
214
+ attempt(this.#cleanup);
215
+ for (const dependency of this.dependencies)
216
+ dependency.removeObserver(this);
217
+ this.dependencies.clear();
144
218
  }
145
219
  }
146
- const r = (xOrDependencies, optionsOrF, options) => (
147
- // @ts-ignore
148
- new FunctionalReactive(xOrDependencies, optionsOrF, options)
149
- );
150
- const reactiveDo = (x, f) => {
151
- if (isReactive(x)) {
152
- f(x.value);
153
- return x.addReaction(() => f(x.value));
220
+ const watch = (fOrDependencies, fOrOptions, options) => {
221
+ if (typeof fOrDependencies === "function" && (fOrOptions === void 0 || typeof fOrOptions !== "function")) {
222
+ const f2 = fOrDependencies;
223
+ const effect2 = new Effect(f2);
224
+ return () => {
225
+ effect2.dispose();
226
+ };
154
227
  }
155
- f(x);
156
- };
157
- const flat = (source) => {
158
- const chain = [];
159
- const reactive = new FunctionalReactive(void 0);
160
- const reaction = () => {
161
- let lastInCommon = source;
162
- let i = 0;
163
- while (lastInCommon.value === chain[i + 1]?.reactive) {
164
- lastInCommon = lastInCommon.value;
165
- i++;
166
- }
167
- if (i + 1 < chain.length) {
168
- for (let j = i + 1; j < chain.length; j++)
169
- chain[j].stopReacting();
170
- chain.length = i;
228
+ const dependenciesOrGet = fOrDependencies;
229
+ const f = fOrOptions;
230
+ let isFirst = true;
231
+ const effect = new Effect(() => {
232
+ const dependencies = typeof dependenciesOrGet === "function" ? untrack(dependenciesOrGet) : dependenciesOrGet;
233
+ for (const dependency of dependencies)
234
+ dependency.value;
235
+ if (isFirst) {
236
+ isFirst = false;
237
+ if (options?.skipFirst)
238
+ return;
171
239
  }
172
- updateChain(lastInCommon.value);
240
+ return untrack(f);
241
+ });
242
+ return () => {
243
+ effect.dispose();
173
244
  };
174
- const updateChain = (newStart) => {
175
- while (isReactive(newStart)) {
176
- chain.push({
177
- reactive: newStart,
178
- stopReacting: newStart.addReaction(reaction)
179
- });
180
- newStart = newStart.value;
245
+ };
246
+ const r = (xOrFOrDependencies, optionsOrF, options) => {
247
+ const isExplicit = (Array.isArray(xOrFOrDependencies) || typeof xOrFOrDependencies === "function") && typeof optionsOrF === "function";
248
+ if (isExplicit) {
249
+ const dependenciesOrGet = xOrFOrDependencies;
250
+ const f = optionsOrF;
251
+ return Reactive.derived(() => {
252
+ const dependencies = typeof dependenciesOrGet === "function" ? untrack(dependenciesOrGet) : dependenciesOrGet;
253
+ for (const dependency of dependencies)
254
+ dependency.value;
255
+ return untrack(f);
256
+ }, options);
257
+ } else {
258
+ const options2 = optionsOrF;
259
+ if (typeof xOrFOrDependencies === "function") {
260
+ const f = xOrFOrDependencies;
261
+ return Reactive.derived(f, options2);
181
262
  }
182
- const innerMost = chain[chain.length - 1].reactive;
183
- reactive.isEqual = innerMost.isEqual;
184
- reactive.value = innerMost.value;
185
- FunctionalReactive.applyUpdates();
186
- };
187
- updateChain(source);
188
- return reactive;
263
+ const x = xOrFOrDependencies;
264
+ return Reactive.source(x, options2);
265
+ }
266
+ };
267
+ const getValue = (x) => x instanceof Reactive ? x.value : x;
268
+ const reactiveDo = (x, f) => {
269
+ if (x instanceof Reactive)
270
+ return watch(() => {
271
+ const value = x.value;
272
+ untrack(() => f(value));
273
+ });
274
+ f(x);
275
+ };
276
+ const flatCache = /* @__PURE__ */ new WeakMap();
277
+ const flat = (nested) => {
278
+ const cached = flatCache.get(nested);
279
+ if (cached)
280
+ return cached;
281
+ const derived = r(() => {
282
+ let cursor = nested.value;
283
+ while (cursor instanceof Reactive)
284
+ cursor = cursor.value;
285
+ return cursor;
286
+ });
287
+ flatCache.set(nested, derived);
288
+ return derived;
189
289
  };
190
290
 
191
- export { FunctionalReactive, SimpleReactive, flat, isReactive, isReactiveSymbol, r, reactiveDo };
291
+ export { Reactive, flat, flush, getValue, r, reactiveDo, untrack, watch };
192
292
  //# sourceMappingURL=reactive.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactive.mjs","sources":["../src/reactive/index.mts"],"sourcesContent":["import { attempt } from \"../utils/index.mts\"\n\nexport const isReactiveSymbol = Symbol.for(\"bruh reactive\")\n\nexport const isReactive = (x: unknown): x is Reactive<unknown> =>\n // @ts-ignore\n x?.[isReactiveSymbol] === true\n\ntype Reaction = () => void\ntype StopReacting = () => void\n\nexport interface Reactive<T> {\n [isReactiveSymbol]: true\n\n value: T\n\n addReaction(reaction: Reaction): StopReacting\n}\n\nexport type Unreactive<T = unknown> = Exclude<T, { [isReactiveSymbol]: true }>\n\nexport type MaybeReactive<T> = Reactive<T> | Unreactive<T>\n\nexport type NestedReactive<T extends Unreactive> = Reactive<T | NestedReactive<T>>\n\n/**\n * A super simple and performant reactive value implementation\n */\nexport class SimpleReactive<T> implements Reactive<T> {\n [isReactiveSymbol] = true as const\n\n #value: T\n #reactions = new Set<Reaction>()\n\n constructor(value: T) {\n this.#value = value\n }\n\n get value() {\n return this.#value\n }\n\n set value(newValue) {\n if (newValue === this.#value)\n return\n\n this.#value = newValue\n for (const reaction of this.#reactions)\n attempt(reaction)\n }\n\n /**\n * @param reaction called every time that the value changes\n * @returns a function that stops the reactions\n */\n addReaction(reaction: Reaction) {\n this.#reactions.add(reaction)\n\n return () =>\n this.#reactions.delete(reaction)\n }\n}\n\nexport type IsEqual<T> = {\n bivarianceHack(a: T, b: T): boolean\n}[\"bivarianceHack\"]\n\nexport type ReactiveOptions<T> = {\n isEqual?: IsEqual<T>\n}\n\nexport type SourceNode<T> = FunctionalReactive<T, \"source\">\nexport type DerivativeNode<T> = FunctionalReactive<T, \"derivative\">\n\n/**\n * A reactive implementation for building functional reactive graphs.\n * Ensures state consistency, minimal node updates, and transparent update batching.\n */\nexport class FunctionalReactive<T, U extends \"source\" | \"derivative\" = any> implements Reactive<T> {\n [isReactiveSymbol] = true as const\n\n #weakRef = new WeakRef(this)\n\n // @ts-ignore\n #value: T\n #reactions = new Set<Reaction>()\n\n // For derived nodes, this is the derivation function\n // @ts-ignore\n #f:\n U extends \"derivative\"\n ? () => T\n : never\n\n isEqual?: IsEqual<T>\n\n // Source nodes are 0 deep in the derivation graph\n // This is for topological sort\n #depth:\n U extends \"source\"\n ? 0\n : number // natural, > 0\n = 0\n\n // All nodes have a set of derivatives that update when the node changes\n #derivatives = new Set<WeakRef<DerivativeNode<unknown>>>()\n\n // Keep track of all the pending changes from the value setter\n static #settersQueue = new Map<SourceNode<unknown>, unknown>()\n\n // A queue of derivatives to potentially update, sorted into sets by depth\n // This starts with depth 1 and can potentially have holes\n static #derivativesQueue: Array<Set<DerivativeNode<unknown>> | undefined> = []\n\n // A queue of reactions to run after the graph is fully updated\n static #reactionsQueue: Array<Reaction> = []\n\n constructor(value: T, options?: ReactiveOptions<T>)\n constructor(\n dependencies: ReadonlyArray<FunctionalReactive<unknown>>,\n f: () => T,\n options?: ReactiveOptions<T>\n )\n constructor(\n xOrDependencies: T | ReadonlyArray<FunctionalReactive<unknown>>,\n optionsOrF?: ReactiveOptions<T> | (() => T),\n options?: ReactiveOptions<T>\n ) {\n // No derivation function means this is a source node\n if (typeof optionsOrF !== \"function\") {\n const this_ = this as SourceNode<T>\n const value = xOrDependencies as T\n const options = optionsOrF as ReactiveOptions<T> | undefined\n\n this_.#value = value\n this_.isEqual = options?.isEqual\n return\n }\n\n // Derived node\n const this_ = this as DerivativeNode<T>\n const dependencies = xOrDependencies as ReadonlyArray<FunctionalReactive<unknown>>\n const f = optionsOrF as () => T\n\n this_.#value = attempt(f)\n this_.#f = f\n this_.isEqual = options?.isEqual\n\n this_.#depth = Math.max(0, ...dependencies.map(dependency => dependency.#depth)) + 1\n\n dependencies.forEach(dependency => dependency.#derivatives.add(this_.#weakRef))\n }\n\n get value(): T {\n // If there are any pending updates\n if (FunctionalReactive.#settersQueue.size) {\n // If this is a source node that was updated, just return that\n // new value without actually updating any derived nodes yet\n if (this.#depth === 0) {\n const this_ = this as SourceNode<T>\n if (FunctionalReactive.#settersQueue.has(this_))\n return FunctionalReactive.#settersQueue.get(this_) as T\n }\n // Heuristic quick invalidation for derived nodes\n // Apply updates now, it's ok that there's already a microtask queued for this\n else {\n FunctionalReactive.applyUpdates()\n }\n }\n\n return this.#value\n }\n\n set value(newValue) {\n // Only allow source nodes to be directly updated\n if (this.#depth !== 0)\n return\n\n const this_ = this as SourceNode<T>\n\n const isEqual = this.isEqual\n ? this.isEqual(newValue, this.#value)\n : newValue === this.#value\n\n if (isEqual) {\n FunctionalReactive.#settersQueue.delete(this_)\n return\n }\n\n // Unless asked for earlier, these updates are just queued up until the microtasks run\n if (!FunctionalReactive.#settersQueue.size)\n queueMicrotask(FunctionalReactive.applyUpdates)\n\n FunctionalReactive.#settersQueue.set(this_, newValue)\n }\n\n /**\n * @param reaction called every time that the value changes\n * @returns a function that stops the reactions\n */\n addReaction(reaction: Reaction) {\n this.#reactions.add(reaction)\n\n return () =>\n this.#reactions.delete(reaction)\n }\n\n // Apply an update for a node and queue its derivatives if it actually changed\n #applyUpdate(newValue: T) {\n const isEqual = this.isEqual\n ? this.isEqual(newValue, this.#value)\n : newValue === this.#value\n\n if (isEqual)\n return\n\n this.#value = newValue\n FunctionalReactive.#reactionsQueue.push(...this.#reactions)\n\n this.#derivatives.forEach(weakRef => {\n const derivative = weakRef.deref()\n if (!derivative) {\n this.#derivatives.delete(weakRef)\n return\n }\n\n const depthSet = FunctionalReactive.#derivativesQueue[derivative.#depth] ??= new Set()\n depthSet.add(derivative)\n })\n }\n\n /**\n * Apply pending updates from actually changed source nodes\n */\n static applyUpdates() {\n if (!FunctionalReactive.#settersQueue.size)\n return\n\n // Bootstrap by applying the updates from the pending setters\n for (const [sourceNode, newValue] of FunctionalReactive.#settersQueue.entries())\n sourceNode.#applyUpdate(newValue)\n FunctionalReactive.#settersQueue.clear()\n\n // Iterate down the depths, ignoring holes\n // Note that both the queue (Array) and each depth Set iterators update as items are added\n for (const depthSet of FunctionalReactive.#derivativesQueue) if (depthSet)\n for (const derivative of depthSet)\n derivative.#applyUpdate(\n attempt(() =>\n derivative.#f()\n )\n )\n\n FunctionalReactive.#derivativesQueue.length = 0\n\n // Call all reactions now that the graph has a fully consistent state\n for (const reaction of FunctionalReactive.#reactionsQueue)\n attempt(reaction)\n FunctionalReactive.#reactionsQueue.length = 0\n }\n}\n\ntype R = {\n /**\n * An initially undefined source node\n */\n <T>(): SourceNode<T | undefined>\n\n /**\n * A source node\n */\n <T>(value: T, options?: ReactiveOptions<T>): SourceNode<T>\n\n /**\n * A derived node\n */\n <T>(\n dependencies: ReadonlyArray<FunctionalReactive<unknown>>,\n f: () => T,\n options?: ReactiveOptions<T>\n ): DerivativeNode<T>\n}\n/**\n * A convenient wrapper for FunctionalReactive\n */\nexport const r: R = <T extends unknown>(\n xOrDependencies?: T | ReadonlyArray<FunctionalReactive<unknown>>,\n optionsOrF?: ReactiveOptions<T> | (() => T),\n options?: ReactiveOptions<T>\n) =>\n // @ts-ignore\n new FunctionalReactive(xOrDependencies, optionsOrF, options)\n\ntype ReactiveDo = {\n /**\n * Calls the given function with the reactive's value whenever it changes\n * @returns a function that stops the reactions\n */\n <T>(\n reactive: Reactive<T>,\n f: (value: T) => unknown\n ): StopReacting\n\n /**\n * Calls the given function with the value once\n */\n <T>(\n value: Unreactive<T>,\n f: (value: Unreactive<T>) => unknown\n ): undefined\n\n /**\n * If the value is not reactive, it calls the given function with that value once.\n * If it is a reactive value, it calls the given function with the reactive's value whenever it changes.\n * @returns a function that stops the reactions, if the value is reactive\n */\n <T>(\n x: MaybeReactive<T>,\n f: (value: T) => unknown\n ): StopReacting | undefined\n}\n/**\n * Do something with a value, updating if it is reactive\n */\nexport const reactiveDo: ReactiveDo = <T extends unknown>(\n x: MaybeReactive<T>,\n f: (value: T) => unknown\n): any => {\n if (isReactive(x)) {\n f(x.value)\n return x.addReaction(() => f(x.value))\n }\n\n f(x)\n}\n\nexport const flat = <T extends Unreactive>(source: NestedReactive<T>): FunctionalReactive<T> => {\n const chain: Array<{\n reactive: NestedReactive<T>,\n stopReacting: StopReacting\n }> = []\n\n const reactive = new FunctionalReactive<T>(undefined as T)\n\n const reaction = () => {\n let lastInCommon: NestedReactive<T> = source\n let i = 0\n while (lastInCommon.value === chain[i + 1]?.reactive) {\n lastInCommon = lastInCommon.value as NestedReactive<T>\n i++\n }\n\n if (i + 1 < chain.length) {\n for (let j = i + 1; j < chain.length; j++)\n chain[j].stopReacting()\n\n chain.length = i\n }\n\n updateChain(lastInCommon.value)\n }\n\n const updateChain = (newStart: T | NestedReactive<T>) => {\n while (isReactive(newStart)) {\n chain.push({\n reactive: newStart,\n stopReacting: newStart.addReaction(reaction)\n })\n newStart = newStart.value\n }\n\n const innerMost = chain[chain.length - 1].reactive as Reactive<T>\n reactive.isEqual = (innerMost as FunctionalReactive<T>).isEqual\n reactive.value = innerMost.value\n FunctionalReactive.applyUpdates()\n }\n\n updateChain(source)\n\n return reactive\n}\n"],"names":["this_","options"],"mappings":"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"}
1
+ {"version":3,"file":"reactive.mjs","sources":["../src/reactive/index.mts"],"sourcesContent":["import { attempt, isSameValueZero } from \"../utils/index.mts\"\n\ninterface Observer {\n weakRef: WeakRef<Observer>,\n dependencies: Set<Reactive<unknown>>,\n isDisposed: boolean,\n markDirty: () => void\n}\n\nlet currentObserver: Observer | undefined\nconst observerStack: (Observer | undefined)[] = []\n\nconst pushObserver = (next: Observer | undefined) => {\n observerStack.push(currentObserver)\n currentObserver = next\n}\n\nconst popObserver = () => {\n currentObserver = observerStack.pop()\n}\n\nconst trackWith = <T extends unknown>(observer: Observer | undefined, f: () => T): T => {\n pushObserver(observer)\n try {\n return f()\n }\n finally {\n popObserver()\n }\n}\n\nexport const untrack = <T extends unknown>(f: () => T): T => {\n return trackWith(undefined, f)\n}\n\nconst dirtyEffects = new Set<Effect>()\nlet isFlushScheduled = false\nlet isFlushing = false\n\nconst scheduleFlush = () => {\n if (isFlushScheduled || isFlushing)\n return\n\n isFlushScheduled = true\n queueMicrotask(flush)\n}\n\nexport const flush = () => {\n if (isFlushing)\n return\n\n isFlushing = true\n isFlushScheduled = false\n\n try {\n while (dirtyEffects.size) {\n const wave = [...dirtyEffects]\n dirtyEffects.clear()\n for (const effect of wave)\n if (!effect.isDisposed)\n effect.run()\n }\n }\n finally {\n isFlushing = false\n }\n}\n\ntype StopReacting = () => void\n\nexport type NonReactive<T = unknown> = T extends Reactive<any> ? never : T\n\nexport type MaybeReactive<T> = Reactive<T> | NonReactive<T>\n\nexport type NestedReactive<T extends NonReactive> = Reactive<T | NestedReactive<T>>\n\nexport type IsEqual<T> = {\n bivarianceHack(a: T, b: T): boolean\n}[\"bivarianceHack\"]\n\nexport type SourceOptions<T> = {\n isEqual?: IsEqual<T>\n}\n\nexport type DerivativeOptions<T> = {\n memoKey?: () => unknown,\n isEqual?: IsEqual<T>\n}\n\nexport type ReadonlyReactive<T> = {\n readonly value: T,\n peek(): T\n}\n\nexport type WritableReactive<T> = {\n value: T,\n peek(): T\n}\n\nexport type SourceNode<T> = Reactive<T> & WritableReactive<T>\nexport type DerivativeNode<T> = Reactive<T> & ReadonlyReactive<T>\n\nexport type ReactiveContext = {\n readonly isTracking: boolean,\n readonly dependencies: ReadonlyArray<Reactive<unknown>>,\n readonly stackDepth: number\n}\n\nexport class Reactive<T> {\n static get context(): ReactiveContext {\n return {\n isTracking: currentObserver !== undefined,\n dependencies: currentObserver ? [...currentObserver.dependencies] : [],\n stackDepth: observerStack.length\n }\n }\n\n #value: T\n #getter?: () => T\n #memoKey?: () => unknown\n #lastMemoKey?: unknown\n #isEqual: IsEqual<T> = isSameValueZero\n #dependencies = new Set<Reactive<unknown>>()\n #observers = new Set<WeakRef<Observer>>()\n #isDirty = false\n #isComputing = false\n\n #ownObserver: Observer\n\n private constructor(\n options: (\n {\n value: T\n } |\n {\n memoKey?: () => unknown,\n getter: () => T\n }\n ) & {\n isEqual?: IsEqual<T>\n }\n ) {\n this.#ownObserver = {\n dependencies: this.#dependencies,\n isDisposed: false,\n weakRef: undefined!,\n markDirty: () => {\n if (this.#isDirty)\n return\n\n this.#isDirty = true\n this.#markObserversDirty()\n }\n }\n this.#ownObserver.weakRef = new WeakRef(this.#ownObserver)\n\n if (\"getter\" in options) {\n this.#memoKey = options.memoKey\n this.#getter = options.getter\n this.#isDirty = true\n this.#value = undefined as T\n }\n else {\n this.#value = options.value\n }\n\n if (options.isEqual)\n this.#isEqual = options.isEqual\n }\n\n static source<T>(value: T, options?: SourceOptions<T>): SourceNode<T> {\n return new Reactive({\n value,\n isEqual: options?.isEqual\n })\n }\n\n static derived<T>(getter: () => T, options?: DerivativeOptions<T>): DerivativeNode<T> {\n const result = new Reactive({\n getter,\n memoKey: options?.memoKey,\n isEqual: options?.isEqual\n })\n result.#compute()\n return result\n }\n\n peek() {\n if (this.#isDirty)\n this.#compute()\n\n return this.#value\n }\n\n get value() {\n this.#trackAccess()\n\n return this.peek()\n }\n\n set value(next: T) {\n if (this.#getter)\n throw new Error(\"Reactive value is readonly\")\n\n if (this.#isEqual(this.#value, next))\n return\n\n this.#value = next\n this.#markObserversDirty()\n }\n\n /**\n * @internal\n */\n removeObserver(observer: Observer) {\n this.#observers.delete(observer.weakRef)\n }\n\n #trackAccess() {\n if (!currentObserver)\n return\n\n this.#observers.add(currentObserver.weakRef)\n currentObserver.dependencies.add(this)\n }\n\n #markObserversDirty() {\n for (const ref of this.#observers) {\n const observer = ref.deref()\n if (observer)\n observer.markDirty()\n else\n this.#observers.delete(ref)\n }\n }\n\n #clearDependencies() {\n for (const dependency of this.#dependencies)\n dependency.removeObserver(this.#ownObserver)\n\n this.#dependencies.clear()\n }\n\n #compute() {\n if (!this.#getter || !this.#isDirty)\n return\n\n if (this.#isComputing)\n throw new Error(\"Cycle detected while computing derivation\")\n\n this.#isComputing = true\n this.#isDirty = false\n this.#clearDependencies()\n\n try {\n if (this.#memoKey) {\n const key = trackWith(this.#ownObserver, this.#memoKey)\n if (isSameValueZero(key, this.#lastMemoKey))\n return\n this.#lastMemoKey = key\n }\n\n const next = trackWith(this.#ownObserver, this.#getter)\n const changed = !this.#isEqual(this.#value, next)\n if (changed)\n this.#value = next\n }\n catch (e) {\n console.error(e)\n }\n finally {\n this.#isComputing = false\n }\n }\n}\n\ntype Cleanup = () => void\n\nconst activeEffects = new Set<Effect>()\n\nclass Effect implements Observer {\n weakRef = new WeakRef(this)\n dependencies = new Set<Reactive<unknown>>()\n isDisposed = false\n\n #f: () => void | Cleanup\n #cleanup?: () => void\n\n constructor(f: () => void | Cleanup) {\n this.#f = f\n\n activeEffects.add(this)\n\n this.markDirty()\n }\n\n markDirty() {\n if (this.isDisposed)\n return\n\n dirtyEffects.add(this)\n scheduleFlush()\n }\n\n run() {\n if (this.isDisposed)\n return\n\n if (this.#cleanup) {\n attempt(this.#cleanup)\n this.#cleanup = undefined\n }\n\n for (const dependency of this.dependencies)\n dependency.removeObserver(this)\n this.dependencies.clear()\n\n const result = trackWith(this, () => attempt(this.#f))\n if (typeof result === \"function\")\n this.#cleanup = result\n }\n\n dispose() {\n if (this.isDisposed)\n return\n\n this.isDisposed = true\n\n activeEffects.delete(this)\n\n dirtyEffects.delete(this)\n\n if (this.#cleanup)\n attempt(this.#cleanup)\n\n for (const dependency of this.dependencies)\n dependency.removeObserver(this)\n this.dependencies.clear()\n }\n}\n\ntype WatchOptionsAuto = {\n}\n\ntype WatchOptionsExplicit = {\n skipFirst?: boolean\n}\n\ntype Watch = {\n /**\n * Auto-tracking effect: tracks all .value reads in the callback\n */\n (f: () => void | Cleanup, options?: WatchOptionsAuto): StopReacting\n\n /**\n * Explicit dependency effect: tracks only the specified dependencies,\n * runs the callback untracked when any dependency changes\n */\n <Dependencies extends ReadonlyArray<Reactive<unknown>>>(\n dependencies: Dependencies | (() => Dependencies),\n f: () => void | Cleanup,\n options?: WatchOptionsExplicit\n ): StopReacting\n}\n\nexport const watch: Watch = <\n Dependencies extends ReadonlyArray<Reactive<unknown>>\n>(\n fOrDependencies: (() => void | Cleanup) | Dependencies | (() => Dependencies),\n fOrOptions?: (() => void | Cleanup) | WatchOptionsAuto,\n options?: WatchOptionsExplicit\n): StopReacting => {\n // Auto-tracking mode: watch(f) or watch(f, options)\n if (typeof fOrDependencies === \"function\" && (fOrOptions === undefined || typeof fOrOptions !== \"function\")) {\n const f = fOrDependencies as () => void | Cleanup\n const options = fOrOptions\n\n const effect = new Effect(f)\n return () => {\n effect.dispose()\n }\n }\n\n // Explicit dependencies mode: watch(dependencies, f, options?)\n const dependenciesOrGet = fOrDependencies as Dependencies | (() => Dependencies)\n const f = fOrOptions as () => void | Cleanup\n\n let isFirst = true\n const effect = new Effect(() => {\n const dependencies =\n typeof dependenciesOrGet === \"function\"\n ? untrack(dependenciesOrGet)\n : dependenciesOrGet\n for (const dependency of dependencies)\n dependency.value\n\n if (isFirst) {\n isFirst = false\n if (options?.skipFirst)\n return\n }\n\n return untrack(f)\n })\n return () => {\n effect.dispose()\n }\n}\n\ntype R = {\n /**\n * A derived node with auto-tracking\n */\n <T>(\n f: () => T,\n options?: DerivativeOptions<T>\n ): DerivativeNode<T>\n\n /**\n * A derived node with explicit dependencies:\n * tracks only the specified dependencies, runs the getter untracked\n */\n <T, Dependencies extends ReadonlyArray<Reactive<unknown>>>(\n dependencies: Dependencies | (() => Dependencies),\n f: () => T,\n options?: DerivativeOptions<T>\n ): DerivativeNode<T>\n\n /**\n * An initially undefined source node\n */\n <T>(): SourceNode<T | undefined>\n\n /**\n * A source node\n */\n <T>(value: T, options?: SourceOptions<T>): SourceNode<T>\n}\n/**\n * A convenient wrapper for Reactive\n */\nexport const r: R = <T extends unknown, Dependencies extends ReadonlyArray<Reactive<unknown>>>(\n xOrFOrDependencies?: T | (() => T) | Dependencies | (() => Dependencies),\n optionsOrF?: SourceOptions<T> | DerivativeOptions<T> | (() => T),\n options?: DerivativeOptions<T>\n) => {\n // r(dependencies, f) or r(() => dependencies, f) - explicit dependency mode\n const isExplicit =\n (Array.isArray(xOrFOrDependencies) || typeof xOrFOrDependencies === \"function\") &&\n typeof optionsOrF === \"function\"\n\n if (isExplicit) {\n const dependenciesOrGet = xOrFOrDependencies as Dependencies | (() => Dependencies)\n const f = optionsOrF\n\n return Reactive.derived(() => {\n const dependencies =\n typeof dependenciesOrGet === \"function\"\n ? untrack(dependenciesOrGet)\n : dependenciesOrGet\n for (const dependency of dependencies)\n dependency.value\n\n return untrack(f)\n }, options)\n }\n else {\n const options = optionsOrF as SourceOptions<T> | DerivativeOptions<T>\n\n // r(f) - auto-tracking derived\n if (typeof xOrFOrDependencies === \"function\") {\n const f = xOrFOrDependencies as () => T\n\n return Reactive.derived(f, options as DerivativeOptions<T>)\n }\n\n // r() or r(value) - source node\n const x = xOrFOrDependencies as T\n\n return Reactive.source(x, options as SourceOptions<T>)\n }\n}\n\nexport const getValue = <T extends unknown>(x: MaybeReactive<T>) =>\n x instanceof Reactive\n ? x.value\n : x\n\ntype ReactiveDo = {\n /**\n * Calls the given function with the reactive's value whenever it changes\n * @returns a function that stops the reactions\n */\n <T>(\n reactive: Reactive<T>,\n f: (value: T) => unknown\n ): StopReacting\n\n /**\n * Calls the given function with the value once\n */\n <T>(\n value: NonReactive<T>,\n f: (value: NonReactive<T>) => unknown\n ): undefined\n\n /**\n * If the value is not reactive, it calls the given function with that value once.\n * If it is a reactive value, it calls the given function with the reactive's value whenever it changes.\n * @returns a function that stops the reactions, if the value is reactive\n */\n <T>(\n x: MaybeReactive<T>,\n f: (value: T) => unknown\n ): StopReacting | undefined\n}\n/**\n * Do something with a value, updating if it is reactive\n */\nexport const reactiveDo: ReactiveDo = <T extends unknown>(\n x: MaybeReactive<T>,\n f: (value: T) => unknown\n): any => {\n if (x instanceof Reactive)\n return watch(() => {\n const value = x.value\n untrack(() => f(value))\n })\n\n f(x)\n}\n\nconst flatCache = new WeakMap<Reactive<unknown>, Reactive<unknown>>()\n\nexport const flat = <T extends unknown>(nested: NestedReactive<T>): Reactive<T> => {\n const cached = flatCache.get(nested)\n if (cached)\n return cached as Reactive<T>\n\n const derived = r(() => {\n let cursor: unknown = nested.value\n while (cursor instanceof Reactive)\n cursor = cursor.value\n return cursor as T\n })\n\n flatCache.set(nested, derived)\n return derived\n}\n"],"names":["f","effect","options"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { MaybeReactive } from '../reactive/index.mts';
2
+ /**
3
+ * Prefer this over `{items.map()}`; it handles reactive and nonreactive iterables with arbitrary memo keys.
4
+ * Memoization is scoped by [MemoMap, ...scope], so different MemoMaps won't collide even with the same items.
5
+ *
6
+ * ```tsx
7
+ * <MemoMap
8
+ * items={maybeReactiveItems}
9
+ * scope={[maybeReactiveItems]} // Optional: defaults to [items]
10
+ * getKey={item => item} // Optional: defaults to the item itself
11
+ * >
12
+ * {item =>
13
+ * <Item>{item}</Item> // Results are memoized within the scope by the key
14
+ * }
15
+ * </MemoMap>
16
+ * ```
17
+ *
18
+ * If rendering the same items in multiple different views, provide distinct scopes:
19
+ * ```tsx
20
+ * <MemoMap items={users} scope={[UserCard, users]}>{...}</MemoMap>
21
+ * <MemoMap items={users} scope={[UserRow, users]}>{...}</MemoMap>
22
+ * ```
23
+ */
24
+ export declare const MemoMap: <In extends unknown, Out extends unknown>({ items, scope, getKey, children: f }: {
25
+ items: MaybeReactive<Iterable<In>>;
26
+ /**
27
+ * Defaults to [items]
28
+ */
29
+ scope?: ReadonlyArray<unknown>;
30
+ /**
31
+ * Defaults to the item itself
32
+ */
33
+ getKey?: (x: In) => unknown;
34
+ children: (x: In) => Out;
35
+ }) => import('../reactive/index.mts').DerivativeNode<Out[]>;
@@ -0,0 +1 @@
1
+ export {};