Jesse A. Green / notebook

Ladybird Browser — Administrator & Developer Guide

Generated May 2026 from LadybirdBrowser/ladybird at de7ed9a

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Architecture Overview

Ladybird is an independent web browser built from scratch in C++ (with Rust components for parsing, regex, and Unicode), using custom implementations for every layer of the browser stack: HTML parsing, CSS layout, JavaScript execution, networking, image decoding, and graphics rendering. It originated from the SerenityOS project and is licensed BSD-2-Clause.

The browser employs a multi-process architecture where the UI process orchestrates specialized child processes for web content rendering, network I/O, image decoding, and Web Workers. Inter-process communication uses a custom IPC framework with Unix domain sockets (or Mach ports on macOS).

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│                       UI Process                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                  │
│  │ Qt 6 UI  │  │ GTK 4 UI │  │AppKit UI │  (one per build) │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘                  │
│       └──────────────┼──────────────┘                        │
│                      ▼                                       │
│              LibWebView::Application                         │
│     (Settings, Bookmarks, CookieJar, HistoryStore)          │
│                      │                                       │
│    ┌─────────────────┼─────────────────┐                    │
│    ▼                 ▼                 ▼                     │
│  ViewImpl ──IPC── ViewImpl ──IPC── ViewImpl   (per tab)     │
└────┬─────────────────┬─────────────────┬────────────────────┘
     │ IPC             │ IPC             │ IPC
     ▼                 ▼                 ▼
┌──────────┐   ┌──────────┐     ┌──────────┐
│WebContent│   │WebContent│     │WebContent│  (one per tab/site)
│ Process  │   │ Process  │     │ Process  │
│  LibWeb  │   │  LibWeb  │     │  LibWeb  │
│  LibJS   │   │  LibJS   │     │  LibJS   │
│  LibGfx  │   │  LibGfx  │     │  LibGfx  │
└────┬─────┘   └────┬─────┘     └────┬─────┘
     │              │                 │
     └──────────────┼─────────────────┘
                    │ IPC
        ┌───────────┼───────────┐
        ▼           ▼           ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Request  │ │  Image   │ │   Web    │
│  Server  │ │ Decoder  │ │  Worker  │
│ (curl)   │ │ (codecs) │ │ (JS VM)  │
└──────────┘ └──────────┘ └──────────┘

Component Inventory

Component Path Role
UI Process UI/Qt/, UI/Gtk/, UI/AppKit/ Window management, tabs, user interaction
LibWebView Libraries/LibWebView/ Browser framework: settings, bookmarks, cookies, history, process management
WebContent Services/WebContent/ Page rendering, DOM, CSS, JS execution, painting
RequestServer Services/RequestServer/ All network I/O (HTTP/HTTPS, WebSocket, DNS) via libcurl
ImageDecoder Services/ImageDecoder/ Image format decoding in isolated process
WebWorker Services/WebWorker/ Web Worker (dedicated + shared) execution
WebDriver Services/WebDriver/ W3C WebDriver protocol server
LibJS Libraries/LibJS/ ECMAScript engine (Rust parser + C++ bytecode VM)
LibWeb Libraries/LibWeb/ Web platform: DOM, CSS, HTML, Layout, Painting, Fetch
LibGfx Libraries/LibGfx/ Graphics primitives, image codecs, fonts, color profiles
LibCore Libraries/LibCore/ Cross-platform OS abstraction (event loop, sockets, files, timers)
LibIPC Libraries/LibIPC/ Inter-process communication framework
LibGC Libraries/LibGC/ Garbage collector for JS heap
LibDNS Libraries/LibDNS/ DNS resolver with DNSSEC support
LibCrypto Libraries/LibCrypto/ ASN.1, X.509, cryptographic primitives
LibTLS Libraries/LibTLS/ TLS 1.2 implementation
AK AK/ Foundation library: strings, containers, smart pointers, utilities

Technology Stack

Layer Technology
Language C++23 (primary), Rust 2024 edition (parser, regex, unicode, gfx helpers)
Build CMake 3.30+ with presets, vcpkg for dependencies, Ninja backend
Rendering Skia (v144) with Vulkan (Linux/Windows/FreeBSD) or Metal (macOS)
Networking libcurl (HTTP/1.1, HTTP/2, HTTP/3, WebSocket, brotli, zstd)
Media FFmpeg 7.1.1 (H.264, VP8/9, AV1, Opus, Vorbis, WebP, Theora)
Fonts HarfBuzz 10.2.0 (with ICU), fontconfig, freetype
Images libjpeg-turbo, libpng (APNG), libjxl, libavif, libwebp, TIFF
Text ICU 78.2, simdjson 4.2.4, simdutf 7.4.0
Crypto OpenSSL 3.5.3
Database SQLite 3.52.0
Allocator mimalloc 2.2.7
UI Qt 6.10.0, GTK 4 + libadwaita 1.8.4, AppKit (macOS native)
Debugging cpptrace, libdwarf

