# Ladybird Browser — Administrator & Developer Guide

## 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

```text
┌─────────────────────────────────────────────────────────────┐
│                       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):**

```bash
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:**

```bash
python3 Meta/ladybird.py build --preset Debug
```

Includes debug symbols, assertions enabled, no optimization.

**Sanitizer:**

```bash
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:

```bash
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

```text
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

```text
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:**

```bash
# 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`):**

```bash
# 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`):**

```bash
# 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:**

```bash
./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:

```bash
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.

---

_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. Unofficial; not affiliated with or reviewed by the project._
