DomEventLoop Class

The window event loop (https://html.spec.whatwg.org/multipage/webappapis.html#window-event-loop) of a browsing context group: each top-level BrowsingContext has its own event loop, shared by its nested browsing contexts (BrowsingContext.EventLoop). It runs the tasks and the microtasks of their documents (load events, timers, mutation observers, slotchange events, scripts...). The documents that are not associated with a browsing context (e.g. a document parsed by HtmlDocumentParser) have no event loop: the tasks and the microtasks of their nodes are not queued. The host drives the loop: call DomEventLoop.PerformMicrotaskCheckpoint, DomEventLoop.RunUntilIdle or DomEventLoop.RunUntilIdleAsync. Tasks can be queued from any thread (e.g. when an asynchronous operation completes); they run on the thread that runs the loop. When a browsing context has a ScriptEngine, the microtasks are queued in the job queue of the engine, so that they run in order with the promise jobs.

public sealed class DomEventLoop

Remarks

In the specification, the agents of a browsing context group are keyed by site, and each agent has its own event loop. The library runs all the documents of a browsing context group on a single thread, so a single event loop runs the tasks of all its agents in one of the orders allowed by the specification.

Properties

NameDescription
AutoPerformMicrotaskCheckpointGets or sets whether queued microtasks run synchronously at the end of each DOM operation that queued them.
HasPendingOperationsGets whether asynchronous operations are in progress (e.g. documents loaded by BrowsingContextOptions.DocumentLoader). They queue a task when they complete.
HasPendingWorkGets whether there are pending tasks or microtasks.
HasRunningWorkersGets whether a worker created by the documents of the event loop (or by its workers) has a task to run, or runs a task that is not waiting for a synchronous operation: a host that advances a fake clock waits for the workers before advancing it.
IsDisposedGets whether the event loop was disposed with its browsing context (BrowsingContext.Dispose): the tasks, the microtasks and the timers queued afterwards are ignored.
MicrotaskQueueOverrideGets or sets a function that queues microtasks in another queue (for instance the job queue of a JavaScript engine), so that microtasks queued by the DOM and by scripts are interleaved in order.
TimeProviderGets or sets the clock of the timers (setTimeout(), requestAnimationFrame(), AbortSignal.timeout()...) and of performance.now(). The default is TimeProvider.System. A browsing context created with BrowsingContextOptions.TimeProvider sets it. Use a fake clock (e.g. FakeTimeProvider) to run the timers without waiting.
TimerQueueOverrideGets or sets a function that schedules the timers of the DOM (e.g. AbortSignal.timeout()) in the host's own timer queue, so they are ordered with the other timers of the host.
WorkSignalGets or sets the callback invoked when work arrives, from any thread: a task is queued (e.g. by an asynchronous operation that completes on another thread, such as a document loaded by BrowsingContextOptions.DocumentLoader), a timer is queued, or an asynchronous operation ends. A host that runs the event loop on its own thread uses it to wake up and call DomEventLoop.RunTask and DomEventLoop.PromoteDueTimers. The callback must not run the event loop itself.
WorkerActivityGets a value that changes each time a worker created by the documents of the event loop (or by its workers) stops running (see DomEventLoop.HasRunningWorkers): it ran a task, or its task waits for a synchronous operation. A worker may run between two reads of DomEventLoop.HasRunningWorkers (e.g. its timer becomes due when another thread reads the clock) and add a timer or queue a task meanwhile: a host that advances a fake clock reads this value before computing the next timer, and does not advance the clock if it changed.

AutoPerformMicrotaskCheckpoint

DomEventLoop.cs

Gets or sets whether queued microtasks run synchronously at the end of each DOM operation that queued them.

public bool AutoPerformMicrotaskCheckpoint { get; set; }

Property value

bool

HasPendingOperations

DomEventLoop.cs

Gets whether asynchronous operations are in progress (e.g. documents loaded by BrowsingContextOptions.DocumentLoader). They queue a task when they complete.

public bool HasPendingOperations { get; }

Property value

bool

HasPendingWork

DomEventLoop.cs

Gets whether there are pending tasks or microtasks.

public bool HasPendingWork { get; }

Property value

bool

HasRunningWorkers

DomEventLoop.Workers.cs

Gets whether a worker created by the documents of the event loop (or by its workers) has a task to run, or runs a task that is not waiting for a synchronous operation: a host that advances a fake clock waits for the workers before advancing it.

public bool HasRunningWorkers { get; }

Property value

bool

IsDisposed

DomEventLoop.cs

Gets whether the event loop was disposed with its browsing context (BrowsingContext.Dispose): the tasks, the microtasks and the timers queued afterwards are ignored.

public bool IsDisposed { get; }

Property value

bool

MicrotaskQueueOverride

DomEventLoop.cs
  • Obsolete: Use BrowsingContextOptions.ScriptEngine: the microtasks are queued in the job queue of the script engine.

Gets or sets a function that queues microtasks in another queue (for instance the job queue of a JavaScript engine), so that microtasks queued by the DOM and by scripts are interleaved in order.

[Obsolete("Use BrowsingContextOptions.ScriptEngine: the microtasks are queued in the job queue of the script engine.")]
public Action<Action>? MicrotaskQueueOverride { get; set; }

Property value

Action<Action>?

TimeProvider

DomEventLoop.cs

Gets or sets the clock of the timers (setTimeout(), requestAnimationFrame(), AbortSignal.timeout()...) and of performance.now(). The default is TimeProvider.System. A browsing context created with BrowsingContextOptions.TimeProvider sets it. Use a fake clock (e.g. FakeTimeProvider) to run the timers without waiting.

public TimeProvider TimeProvider { get; set; }

Property value

TimeProvider

TimerQueueOverride

DomEventLoop.cs
  • Obsolete: Use BrowsingContextOptions.TimeProvider or DomEventLoop.TimeProvider: the timers of the windows are implemented by the library.

Gets or sets a function that schedules the timers of the DOM (e.g. AbortSignal.timeout()) in the host's own timer queue, so they are ordered with the other timers of the host.

[Obsolete("Use BrowsingContextOptions.TimeProvider or DomEventLoop.TimeProvider: the timers of the windows are implemented by the library.")]
public Action<TimeSpan, Action>? TimerQueueOverride { get; set; }

WorkSignal

DomEventLoop.cs

Gets or sets the callback invoked when work arrives, from any thread: a task is queued (e.g. by an asynchronous operation that completes on another thread, such as a document loaded by BrowsingContextOptions.DocumentLoader), a timer is queued, or an asynchronous operation ends. A host that runs the event loop on its own thread uses it to wake up and call DomEventLoop.RunTask and DomEventLoop.PromoteDueTimers. The callback must not run the event loop itself.

public Action? WorkSignal { get; set; }

Property value

Action?

Gets a value that changes each time a worker created by the documents of the event loop (or by its workers) stops running (see DomEventLoop.HasRunningWorkers): it ran a task, or its task waits for a synchronous operation. A worker may run between two reads of DomEventLoop.HasRunningWorkers (e.g. its timer becomes due when another thread reads the clock) and add a timer or queue a task meanwhile: a host that advances a fake clock reads this value before computing the next timer, and does not advance the clock if it changed.

public long WorkerActivity { get; }

Property value

long

Methods

NameDescription
PerformMicrotaskCheckpoint()https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
PromoteDueTimers()Moves the due timers to the task queue. Returns the time until the next timer, or null when there is none. The timers of the workers created by the documents of the event loop are included in the result (they run on the threads of the workers), so that a host that advances a fake clock to the next timer also runs the timers of the workers.
QueueMicrotask(Action)https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
QueueTask(Action)Queues a task (https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task).
QueueTimer(TimeSpan, Action)Queues a task after a delay (e.g. setTimeout() or AbortSignal.timeout()), measured with DomEventLoop.TimeProvider. The timers are moved to the task queue once they are due (DomEventLoop.PromoteDueTimers, DomEventLoop.RunUntilIdle). The timers that are due at the same time run in the order they were queued.
RunTask()Runs one task, followed by a microtask checkpoint. Returns false when there is no task. The tasks run in the order they were queued, except the tasks of the schedulers (Scheduler.PostTask, Scheduler.Yield), which run in the order of their priorities: see DomEventLoop.SelectNextSchedulerTaskQueue. When no task is queued, an idle period runs the idle callbacks of the windows (Window.RequestIdleCallback).
RunUntilIdle()Runs the microtasks and the tasks until both queues are empty.
RunUntilIdleAsync(CancellationToken)Runs the microtasks and the tasks until both queues are empty and no asynchronous operation is in progress (e.g. the documents loaded by BrowsingContextOptions.DocumentLoader).
WaitForNextTimerAsync(CancellationToken)Waits until the next timer is due, using DomEventLoop.TimeProvider (e.g. until a fake clock is advanced), and moves it to the task queue. Returns false when there is no timer and no task. For instance, to run the tasks and the timers until there is nothing left: do { await eventLoop.RunUntilIdleAsync(); } while (await eventLoop.WaitForNextTimerAsync());

PerformMicrotaskCheckpoint()

DomEventLoop.cs

https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint

public void PerformMicrotaskCheckpoint()

PromoteDueTimers()

DomEventLoop.cs

Moves the due timers to the task queue. Returns the time until the next timer, or null when there is none. The timers of the workers created by the documents of the event loop are included in the result (they run on the threads of the workers), so that a host that advances a fake clock to the next timer also runs the timers of the workers.

public TimeSpan? PromoteDueTimers()

Returns

TimeSpan?

QueueMicrotask(Action)

DomEventLoop.cs

https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask

public void QueueMicrotask(Action callback)

Parameters

callback Action

QueueTask(Action)

DomEventLoop.cs

Queues a task (https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task).

public void QueueTask(Action callback)

Parameters

callback Action

QueueTimer(TimeSpan, Action)

DomEventLoop.cs

Queues a task after a delay (e.g. setTimeout() or AbortSignal.timeout()), measured with DomEventLoop.TimeProvider. The timers are moved to the task queue once they are due (DomEventLoop.PromoteDueTimers, DomEventLoop.RunUntilIdle). The timers that are due at the same time run in the order they were queued.

public void QueueTimer(TimeSpan delay, Action callback)

Parameters

delay TimeSpan
callback Action

Runs one task, followed by a microtask checkpoint. Returns false when there is no task. The tasks run in the order they were queued, except the tasks of the schedulers (Scheduler.PostTask, Scheduler.Yield), which run in the order of their priorities: see DomEventLoop.SelectNextSchedulerTaskQueue. When no task is queued, an idle period runs the idle callbacks of the windows (Window.RequestIdleCallback).

public bool RunTask()

Returns

bool

RunUntilIdle()

DomEventLoop.cs

Runs the microtasks and the tasks until both queues are empty.

public void RunUntilIdle()

RunUntilIdleAsync(CancellationToken)

DomEventLoop.cs

Runs the microtasks and the tasks until both queues are empty and no asynchronous operation is in progress (e.g. the documents loaded by BrowsingContextOptions.DocumentLoader).

net10.0

public Task RunUntilIdleAsync(CancellationToken cancellationToken = default)

net11.0

public Task RunUntilIdleAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

Task

WaitForNextTimerAsync(CancellationToken)

DomEventLoop.cs

Waits until the next timer is due, using DomEventLoop.TimeProvider (e.g. until a fake clock is advanced), and moves it to the task queue. Returns false when there is no timer and no task. For instance, to run the tasks and the timers until there is nothing left: do { await eventLoop.RunUntilIdleAsync(); } while (await eventLoop.WaitForNextTimerAsync());

net10.0

public Task<bool> WaitForNextTimerAsync(CancellationToken cancellationToken = default)

net11.0

public Task<bool> WaitForNextTimerAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

Task<bool>