Data Flow: Page Load

  1. User enters URL in address bar → UI process sends load_url() via IPC to WebContent
  2. WebContent's ResourceLoader sends fetch request via IPC to RequestServer
  3. RequestServer resolves DNS (via Resolver::default_resolver() or custom DNS-over-TLS), performs HTTP request via curl_multi
  4. Response data streams back to WebContent via IPC
  5. WebContent parses HTML (LibWeb), constructs DOM, resolves CSS, runs JavaScript (LibJS)
  6. Image resources are dispatched to ImageDecoder processes for parallel decoding
  7. Layout tree is computed, display list generated, painting occurs via Skia
  8. Rendered bitmap is shared with UI process via anonymous shared memory buffers
  9. UI process composites and displays the result

2. System Requirements

Hardware

Resource Minimum Recommended
CPU x86_64 or AArch64, 2 cores 4+ cores
RAM 4 GB runtime, 8 GB build 16 GB (build + browsing)
Disk 10 GB (source + build + vcpkg) 20 GB
GPU Vulkan 1.0+ or Metal-capable Vulkan 1.2+ / Apple Silicon

Software

Dependency Required Version
C++ Compiler Clang 18+ or GCC 14+ (C++23 support)
CMake 3.30.0+
Rust 1.95.0 (pinned via rust-toolchain.toml)
Python 3.8+
Ninja 1.11+ (recommended)
Git 2.25+
pkg-config Any recent version

Platform-Specific Requirements

Platform Graphics Additional
Linux Vulkan drivers, fontconfig, freetype, harfbuzz D-Bus (for GTK), nasm, autoconf, automake, libtool
macOS Metal (automatic) Xcode Command Line Tools, nasm, autoconf, automake, libtool
Windows Vulkan drivers, freetype Visual Studio 2022 (C++ workload)
FreeBSD Vulkan drivers, fontconfig, freetype, harfbuzz nasm, autoconf, automake, libtool
Android Vulkan Android SDK/NDK (experimental)

Note

The Rust toolchain is automatically managed via rust-toolchain.toml. Components rustfmt and clippy are included. Code style: 120 max line width, 4-space tabs, Rust 2024 edition.


3. Configuration Reference

CMake Build Presets

Defined in CMakePresets.json (version 9 format, requires CMake 3.30+):

Preset Type Description
Release Build Optimized production build
Debug Build Debug symbols, no optimization
Sanitizer Build AddressSanitizer + UBSan (Unix only)

Platform-specific presets are included dynamically from Meta/CMake/presets/CMake${hostSystemName}Presets.json.

Environment Variables

Variable Type Default Description Used By
LADYBIRD_SOURCE_DIR string (auto-set by test presets) Path to the Ladybird source tree Test runner
MAKEJOBS int CPU count Number of parallel build jobs Meta/ladybird.py
BUILD_PRESET string Release Default CMake build preset Meta/ladybird.py
CC string (auto-detect) C compiler path Build system
CXX string (auto-detect) C++ compiler path Build system
ASAN_OPTIONS string strict_string_checks=1:check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=1:allocator_may_return_null=1 ASan configuration Sanitizer preset
UBSAN_OPTIONS string print_stacktrace=1:print_summary=1:halt_on_error=1 UBSan configuration Sanitizer preset

Important

The Sanitizer preset's ASAN_OPTIONS enables detect_stack_use_after_return=1, which significantly increases memory usage. Allocate at least 16 GB RAM when running sanitizer builds.

Complete CLI Flag Reference

All flags accepted by the Ladybird binary (from LibWebView::Application):

Positional arguments:

Argument Description
url One or more URLs to open (optional)

General options:

Flag Type Default Description
--new-window / -n bool false Force opening in a new window
--force-new-process bool false Start new process (disable SQL, partition cache)
--allow-popups bool false Disable popup blocking
--disable-scripting bool false Disable JavaScript
--disable-sql-database bool false Disable SQLite database
--tuple-file-origins bool false Treat file:// URLs as tuple origins
--default-time-zone string — Override default time zone (e.g., America/New_York)
--certificate / -C path — Path to additional certificate file
--user-agent-preset string — Named User-Agent string preset
--resource-map path — JSON file mapping URLs to local files

Rendering options:

Flag Type Default Description
--force-cpu-painting bool false Use Skia CPU backend instead of GPU
--force-fontconfig bool false Force fontconfig for font loading
--disable-scrollbar-painting bool false Don't paint viewport scrollbars

Network options:

Flag Type Default Description
--dns-server string — Custom DNS server address
--dns-port int 53 (853 with --dot) DNS server port
--dot bool false Use DNS over TLS
--dnssec bool false Validate DNSSEC locally
--disable-http-memory-cache bool false Disable HTTP memory cache
--disable-http-disk-cache bool false Disable HTTP disk cache
--disable-content-filter bool false Disable content filter

Headless mode:

Flag Type Default Description
--headless string screenshot Headless mode: screenshot, layout-tree, text, manual
--screenshot-delay int 0 Seconds to wait before screenshot capture
--window-width int 800 Viewport width in pixels
--window-height int 600 Viewport height in pixels

Developer / debug options:

Flag Type Default Description
--devtools int default port Enable Firefox DevTools protocol server
--debug-process string — Wait for debugger to attach to named process
--profile-process string — Enable callgrind profiling for named process
--test-mode bool false Enable test mode (experimental interfaces, internals, CPU painting)
--log-all-js-exceptions bool false Log all JavaScript exceptions to console
--disable-site-isolation bool false Disable site isolation
--enable-idl-tracing bool false Enable Web IDL call tracing
--expose-experimental-interfaces bool false Expose experimental Web API interfaces
--expose-internals-object bool false Expose internals object for testing
--enable-autoplay bool false Enable multimedia autoplay
--collect-garbage-on-every-allocation / -g bool false Force GC after every JS heap allocation

