signalium 0.2.7 → 0.3.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.
Files changed (152) hide show
  1. package/.turbo/turbo-build.log +12 -0
  2. package/CHANGELOG.md +12 -0
  3. package/dist/cjs/config.d.ts +14 -5
  4. package/dist/cjs/config.d.ts.map +1 -1
  5. package/dist/cjs/config.js +23 -14
  6. package/dist/cjs/config.js.map +1 -1
  7. package/dist/cjs/debug.d.ts +3 -0
  8. package/dist/cjs/debug.d.ts.map +1 -0
  9. package/dist/cjs/debug.js +16 -0
  10. package/dist/cjs/debug.js.map +1 -0
  11. package/dist/cjs/hooks.d.ts +45 -0
  12. package/dist/cjs/hooks.d.ts.map +1 -0
  13. package/dist/cjs/hooks.js +260 -0
  14. package/dist/cjs/hooks.js.map +1 -0
  15. package/dist/cjs/index.d.ts +5 -3
  16. package/dist/cjs/index.d.ts.map +1 -1
  17. package/dist/cjs/index.js +21 -8
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/react/context.d.ts +4 -0
  20. package/dist/cjs/react/context.d.ts.map +1 -0
  21. package/dist/cjs/react/context.js +10 -0
  22. package/dist/cjs/react/context.js.map +1 -0
  23. package/dist/cjs/react/index.d.ts +5 -0
  24. package/dist/cjs/react/index.d.ts.map +1 -0
  25. package/dist/cjs/react/index.js +12 -0
  26. package/dist/cjs/react/index.js.map +1 -0
  27. package/dist/cjs/react/provider.d.ts +7 -0
  28. package/dist/cjs/react/provider.d.ts.map +1 -0
  29. package/dist/cjs/react/provider.js +13 -0
  30. package/dist/cjs/react/provider.js.map +1 -0
  31. package/dist/cjs/react/signal-value.d.ts +3 -0
  32. package/dist/cjs/react/signal-value.d.ts.map +1 -0
  33. package/dist/cjs/react/signal-value.js +42 -0
  34. package/dist/cjs/react/signal-value.js.map +1 -0
  35. package/dist/cjs/react/state.d.ts +3 -0
  36. package/dist/cjs/react/state.d.ts.map +1 -0
  37. package/dist/cjs/react/state.js +13 -0
  38. package/dist/cjs/react/state.js.map +1 -0
  39. package/dist/cjs/scheduling.d.ts +5 -0
  40. package/dist/cjs/scheduling.d.ts.map +1 -1
  41. package/dist/cjs/scheduling.js +59 -5
  42. package/dist/cjs/scheduling.js.map +1 -1
  43. package/dist/cjs/signals.d.ts +28 -65
  44. package/dist/cjs/signals.d.ts.map +1 -1
  45. package/dist/cjs/signals.js +223 -65
  46. package/dist/cjs/signals.js.map +1 -1
  47. package/dist/cjs/trace.d.ts +127 -0
  48. package/dist/cjs/trace.d.ts.map +1 -0
  49. package/dist/cjs/trace.js +319 -0
  50. package/dist/cjs/trace.js.map +1 -0
  51. package/dist/cjs/types.d.ts +66 -0
  52. package/dist/cjs/types.d.ts.map +1 -0
  53. package/dist/cjs/types.js +3 -0
  54. package/dist/cjs/types.js.map +1 -0
  55. package/dist/cjs/utils.d.ts +4 -0
  56. package/dist/cjs/utils.d.ts.map +1 -0
  57. package/dist/cjs/utils.js +80 -0
  58. package/dist/cjs/utils.js.map +1 -0
  59. package/dist/esm/config.d.ts +14 -5
  60. package/dist/esm/config.d.ts.map +1 -1
  61. package/dist/esm/config.js +19 -11
  62. package/dist/esm/config.js.map +1 -1
  63. package/dist/esm/debug.d.ts +3 -0
  64. package/dist/esm/debug.d.ts.map +1 -0
  65. package/dist/esm/debug.js +3 -0
  66. package/dist/esm/debug.js.map +1 -0
  67. package/dist/esm/hooks.d.ts +45 -0
  68. package/dist/esm/hooks.d.ts.map +1 -0
  69. package/dist/esm/hooks.js +243 -0
  70. package/dist/esm/hooks.js.map +1 -0
  71. package/dist/esm/index.d.ts +5 -3
  72. package/dist/esm/index.d.ts.map +1 -1
  73. package/dist/esm/index.js +4 -2
  74. package/dist/esm/index.js.map +1 -1
  75. package/dist/esm/react/context.d.ts +4 -0
  76. package/dist/esm/react/context.d.ts.map +1 -0
  77. package/dist/esm/react/context.js +6 -0
  78. package/dist/esm/react/context.js.map +1 -0
  79. package/dist/esm/react/index.d.ts +5 -0
  80. package/dist/esm/react/index.d.ts.map +1 -0
  81. package/dist/esm/react/index.js +5 -0
  82. package/dist/esm/react/index.js.map +1 -0
  83. package/dist/esm/react/provider.d.ts +7 -0
  84. package/dist/esm/react/provider.d.ts.map +1 -0
  85. package/dist/esm/react/provider.js +10 -0
  86. package/dist/esm/react/provider.js.map +1 -0
  87. package/dist/esm/react/signal-value.d.ts +3 -0
  88. package/dist/esm/react/signal-value.d.ts.map +1 -0
  89. package/dist/esm/react/signal-value.js +38 -0
  90. package/dist/esm/react/signal-value.js.map +1 -0
  91. package/dist/esm/react/state.d.ts +3 -0
  92. package/dist/esm/react/state.d.ts.map +1 -0
  93. package/dist/esm/react/state.js +10 -0
  94. package/dist/esm/react/state.js.map +1 -0
  95. package/dist/esm/scheduling.d.ts +5 -0
  96. package/dist/esm/scheduling.d.ts.map +1 -1
  97. package/dist/esm/scheduling.js +51 -1
  98. package/dist/esm/scheduling.js.map +1 -1
  99. package/dist/esm/signals.d.ts +28 -65
  100. package/dist/esm/signals.d.ts.map +1 -1
  101. package/dist/esm/signals.js +215 -61
  102. package/dist/esm/signals.js.map +1 -1
  103. package/dist/esm/trace.d.ts +127 -0
  104. package/dist/esm/trace.d.ts.map +1 -0
  105. package/dist/esm/trace.js +311 -0
  106. package/dist/esm/trace.js.map +1 -0
  107. package/dist/esm/types.d.ts +66 -0
  108. package/dist/esm/types.d.ts.map +1 -0
  109. package/dist/esm/types.js +2 -0
  110. package/dist/esm/types.js.map +1 -0
  111. package/dist/esm/utils.d.ts +4 -0
  112. package/dist/esm/utils.d.ts.map +1 -0
  113. package/dist/esm/utils.js +75 -0
  114. package/dist/esm/utils.js.map +1 -0
  115. package/package.json +43 -2
  116. package/src/__tests__/hooks/async-computed.test.ts +190 -0
  117. package/src/__tests__/hooks/async-task.test.ts +227 -0
  118. package/src/__tests__/hooks/computed.test.ts +126 -0
  119. package/src/__tests__/hooks/context.test.ts +527 -0
  120. package/src/__tests__/hooks/nesting.test.ts +303 -0
  121. package/src/__tests__/hooks/params-and-state.test.ts +168 -0
  122. package/src/__tests__/hooks/subscription.test.ts +97 -0
  123. package/src/__tests__/signals/async.test.ts +416 -0
  124. package/src/__tests__/signals/basic.test.ts +399 -0
  125. package/src/__tests__/signals/subscription.test.ts +632 -0
  126. package/src/__tests__/signals/watcher.test.ts +253 -0
  127. package/src/__tests__/utils/async.ts +6 -0
  128. package/src/__tests__/utils/builders.ts +22 -0
  129. package/src/__tests__/utils/instrumented-hooks.ts +309 -0
  130. package/src/__tests__/utils/instrumented-signals.ts +281 -0
  131. package/src/__tests__/utils/permute.ts +74 -0
  132. package/src/config.ts +32 -17
  133. package/src/debug.ts +14 -0
  134. package/src/hooks.ts +429 -0
  135. package/src/index.ts +28 -3
  136. package/src/react/__tests__/react.test.tsx +135 -0
  137. package/src/react/context.ts +8 -0
  138. package/src/react/index.ts +4 -0
  139. package/src/react/provider.tsx +18 -0
  140. package/src/react/signal-value.ts +56 -0
  141. package/src/react/state.ts +13 -0
  142. package/src/scheduling.ts +69 -1
  143. package/src/signals.ts +331 -157
  144. package/src/trace.ts +449 -0
  145. package/src/types.ts +86 -0
  146. package/src/utils.ts +83 -0
  147. package/tsconfig.json +2 -1
  148. package/vitest.workspace.ts +24 -0
  149. package/src/__tests__/async.test.ts +0 -426
  150. package/src/__tests__/basic.test.ts +0 -378
  151. package/src/__tests__/subscription.test.ts +0 -645
  152. package/src/__tests__/utils/instrumented.ts +0 -326
