commits
Add property descriptors with writable/enumerable/configurable flags,
replacing the plain HashMap<String, Value> with HashMap<String, Property>.
This gives correct JavaScript semantics for property access, deletion,
and enumeration.
Key changes:
- Property struct with data descriptor flags (writable, enumerable, configurable)
- ObjectData gains extensible flag for future Object.preventExtensions
- FunctionData gains prototype_obj for instanceof support
- instanceof walks the prototype chain checking constructor.prototype
- delete respects the configurable flag (non-configurable = returns false)
- Compiler properly emits Delete bytecode for member expressions
- for-in loops fully implemented with ForInInit/ForInNext bytecode ops
- Property enumeration: integer indices first (sorted), then string keys
- Non-enumerable properties (e.g. array length) excluded from for-in
- SetPrototype/GetPrototype bytecode ops for prototype manipulation
- CreateClosure creates a .prototype object with constructor back-reference
15 new tests covering property descriptors, prototype chain, typeof,
instanceof, in, delete, for-in, enumeration order, and reference semantics.
All 241 JS tests pass (was 226).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a generic GC module (gc.rs) with tri-color marking (white/gray/black),
heap allocation via Vec with free-list reuse, and stop-the-world collection
triggered when live object count exceeds a configurable threshold.
Refactor VM to use GcRef handles for heap objects (plain objects and
functions) instead of owned values. This gives correct JS reference
semantics — object assignment shares identity rather than deep-cloning.
The GC traces through object properties and prototype chains to find all
reachable objects, and correctly collects cycles.
Key changes:
- gc.rs: Generic Gc<T: Traceable> with alloc/get/collect, HeapSlot with
color metadata, mark phase with gray stack, sweep with free-list
- vm.rs: Value::Object(GcRef) and Value::Function(GcRef) replace owned
data; VM allocates through self.gc and triggers collection after
allocations; root collection scans registers and globals
- lib.rs: evaluate() uses to_js_string(&gc) for GC-aware string conversion
8 new GC tests (alloc, collect, transitive reachability, cycle collection,
free-list reuse, threshold, stress) plus 3 integration tests. All 226
existing tests continue to pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the core VM execution engine for the JavaScript bytecode compiler:
- Value type with all JS primitives (Number, String, Boolean, Null,
Undefined, Object, Function)
- Register file with call frame base offsets for nested calls
- Instruction dispatch loop executing all ~50 bytecode opcodes
- Arithmetic with type coercion (ToNumber), string concatenation
- Comparison with abstract/strict equality (ECMA-262 §7.2.14/15)
- Bitwise operations with ToInt32/ToUint32 conversion
- Control flow: jumps, conditional branches, loops
- Function calls: push/pop call frames, argument passing, returns
- Native function support (fn(&[Value]) -> Result<Value, RuntimeError>)
- Object property get/set (plain objects with prototype chain)
- Exception handling with throw and handler stack unwinding
- typeof, instanceof, in, void, delete operators
- Global variable storage via HashMap
- Stack overflow protection (512 frame limit)
Also store function declarations as globals so recursive calls work,
update evaluate() to return completion values, and fix test262 harness
for new signature.
40+ unit tests and end-to-end tests including fibonacci, factorial,
loops, objects, string concat, and type coercion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix five correctness bugs in the bytecode compiler:
1. Switch default case corrupted bytecode — patch_jump(0) overwrote the
first instruction when a default case was present. Rewrote switch
compilation to use separate tracking for case jumps vs default fallthrough.
2. For-loop continue jumped to wrong target — continue inside a for-loop
body jumped before the body instead of to the update expression. Changed
continue to use forward-jump patching (like break) so the target is
resolved after body compilation.
3. Do-while continue jumped to wrong target — continue jumped to the body
start instead of the condition check. Same forward-jump patching fix.
4. Empty constructor had no Return instruction — classes without explicit
constructors created a Function with empty bytecode. Now emits
LoadUndefined + Return.
5. Class expression didn't compile methods — only the constructor was
compiled for class expressions. Now compiles methods as properties,
matching class declaration behavior.
Also adds patch_jump_to(pos, target) to BytecodeBuilder for patching
jumps to arbitrary targets (not just current offset).
6 new regression tests. All 182 JS tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add register-based bytecode instruction set designed for JIT compilation
and a recursive-descent compiler that transforms the parser AST into
bytecode functions.
New files:
- bytecode.rs — Instruction set (50+ opcodes), constant pool, function
objects, bytecode builder with jump patching, and disassembler
- compiler.rs — AST → bytecode compiler with greedy register allocation,
scope-aware local variable binding, and support for all statement and
expression types
Instruction categories: register loads, arithmetic, bitwise, comparison,
logical, control flow (jumps, calls, returns), object/property access,
closures, and small-integer optimization (LoadInt8).
Compiler handles: variable declarations, function/class/arrow declarations,
if/else, for/while/do-while loops with break/continue/labels, switch,
try/catch, member access, assignment (simple and compound), logical
short-circuit, conditional expressions, template literals, destructuring,
object/array literals, and nested function compilation.
52 unit tests covering bytecode encoding, constant pool dedup, jump
patching, disassembler output, and compilation of all major grammar
productions. All 176 workspace JS tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
export default function() {} and export default class {} are valid
JavaScript but the parser incorrectly required a name. Check whether
the function/class has a name and route to expression parsing when
anonymous.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a recursive-descent JavaScript parser with Pratt expression parsing
for ECMAScript 2024. Transforms the token stream from the lexer into an
Abstract Syntax Tree.
AST node types cover:
- All expression types (literals, binary, unary, assignment, member access,
call, new, arrow functions, template literals, spread, yield, await)
- All statement types (if, for/for-in/for-of, while, do-while, switch,
try/catch/finally, return, throw, break, continue, labeled, with)
- Variable declarations (var/let/const) with destructuring patterns
- Function declarations (sync, async, generators)
- Class declarations (constructor, methods, getters/setters, static)
- Import/export declarations (default, named, namespace, re-export)
Features:
- Operator precedence via Pratt parsing with binding power table
- Automatic Semicolon Insertion (ASI) using lexer newline tracking
- Arrow function detection with expression-to-pattern reinterpretation
- Destructuring patterns (array, object, default values, rest)
- for-in/for-of disambiguation with allow_in flag
- 73 unit tests covering all grammar productions and error cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
\<newline> in string/template literals is a line continuation per
ECMAScript spec — it should produce no character, not a newline.
Changed scan_escape_sequence to return Option<char>, returning None
for line continuations. Added test for this behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a full JavaScript lexer to the we-js crate supporting all ES2024
token types: keywords, identifiers (including Unicode), numeric literals
(decimal, hex, octal, binary with separators), string literals with full
escape sequences, template literals with ${} substitution tracking,
regular expression literals with context-based disambiguation, and all
punctuators/operators. Includes source position tracking (line/column)
and newline tracking for automatic semicolon insertion.
48 unit tests covering all token types, edge cases, and error handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a container has only float children and bare inline content (no
in-flow block siblings), normalize_children returned early without
wrapping the inline content in anonymous blocks. This caused the text
to be silently dropped during layout_block_children since compute_layout
is a no-op for TextRun/Inline boxes.
Include floated children in the has_block check so that inline content
gets properly wrapped in anonymous blocks and laid out through the
inline formatting context.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add float layout support to the layout engine:
- Parse float (none/left/right) and clear (none/left/right/both) CSS properties
- Float positioning: left floats at left edge, right floats at right edge
- Float stacking: multiple floats stack horizontally, wrapping when full
- Line box shortening: inline content flows around active floats
- Clear property: elements move below cleared floats
- BFC containment: overflow:hidden/scroll containers expand to contain floats
- Floated inline elements are blockified per CSS2 §9.7
Implements issue 3mhlhnjkxcr2x
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Sticky variant to Position enum and parse "sticky" keyword
- Sticky elements participate in normal flow (like relative positioning)
- Store sticky_constraint rect on LayoutBox (parent's content area)
- Compute sticky paint-time offset in render crate based on scroll state
- Support top stickiness with containing block constraint clamping
- Update scroll container reference point tracking through paint recursion
- Add tests: parsing, normal flow layout, constraint rect, scroll sticking,
and parent constraint behavior
Implements issue 3mhlhoituxu2u
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add z_index field to ComputedStyle and parse CSS z-index property
- Remove absolute/fixed elements from normal flow (block, inline, flex layout)
- Position absolute elements relative to nearest positioned ancestor's padding box
- Position fixed elements relative to viewport
- Support left/right/top/bottom offsets with percentage resolution
- Support width/height stretching when both sides are specified
- Implement stacking context paint order: negative z-index, in-flow, non-negative z-index
- Update normalize_children and margin collapsing to exclude out-of-flow elements
- Add tests for absolute positioning, fixed positioning, z-index, stretching, and
bottom/right positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per CSS Box Alignment §8, row-gap applies between rows and column-gap
between columns. In a column flex container the main axis is vertical,
so the gap between items should use row-gap (not column-gap) and the
gap between flex lines should use column-gap (not row-gap).
Introduces main_gap/cross_gap variables that swap based on flex direction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full flexbox support with flex container and item properties:
CSS parsing:
- Parse display: flex/inline-flex
- Parse flex container props: flex-direction, flex-wrap, justify-content,
align-items, align-content, gap/row-gap/column-gap
- Parse flex item props: flex-grow, flex-shrink, flex-basis, align-self, order
- Expand flex, flex-flow, and gap shorthands
Layout algorithm (CSS Flexbox Level 1 §9):
- Determine main/cross axes from flex-direction
- Content-based flex-basis sizing for auto basis
- Distribute free space via flex-grow/flex-shrink
- Line wrapping (flex-wrap: wrap/wrap-reverse)
- Main axis justification (all justify-content modes)
- Cross axis alignment (all align-items/align-self modes)
- Multi-line align-content distribution
- Visual ordering via order property
- Gap spacing between items
- Reverse direction support (row-reverse, column-reverse)
Tests: 10 new flex layout tests covering row/column direction,
grow/shrink, justify-content, align-items, wrap, gap, and order.
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 scrollable overflow regions for overflow:scroll and overflow:auto
boxes, with rendered scroll bars and mouse wheel event support.
Layout crate:
- Add content_height field to LayoutBox tracking natural content height
before CSS height override (used for overflow detection)
- Reserve SCROLLBAR_WIDTH (15px) from content area for overflow:scroll
- Export SCROLLBAR_WIDTH constant
Render crate:
- Add ScrollState type (HashMap<NodeId, (f32, f32)>) for scroll offsets
- Modify display list builder to accept scroll state and translate offset
- Apply scroll offset to child coordinates in scrollable containers
- Render vertical scroll bars (track + proportional thumb) for
overflow:scroll (always) and overflow:auto (when content overflows)
- Add page-level scroll support via paint_with_scroll()
- Add build_display_list_with_page_scroll() for viewport scrolling
- 6 new tests: scrollbar rendering, scroll offset, thumb proportionality,
overflow:auto conditional scrollbar, page scroll
Platform crate:
- Add scrollWheel: event handler to WeView class
- Add set_scroll_handler() for registering scroll callbacks
- Forward scroll delta (dx, dy) and mouse position to handler
Browser crate:
- Add page_scroll_y, content_height, scroll_offsets to BrowserState
- Handle scroll wheel events: update page scroll, clamp to bounds,
re-render
- Pass scroll state through rendering pipeline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add clip rect support to the rendering pipeline so that boxes with
overflow != visible clip their children's content to the padding box.
Render crate changes:
- Add PushClip/PopClip variants to PaintCommand
- Maintain a clip rect stack in Renderer that intersects nested clips
- Apply active clip rect in fill_rect, composite_glyph, and draw_image
- overflow:hidden, overflow:auto, and overflow:scroll all clip content
- overflow:visible (default) continues to render without clipping
Layout crate fix:
- Fix is_empty_block to not treat blocks with explicit CSS height as
empty (they should not self-collapse per CSS2 §8.3.1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread viewport dimensions through style resolution so viewport units
resolve correctly: 1vw = 1% of viewport width, 1vh = 1% of viewport
height, vmin/vmax use the smaller/larger dimension.
For layout properties (width, height, margin, padding), percentages are
now preserved as LengthOrAuto::Percentage through style computation and
resolved during layout against the containing block width. Height
percentages resolve against viewport height. Per CSS spec, even vertical
margins and padding resolve against containing block width.
Changes:
- Add Percentage(f32) variant to LengthOrAuto
- Change ComputedStyle padding fields from f32 to LengthOrAuto
- Add viewport parameter to resolve_styles, threaded through resolution
- resolve_length_unit now computes vw/vh/vmin/vmax from viewport dims
- Layout resolves percentage width/height/margin/padding against
containing block; nested percentages compound correctly
- Store css_margin/css_padding/css_offsets on LayoutBox for deferred
resolution during layout
- 9 new tests covering all acceptance criteria
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire up visibility property through the layout and render pipeline:
- Add visibility field to LayoutBox, populated from ComputedStyle
- Renderer skips painting (background, borders, text, images) for
hidden/collapse elements but still recurses into children
- Children can override with visibility:visible per CSS spec
- display:none already worked (excluded from layout tree); verified
9 new tests: 5 layout tests (display:none exclusion, hidden preserves
space, inheritance, visible override, collapse behavior) and 4 render
tests (hidden not painted, visible child of hidden parent painted,
collapse not painted, display:none not in display list).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add BoxSizing enum and box_sizing field to ComputedStyle with CSS
parsing support. Layout engine now respects explicit CSS width/height
and adjusts content dimensions based on box-sizing mode:
- content-box (default): width/height apply to content area only
- border-box: width/height include padding and border
Content area clamps to 0 when padding+border exceeds specified size
in border-box mode. Property is not inherited per spec.
9 new tests covering both modes, clamping, non-inheritance, and height.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements CSS2 §8.3.1 margin collapsing:
- Adjacent sibling margins collapse (gap = max, not sum)
- Parent-child margin collapsing via pre_collapse_margins pass
- Empty block self-collapsing (top+bottom margins fold together)
- Negative margin handling (positive+negative=sum, both negative=min)
- Collapsing blocked by border, padding, or overflow!=visible (BFC)
Adds overflow field to LayoutBox for BFC detection. Updates existing
tests to reflect correct collapsed margin behavior and adds 9 new
tests covering all collapsing scenarios.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add relative positioning support to the layout engine. After normal-flow
layout, elements with position: relative are visually shifted by their
top/right/bottom/left offset values without affecting surrounding elements.
- Add position and relative_offset fields to LayoutBox
- Resolve offset conflicts per CSS spec (top wins over bottom, left over right)
- Recursively shift box rect, text lines, and all descendants
- Add 7 tests covering offsets, sibling independence, conflicts, and auto values
Wire together all Phase 8 components into the browser's navigation flow:
- Use css_loader::collect_stylesheets for external <link> and inline <style>
- Use img_loader::collect_images to fetch and decode <img> elements
- Store pre-fetched PageState (DOM, stylesheet, images) so window resizes
only re-style/re-layout/re-render without re-fetching
- Show error page for network failures instead of process::exit
- Preserve base URL from HTTP response for resolving relative subresources
- Generate file:// base URL for local file paths
Implements issue 3mhktaciaf42q.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add about: scheme handling to ResourceLoader:
- Recognize about:blank and return a minimal empty HTML document
(<!DOCTYPE html><html><head></head><body></body></html>)
- UTF-8 encoding, no network requests
- Unsupported about: URLs return InvalidUrl error
Update browser main to use about:blank as default:
- No URL argument opens about:blank instead of hardcoded demo page
- URL arguments (http://, https://, about:, data:) load via ResourceLoader
- File path arguments still work as before
4 tests covering fetch/fetch_url paths, DOM structure validation,
and unsupported about: URL rejection.
Implements issue 3mhkt7vaxsb23
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add data_url module to the url crate:
- Base64 decoder (RFC 4648): standard alphabet, whitespace stripping, padding
- Data URL parser: extract MIME type, charset, base64/percent-encoded payload
- Default MIME type text/plain;charset=US-ASCII when omitted
Integrate with ResourceLoader in browser crate:
- Handle data: URLs in both fetch() and fetch_url() without network access
- Classify decoded content into Html/Css/Image/Other resource types
- Decode text resources using charset from data URL parameters
44 tests covering base64 decoding, data URL parsing, MIME extraction,
percent decoding, and ResourceLoader integration.
Implements issue 3mhkt7m45472x
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add img_loader module to the browser crate that loads images from the DOM:
- Scan DOM for <img src="..."> elements in document order
- Fetch image data via ResourceLoader with URL resolution
- Detect format from magic bytes (PNG: 89504E47, JPEG: FFD8, GIF: GIF8)
- Decode using image crate decoders (PNG, JPEG, GIF)
- Parse width/height attributes with proportional scaling
- Graceful degradation: failed loads store alt text, no crash
Layout integration:
- Add replaced_size field to LayoutBox for replaced elements
- Accept image_sizes map in layout() for intrinsic/attribute dimensions
- Replaced elements use their dimensions instead of child layout
Render integration:
- Add DrawImage variant to PaintCommand
- Nearest-neighbor scaling with RGBA→BGRA conversion
- Alpha compositing for semi-transparent image pixels
37 tests covering format detection, dimension parsing/resolution,
DOM scanning, graceful failure, error display, and PNG decoding.
Implements issue 3mhkt7br4jx25
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add css_loader module to the browser crate that collects CSS from the DOM:
- Scan DOM for <style> elements (inline CSS) and <link rel="stylesheet"> (external)
- Fetch external stylesheets via ResourceLoader with encoding detection
- Resolve @import rules recursively (max depth 5 to prevent cycles)
- Basic media attribute support (screen, all)
- Type attribute validation (text/css default)
- Graceful degradation: failed loads are silently skipped
- Merge all rules into a single Stylesheet in document order
37 tests covering DOM scanning, classification, media matching, text
collection, import resolution, error handling, and edge cases.
Implements issue 3mhkt6vtv3q2g
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ResourceLoader to the browser crate that integrates the net, encoding,
url, and image crates into a unified resource fetching API:
- ResourceLoader wraps HttpClient for HTTP/HTTPS fetching
- Content-Type parsing determines resource type (HTML, CSS, image, other)
- WHATWG encoding sniffing for HTML (BOM > HTTP > meta prescan > default)
- BOM/HTTP charset detection for non-HTML text resources (default UTF-8)
- Relative URL resolution via base URL support
- HTTP error status handling (4xx, 5xx)
- Resource enum: Html, Css, Image, Other with appropriate metadata
30 tests covering MIME classification, text decoding (BOM, HTTP charset,
meta prescan, Windows-1252 special chars), URL resolution, and error types.
Implements issue 3mhkt6hnbhp25
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add encoding detection per WHATWG Encoding Standard and HTML spec:
- BOM sniffing for UTF-8, UTF-16LE, UTF-16BE
- HTTP Content-Type charset extraction (quoted/unquoted values)
- HTML meta prescan: scan first 1024 bytes for <meta charset> and
<meta http-equiv="Content-Type" content="...;charset=...">
- Priority: BOM > HTTP header > meta prescan > default (Windows-1252)
- UTF-16 from HTTP/meta overridden to UTF-8 per spec
- EncodingSource enum for tracking detection method confidence
39 new tests covering all detection methods and priority ordering.
Implements issue 3mhkt62ryxo2l
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add all 27 WHATWG single-byte encodings to the encoding crate:
- Windows-1252 (with ISO-8859-1 and US-ASCII aliases per WHATWG spec)
- ISO-8859-2 through ISO-8859-16 (excluding 8859-9 which maps to Windows-1254)
- Windows-874, Windows-1250 through Windows-1258
- KOI8-R, KOI8-U
- macintosh, x-mac-cyrillic
- IBM866
Each encoding uses a 128-entry u16 lookup table for bytes 0x80-0xFF.
All WHATWG label aliases are registered for case-insensitive lookup.
32 new tests covering per-encoding correctness and error handling.
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure Rust implementation of UTF-8 and UTF-16 text encoding/decoding
per the WHATWG Encoding Standard:
- UTF-8 decoder (streaming state machine with replacement/fatal modes)
- UTF-8 encoder
- UTF-16LE/BE decoders with surrogate pair handling and BOM stripping
- Encoding label lookup (case-insensitive, whitespace-trimmed)
- BOM sniffing utility
- Public API: decode(), decode_strict(), encode(), lookup(), bom_sniff()
- 93 unit tests covering edge cases (overlong, surrogates, truncated, BOM)
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure Rust baseline JPEG decoder in the image crate supporting:
- JFIF marker parsing (SOI, APP0/APP1, DQT, SOF0, DHT, SOS, DRI, EOI)
- Huffman entropy decoding (DC and AC coefficients)
- 8x8 block-based inverse DCT (Loeffler algorithm, integer fixed-point)
- Dequantization with DQT tables
- Chroma subsampling: 4:4:4, 4:2:2, 4:2:0
- YCbCr to RGB color conversion (BT.601 fixed-point)
- Restart marker support
- Grayscale JPEG support
- 28 unit tests covering Huffman, IDCT, color conversion, parsing, and
end-to-end decoding of hand-crafted JPEG streams
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GIF LZW uses "early change" — the code size must bump when next_code
reaches (1 << code_size), not after it exceeds it. Without this fix,
the decoder would read codes with the wrong bit width for GIFs with
enough unique codes to trigger a code size increase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust GIF decoder in the image crate supporting:
- GIF87a and GIF89a format parsing
- LZW decompression with variable-width codes, clear/EOI codes
- Global and local color tables
- Graphic Control Extension (transparency, delay, disposal methods)
- Multi-frame animated GIFs with canvas compositing
- Interlaced image support (4-pass Adam7-style deinterlacing)
- Sub-frame positioning (frames smaller than logical screen)
- Application, comment, and plain text extension skipping
- API: decode_gif() for first frame, decode_gif_frames() for all frames
31 unit tests covering LZW decompression, deinterlacing, frame decoding,
transparency, animation, local color tables, extensions, and error cases.
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust PNG decoder supporting all color types (grayscale, RGB,
indexed, grayscale+alpha, RGBA), bit depths 1-16, scanline filtering
(None/Sub/Up/Average/Paeth), Adam7 interlacing, tRNS transparency,
CRC-32 validation, and multiple IDAT chunk concatenation.
40+ unit tests covering all color types, bit depths, filter types,
interlacing, transparency, error cases, and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Image struct (always RGBA8) with conversions from grayscale,
grayscale+alpha, RGB, RGBA, indexed color, and indexed+alpha.
29 unit tests covering all conversion paths and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse zlib header (CMF/FLG), validate header checksum, delegate to
DEFLATE for compressed data, verify Adler-32 checksum of output.
21 unit tests covering Adler-32, header validation, round-trip
decompression, error propagation, and all window sizes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust DEFLATE decompression supporting all three block types:
- Non-compressed blocks (BTYPE=00) with LEN/NLEN validation
- Fixed Huffman codes (BTYPE=01) per RFC 1951 §3.2.6
- Dynamic Huffman codes (BTYPE=10) with code length decoding
Implementation details:
- LSB-first bit reader with peek/consume pattern for Huffman decoding
- Two-level Huffman lookup table (primary + subtable for long codes)
- LZ77 back-reference decoding with overlapping copy support
- Handles end-of-stream gracefully when final code needs fewer bits
than the primary table width
33 unit tests covering BitReader, Huffman trees, all block types,
back-references, error cases, and round-trip verification against
zlib-generated test vectors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace strip_prefix-based header matching (only matched exact case and
lowercase) with a proper case-insensitive helper that splits on the
first colon and compares the header name using eq_ignore_ascii_case.
Adds tests for all-caps header names (CONTENT-LENGTH, TRANSFER-ENCODING).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
High-level HTTP client in the net crate bringing together TCP, TLS 1.3,
DNS, URL parsing, and HTTP message handling:
- HttpClient with get(), post(), request() methods
- Scheme handling: http:// (plain TCP) and https:// (TLS)
- Connection pooling by (host, port, is_tls) with max idle time and
max connections per host
- Redirect following (301, 302, 307, 308) with configurable max
- Configurable connect and read timeouts
- Streaming response reader: header detection, Content-Length,
chunked Transfer-Encoding, and read-until-close strategies
- std::io::Read and Write trait impls for TcpConnection
30+ unit tests covering error types, configuration, connection pool,
URL path building, header parsing, body strategy selection, and
chunked terminator detection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HTTP/1.1 message parser (RFC 7230, 7231) for the net crate:
- Request serialization (GET, POST, HEAD, PUT, DELETE, OPTIONS, PATCH)
- Response parsing: status line, headers, body
- Headers collection with case-insensitive name lookup
- Content-Length body reading
- Chunked Transfer-Encoding decoding (RFC 7230 §4.1)
- Content-Type parsing with charset extraction
- Proper handling of 1xx/204/304 no-body responses
55 tests covering all acceptance criteria.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The application traffic secrets (RFC 8446 §7.1) must be derived from
the transcript hash covering ClientHello...server Finished, not
including the client Finished message. The code was using
transcript.current_hash() after updating with client_finished_msg,
producing incorrect application keys that would fail against real
servers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- random_bytes: panic instead of silently using zero-filled buffers when
/dev/urandom fails — using all-zero keys is a critical security issue
- Rename _ee_body to ee_body since the variable is actually used
- Fix wildcard hostname matching to reject empty labels (e.g. ".example.com"
should not match "*.example.com")
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full TLS 1.3 client handshake: ClientHello with SNI/supported_versions/
key_share/signature_algorithms extensions, ServerHello processing,
ECDHE key exchange (X25519), encrypted handshake message processing
(EncryptedExtensions, Certificate, CertificateVerify, Finished),
certificate chain validation, server name verification with wildcard
matching, key phase transitions, and TlsStream type for application data.
Supports RSA PKCS#1 v1.5 and ECDSA (P-256/P-384) signature verification
in CertificateVerify. Validates server certificates against embedded
root CA store (ISRG Root X1, DigiCert, GlobalSign).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Key schedule for deriving encryption keys from shared secrets using HKDF.
Includes HKDF-Expand-Label, Derive-Secret, transcript hashing, traffic
key/IV derivation, and Finished verify data computation. Supports all
three TLS 1.3 cipher suites (AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305).
Also adds Clone derive to SHA-256, SHA-384, SHA-512 hashers in the crypto
crate to support transcript hash snapshotting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Record layer protocol in the net crate for framing and encrypting TLS
records. ContentType enum (ChangeCipherSpec, Alert, Handshake,
ApplicationData). Plaintext record read/write with header framing and
size enforcement. Encrypted record support via RecordCryptoState with
per-record nonce construction (XOR base IV with sequence number),
inner content type hiding, and AEAD using AES-128-GCM, AES-256-GCM,
or ChaCha20-Poly1305. Alert protocol with close_notify and fatal error
handling. RecordLayer type combining plaintext and encrypted modes with
runtime crypto state switching.
36 tests covering content types, alert encode/decode, nonce construction,
plaintext record I/O, encrypted roundtrips for all cipher suites,
sequence numbering, tamper detection, record overflow, and RecordLayer
integration with plaintext-to-encrypted transitions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DNS resolver in the net crate for resolving hostnames to IP addresses
via UDP queries to system nameservers. Parses /etc/resolv.conf for
nameserver discovery with fallback to Google DNS. Supports A and AAAA
record types, DNS name compression pointers, NXDOMAIN handling, timeout
and retry across multiple nameservers, and direct IP address passthrough.
DnsResolver type with system() and with_nameservers() constructors,
configurable timeout, and resolve() method. Convenience resolve()
function for one-shot lookups. 38 tests covering name encoding, query
building, response parsing, compression pointers, resolv.conf parsing,
address extraction, error types, and real hostname resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TcpConnection type wrapping std::net::TcpStream with connect,
connect_timeout, read, write, read_exact, write_all, flush, timeout
configuration, and shutdown. NetError enum with automatic mapping
from io::Error (ConnectionRefused, TimedOut variants). BufferedReader
and BufferedWriter wrappers for efficient line-oriented I/O with
split read/write support via stream cloning.
15 tests covering error types, connection failures, loopback echo,
buffered line reading, buffered read/write pairs, timeouts, and
debug formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
URL record type with scheme, username, password, host, port, path,
query, fragment. State-machine parser handling special schemes (http,
https, ftp, ws, wss, file) with default ports. Host parsing for
domains, IPv4 (decimal/hex/octal), and IPv6 (including IPv4-mapped
and :: compression). Percent-encoding/decoding per spec encode sets
(C0, fragment, query, path, userinfo). Relative URL resolution via
base URL. URL serialization with round-trip fidelity. Origin
derivation (tuple for special schemes, opaque otherwise).
88 tests covering absolute URLs, scheme handling, host types,
IPv4/IPv6 parsing and serialization, percent encoding, path dot
resolution, relative URL resolution, serialization round-trips,
file URLs, and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PEM decoding with custom Base64 decoder, X.509v3 certificate parsing
extracting version, serial, issuer, subject, validity, SPKI, and
extensions (Basic Constraints, Key Usage, SAN, AKI, SKI). Certificate
chain validation with signature verification (RSA + ECDSA), validity
period checks, and CA constraint enforcement. Embedded root CA store
with ISRG Root X1, DigiCert Global Root G2, and GlobalSign Root R3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Elliptic curve arithmetic in Jacobian coordinates with point addition,
doubling, and Montgomery ladder scalar multiplication. Field arithmetic
over the prime fields of P-256 (secp256r1) and P-384 (secp384r1) using
the existing BigUint type.
ECDSA verification per FIPS 186-4 §4.1.4 with Shamir's trick for
multi-scalar multiplication. Parses EC public keys from uncompressed
point format and SubjectPublicKeyInfo DER. Parses DER-encoded
ECDSA signatures.
34 tests including: curve parameter validation, point arithmetic,
RFC 6979 test vectors (P-256/SHA-256), self-generated test vectors
for both P-256 and P-384, signature rejection, and DER parsing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BigUint type with arbitrary-precision arithmetic backed by little-endian
u64 limbs. Supports modular exponentiation via Montgomery multiplication
for odd moduli (RSA) with fallback for even moduli.
RSA public key parsing from both PKCS#1 RSAPublicKey and PKCS#8
SubjectPublicKeyInfo DER formats. RSASSA-PKCS1-v1_5-VERIFY with
EMSA-PKCS1-v1_5 encoding for SHA-256, SHA-384, and SHA-512.
Constant-time signature comparison. Key sizes 2048-4096 bits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DerParser reads TLV structures from DER-encoded byte slices. Supports
all primitive types needed for X.509 certificates: BOOLEAN, INTEGER,
BIT STRING, OCTET STRING, NULL, OID, UTF8String, PrintableString,
IA5String, UTCTime, GeneralizedTime. Constructed types: SEQUENCE, SET.
Context-specific tags with explicit/implicit tagging.
Includes well-known OID constants for RSA, ECDSA, SHA-2, X.509
extensions, and X.500 attribute types. OID encode/decode with dotted
notation. Rejects non-DER encodings (indefinite length, non-minimal
integers/lengths).
45 tests covering all types, DER validation, real certificate fragments,
and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Field arithmetic in GF(2^255 - 19) using 5x51-bit limb representation.
Montgomery ladder scalar multiplication on Curve25519. Constant-time
implementation with no secret-dependent branches or memory accesses.
Passes RFC 7748 §6.1 DH test vectors and §5.2 iterated test vector
(1,000 iterations).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The constant-time conditional select between h and g in the Poly1305
final reduction was missing h4/g4. When h >= p (2^130-5), the code
selected g for h0-h3 but left h4 unchanged, producing incorrect tags
for inputs where the accumulator exceeds the prime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pure Rust ChaCha20-Poly1305 authenticated encryption in the crypto crate:
- ChaCha20 stream cipher: quarter round, block function (20 rounds),
counter-mode encryption with 256-bit key, 96-bit nonce, 32-bit counter
- Poly1305 one-time MAC: GF(2^130-5) using 5 limbs of 26 bits,
clamped r key, constant-time final reduction
- AEAD construction: Poly1305 key generation from ChaCha20 block 0,
encrypt-then-MAC with RFC 8439 padding and length encoding
- Constant-time tag comparison for secure decryption
- 13 tests: RFC 8439 test vectors (§2.1.1, §2.3.2, §2.4.2, §2.5.2,
§2.6.2, §2.8.2), tag tamper detection, and round-trip tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pure Rust AES-GCM authenticated encryption in the crypto crate:
- AES block cipher (FIPS 197): key expansion and encrypt for 128/256-bit keys
- GHASH: constant-time GF(2^128) multiplication using bit masking
- GCM encrypt/decrypt with 96-bit nonce, 128-bit authentication tag, and AAD
- Constant-time tag comparison for secure decryption
- 25 tests including NIST SP 800-38D test vectors (cases 1-4, 13-16),
tag tamper detection, and encrypt/decrypt round-trips
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add property descriptors with writable/enumerable/configurable flags,
replacing the plain HashMap<String, Value> with HashMap<String, Property>.
This gives correct JavaScript semantics for property access, deletion,
and enumeration.
Key changes:
- Property struct with data descriptor flags (writable, enumerable, configurable)
- ObjectData gains extensible flag for future Object.preventExtensions
- FunctionData gains prototype_obj for instanceof support
- instanceof walks the prototype chain checking constructor.prototype
- delete respects the configurable flag (non-configurable = returns false)
- Compiler properly emits Delete bytecode for member expressions
- for-in loops fully implemented with ForInInit/ForInNext bytecode ops
- Property enumeration: integer indices first (sorted), then string keys
- Non-enumerable properties (e.g. array length) excluded from for-in
- SetPrototype/GetPrototype bytecode ops for prototype manipulation
- CreateClosure creates a .prototype object with constructor back-reference
15 new tests covering property descriptors, prototype chain, typeof,
instanceof, in, delete, for-in, enumeration order, and reference semantics.
All 241 JS tests pass (was 226).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a generic GC module (gc.rs) with tri-color marking (white/gray/black),
heap allocation via Vec with free-list reuse, and stop-the-world collection
triggered when live object count exceeds a configurable threshold.
Refactor VM to use GcRef handles for heap objects (plain objects and
functions) instead of owned values. This gives correct JS reference
semantics — object assignment shares identity rather than deep-cloning.
The GC traces through object properties and prototype chains to find all
reachable objects, and correctly collects cycles.
Key changes:
- gc.rs: Generic Gc<T: Traceable> with alloc/get/collect, HeapSlot with
color metadata, mark phase with gray stack, sweep with free-list
- vm.rs: Value::Object(GcRef) and Value::Function(GcRef) replace owned
data; VM allocates through self.gc and triggers collection after
allocations; root collection scans registers and globals
- lib.rs: evaluate() uses to_js_string(&gc) for GC-aware string conversion
8 new GC tests (alloc, collect, transitive reachability, cycle collection,
free-list reuse, threshold, stress) plus 3 integration tests. All 226
existing tests continue to pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the core VM execution engine for the JavaScript bytecode compiler:
- Value type with all JS primitives (Number, String, Boolean, Null,
Undefined, Object, Function)
- Register file with call frame base offsets for nested calls
- Instruction dispatch loop executing all ~50 bytecode opcodes
- Arithmetic with type coercion (ToNumber), string concatenation
- Comparison with abstract/strict equality (ECMA-262 §7.2.14/15)
- Bitwise operations with ToInt32/ToUint32 conversion
- Control flow: jumps, conditional branches, loops
- Function calls: push/pop call frames, argument passing, returns
- Native function support (fn(&[Value]) -> Result<Value, RuntimeError>)
- Object property get/set (plain objects with prototype chain)
- Exception handling with throw and handler stack unwinding
- typeof, instanceof, in, void, delete operators
- Global variable storage via HashMap
- Stack overflow protection (512 frame limit)
Also store function declarations as globals so recursive calls work,
update evaluate() to return completion values, and fix test262 harness
for new signature.
40+ unit tests and end-to-end tests including fibonacci, factorial,
loops, objects, string concat, and type coercion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix five correctness bugs in the bytecode compiler:
1. Switch default case corrupted bytecode — patch_jump(0) overwrote the
first instruction when a default case was present. Rewrote switch
compilation to use separate tracking for case jumps vs default fallthrough.
2. For-loop continue jumped to wrong target — continue inside a for-loop
body jumped before the body instead of to the update expression. Changed
continue to use forward-jump patching (like break) so the target is
resolved after body compilation.
3. Do-while continue jumped to wrong target — continue jumped to the body
start instead of the condition check. Same forward-jump patching fix.
4. Empty constructor had no Return instruction — classes without explicit
constructors created a Function with empty bytecode. Now emits
LoadUndefined + Return.
5. Class expression didn't compile methods — only the constructor was
compiled for class expressions. Now compiles methods as properties,
matching class declaration behavior.
Also adds patch_jump_to(pos, target) to BytecodeBuilder for patching
jumps to arbitrary targets (not just current offset).
6 new regression tests. All 182 JS tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add register-based bytecode instruction set designed for JIT compilation
and a recursive-descent compiler that transforms the parser AST into
bytecode functions.
New files:
- bytecode.rs — Instruction set (50+ opcodes), constant pool, function
objects, bytecode builder with jump patching, and disassembler
- compiler.rs — AST → bytecode compiler with greedy register allocation,
scope-aware local variable binding, and support for all statement and
expression types
Instruction categories: register loads, arithmetic, bitwise, comparison,
logical, control flow (jumps, calls, returns), object/property access,
closures, and small-integer optimization (LoadInt8).
Compiler handles: variable declarations, function/class/arrow declarations,
if/else, for/while/do-while loops with break/continue/labels, switch,
try/catch, member access, assignment (simple and compound), logical
short-circuit, conditional expressions, template literals, destructuring,
object/array literals, and nested function compilation.
52 unit tests covering bytecode encoding, constant pool dedup, jump
patching, disassembler output, and compilation of all major grammar
productions. All 176 workspace JS tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a recursive-descent JavaScript parser with Pratt expression parsing
for ECMAScript 2024. Transforms the token stream from the lexer into an
Abstract Syntax Tree.
AST node types cover:
- All expression types (literals, binary, unary, assignment, member access,
call, new, arrow functions, template literals, spread, yield, await)
- All statement types (if, for/for-in/for-of, while, do-while, switch,
try/catch/finally, return, throw, break, continue, labeled, with)
- Variable declarations (var/let/const) with destructuring patterns
- Function declarations (sync, async, generators)
- Class declarations (constructor, methods, getters/setters, static)
- Import/export declarations (default, named, namespace, re-export)
Features:
- Operator precedence via Pratt parsing with binding power table
- Automatic Semicolon Insertion (ASI) using lexer newline tracking
- Arrow function detection with expression-to-pattern reinterpretation
- Destructuring patterns (array, object, default values, rest)
- for-in/for-of disambiguation with allow_in flag
- 73 unit tests covering all grammar productions and error cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
\<newline> in string/template literals is a line continuation per
ECMAScript spec — it should produce no character, not a newline.
Changed scan_escape_sequence to return Option<char>, returning None
for line continuations. Added test for this behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a full JavaScript lexer to the we-js crate supporting all ES2024
token types: keywords, identifiers (including Unicode), numeric literals
(decimal, hex, octal, binary with separators), string literals with full
escape sequences, template literals with ${} substitution tracking,
regular expression literals with context-based disambiguation, and all
punctuators/operators. Includes source position tracking (line/column)
and newline tracking for automatic semicolon insertion.
48 unit tests covering all token types, edge cases, and error handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a container has only float children and bare inline content (no
in-flow block siblings), normalize_children returned early without
wrapping the inline content in anonymous blocks. This caused the text
to be silently dropped during layout_block_children since compute_layout
is a no-op for TextRun/Inline boxes.
Include floated children in the has_block check so that inline content
gets properly wrapped in anonymous blocks and laid out through the
inline formatting context.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add float layout support to the layout engine:
- Parse float (none/left/right) and clear (none/left/right/both) CSS properties
- Float positioning: left floats at left edge, right floats at right edge
- Float stacking: multiple floats stack horizontally, wrapping when full
- Line box shortening: inline content flows around active floats
- Clear property: elements move below cleared floats
- BFC containment: overflow:hidden/scroll containers expand to contain floats
- Floated inline elements are blockified per CSS2 §9.7
Implements issue 3mhlhnjkxcr2x
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Sticky variant to Position enum and parse "sticky" keyword
- Sticky elements participate in normal flow (like relative positioning)
- Store sticky_constraint rect on LayoutBox (parent's content area)
- Compute sticky paint-time offset in render crate based on scroll state
- Support top stickiness with containing block constraint clamping
- Update scroll container reference point tracking through paint recursion
- Add tests: parsing, normal flow layout, constraint rect, scroll sticking,
and parent constraint behavior
Implements issue 3mhlhoituxu2u
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add z_index field to ComputedStyle and parse CSS z-index property
- Remove absolute/fixed elements from normal flow (block, inline, flex layout)
- Position absolute elements relative to nearest positioned ancestor's padding box
- Position fixed elements relative to viewport
- Support left/right/top/bottom offsets with percentage resolution
- Support width/height stretching when both sides are specified
- Implement stacking context paint order: negative z-index, in-flow, non-negative z-index
- Update normalize_children and margin collapsing to exclude out-of-flow elements
- Add tests for absolute positioning, fixed positioning, z-index, stretching, and
bottom/right positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per CSS Box Alignment §8, row-gap applies between rows and column-gap
between columns. In a column flex container the main axis is vertical,
so the gap between items should use row-gap (not column-gap) and the
gap between flex lines should use column-gap (not row-gap).
Introduces main_gap/cross_gap variables that swap based on flex direction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full flexbox support with flex container and item properties:
CSS parsing:
- Parse display: flex/inline-flex
- Parse flex container props: flex-direction, flex-wrap, justify-content,
align-items, align-content, gap/row-gap/column-gap
- Parse flex item props: flex-grow, flex-shrink, flex-basis, align-self, order
- Expand flex, flex-flow, and gap shorthands
Layout algorithm (CSS Flexbox Level 1 §9):
- Determine main/cross axes from flex-direction
- Content-based flex-basis sizing for auto basis
- Distribute free space via flex-grow/flex-shrink
- Line wrapping (flex-wrap: wrap/wrap-reverse)
- Main axis justification (all justify-content modes)
- Cross axis alignment (all align-items/align-self modes)
- Multi-line align-content distribution
- Visual ordering via order property
- Gap spacing between items
- Reverse direction support (row-reverse, column-reverse)
Tests: 10 new flex layout tests covering row/column direction,
grow/shrink, justify-content, align-items, wrap, gap, and order.
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 scrollable overflow regions for overflow:scroll and overflow:auto
boxes, with rendered scroll bars and mouse wheel event support.
Layout crate:
- Add content_height field to LayoutBox tracking natural content height
before CSS height override (used for overflow detection)
- Reserve SCROLLBAR_WIDTH (15px) from content area for overflow:scroll
- Export SCROLLBAR_WIDTH constant
Render crate:
- Add ScrollState type (HashMap<NodeId, (f32, f32)>) for scroll offsets
- Modify display list builder to accept scroll state and translate offset
- Apply scroll offset to child coordinates in scrollable containers
- Render vertical scroll bars (track + proportional thumb) for
overflow:scroll (always) and overflow:auto (when content overflows)
- Add page-level scroll support via paint_with_scroll()
- Add build_display_list_with_page_scroll() for viewport scrolling
- 6 new tests: scrollbar rendering, scroll offset, thumb proportionality,
overflow:auto conditional scrollbar, page scroll
Platform crate:
- Add scrollWheel: event handler to WeView class
- Add set_scroll_handler() for registering scroll callbacks
- Forward scroll delta (dx, dy) and mouse position to handler
Browser crate:
- Add page_scroll_y, content_height, scroll_offsets to BrowserState
- Handle scroll wheel events: update page scroll, clamp to bounds,
re-render
- Pass scroll state through rendering pipeline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add clip rect support to the rendering pipeline so that boxes with
overflow != visible clip their children's content to the padding box.
Render crate changes:
- Add PushClip/PopClip variants to PaintCommand
- Maintain a clip rect stack in Renderer that intersects nested clips
- Apply active clip rect in fill_rect, composite_glyph, and draw_image
- overflow:hidden, overflow:auto, and overflow:scroll all clip content
- overflow:visible (default) continues to render without clipping
Layout crate fix:
- Fix is_empty_block to not treat blocks with explicit CSS height as
empty (they should not self-collapse per CSS2 §8.3.1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread viewport dimensions through style resolution so viewport units
resolve correctly: 1vw = 1% of viewport width, 1vh = 1% of viewport
height, vmin/vmax use the smaller/larger dimension.
For layout properties (width, height, margin, padding), percentages are
now preserved as LengthOrAuto::Percentage through style computation and
resolved during layout against the containing block width. Height
percentages resolve against viewport height. Per CSS spec, even vertical
margins and padding resolve against containing block width.
Changes:
- Add Percentage(f32) variant to LengthOrAuto
- Change ComputedStyle padding fields from f32 to LengthOrAuto
- Add viewport parameter to resolve_styles, threaded through resolution
- resolve_length_unit now computes vw/vh/vmin/vmax from viewport dims
- Layout resolves percentage width/height/margin/padding against
containing block; nested percentages compound correctly
- Store css_margin/css_padding/css_offsets on LayoutBox for deferred
resolution during layout
- 9 new tests covering all acceptance criteria
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire up visibility property through the layout and render pipeline:
- Add visibility field to LayoutBox, populated from ComputedStyle
- Renderer skips painting (background, borders, text, images) for
hidden/collapse elements but still recurses into children
- Children can override with visibility:visible per CSS spec
- display:none already worked (excluded from layout tree); verified
9 new tests: 5 layout tests (display:none exclusion, hidden preserves
space, inheritance, visible override, collapse behavior) and 4 render
tests (hidden not painted, visible child of hidden parent painted,
collapse not painted, display:none not in display list).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add BoxSizing enum and box_sizing field to ComputedStyle with CSS
parsing support. Layout engine now respects explicit CSS width/height
and adjusts content dimensions based on box-sizing mode:
- content-box (default): width/height apply to content area only
- border-box: width/height include padding and border
Content area clamps to 0 when padding+border exceeds specified size
in border-box mode. Property is not inherited per spec.
9 new tests covering both modes, clamping, non-inheritance, and height.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements CSS2 §8.3.1 margin collapsing:
- Adjacent sibling margins collapse (gap = max, not sum)
- Parent-child margin collapsing via pre_collapse_margins pass
- Empty block self-collapsing (top+bottom margins fold together)
- Negative margin handling (positive+negative=sum, both negative=min)
- Collapsing blocked by border, padding, or overflow!=visible (BFC)
Adds overflow field to LayoutBox for BFC detection. Updates existing
tests to reflect correct collapsed margin behavior and adds 9 new
tests covering all collapsing scenarios.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add relative positioning support to the layout engine. After normal-flow
layout, elements with position: relative are visually shifted by their
top/right/bottom/left offset values without affecting surrounding elements.
- Add position and relative_offset fields to LayoutBox
- Resolve offset conflicts per CSS spec (top wins over bottom, left over right)
- Recursively shift box rect, text lines, and all descendants
- Add 7 tests covering offsets, sibling independence, conflicts, and auto values
Wire together all Phase 8 components into the browser's navigation flow:
- Use css_loader::collect_stylesheets for external <link> and inline <style>
- Use img_loader::collect_images to fetch and decode <img> elements
- Store pre-fetched PageState (DOM, stylesheet, images) so window resizes
only re-style/re-layout/re-render without re-fetching
- Show error page for network failures instead of process::exit
- Preserve base URL from HTTP response for resolving relative subresources
- Generate file:// base URL for local file paths
Implements issue 3mhktaciaf42q.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add about: scheme handling to ResourceLoader:
- Recognize about:blank and return a minimal empty HTML document
(<!DOCTYPE html><html><head></head><body></body></html>)
- UTF-8 encoding, no network requests
- Unsupported about: URLs return InvalidUrl error
Update browser main to use about:blank as default:
- No URL argument opens about:blank instead of hardcoded demo page
- URL arguments (http://, https://, about:, data:) load via ResourceLoader
- File path arguments still work as before
4 tests covering fetch/fetch_url paths, DOM structure validation,
and unsupported about: URL rejection.
Implements issue 3mhkt7vaxsb23
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add data_url module to the url crate:
- Base64 decoder (RFC 4648): standard alphabet, whitespace stripping, padding
- Data URL parser: extract MIME type, charset, base64/percent-encoded payload
- Default MIME type text/plain;charset=US-ASCII when omitted
Integrate with ResourceLoader in browser crate:
- Handle data: URLs in both fetch() and fetch_url() without network access
- Classify decoded content into Html/Css/Image/Other resource types
- Decode text resources using charset from data URL parameters
44 tests covering base64 decoding, data URL parsing, MIME extraction,
percent decoding, and ResourceLoader integration.
Implements issue 3mhkt7m45472x
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add img_loader module to the browser crate that loads images from the DOM:
- Scan DOM for <img src="..."> elements in document order
- Fetch image data via ResourceLoader with URL resolution
- Detect format from magic bytes (PNG: 89504E47, JPEG: FFD8, GIF: GIF8)
- Decode using image crate decoders (PNG, JPEG, GIF)
- Parse width/height attributes with proportional scaling
- Graceful degradation: failed loads store alt text, no crash
Layout integration:
- Add replaced_size field to LayoutBox for replaced elements
- Accept image_sizes map in layout() for intrinsic/attribute dimensions
- Replaced elements use their dimensions instead of child layout
Render integration:
- Add DrawImage variant to PaintCommand
- Nearest-neighbor scaling with RGBA→BGRA conversion
- Alpha compositing for semi-transparent image pixels
37 tests covering format detection, dimension parsing/resolution,
DOM scanning, graceful failure, error display, and PNG decoding.
Implements issue 3mhkt7br4jx25
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add css_loader module to the browser crate that collects CSS from the DOM:
- Scan DOM for <style> elements (inline CSS) and <link rel="stylesheet"> (external)
- Fetch external stylesheets via ResourceLoader with encoding detection
- Resolve @import rules recursively (max depth 5 to prevent cycles)
- Basic media attribute support (screen, all)
- Type attribute validation (text/css default)
- Graceful degradation: failed loads are silently skipped
- Merge all rules into a single Stylesheet in document order
37 tests covering DOM scanning, classification, media matching, text
collection, import resolution, error handling, and edge cases.
Implements issue 3mhkt6vtv3q2g
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ResourceLoader to the browser crate that integrates the net, encoding,
url, and image crates into a unified resource fetching API:
- ResourceLoader wraps HttpClient for HTTP/HTTPS fetching
- Content-Type parsing determines resource type (HTML, CSS, image, other)
- WHATWG encoding sniffing for HTML (BOM > HTTP > meta prescan > default)
- BOM/HTTP charset detection for non-HTML text resources (default UTF-8)
- Relative URL resolution via base URL support
- HTTP error status handling (4xx, 5xx)
- Resource enum: Html, Css, Image, Other with appropriate metadata
30 tests covering MIME classification, text decoding (BOM, HTTP charset,
meta prescan, Windows-1252 special chars), URL resolution, and error types.
Implements issue 3mhkt6hnbhp25
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add encoding detection per WHATWG Encoding Standard and HTML spec:
- BOM sniffing for UTF-8, UTF-16LE, UTF-16BE
- HTTP Content-Type charset extraction (quoted/unquoted values)
- HTML meta prescan: scan first 1024 bytes for <meta charset> and
<meta http-equiv="Content-Type" content="...;charset=...">
- Priority: BOM > HTTP header > meta prescan > default (Windows-1252)
- UTF-16 from HTTP/meta overridden to UTF-8 per spec
- EncodingSource enum for tracking detection method confidence
39 new tests covering all detection methods and priority ordering.
Implements issue 3mhkt62ryxo2l
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add all 27 WHATWG single-byte encodings to the encoding crate:
- Windows-1252 (with ISO-8859-1 and US-ASCII aliases per WHATWG spec)
- ISO-8859-2 through ISO-8859-16 (excluding 8859-9 which maps to Windows-1254)
- Windows-874, Windows-1250 through Windows-1258
- KOI8-R, KOI8-U
- macintosh, x-mac-cyrillic
- IBM866
Each encoding uses a 128-entry u16 lookup table for bytes 0x80-0xFF.
All WHATWG label aliases are registered for case-insensitive lookup.
32 new tests covering per-encoding correctness and error handling.
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure Rust implementation of UTF-8 and UTF-16 text encoding/decoding
per the WHATWG Encoding Standard:
- UTF-8 decoder (streaming state machine with replacement/fatal modes)
- UTF-8 encoder
- UTF-16LE/BE decoders with surrogate pair handling and BOM stripping
- Encoding label lookup (case-insensitive, whitespace-trimmed)
- BOM sniffing utility
- Public API: decode(), decode_strict(), encode(), lookup(), bom_sniff()
- 93 unit tests covering edge cases (overlong, surrogates, truncated, BOM)
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure Rust baseline JPEG decoder in the image crate supporting:
- JFIF marker parsing (SOI, APP0/APP1, DQT, SOF0, DHT, SOS, DRI, EOI)
- Huffman entropy decoding (DC and AC coefficients)
- 8x8 block-based inverse DCT (Loeffler algorithm, integer fixed-point)
- Dequantization with DQT tables
- Chroma subsampling: 4:4:4, 4:2:2, 4:2:0
- YCbCr to RGB color conversion (BT.601 fixed-point)
- Restart marker support
- Grayscale JPEG support
- 28 unit tests covering Huffman, IDCT, color conversion, parsing, and
end-to-end decoding of hand-crafted JPEG streams
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GIF LZW uses "early change" — the code size must bump when next_code
reaches (1 << code_size), not after it exceeds it. Without this fix,
the decoder would read codes with the wrong bit width for GIFs with
enough unique codes to trigger a code size increase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust GIF decoder in the image crate supporting:
- GIF87a and GIF89a format parsing
- LZW decompression with variable-width codes, clear/EOI codes
- Global and local color tables
- Graphic Control Extension (transparency, delay, disposal methods)
- Multi-frame animated GIFs with canvas compositing
- Interlaced image support (4-pass Adam7-style deinterlacing)
- Sub-frame positioning (frames smaller than logical screen)
- Application, comment, and plain text extension skipping
- API: decode_gif() for first frame, decode_gif_frames() for all frames
31 unit tests covering LZW decompression, deinterlacing, frame decoding,
transparency, animation, local color tables, extensions, and error cases.
No external dependencies, no unsafe.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust PNG decoder supporting all color types (grayscale, RGB,
indexed, grayscale+alpha, RGBA), bit depths 1-16, scanline filtering
(None/Sub/Up/Average/Paeth), Adam7 interlacing, tRNS transparency,
CRC-32 validation, and multiple IDAT chunk concatenation.
40+ unit tests covering all color types, bit depths, filter types,
interlacing, transparency, error cases, and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse zlib header (CMF/FLG), validate header checksum, delegate to
DEFLATE for compressed data, verify Adler-32 checksum of output.
21 unit tests covering Adler-32, header validation, round-trip
decompression, error propagation, and all window sizes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Rust DEFLATE decompression supporting all three block types:
- Non-compressed blocks (BTYPE=00) with LEN/NLEN validation
- Fixed Huffman codes (BTYPE=01) per RFC 1951 §3.2.6
- Dynamic Huffman codes (BTYPE=10) with code length decoding
Implementation details:
- LSB-first bit reader with peek/consume pattern for Huffman decoding
- Two-level Huffman lookup table (primary + subtable for long codes)
- LZ77 back-reference decoding with overlapping copy support
- Handles end-of-stream gracefully when final code needs fewer bits
than the primary table width
33 unit tests covering BitReader, Huffman trees, all block types,
back-references, error cases, and round-trip verification against
zlib-generated test vectors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace strip_prefix-based header matching (only matched exact case and
lowercase) with a proper case-insensitive helper that splits on the
first colon and compares the header name using eq_ignore_ascii_case.
Adds tests for all-caps header names (CONTENT-LENGTH, TRANSFER-ENCODING).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
High-level HTTP client in the net crate bringing together TCP, TLS 1.3,
DNS, URL parsing, and HTTP message handling:
- HttpClient with get(), post(), request() methods
- Scheme handling: http:// (plain TCP) and https:// (TLS)
- Connection pooling by (host, port, is_tls) with max idle time and
max connections per host
- Redirect following (301, 302, 307, 308) with configurable max
- Configurable connect and read timeouts
- Streaming response reader: header detection, Content-Length,
chunked Transfer-Encoding, and read-until-close strategies
- std::io::Read and Write trait impls for TcpConnection
30+ unit tests covering error types, configuration, connection pool,
URL path building, header parsing, body strategy selection, and
chunked terminator detection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HTTP/1.1 message parser (RFC 7230, 7231) for the net crate:
- Request serialization (GET, POST, HEAD, PUT, DELETE, OPTIONS, PATCH)
- Response parsing: status line, headers, body
- Headers collection with case-insensitive name lookup
- Content-Length body reading
- Chunked Transfer-Encoding decoding (RFC 7230 §4.1)
- Content-Type parsing with charset extraction
- Proper handling of 1xx/204/304 no-body responses
55 tests covering all acceptance criteria.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The application traffic secrets (RFC 8446 §7.1) must be derived from
the transcript hash covering ClientHello...server Finished, not
including the client Finished message. The code was using
transcript.current_hash() after updating with client_finished_msg,
producing incorrect application keys that would fail against real
servers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- random_bytes: panic instead of silently using zero-filled buffers when
/dev/urandom fails — using all-zero keys is a critical security issue
- Rename _ee_body to ee_body since the variable is actually used
- Fix wildcard hostname matching to reject empty labels (e.g. ".example.com"
should not match "*.example.com")
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full TLS 1.3 client handshake: ClientHello with SNI/supported_versions/
key_share/signature_algorithms extensions, ServerHello processing,
ECDHE key exchange (X25519), encrypted handshake message processing
(EncryptedExtensions, Certificate, CertificateVerify, Finished),
certificate chain validation, server name verification with wildcard
matching, key phase transitions, and TlsStream type for application data.
Supports RSA PKCS#1 v1.5 and ECDSA (P-256/P-384) signature verification
in CertificateVerify. Validates server certificates against embedded
root CA store (ISRG Root X1, DigiCert, GlobalSign).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Key schedule for deriving encryption keys from shared secrets using HKDF.
Includes HKDF-Expand-Label, Derive-Secret, transcript hashing, traffic
key/IV derivation, and Finished verify data computation. Supports all
three TLS 1.3 cipher suites (AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305).
Also adds Clone derive to SHA-256, SHA-384, SHA-512 hashers in the crypto
crate to support transcript hash snapshotting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Record layer protocol in the net crate for framing and encrypting TLS
records. ContentType enum (ChangeCipherSpec, Alert, Handshake,
ApplicationData). Plaintext record read/write with header framing and
size enforcement. Encrypted record support via RecordCryptoState with
per-record nonce construction (XOR base IV with sequence number),
inner content type hiding, and AEAD using AES-128-GCM, AES-256-GCM,
or ChaCha20-Poly1305. Alert protocol with close_notify and fatal error
handling. RecordLayer type combining plaintext and encrypted modes with
runtime crypto state switching.
36 tests covering content types, alert encode/decode, nonce construction,
plaintext record I/O, encrypted roundtrips for all cipher suites,
sequence numbering, tamper detection, record overflow, and RecordLayer
integration with plaintext-to-encrypted transitions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DNS resolver in the net crate for resolving hostnames to IP addresses
via UDP queries to system nameservers. Parses /etc/resolv.conf for
nameserver discovery with fallback to Google DNS. Supports A and AAAA
record types, DNS name compression pointers, NXDOMAIN handling, timeout
and retry across multiple nameservers, and direct IP address passthrough.
DnsResolver type with system() and with_nameservers() constructors,
configurable timeout, and resolve() method. Convenience resolve()
function for one-shot lookups. 38 tests covering name encoding, query
building, response parsing, compression pointers, resolv.conf parsing,
address extraction, error types, and real hostname resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TcpConnection type wrapping std::net::TcpStream with connect,
connect_timeout, read, write, read_exact, write_all, flush, timeout
configuration, and shutdown. NetError enum with automatic mapping
from io::Error (ConnectionRefused, TimedOut variants). BufferedReader
and BufferedWriter wrappers for efficient line-oriented I/O with
split read/write support via stream cloning.
15 tests covering error types, connection failures, loopback echo,
buffered line reading, buffered read/write pairs, timeouts, and
debug formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
URL record type with scheme, username, password, host, port, path,
query, fragment. State-machine parser handling special schemes (http,
https, ftp, ws, wss, file) with default ports. Host parsing for
domains, IPv4 (decimal/hex/octal), and IPv6 (including IPv4-mapped
and :: compression). Percent-encoding/decoding per spec encode sets
(C0, fragment, query, path, userinfo). Relative URL resolution via
base URL. URL serialization with round-trip fidelity. Origin
derivation (tuple for special schemes, opaque otherwise).
88 tests covering absolute URLs, scheme handling, host types,
IPv4/IPv6 parsing and serialization, percent encoding, path dot
resolution, relative URL resolution, serialization round-trips,
file URLs, and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PEM decoding with custom Base64 decoder, X.509v3 certificate parsing
extracting version, serial, issuer, subject, validity, SPKI, and
extensions (Basic Constraints, Key Usage, SAN, AKI, SKI). Certificate
chain validation with signature verification (RSA + ECDSA), validity
period checks, and CA constraint enforcement. Embedded root CA store
with ISRG Root X1, DigiCert Global Root G2, and GlobalSign Root R3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Elliptic curve arithmetic in Jacobian coordinates with point addition,
doubling, and Montgomery ladder scalar multiplication. Field arithmetic
over the prime fields of P-256 (secp256r1) and P-384 (secp384r1) using
the existing BigUint type.
ECDSA verification per FIPS 186-4 §4.1.4 with Shamir's trick for
multi-scalar multiplication. Parses EC public keys from uncompressed
point format and SubjectPublicKeyInfo DER. Parses DER-encoded
ECDSA signatures.
34 tests including: curve parameter validation, point arithmetic,
RFC 6979 test vectors (P-256/SHA-256), self-generated test vectors
for both P-256 and P-384, signature rejection, and DER parsing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BigUint type with arbitrary-precision arithmetic backed by little-endian
u64 limbs. Supports modular exponentiation via Montgomery multiplication
for odd moduli (RSA) with fallback for even moduli.
RSA public key parsing from both PKCS#1 RSAPublicKey and PKCS#8
SubjectPublicKeyInfo DER formats. RSASSA-PKCS1-v1_5-VERIFY with
EMSA-PKCS1-v1_5 encoding for SHA-256, SHA-384, and SHA-512.
Constant-time signature comparison. Key sizes 2048-4096 bits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DerParser reads TLV structures from DER-encoded byte slices. Supports
all primitive types needed for X.509 certificates: BOOLEAN, INTEGER,
BIT STRING, OCTET STRING, NULL, OID, UTF8String, PrintableString,
IA5String, UTCTime, GeneralizedTime. Constructed types: SEQUENCE, SET.
Context-specific tags with explicit/implicit tagging.
Includes well-known OID constants for RSA, ECDSA, SHA-2, X.509
extensions, and X.500 attribute types. OID encode/decode with dotted
notation. Rejects non-DER encodings (indefinite length, non-minimal
integers/lengths).
45 tests covering all types, DER validation, real certificate fragments,
and edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Field arithmetic in GF(2^255 - 19) using 5x51-bit limb representation.
Montgomery ladder scalar multiplication on Curve25519. Constant-time
implementation with no secret-dependent branches or memory accesses.
Passes RFC 7748 §6.1 DH test vectors and §5.2 iterated test vector
(1,000 iterations).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The constant-time conditional select between h and g in the Poly1305
final reduction was missing h4/g4. When h >= p (2^130-5), the code
selected g for h0-h3 but left h4 unchanged, producing incorrect tags
for inputs where the accumulator exceeds the prime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pure Rust ChaCha20-Poly1305 authenticated encryption in the crypto crate:
- ChaCha20 stream cipher: quarter round, block function (20 rounds),
counter-mode encryption with 256-bit key, 96-bit nonce, 32-bit counter
- Poly1305 one-time MAC: GF(2^130-5) using 5 limbs of 26 bits,
clamped r key, constant-time final reduction
- AEAD construction: Poly1305 key generation from ChaCha20 block 0,
encrypt-then-MAC with RFC 8439 padding and length encoding
- Constant-time tag comparison for secure decryption
- 13 tests: RFC 8439 test vectors (§2.1.1, §2.3.2, §2.4.2, §2.5.2,
§2.6.2, §2.8.2), tag tamper detection, and round-trip tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pure Rust AES-GCM authenticated encryption in the crypto crate:
- AES block cipher (FIPS 197): key expansion and encrypt for 128/256-bit keys
- GHASH: constant-time GF(2^128) multiplication using bit masking
- GCM encrypt/decrypt with 96-bit nonce, 128-bit authentication tag, and AAD
- Constant-time tag comparison for secure decryption
- 25 tests including NIST SP 800-38D test vectors (cases 1-4, 13-16),
tag tamper detection, and encrypt/decrypt round-trips
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>