Expand description

Implements parallel traversal over the DOM tree.

This traversal is based on Rayon, and therefore its safety is largely verified by the type system.

The primary trickiness and fine print for the above relates to the thread safety of the DOM nodes themselves. Accessing a DOM element concurrently on multiple threads is actually mostly “safe”, since all the mutable state is protected by an AtomicRefCell, and so we’ll generally panic if something goes wrong. Still, we try to to enforce our thread invariants at compile time whenever possible. As such, TNode and TElement are not Send, so ordinary style system code cannot accidentally share them with other threads. In the parallel traversal, we explicitly invoke |unsafe { SendNode::new(n) }| to put nodes in containers that may be sent to other threads. This occurs in only a handful of places and is easy to grep for. At the time of this writing, there is no other unsafe code in the parallel traversal.


Controls whether traverse_nodes may make a recursive call to continue doing work, or whether it should always dispatch work asynchronously.


The stack margin. If we get this deep in the stack, we will skip recursive optimizations to ensure that there is sufficient room for non-recursive work.

The minimum stack size for a thread in the styling pool, in kilobytes.

The maximum number of child nodes that we will process as a single unit.


A callback to create our thread local context. This needs to be out of line so we don’t allocate stack space for the entire struct in the caller.

A parallel top-down DOM traversal.

Enqueues |nodes| for processing, possibly on this thread if the tail call conditions are met.

Type Definitions

WorkUnit 🔒

A set of nodes, sized to the work unit. This gets copied when sent to other threads, so we keep it compact.