zero-query 1.0.9 → 1.2.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 (154) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +2 -0
  3. package/cli/args.js +33 -33
  4. package/cli/commands/build-api.js +443 -0
  5. package/cli/commands/build.js +254 -216
  6. package/cli/commands/bundle.js +1228 -1183
  7. package/cli/commands/create.js +137 -121
  8. package/cli/commands/dev/devtools/index.js +56 -56
  9. package/cli/commands/dev/devtools/js/components.js +49 -49
  10. package/cli/commands/dev/devtools/js/core.js +423 -423
  11. package/cli/commands/dev/devtools/js/elements.js +421 -421
  12. package/cli/commands/dev/devtools/js/network.js +166 -166
  13. package/cli/commands/dev/devtools/js/performance.js +73 -73
  14. package/cli/commands/dev/devtools/js/router.js +105 -105
  15. package/cli/commands/dev/devtools/js/source.js +132 -132
  16. package/cli/commands/dev/devtools/js/stats.js +35 -35
  17. package/cli/commands/dev/devtools/js/tabs.js +79 -79
  18. package/cli/commands/dev/devtools/panel.html +95 -95
  19. package/cli/commands/dev/devtools/styles.css +244 -244
  20. package/cli/commands/dev/index.js +107 -107
  21. package/cli/commands/dev/logger.js +75 -75
  22. package/cli/commands/dev/overlay.js +858 -858
  23. package/cli/commands/dev/server.js +220 -167
  24. package/cli/commands/dev/validator.js +94 -94
  25. package/cli/commands/dev/watcher.js +172 -172
  26. package/cli/help.js +114 -112
  27. package/cli/index.js +52 -52
  28. package/cli/scaffold/default/LICENSE +21 -21
  29. package/cli/scaffold/default/app/app.js +207 -207
  30. package/cli/scaffold/default/app/components/about.js +201 -201
  31. package/cli/scaffold/default/app/components/api-demo.js +143 -143
  32. package/cli/scaffold/default/app/components/contact-card.js +231 -231
  33. package/cli/scaffold/default/app/components/contacts/contacts.css +706 -706
  34. package/cli/scaffold/default/app/components/contacts/contacts.html +200 -200
  35. package/cli/scaffold/default/app/components/contacts/contacts.js +196 -196
  36. package/cli/scaffold/default/app/components/counter.js +127 -127
  37. package/cli/scaffold/default/app/components/home.js +249 -249
  38. package/cli/scaffold/default/app/components/not-found.js +16 -16
  39. package/cli/scaffold/default/app/components/playground/playground.css +115 -115
  40. package/cli/scaffold/default/app/components/playground/playground.html +161 -161
  41. package/cli/scaffold/default/app/components/playground/playground.js +116 -116
  42. package/cli/scaffold/default/app/components/todos.js +225 -225
  43. package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -97
  44. package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -146
  45. package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -280
  46. package/cli/scaffold/default/app/routes.js +15 -15
  47. package/cli/scaffold/default/app/store.js +101 -101
  48. package/cli/scaffold/default/global.css +552 -552
  49. package/cli/scaffold/default/index.html +99 -99
  50. package/cli/scaffold/minimal/app/app.js +85 -85
  51. package/cli/scaffold/minimal/app/components/about.js +68 -68
  52. package/cli/scaffold/minimal/app/components/counter.js +122 -122
  53. package/cli/scaffold/minimal/app/components/home.js +68 -68
  54. package/cli/scaffold/minimal/app/components/not-found.js +16 -16
  55. package/cli/scaffold/minimal/app/routes.js +9 -9
  56. package/cli/scaffold/minimal/app/store.js +36 -36
  57. package/cli/scaffold/minimal/global.css +300 -300
  58. package/cli/scaffold/minimal/index.html +44 -44
  59. package/cli/scaffold/ssr/app/app.js +41 -41
  60. package/cli/scaffold/ssr/app/components/about.js +55 -55
  61. package/cli/scaffold/ssr/app/components/blog/index.js +65 -65
  62. package/cli/scaffold/ssr/app/components/blog/post.js +86 -86
  63. package/cli/scaffold/ssr/app/components/home.js +37 -37
  64. package/cli/scaffold/ssr/app/components/not-found.js +15 -15
  65. package/cli/scaffold/ssr/app/routes.js +8 -8
  66. package/cli/scaffold/ssr/global.css +228 -228
  67. package/cli/scaffold/ssr/index.html +37 -37
  68. package/cli/scaffold/ssr/package.json +8 -8
  69. package/cli/scaffold/ssr/server/data/posts.js +144 -144
  70. package/cli/scaffold/ssr/server/index.js +213 -213
  71. package/cli/scaffold/webrtc/app/app.js +11 -0
  72. package/cli/scaffold/webrtc/app/components/video-room.js +295 -0
  73. package/cli/scaffold/webrtc/app/lib/room.js +252 -0
  74. package/cli/scaffold/webrtc/assets/.gitkeep +0 -0
  75. package/cli/scaffold/webrtc/global.css +250 -0
  76. package/cli/scaffold/webrtc/index.html +21 -0
  77. package/cli/utils.js +305 -287
  78. package/dist/API.md +7264 -0
  79. package/dist/zquery.dist.zip +0 -0
  80. package/dist/zquery.js +10313 -6252
  81. package/dist/zquery.min.js +8 -601
  82. package/index.d.ts +570 -365
  83. package/index.js +311 -232
  84. package/package.json +76 -69
  85. package/src/component.js +1709 -1454
  86. package/src/core.js +921 -921
  87. package/src/diff.js +497 -497
  88. package/src/errors.js +209 -209
  89. package/src/expression.js +922 -922
  90. package/src/http.js +242 -242
  91. package/src/package.json +1 -1
  92. package/src/reactive.js +255 -254
  93. package/src/router.js +843 -773
  94. package/src/ssr.js +418 -418
  95. package/src/store.js +318 -272
  96. package/src/utils.js +515 -515
  97. package/src/webrtc/e2ee.js +351 -0
  98. package/src/webrtc/errors.js +116 -0
  99. package/src/webrtc/ice.js +301 -0
  100. package/src/webrtc/index.js +131 -0
  101. package/src/webrtc/joinToken.js +119 -0
  102. package/src/webrtc/observe.js +172 -0
  103. package/src/webrtc/peer.js +351 -0
  104. package/src/webrtc/reactive.js +268 -0
  105. package/src/webrtc/room.js +625 -0
  106. package/src/webrtc/sdp.js +302 -0
  107. package/src/webrtc/sfu/index.js +43 -0
  108. package/src/webrtc/sfu/livekit.js +131 -0
  109. package/src/webrtc/sfu/mediasoup.js +150 -0
  110. package/src/webrtc/signaling.js +373 -0
  111. package/src/webrtc/turn.js +237 -0
  112. package/tests/_helpers/webrtcFakes.js +289 -0
  113. package/tests/audit.test.js +4158 -4158
  114. package/tests/cli.test.js +1136 -1023
  115. package/tests/compare.test.js +497 -0
  116. package/tests/component.test.js +3969 -3938
  117. package/tests/core.test.js +1910 -1910
  118. package/tests/dev-server.test.js +489 -0
  119. package/tests/diff.test.js +1416 -1416
  120. package/tests/docs.test.js +1664 -0
  121. package/tests/electron-features.test.js +864 -0
  122. package/tests/errors.test.js +619 -619
  123. package/tests/expression.test.js +1056 -1056
  124. package/tests/http.test.js +648 -648
  125. package/tests/reactive.test.js +819 -819
  126. package/tests/router.test.js +2327 -2327
  127. package/tests/ssr.test.js +870 -870
  128. package/tests/store.test.js +830 -830
  129. package/tests/test-minifier.js +153 -153
  130. package/tests/test-ssr.js +27 -27
  131. package/tests/utils.test.js +1377 -1377
  132. package/tests/webrtc/e2ee.test.js +283 -0
  133. package/tests/webrtc/ice.test.js +202 -0
  134. package/tests/webrtc/joinToken.test.js +89 -0
  135. package/tests/webrtc/observe.test.js +111 -0
  136. package/tests/webrtc/peer.test.js +373 -0
  137. package/tests/webrtc/reactive.test.js +235 -0
  138. package/tests/webrtc/room.test.js +406 -0
  139. package/tests/webrtc/sdp.test.js +151 -0
  140. package/tests/webrtc/sfu-livekit.test.js +119 -0
  141. package/tests/webrtc/sfu.test.js +160 -0
  142. package/tests/webrtc/signaling.test.js +251 -0
  143. package/tests/webrtc/turn.test.js +256 -0
  144. package/types/collection.d.ts +383 -383
  145. package/types/component.d.ts +186 -186
  146. package/types/errors.d.ts +135 -135
  147. package/types/http.d.ts +92 -92
  148. package/types/misc.d.ts +201 -201
  149. package/types/reactive.d.ts +98 -98
  150. package/types/router.d.ts +190 -190
  151. package/types/ssr.d.ts +102 -102
  152. package/types/store.d.ts +146 -145
  153. package/types/utils.d.ts +245 -245
  154. package/types/webrtc.d.ts +653 -0
