commits
Add fillRect(), strokeRect(), clearRect() drawing operations and
fillStyle/strokeStyle/lineWidth/globalAlpha property support to the
Canvas 2D API.
- CSS crate: add parse_color_string() for canvas color parsing (hex,
rgb/rgba, named colors, transparent) with hex digit validation
- DOM crate: add rasterization functions with affine transform support,
source-over alpha blending, axis-aligned fast path, and general
inverse-mapping path for rotated/skewed transforms
- JS crate: wire up fillRect/strokeRect/clearRect native methods,
add property setter interception for fillStyle/strokeStyle/lineWidth/
globalAlpha with spec-compliant validation (invalid colors silently
ignored, non-finite lineWidth rejected)
- Tests: color parsing (12 tests), rectangle rasterization with
transforms and alpha blending (8 tests), JS integration (14 tests)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Canvas2dState, Canvas2dContext, and AffineTransform to the dom crate,
with full state stack (save/restore) and CTM operations (translate, rotate,
scale, transform, setTransform, resetTransform, getTransform). Wire up JS
bindings on the CanvasRenderingContext2D wrapper object. 25 Rust-level and
10 JS integration tests covering all transform operations, nested
save/restore, edge cases, and matrix inversion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HTMLCanvasElement support with backing pixel buffer, layout integration
as a replaced element, render pipeline integration, and JS bindings for
getContext('2d'), width/height properties.
- DOM: canvas backing buffer storage (init, resize, clear per spec)
- Layout: canvas intrinsic sizing (default 300x150, from width/height attrs)
- Render: canvas buffers composited as images via DrawImage pipeline
- JS: getContext('2d') returns CanvasRenderingContext2D with canvas back-ref
- JS: width/height getters/setters that resize and clear the buffer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add DOMContentLoaded, load, beforeunload, pagehide, and unload events
with correct firing order. Implement document.readyState property
with loading → interactive → complete transitions.
- DOMContentLoaded fires on document after sync scripts, bubbles to window
- load fires on window after all resources (CSS, fonts, images) are loaded
- beforeunload fires before navigation and can cancel via preventDefault()
- pagehide and unload fire during document teardown
- VM persisted in PageState so lifecycle handlers survive page load
- Window object gets sentinel __node_id__ for addEventListener support
- 10 new unit tests covering event ordering, readyState transitions,
and beforeunload cancellation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a browser chrome bar above the web page viewport with navigation
buttons (back, forward, reload), an editable address bar, and keyboard
shortcuts. This transforms the project from a page viewer into a
navigable browser.
Features:
- Chrome bar rendered at top of window (40px), web content below
- Back/Forward/Reload buttons with enabled/disabled state
- Address bar displays current URL, click to focus and edit
- Enter in address bar navigates to the typed URL
- Cmd+L focuses address bar and selects all text
- Cmd+R reloads current page
- Cmd+[/] navigate back/forward (existing)
- Escape cancels address bar editing and restores URL
- Full text editing: cursor movement, selection, copy/cut/paste
- Chrome rendering independent of web content CSS
- All event coordinates adjusted for chrome offset
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add fragment navigation support: clicking <a href="#id"> scrolls to the
matching element without reloading the page. Handles fragment-only links,
cross-document URLs that only differ in fragment, and history traversal
for fragment changes.
Changes:
- Url::equals_ignoring_fragment() and Url::set_fragment() for detecting
and manipulating fragment-only URL changes
- Document::find_anchor_by_name() for legacy <a name="..."> fallback
- create_hashchange_event() for the HashChangeEvent JS object
- navigate_fragment() in the browser main loop: updates URL, pushes
history entry, scrolls to target element, fires hashchange
- navigate_to_link() now detects fragment-only links and same-document
fragment changes instead of ignoring them
- navigate_history() avoids page reload for fragment-only traversals
- find_element_y_in_layout() walks the layout tree to find an element's
absolute Y position for scroll targeting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add navigation_error_page() that generates specific, descriptive error
pages based on the LoadError type. Each error type gets a tailored title,
description, and technical details code:
- DNS resolution failures: hostname + DNS_RESOLUTION_FAILED
- Connection refused/timeout: host + CONNECTION_REFUSED/TIMED_OUT
- TLS errors: specific reason (expired cert, wrong host, etc.)
- HTTP 4xx/5xx: status code + reason phrase with friendly titles
- Redirect loops: ERR_TOO_MANY_REDIRECTS / ERR_REDIRECT_LOOP
- Invalid URLs, unsupported schemes, encoding errors, CSP/CORS blocks
Error pages include a styled reload link pointing back to the failed URL,
and set base_url to the failed URL so the address bar shows the intended
destination. All user-provided strings are HTML-escaped to prevent XSS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Route fetched resources to appropriate renderers based on Content-Type:
- HTML renders normally (no regression)
- Plain text, CSS, JS, JSON, XML display in monospace <pre> blocks
- Images display centered in viewport via data URL embedding
- Unsupported binary types show friendly "Cannot Display" message
- Missing Content-Type triggers content sniffing (magic bytes, HTML
detection, text heuristic)
Adds base64_encode to we-url for image data URL generation.
Refactors loader to use shared classify_and_decode helper, eliminating
duplicated MIME routing logic across fetch/post_form/decode_response.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add proper HTTP redirect handling per spec:
- Support 301, 302, 303, 307, 308 status codes
- 301/302/303 change method to GET and drop body
- 307/308 preserve original method and body
- Detect redirect loops and produce clear error
- Increase max redirect limit from 10 to 20
- Strip Authorization header on cross-origin redirects
- Track redirect metadata (redirected flag, final URL)
- Expose response.redirected and final URL in fetch API
- Use final URL after redirects as base URL in loader
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add pushState, replaceState, back, forward, go methods and popstate
event support. History commands are queued in a thread-local queue
(like navigation commands) and drained by the browser main loop.
- Add push_state/replace_state to NavigationHistory (browser crate)
- Create history.rs module in JS crate with full History API
- Wire history object into window initialization
- Add dynamic property resolution for history.length/state
- Process history command queue after page loads and navigation
- Create PopStateEvent with state property for traversal events
- Cross-origin URL validation for pushState/replaceState
- 23 new tests covering all History API functionality
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add session history tracking with back/forward traversal for the browser
engine. NavigationHistory maintains a bounded stack of HistoryEntry values
(URL, scroll position, state, title) with a current-index cursor.
- Push new entries on link click and form submission navigation
- Save/restore scroll position on traversal
- Discard forward entries when navigating from mid-stack
- Enforce MAX_HISTORY_SIZE (50) to bound memory usage
- Cmd+[ / Cmd+] keyboard shortcuts for back/forward
- 9 unit tests covering all stack operations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a proper Location object with URL property getters (href, protocol,
host, hostname, port, pathname, search, hash, origin), property setters
that trigger navigation, and methods (assign, replace, reload, toString).
- New crates/js/src/location.rs with Location object, dynamic property
resolution, setter-driven navigation queue, and comprehensive tests
- Replace window.location stub in iframe_bridge with real Location object
- Wire document.location as alias via resolve_document_get
- Hook location getters/setters into VM property resolution chain
- Initialize window object and document URL in script_loader
- Thread-local NavigationCommand queue for browser to consume
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add click-to-navigate support for <a href="..."> elements. When a user
clicks on a link (or any element nested inside an anchor), the browser
resolves the href against the current page's base URL and navigates to
the target page.
Changes:
- Add base_url field to PageState for relative URL resolution
- Add find_ancestor_anchor() to walk DOM ancestors for <a href>
- Add navigate_to_link() to resolve URLs and trigger page loads
- Modify handle_mouse_down() to detect link clicks before label delegation
- Fix form submission to use actual page base URL instead of about:blank
- Skip javascript: and fragment-only (#) hrefs gracefully
- Add 7 unit tests covering anchor detection and URL resolution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete form submission support:
- Entry list construction from form controls (text, checkbox, radio,
select, textarea, hidden, submit buttons)
- application/x-www-form-urlencoded encoding
- multipart/form-data encoding with boundary generation
- text/plain encoding
- Form submission algorithm with constraint validation integration
- Submit triggers: button click, Enter in text inputs, Space/Enter on
focused submit buttons
- Submitter attribute overrides (formaction, formmethod, formenctype,
formnovalidate)
- GET submission (query string) and POST submission (request body)
- Page navigation on form submission response
- form.submit() and form.requestSubmit() JS bindings
- ResourceLoader.post_form() for POST form requests
- 26 tests covering entry list, encoding, and parameter extraction
Add the constraint validation API for form controls:
- ValidityState with all flags: valueMissing, typeMismatch, patternMismatch,
tooLong, tooShort, rangeUnderflow, rangeOverflow, stepMismatch, customError
- Constraint checking for all input types (text, email, url, number,
checkbox, radio), textarea, and select elements
- Built-in regex engine for pattern attribute matching
- CSS pseudo-classes: :valid, :invalid, :required, :optional,
:in-range, :out-of-range
- JS API: validity, validationMessage, willValidate properties;
checkValidity(), reportValidity(), setCustomValidity() methods
- Custom validity messages via setCustomValidity()
- Validation message generation for each constraint type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add interactive dropdown popup for <select> elements with full keyboard
navigation, mouse interaction, type-ahead search, and multiple select
support as a scrollable listbox.
DOM (crates/dom):
- Add select open/close state tracking (select_open, select_highlighted)
- Add SelectOptionInfo struct for option metadata
- Add select_options(), selected_index(), select_option_at() helpers
- Add type-ahead search with 1-second timeout buffer
- Tests for all select DOM operations
Layout (crates/layout):
- Extend FormControlInfo with dropdown_open, options, highlighted_index,
multiple, visible_size fields
- Add SelectOption struct for render-side option data
- Support <select multiple> sizing with size attribute
Render (crates/render):
- Two-phase rendering: collect open dropdowns during paint, render
overlays after main pass (ensures dropdowns paint on top)
- Dropdown overlay with shadow, border, highlighted option, optgroup
labels
- Multiple select listbox rendering with selection highlighting
- paint_rect_border helper, dropdown_menu_geometry public API
Browser (crates/browser):
- Click to open/close single-select dropdown
- Click on dropdown option to select it
- Click outside dropdown to dismiss
- Keyboard: Space/Enter to open/close, Up/Down to navigate options,
Escape to close, Home/End for first/last option
- Arrow keys cycle selection on closed single-select
- Multiple select: click to select, Cmd+Click to toggle, Up/Down
keyboard navigation, Space to toggle
- Type-ahead character search in open dropdown
- Hit-testing for dropdown overlay menu
- Close dropdowns on Tab navigation
JS bridge (crates/js):
- select.value getter/setter
- select.selectedIndex getter/setter
- select.options (HTMLOptionsCollection)
- select.selectedOptions
- select.type ("select-one" / "select-multiple")
- option.selected getter/setter
- input.checked, input.type, element.disabled getter/setters
- Tests for JS select interface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Checkbox click/space toggles checked state, clears indeterminate
- Radio button click/space selects and deselects siblings in same name group
- Arrow keys (Up/Left/Down/Right) cycle focus within radio groups
- Label click delegates to associated control (for attribute or descendant)
- Indeterminate visual state for checkboxes (horizontal dash)
- Hit-test extended to detect all form control types (not just text inputs)
- General element hit-test added for label click delegation
- Tests for radio group membership, indeterminate state, and grouping rules
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full text editing support for <input> and <textarea> elements:
- InputState module in DOM crate tracks cursor position, selection range,
and edited text buffer per form control
- Platform crate: KeyModifiers struct with Cmd/Option/Ctrl/Shift flags,
mouse-down/drag handlers, NSPasteboard clipboard read/write
- Keyboard input: character insertion, Backspace/Delete, Return for textarea
- Cursor movement: arrow keys, Home/End, Cmd+arrows (line start/end),
Option+arrows (word navigation), Cmd+Up/Down (document start/end)
- Text selection: Shift+arrows extend selection, Cmd+A select all,
click to position cursor, double-click to select word, click-drag to
extend selection
- Clipboard: Cmd+C copy, Cmd+X cut, Cmd+V paste via macOS pasteboard
- Rendering: cursor caret and selection highlight in focused text inputs
- Value sync: edited text synced back to DOM value attribute
- 25+ unit tests for cursor movement, selection, editing, word/line
navigation, Unicode handling, and change detection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add focus tracking, tab-order navigation, focus-related CSS pseudo-classes,
focus ring rendering, and JS DOM APIs for focus management.
- DOM: activeElement tracking, is_focusable(), compute_tab_order()
- CSS: :focus, :focus-visible, :focus-within, :disabled, :enabled, :checked
- Layout: focused field on FormControlInfo
- Render: blue focus ring around focused form controls
- Platform: key event handler (keyDown: dispatch)
- Browser: Tab/Shift+Tab cycles through focusable elements
- JS: document.activeElement, element.focus(), element.blur(), element.tabIndex
Paint native-style form controls into the rendering pipeline. Each form
control type gets a distinguishable visual appearance rendered using
existing FillRect and DrawGlyphs paint commands.
Layout crate changes:
- Add FormControlInfo struct and FormControlType enum to carry control
type, value text, checked/disabled state through the layout tree
- Populate form_control field during layout tree construction from DOM
attributes (tag name, type, value, checked, disabled, selected)
- Fix inline replaced element positioning: update child rects after
inline layout so atomic inline boxes (images, form controls) have
correct positions and dimensions
Render crate changes:
- Paint text inputs with inset border, white background, value text
- Paint password fields with bullet character masking
- Paint checkboxes as bordered squares with diagonal checkmark when checked
- Paint radio buttons as circles (scanline approximation) with filled
dot when selected
- Paint buttons (submit/reset/button) with raised border and centered
label text
- Paint select dropdowns with border, selected option text, and
triangular dropdown arrow indicator
- Paint textarea with same style as text input
- Render disabled controls with dimmed background and text colors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Form controls now participate in inline layout as atomic inline-level
boxes with correct intrinsic dimensions:
- Text inputs: width from size attribute (default 20 chars)
- Textareas: width/height from cols/rows attributes
- Buttons: sized to fit label text + padding
- Checkboxes/radio buttons: 13x13 CSS px
- Select dropdowns: width from longest option text
- CSS width/height properties override intrinsic sizes
Also adds:
- UA stylesheet rules for fieldset, legend, and form controls
- Fieldset/legend block layout with legend overlapping top border
- AtomicInline variant in inline formatting context
- Per-line max height tracking for lines with tall atomic boxes
- 15 new tests covering all form control types
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HTML form-related elements to the parser and DOM tree:
- Tree builder: form-specific rules for <form>, <fieldset>, <button>,
<textarea>, <select>, <option>, <optgroup> with proper scope handling
- InSelect insertion mode for <select> content model
- Form element pointer per HTML spec §13.2.4.1
- DOM interfaces: form_owner(), form_elements(), label_control(),
get_element_by_id(), is_form_control()
- 18 new tests covering parsing and attribute access for all form elements
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add comprehensive memory accounting, string interning, and targeted
optimizations across all browser subsystems:
- New `memory` crate: MemoryReport/SubsystemStats for profiling,
Atom (Rc<str>-backed interned strings), CompactString (22-byte SSO),
typed Arena<T> bump allocator
- DOM: tag names and attribute names now use Atom for deduplication,
reducing per-element memory by ~7x for repeated tags; memory_usage()
and element/text node counting methods added
- Style: font_family uses Atom instead of String (saves 16 bytes per
ComputedStyle); StyleCache gains len/is_empty/memory_usage methods;
ComputedStyle.heap_bytes() for dynamic field accounting
- Layout: LayoutTree gains box_count(), memory_usage(), LayoutHints
for pre-allocation across frames
- Render: display list compaction via build_display_list_into() that
reuses buffer capacity; LayerTree.memory_usage() and utilization
tracking for glyph atlas
- JS GC: adaptive threshold (1.5x growth factor, capped at 1M),
heap compaction when free ratio exceeds 50%, memory_usage() method
- Net: HttpClient.memory_usage(), pooled/h2 connection counts
- Text: GlyphCache.memory_usage() for bitmap data tracking
- Browser: memory_stats module aggregating all subsystem stats into
a formatted MemoryReport for debug/about:memory display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a speculative parser that runs on a background thread to discover
preloadable resources while the main parser is blocked on script execution.
- PreloadScanner: lightweight state machine that identifies <link rel=stylesheet>,
<script src>, <img src>, and <link rel=preload> tags
- SpeculativeParser: manages background thread, mpsc channels, token buffering,
and invalidation on document.write
- Handles inline script content correctly (enters ScriptData mode)
- Skips HTML comments to avoid false positives
- Supports double-quoted, single-quoted, and unquoted attribute values
- 22 new tests covering resource discovery, speculation hit/miss, invalidation,
and token replay
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete HTTP/2 protocol support (RFC 7540):
- Binary framing layer: 9-byte frame header, all frame types (DATA,
HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING,
GOAWAY, WINDOW_UPDATE, CONTINUATION)
- Stream state machine: idle → open → half-closed → closed with
proper state transition validation
- Connection management: preface exchange, SETTINGS negotiation,
HPACK header encoding/decoding, stream multiplexing
- Flow control: per-stream and connection-level window tracking
with automatic WINDOW_UPDATE frames
- TLS ALPN extension: negotiate h2 during TLS 1.3 handshake
- HttpClient integration: transparent HTTP/2 upgrade when server
supports h2, with fallback to HTTP/1.1
- std::io::Read/Write trait implementations for TlsStream
- Comprehensive tests for frame encoding/decoding, stream state
transitions, flow control, connection handshake, and full
request/response cycles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a retained layer tree system that tracks layout box state between frames
and computes damage rectangles for partial repainting. The system compares
box fingerprints (position, color, opacity, text content, borders) across
frames to identify which screen regions changed, merges nearby damage rects
to reduce draw calls, and skips rendering entirely when nothing changed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete HPACK encoder/decoder at crates/net/src/http2/hpack.rs:
- Integer encoding/decoding with prefix bits (§5.1)
- Huffman coding via canonical code generation from RFC code lengths (§5.2, Appendix B)
- Static table with 61 predefined headers (Appendix A)
- Dynamic table with FIFO eviction and configurable max size (§2.3)
- All header field representations: indexed, literal with/without indexing, never indexed (§6)
- Dynamic table size updates (§6.3)
- 41 tests including RFC 7541 Appendix C examples (C.2-C.6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a StyleCache that reuses computed styles across elements with
identical styling inputs (matched rules, inline style, parent style),
avoiding redundant cascade resolution. Cache keys are computed from
hashed matched rule sets, inline style attribute strings, and parent
style IDs. The cache is scoped per style resolution pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a dirty-bit system to the layout engine so that only modified subtrees
are re-laid-out instead of recomputing the entire layout tree each frame.
- Add `dirty` flag and `cached_available_width` to `LayoutBox`
- Add `DirtyTracker` struct with `mark_dirty()` (propagates to ancestors),
`mark_all_dirty()`, and `clear()` APIs
- `compute_layout()` skips clean subtrees, offsetting position if needed
- `pre_collapse_margins()` skips clean subtrees (already collapsed)
- Add `layout_incremental()` entry point that rebuilds the box tree,
transfers cached layout for clean nodes, and only runs expensive
layout computation on dirty subtrees
- Add layout counter (`layout_count()` / `reset_layout_count()`) for
metrics and testing
- Add tests: dirty tracker propagation, incremental skip verification,
correctness invariant (incremental == full layout), empty/all-dirty
edge cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a single-pass baseline JIT that compiles frequently-called bytecode
functions to AArch64 machine code. The compiler translates each bytecode
instruction to a call to a corresponding extern "C" helper function,
eliminating interpreter dispatch overhead while keeping implementation
simple and correct.
Key components:
- jit/compiler.rs: BaselineJit walks bytecode, emits native call sequences
and direct branches for control flow (Jump, JumpIfTrue, JumpIfFalse)
- jit/helpers.rs: extern "C" helper functions for all supported opcodes
including arithmetic, comparisons, property access with IC integration,
function calls, closures, and exception handling
- VM integration: per-function call counting (threshold=100), lazy JIT
buffer allocation, compiled code caching per GcRef, re-entrancy guard
to prevent recursive JIT dispatch, and run_to_depth for synchronous
callee execution from JIT code
Supported opcodes: LoadConst, LoadNull, LoadUndefined, LoadTrue, LoadFalse,
Move, LoadInt8, LoadGlobal, StoreGlobal, Add, Sub, Mul, Div, Rem, Neg,
BitAnd/Or/Xor, shifts, all comparisons, LogicalNot, TypeOf, Void, Jump,
JumpIfTrue/False/Nullish, Call, Return, Throw, CreateClosure, GetProperty,
SetProperty, GetPropertyByName, SetPropertyByName, CreateObject, CreateArray,
NewCell, CellLoad, CellStore, LoadUpvalue, StoreUpvalue, exception handlers.
Unsupported opcodes (Exp, InstanceOf, In, Delete, ForIn, Yield, Spread,
Await) bail out to the interpreter for correct execution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the low-level building blocks for JIT compilation in crates/js/src/jit/:
- ExecutableMemory: mmap-based allocator with W^X policy using MAP_JIT and
pthread_jit_write_protect_np for Apple Silicon
- JitBuffer: manages code pages with automatic overflow to new pages,
tracks used/free space per page
- CodePtr: type-safe wrapper for calling into JIT-compiled code
- Assembler: full AArch64 instruction emitter with label-based forward
references and backpatching, covering:
- Arithmetic: add, sub, mul, sdiv (register and immediate)
- Logic: and, orr, eor, lsl, lsr, asr
- Memory: ldr, str (register/immediate/pre-index/post-index), stp, ldp
- Branch: b, b.cond, bl, blr, br, ret, cbz, cbnz
- Comparison: cmp, tst
- Move: mov, movz, movk, mov_imm64
- FP: fmov, fadd, fsub, fmul, fdiv, fcmp, scvtf, fcvtzs
- Entry/exit stubs: prologue/epilogue saving/restoring callee-saved
registers (x19-x28, fp, lr) with proper frame pointer setup
- 88 tests including instruction encoding verification and execution
tests that JIT-compile and run AArch64 code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add polymorphic inline caches (ICs) to GetPropertyByName and SetPropertyByName
bytecode operations. Each property-access site caches up to 4 (shape, slot_index)
pairs for O(1) fast-path lookups, with megamorphic fallback when more shapes are
seen.
Key changes:
- Define InlineCache with Uninitialized/Monomorphic/Polymorphic/Megamorphic states
- Add Vec<InlineCache> to Function, allocated by the compiler per call site
- Extend GetPropertyByName/SetPropertyByName opcodes with a u16 IC index operand
- VM fast path: on IC hit, bypass shape table lookup and read/write slots directly
- Only own-property hits on shaped objects are cached (not prototype chain)
- IC updates on slow-path misses populate the cache for subsequent iterations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace HashMap<String, Property> object representation with a shape
(hidden class) system that tracks object layout transitions. Each shape
maps property names to fixed slot indices with attributes, enabling O(1)
indexed property access once the shape is known.
- Add Shape, ShapeId, ShapeTable, PropertyAttrs in new shape module
- ObjectData uses ObjectStorage enum: Shaped (shape + dense Vec<Value>
slots) or Dictionary (HashMap fallback after deletion/freeze/seal)
- Shape transitions cached by (name, attrs) so identical property
additions reuse shapes across objects
- Property deletion transitions object to dictionary mode
- All 701 existing JS tests pass unchanged
This is the foundation for inline caches and JIT property access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add BrowsingContext model with sandbox flags, origin tracking, and
parent-child relationships (browser crate)
- Add iframe element parsing with RAWTEXT mode in HTML tree builder
- Add iframe loader: discover iframes, fetch src URLs, parse nested
documents, render to pixel buffers as replaced elements
- Add window object, postMessage API, and MessageEvent to JS engine
- Add contentWindow/contentDocument with same-origin policy enforcement
- Add iframe_windows map on DomBridge for cross-context window proxies
- Integrate iframe sizes into layout pipeline as replaced elements
- Comprehensive tests for sandbox flags, browsing context tree, iframe
sizing, message serialization, and message queue
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a basic IndexedDB API implementation covering:
- Database lifecycle: open, close, deleteDatabase, version upgrades with upgradeneeded events
- Object stores: put, get, delete, clear, count, getAll with keyPath and autoIncrement support
- Transactions: readonly/readwrite mode enforcement, auto-commit with complete event, abort
- Indexes: createIndex with unique constraint, index.get for querying by non-primary key
- Structured clone: JS Value <-> IdbValue conversion for storing objects, arrays, primitives
- File-based persistence: origin-partitioned storage in ~/.we/indexeddb/ with binary serialization
- Event-driven API: deferred event firing via VM event loop (onsuccess, onerror, onupgradeneeded, oncomplete, onabort)
- Integration: DomBridge field, VM event loop drain, GC roots for pending events
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- StorageArea: in-memory key-value store with 5 MB per-origin quota,
insertion-order key tracking, binary serialization for persistence
- StorageManager: file-based persistence for localStorage (~/.we/storage/),
origin-keyed isolation, opaque origins get no storage
- JS integration: localStorage and sessionStorage globals with
getItem/setItem/removeItem/clear/key/length methods
- Property proxy: storage["key"] and storage.key work as getItem/setItem
- QuotaExceededError thrown when 5 MB limit exceeded
- VM API: set/take localStorage/sessionStorage for browser lifecycle
- 30 new tests covering unit, integration, and persistence
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Parse CSP from Content-Security-Policy and Content-Security-Policy-Report-Only HTTP headers
- Parse CSP from <meta http-equiv="Content-Security-Policy"> elements
- Support all fetch directives: default-src, script-src, style-src, img-src, font-src,
connect-src, frame-src, media-src, object-src, base-uri, form-action
- Support source expressions: 'none', 'self', 'unsafe-inline', 'unsafe-eval',
nonce sources, hash sources (sha256/sha384/sha512), scheme sources, host sources
- Enforce default-src fallback for fetch directives
- Block inline scripts unless allowed by 'unsafe-inline', matching nonce, or matching hash
- Nonce/hash presence disables 'unsafe-inline' per CSP2 spec
- Multiple policies use intersection semantics (all must allow)
- Report-only policies log violations but do not block
- Integrate CSP checks into ResourceLoader.fetch_subresource
- Integrate inline script CSP checks into script_loader with nonce attribute support
- 64 unit tests covering parsing, matching, enforcement, and edge cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add W3C Referrer Policy support with all 8 policies: no-referrer,
no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin,
strict-origin, strict-origin-when-cross-origin (default), and unsafe-url.
- New crates/net/src/referrer.rs: ReferrerPolicy enum, header/attribute
parsing, and compute_referrer() for Referer header computation
- ResourceLoader: tracks document URL and referrer policy, sets Referer
header on all outgoing requests, updates policy from Referrer-Policy
response headers
- HTML integration: extracts <meta name="referrer"> from DOM, reads
referrerpolicy attribute on <script>, <link>, and <img> elements
- Element-level policy overrides document-level policy per spec
- Strips fragment and userinfo from referrer URLs
- HTTPS-to-HTTP downgrade correctly handled for strict/downgrade policies
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a full RFC 6265bis cookie implementation:
- Set-Cookie header parsing with all attributes (Domain, Path, Expires,
Max-Age, Secure, HttpOnly, SameSite)
- CookieJar with domain/path matching, expiry, per-domain and total limits
- Automatic cookie attachment to outgoing HTTP requests and storage from
responses in HttpClient
- document.cookie getter/setter in the JS-DOM bridge (HttpOnly cookies
hidden from JS, JS cannot set HttpOnly cookies)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full CORS (Cross-Origin Resource Sharing) per the Fetch Standard:
- Simple request detection: CORS-safelisted methods (GET/HEAD/POST) and
headers (Accept, Accept-Language, Content-Language, Content-Type with
safelisted values) skip preflight
- Preflight (OPTIONS) requests for non-simple cross-origin requests with
Access-Control-Request-Method/Headers, validated against server response
- Preflight cache keyed by (origin, URL) with Access-Control-Max-Age TTL
- Access-Control-Allow-Origin validation (wildcard and exact match)
- Access-Control-Allow-Credentials enforcement (must be exact origin echo
and 'true' when credentials: include)
- Access-Control-Expose-Headers controls which response headers scripts see
- Response header filtering (only CORS-safelisted + explicitly exposed)
- Origin header sent on all cross-origin requests
- Fetch API supports mode (cors/no-cors) and credentials (omit/same-origin/
include) options
Integration points:
- crates/net/src/cors.rs: core CORS module (56 unit tests)
- crates/browser/src/loader.rs: CORS in resource loading pipeline
- crates/js/src/fetch.rs: CORS mode/credentials in Fetch API bridge
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the foundational security primitive for the browser engine:
- Origin::same_origin() with default port normalization (http/80, https/443, ftp/21)
- Origin::serialize() and Display impl for CORS header comparison
- ResourceLoader::fetch_subresource() with SOP enforcement per resource type:
scripts, stylesheets, fonts, and fetch blocked cross-origin without CORS;
images and navigation always allowed
- JS fetch() API SOP enforcement via document origin thread-local
- DomBridge origin field and document.domain property for future iframe isolation
- Updated CSS loader, script loader, and font loader to use SOP-enforcing methods
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for @font-face CSS rules to load and use web fonts:
- CSS parser: parse @font-face blocks with font-family, src (url() with
optional format()), font-weight (normal/bold/numeric), font-style
(normal/italic/oblique), and font-display descriptors
- Text crate: extend FontRegistry with web font registration from raw
bytes, with web fonts taking priority over system fonts in lookups
- Browser crate: new font_loader module that collects @font-face rules
from stylesheets, fetches font files via the resource loader, and
registers them in the FontRegistry
- Integration: page loading pipeline now loads web fonts after CSS
collection, and the rendering font is selected from the registry
(preferring web fonts when available)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds full CSS Grid support across three crates:
CSS crate: shorthand expansion for grid-column, grid-row, grid-area
Style crate: Display::Grid/InlineGrid, GridTrackSize (fr, minmax, repeat),
GridPlacement, GridAutoFlow, grid-template-columns/rows/areas parsing,
grid item placement properties, justify-items/justify-self
Layout crate: grid layout algorithm with explicit grid resolution,
auto-placement (row/column/dense), fr unit distribution, track sizing,
gap support, and justify/align item positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `svg` crate with:
- SVG path data parser (M, L, H, V, C, S, Q, T, A, Z and relative variants)
- 2D affine transform parsing (translate, rotate, scale, matrix, skewX/Y)
- Scanline rasterizer with even-odd fill and stroke expansion
- Shape-to-path converters (rect, circle, ellipse, rounded rect via cubic arcs)
- SVG color parsing (named colors, #hex, rgb())
- viewBox coordinate mapping
- Presentation attributes: fill, stroke, stroke-width, opacity, transform
- SVG text rendering via the text crate's glyph rasterizer
Integration:
- HTML parser: SVG foreign content mode with namespace tracking
- Style resolver: skip children of SVG root elements (replaced element)
- Browser: rasterize SVG elements to RGBA images for layout/render pipeline
- UA stylesheet: svg { display: block }
35 new tests covering path parsing, transforms, shape rendering, viewBox
scaling, color parsing, group transforms, and HTML-SVG integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Parse @keyframes rules with from/to keywords, percentage stops, and
multiple selectors per block (including -webkit-/-moz- prefixes)
- Parse animation shorthand and all 8 longhand properties:
animation-name, animation-duration, animation-timing-function,
animation-delay, animation-iteration-count, animation-direction,
animation-fill-mode, animation-play-state
- Animation engine reuses transition timing functions and interpolation:
cubic-bezier, steps, linear, and all ease-* variants
- Multi-keyframe interpolation across arbitrary percentage stops
- Direction support: normal, reverse, alternate, alternate-reverse
- Fill modes: none, forwards, backwards, both
- Iteration count: finite numbers and infinite
- Pause/resume support with elapsed time tracking
- Animation events: animationstart, animationiteration, animationend
- AnimationMap for per-element animation state management
- Keyframe property resolution with value resolver callback
- Style system integration: AnimationSpec in ComputedStyle, cascade
handling for animation properties at all priority levels
- 40+ new tests covering parsing, keyframe interpolation, timing,
direction, fill modes, pause/resume, events, and animation map
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new `transitions` module to the CSS crate with:
- Transition property parsing (shorthand and longhands: transition-property,
transition-duration, transition-timing-function, transition-delay)
- Timing function evaluation: linear, ease, ease-in, ease-out, ease-in-out,
cubic-bezier (Newton + bisection solver), steps(n, start|end)
- Property value interpolation engine for lengths, colors (sRGB), and numbers
with mismatched-type snap-at-50% behavior
- TransitionMap for per-element transition tracking: start, evaluate at time,
mid-flight interruption (restarts from current interpolated value), and
completion detection for transitionend events
- Integration with ComputedStyle: TransitionSpec field, cascade-level parsing
from raw ComponentValues for transition properties
- 25 unit tests covering timing functions, interpolation, parsing, and
transition state management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add crates/css/src/media.rs with MediaQueryList, MediaQuery, MediaFeature types
- Parse @media prelude into structured AST (types, features, operators, range syntax)
- Support screen/print/all types, not/only modifiers, comma OR semantics
- Support width/height features (min-, max-, range syntax including double ranges)
- Support prefers-color-scheme and prefers-reduced-motion discrete features
- Evaluate media queries against MediaContext (viewport dimensions, color scheme)
- Integrate with style crate: collect_from_rules now conditionally applies @media rules
- Add resolve_styles_with_media for full MediaContext control
- Add is_dark_mode() to platform crate for macOS dark mode detection
- 30+ unit tests for parsing and evaluation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add parsing, evaluation, and layout-time resolution for CSS math
functions per CSS Values and Units Module Level 4.
- CSS crate: MathExpr AST with recursive descent parser supporting
operator precedence, nested functions, and mixed units
- Style crate: Two-phase evaluation — resolves non-percentage units
at style time, defers percentage-based expressions to layout via
new LengthOrAuto::Calc and ClampCalc variants
- Layout crate: Resolves deferred calc expressions against containing
block dimensions at layout time
- Handles calc(100% - 20px), min/max with vw/px, clamp with mixed
units, division by zero, and nested expressions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for CSS Custom Properties per CSS Custom Properties for
Cascading Variables Module Level 1:
- Custom property declarations (--name: value) stored on ComputedStyle
- var() function substitution with fallback values
- Custom properties inherit through the DOM tree by default
- Cycle detection for circular var() references
- Support for initial/inherit/unset keywords on custom properties
- Nested var() in fallback values: var(--a, var(--b, blue))
- var() substitution in shorthand properties
- Case-sensitive custom property names
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a RenderBackend enum that abstracts over the Metal GPU and
software CPU renderers, with automatic backend selection at startup.
Falls back to software rendering when Metal is unavailable or shader
compilation fails. Logs the active backend to stderr.
- Add RenderBackend enum (Metal/Software) with detection and fallback
- Add Renderer::paint_display_list() for pre-built display list rendering
- Unify browser render pipeline into a single render_page() function
- Handle Metal errors gracefully (nil drawable skips frame)
- Add tests for backend selection, software rendering, and display lists
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a layer tree that renders subtrees to intermediate Metal textures for
correct group compositing of opacity, will-change, fixed-position, and
scrollable elements.
CSS properties:
- Add `opacity` (0.0-1.0, clamped) to ComputedStyle, LayoutBox
- Add `will-change` (transform, opacity) to ComputedStyle, LayoutBox
- Parse both properties from CSS declarations
Display list:
- Add PushLayer/PopLayer paint commands wrapping elements that need
compositing isolation
- Detect layer-needing elements: opacity < 1.0, will-change hints,
position: fixed, scrollable overflow containers
Metal GPU renderer:
- Render-to-texture for layers with opacity < 1.0: create offscreen
BGRA render target, render layer contents, composite back with opacity
- Layers with opacity=1.0 are pass-through (no intermediate texture)
- Handle nested layers via a layer state stack
- Coordinate offset tracking for layer-local rendering
- Graceful fallback if render target creation fails
Platform (Metal FFI):
- Device::new_render_target_texture() with ShaderRead | RenderTarget usage
- make_load_pass_descriptor() for resuming rendering to existing targets
Software renderer:
- Buffer-swap compositing for opacity layers
- Alpha-blend layer buffer back with group opacity on PopLayer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GpuRenderer that translates the DisplayList into batched Metal GPU
draw calls, replacing the software renderer when Metal is available.
- FillRect → solid-color quads via dummy 1x1 white texture
- DrawGlyphs → textured quads sampling from glyph atlas pages
- DrawImage → textured quads from per-node image textures
- PushClip/PopClip → Metal scissor rects with clip stack
- Batches consecutive same-texture draws into single draw calls
- Flushes batches at texture and clip boundary changes
Platform changes:
- Expose MetalView layer/queue/clear_color accessors
- Add RenderCommandEncoder::set_scissor_rect
- Make MTL_PRIMITIVE_TYPE_TRIANGLE and MetalRenderer accessors public
Browser integration:
- GPU path: style → layout → display list → Metal draw (no bitmap copy)
- Software fallback preserved when Metal unavailable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement a shelf-packing texture atlas in the render crate that packs
rasterized glyph bitmaps into R8 grayscale texture pages. The atlas
provides UV coordinates for each glyph and can generate textured quads
from TextLine data for the Metal rendering pipeline.
- Shelf-packing allocator with configurable page size (default 1024x1024)
- Multi-page support: automatically creates new pages when full
- Dirty tracking for efficient GPU texture uploads
- TexturedQuad generation from TextLine with correct UV mapping
- Integration with existing Font glyph cache for on-demand rasterization
- 19 comprehensive unit tests
Implements issue 3mi4366fkxs2g
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential out-of-bounds read by checking that the data slice
is at least bytes_per_row * height before passing it to Metal's
replaceRegion:withBytes:bytesPerRow: API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential out-of-bounds read by checking that the data slice
is at least bytes_per_row * height before passing it to Metal's
replaceRegion:withBytes:bytesPerRow: API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential out-of-bounds read by checking that the data slice
is at least bytes_per_row * height before passing it to Metal's
replaceRegion:withBytes:bytesPerRow: API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential out-of-bounds read by checking that the data slice
is at least bytes_per_row * height before passing it to Metal's
replaceRegion:withBytes:bytesPerRow: API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add fillRect(), strokeRect(), clearRect() drawing operations and
fillStyle/strokeStyle/lineWidth/globalAlpha property support to the
Canvas 2D API.
- CSS crate: add parse_color_string() for canvas color parsing (hex,
rgb/rgba, named colors, transparent) with hex digit validation
- DOM crate: add rasterization functions with affine transform support,
source-over alpha blending, axis-aligned fast path, and general
inverse-mapping path for rotated/skewed transforms
- JS crate: wire up fillRect/strokeRect/clearRect native methods,
add property setter interception for fillStyle/strokeStyle/lineWidth/
globalAlpha with spec-compliant validation (invalid colors silently
ignored, non-finite lineWidth rejected)
- Tests: color parsing (12 tests), rectangle rasterization with
transforms and alpha blending (8 tests), JS integration (14 tests)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Canvas2dState, Canvas2dContext, and AffineTransform to the dom crate,
with full state stack (save/restore) and CTM operations (translate, rotate,
scale, transform, setTransform, resetTransform, getTransform). Wire up JS
bindings on the CanvasRenderingContext2D wrapper object. 25 Rust-level and
10 JS integration tests covering all transform operations, nested
save/restore, edge cases, and matrix inversion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HTMLCanvasElement support with backing pixel buffer, layout integration
as a replaced element, render pipeline integration, and JS bindings for
getContext('2d'), width/height properties.
- DOM: canvas backing buffer storage (init, resize, clear per spec)
- Layout: canvas intrinsic sizing (default 300x150, from width/height attrs)
- Render: canvas buffers composited as images via DrawImage pipeline
- JS: getContext('2d') returns CanvasRenderingContext2D with canvas back-ref
- JS: width/height getters/setters that resize and clear the buffer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add DOMContentLoaded, load, beforeunload, pagehide, and unload events
with correct firing order. Implement document.readyState property
with loading → interactive → complete transitions.
- DOMContentLoaded fires on document after sync scripts, bubbles to window
- load fires on window after all resources (CSS, fonts, images) are loaded
- beforeunload fires before navigation and can cancel via preventDefault()
- pagehide and unload fire during document teardown
- VM persisted in PageState so lifecycle handlers survive page load
- Window object gets sentinel __node_id__ for addEventListener support
- 10 new unit tests covering event ordering, readyState transitions,
and beforeunload cancellation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a browser chrome bar above the web page viewport with navigation
buttons (back, forward, reload), an editable address bar, and keyboard
shortcuts. This transforms the project from a page viewer into a
navigable browser.
Features:
- Chrome bar rendered at top of window (40px), web content below
- Back/Forward/Reload buttons with enabled/disabled state
- Address bar displays current URL, click to focus and edit
- Enter in address bar navigates to the typed URL
- Cmd+L focuses address bar and selects all text
- Cmd+R reloads current page
- Cmd+[/] navigate back/forward (existing)
- Escape cancels address bar editing and restores URL
- Full text editing: cursor movement, selection, copy/cut/paste
- Chrome rendering independent of web content CSS
- All event coordinates adjusted for chrome offset
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add fragment navigation support: clicking <a href="#id"> scrolls to the
matching element without reloading the page. Handles fragment-only links,
cross-document URLs that only differ in fragment, and history traversal
for fragment changes.
Changes:
- Url::equals_ignoring_fragment() and Url::set_fragment() for detecting
and manipulating fragment-only URL changes
- Document::find_anchor_by_name() for legacy <a name="..."> fallback
- create_hashchange_event() for the HashChangeEvent JS object
- navigate_fragment() in the browser main loop: updates URL, pushes
history entry, scrolls to target element, fires hashchange
- navigate_to_link() now detects fragment-only links and same-document
fragment changes instead of ignoring them
- navigate_history() avoids page reload for fragment-only traversals
- find_element_y_in_layout() walks the layout tree to find an element's
absolute Y position for scroll targeting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add navigation_error_page() that generates specific, descriptive error
pages based on the LoadError type. Each error type gets a tailored title,
description, and technical details code:
- DNS resolution failures: hostname + DNS_RESOLUTION_FAILED
- Connection refused/timeout: host + CONNECTION_REFUSED/TIMED_OUT
- TLS errors: specific reason (expired cert, wrong host, etc.)
- HTTP 4xx/5xx: status code + reason phrase with friendly titles
- Redirect loops: ERR_TOO_MANY_REDIRECTS / ERR_REDIRECT_LOOP
- Invalid URLs, unsupported schemes, encoding errors, CSP/CORS blocks
Error pages include a styled reload link pointing back to the failed URL,
and set base_url to the failed URL so the address bar shows the intended
destination. All user-provided strings are HTML-escaped to prevent XSS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Route fetched resources to appropriate renderers based on Content-Type:
- HTML renders normally (no regression)
- Plain text, CSS, JS, JSON, XML display in monospace <pre> blocks
- Images display centered in viewport via data URL embedding
- Unsupported binary types show friendly "Cannot Display" message
- Missing Content-Type triggers content sniffing (magic bytes, HTML
detection, text heuristic)
Adds base64_encode to we-url for image data URL generation.
Refactors loader to use shared classify_and_decode helper, eliminating
duplicated MIME routing logic across fetch/post_form/decode_response.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add proper HTTP redirect handling per spec:
- Support 301, 302, 303, 307, 308 status codes
- 301/302/303 change method to GET and drop body
- 307/308 preserve original method and body
- Detect redirect loops and produce clear error
- Increase max redirect limit from 10 to 20
- Strip Authorization header on cross-origin redirects
- Track redirect metadata (redirected flag, final URL)
- Expose response.redirected and final URL in fetch API
- Use final URL after redirects as base URL in loader
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add pushState, replaceState, back, forward, go methods and popstate
event support. History commands are queued in a thread-local queue
(like navigation commands) and drained by the browser main loop.
- Add push_state/replace_state to NavigationHistory (browser crate)
- Create history.rs module in JS crate with full History API
- Wire history object into window initialization
- Add dynamic property resolution for history.length/state
- Process history command queue after page loads and navigation
- Create PopStateEvent with state property for traversal events
- Cross-origin URL validation for pushState/replaceState
- 23 new tests covering all History API functionality
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add session history tracking with back/forward traversal for the browser
engine. NavigationHistory maintains a bounded stack of HistoryEntry values
(URL, scroll position, state, title) with a current-index cursor.
- Push new entries on link click and form submission navigation
- Save/restore scroll position on traversal
- Discard forward entries when navigating from mid-stack
- Enforce MAX_HISTORY_SIZE (50) to bound memory usage
- Cmd+[ / Cmd+] keyboard shortcuts for back/forward
- 9 unit tests covering all stack operations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a proper Location object with URL property getters (href, protocol,
host, hostname, port, pathname, search, hash, origin), property setters
that trigger navigation, and methods (assign, replace, reload, toString).
- New crates/js/src/location.rs with Location object, dynamic property
resolution, setter-driven navigation queue, and comprehensive tests
- Replace window.location stub in iframe_bridge with real Location object
- Wire document.location as alias via resolve_document_get
- Hook location getters/setters into VM property resolution chain
- Initialize window object and document URL in script_loader
- Thread-local NavigationCommand queue for browser to consume
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add click-to-navigate support for <a href="..."> elements. When a user
clicks on a link (or any element nested inside an anchor), the browser
resolves the href against the current page's base URL and navigates to
the target page.
Changes:
- Add base_url field to PageState for relative URL resolution
- Add find_ancestor_anchor() to walk DOM ancestors for <a href>
- Add navigate_to_link() to resolve URLs and trigger page loads
- Modify handle_mouse_down() to detect link clicks before label delegation
- Fix form submission to use actual page base URL instead of about:blank
- Skip javascript: and fragment-only (#) hrefs gracefully
- Add 7 unit tests covering anchor detection and URL resolution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete form submission support:
- Entry list construction from form controls (text, checkbox, radio,
select, textarea, hidden, submit buttons)
- application/x-www-form-urlencoded encoding
- multipart/form-data encoding with boundary generation
- text/plain encoding
- Form submission algorithm with constraint validation integration
- Submit triggers: button click, Enter in text inputs, Space/Enter on
focused submit buttons
- Submitter attribute overrides (formaction, formmethod, formenctype,
formnovalidate)
- GET submission (query string) and POST submission (request body)
- Page navigation on form submission response
- form.submit() and form.requestSubmit() JS bindings
- ResourceLoader.post_form() for POST form requests
- 26 tests covering entry list, encoding, and parameter extraction
Add the constraint validation API for form controls:
- ValidityState with all flags: valueMissing, typeMismatch, patternMismatch,
tooLong, tooShort, rangeUnderflow, rangeOverflow, stepMismatch, customError
- Constraint checking for all input types (text, email, url, number,
checkbox, radio), textarea, and select elements
- Built-in regex engine for pattern attribute matching
- CSS pseudo-classes: :valid, :invalid, :required, :optional,
:in-range, :out-of-range
- JS API: validity, validationMessage, willValidate properties;
checkValidity(), reportValidity(), setCustomValidity() methods
- Custom validity messages via setCustomValidity()
- Validation message generation for each constraint type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add interactive dropdown popup for <select> elements with full keyboard
navigation, mouse interaction, type-ahead search, and multiple select
support as a scrollable listbox.
DOM (crates/dom):
- Add select open/close state tracking (select_open, select_highlighted)
- Add SelectOptionInfo struct for option metadata
- Add select_options(), selected_index(), select_option_at() helpers
- Add type-ahead search with 1-second timeout buffer
- Tests for all select DOM operations
Layout (crates/layout):
- Extend FormControlInfo with dropdown_open, options, highlighted_index,
multiple, visible_size fields
- Add SelectOption struct for render-side option data
- Support <select multiple> sizing with size attribute
Render (crates/render):
- Two-phase rendering: collect open dropdowns during paint, render
overlays after main pass (ensures dropdowns paint on top)
- Dropdown overlay with shadow, border, highlighted option, optgroup
labels
- Multiple select listbox rendering with selection highlighting
- paint_rect_border helper, dropdown_menu_geometry public API
Browser (crates/browser):
- Click to open/close single-select dropdown
- Click on dropdown option to select it
- Click outside dropdown to dismiss
- Keyboard: Space/Enter to open/close, Up/Down to navigate options,
Escape to close, Home/End for first/last option
- Arrow keys cycle selection on closed single-select
- Multiple select: click to select, Cmd+Click to toggle, Up/Down
keyboard navigation, Space to toggle
- Type-ahead character search in open dropdown
- Hit-testing for dropdown overlay menu
- Close dropdowns on Tab navigation
JS bridge (crates/js):
- select.value getter/setter
- select.selectedIndex getter/setter
- select.options (HTMLOptionsCollection)
- select.selectedOptions
- select.type ("select-one" / "select-multiple")
- option.selected getter/setter
- input.checked, input.type, element.disabled getter/setters
- Tests for JS select interface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Checkbox click/space toggles checked state, clears indeterminate
- Radio button click/space selects and deselects siblings in same name group
- Arrow keys (Up/Left/Down/Right) cycle focus within radio groups
- Label click delegates to associated control (for attribute or descendant)
- Indeterminate visual state for checkboxes (horizontal dash)
- Hit-test extended to detect all form control types (not just text inputs)
- General element hit-test added for label click delegation
- Tests for radio group membership, indeterminate state, and grouping rules
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full text editing support for <input> and <textarea> elements:
- InputState module in DOM crate tracks cursor position, selection range,
and edited text buffer per form control
- Platform crate: KeyModifiers struct with Cmd/Option/Ctrl/Shift flags,
mouse-down/drag handlers, NSPasteboard clipboard read/write
- Keyboard input: character insertion, Backspace/Delete, Return for textarea
- Cursor movement: arrow keys, Home/End, Cmd+arrows (line start/end),
Option+arrows (word navigation), Cmd+Up/Down (document start/end)
- Text selection: Shift+arrows extend selection, Cmd+A select all,
click to position cursor, double-click to select word, click-drag to
extend selection
- Clipboard: Cmd+C copy, Cmd+X cut, Cmd+V paste via macOS pasteboard
- Rendering: cursor caret and selection highlight in focused text inputs
- Value sync: edited text synced back to DOM value attribute
- 25+ unit tests for cursor movement, selection, editing, word/line
navigation, Unicode handling, and change detection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add focus tracking, tab-order navigation, focus-related CSS pseudo-classes,
focus ring rendering, and JS DOM APIs for focus management.
- DOM: activeElement tracking, is_focusable(), compute_tab_order()
- CSS: :focus, :focus-visible, :focus-within, :disabled, :enabled, :checked
- Layout: focused field on FormControlInfo
- Render: blue focus ring around focused form controls
- Platform: key event handler (keyDown: dispatch)
- Browser: Tab/Shift+Tab cycles through focusable elements
- JS: document.activeElement, element.focus(), element.blur(), element.tabIndex
Paint native-style form controls into the rendering pipeline. Each form
control type gets a distinguishable visual appearance rendered using
existing FillRect and DrawGlyphs paint commands.
Layout crate changes:
- Add FormControlInfo struct and FormControlType enum to carry control
type, value text, checked/disabled state through the layout tree
- Populate form_control field during layout tree construction from DOM
attributes (tag name, type, value, checked, disabled, selected)
- Fix inline replaced element positioning: update child rects after
inline layout so atomic inline boxes (images, form controls) have
correct positions and dimensions
Render crate changes:
- Paint text inputs with inset border, white background, value text
- Paint password fields with bullet character masking
- Paint checkboxes as bordered squares with diagonal checkmark when checked
- Paint radio buttons as circles (scanline approximation) with filled
dot when selected
- Paint buttons (submit/reset/button) with raised border and centered
label text
- Paint select dropdowns with border, selected option text, and
triangular dropdown arrow indicator
- Paint textarea with same style as text input
- Render disabled controls with dimmed background and text colors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Form controls now participate in inline layout as atomic inline-level
boxes with correct intrinsic dimensions:
- Text inputs: width from size attribute (default 20 chars)
- Textareas: width/height from cols/rows attributes
- Buttons: sized to fit label text + padding
- Checkboxes/radio buttons: 13x13 CSS px
- Select dropdowns: width from longest option text
- CSS width/height properties override intrinsic sizes
Also adds:
- UA stylesheet rules for fieldset, legend, and form controls
- Fieldset/legend block layout with legend overlapping top border
- AtomicInline variant in inline formatting context
- Per-line max height tracking for lines with tall atomic boxes
- 15 new tests covering all form control types
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HTML form-related elements to the parser and DOM tree:
- Tree builder: form-specific rules for <form>, <fieldset>, <button>,
<textarea>, <select>, <option>, <optgroup> with proper scope handling
- InSelect insertion mode for <select> content model
- Form element pointer per HTML spec §13.2.4.1
- DOM interfaces: form_owner(), form_elements(), label_control(),
get_element_by_id(), is_form_control()
- 18 new tests covering parsing and attribute access for all form elements
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add comprehensive memory accounting, string interning, and targeted
optimizations across all browser subsystems:
- New `memory` crate: MemoryReport/SubsystemStats for profiling,
Atom (Rc<str>-backed interned strings), CompactString (22-byte SSO),
typed Arena<T> bump allocator
- DOM: tag names and attribute names now use Atom for deduplication,
reducing per-element memory by ~7x for repeated tags; memory_usage()
and element/text node counting methods added
- Style: font_family uses Atom instead of String (saves 16 bytes per
ComputedStyle); StyleCache gains len/is_empty/memory_usage methods;
ComputedStyle.heap_bytes() for dynamic field accounting
- Layout: LayoutTree gains box_count(), memory_usage(), LayoutHints
for pre-allocation across frames
- Render: display list compaction via build_display_list_into() that
reuses buffer capacity; LayerTree.memory_usage() and utilization
tracking for glyph atlas
- JS GC: adaptive threshold (1.5x growth factor, capped at 1M),
heap compaction when free ratio exceeds 50%, memory_usage() method
- Net: HttpClient.memory_usage(), pooled/h2 connection counts
- Text: GlyphCache.memory_usage() for bitmap data tracking
- Browser: memory_stats module aggregating all subsystem stats into
a formatted MemoryReport for debug/about:memory display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a speculative parser that runs on a background thread to discover
preloadable resources while the main parser is blocked on script execution.
- PreloadScanner: lightweight state machine that identifies <link rel=stylesheet>,
<script src>, <img src>, and <link rel=preload> tags
- SpeculativeParser: manages background thread, mpsc channels, token buffering,
and invalidation on document.write
- Handles inline script content correctly (enters ScriptData mode)
- Skips HTML comments to avoid false positives
- Supports double-quoted, single-quoted, and unquoted attribute values
- 22 new tests covering resource discovery, speculation hit/miss, invalidation,
and token replay
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete HTTP/2 protocol support (RFC 7540):
- Binary framing layer: 9-byte frame header, all frame types (DATA,
HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING,
GOAWAY, WINDOW_UPDATE, CONTINUATION)
- Stream state machine: idle → open → half-closed → closed with
proper state transition validation
- Connection management: preface exchange, SETTINGS negotiation,
HPACK header encoding/decoding, stream multiplexing
- Flow control: per-stream and connection-level window tracking
with automatic WINDOW_UPDATE frames
- TLS ALPN extension: negotiate h2 during TLS 1.3 handshake
- HttpClient integration: transparent HTTP/2 upgrade when server
supports h2, with fallback to HTTP/1.1
- std::io::Read/Write trait implementations for TlsStream
- Comprehensive tests for frame encoding/decoding, stream state
transitions, flow control, connection handshake, and full
request/response cycles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a retained layer tree system that tracks layout box state between frames
and computes damage rectangles for partial repainting. The system compares
box fingerprints (position, color, opacity, text content, borders) across
frames to identify which screen regions changed, merges nearby damage rects
to reduce draw calls, and skips rendering entirely when nothing changed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add complete HPACK encoder/decoder at crates/net/src/http2/hpack.rs:
- Integer encoding/decoding with prefix bits (§5.1)
- Huffman coding via canonical code generation from RFC code lengths (§5.2, Appendix B)
- Static table with 61 predefined headers (Appendix A)
- Dynamic table with FIFO eviction and configurable max size (§2.3)
- All header field representations: indexed, literal with/without indexing, never indexed (§6)
- Dynamic table size updates (§6.3)
- 41 tests including RFC 7541 Appendix C examples (C.2-C.6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a StyleCache that reuses computed styles across elements with
identical styling inputs (matched rules, inline style, parent style),
avoiding redundant cascade resolution. Cache keys are computed from
hashed matched rule sets, inline style attribute strings, and parent
style IDs. The cache is scoped per style resolution pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a dirty-bit system to the layout engine so that only modified subtrees
are re-laid-out instead of recomputing the entire layout tree each frame.
- Add `dirty` flag and `cached_available_width` to `LayoutBox`
- Add `DirtyTracker` struct with `mark_dirty()` (propagates to ancestors),
`mark_all_dirty()`, and `clear()` APIs
- `compute_layout()` skips clean subtrees, offsetting position if needed
- `pre_collapse_margins()` skips clean subtrees (already collapsed)
- Add `layout_incremental()` entry point that rebuilds the box tree,
transfers cached layout for clean nodes, and only runs expensive
layout computation on dirty subtrees
- Add layout counter (`layout_count()` / `reset_layout_count()`) for
metrics and testing
- Add tests: dirty tracker propagation, incremental skip verification,
correctness invariant (incremental == full layout), empty/all-dirty
edge cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a single-pass baseline JIT that compiles frequently-called bytecode
functions to AArch64 machine code. The compiler translates each bytecode
instruction to a call to a corresponding extern "C" helper function,
eliminating interpreter dispatch overhead while keeping implementation
simple and correct.
Key components:
- jit/compiler.rs: BaselineJit walks bytecode, emits native call sequences
and direct branches for control flow (Jump, JumpIfTrue, JumpIfFalse)
- jit/helpers.rs: extern "C" helper functions for all supported opcodes
including arithmetic, comparisons, property access with IC integration,
function calls, closures, and exception handling
- VM integration: per-function call counting (threshold=100), lazy JIT
buffer allocation, compiled code caching per GcRef, re-entrancy guard
to prevent recursive JIT dispatch, and run_to_depth for synchronous
callee execution from JIT code
Supported opcodes: LoadConst, LoadNull, LoadUndefined, LoadTrue, LoadFalse,
Move, LoadInt8, LoadGlobal, StoreGlobal, Add, Sub, Mul, Div, Rem, Neg,
BitAnd/Or/Xor, shifts, all comparisons, LogicalNot, TypeOf, Void, Jump,
JumpIfTrue/False/Nullish, Call, Return, Throw, CreateClosure, GetProperty,
SetProperty, GetPropertyByName, SetPropertyByName, CreateObject, CreateArray,
NewCell, CellLoad, CellStore, LoadUpvalue, StoreUpvalue, exception handlers.
Unsupported opcodes (Exp, InstanceOf, In, Delete, ForIn, Yield, Spread,
Await) bail out to the interpreter for correct execution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the low-level building blocks for JIT compilation in crates/js/src/jit/:
- ExecutableMemory: mmap-based allocator with W^X policy using MAP_JIT and
pthread_jit_write_protect_np for Apple Silicon
- JitBuffer: manages code pages with automatic overflow to new pages,
tracks used/free space per page
- CodePtr: type-safe wrapper for calling into JIT-compiled code
- Assembler: full AArch64 instruction emitter with label-based forward
references and backpatching, covering:
- Arithmetic: add, sub, mul, sdiv (register and immediate)
- Logic: and, orr, eor, lsl, lsr, asr
- Memory: ldr, str (register/immediate/pre-index/post-index), stp, ldp
- Branch: b, b.cond, bl, blr, br, ret, cbz, cbnz
- Comparison: cmp, tst
- Move: mov, movz, movk, mov_imm64
- FP: fmov, fadd, fsub, fmul, fdiv, fcmp, scvtf, fcvtzs
- Entry/exit stubs: prologue/epilogue saving/restoring callee-saved
registers (x19-x28, fp, lr) with proper frame pointer setup
- 88 tests including instruction encoding verification and execution
tests that JIT-compile and run AArch64 code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add polymorphic inline caches (ICs) to GetPropertyByName and SetPropertyByName
bytecode operations. Each property-access site caches up to 4 (shape, slot_index)
pairs for O(1) fast-path lookups, with megamorphic fallback when more shapes are
seen.
Key changes:
- Define InlineCache with Uninitialized/Monomorphic/Polymorphic/Megamorphic states
- Add Vec<InlineCache> to Function, allocated by the compiler per call site
- Extend GetPropertyByName/SetPropertyByName opcodes with a u16 IC index operand
- VM fast path: on IC hit, bypass shape table lookup and read/write slots directly
- Only own-property hits on shaped objects are cached (not prototype chain)
- IC updates on slow-path misses populate the cache for subsequent iterations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace HashMap<String, Property> object representation with a shape
(hidden class) system that tracks object layout transitions. Each shape
maps property names to fixed slot indices with attributes, enabling O(1)
indexed property access once the shape is known.
- Add Shape, ShapeId, ShapeTable, PropertyAttrs in new shape module
- ObjectData uses ObjectStorage enum: Shaped (shape + dense Vec<Value>
slots) or Dictionary (HashMap fallback after deletion/freeze/seal)
- Shape transitions cached by (name, attrs) so identical property
additions reuse shapes across objects
- Property deletion transitions object to dictionary mode
- All 701 existing JS tests pass unchanged
This is the foundation for inline caches and JIT property access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add BrowsingContext model with sandbox flags, origin tracking, and
parent-child relationships (browser crate)
- Add iframe element parsing with RAWTEXT mode in HTML tree builder
- Add iframe loader: discover iframes, fetch src URLs, parse nested
documents, render to pixel buffers as replaced elements
- Add window object, postMessage API, and MessageEvent to JS engine
- Add contentWindow/contentDocument with same-origin policy enforcement
- Add iframe_windows map on DomBridge for cross-context window proxies
- Integrate iframe sizes into layout pipeline as replaced elements
- Comprehensive tests for sandbox flags, browsing context tree, iframe
sizing, message serialization, and message queue
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a basic IndexedDB API implementation covering:
- Database lifecycle: open, close, deleteDatabase, version upgrades with upgradeneeded events
- Object stores: put, get, delete, clear, count, getAll with keyPath and autoIncrement support
- Transactions: readonly/readwrite mode enforcement, auto-commit with complete event, abort
- Indexes: createIndex with unique constraint, index.get for querying by non-primary key
- Structured clone: JS Value <-> IdbValue conversion for storing objects, arrays, primitives
- File-based persistence: origin-partitioned storage in ~/.we/indexeddb/ with binary serialization
- Event-driven API: deferred event firing via VM event loop (onsuccess, onerror, onupgradeneeded, oncomplete, onabort)
- Integration: DomBridge field, VM event loop drain, GC roots for pending events
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- StorageArea: in-memory key-value store with 5 MB per-origin quota,
insertion-order key tracking, binary serialization for persistence
- StorageManager: file-based persistence for localStorage (~/.we/storage/),
origin-keyed isolation, opaque origins get no storage
- JS integration: localStorage and sessionStorage globals with
getItem/setItem/removeItem/clear/key/length methods
- Property proxy: storage["key"] and storage.key work as getItem/setItem
- QuotaExceededError thrown when 5 MB limit exceeded
- VM API: set/take localStorage/sessionStorage for browser lifecycle
- 30 new tests covering unit, integration, and persistence
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Parse CSP from Content-Security-Policy and Content-Security-Policy-Report-Only HTTP headers
- Parse CSP from <meta http-equiv="Content-Security-Policy"> elements
- Support all fetch directives: default-src, script-src, style-src, img-src, font-src,
connect-src, frame-src, media-src, object-src, base-uri, form-action
- Support source expressions: 'none', 'self', 'unsafe-inline', 'unsafe-eval',
nonce sources, hash sources (sha256/sha384/sha512), scheme sources, host sources
- Enforce default-src fallback for fetch directives
- Block inline scripts unless allowed by 'unsafe-inline', matching nonce, or matching hash
- Nonce/hash presence disables 'unsafe-inline' per CSP2 spec
- Multiple policies use intersection semantics (all must allow)
- Report-only policies log violations but do not block
- Integrate CSP checks into ResourceLoader.fetch_subresource
- Integrate inline script CSP checks into script_loader with nonce attribute support
- 64 unit tests covering parsing, matching, enforcement, and edge cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add W3C Referrer Policy support with all 8 policies: no-referrer,
no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin,
strict-origin, strict-origin-when-cross-origin (default), and unsafe-url.
- New crates/net/src/referrer.rs: ReferrerPolicy enum, header/attribute
parsing, and compute_referrer() for Referer header computation
- ResourceLoader: tracks document URL and referrer policy, sets Referer
header on all outgoing requests, updates policy from Referrer-Policy
response headers
- HTML integration: extracts <meta name="referrer"> from DOM, reads
referrerpolicy attribute on <script>, <link>, and <img> elements
- Element-level policy overrides document-level policy per spec
- Strips fragment and userinfo from referrer URLs
- HTTPS-to-HTTP downgrade correctly handled for strict/downgrade policies
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a full RFC 6265bis cookie implementation:
- Set-Cookie header parsing with all attributes (Domain, Path, Expires,
Max-Age, Secure, HttpOnly, SameSite)
- CookieJar with domain/path matching, expiry, per-domain and total limits
- Automatic cookie attachment to outgoing HTTP requests and storage from
responses in HttpClient
- document.cookie getter/setter in the JS-DOM bridge (HttpOnly cookies
hidden from JS, JS cannot set HttpOnly cookies)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full CORS (Cross-Origin Resource Sharing) per the Fetch Standard:
- Simple request detection: CORS-safelisted methods (GET/HEAD/POST) and
headers (Accept, Accept-Language, Content-Language, Content-Type with
safelisted values) skip preflight
- Preflight (OPTIONS) requests for non-simple cross-origin requests with
Access-Control-Request-Method/Headers, validated against server response
- Preflight cache keyed by (origin, URL) with Access-Control-Max-Age TTL
- Access-Control-Allow-Origin validation (wildcard and exact match)
- Access-Control-Allow-Credentials enforcement (must be exact origin echo
and 'true' when credentials: include)
- Access-Control-Expose-Headers controls which response headers scripts see
- Response header filtering (only CORS-safelisted + explicitly exposed)
- Origin header sent on all cross-origin requests
- Fetch API supports mode (cors/no-cors) and credentials (omit/same-origin/
include) options
Integration points:
- crates/net/src/cors.rs: core CORS module (56 unit tests)
- crates/browser/src/loader.rs: CORS in resource loading pipeline
- crates/js/src/fetch.rs: CORS mode/credentials in Fetch API bridge
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the foundational security primitive for the browser engine:
- Origin::same_origin() with default port normalization (http/80, https/443, ftp/21)
- Origin::serialize() and Display impl for CORS header comparison
- ResourceLoader::fetch_subresource() with SOP enforcement per resource type:
scripts, stylesheets, fonts, and fetch blocked cross-origin without CORS;
images and navigation always allowed
- JS fetch() API SOP enforcement via document origin thread-local
- DomBridge origin field and document.domain property for future iframe isolation
- Updated CSS loader, script loader, and font loader to use SOP-enforcing methods
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for @font-face CSS rules to load and use web fonts:
- CSS parser: parse @font-face blocks with font-family, src (url() with
optional format()), font-weight (normal/bold/numeric), font-style
(normal/italic/oblique), and font-display descriptors
- Text crate: extend FontRegistry with web font registration from raw
bytes, with web fonts taking priority over system fonts in lookups
- Browser crate: new font_loader module that collects @font-face rules
from stylesheets, fetches font files via the resource loader, and
registers them in the FontRegistry
- Integration: page loading pipeline now loads web fonts after CSS
collection, and the rendering font is selected from the registry
(preferring web fonts when available)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds full CSS Grid support across three crates:
CSS crate: shorthand expansion for grid-column, grid-row, grid-area
Style crate: Display::Grid/InlineGrid, GridTrackSize (fr, minmax, repeat),
GridPlacement, GridAutoFlow, grid-template-columns/rows/areas parsing,
grid item placement properties, justify-items/justify-self
Layout crate: grid layout algorithm with explicit grid resolution,
auto-placement (row/column/dense), fr unit distribution, track sizing,
gap support, and justify/align item positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `svg` crate with:
- SVG path data parser (M, L, H, V, C, S, Q, T, A, Z and relative variants)
- 2D affine transform parsing (translate, rotate, scale, matrix, skewX/Y)
- Scanline rasterizer with even-odd fill and stroke expansion
- Shape-to-path converters (rect, circle, ellipse, rounded rect via cubic arcs)
- SVG color parsing (named colors, #hex, rgb())
- viewBox coordinate mapping
- Presentation attributes: fill, stroke, stroke-width, opacity, transform
- SVG text rendering via the text crate's glyph rasterizer
Integration:
- HTML parser: SVG foreign content mode with namespace tracking
- Style resolver: skip children of SVG root elements (replaced element)
- Browser: rasterize SVG elements to RGBA images for layout/render pipeline
- UA stylesheet: svg { display: block }
35 new tests covering path parsing, transforms, shape rendering, viewBox
scaling, color parsing, group transforms, and HTML-SVG integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Parse @keyframes rules with from/to keywords, percentage stops, and
multiple selectors per block (including -webkit-/-moz- prefixes)
- Parse animation shorthand and all 8 longhand properties:
animation-name, animation-duration, animation-timing-function,
animation-delay, animation-iteration-count, animation-direction,
animation-fill-mode, animation-play-state
- Animation engine reuses transition timing functions and interpolation:
cubic-bezier, steps, linear, and all ease-* variants
- Multi-keyframe interpolation across arbitrary percentage stops
- Direction support: normal, reverse, alternate, alternate-reverse
- Fill modes: none, forwards, backwards, both
- Iteration count: finite numbers and infinite
- Pause/resume support with elapsed time tracking
- Animation events: animationstart, animationiteration, animationend
- AnimationMap for per-element animation state management
- Keyframe property resolution with value resolver callback
- Style system integration: AnimationSpec in ComputedStyle, cascade
handling for animation properties at all priority levels
- 40+ new tests covering parsing, keyframe interpolation, timing,
direction, fill modes, pause/resume, events, and animation map
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new `transitions` module to the CSS crate with:
- Transition property parsing (shorthand and longhands: transition-property,
transition-duration, transition-timing-function, transition-delay)
- Timing function evaluation: linear, ease, ease-in, ease-out, ease-in-out,
cubic-bezier (Newton + bisection solver), steps(n, start|end)
- Property value interpolation engine for lengths, colors (sRGB), and numbers
with mismatched-type snap-at-50% behavior
- TransitionMap for per-element transition tracking: start, evaluate at time,
mid-flight interruption (restarts from current interpolated value), and
completion detection for transitionend events
- Integration with ComputedStyle: TransitionSpec field, cascade-level parsing
from raw ComponentValues for transition properties
- 25 unit tests covering timing functions, interpolation, parsing, and
transition state management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add crates/css/src/media.rs with MediaQueryList, MediaQuery, MediaFeature types
- Parse @media prelude into structured AST (types, features, operators, range syntax)
- Support screen/print/all types, not/only modifiers, comma OR semantics
- Support width/height features (min-, max-, range syntax including double ranges)
- Support prefers-color-scheme and prefers-reduced-motion discrete features
- Evaluate media queries against MediaContext (viewport dimensions, color scheme)
- Integrate with style crate: collect_from_rules now conditionally applies @media rules
- Add resolve_styles_with_media for full MediaContext control
- Add is_dark_mode() to platform crate for macOS dark mode detection
- 30+ unit tests for parsing and evaluation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add parsing, evaluation, and layout-time resolution for CSS math
functions per CSS Values and Units Module Level 4.
- CSS crate: MathExpr AST with recursive descent parser supporting
operator precedence, nested functions, and mixed units
- Style crate: Two-phase evaluation — resolves non-percentage units
at style time, defers percentage-based expressions to layout via
new LengthOrAuto::Calc and ClampCalc variants
- Layout crate: Resolves deferred calc expressions against containing
block dimensions at layout time
- Handles calc(100% - 20px), min/max with vw/px, clamp with mixed
units, division by zero, and nested expressions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for CSS Custom Properties per CSS Custom Properties for
Cascading Variables Module Level 1:
- Custom property declarations (--name: value) stored on ComputedStyle
- var() function substitution with fallback values
- Custom properties inherit through the DOM tree by default
- Cycle detection for circular var() references
- Support for initial/inherit/unset keywords on custom properties
- Nested var() in fallback values: var(--a, var(--b, blue))
- var() substitution in shorthand properties
- Case-sensitive custom property names
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a RenderBackend enum that abstracts over the Metal GPU and
software CPU renderers, with automatic backend selection at startup.
Falls back to software rendering when Metal is unavailable or shader
compilation fails. Logs the active backend to stderr.
- Add RenderBackend enum (Metal/Software) with detection and fallback
- Add Renderer::paint_display_list() for pre-built display list rendering
- Unify browser render pipeline into a single render_page() function
- Handle Metal errors gracefully (nil drawable skips frame)
- Add tests for backend selection, software rendering, and display lists
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a layer tree that renders subtrees to intermediate Metal textures for
correct group compositing of opacity, will-change, fixed-position, and
scrollable elements.
CSS properties:
- Add `opacity` (0.0-1.0, clamped) to ComputedStyle, LayoutBox
- Add `will-change` (transform, opacity) to ComputedStyle, LayoutBox
- Parse both properties from CSS declarations
Display list:
- Add PushLayer/PopLayer paint commands wrapping elements that need
compositing isolation
- Detect layer-needing elements: opacity < 1.0, will-change hints,
position: fixed, scrollable overflow containers
Metal GPU renderer:
- Render-to-texture for layers with opacity < 1.0: create offscreen
BGRA render target, render layer contents, composite back with opacity
- Layers with opacity=1.0 are pass-through (no intermediate texture)
- Handle nested layers via a layer state stack
- Coordinate offset tracking for layer-local rendering
- Graceful fallback if render target creation fails
Platform (Metal FFI):
- Device::new_render_target_texture() with ShaderRead | RenderTarget usage
- make_load_pass_descriptor() for resuming rendering to existing targets
Software renderer:
- Buffer-swap compositing for opacity layers
- Alpha-blend layer buffer back with group opacity on PopLayer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GpuRenderer that translates the DisplayList into batched Metal GPU
draw calls, replacing the software renderer when Metal is available.
- FillRect → solid-color quads via dummy 1x1 white texture
- DrawGlyphs → textured quads sampling from glyph atlas pages
- DrawImage → textured quads from per-node image textures
- PushClip/PopClip → Metal scissor rects with clip stack
- Batches consecutive same-texture draws into single draw calls
- Flushes batches at texture and clip boundary changes
Platform changes:
- Expose MetalView layer/queue/clear_color accessors
- Add RenderCommandEncoder::set_scissor_rect
- Make MTL_PRIMITIVE_TYPE_TRIANGLE and MetalRenderer accessors public
Browser integration:
- GPU path: style → layout → display list → Metal draw (no bitmap copy)
- Software fallback preserved when Metal unavailable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement a shelf-packing texture atlas in the render crate that packs
rasterized glyph bitmaps into R8 grayscale texture pages. The atlas
provides UV coordinates for each glyph and can generate textured quads
from TextLine data for the Metal rendering pipeline.
- Shelf-packing allocator with configurable page size (default 1024x1024)
- Multi-page support: automatically creates new pages when full
- Dirty tracking for efficient GPU texture uploads
- TexturedQuad generation from TextLine with correct UV mapping
- Integration with existing Font glyph cache for on-demand rasterization
- 19 comprehensive unit tests
Implements issue 3mi4366fkxs2g
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>