package/src/scheduling.ts CHANGED
@@ -1,15 +1,33 @@
1
1
  import { ComputedSignal } from './signals.js';
2
- import { scheduleFlush, runBatch } from './config.js';
2
+ import { scheduleFlush as _scheduleFlush, runBatch } from './config.js';
3
+ import { Tracer } from './trace.js';
3
4
 
4
5
  let PENDING_DIRTIES: ComputedSignal<any>[] = [];
5
6
  let PENDING_PULLS: ComputedSignal<any>[] = [];
6
7
  let PENDING_WATCHERS: ComputedSignal<any>[] = [];
8
+ let PENDING_CONNECTS = new Map<ComputedSignal<any>, number>();
7
9
  let PENDING_DISCONNECTS = new Map<ComputedSignal<any>, number>();
10
+ let PENDING_EFFECTS: ComputedSignal<any>[] = [];
11
+ let PENDING_TRACERS: Tracer[] = [];
8
12
 
9
13
  const microtask = () => Promise.resolve();
10
14
 
15
+ let currentFlush: { promise: Promise<void>; resolve: () => void } | null = null;
16
+
17
+ const scheduleFlush = (fn: () => void) => {
18
+ if (currentFlush) return;
19
+
20
+ let resolve: () => void;
21
+ const promise = new Promise<void>(r => (resolve = r));
22
+
23
+ currentFlush = { promise, resolve: resolve! };
24
+
25
+ _scheduleFlush(flushWatchers);
26
+ };
27
+
11
28
  export const scheduleWatcher = (watcher: ComputedSignal<any>) => {
12
29
  PENDING_WATCHERS.push(watcher);
30
+
13
31
  scheduleFlush(flushWatchers);
14
32
  };