package/src/reactive.js CHANGED
@@ -1,254 +1,255 @@
1
- /**
2
- * zQuery Reactive - Proxy-based deep reactivity system
3
- *
4
- * Creates observable objects that trigger callbacks on mutation.
5
- * Used internally by components and store for auto-updates.
6
- */
7
-
8
- import { reportError, ErrorCode } from './errors.js';
9
-
10
- // ---------------------------------------------------------------------------
11
- // Deep reactive proxy
12
- // ---------------------------------------------------------------------------
13
- export function reactive(target, onChange, _path = '') {
14
- if (typeof target !== 'object' || target === null) return target;
15
- if (typeof onChange !== 'function') {
16
- reportError(ErrorCode.REACTIVE_CALLBACK, 'reactive() onChange must be a function', { received: typeof onChange });
17
- onChange = () => {};
18
- }
19
-
20
- const proxyCache = new WeakMap();
21
-
22
- const handler = {
23
- get(obj, key) {
24
- if (key === '__isReactive') return true;
25
- if (key === '__raw') return obj;
26
-
27
- const value = obj[key];
28
- if (typeof value === 'object' && value !== null) {
29
- // Return cached proxy or create new one
30
- if (proxyCache.has(value)) return proxyCache.get(value);
31
- const childProxy = new Proxy(value, handler);
32
- proxyCache.set(value, childProxy);
33
- return childProxy;
34
- }
35
- return value;
36
- },
37
-
38
- set(obj, key, value) {
39
- const old = obj[key];
40
- if (old === value) return true;
41
- obj[key] = value;
42
- // Invalidate proxy cache for the old value (it may have been replaced)
43
- if (old && typeof old === 'object') proxyCache.delete(old);
44
- try {
45
- onChange(key, value, old);
46
- } catch (err) {
47
- reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, value, old }, err);
48
- }
49
- return true;
50
- },
51
-
52
- deleteProperty(obj, key) {
53
- const old = obj[key];
54
- delete obj[key];
55
- if (old && typeof old === 'object') proxyCache.delete(old);
56
- try {
57
- onChange(key, undefined, old);
58
- } catch (err) {
59
- reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, old }, err);
60
- }
61
- return true;
62
- }
63
- };
64
-
65
- return new Proxy(target, handler);
66
- }
67
-
68
-
69
- // ---------------------------------------------------------------------------
70
- // Signal - lightweight reactive primitive (inspired by Solid/Preact signals)
71
- // ---------------------------------------------------------------------------
72
- export class Signal {
73
- constructor(value) {
74
- this._value = value;
75
- this._subscribers = new Set();
76
- }
77
-
78
- get value() {
79
- // Track dependency if there's an active effect
80
- if (Signal._activeEffect) {
81
- this._subscribers.add(Signal._activeEffect);
82
- // Record this signal in the effect's dependency set for proper cleanup
83
- if (Signal._activeEffect._deps) {
84
- Signal._activeEffect._deps.add(this);
85
- }
86
- }
87
- return this._value;
88
- }
89
-
90
- set value(newVal) {
91
- if (this._value === newVal) return;
92
- this._value = newVal;
93
- this._notify();
94
- }
95
-
96
- peek() { return this._value; }
97
-
98
- _notify() {
99
- if (Signal._batching) {
100
- Signal._batchQueue.add(this);
101
- return;
102
- }
103
- // Snapshot subscribers before iterating - a subscriber might modify
104
- // the set (e.g., an effect re-running, adding itself back)
105
- const subs = [...this._subscribers];
106
- for (let i = 0; i < subs.length; i++) {
107
- try { subs[i](); }
108
- catch (err) {
109
- reportError(ErrorCode.SIGNAL_CALLBACK, 'Signal subscriber threw', { signal: this }, err);
110
- }
111
- }
112
- }
113
-
114
- subscribe(fn) {
115
- this._subscribers.add(fn);
116
- return () => this._subscribers.delete(fn);
117
- }
118
-
119
- toString() { return String(this._value); }
120
- }
121
-
122
- // Active effect tracking
123
- Signal._activeEffect = null;
124
- // Batch state
125
- Signal._batching = false;
126
- Signal._batchQueue = new Set();
127
-
128
- /**
129
- * Create a signal
130
- * @param {*} initial - initial value
131
- * @returns {Signal}
132
- */
133
- export function signal(initial) {
134
- return new Signal(initial);
135
- }
136
-
137
- /**
138
- * Create a computed signal (derived from other signals)
139
- * @param {Function} fn - computation function
140
- * @returns {Signal}
141
- */
142
- export function computed(fn) {
143
- const s = new Signal(undefined);
144
- effect(() => {
145
- const v = fn();
146
- if (v !== s._value) {
147
- s._value = v;
148
- s._notify();
149
- }
150
- });
151
- return s;
152
- }
153
-
154
- /**
155
- * Create a side-effect that auto-tracks signal dependencies.
156
- * Returns a dispose function that removes the effect from all
157
- * signals it subscribed to - prevents memory leaks.
158
- *
159
- * @param {Function} fn - effect function
160
- * @returns {Function} - dispose function
161
- */
162
- export function effect(fn) {
163
- const execute = () => {
164
- // Clean up old subscriptions before re-running so stale
165
- // dependencies from a previous run are properly removed
166
- if (execute._deps) {
167
- for (const sig of execute._deps) {
168
- sig._subscribers.delete(execute);
169
- }
170
- execute._deps.clear();
171
- }
172
-
173
- Signal._activeEffect = execute;
174
- try { fn(); }
175
- catch (err) {
176
- reportError(ErrorCode.EFFECT_EXEC, 'Effect function threw', {}, err);
177
- }
178
- finally { Signal._activeEffect = null; }
179
- };
180
-
181
- // Track which signals this effect reads from
182
- execute._deps = new Set();
183
-
184
- execute();
185
- return () => {
186
- // Dispose: remove this effect from every signal it subscribed to
187
- if (execute._deps) {
188
- for (const sig of execute._deps) {
189
- sig._subscribers.delete(execute);
190
- }
191
- execute._deps.clear();
192
- }
193
- // Don't clobber _activeEffect - another effect may be running
194
- };
195
- }
196
-
197
-
198
- // ---------------------------------------------------------------------------
199
- // batch() - defer signal notifications until the batch completes
200
- // ---------------------------------------------------------------------------
201
-
202
- /**
203
- * Batch multiple signal writes - subscribers and effects fire once at the end.
204
- * @param {Function} fn - function that performs signal writes
205
- */
206
- export function batch(fn) {
207
- if (Signal._batching) {
208
- // Already inside a batch, just run
209
- fn();
210
- return;
211
- }
212
- Signal._batching = true;
213
- Signal._batchQueue.clear();
214
- try {
215
- fn();
216
- } finally {
217
- Signal._batching = false;
218
- // Collect all unique subscribers across all queued signals
219
- // so each subscriber/effect runs exactly once
220
- const subs = new Set();
221
- for (const sig of Signal._batchQueue) {
222
- for (const sub of sig._subscribers) {
223
- subs.add(sub);
224
- }
225
- }
226
- Signal._batchQueue.clear();
227
- for (const sub of subs) {
228
- try { sub(); }
229
- catch (err) {
230
- reportError(ErrorCode.SIGNAL_CALLBACK, 'Signal subscriber threw', {}, err);
231
- }
232
- }
233
- }
234
- }
235
-
236
-
237
- // ---------------------------------------------------------------------------
238
- // untracked() - read signals without creating dependencies
239
- // ---------------------------------------------------------------------------
240
-
241
- /**
242
- * Execute a function without tracking signal reads as dependencies.
243
- * @param {Function} fn - function to run
244
- * @returns {*} the return value of fn
245
- */
246
- export function untracked(fn) {
247
- const prev = Signal._activeEffect;
248
- Signal._activeEffect = null;
249
- try {
250
- return fn();
251
- } finally {
252
- Signal._activeEffect = prev;
253
- }
254
- }
1
+ /**
2
+ * zQuery Reactive - Proxy-based deep reactivity system
3
+ *
4
+ * Creates observable objects that trigger callbacks on mutation.
5
+ * Used internally by components and store for auto-updates.
6
+ */
7
+
8
+ import { reportError, ErrorCode } from './errors.js';
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Deep reactive proxy
12
+ // ---------------------------------------------------------------------------
13
+ export function reactive(target, onChange, _path = '') {
14
+ if (typeof target !== 'object' || target === null) return target;
15
+ if (typeof onChange !== 'function') {
16
+ reportError(ErrorCode.REACTIVE_CALLBACK, 'reactive() onChange must be a function', { received: typeof onChange });
17
+ onChange = () => {};
18
+ }
19
+
20
+ const proxyCache = new WeakMap();
21
+
22
+ const handler = {
23
+ get(obj, key) {
24
+ if (key === '__isReactive') return true;
25
+ if (key === '__raw') return obj;
26
+
27
+ const value = obj[key];
28
+ if (typeof value === 'object' && value !== null) {
29
+ // Return cached proxy or create new one
30
+ if (proxyCache.has(value)) return proxyCache.get(value);
31
+ const childProxy = new Proxy(value, handler);
32
+ proxyCache.set(value, childProxy);
33
+ return childProxy;
34
+ }
35
+ return value;
36
+ },
37
+
38
+ set(obj, key, value) {
39
+ const old = obj[key];
40
+ if (old === value) return true;
41
+ obj[key] = value;
42
+ // Invalidate proxy cache for the old value (it may have been replaced)
43
+ if (old && typeof old === 'object') proxyCache.delete(old);
44
+ try {
45
+ onChange(key, value, old);
46
+ } catch (err) {
47
+ reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, value, old }, err);
48
+ }
49
+ return true;
50
+ },
51
+
52
+ deleteProperty(obj, key) {
53
+ const old = obj[key];
54
+ delete obj[key];
55
+ if (old && typeof old === 'object') proxyCache.delete(old);
56
+ try {
57
+ onChange(key, undefined, old);
58
+ } catch (err) {
59
+ reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, old }, err);
60
+ }
61
+ return true;
62
+ }
63
+ };
64
+
65
+ return new Proxy(target, handler);
66
+ }
67
+
68
+
69
+ // ---------------------------------------------------------------------------
70
+ // Signal - lightweight reactive primitive (inspired by Solid/Preact signals)
71
+ // ---------------------------------------------------------------------------
72
+ export class Signal {
73
+ constructor(value) {
74
+ this._value = value;
75
+ this._subscribers = new Set();
76
+ }
77
+
78
+ get value() {
79
+ // Track dependency if there's an active effect
80
+ if (Signal._activeEffect) {
81
+ this._subscribers.add(Signal._activeEffect);
82
+ // Record this signal in the effect's dependency set for proper cleanup
83
+ if (Signal._activeEffect._deps) {
84
+ Signal._activeEffect._deps.add(this);
85
+ }
86
+ }
87
+ return this._value;
88
+ }
89
+
90
+ set value(newVal) {
91
+ if (this._value === newVal) return;
92
+ this._value = newVal;
93
+ this._notify();
94
+ }
95
+
96
+ peek() { return this._value; }
97
+
98
+ _notify() {
99
+ if (Signal._batching) {
100
+ Signal._batchQueue.add(this);
101
+ return;
102
+ }
103
+ // Snapshot subscribers before iterating - a subscriber might modify
104
+ // the set (e.g., an effect re-running, adding itself back)
105
+ const subs = [...this._subscribers];
106
+ for (let i = 0; i < subs.length; i++) {
107
+ try { subs[i](); }
108
+ catch (err) {
109
+ reportError(ErrorCode.SIGNAL_CALLBACK, 'Signal subscriber threw', { signal: this }, err);
110
+ }
111
+ }
112
+ }
113
+
114
+ subscribe(fn) {
115
+ this._subscribers.add(fn);
116
+ return () => this._subscribers.delete(fn);
117
+ }
118
+
119
+ toString() { return String(this._value); }
120
+ }
121
+
122
+ // Active effect tracking
123
+ Signal._activeEffect = null;
124
+ // Batch state
125
+ Signal._batching = false;
126
+ Signal._batchQueue = new Set();
127
+
128
+ /**
129
+ * Create a signal
130
+ * @param {*} initial - initial value
131
+ * @returns {Signal}
132
+ */
133
+ export function signal(initial) {
134
+ return new Signal(initial);
135
+ }
136
+
137
+ /**
138
+ * Create a computed signal (derived from other signals)
139
+ * @param {Function} fn - computation function
140
+ * @returns {Signal}
141
+ */
142
+ export function computed(fn) {
143
+ const s = new Signal(undefined);
144
+ effect(() => {
145
+ const v = fn();
146
+ if (v !== s._value) {
147
+ s._value = v;
148
+ s._notify();
149
+ }
150
+ });
151
+ return s;
152
+ }
153
+
154
+ /**
155
+ * Create a side-effect that auto-tracks signal dependencies.
156
+ * Returns a dispose function that removes the effect from all
157
+ * signals it subscribed to - prevents memory leaks.
158
+ *
159
+ * @param {Function} fn - effect function
160
+ * @returns {Function} - dispose function
161
+ */
162
+ export function effect(fn) {
163
+ const execute = () => {
164
+ // Clean up old subscriptions before re-running so stale
165
+ // dependencies from a previous run are properly removed
166
+ if (execute._deps) {
167
+ for (const sig of execute._deps) {
168
+ sig._subscribers.delete(execute);
169
+ }
170
+ execute._deps.clear();
171
+ }
172
+
173
+ Signal._activeEffect = execute;
174
+ try { fn(); }
175
+ catch (err) {
176
+ reportError(ErrorCode.EFFECT_EXEC, 'Effect function threw', {}, err);
177
+ }
178
+ finally { Signal._activeEffect = null; }
179
+ };
180
+
181
+ // Track which signals this effect reads from
182
+ execute._deps = new Set();
183
+
184
+ execute();
185
+ return () => {
186
+ // Dispose: remove this effect from every signal it subscribed to
187
+ if (execute._deps) {
188
+ for (const sig of execute._deps) {
189
+ sig._subscribers.delete(execute);
190
+ }
191
+ execute._deps.clear();
192
+ }
193
+ // Don't clobber _activeEffect - another effect may be running
194
+ };
195
+ }
196
+
197
+
198
+ // ---------------------------------------------------------------------------
199
+ // batch() - defer signal notifications until the batch completes
200
+ // ---------------------------------------------------------------------------
201
+
202
+ /**
203
+ * Batch multiple signal writes - subscribers and effects fire once at the end.
204
+ * @param {Function} fn - function that performs signal writes
205
+ */
206
+ export function batch(fn) {
207
+ if (Signal._batching) {
208
+ // Already inside a batch, just run
209
+ return fn();
210
+ }
211
+ Signal._batching = true;
212
+ Signal._batchQueue.clear();
213
+ let result;
214
+ try {
215
+ result = fn();
216
+ } finally {
217
+ Signal._batching = false;
218
+ // Collect all unique subscribers across all queued signals
219
+ // so each subscriber/effect runs exactly once
220
+ const subs = new Set();
221
+ for (const sig of Signal._batchQueue) {
222
+ for (const sub of sig._subscribers) {
223
+ subs.add(sub);
224
+ }
225
+ }
226
+ Signal._batchQueue.clear();
227
+ for (const sub of subs) {
228
+ try { sub(); }
229
+ catch (err) {
230
+ reportError(ErrorCode.SIGNAL_CALLBACK, 'Signal subscriber threw', {}, err);
231
+ }
232
+ }
233
+ }
234
+ return result;
235
+ }
236
+
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // untracked() - read signals without creating dependencies
240
+ // ---------------------------------------------------------------------------
241
+
242
+ /**
243
+ * Execute a function without tracking signal reads as dependencies.
244
+ * @param {Function} fn - function to run
245
+ * @returns {*} the return value of fn
246
+ */
247
+ export function untracked(fn) {
248
+ const prev = Signal._activeEffect;
249
+ Signal._activeEffect = null;
250
+ try {
251
+ return fn();
252
+ } finally {
253
+ Signal._activeEffect = prev;
254
+ }
255
+ }