WebDriver options:

Flag Type Description
--webdriver-content-path path WebDriver IPC socket path (non-macOS)
--webdriver-mach-server-name string WebDriver Mach server name (macOS only)

about:settings WebUI Message Protocol

The settings page communicates with the browser via a WebUI messaging protocol:

Message Direction Data
loadSettings page → browser Request current settings
setBrowsingBehavior page → browser { autoscroll: bool }
setDefaultZoomLevelFactor page → browser { factor: float }
setLanguages page → browser { languages: string[] }
setDNSSettings page → browser { type, server, port, dnssec }
setNewTabPageURL page → browser { url: string }
setSiteSettingEnabledGlobally page → browser { setting, enabled }
addSiteSettingFilter page → browser { setting, site, value }
removeSiteSettingFilter page → browser { setting, site }
removeAllSiteSettingFilters page → browser { setting }
setGlobalPrivacyControl page → browser { enabled: bool }
setBrowsingDataSettings page → browser { maxCacheSize }
clearBrowsingData page → browser { types[], timeRange }
estimateBrowsingDataSizes page → browser Request size estimates
setSearchEngine page → browser { engine: string }
setAutocompleteEngine page → browser { engine: string }
addCustomSearchEngine page → browser { name, url }
removeCustomSearchEngine page → browser { name }
loadAvailableEngines page → browser Request engine list
loadForciblyEnabledSiteSettings page → browser Request CLI-forced settings

4. Deployment & Scaling

Build Configurations

Production (Release):

python3 Meta/ladybird.py build --preset Release

Produces optimized binaries with full LTO in the distribution Cargo profile. Rust libraries are built with panic = "abort", codegen-units = 1, and full LTO.

Debug:

python3 Meta/ladybird.py build --preset Debug

Includes debug symbols, assertions enabled, no optimization.

Sanitizer:

python3 Meta/ladybird.py build --preset Sanitizer

Caution

Sanitizer builds have 2-5x memory overhead and significant performance impact. Use for testing only, not production deployment.

vcpkg Dependency Management

All third-party dependencies are managed via vcpkg.json with pinned versions. Key dependencies and their versions:

Dependency Version Purpose
Skia 144 2D graphics rendering
curl 8.19.0 HTTP client (HTTP/2, HTTP/3, WebSocket)
FFmpeg 7.1.1 Media decoding
Qt 6.10.0 UI toolkit (optional)
libadwaita 1.8.4 GTK UI toolkit (optional)
HarfBuzz 10.2.0 Text shaping
ICU 78.2 Internationalization
OpenSSL 3.5.3 TLS/crypto
SQLite 3.52.0 Database storage
mimalloc 2.2.7 Memory allocator
simdjson 4.2.4 Fast JSON parsing
simdutf 7.4.0 Fast Unicode validation
SDL3 3.2.28 Cross-platform multimedia

vcpkg overlay ports live in Meta/CMake/vcpkg/overlay-ports/ for customized builds (ANGLE, curl, Skia, etc.).

Flatpak Packaging

After changing Rust dependencies, regenerate Flatpak sources:

python3 Meta/CMake/flatpak/generate-cargo-sources.py

Resource Limits

Ladybird automatically increases RLIMIT_NOFILE to 8192 on startup (non-Windows). This is required for the multi-process architecture's IPC socket usage. In containerized environments, ensure this limit is configurable.


5. Operations

Process Management

Each tab spawns a dedicated WebContent process. The UI process manages process lifecycles:

  • WebContent processes — one per tab (or per site with site isolation). Spawned via launch_web_content_process(). Spare processes can be pre-launched with launch_spare_web_content_process().
  • RequestServer — shared network process. New clients connect via connect_new_request_server_client().
  • ImageDecoder — shared image decoding process with multi-client support via connect_new_clients(count).
  • WebWorker — spawned per Web Worker (dedicated or shared).

Tip

Use --debug-process WebContent to pause a WebContent process at startup and attach a debugger. This is invaluable for diagnosing rendering bugs.

Disk Cache

RequestServer maintains an HTTP disk cache at {cache_dir}/Ladybird/:

File Purpose
alt-svc-cache.txt HTTP Alt-Svc header cache
HTTP disk cache files Cached HTTP responses

Cache behavior is controlled by:

  • --disable-http-disk-cache — disable entirely
  • --force-new-process — enables partitioned disk caching (HTTPDiskCacheMode::Partitioned)
  • about:settings → Privacy → disk cache size configuration

Note

When --force-new-process is used, the SQL database is disabled and disk caching switches to partitioned mode to prevent data leakage between instances.

Monitoring

Ladybird does not expose a metrics endpoint. Monitor process health via:

  • Process table: check for WebContent, RequestServer, ImageDecoder, WebWorker processes
  • File descriptor usage: ls /proc/<pid>/fd | wc -l
  • Memory: each WebContent process runs an independent JS heap with garbage collection

Debug Requests

WebContent processes support debug introspection via debug_request(page_id, request, argument):

