@askrjs/askr 0.3.0 → 0.4.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 (123) hide show
  1. package/CHANGELOG.md +874 -0
  2. package/README.md +61 -29
  3. package/capabilities.json +19 -9
  4. package/dist/actions/index.js +56 -12
  5. package/dist/benchmark.js +10 -15
  6. package/dist/boot/index.d.ts +3 -2
  7. package/dist/boot/index.js +1 -1
  8. package/dist/boot-DaoTYoCw.js +3989 -0
  9. package/dist/browser-activity-CB8e-V4f.js +220 -0
  10. package/dist/components/index.d.ts +8 -1
  11. package/dist/components/index.js +1 -43
  12. package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
  13. package/dist/control/index.d.ts +2 -0
  14. package/dist/control/index.js +1 -1
  15. package/dist/control-nfpT2fbK.js +209 -0
  16. package/dist/core.d.ts +5 -9
  17. package/dist/csp-nonce-DwGw1A6Q.js +35 -0
  18. package/dist/data/index.js +3 -3
  19. package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
  20. package/dist/data-runtime-C1bFAlba.js +242 -0
  21. package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
  22. package/dist/domains/actions.d.ts +8 -3
  23. package/dist/domains/component.d.ts +1 -107
  24. package/dist/domains/context.d.ts +0 -15
  25. package/dist/domains/control.d.ts +36 -249
  26. package/dist/domains/data.d.ts +31 -13
  27. package/dist/domains/diagnostics.d.ts +1 -2
  28. package/dist/domains/lifecycle.d.ts +2 -5
  29. package/dist/domains/refs.d.ts +0 -2
  30. package/dist/domains/routing.d.ts +43 -8
  31. package/dist/domains/scheduler.d.ts +1 -76
  32. package/dist/domains/server.d.ts +5 -2
  33. package/dist/domains/state.d.ts +2 -5
  34. package/dist/domains/telemetry.d.ts +0 -2
  35. package/dist/elements.d.ts +214 -51
  36. package/dist/error-boundary-Bpwofwps.js +293 -0
  37. package/dist/foundations/icon/index.d.ts +0 -58
  38. package/dist/foundations/icon/index.js +2 -2
  39. package/dist/foundations/index.js +2 -1
  40. package/dist/foundations/interactions/index.js +1 -1
  41. package/dist/foundations/state/index.d.ts +3 -3
  42. package/dist/foundations/state/index.js +5 -3
  43. package/dist/foundations/structures/index.js +2 -1
  44. package/dist/foundations/utilities/index.d.ts +2 -0
  45. package/dist/foundations/utilities/index.js +1 -2
  46. package/dist/fx/index.d.ts +31 -58
  47. package/dist/fx/index.js +313 -195
  48. package/dist/hooks-BimKStr4.js +202 -0
  49. package/dist/index.d.ts +11 -74
  50. package/dist/index.js +8 -447
  51. package/dist/instance-BAnfmXOR.js +988 -0
  52. package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
  53. package/dist/jsx-dev-runtime.d.ts +41 -18
  54. package/dist/jsx-dev-runtime.js +1 -6
  55. package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
  56. package/dist/jsx-runtime.js +1 -1
  57. package/dist/jsx.d.ts +61 -37
  58. package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
  59. package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
  60. package/dist/navigation.d.ts +12 -3
  61. package/dist/peer-types.d.ts +8 -0
  62. package/dist/portal-DuOKfnLa.js +349 -0
  63. package/dist/promise-Dz8iIHAm.js +16 -0
  64. package/dist/query-registry-WMCN0BJL.js +320 -0
  65. package/dist/readable-DFWOsTac.js +21 -0
  66. package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
  67. package/dist/render-sync-IC5lMFpq.js +1240 -0
  68. package/dist/resolution-Cx82-xjW.js +1244 -0
  69. package/dist/resource-CLjB7RBQ.js +377 -0
  70. package/dist/resources/index.d.ts +21 -11
  71. package/dist/resources/index.js +45 -244
  72. package/dist/router/index.d.ts +14 -5
  73. package/dist/router/index.js +22 -53
  74. package/dist/scope-CwpVSHVf.js +55 -0
  75. package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
  76. package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
  77. package/dist/ssg/index.d.ts +1 -2
  78. package/dist/ssg/index.js +5 -13
  79. package/dist/ssr/index.d.ts +26 -28
  80. package/dist/ssr/index.js +4 -4
  81. package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
  82. package/dist/ssr-DoV-vJ-5.js +229 -0
  83. package/dist/state-DWO1KzkX.js +232 -0
  84. package/dist/structures-D4dDMqHX.js +231 -0
  85. package/dist/testing/index.d.ts +8 -4
  86. package/dist/testing/index.js +29 -34
  87. package/dist/url-CnbfpX0K.js +185 -0
  88. package/dist/utilities.d.ts +48 -2
  89. package/dist/verify-hydration-DpVaDnqz.js +152 -0
  90. package/package.json +19 -9
  91. package/dist/access-CEA2pOry.js +0 -1046
  92. package/dist/activity-oy2YFTFF.js +0 -201
  93. package/dist/boot-BMBMWUGI.js +0 -1084
  94. package/dist/capabilities-Bbf0mlp9.js +0 -42
  95. package/dist/compose-ref-v0qGlHoN.js +0 -26
  96. package/dist/control-BR_mrX__.js +0 -173
  97. package/dist/control-C-ApnFs1.js +0 -20
  98. package/dist/csp-nonce-BfFWcd0w.js +0 -173
  99. package/dist/data-runtime-CxoY98lX.js +0 -149
  100. package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
  101. package/dist/dom-renderer.d.ts +0 -77
  102. package/dist/domains/renderer.d.ts +0 -127
  103. package/dist/eager-control.d.ts +0 -8
  104. package/dist/effect-C3Zsc1k6.js +0 -292
  105. package/dist/for-state-BDykeOJL.js +0 -1753
  106. package/dist/instance-VAFYVJOa.js +0 -1027
  107. package/dist/notify-DxxuDPeY.js +0 -266
  108. package/dist/portal-w3oQ6oQU.js +0 -29
  109. package/dist/query-registry-LrYpQsDJ.js +0 -83
  110. package/dist/render-resolved-BC0W7_5b.js +0 -1123
  111. package/dist/renderer-CT0HeY58.js +0 -8623
  112. package/dist/resolution-3DskUkjG.js +0 -577
  113. package/dist/resource-18-sFRl9.js +0 -344
  114. package/dist/route-matching-CUzZ31gT.js +0 -551
  115. package/dist/router-internal-7nuNEHfG.js +0 -36
  116. package/dist/scope-Cq_iYbTR.js +0 -403
  117. package/dist/selector-BSPVkjKP.js +0 -311
  118. package/dist/ssr-EPjwJH5R.js +0 -29
  119. package/dist/state-BXJfudq1.js +0 -91
  120. package/dist/structures-CjEzfj4h.js +0 -654
  121. package/dist/timer-C7uqnJVt.js +0 -85
  122. package/dist/verify-hydration-ikaxotf7.js +0 -27
  123. package/dist/vnode-D24p6IW2.js +0 -7
