@hoosk/minisignals 1.1.0 → 1.1.1

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/README.md CHANGED
@@ -63,4 +63,4 @@ computed-batched-writes-then-read 706.54K ops/s 1.42 µs/op
63
63
 
64
64
  Run `npm run bench` to reproduce locally.
65
65
 
66
- For full documentation and advanced features, please refer to the [main repository README](../../README.md).
66
+ For full documentation and advanced features, please refer to the [main repository README](https://github.com/Hoosk/minisignals#readme).
package/dist/computed.js CHANGED
@@ -1,4 +1,4 @@
1
- import { cleanupSubscriber, createDependencySource, getActiveSubscriber, scheduleSource, trackDependency, trackSubscriber, } from './effect.js';
1
+ import { cleanupSubscriber, createDependencySource, getActiveSubscriber, PENDING, scheduleSource, trackDependency, trackSubscriber, } from './effect.js';
2
2
  /**
3
3
  * Creates a computed signal that derives its value from other signals.
4
4
  * It only calculates and subscribes when its value is read for the first time.
@@ -18,18 +18,18 @@ export function computed(fn) {
18
18
  depsHead: null,
19
19
  depsTail: null,
20
20
  trackId: 0,
21
- pending: false,
21
+ flags: 0,
22
22
  };
23
23
  let initialized = false;
24
24
  let isDisposed = false;
25
25
  let dirty = true;
26
26
  let cachedValue;
27
27
  function refreshValue() {
28
- // Clear pending so a batch flush after an eager read inside the same batch
28
+ // Clear PENDING so a batch flush after an eager read inside the same batch
29
29
  // does not re-trigger notify() on an already-fresh computed.
30
30
  // We do NOT call cleanupSubscriber here: trackSubscriber increments trackId
31
31
  // and pruneStaleDependencies removes only stale links, reusing stable ones.
32
- observer.pending = false;
32
+ observer.flags &= ~PENDING;
33
33
  cachedValue = trackSubscriber(observer, fn);
34
34
  initialized = true;
35
35
  dirty = false;
package/dist/effect.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export declare const PENDING: number;
2
+ export declare const RUNNING: number;
3
+ export declare const NEEDS_RERUN: number;
1
4
  export interface DependencySource {
2
5
  subsHead: DependencyLink | null;
3
6
  currentLink: DependencyLink | null;
@@ -17,7 +20,7 @@ export interface Subscriber {
17
20
  depsHead: DependencyLink | null;
18
21
  depsTail: DependencyLink | null;
19
22
  trackId: number;
20
- pending: boolean;
23
+ flags: number;
21
24
  }
22
25
  declare let _activeSubscriber: Subscriber | null;
23
26
  export { _activeSubscriber };
package/dist/effect.js CHANGED
@@ -1,4 +1,7 @@
1
- // ─── Dependency graph types ───────────────────────────────────────────────────
1
+ // ─── Subscriber flags ───────────────────────────────────────────────────────
2
+ export const PENDING = 1 << 0; // queued in _pendingNotifications
3
+ export const RUNNING = 1 << 1; // effect is currently executing
4
+ export const NEEDS_RERUN = 1 << 2; // dependency changed while RUNNING
2
5
  let _activeSubscriber = null;
3
6
  // Exported so signal.ts can do an inline null-check in the getter hot path,
4
7
  // avoiding a function call when there is no active subscriber.
@@ -120,15 +123,15 @@ export function cleanupSubscriber(subscriber) {
120
123
  unlinkDependency(link);
121
124
  link = next;
122
125
  }
123
- subscriber.pending = false;
126
+ subscriber.flags &= ~PENDING;
124
127
  }
125
128
  // ─── Batch scheduling ────────────────────────────────────────────────────────
126
129
  let _batchDepth = 0;
127
130
  const _pendingNotifications = [];
128
131
  function queueSubscriber(subscriber) {
129
132
  if (_batchDepth > 0) {
130
- if (!subscriber.pending) {
131
- subscriber.pending = true;
133
+ if (!(subscriber.flags & PENDING)) {
134
+ subscriber.flags |= PENDING;
132
135
  _pendingNotifications.push(subscriber);
133
136
  }
134
137
  }
@@ -154,9 +157,9 @@ export function batch(fn) {
154
157
  if (_batchDepth === 0) {
155
158
  const pending = _pendingNotifications.splice(0);
156
159
  for (const sub of pending) {
157
- if (!sub.pending)
160
+ if (!(sub.flags & PENDING))
158
161
  continue;
159
- sub.pending = false;
162
+ sub.flags &= ~PENDING;
160
163
  sub.notify();
161
164
  }
162
165
  }
@@ -183,31 +186,29 @@ const MAX_EFFECT_ITERATIONS = 100;
183
186
  export function effect(fn) {
184
187
  const effectObj = {};
185
188
  effectObj.notify = () => {
186
- if (effectObj.isRunning) {
187
- effectObj.needsRerun = true;
189
+ if (effectObj.flags & RUNNING) {
190
+ effectObj.flags |= NEEDS_RERUN;
188
191
  return;
189
192
  }
190
- effectObj.isRunning = true;
193
+ effectObj.flags |= RUNNING;
191
194
  let iterations = 0;
192
195
  try {
193
196
  do {
194
197
  if (++iterations > MAX_EFFECT_ITERATIONS) {
195
198
  throw new Error('Circular dependency detected: effect exceeded maximum re-run limit');
196
199
  }
197
- effectObj.needsRerun = false;
200
+ effectObj.flags &= ~NEEDS_RERUN;
198
201
  trackSubscriber(effectObj, fn);
199
- } while (effectObj.needsRerun);
202
+ } while (effectObj.flags & NEEDS_RERUN);
200
203
  }
201
204
  finally {
202
- effectObj.isRunning = false;
205
+ effectObj.flags &= ~RUNNING;
203
206
  }
204
207
  };
205
208
  effectObj.depsHead = null;
206
209
  effectObj.depsTail = null;
207
210
  effectObj.trackId = 0;
208
- effectObj.pending = false;
209
- effectObj.isRunning = false;
210
- effectObj.needsRerun = false;
211
+ effectObj.flags = 0;
211
212
  effectObj.notify();
212
213
  return () => cleanupSubscriber(effectObj);
213
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoosk/minisignals",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Minimal agnostic signals library",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test": "vitest run",
23
23
  "bench": "npm run build && node ./bench/core.bench.mjs"
24
24
  },
25
- "keywords": [],
25
+ "keywords": ["signals", "reactive", "reactivity", "state", "computed", "effect", "signal", "observable", "framework-agnostic"],
26
26
  "author": "Hoosk",
27
27
  "license": "MIT"
28
28
  }