Request Description
dump-dom-tree Print DOM tree to stdout
dump-layout-tree Print layout tree
dump-paint-tree Print paint tree
dump-stacking-context-tree Print stacking context hierarchy
dump-style-sheets Print all loaded CSS style sheets
dump-all-resolved-styles Print computed styles for all elements
dump-all-css-errors Print CSS parsing errors
dump-display-list Print the display list
dump-session-history Print navigation session history
collect-garbage Trigger deferred garbage collection
set-line-box-borders Toggle line box border visualization

6. Performance

Rendering Pipeline

  1. DOM Construction — HTML is parsed into a DOM tree
  2. Style Resolution — CSS rules are matched and computed properties calculated (StyleComputer)
  3. Layout — box tree construction, formatting contexts (block, inline, flex, grid)
  4. Painting — display list generation, stacking context ordering
  5. Compositing — Skia renders the display list to a GPU (Vulkan/Metal) or CPU bitmap
  6. Transfer — rendered bitmap shared with UI process via anonymous shared memory (AnonymousBuffer)

Input Event Coalescing

WebContent implements mouse event coalescing: consecutive mousemove and wheel events are merged when the pipeline is busy, reducing IPC overhead and improving responsiveness.

JavaScript Performance

LibJS uses a three-tier execution strategy:

  1. Rust Parser — tokenizes and parses source into AST
  2. Bytecode Compiler — generates bytecode from AST
  3. AsmIntGen Interpreter — assembly-level threaded-dispatch interpreter for x86_64 and AArch64

The AsmIntGen interpreter maps bytecode opcodes to native assembly handlers via a 256-entry dispatch table. Five registers are pinned to callee-saved hardware registers for performance:

Register Purpose
pc Program counter (byte offset into bytecode)
pb Bytecode base pointer
values Pointer to Value[] array
exec_ctx Running ExecutionContext pointer
dispatch Dispatch table base pointer

NaN-boxing is used for JS values: the upper 16 bits encode the value type tag, allowing efficient type checks and unboxing.

Image Decoding

ImageDecoder uses streaming decoding for animated images with a batch size of 4 frames, keeping the decoder alive via AnimationSession for future frame requests. This avoids re-parsing the entire image for each frame.

Tip

For debugging rendering performance, use --force-cpu-painting to bypass GPU acceleration and isolate whether performance issues are in the rendering pipeline or GPU driver.


7. Security

Process Isolation

Each WebContent process runs in its own address space. Site isolation (enabled by default) ensures that content from different origins runs in separate processes, preventing cross-site data leakage through memory vulnerabilities.

Isolation feature Status
Per-tab process isolation Enabled
Site isolation Enabled (disable with --disable-site-isolation)
Network process isolation Enabled (RequestServer is a separate process)
Image decoder isolation Enabled (ImageDecoder is a separate process)

Warning

Disabling site isolation (--disable-site-isolation) removes a critical security boundary. It is automatically disabled when debugging WebContent processes.

IPC Security

IPC uses Unix domain sockets (Linux/FreeBSD/Windows) or Mach ports (macOS). On macOS, Mach port names are derived from the process name and PID (mach_server_name_for_process("Ladybird", pid)), scoping IPC to the running instance.

Cryptographic Support

LibCrypto supports the following algorithms (from ASN.1 OID constants):

Algorithm OIDs
RSA RSA-MD5, RSA-SHA1, RSA-SHA224, RSA-SHA256, RSA-SHA384, RSA-SHA512
ECDSA ECDSA-SHA224, ECDSA-SHA256, ECDSA-SHA384, ECDSA-SHA512
Curves secp256r1, secp384r1, secp521r1, X25519, X448
EdDSA Ed25519, Ed448
Post-quantum ML-DSA-44, ML-DSA-65, ML-DSA-87, ML-KEM-512, ML-KEM-768, ML-KEM-1024

TLS

LibTLS implements TLS 1.2. OpenSSL 3.5.3 is available via vcpkg for additional TLS support in libcurl.

DNS Security

  • DNS-over-TLS — encrypts DNS queries, configurable via --dot or about:settings
  • DNSSEC — local validation available via --dnssec or about:settings
  • DNS resolution runs in the isolated RequestServer process

Global Privacy Control

When enabled in about:settings, the browser sends Sec-GPC: 1 on all HTTP requests, signaling the user's preference not to have their data sold or shared.

Content Filtering

A content filter (ContentFilter) is available and enabled by default. Disable with --disable-content-filter.

Known Security Issues

GitHub issue #9062 reports a use-after-free read/write via stale TypedArray cached_data_ptr on shared WebAssembly.Memory after multiple grows. This is an active vulnerability in the WebAssembly implementation.

Caution