package/dist/fx/index.js CHANGED
@@ -1,54 +1,115 @@
1
- import { h as scheduleEventHandler, n as enqueueRuntimeTask, v as logger } from "../access-CEA2pOry.js";
2
- import { O as ownCleanup, f as getCurrentComponentInstance } from "../scope-Cq_iYbTR.js";
1
+ import { S as queueTask } from "../instance-BAnfmXOR.js";
2
+ import { a as currentOwner, f as withOwner, i as currentComponent, y as reportUncaughtError } from "../hooks-BimKStr4.js";
3
+ import { n as isPromiseLike } from "../promise-Dz8iIHAm.js";
3
4
  //#region src/fx/timing.ts
4
5
  /**
5
- * Debounce — delay execution, coalesce rapid calls
6
- *
7
- * Useful for: text input, resize, autosave
8
- *
9
- * @param fn Function to debounce
10
- * @param ms Delay in milliseconds
11
- * @param options trailing (default true), leading
12
- * @returns Debounced function with cancel() method
13
- *
14
- * @example
15
- * ```ts
16
- * const save = debounce((text) => api.save(text), 500);
17
- * input.addEventListener('input', (e) => save(e.target.value));
18
- * save.cancel(); // stop any pending execution
19
- * ```
6
+ * @internal Edge logic for fx `debounceEvent`.
7
+ * A trailing call only runs when a call arrived after the leading call.
20
8
  */
