Skip to content

feat(timer): add cancellable microtask scheduling with cross-runtime fallback support#570

Open
nev21 wants to merge 1 commit into
mainfrom
nev21/Release
Open

feat(timer): add cancellable microtask scheduling with cross-runtime fallback support#570
nev21 wants to merge 1 commit into
mainfrom
nev21/Release

Conversation

@nev21
Copy link
Copy Markdown
Contributor

@nev21 nev21 commented May 22, 2026

Add a new microtask scheduling API that extends standard microtasks with cancellable handlers while preserving runtime parity across Node.js, browsers, and web workers.

  • Add timer microtask API surface:
    • scheduleMicrotask
    • hasQueueMicrotask
    • getQueueMicrotask
    • setMicroTaskFallbackOptions
    • ScheduleMicrotaskFn and MicroTaskOptions types
  • Implement fallback chain:
    • native queueMicrotask when available
    • Promise.resolve().then fallback
    • timer-backed microtask queue fallback
  • Return ITimerHandler from scheduled microtasks to support cancellation and refresh semantics.
  • Ensure thrown microtask callback errors are surfaced via task rethrow handling.
  • Integrate timer-backed microtask flushing with timeout scheduling behavior for correct ordering.
  • Export new public APIs from index entrypoints.
  • Add comprehensive common-runtime tests for ordering, cancellation, fallback behavior, nested microtasks, batching across ticks, and throw surfacing.
  • Update documentation and release notes:
    • README and CHANGELOG now describe runtime parity and that helpers extend standard microtasks as cancellable.
  • Update package metadata:
    • add microtask-related keywords to both package manifests.
  • Refresh size/check expectations and related tests for new API additions.

@nev21 nev21 added this to the 0.15.0 milestone May 22, 2026
@nev21 nev21 requested a review from a team as a code owner May 22, 2026 16:13
Copilot AI review requested due to automatic review settings May 22, 2026 16:13
@nev21 nev21 requested a review from a team as a code owner May 22, 2026 16:13
@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.41%. Comparing base (45cb369) to head (70720a3).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #570      +/-   ##
==========================================
+ Coverage   99.39%   99.41%   +0.02%     
==========================================
  Files         154      158       +4     
  Lines        4659     4821     +162     
  Branches      998     1036      +38     
==========================================
+ Hits         4631     4793     +162     
  Misses         28       28              
Files with missing lines Coverage Δ
lib/src/timer/microtask.ts 100.00% <100.00%> (ø)
lib/src/timer/microtasks/promiseMicrotask.ts 100.00% <100.00%> (ø)
lib/src/timer/microtasks/runMicrotask.ts 100.00% <100.00%> (ø)
lib/src/timer/microtasks/timerMicrotask.ts 100.00% <100.00%> (ø)
lib/src/timer/timeout.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Timer microtask scheduling API (scheduleMicrotask + related helpers/types) that provides cancellable microtasks with consistent fallback behavior across runtimes (native queueMicrotask → Promise microtasks → timer-backed queue), plus supporting documentation, tests, and size/metadata updates.

Changes:

  • Introduces new timer/microtask public API surface (helpers + types) and exports it from the main index.
  • Implements Promise- and timer-backed microtask fallbacks, including timeout integration to preserve ordering.
  • Adds common-runtime tests and updates README/CHANGELOG/package metadata and size limits for the new API.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
README.md Documents the new microtask helpers and adds them to the categorized API listing.
package.json Adds microtask-related keywords to package metadata.
lib/package.json Adds microtask-related keywords to the published library package metadata.
CHANGELOG.md Adds an Unreleased entry describing the new microtask API and behavior.
.size-limit.json Updates size budgets and adds new size-limit entries for the new exports.
lib/test/bundle-size-check.js Adjusts bundle size thresholds to accommodate new API additions.
lib/test/src/common/timer/microtask.test.ts Adds comprehensive tests for ordering, cancellation, fallback behavior, and error surfacing.
lib/test/src/common/object/for_each_key.test.ts Minor formatting/indentation adjustment in an existing test.
lib/src/timer/timeout.ts Adds a microtask-flush hook so timer-backed microtasks can run before timeout callbacks.
lib/src/timer/microtasks/timerMicrotask.ts Implements a timer-backed microtask queue and flush scheduling logic.
lib/src/timer/microtasks/runMicrotask.ts Adds a helper to run microtasks while rethrowing exceptions via a task.
lib/src/timer/microtasks/promiseMicrotask.ts Adds a Promise-based microtask scheduler wrapper.
lib/src/timer/microtask.ts Adds the public microtask API (getters, options, scheduling, cancellable handler).
lib/src/index.ts Exports the new microtask APIs (and also re-exports IGetLength).

