@but212/atom-effect 0.10.0 → 0.11.0

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/index.d.ts CHANGED
@@ -14,20 +14,8 @@ export declare type AsyncStateType = (typeof AsyncState)[keyof typeof AsyncState
14
14
  /**
15
15
  * Creates a reactive atom holding mutable state.
16
16
  *
17
- * Atoms are the building blocks of reactive state. When an atom's value changes,
18
- * any effects or computed atoms that depend on it will be automatically re-executed.
19
- *
20
17
  * @param initialValue - The initial value of the atom.
21
- * @param options - Configuration options.
22
- * @param options.sync - If true, notifications are delivered synchronously when the value changes.
23
- * @returns A writable atom object.
24
- *
25
- * @example
26
- * ```ts
27
- * const count = atom(0);
28
- * count.value = 1; // Notifies subscribers
29
- * console.log(count.value); // 1
30
- * ```
18
+ * @param options - Configuration options (sync: boolean).
31
19
  */
32
20
  export declare function atom<T>(initialValue: T, options?: AtomOptions): WritableAtom<T>;
33
21
 
@@ -224,6 +212,14 @@ export declare interface Dependency {
224
212
  /* Excluded from this release type: _tempUnsub */
225
213
  /* Excluded from this release type: _modifiedAtEpoch */
226
214
  /* Excluded from this release type: _visitedEpoch */
215
+ /**
216
+ * Calculates the logical distance (shift) between current and cached version.
217
+ * Used for priority scheduling - large shifts indicate stale updates.
218
+ *
219
+ * @param cachedVersion - The previously cached version
220
+ * @returns Non-negative shift distance (0 to 0x3fffffff)
221
+ */
222
+ getShift(cachedVersion: number): number;
227
223
  /**
228
224
  * Subscribe to dependency updates
229
225
  */
@@ -333,6 +329,14 @@ export declare function isComputed(obj: unknown): obj is ComputedAtom;
333
329
  /** Checks if the given object is an EffectObject. */
334
330
  export declare function isEffect(obj: unknown): obj is EffectObject;
335
331
 
332
+ /**
333
+ * Interface for nodes that support phase-shift priority calculation.
334
+ * Used by Scheduler to determine job urgency.
335
+ */
336
+ declare interface PhaseShiftNode {
337
+ getShift(cachedVersion: number): number;
338
+ }
339
+
336
340
  /**
337
341
  * Object pool configuration
338
342
  * Controls memory management and GC pressure reduction
@@ -366,15 +370,28 @@ export declare interface ReadonlyAtom<T = unknown> {
366
370
  }
367
371
 
368
372
  /**
369
- * Scheduler for reactive updates.
370
- * Manages the execution of effects and computed updates using batching and double-buffering.
371
- * Supports both asynchronous (microtask-based) and synchronous (manual or batch-end) flushing.
373
+ * Scheduler for reactive updates with phase-shift priority scheduling.
374
+ *
375
+ * Features:
376
+ * - Double-buffered queue for efficient processing
377
+ * - Urgent queue for high-priority updates (glitch reduction)
378
+ * - Branchless priority calculation using phase-shift
379
+ * - Batching support for transactional updates
380
+ *
381
+ * Priority Logic:
382
+ * When a job's phase shift exceeds PHASE_THRESHOLD (90° equivalent),
383
+ * it's considered "urgent" and processed before normal jobs.
384
+ * This reduces glitches by prioritizing stale updates.
372
385
  */
373
386
  declare class Scheduler {
374
387
  private queueA;
375
388
  private queueB;
376
389
  private queue;
377
390
  private queueSize;
391
+ private urgentQueueA;
392
+ private urgentQueueB;
393
+ private urgentQueue;
394
+ private urgentQueueSize;
378
395
  private _epoch;
379
396
  private isProcessing;
380
397
  isBatching: boolean;
@@ -385,16 +402,50 @@ declare class Scheduler {
385
402
  private maxFlushIterations;
386
403
  get phase(): SchedulerPhase;
387
404
  /**
388
- * Schedules a task for execution.
389
- * Tasks are deduplicated within the same flush cycle using epoch tracking.
390
- * @param callback - The function to execute.
391
- * @throws {SchedulerError} If the callback is not a function.
405
+ * Schedules a task for execution with optional priority based on phase shift.
406
+ *
407
+ * Priority Calculation (Branchless):
408
+ * - If sourceNode and cachedVersion are provided, calculates shift
409
+ * - Jobs with shift >= PHASE_THRESHOLD go to urgentQueue
410
+ * - Uses branchless bit manipulation: ((shift - THRESHOLD) >>> 31) ^ 1
411
+ *
412
+ * @param callback - The function to execute
413
+ * @param sourceNode - Optional reactive node for shift calculation
414
+ * @throws {SchedulerError} If the callback is not a function
392
415
  */
393
- schedule(callback: SchedulerJob): void;
416
+ schedule(callback: SchedulerJob, sourceNode?: PhaseShiftNode): void;
417
+ /**
418
+ * Calculates urgency flag using branchless bit manipulation.
419
+ *
420
+ * Formula: ((shift - PHASE_THRESHOLD) >>> 31) ^ 1
421
+ * - If shift >= THRESHOLD: (negative >>> 31) = 0, XOR 1 = 1 (urgent)
422
+ * - If shift < THRESHOLD: (positive >>> 31) = 0... wait, that's wrong
423
+ *
424
+ * Correct formula: (shift >= THRESHOLD) ? 1 : 0
425
+ * Branchless: ((PHASE_THRESHOLD - 1 - shift) >>> 31)
426
+ *
427
+ * @returns 1 if urgent, 0 if normal
428
+ */
429
+ private _calculateUrgency;
394
430
  private flush;
395
431
  private flushSync;
396
432
  private _mergeBatchQueue;
433
+ /**
434
+ * Drains all queues, processing urgent queue completely first.
435
+ *
436
+ * Processing Order:
437
+ * 1. Process all urgent jobs (high phase shift = stale updates)
438
+ * 2. Process normal jobs
439
+ * 3. Repeat until both queues are empty
440
+ *
441
+ * This ordering reduces glitches by ensuring that the most
442
+ * impactful state changes are propagated first.
443
+ */
397
444
  private _drainQueue;
445
+ /**
446
+ * Processes the urgent queue using double-buffering.
447
+ */
448
+ private _processUrgentQueue;
398
449
  private _processCurrentQueue;
399
450
  private _handleFlushOverflow;
400
451
  private _processJobs;
@@ -454,9 +505,16 @@ export declare class SchedulerError extends AtomError {
454
505
  constructor(message: string, cause?: Error | null);
455
506
  }
456
507
 
508
+ /**
509
+ * Scheduler job interface with phase-shift tracking support.
510
+ * _cachedVersion enables priority calculation based on staleness.
511
+ */
457
512
  declare interface SchedulerJob {
458
513
  (): void;
514
+ /** Epoch for deduplication */
459
515
  _nextEpoch?: number;
516
+ /** Cached version for phase-shift priority calculation */
517
+ _cachedVersion?: number;
460
518
  }
461
519
 
462
520
  declare enum SchedulerPhase {