21
- function debounce(fn, ms, options) {
22
- const callable = fn;
23
- let timeoutId = null;
9
+ function createDebouncer(invoke, ms, options) {
24
10
  const { leading = false, trailing = true } = options || {};
11
+ let timeoutId = null;
25
12
  let lastArgs = null;
26
13
  let lastThis = null;
27
14
  let trailingPending = false;
28
- const debounced = function(...args) {
29
- const windowActive = timeoutId !== null;
30
- lastArgs = args;
31
- lastThis = this;
32
- if (timeoutId !== null) clearTimeout(timeoutId);
33
- if (leading && !windowActive) {
34
- callable.apply(this, args);
35
- trailingPending = false;
36
- } else if (trailing) trailingPending = true;
37
- timeoutId = setTimeout(() => {
38
- if (trailingPending) callable.apply(lastThis, lastArgs);
15
+ const clearTimer = () => {
16
+ if (timeoutId !== null) {
17
+ clearTimeout(timeoutId);
39
18
  timeoutId = null;
40
- trailingPending = false;
41
- }, ms);
19
+ }
42
20
  };
43
- debounced.cancel = () => {
21
+ const reset = () => {
22
+ trailingPending = false;
23
+ lastArgs = null;
24
+ lastThis = null;
25
+ };
26
+ const runTrailing = () => {
27
+ const pending = trailingPending;
28
+ const args = lastArgs;
29
+ const thisArg = lastThis;
30
+ reset();
31
+ if (pending) invoke(thisArg, args);
32
+ };
33
+ return {
34
+ call(thisArg, args) {
35
+ const windowActive = timeoutId !== null;
36
+ clearTimer();
37
+ if (leading && !windowActive) {
38
+ reset();
39
+ invoke(thisArg, args);
40
+ } else if (trailing) {
41
+ lastArgs = args;
42
+ lastThis = thisArg;
43
+ trailingPending = true;
44
+ }
45
+ timeoutId = setTimeout(() => {
46
+ timeoutId = null;
47
+ runTrailing();
48
+ }, ms);
49
+ },
50
+ cancel() {
51
+ clearTimer();
52
+ reset();
53
+ },
54
+ flush() {
55
+ if (timeoutId === null) return;
56
+ clearTimer();
57
+ runTrailing();
58
+ }
59
+ };
60
+ }
61
+ /**
62
+ * @internal Edge logic shared by {@link throttle} and fx `throttleEvent`.
63
+ * A trailing call only runs when a call arrived after the leading call.
64
+ */
65
+ function createThrottler(invoke, ms, options) {
66
+ const { leading = true, trailing = true } = options || {};
67
+ let lastCallTime = null;
68
+ let timeoutId = null;
69
+ let lastArgs = null;
70
+ let lastThis = null;
71
+ const clearTimer = () => {
44
72
  if (timeoutId !== null) {
45
73
  clearTimeout(timeoutId);
46
74
  timeoutId = null;
47
75
  }
48
- trailingPending = false;
49
76
  };
50
- return debounced;
77
+ return {
78
+ call(thisArg, args) {
79
+ const callTime = Date.now();
80
+ const timeSinceLastCall = lastCallTime === null ? Number.POSITIVE_INFINITY : callTime - lastCallTime;
81
+ if (leading && timeSinceLastCall >= ms) {
82
+ clearTimer();
83
+ lastArgs = null;
84
+ lastThis = null;
85
+ lastCallTime = callTime;
86
+ invoke(thisArg, args);
87
+ return;
88
+ }
89
+ if (!trailing) return;
90
+ lastArgs = args;
91
+ lastThis = thisArg;
92
+ if (!leading && timeSinceLastCall >= ms) lastCallTime = callTime;
93
+ if (timeoutId === null) timeoutId = setTimeout(() => {
94
+ timeoutId = null;
95
+ lastCallTime = Date.now();
96
+ const pendingArgs = lastArgs;
97
+ const pendingThis = lastThis;
98
+ lastArgs = null;
99
+ lastThis = null;
100
+ invoke(pendingThis, pendingArgs);
101
+ }, Math.max(0, ms - (callTime - lastCallTime)));
102
+ },
103
+ cancel() {
104
+ clearTimer();
105
+ lastArgs = null;
106
+ lastThis = null;
107
+ }
108
+ };
51
109
  }
110
+ const applyTo = (callable) => (thisArg, args) => {
111
+ callable.apply(thisArg, args);
112
+ };
52
113
  /**
53
114
  * Throttle — rate-limit execution, keep first/last
54
115
  *
@@ -67,39 +128,11 @@ function debounce(fn, ms, options) {
67
128
  * ```
68
129
  */
69
130
  function throttle(fn, ms, options) {
70
- const callable = fn;
71
- let lastCallTime = null;
72
- let timeoutId = null;
73
- const { leading = true, trailing = true } = options || {};
74
- let lastArgs = null;
75
- let lastThis = null;
131
+ const throttler = createThrottler(applyTo(fn), ms, options);
76
132
  const throttled = function(...args) {
77
- const callTime = Date.now();
78
- const timeSinceLastCall = lastCallTime === null ? Number.POSITIVE_INFINITY : callTime - lastCallTime;
79
- lastArgs = args;
80
- lastThis = this;
81
- if (leading && timeSinceLastCall >= ms) {
82
- callable.apply(this, args);
83
- lastCallTime = callTime;
84
- if (timeoutId !== null) {
85
- clearTimeout(timeoutId);
86
- timeoutId = null;
87
- }
88
- return;
89
- }
90
- if (!leading && lastCallTime === null) lastCallTime = callTime;
91
- if (trailing && timeoutId === null) timeoutId = setTimeout(() => {
92
- callable.apply(lastThis, lastArgs);
93
- lastCallTime = Date.now();
94
- timeoutId = null;
95
- }, lastCallTime === null ? ms : Math.max(0, ms - (callTime - lastCallTime)));
96
- };
97
- throttled.cancel = () => {
98
- if (timeoutId !== null) {
99
- clearTimeout(timeoutId);
100
- timeoutId = null;
101
- }
133
+ throttler.call(this, args);
102
134
  };
135
+ throttled.cancel = throttler.cancel;
103
136
  return throttled;
104
137
  }
105
138
  /**
@@ -131,22 +164,6 @@ function once(fn) {
131
164
  };
132
165
  }
133
166
  /**
134
- * Defer — schedule on microtask queue
135
- *
136
- * Useful for: run-after-current-stack logic
137
- * More reliable than setTimeout(..., 0)
138
- *
139
- * @param fn Function to defer
140
- *
141
- * @example
142
- * ```ts
143
- * defer(() => update()); // runs after current stack, before next macrotask
144
- * ```
145
- */
146
- function defer(fn) {
147
- Promise.resolve().then(fn);
148
- }
149
- /**
150
167
  * RAF — coalesce multiple updates into single frame
151
168
  *
152
169
  * Useful for: animation, layout work, render updates
@@ -166,14 +183,31 @@ function raf(fn) {
166
183
  let frameId = null;
167
184
  let lastArgs = null;
168
185
  let lastThis = null;
169
- return function(...args) {
186
+ let generation = 0;
187
+ const scheduled = function(...args) {
170
188
  lastArgs = args;
171
189
  lastThis = this;
172
- if (frameId === null) frameId = requestAnimationFrame(() => {
173
- callable.apply(lastThis, lastArgs);
174
- frameId = null;
175
- });
190
+ if (frameId === null) {
191
+ const currentGeneration = ++generation;
192
+ frameId = requestAnimationFrame(() => {
193
+ if (currentGeneration !== generation) return;
194
+ frameId = null;
195
+ const args = lastArgs;
196
+ const receiver = lastThis;
197
+ lastArgs = null;
198
+ lastThis = null;
199
+ callable.apply(receiver, args);
200
+ });
201
+ }
176
202
  };
203
+ scheduled.cancel = () => {
204
+ generation++;
205
+ if (frameId !== null) cancelAnimationFrame(frameId);
206
+ frameId = null;
207
+ lastArgs = null;
208
+ lastThis = null;
209
+ };
210
+ return scheduled;
177
211
  }
178
212
  /**
179
213
  * Idle — schedule low-priority work
@@ -249,126 +283,122 @@ const noopEventListenerWithFlush = Object.assign((_ev) => {}, {
249
283
  });
250
284
  //#endregion
251
285
  //#region src/fx/fx.ts
286
+ /** The owner an event arrives under, else the owner that created the handler. */
287
+ function captureLifecycleOwner() {
288
+ const captured = currentOwner();
289
+ return () => currentOwner() ?? captured;
290
+ }
291
+ function ownCleanup(owner, cleanup) {
292
+ owner.onCleanup(cleanup);
293
+ }
252
294
  function throwIfDuringRender() {
253
- if (getCurrentComponentInstance() !== null) throw new Error("[Askr] calling FX handler during render is not allowed. Move calls to event handlers or effects.");
295
+ if (currentComponent() !== null) throw new Error("[Askr] calling FX handler during render is not allowed. Move calls to event handlers or effects.");
254
296
  }
255
297
  /**
256
- * Helper: schedule a user callback through the global scheduler
298
+ * Schedule a user callback through the runtime scheduler. Its errors are
299
+ * reported like a native listener's (reportError) so the rest of the flush
300
+ * still runs.
257
301
  */
258
302
  function enqueueUserCallback(fn) {
259
- enqueueRuntimeTask(() => {
303
+ queueTask(() => {
260
304
  try {
261
305
  fn();
262
306
  } catch (err) {
263
- logger.error("[Askr] FX handler error:", err);
307
+ reportUncaughtError(err);
264
308
  }
265
309
  });
266
310
  }
311
+ const noopRelease = () => {};
312
+ /**
313
+ * Cancel scheduled work when the component whose committed lifecycle
314
+ * (mount/commit operation, task, watch callback, or event handler) scheduled
315
+ * it is cleaned up. Returns a release function for work that settles first.
316
+ */
317
+ function cancelWithLifecycleOwner(owner, cancel) {
318
+ if (!owner) return noopRelease;
319
+ if (owner.disposed) {
320
+ cancel();
321
+ return noopRelease;
322
+ }
323
+ let active = true;
324
+ owner.onCleanup(() => {
325
+ if (active) cancel();
326
+ });
327
+ return () => {
328
+ active = false;
329
+ };
330
+ }
331
+ /** Run a wrapped handler later as the lifetime that received its event. */
332
+ function enqueueOwnedHandler(handler, event, owner) {
333
+ enqueueUserCallback(() => withOwner(owner, () => handler.call(null, event)));
334
+ }
335
+ /** Schedule a native listener under the owner that created it. */
336
+ function scheduleEventHandler(handler) {
337
+ const resolveOwner = captureLifecycleOwner();
338
+ return (event) => {
339
+ enqueueOwnedHandler(handler, event, resolveOwner());
340
+ };
341
+ }
342
+ function enqueueEventHandler(handler) {
343
+ return (_thisArg, [event, owner]) => {
344
+ enqueueOwnedHandler(handler, event, owner);
345
+ };
346
+ }
267
347
  /** Wrap an event handler so rapid events are coalesced and delayed by `ms`. */
268
348
  function debounceEvent(ms, handler, options) {
269
- const { leading = false, trailing = true } = options || {};
270
- const inst = getCurrentComponentInstance();
271
- if (inst && inst.ssr) return noopEventListenerWithFlush;
272
- let timeoutId = null;
273
- let lastEvent = null;
274
- let lastCallTime = 0;
349
+ const inst = currentComponent();
350
+ if (inst && inst.server) return noopEventListenerWithFlush;
351
+ const resolveOwner = captureLifecycleOwner();
352
+ const debouncer = createDebouncer(enqueueEventHandler(handler), ms, options);
275
353
  const debounced = function(ev) {
276
354
  throwIfDuringRender();
277
- const now = Date.now();
278
- lastEvent = ev;
279
- if (timeoutId !== null) {
280
- clearTimeout(timeoutId);
281
- timeoutId = null;
282
- }
283
- if (leading && now - lastCallTime >= ms) {
284
- enqueueUserCallback(() => handler.call(null, ev));
285
- lastCallTime = now;
286
- }
287
- if (trailing) timeoutId = setTimeout(() => {
288
- if (lastEvent) enqueueUserCallback(() => handler.call(null, lastEvent));
289
- timeoutId = null;
290
- lastCallTime = Date.now();
291
- }, ms);
355
+ debouncer.call(null, [ev, resolveOwner()]);
292
356
  };
293
- debounced.cancel = () => {
294
- if (timeoutId !== null) {
295
- clearTimeout(timeoutId);
296
- timeoutId = null;
297
- }
298
- lastEvent = null;
299
- };
300
- debounced.flush = () => {
301
- if (timeoutId !== null) {
302
- clearTimeout(timeoutId);
303
- const ev = lastEvent;
304
- lastEvent = null;
305
- timeoutId = null;
306
- if (ev) enqueueUserCallback(() => handler.call(null, ev));
307
- }
308
- };
309
- if (inst) ownCleanup(inst.owner, () => {
310
- debounced.cancel();
311
- });
357
+ debounced.cancel = debouncer.cancel;
358
+ debounced.flush = debouncer.flush;
359
+ const owner = inst ?? currentOwner();
360
+ if (owner) ownCleanup(owner, debounced.cancel);
312
361
  return debounced;
313
362
  }
314
363
  /** Wrap an event handler so it runs at most once per `ms` interval. */
315
364
  function throttleEvent(ms, handler, options) {
316
- const { leading = true, trailing = true } = options || {};
317
- const inst = getCurrentComponentInstance();
318
- if (inst && inst.ssr) return noopEventListener;
319
- let lastCallTime = 0;
320
- let timeoutId = null;
321
- let lastEvent = null;
365
+ const inst = currentComponent();
366
+ if (inst && inst.server) return noopEventListener;
367
+ const resolveOwner = captureLifecycleOwner();
368
+ const throttler = createThrottler(enqueueEventHandler(handler), ms, options);
322
369
  const throttled = function(ev) {
323
370
  throwIfDuringRender();
324
- const now = Date.now();
325
- lastEvent = ev;
326
- if (leading && now - lastCallTime >= ms) {
327
- enqueueUserCallback(() => handler.call(null, ev));
328
- lastCallTime = now;
329
- if (timeoutId !== null) {
330
- clearTimeout(timeoutId);
331
- timeoutId = null;
332
- }
333
- } else if (!leading && lastCallTime === 0) lastCallTime = now;
334
- if (trailing && timeoutId === null) {
335
- const wait = ms - (now - lastCallTime);
336
- timeoutId = setTimeout(() => {
337
- if (lastEvent) enqueueUserCallback(() => handler.call(null, lastEvent));
338
- lastCallTime = Date.now();
339
- timeoutId = null;
340
- }, Math.max(0, wait));
341
- }
371
+ throttler.call(null, [ev, resolveOwner()]);
342
372
  };
343
- throttled.cancel = () => {
344
- if (timeoutId !== null) {
345
- clearTimeout(timeoutId);
346
- timeoutId = null;
347
- }
348
- lastEvent = null;
349
- };
350
- if (inst) ownCleanup(inst.owner, () => throttled.cancel());
373
+ throttled.cancel = throttler.cancel;
374
+ const owner = inst ?? currentOwner();
375
+ if (owner) ownCleanup(owner, throttled.cancel);
351
376
  return throttled;
352
377
  }
353
378
  /** Wrap an event handler so it runs at most once per animation frame, using the latest event. */
354
379
  function rafEvent(handler) {
355
- const inst = getCurrentComponentInstance();
356
- if (inst && inst.ssr) return noopEventListener;
380
+ const inst = currentComponent();
381
+ if (inst && inst.server) return noopEventListener;
382
+ const resolveOwner = captureLifecycleOwner();
357
383
  let frameId = null;
358
384
  let lastEvent = null;
385
+ let lastOwner = null;
359
386
  const scheduleFrame = () => {
360
387
  frameId = (typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(() => cb(Date.now()), 16))(() => {
361
388
  frameId = null;
362
389
  if (lastEvent) {
363
390
  const ev = lastEvent;
391
+ const owner = lastOwner;
364
392
  lastEvent = null;
365
- enqueueUserCallback(() => handler.call(null, ev));
393
+ lastOwner = null;
394
+ enqueueOwnedHandler(handler, ev, owner);
366
395
  }
367
396
  });
368
397
  };
369
398
  const fn = function(ev) {
370
399
  throwIfDuringRender();
371
400
  lastEvent = ev;
401
+ lastOwner = resolveOwner();
372
402
  if (frameId === null) scheduleFrame();
373
403
  };
374
404
  fn.cancel = () => {
@@ -378,85 +408,173 @@ function rafEvent(handler) {
378
408
  frameId = null;
379
409
  }
380
410
  lastEvent = null;
411
+ lastOwner = null;
381
412
  };
382
- if (inst) ownCleanup(inst.owner, () => fn.cancel());
413
+ const owner = inst ?? currentOwner();
414
+ if (owner) ownCleanup(owner, fn.cancel);
383
415
  return fn;
384
416
  }
385
- /** Schedule `fn` after `ms`, auto-cancelling on component cleanup; returns a cancel function. */
417
+ /**
418
+ * Schedule `fn` after `ms`; returns a cancel function. Called from a mounted
419
+ * component's task, watch callback, or event handler, it is also cancelled
420
+ * when that component is cleaned up.
421
+ */
386
422
  function scheduleTimeout(ms, fn) {
387
423
  throwIfDuringRender();
388
- const inst = getCurrentComponentInstance();
389
- if (inst && inst.ssr) return () => {};
424
+ const owner = currentOwner();
425
+ let release = noopRelease;
426
+ let settled = false;
427
+ const run = () => {
428
+ if (settled) return;
429
+ settled = true;
430
+ release();
431
+ withOwner(owner, fn);
432
+ };
390
433
  let id = setTimeout(() => {
391
434
  id = null;
392
- enqueueUserCallback(fn);
435
+ enqueueUserCallback(run);
393
436
  }, ms);
394
437
  const cancel = () => {
438
+ settled = true;
395
439
  if (id !== null) {
396
440
  clearTimeout(id);
397
441
  id = null;
398
442
  }
443
+ release();
399
444
  };
400
- if (inst) ownCleanup(inst.owner, cancel);
445
+ release = cancelWithLifecycleOwner(owner, cancel);
401
446
  return cancel;
402
447
  }
403
- /** Schedule `fn` during browser idle time, auto-cancelling on component cleanup. */
448
+ /**
449
+ * Schedule `fn` during browser idle time; returns a cancel function. Called
450
+ * from a mounted component's task, watch callback, or event handler, it is
451
+ * also cancelled when that component is cleaned up.
452
+ */
404
453
  function scheduleIdle(fn, options) {
405
454
  throwIfDuringRender();
406
- const inst = getCurrentComponentInstance();
407
- if (inst && inst.ssr) return () => {};
455
+ const owner = currentOwner();
456
+ let release = noopRelease;
457
+ let settled = false;
458
+ const run = () => {
459
+ if (settled) return;
460
+ settled = true;
461
+ release();
462
+ withOwner(owner, fn);
463
+ };
408
464
  let id = null;
409
465
  let usingRIC = false;
410
466
  if (typeof requestIdleCallback !== "undefined") {
411
467
  usingRIC = true;
412
468
  id = requestIdleCallback(() => {
413
469
  id = null;
414
- enqueueUserCallback(fn);
470
+ enqueueUserCallback(run);
415
471
  }, options);
416
472
  } else id = setTimeout(() => {
417
473
  id = null;
418
- enqueueUserCallback(fn);
474
+ enqueueUserCallback(run);
419
475
  }, 0);
420
476
  const cancel = () => {
477
+ settled = true;
421
478
  if (id !== null) {
422
479
  if (usingRIC && typeof cancelIdleCallback !== "undefined" && typeof id === "number") cancelIdleCallback(id);
423
480
  else clearTimeout(id);
424
481
  id = null;
425
482
  }
483
+ release();
426
484
  };
427
- if (inst) ownCleanup(inst.owner, cancel);
485
+ release = cancelWithLifecycleOwner(owner, cancel);
428
486
  return cancel;
429
487
  }
430
- /** Run `fn`, retrying with backoff on failure, auto-cancelling on component cleanup. */
488
+ /**
489
+ * Run `fn`, retrying with backoff on failure. Called from a mounted
490
+ * component's task, watch callback, or event handler, pending attempts are
491
+ * also cancelled when that component is cleaned up.
492
+ */
431
493
  function scheduleRetry(fn, options) {
432
494
  throwIfDuringRender();
433
- const inst = getCurrentComponentInstance();
434
- if (inst && inst.ssr) return { cancel: () => {} };
435
495
  const { maxAttempts = 3, delayMs = 100, backoff = (i) => delayMs * Math.pow(2, i) } = options || {};
496
+ const owner = currentOwner();
436
497
  let cancelled = false;
498
+ let retryId = null;
499
+ let release = noopRelease;
500
+ let resolveResult;
501
+ const result = new Promise((resolve) => {
502
+ resolveResult = resolve;
503
+ });
504
+ const settle = (outcome) => {
505
+ if (cancelled) return;
506
+ cancelled = true;
507
+ release();
508
+ resolveResult(outcome);
509
+ };
437
510
  const attempt = (index) => {
511
+ retryId = null;
438
512
  if (cancelled) return;
439
- enqueueRuntimeTask(() => {
513
+ queueTask(() => {
440
514
  if (cancelled) return;
441
- fn().then(() => {}, () => {
515
+ let p;
516
+ try {
517
+ p = withOwner(owner, fn);
518
+ } catch (e) {
519
+ settle({
520
+ status: "error",
521
+ error: e
522
+ });
523
+ reportUncaughtError(e);
524
+ return;
525
+ }
526
+ if (!isPromiseLike(p)) {
527
+ settle({
528
+ status: "error",
529
+ error: /* @__PURE__ */ new TypeError("scheduleRetry callback must return a promise")
530
+ });
531
+ return;
532
+ }
533
+ Promise.resolve(p).then((value) => settle({
534
+ status: "success",
535
+ value
536
+ }), (error) => {
442
537
  if (cancelled) return;
443
- if (index + 1 < maxAttempts) {
444
- const delay = backoff(index);
445
- setTimeout(() => {
538
+ if (index + 1 < maxAttempts) try {
539
+ retryId = setTimeout(() => {
446
540
  attempt(index + 1);
447
- }, delay);
541
+ }, backoff(index));
542
+ } catch (backoffError) {
543
+ settle({
544
+ status: "error",
545
+ error: backoffError
546
+ });
547
+ reportUncaughtError(backoffError);
448
548
  }
449
- }).catch((e) => {
450
- logger.error("[Askr] scheduleRetry error:", e);
549
+ else {
550
+ settle({
551
+ status: "error",
552
+ error
553
+ });
554
+ reportUncaughtError(error);
555
+ }
556
+ }).catch((error) => {
557
+ settle({
558
+ status: "error",
559
+ error
560
+ });
561
+ reportUncaughtError(error);
451
562
  });
452
563
  });
453
564
  };
454
- attempt(0);
455
565
  const cancel = () => {
456
- cancelled = true;
566
+ if (retryId !== null) {
567
+ clearTimeout(retryId);
568
+ retryId = null;
569
+ }
570
+ settle({ status: "cancelled" });
571
+ };
572
+ release = cancelWithLifecycleOwner(owner, cancel);
573
+ attempt(0);
574
+ return {
575
+ cancel,
576
+ result
457
577
  };
458
- if (inst) ownCleanup(inst.owner, cancel);
459
- return { cancel };
460
578
  }
461
579
  //#endregion
462
- export { debounce, debounceEvent, defer, idle, once, raf, rafEvent, retry, scheduleEventHandler, scheduleIdle, scheduleRetry, scheduleTimeout, throttle, throttleEvent, timeout };
580
+ export { debounceEvent, idle, once, raf, rafEvent, retry, scheduleEventHandler, scheduleIdle, scheduleRetry, scheduleTimeout, throttle, throttleEvent, timeout };