The UAF in shared WebAssembly.Memory (#9062) could allow memory corruption. Monitor the issue tracker for the fix.


8. Developer Internals

8.1 Repository Structure

ladybird/
├── AK/                        # Foundation library (196 files, 1.3M chars)
│   ├── String.h/cpp           # UTF-8 string types
│   ├── HashMap.h              # Hash map container
│   ├── Vector.h               # Dynamic array
│   ├── Optional.h             # Optional<T> type
│   ├── Error.h                # ErrorOr<T> error handling
│   └── ...                    # Smart pointers, formatting, math, etc.
├── Libraries/
│   ├── LibWeb/                # Web platform (DOM, CSS, HTML, Layout, Painting, Fetch)
│   ├── LibJS/                 # JavaScript engine
│   │   ├── Rust/src/          # Rust parser (lexer, parser, scope collector, AST)
│   │   ├── AsmIntGen/src/     # Assembly interpreter code generator
│   │   ├── BytecodeDef/src/   # Bytecode definition DSL
│   │   └── *.cpp/h            # C++ runtime, builtins, GC integration
│   ├── LibWebView/            # Browser framework (65 files, 473K chars)
│   ├── LibCore/               # OS abstraction (97 files, 395K chars)
│   ├── LibGfx/                # Graphics (93 files, 425K chars)
│   ├── LibIPC/                # IPC framework (37 files, 125K chars)
│   ├── LibGC/                 # Garbage collector (34 files, 105K chars)
│   ├── LibDNS/                # DNS resolver (3 files, 134K chars)
│   ├── LibUnicode/            # ICU integration (40 files, 246K chars)
│   ├── LibCrypto/             # Cryptographic primitives
│   ├── LibTLS/                # TLS 1.2 implementation
│   ├── LibHTTP/               # HTTP cache
│   ├── LibRequests/           # Network request types
│   ├── LibWebSocket/          # WebSocket support
│   ├── LibWasm/               # WebAssembly engine
│   ├── LibLine/               # Terminal line editor (REPL)
│   ├── LibRegex/              # Regular expression engine (with Rust)
│   ├── LibCompress/           # Compression (zlib, brotli, zstd)
│   ├── LibTextCodec/          # Text encoding/decoding
│   ├── LibXML/                # XML parser
│   ├── LibIDL/                # Web IDL parser
│   ├── LibDatabase/           # SQLite wrapper
│   ├── LibDiff/               # Diff algorithm
│   ├── LibSyntax/             # Syntax highlighting
│   ├── LibTest/               # Testing framework
│   ├── LibMedia/              # Media codec integration
│   ├── LibDevTools/           # Firefox DevTools protocol
│   ├── LibImageDecoderClient/ # ImageDecoder IPC client
│   ├── LibFileSystem/         # File system utilities
│   ├── LibThreading/          # Threading primitives
│   ├── LibMain/               # Entry point helpers
│   └── LibURL/                # URL parsing
├── Services/
│   ├── WebContent/            # Page rendering process (18 files, 319K chars)
│   ├── RequestServer/         # Network I/O process (18 files, 93K chars)
│   ├── ImageDecoder/          # Image decoding process (4 files, 16K chars)
│   ├── WebWorker/             # Web Worker process (8 files, 38K chars)
│   └── WebDriver/             # WebDriver server (7 files, 78K chars)
├── UI/
│   ├── Qt/                    # Qt 6 UI (33 files, 231K chars)
│   ├── Gtk/                   # GTK 4 UI (18 files, 115K chars)
│   ├── AppKit/                # macOS native UI
│   ├── Android/               # Android UI (experimental)
│   └── Icons/                 # Application icons
├── Utilities/
│   ├── js.cpp                 # JavaScript REPL
│   ├── dns.cpp                # DNS query tool
│   └── image.cpp              # Image format converter
├── Meta/
│   ├── ladybird.py            # Build script
│   ├── WPT.sh                 # Web Platform Tests runner
│   ├── CMake/                 # CMake modules, vcpkg config
│   ├── Generators/            # Code generators (Python)
│   ├── Linters/               # Code linters
│   ├── Lagom/                 # Lagom build framework
│   └── Utils/                 # Build utilities
├── Tests/                     # Test suites per library
├── Base/res/                  # Resources (icons, about pages, templates, fonts)
├── Documentation/             # Build instructions, coding style, architecture docs
├── CMakePresets.json          # Build presets
├── Cargo.toml                 # Rust workspace
├── rust-toolchain.toml        # Pinned Rust version (1.95.0)
├── vcpkg.json                 # Dependency manifest
└── .pre-commit-config.yaml    # Pre-commit hooks

8.2 AK Foundation Library

AK (formerly "AK" from SerenityOS) provides the foundational types used throughout the codebase:

String types:

Type Encoding Allocation Use case
String UTF-8 Heap General-purpose strings
ByteString raw bytes Heap Binary data, legacy code
FlyString UTF-8 Interned Frequently-compared strings
StringView UTF-8 Borrowed Non-owning reference
Utf16String UTF-16 Heap JavaScript string storage
Utf16FlyString UTF-16 Interned JavaScript interned strings

Smart pointers:

Type Semantics
NonnullRefPtr<T> Non-null reference-counted
RefPtr<T> Nullable reference-counted
NonnullOwnPtr<T> Non-null unique ownership
OwnPtr<T> Nullable unique ownership
GC::Root<T> GC root preventing collection
GC::Ref<T> GC-managed reference

Containers: Vector<T>, HashMap<K,V>, HashTable<T>, Array<T,N>, Queue<T>, CircularBuffer, SinglyLinkedList<T>.

Error handling: ErrorOr<T> return type with TRY() macro for propagation. ThrowCompletionOr<Value> for JS-visible errors.

8.3 IPC Framework

All inter-process communication is built on IPC::ConnectionFromClient<ClientEndpoint, ServerEndpoint>:

  1. Endpoint IDL files define the message protocol (serialization code generated at build time)
  2. Transport layer uses Unix domain sockets (Linux/FreeBSD/Windows) or Mach ports (macOS)
  3. Connection lifecycle: UI process spawns child, establishes IPC transport, passes handles for cross-service connections
UI Process
  │
  ├── IPC::Transport ──→ WebContent (per tab)
  │     │
  │     ├── passes IPC handle ──→ RequestServer
  │     └── passes IPC handle ──→ ImageDecoder
  │
  └── IPC::Transport ──→ WebDriver

On macOS, IPC::MachBootstrapListener and IPC::TransportBootstrapMach handle Mach port bootstrapping. The server name format is Ladybird-<pid>.

8.4 Event Loop Architecture

Each UI backend provides its own event loop bridge:

Backend EventLoop Implementation Native Loop
Qt EventLoopImplementationQt / EventLoopManagerQt QApplication::exec()
GTK EventLoopImplementationGtk / EventLoopManagerGtk GLib main loop
AppKit AppKit run loop NSRunLoop

These bridge Core::EventLoop (the platform-agnostic event loop) to the native toolkit's event loop, enabling timers, socket notifications, and deferred invocations to work seamlessly across UI backends.

8.5 Garbage Collection

LibGC implements a mark-and-sweep garbage collector for the JavaScript heap:

  • GC::Heap — manages allocations
  • GC_DEFINE_ALLOCATOR macro — declares allocator for a GC-managed type
  • GC::Root<T> — prevents an object from being collected
  • GC::RootVector<T> — a vector of GC roots
  • visit_edges() method — each GC-managed object implements this to mark reachable references

The --collect-garbage-on-every-allocation / -g flag triggers GC after every allocation, useful for detecting GC-related bugs.

8.6 LibJS Engine Architecture

Parser (Rust):

  • Lexer (lexer.rs) — tokenizer with save/restore state, regex disambiguation
  • Parser (parser.rs) — parse_program(starts_in_strict_mode) returns AST
  • ScopeCollector (scope_collector.rs) — variable binding analysis with scope types: program, function, block, for-loop, with, catch, static-init, class-field, class-declaration
  • AST (ast.rs) — comprehensive node types for all ECMAScript constructs
  • FFI: rust_tokenize() provides token stream to C++ (used by REPL syntax highlighting)

Bytecode Compiler (C++): Compiles AST to a bytecode format defined in Libraries/LibJS/BytecodeDef/:

  • Opcodes are defined in a DSL (Bytecode.def)
  • generate_libjs_bytecode_def_derived.py generates C++ from the definition
  • Fields include operand types, sizes, and layout information

AsmIntGen (Rust → Assembly): Compiles a platform-neutral DSL (asmint.asm) into native assembly for the bytecode interpreter's hot loop:

  • Targets: x86_64 (codegen_x86_64.rs) and AArch64 (codegen_aarch64.rs)
  • 256-entry dispatch table maps opcodes to handler addresses
  • Threaded dispatch: each handler executes one instruction, reads next opcode, jumps through table
  • C++ interop: call_slow_path (terminal), call_helper (non-terminal), call_interp (non-terminal), call_raw_native (indirect function pointer)
  • NaN-boxing operations: extract_tag, unbox_int32, unbox_object, box_int32, box_int32_clean
  • 32-bit overflow-checked arithmetic: add32_overflow, sub32_overflow, mul32_overflow, neg32_overflow

Console implementation follows the WHATWG Console spec: assert_, clear, debug, error, info, log, table, trace, warn, dir, count, countReset, group, groupCollapsed, groupEnd, time, timeLog, timeEnd.

8.7 LibWeb Architecture

LibWeb implements the web platform across multiple namespaces:

Namespace Subsystem Key Classes
Web::DOM Document Object Model Document, Element, Text, ShadowRoot, Attr, ParentNode
Web::CSS Cascading Style Sheets StyleComputer, CSSStyleSheet, ComputedProperties, PropertyID
Web::HTML HTML elements & APIs Window, BrowsingContext, TraversableNavigable, Storage
Web::Layout Box model & formatting Viewport, BlockContainer, InlineNode, FormattingContext
Web::Painting Rendering pipeline PaintableBox, ViewportPaintable, StackingContext
Web::Fetch Fetch API Fetching
Web::WebDriver WebDriver protocol Client, Session
Web::IndexedDB IndexedDB storage Internal implementation
Web::Editing Content editing Internal editing commands

8.8 Code Generation Pipeline

Ladybird uses extensive code generation for Web API bindings and browser internals:

Python generators (Meta/Generators/):

Generator Input Output
generate_ipc_definitions.py IPC endpoint .ipc files C++ serialization/deserialization code
generate_dom_tree.py HTML templates C++ static DOM tree builders
embed_as_string.py Any file C++ raw string literal variable
generate_encoding_indexes.py JSON encoding data C++ encoding lookup tables
generate_public_suffix_data.py Public suffix list C++ public suffix lookup
generate_libwasm_spec_test.py Wasm spec test JSON C++ test cases
libjs_bytecode_def.py Bytecode.def C++ bytecode definitions

C++ generators (Meta/Lagom/Tools/CodeGenerators/LibWeb/):

Generator Purpose
GenerateCSSPropertyID CSS property enum and metadata
GenerateCSSEnums CSS enum types
GenerateCSSKeyword CSS keyword definitions
GenerateCSSPseudoClass CSS pseudo-class handling
GenerateCSSPseudoElement CSS pseudo-element handling
GenerateCSSDescriptors CSS descriptor definitions
GenerateCSSUnits CSS unit types
GenerateCSSTransformFunctions CSS transform functions
GenerateCSSMathFunctions CSS math functions
GenerateCSSStyleProperties CSS style property accessors
GenerateCSSMediaFeatureID CSS media feature IDs
GenerateCSSNumericFactoryMethods CSS numeric type factories
GenerateCSSEnvironmentVariable CSS env() variable support
GenerateAriaRoles ARIA role definitions
GenerateNamedCharacterReferences HTML named character references
GenerateWindowOrWorkerInterfaces Web IDL interface registration
BindingsGenerator Web IDL → C++ binding code

8.9 Testing Infrastructure

Test suites per library:

Suite Framework Files
Tests/AK/ LibTest 87 files, 838K chars
Tests/LibJS/ LibTest + custom runners JS runtime, AST, bytecode tests
Tests/LibWeb/ LibTest + WPT Layout, text, ref, crash tests
Tests/LibCore/ LibTest 12 files
Tests/LibCrypto/ LibTest 16 files, 247K chars
Tests/LibGfx/ LibTest Image codec tests
Tests/LibRegex/ LibTest 1 file, 26K chars
Tests/LibURL/ LibTest 4 files, 41K chars
Tests/LibUnicode/ LibTest 7 files
Tests/LibWasm/ LibTest Wasm spec tests
Tests/LibIPC/ LibTest IPC serialization tests
Tests/LibDNS/ LibTest DNS resolver tests
Tests/LibTLS/ LibTest TLS protocol tests
Tests/LibDatabase/ LibTest SQLite wrapper tests
Tests/LibCompress/ LibTest Compression tests
Tests/LibHTTP/ LibTest HTTP cache tests
Tests/LibWebView/ LibTest Browser framework tests
Tests/ClangPlugins/ lit (LLVM) Clang plugin tests

LibTest framework features:

  • RANDOMIZED_TEST_CASE — property-based testing with automatic shrinking
  • Generator combinators: Gen::unsigned_int(max), Gen::vector(min, max, gen)
  • ASSUME(predicate) — reject invalid test inputs
  • Automatic shrinking to minimal failing example

Web Platform Tests (Meta/WPT.sh):

Command Description
./Meta/WPT.sh update Clone/update WPT repository
./Meta/WPT.sh run [tests] Run tests (auto-builds Ladybird + WebDriver)
./Meta/WPT.sh compare <log> [tests] Run and compare against baseline
./Meta/WPT.sh import [paths] Import tests from wpt.live
./Meta/WPT.sh list-tests [paths] List available tests
./Meta/WPT.sh clean Cleanup overlayfs mounts and network namespaces
./Meta/WPT.sh bisect <bad> <good> [tests] Git bisect for test regressions

WPT execution options: --show-window, --debug-process <name>, --parallel-instances <N>, various log formats (raw, xunit, html, mach, wptreport, wptscreenshot, chromium).

Linux parallel execution uses network namespaces (ip netns) with overlayfs for per-instance WPT directories.

Running tests:

# Run all tests
python3 Meta/ladybird.py test

# Run specific test binary
./Build/Release/bin/TestLibJS

# Run WPT tests
./Meta/WPT.sh run css/css-flexbox/

Note

Test presets automatically set LADYBIRD_SOURCE_DIR and sanitizer environment variables. Always use test presets rather than running test binaries directly to ensure proper configuration.

8.10 Utility Programs

js — JavaScript REPL and script runner (Utilities/js.cpp):

Feature Details
Interactive REPL LibLine::Editor with syntax highlighting (Unix only)
Script execution Files run as scripts or modules (--as-module)
REPL functions exit(code), help(), save(file), loadINI(file), loadJSON(file), print(value)
Last value _ accesses the last evaluated result
Flags --dump-ast, --as-module, --strip-ansi, --raw-strings, --disable-source-location-hints
History Saved to persistent history file
Signal handling Ctrl+C: first press warns, second press exits

dns — DNS query tool (Utilities/dns.cpp):

# Query A and AAAA records
./Build/Release/bin/dns A,[email removed]

# DNS-over-TLS with DNSSEC
./Build/Release/bin/dns --tls --server 1.1.1.1 --dnssec [email removed]

# With custom CA certificates
./Build/Release/bin/dns --ca-certs /path/to/certs.pem --tls [email removed]

image — Image format converter (Utilities/image.cpp):

# Convert PNG to WebP
./Build/Release/bin/image input.png -o output.webp

# Convert with JPEG quality setting
./Build/Release/bin/image input.png -o output.jpg --quality 85

# Crop and convert
./Build/Release/bin/image input.png -o output.bmp --crop 10,20,200,300

# Benchmark decoding (no output)
./Build/Release/bin/image input.avif --no-output

Options: -o <path>, --no-output, --frame-index <N>, --invert-cmyk, --crop <x,y,w,h>, --move-alpha-to-rgb, --strip-alpha, --assign-color-profile <file>, --quality <0-100>, --webp-allowed-transforms <list>.

8.11 Linters (Meta/Linters/)

Linter File Purpose
lint_clang_format.py C++ formatting Runs clang-format with --overwrite-inplace option
check_idl_files.py Web IDL files Validates IDL file correctness
lint_ipc.py IPC definitions Validates IPC endpoint definitions
lint-ci.sh CI integration Pre-commit hook runner
lint-commit.sh Commit messages Commit message format validation

8.12 Clang Plugins (Meta/Lagom/ClangPlugins/)

Two custom Clang plugins enforce code correctness at compile time:

Plugin Purpose
LambdaCaptureClangPlugin Validates lambda capture correctness
LibJSGCClangPlugin Detects GC-unsafe patterns in LibJS code

The GC scanner plugin optionally detects invalid function members (-fplugin-arg-libjs_gc_scanner-detect-invalid-function-members).

8.13 Fuzz Testing (Meta/Lagom/Fuzzers/)

36 fuzzer targets cover critical attack surfaces:

Areas fuzzed include: compression formats (brotli, deflate, gzip, lzma, zlib), image decoders (AVIF, BMP, GIF, ICO, ILBM, JPEG, JPEG2000, JXL, PNG, QOI, TIFF, TGA, WebP), font parsers (OpenType, WOFF/WOFF2), text processing (regex, URL parsing, text decoders), web formats (CSS, HTML, HTTP, XML), cryptographic protocols (TLS), and WebAssembly.


9. Integration Points

WebDriver (W3C Protocol)

Ladybird implements the W3C WebDriver standard for browser automation:

Starting the server:

./Build/Release/bin/WebDriver --port 4444

Supported endpoints:

Method Path Description
POST /session Create new session
DELETE /session/{id} Delete session
GET /status Server readiness state
GET/POST /session/{id}/timeouts Get/set timeouts
POST /session/{id}/url Navigate to URL
GET /session/{id}/url Get current URL
POST /session/{id}/back Navigate back
POST /session/{id}/forward Navigate forward

Session capabilities are processed per W3C specification. SessionFlags::Http is used for HTTP sessions.

Important

Only one HTTP WebDriver session is supported at a time. Concurrent sessions will fail with a session creation error.

Firefox DevTools Protocol

LibDevTools implements the Firefox DevTools protocol server, enabling remote debugging:

Ladybird --devtools 9222

Connect via Firefox's "Remote Debugging" feature or any compatible client. Supports DOM inspection, CSS editing, and JavaScript debugging.

D-Bus Integration (GTK)

The GTK backend registers as org.ladybird.Ladybird on the D-Bus session bus. Features:

  • Single-instance activation: opening a URL when Ladybird is already running sends the URL to the existing instance
  • Signal handling: open and activate signals for URL forwarding
  • forward_urls_to_remote_and_exit() detects an existing instance and forwards URLs instead of launching a new process

Mach Port IPC (macOS)

On macOS, IPC uses Mach ports instead of Unix sockets:

  • IPC::MachBootstrapListener — listens for incoming Mach port connections
  • IPC::TransportBootstrapMach — establishes Mach transport
  • Server names: Ladybird-<pid> format via mach_server_name_for_process()
  • WebDriver uses --webdriver-mach-server-name instead of --webdriver-content-path

10. Troubleshooting

Build Failures

Error: CMake version too old

Cause: CMake < 3.30.0 does not support the preset format used.

Solution: Install CMake 3.30.0+ from https://cmake.org or your package manager's latest repository.

Error: Rust compilation failures

Cause: Wrong Rust version or missing components.

Solution:

  1. Ensure rust-toolchain.toml is present (pinned to 1.95.0)
  2. Run rustup show to verify the active toolchain
  3. If needed: rustup install 1.95.0 && rustup component add rustfmt clippy

Error: vcpkg build failures in overlay ports

Cause: Stale vcpkg cache or network issues.

Solution:

  1. Delete vcpkg build cache: rm -rf Build/Release/vcpkg_installed
  2. Retry the build
  3. Check proxy settings if behind a corporate firewall

Warning

Deleting vcpkg_installed forces a full dependency rebuild, which can take 30+ minutes.

Runtime Issues

WebContent process crashes repeatedly

Cause: Rendering engine bug, GPU driver incompatibility, or memory corruption.

Solution:

  1. Try --force-cpu-painting to rule out GPU issues
  2. Check dmesg or system logs for OOM killer activity
  3. Run with --debug-process WebContent and attach a debugger
  4. Build with Sanitizer preset for memory error detection

RequestServer DNS resolution fails

Cause: DNS server unreachable or misconfigured.

Solution:

  1. Test DNS directly: ./Build/Release/bin/dns [email removed]
  2. Try system DNS: remove --dns-server flag
  3. Check firewall rules for DNS ports (53/UDP, 853/TCP for DoT)

High memory usage with many tabs

Cause: Each tab runs a separate WebContent process with its own memory space.

Solution:

  1. Close unused tabs
  2. Monitor per-process memory: ps aux | grep WebContent
  3. Use --collect-garbage-on-every-allocation (debug only) to check for leaks

Note

Memory usage scales linearly with open tabs since each tab has its own process, JS heap, and DOM tree. This is by design for security isolation.