15
33
 
@@ -23,6 +41,14 @@ export const schedulePull = (signal: ComputedSignal<any>) => {
23
41
  scheduleFlush(flushWatchers);
24
42
  };
25
43
 
44
+ export const scheduleConnect = (connect: ComputedSignal<any>) => {
45
+ const current = PENDING_CONNECTS.get(connect) ?? 0;
46
+
47
+ PENDING_CONNECTS.set(connect, current + 1);
48
+
49
+ scheduleFlush(flushWatchers);
50
+ };
51
+
26
52
  export const scheduleDisconnect = (disconnect: ComputedSignal<any>) => {
27
53
  const current = PENDING_DISCONNECTS.get(disconnect) ?? 0;
28
54
 
@@ -31,7 +57,21 @@ export const scheduleDisconnect = (disconnect: ComputedSignal<any>) => {
31
57
  scheduleFlush(flushWatchers);
32
58
  };
33
59
 
60
+ export const scheduleEffect = (signal: ComputedSignal<any>) => {
61
+ PENDING_EFFECTS.push(signal);
62
+ scheduleFlush(flushWatchers);
63
+ };
64
+
65
+ export const scheduleTracer = (tracer: Tracer) => {
66
+ PENDING_TRACERS.push(tracer);
67
+ scheduleFlush(flushWatchers);
68
+ };
69
+
34
70
  const flushWatchers = async () => {
71
+ const flush = currentFlush!;
72
+
73
+ // Flush all the dirty signals and pulls recursively, clearing
74
+ // the microtask queue until they are all settled
35
75
  while (PENDING_DIRTIES.length > 0 || PENDING_PULLS.length > 0) {
36
76
  for (const dirty of PENDING_DIRTIES) {
37
77
  dirty._dirtyConsumers();
@@ -47,16 +87,44 @@ const flushWatchers = async () => {
47
87
  await microtask();
48
88
  }
49
89
 
90
+ // Clear the flush so that if any more watchers are scheduled,
91
+ // they will be flushed in the next tick
92
+ currentFlush = null;
93
+
50
94
  runBatch(() => {
51
95
  for (const watcher of PENDING_WATCHERS) {
52
96
  watcher._check();
53
97
  }
54
98
 
99
+ for (const [signal, count] of PENDING_CONNECTS) {
100
+ signal._check(true, count);
101
+ }
102
+
55
103
  for (const [signal, count] of PENDING_DISCONNECTS) {
56
104
  signal._disconnect(count);
57
105
  }
58
106
 
107
+ for (const signal of PENDING_EFFECTS) {
108
+ signal._runEffects();
109
+ }
110
+
111
+ for (const tracer of PENDING_TRACERS) {
112
+ tracer.flush();
113
+ }
114
+
59
115
  PENDING_WATCHERS = [];
116
+ PENDING_CONNECTS.clear();
60
117
  PENDING_DISCONNECTS.clear();
118
+ PENDING_EFFECTS = [];
119
+ PENDING_TRACERS = [];
61
120
  });
121
+
122
+ // resolve the flush promise
123
+ flush.resolve();
124
+ };
125
+
126
+ export const settled = async () => {
127
+ while (currentFlush) {
128
+ await currentFlush.promise;
129
+ }
62
130
  };