Most developers view web browsers as monolithic black boxes maintained exclusively by trillion-dollar tech giants (Google, Apple, Mozilla). But building a browser engine from first principles in Rust is one of the most intellectually rewarding engineering challenges in computer science.

PronBrow Engine is our pure-Rust web engine spanning over 33,000 lines of code, implementing an HTML5 parser, CSS3 cascade, box model layout, and a custom JavaScript execution runtime with 100% compliance across 1,200 ES2025 features.

1. The Subsystem Architecture

A modern browser engine is a pipeline transforming raw network bytes into rendered screen pixels.

graph TD
    Network["Network Subsystem<br/>(HTTP/2, Fetch, TLS, Cookies)"] --> Stream["Byte Stream"]
    Stream --> HTMLParser["HTML5 Parser<br/>(Tokenization & DOM Tree Builder)"]
    Stream --> CSSParser["CSS3 Parser<br/>(Selectors & Cascade Resolver)"]
    HTMLParser --> DOM["DOM Level 4 Tree"]
    CSSParser --> StyleTree["Style Tree (Computed Styles)"]
    DOM --> Layout["Layout Engine<br/>(Box Model, Flexbox, Float)"]
    StyleTree --> Layout
    Layout --> Render["Paint & Rasterizer<br/>(Canvas 2D, TrueType Text)"]
    JS["JavaScript Runtime<br/>(Microtask Queue, Event Loop)"] <--> DOM

2. The HTML5 Tokenizer & Tree Construction

HTML cannot be parsed with standard LL(k) or LR(k) context-free grammar parsers because the HTML5 specification requires forgiving, state-dependent error recovery.

We structured the parser into two distinct stages:

  1. Stateful Tokenizer: Consumes raw UTF-8 characters and emits StartTag, EndTag, Character, Comment, and Doctype tokens.
  2. Tree Builder: Maintains an open element stack and handles malformed markup (e.g. unclosed <p> tags, missing <tbody>, misplaced <li>).
pub enum Token {
    Doctype { name: String, public_id: Option<String>, system_id: Option<String> },
    StartTag { tag_name: String, attributes: HashMap<String, String>, self_closing: bool },
    EndTag { tag_name: String },
    Character(char),
    Comment(String),
    EndOfFile,
}

3. CSS Selector Matching & The Cascade

The CSS engine computes specificity tuples (inline, ids, classes/attributes, elements) and resolves cascading inheritance:

  • Universal & Type Selectors: div, span, *
  • Class & ID Selectors: .nav-bar, #main-content
  • Combinators: Child (>), Descendant ( ), Adjacent Sibling (+)
  • Computed Value Resolution: Resolving relative units (em, rem, vh, %) into absolute device-pixel floating-point bounds.

4. Box Model & Flexbox Layout Engine

Once styles are computed, the Layout Engine constructs a Render Tree where non-rendered nodes (display: none, <head>, <script>) are omitted.

For Flexbox:

  1. Determine the main axis and cross axis (flex-direction).
  2. Collect flex items into flex lines based on flex-wrap.
  3. Resolve flexible lengths using flex-grow, flex-shrink, and flex-basis.
  4. Align items along the main axis (justify-content) and cross axis (align-items).

5. The JavaScript Engine (1,200 ES2025 Features)

Rather than embedding V8, we engineered a dedicated execution runtime implementing:

  • Async/Await & Microtasks: Program-counter (PC) based state suspension across yield/await boundaries.
  • Generators & Iterators: First-class support for function* with bi-directional value passing.
  • Modern Operators: Optional chaining (?.), nullish coalescing (??), and logical assignments (||=, &&=, ??=).

PronBrow Engine demonstrates that when you break massive software down into strict invariants, even a browser engine can be mastered from scratch.