Comment on lines +16 to +38
let _promiseFn: ICachedValue<ScheduleMicrotaskFn>;

/**
* @internal
* @since 0.15.0
*/
function _promiseScheduleFn(promiseCls: PromiseConstructor): ScheduleMicrotaskFn {
return function (callback: () => void ): void {
promiseCls.resolve().then(() => {
_runMicroTask(callback);
});
};
}

/**
* @internal
* @since 0.15.0
*/
function _initPromiseFn(): void {
let promiseCls = getInst<PromiseConstructor>("Promise");

_promiseFn = createCachedValue((promiseCls && isFunction(promiseCls.resolve)) ? _promiseScheduleFn(promiseCls) : UNDEF_VALUE as any);
}
Comment on lines +22 to +27
function _promiseScheduleFn(promiseCls: PromiseConstructor): ScheduleMicrotaskFn {
return function (callback: () => void ): void {
promiseCls.resolve().then(() => {
_runMicroTask(callback);
});
};
Comment on lines +42 to +55
export interface MicroTaskOptions {
/**
* Provide a custom scheduling function to use ONLY when native `queueMicrotask` and Promise support
* is unavailable. When specified, this option takes precedence over `disablePromise`.
*/
scheduleFn?: ScheduleMicrotaskFn;

/**
* Disable Promise fallback usage and use `scheduleTimeout(..., 0)` instead. When `scheduleFn` is
* not provided, this option controls whether to use `scheduleTimeout(..., 0)` as the fallback
* instead of `Promise.resolve().then(...)`.
*/
disablePromise?: boolean;
}
Comment on lines +194 to +206
function _createCancellableMicroTask(callback: () => void, queueFn: ScheduleMicrotaskFn): ITimerHandler {
let handler: _TimerHandler;
// Used to track the currently scheduled task, incremented to cancel pending tasks when needed
let currentTask = 0;

function _scheduleTask() {
let taskId = ++currentTask;
queueFn(() => {
if (taskId === currentTask) {
handler.dn();
callback();
}
});
Comment thread lib/src/timer/microtask.ts Outdated
let handler: _TimerHandler;
// Used to track the currently scheduled task, incremented to cancel pending tasks when needed
let currentTask = 0;

Comment thread lib/src/timer/timeout.ts Outdated
Comment on lines +61 to +62
// Run and pending microtasks before running the timeout callback to allow any microtasks
// scheduled within the callback to run before the next timeout
* Reset the timer-backed microtask queue state. Intended for tests that need a clean queue/timer instance.
* @since 0.15.0
*/
export function _resetMicrotaskQueue(): void {

import { UNDEF_VALUE } from "../../internal/constants";
import { ITimerHandler } from "../handler";
import { MicrotaskFn, ScheduleMicrotaskFn } from "../microtask";
…fallback support

Add a new microtask scheduling API that extends standard microtasks with cancellable handlers while preserving runtime parity across Node.js, browsers, and web workers.

- Add timer microtask API surface:
  - scheduleMicrotask
  - hasQueueMicrotask
  - getQueueMicrotask
  - setMicroTaskFallbackOptions
  - ScheduleMicrotaskFn and MicroTaskOptions types
- Implement fallback chain:
  - native queueMicrotask when available
  - Promise.resolve().then fallback
  - timer-backed microtask queue fallback
- Return ITimerHandler from scheduled microtasks to support cancellation and refresh semantics.
- Ensure thrown microtask callback errors are surfaced via task rethrow handling.
- Integrate timer-backed microtask flushing with timeout scheduling behavior for correct ordering.
- Export new public APIs from index entrypoints.
- Add comprehensive common-runtime tests for ordering, cancellation, fallback behavior, nested microtasks, batching across ticks, and throw surfacing.
- Update documentation and release notes:
  - README and CHANGELOG now describe runtime parity and that helpers extend standard microtasks as cancellable.
- Update package metadata:
  - add microtask-related keywords to both package manifests.
- Refresh size/check expectations and related tests for new API additions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants