The ch measurement previously ran only in the main element loop, so ::before/::after/::first-line/::first-letter fell back to the 0.5em approximation for `ch`. Factor "resolve font longhands early + measure the 0 advance" into a shared `resolve_fonts_and_measure_ch` helper and call it from the main cascade, compute_pseudo_styles, and apply_pseudo_declarations (which backs ::first-line/::first-letter). The Pass-3 skip of those longhands now goes through a shared `is_early_font_longhand` predicate. Net: removes the duplicated early-pass logic the main loop carried and closes the pseudo-element gap. text-wrap-balance-before-after-002 draws its text via `content:` generated content; with accurate ch now applied to both the test and reference pseudo-elements, they align within reftest tolerance. This reverts the demote from the previous commit — the failure was pseudo-element ch, not text-wrap:balance as first attributed. WPT 1747 -> 1748, failures=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rust_browser
A modular, experimental web browser engine and desktop shell written in Rust.
This repository is organized as a Cargo workspace with focused crates for HTML/CSS parsing, DOM, style, layout, rendering, networking, and a desktop app shell.
Current Status
rust_browser is under active development. The project prioritizes:
- correctness before performance
- deterministic behavior and testability
- clear crate boundaries for long-term maintainability
Implemented today includes:
- HTML parsing and DOM construction
- CSS parsing, selector matching, and core style computation
- block/inline layout, flexbox support, table support (partial)
- display-list generation and CPU rasterization path
- local file and HTTP loading
- golden tests and WPT-based external conformance harnessing
Workspace Layout
Top-level crates in crates/:
app_browser: desktop app binary (app_browser)browser_runtime: navigation/session/runtime orchestrationweb_api: browser-facing API surfacejs,js_vm,js_parser: JavaScript stackdom,html,css,selectors,style: document/style pipelinelayout,display_list,render,graphics: layout and rendering pipelinenet,storage,image,fonts: resource and media subsystemsplatform: platform integrationshared: shared types/utilities
See docs/browser_project_structure_modularization_guide.md for dependency layering and crate ownership rules.
Prerequisites
- Rust toolchain from
rust-toolchain.toml(currentlystable) justcommand runner
Install just if needed:
cargo install just
Build
cargo build -p app_browser
Run
Show CLI help:
cargo run -p app_browser -- --help
Open a URL in windowed mode:
cargo run -p app_browser -- https://example.com
Render an input file/URL to layout and display-list dumps:
cargo run -p app_browser -- --render tests/goldens/fixtures/001-empty.html
Render and emit PNG:
cargo run -p app_browser -- --render tests/goldens/fixtures/001-empty.html --png
Execute JavaScript from a file:
cargo run -p app_browser -- --js script.js
Execute JavaScript from stdin (useful for quick debugging):
echo 'console.log(1 + 2)' | cargo run -p app_browser -- --js
Pipeline Overview
The browser pipeline is intentionally staged and deterministic:
browser_runtimereceives a navigation request and tracks lifecycle/history state.netloads content (HTTP or file) and returns response bytes.htmlparses markup into adomdocument tree.cssparses stylesheets andselectorsmatches rules to DOM nodes.stylecomputes final values (UA + author + inline cascade).layoutbuilds and resolves the layout tree (box geometry/flow).display_listconverts layout output into backend-agnostic draw commands.renderrasterizes draw commands to pixels, andplatformpresents them in a window.
In --render mode, steps 3-7 are written to artifact dumps (.layout.txt and .dl.txt) to make regressions easy to diff and review in tests.
Development Commands
Primary workflow commands are defined in justfile:
just fmt: check formattingjust lint: run clippy (warnings denied)just test: run workspace tests + WPT manifest expectation testjust policy: enforce unsafe/dependency/file-size policy checksjust metrics: report project metricsjust ci: run full local CI pipeline (fmt,lint,test,policy,metrics)just regen-wpt: regenerate expected WPT outputsjust import-wpt ...: import WPT reftests into fixture formjust wpt-status ...: summarize WPT status
Testing Strategy
Testing combines multiple layers:
- unit tests in crate source modules
- integration tests in
tests/ - golden rendering regression tests (
tests/goldens) - external conformance fixtures and WPT harnessing (
tests/external/wpt)
Details: docs/browser_testing_strategy_high_level_to_detailed.md.
Architecture Notes
Initial architecture is deliberately conservative:
- interpreter-first semantics
- deterministic single-threaded core pipeline
- worker threads for I/O-oriented work
- display-list abstraction between layout/paint and rendering backend
Details: docs/browser_architecture_initial_exploration.md.
Contributing
General expectations in this repo:
- keep crate boundaries clean (no cross-layer leaks)
- avoid introducing
unsafeoutside approved crates - add regression tests for bug fixes
- run
just cibefore sending changes