Add parent-first-child top and parent-last-child bottom margin collapsing using a two-level approach (Level A shifts child inside parent, Level B adjusts grandparent for effective collapsed margin). Fix pre-existing bug in shift_subtree_x that incorrectly skipped absolute/fixed children. Extract shared MARGIN_EPSILON constant, add 9 unit tests and 4 golden tests (209-212), promote 31 WPT tests to pass. Includes code review fixes: pub(crate) visibility for is_root_element, known-limitation docs, and inline-content shift test coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
78 KiB
stepsCompleted, status, completedAt, inputDocuments, scopeExclusions
| stepsCompleted | status | completedAt | inputDocuments | scopeExclusions | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
complete | 2026-03-12 |
|
|
rust_browser - Epic Breakdown
Overview
This document provides the complete epic and story breakdown for rust_browser, decomposing the requirements from the PRD, UX Design if it exists, and Architecture requirements into implementable stories.
Requirements Inventory
Functional Requirements
FR1: The browser parses HTML documents and constructs a DOM tree from arbitrary web content. Acceptance: all WPT tree-construction tests pass. FR2: The browser parses CSS stylesheets (inline, embedded, and external) and computes styles for all DOM nodes. Acceptance: computed style output matches WPT expectations for supported properties. FR3: The browser performs layout computation for block, inline, flexbox, table, and positioned elements. Acceptance: golden test output matches expected layout trees for each layout mode. FR4: The browser generates a display list from the layout tree and rasterizes it to pixels. Acceptance: golden test pixel output matches expected display list dumps. FR5a: The browser selects the correct font based on CSS font-family, font-weight, and font-style declarations. Acceptance: golden tests with multiple font stacks render the expected glyphs. FR5b: The browser performs line breaking per UAX#14 and renders text with correct line-height, font-size, and baseline alignment. Acceptance: golden tests with multi-line text match expected output. FR6: The browser renders images in PNG, JPEG, GIF, WebP, and SVG formats as both inline content and CSS background-image. Acceptance: golden tests with each format produce correct visual output. FR7a: The browser renders CSS backgrounds (color, image, repeat, position, attachment) and borders (all border-style values including double, groove, ridge, inset, outset). Acceptance: WPT background/border tests pass. FR7b: The browser renders box-shadow, CSS gradients (linear-gradient, radial-gradient), and opacity. Acceptance: golden tests for each effect match expected output. FR8: [P2] The browser renders CSS generated content (::before, ::after) with content property values including strings, attr(), and counter(). Acceptance: WPT generated-content tests pass. FR9: The browser performs CSS selector matching with full specificity calculation and cascade resolution per CSS 2.1 sections 6 and 6.4. Acceptance: WPT cascade/specificity tests pass. FR10: [P2] The browser resolves CSS inheritance, initial values, and inherit/initial/unset keywords for all CSS 2.1 properties. Acceptance: WPT inheritance tests pass for each supported property. FR11: The browser parses and executes JavaScript programs. Acceptance: Test262 pass rate reaches 95%+ against the full tc39/test262 suite (50,000+ tests). FR12: The browser executes scripts from inline <script> elements and external script resources, including deferred and asynchronous loading. Acceptance: WPT script-loading tests pass for each loading mode. FR13: The browser exposes DOM manipulation APIs to JavaScript: getElementById, querySelector, querySelectorAll, createElement, appendChild, removeChild, insertBefore, replaceChild, classList, and style property access. Acceptance: WPT DOM manipulation tests pass for each listed API. FR14: The browser dispatches events to JavaScript listeners with capture, target, and bubble phases per the DOM Events specification. Acceptance: WPT event dispatch tests pass including stopPropagation and preventDefault. FR15: The browser executes microtasks (Promise.then), macrotasks (setTimeout, setInterval), and requestAnimationFrame callbacks in spec-defined order. Acceptance: event loop ordering tests produce correct execution sequences. FR16: The browser exposes these Web APIs to JavaScript: console (log/warn/error), JSON (parse/stringify), fetch, localStorage, sessionStorage, and all DOM/event APIs listed in FR13-FR14. Acceptance: each API has at least one integration test verifying correct behavior. FR17: The browser catches JavaScript runtime errors (TypeError, ReferenceError, SyntaxError) without crashing and reports them to console.error. Acceptance: a test script with each error type runs without process termination and produces console output. FR18: The user enters a URL in the address bar and the browser navigates to it. Acceptance: URL entry triggers resource fetch and page render within the performance bounds defined in NFR1. FR19: The browser loads resources over HTTP, HTTPS, file://, and data: URI schemes. Acceptance: integration tests verify successful resource loading for each scheme. FR20a: The browser follows HTTP 301, 302, 303, 307, and 308 redirects up to a maximum of 20 hops. Acceptance: redirect chain tests verify correct final destination and hop limit enforcement. FR20b: The browser displays HTTP error responses (4xx, 5xx) to the user with the status code and a descriptive message. Acceptance: error page tests verify status code display for 404 and 500 responses. FR21: [P1 -- done] The browser manages cookies per RFC 6265: domain scoping, path matching, Secure/HttpOnly flags, and Max-Age/Expires expiry. Acceptance: cookie integration tests verify correct set/send behavior for each attribute. FR22: [P1 -- done] The browser caches HTTP responses using ETag and Last-Modified headers, sends conditional requests (If-None-Match, If-Modified-Since), and honors Cache-Control directives (max-age, no-cache, no-store). Acceptance: caching integration tests verify 304 responses and cache hit/miss behavior. FR23: [P1 -- done] The browser maintains cookie-based session state across navigations within a browsing session: cookies set on page A are sent with requests to the same domain on page B. Acceptance: a multi-navigation test verifies session cookie persistence across 3+ page loads. FR24: The user navigates forward and backward through browsing history. Acceptance: history navigation tests verify correct page restoration for 3+ history entries. FR25: The browser resolves relative URLs against the document base URL (including if present). Acceptance: URL resolution tests cover relative paths, query strings, fragments, and base element override. FR26: The user interacts with form controls: text inputs, buttons, checkboxes, radio buttons, select menus, and textareas. Acceptance: integration tests verify user input produces correct form control state for each control type. FR27: The browser submits forms via GET and POST with application/x-www-form-urlencoded encoding. [P2] multipart/form-data encoding for file uploads. Acceptance: form submission tests verify correct request body encoding for each method and encoding type. FR28: [P2] The browser performs client-side form validation for required, pattern, min, max, minlength, maxlength, and type-based constraints (email, url, number). Acceptance: validation tests verify correct constraint enforcement and user-visible error indication for each constraint type. FR29: The user interacts with the page via click, keyboard input, and scroll. Acceptance: input event tests verify correct event dispatch and default behavior for each input type. FR30: The browser manages focus state and supports keyboard navigation (Tab/Shift+Tab) between focusable elements in document order. Acceptance: focus management tests verify correct tab order across form controls, links, and elements with tabindex. FR31: The user views and edits the current URL in an address bar that updates on navigation. Acceptance: address bar reflects the current page URL after each navigation. FR32: [P3] The user opens new tabs, switches between tabs, and closes tabs. Each tab maintains independent navigation history, DOM state, and scroll position. Acceptance: multi-tab tests verify independent state across 3+ tabs. FR33: The user scrolls page content vertically and horizontally when content exceeds the viewport. Acceptance: scroll tests verify content accessibility for pages taller and wider than the viewport. FR34: The browser displays a loading indicator during page load and clears it on completion or failure. Acceptance: loading state tests verify indicator visibility during fetch and removal after load/error events. FR35: The user reloads the current page (re-fetches all resources) and stops a loading navigation (cancels pending fetches). Acceptance: reload/stop tests verify correct behavior for each action. FR36: The browser renders a chrome UI containing the address bar, navigation buttons (back/forward/reload/stop), and a tab bar (Phase 3). Acceptance: chrome UI renders correctly at window widths from 800px to 2560px. FR37: [P3] The browser blocks tracker and advertisement requests by matching URLs against a bundled blocklist (e.g., EasyList format). Acceptance: blocking tests verify that requests matching 10+ known tracker patterns are prevented, and non-matching requests proceed normally. FR38: The browser enforces same-origin policy: JavaScript on origin A cannot read DOM content, cookies, or network responses from origin B (where A and B differ in scheme, host, or port). Acceptance: cross-origin access tests verify blocked read access for each resource type. FR39: The browser blocks top-level navigation to javascript: URIs and data: URIs. Sub-resource loading of data: URIs is permitted. Acceptance: navigation blocking tests verify blocked and permitted cases. FR40: [P3] The browser persists cookies and session data to disk and restores them on application restart. Acceptance: restart persistence tests verify cookie availability after process termination and relaunch. FR41: [P1 -- done] The browser serves previously cached HTTP responses when the origin server is unreachable, subject to Cache-Control freshness rules. Acceptance: offline tests verify cached page display when network requests fail. FR42: [P2] The browser provides localStorage (persistent, 5MB per origin) and sessionStorage (per-tab, cleared on tab close) to JavaScript. Acceptance: Web Storage tests verify getItem/setItem/removeItem/clear behavior, storage limits, and cross-origin isolation. FR43: [P3] The browser discovers and uses OS-installed fonts on macOS (Core Text) and Linux (fontconfig), falling back to bundled Noto Sans. Acceptance: font discovery tests verify at least 3 system fonts are available beyond the bundled set on each supported platform. FR44: [P3] The user copies selected text to the system clipboard and pastes text from the clipboard into form inputs. Acceptance: clipboard tests verify round-trip copy/paste of plain text content. FR45: [P3] The browser presents native file dialogs for file upload () and download (Content-Disposition: attachment). Acceptance: file dialog tests verify dialog presentation and correct file data transfer. FR46: [P3] The browser registers as the default URL handler on macOS and Linux so that clicking links in other applications opens rust_browser. Acceptance: URL handler registration tests verify correct launch from an external link on each platform. FR47: [P2] The browser passes 90%+ of CSS 2.1 Web Platform Tests as measured by the WPT harness in CI. FR48: [P2] The browser passes 95%+ of the full tc39/test262 ECMAScript conformance suite (50,000+ tests) as measured by the Test262 harness. FR49: [P2] The browser passes 90%+ of HTML5 Web Platform Tests as measured by the WPT harness in CI. FR50: The browser handles malformed HTML, CSS, and JavaScript input without crashing. Acceptance: fuzz tests and malformed-input test suites covering each parser run without panics.
NonFunctional Requirements
NFR1: Page load and first paint for a content-heavy site (CNN, Hacker News) completes within 3 seconds on an M1 MacBook or equivalent. Measured by timing from navigation start to first paint event in debug logs. NFR2: Scrolling maintains 30+ frames per second on pages with up to 500 DOM elements. Measured by frame timing instrumentation in the render loop. NFR3: No single JavaScript task blocks the rendering thread for more than 100ms. Measured by task duration logging in the event loop. NFR4: The browser starts up and displays the address bar ready for URL input within 2 seconds from process launch. Measured by startup timing instrumentation. NFR5: Resident memory usage does not grow by more than 50MB after navigating to 20 different pages and returning to the first. Measured by RSS sampling before and after the navigation sequence. NFR6: All parsers (HTML, CSS, JavaScript) handle malformed and adversarial input without panics or undefined behavior. Verified by fuzz test suites covering each parser with 10,000+ random inputs without crashes. NFR7: The unsafe keyword is forbidden in all crates except the two designated platform-integration crates. Verified by an automated CI check that scans source files and fails the build on violations. NFR8: JavaScript on origin A cannot read DOM content, cookies, or fetch responses from origin B (different scheme, host, or port). Verified by cross-origin integration tests covering each resource type. NFR9: Top-level navigation to javascript: and data: URIs is blocked; sub-resource data: URIs are permitted. Verified by navigation tests for each URI scheme. NFR10: The browser binary contains zero telemetry, analytics, or tracking code. Verified by code audit: no outbound network requests are made except those explicitly initiated by page content or user navigation. NFR11: The browser does not crash on any valid or malformed web content. Parser, layout, and render failures produce user-visible error messages instead of panics. Verified by running the full WPT and Test262 suites plus malformed-input tests without process termination. NFR12: The CI gate passes on every merged change, covering formatting, linting, all test suites, safety policy, and metrics. Verified by CI pass/fail status on every merge. NFR13: Every bug fix includes at least one regression test that reproduces the bug and verifies the fix. Verified by code review policy. NFR14: Conformance test suites (golden tests, WPT, Test262) run on every CI build. Any test that previously passed and now fails blocks the merge. Verified by CI harness exit codes. NFR15: The browser displays a user-visible error page (not a blank screen or hang) within 10 seconds of a network failure (timeout, DNS error, connection refused). Verified by network failure integration tests with simulated failures. NFR16: No crate in a lower architectural layer depends on a crate in a higher layer. Verified by an automated dependency check in CI that parses Cargo.toml files and fails on violations. NFR17: Each crate has a single documented responsibility. No crate's public API surface exceeds 50 exported items. Verified by periodic API surface audit. NFR18: No source file exceeds 1,000 lines. Verified by an automated file-size check in CI. NFR19: New external dependencies require documented rationale and workspace-level version pinning. Verified by code review policy. NFR20: Implementation of non-obvious spec behavior includes a comment citing the relevant spec section (e.g., CSS 2.1 section 8.3.1). Verified by code review policy. NFR21: The total crate count does not exceed 30 and total source file count does not exceed 500. Verified by periodic metrics collection in CI.
Additional Requirements
From Architecture document:
- Brownfield project -- no starter template needed; all new work extends existing 22-crate, 4-layer architecture
- Cookie jar module in
netwith domain scoping and swappable backing store interface for laterstorage-backed persistence - HTTP cache -- in-memory first, disk persistence later via
storagecrate - Storage crate serves as general-purpose persistence layer for all disk-persisted data (cookies, cache, localStorage, sessionStorage)
- CSS property implementation order enforced: parse (css/) → computed style (style/) → layout effect (layout/) → paint effect (display_list/) → golden test → checklist update → CI
- HTML element implementation order enforced: parse (html/) → DOM (dom/) → UA styling (style/) → layout (layout/) → paint (display_list/) → runtime behavior (web_api/) → golden test → checklist update → CI
- JS feature implementation order enforced: tokenization (js_parser/) → AST (js_parser/) → execution (js_vm/) → unit tests → Test262 manifest → feature matrix update → CI
- Bytecode IR introduction deferred until generators/async-await become priority -- AST walker sufficient for current spec compliance work
- Compositor thread as first concurrency step -- consuming immutable display lists for async rasterization
- JS yield mechanism via cooperative yielding with statement counter (existing
max_statementsin VmConfig) - Web API crate scaling -- module-per-domain initially, extract to
web_api_<domain>crates when complexity warrants (~10-15 files) - System font discovery through
platform/OS-specific trait,fontscrate providesFontProviderfacade - Clipboard & file dialogs wrapped in
platform/behind traits, consumed byapp_browser - Single-process model now; multi-process architecture designed when tabs are implemented
- Tab state isolation -- fully isolated per tab (own DOM, JS engine, styles, layout); cookie jar shared semantically
- Error handling -- thiserror-derived specific error types in parsers, SharedResult in engine crates, domain conversions at bridge boundaries
- Spec citations required for non-obvious behavior (CSS 2.1 §X.Y.Z, HTML §X.Y.Z, ECMAScript §X.Y.Z)
- Dependency addition protocol -- check std first, pin in workspace, document rationale, pass deny.toml
FR Coverage Map
FR1: Epic 2 - HTML parsing and DOM tree construction FR2: Epic 1 - CSS parsing and style computation FR3: Epic 1 - Layout computation (block, inline, flex, table, positioned) FR4: Epic 1 - Display list generation and rasterization FR5a: Epic 1 - Font selection (font-family, font-weight, font-style) FR5b: Epic 1 - Line breaking and text rendering FR6: Epic 2 - Image rendering (PNG, JPEG, GIF, WebP, SVG) FR7a: Epic 1 - CSS backgrounds and borders FR7b: Epic 1 - Box-shadow, gradients, opacity FR8: Epic 1 - CSS generated content (::before, ::after) FR9: Epic 1 - Selector matching and cascade resolution FR10: Epic 1 - CSS inheritance and initial/inherit/unset keywords FR11: Epic 3 - JavaScript parsing and execution FR12: Epic 2 - Script loading (inline, external, async, defer) FR13: Epic 2 (DOM infrastructure) + Epic 3 (JS bindings) - DOM manipulation APIs FR14: Epic 3 - Event dispatch (capture, target, bubble phases) FR15: Epic 3 - Microtasks, macrotasks, requestAnimationFrame FR16: Epic 3 - Web API exposure (console, JSON, fetch, storage APIs) FR17: Epic 3 - JavaScript error handling without crashing FR18: Epic 5 - URL navigation FR19: Epic 5 - Resource loading (HTTP, HTTPS, file://, data:) FR20a: Epic 5 - HTTP redirect following FR20b: Epic 5 - HTTP error response display FR21: Epic 5 - Cookie management (P1 -- done, maintained) FR22: Epic 5 - HTTP caching (P1 -- done, maintained) FR23: Epic 5 - Session state persistence (P1 -- done, maintained) FR24: Epic 5 - Forward/backward history navigation FR25: Epic 2 - Base URL resolution () FR26: Epic 4 - Form control interaction FR27: Epic 4 - Form submission (GET/POST, multipart/form-data) FR28: Epic 4 - Client-side form validation FR29: Epic 4 - Click, keyboard, scroll interaction FR30: Epic 4 - Focus management and keyboard navigation FR31: Epic 5 - Address bar display and editing FR33: Epic 5 - Vertical and horizontal scrolling FR34: Epic 5 - Loading indicator FR35: Epic 5 - Reload and stop navigation FR36: Epic 5 - Chrome UI rendering FR38: Epic 6 - Same-origin policy enforcement FR39: Epic 6 - javascript:/data: URI navigation blocking FR41: Epic 5 - Offline cached response serving (P1 -- done, maintained) FR42: Epic 6 - localStorage and sessionStorage FR47: Epic 1 - CSS 2.1 WPT 90%+ pass rate FR48: Epic 3 - Test262 95%+ pass rate FR49: Epic 2 - HTML5 WPT 90%+ pass rate FR50: Epic 6 - Malformed input handling without crashes
Epic List
Epic 1: Visual Fidelity -- CSS 2.1 Complete
Web pages render with full CSS 2.1 visual fidelity. Margin collapsing, stacking contexts, positioning, generated content, tables, backgrounds, borders, text, and overflow all work correctly. Sites like CNN and Hacker News look right. FRs covered: FR2, FR3, FR4, FR5a, FR5b, FR7a, FR7b, FR8, FR9, FR10, FR47
Epic 1: Visual Fidelity -- CSS 2.1 Complete
Web pages render with full CSS 2.1 visual fidelity. Margin collapsing, stacking contexts, positioning, generated content, tables, backgrounds, borders, text, and overflow all work correctly. Sites like CNN and Hacker News look right.
FRs covered: FR2, FR3, FR4, FR5a, FR5b, FR7a, FR7b, FR8, FR9, FR10 Exit criterion: FR47 -- CSS 2.1 WPT 90%+ pass rate
Story 1.1: Margin Collapsing Completeness
As a web user, I want pages to render with correct vertical spacing between elements, So that text, headings, and content blocks have proper visual separation matching other browsers.
Acceptance Criteria:
Given two adjacent block-level siblings with bottom and top margins When the page is rendered Then the margins collapse to the larger of the two values per CSS 2.1 §8.3.1
Given a parent element with no border, padding, or clearance and a first/last child with margin When the page is rendered Then the child's margin collapses through the parent per CSS 2.1 §8.3.1
Given an empty block with top and bottom margins and no border, padding, or height When the page is rendered Then the top and bottom margins collapse into a single margin
Given an element with clearance set When the page is rendered Then margin collapsing is prevented at the clearance boundary
And golden tests cover each collapsing case, docs/CSS2.1_Implementation_Checklist.md is updated, and just ci passes.
Story 1.2: Stacking Contexts & Z-Index
As a web user, I want overlapping elements to render in the correct front-to-back order, So that menus, modals, and layered content display correctly.
Acceptance Criteria:
Given an element with position: relative/absolute/fixed and a z-index value other than auto
When the page is rendered
Then a new stacking context is created per CSS 2.1 §9.9.1
Given elements within the same stacking context When the page is rendered Then painting order follows CSS 2.1 §E.2: backgrounds/borders → negative z-index → block flow → floats → inline flow → z-index 0/auto → positive z-index
Given nested stacking contexts When the page is rendered Then child stacking contexts are painted atomically within their parent's z-order position
And golden tests cover overlapping positioned elements with various z-index values, checklist is updated, and just ci passes.
Story 1.3: Positioning Completeness
As a web user, I want fixed-position headers, tooltips, and absolutely positioned elements to appear in the correct location, So that page layouts with positioned elements render correctly.
Acceptance Criteria:
Given an element with position: fixed
When the page is scrolled
Then the element remains fixed relative to the viewport
Given a positioned element with top, right, bottom, left set to auto
When the page is rendered
Then auto values resolve per CSS 2.1 §10.6.4 and §10.3.7 based on the element's static position
Given a positioned element with clip: rect(...)
When the page is rendered
Then the element's visible area is clipped to the specified rectangle per CSS 2.1 §11.1.2
Given an absolutely positioned element within a relatively positioned container When the page is rendered Then the element is positioned relative to its containing block's padding edge
And golden tests cover fixed positioning, auto resolution, and clip, checklist is updated, and just ci passes.
Story 1.4: Generated Content
As a web user,
I want CSS-generated content (bullets, quotes, labels) to render correctly,
So that pages using ::before and ::after pseudo-elements display as intended.
Acceptance Criteria:
Given a CSS rule with ::before or ::after and a content property with a string value
When the page is rendered
Then the string content is inserted as an inline box before/after the element's content per CSS 2.1 §12.1
Given a content value using attr()
When the page is rendered
Then the attribute value from the HTML element is inserted as generated content
Given a content value using counter() with counter-reset and counter-increment
When the page is rendered
Then the counter value is computed and displayed per CSS 2.1 §12.4
Given generated content with styling (color, font-size, display) When the page is rendered Then the pseudo-element is styled independently from its originating element
And golden tests cover string content, attr(), counter(), checklist is updated, and just ci passes.
Story 1.5: Table Layout Completeness
As a web user, I want HTML tables to render with correct cell sizing, borders, and captions, So that tabular data displays correctly on real websites.
Acceptance Criteria:
Given a table with border-collapse: collapse
When the page is rendered
Then adjacent cell borders are merged using the conflict resolution rules per CSS 2.1 §17.6.2
Given a table with border-collapse: separate and border-spacing
When the page is rendered
Then cells are separated by the specified spacing
Given a table with caption-side: top or caption-side: bottom
When the page is rendered
Then the caption is placed above or below the table box respectively
Given a table with empty-cells: hide and cells containing no content
When the page is rendered
Then borders and backgrounds of empty cells are not drawn
Given a table with cells spanning rows/columns and percentage/fixed widths When the page is rendered Then the table layout algorithm distributes space correctly per CSS 2.1 §17.5
And golden tests cover each table feature, checklist is updated, and just ci passes.
Story 1.6: Lists & Counters
As a web user, I want ordered and unordered lists to render with correct markers and numbering, So that list content displays properly on real websites.
Acceptance Criteria:
Given a list element with list-style-position: inside or outside
When the page is rendered
Then the marker is positioned inside or outside the list item's content area per CSS 2.1 §12.5.1
Given a list with list-style-image pointing to a valid URL
When the page is rendered
Then the specified image is used as the list marker
Given elements with counter-reset and counter-increment properties
When the page is rendered
Then counters are created, incremented, and scoped correctly per CSS 2.1 §12.4
Given nested lists with automatic counter numbering When the page is rendered Then each nesting level maintains its own counter scope
And golden tests cover list marker positioning, custom images, and nested counters, checklist is updated, and just ci passes.
Story 1.7: Backgrounds
As a web user, I want page and element backgrounds to render correctly with images, patterns, and positioning, So that visually rich websites display as intended.
Acceptance Criteria:
Given an element with the full background shorthand property
When the page is rendered
Then all background sub-properties (color, image, repeat, attachment, position) are parsed and applied correctly per CSS 2.1 §14.2.1
Given an element with background-image: url(...) and background-repeat
When the page is rendered
Then the image is tiled according to the repeat value (repeat, repeat-x, repeat-y, no-repeat)
Given an element with background-attachment: fixed
When the page is scrolled
Then the background image remains fixed relative to the viewport
Given an element with background-position using keyword, percentage, or length values
When the page is rendered
Then the background image is positioned correctly within the element's padding box
And golden tests cover each background property combination, checklist is updated, and just ci passes.
Story 1.8: Borders & Outline
As a web user, I want all CSS border styles and outlines to render correctly, So that element borders display with the correct visual appearance.
Acceptance Criteria:
Given an element with border-style set to double
When the page is rendered
Then two parallel lines with a gap between them are drawn per CSS 2.1 §8.5.3
Given an element with border-style set to groove, ridge, inset, or outset
When the page is rendered
Then the 3D border effect is rendered with appropriate light/dark color variations
Given an element with outline properties (outline-style, outline-width, outline-color)
When the page is rendered
Then the outline is drawn outside the border edge without affecting layout per CSS 2.1 §18.4
Given an element with outline-offset
When the page is rendered
Then the outline is offset from the border edge by the specified amount
And golden tests cover each border style and outline, checklist is updated, and just ci passes.
Story 1.9: Text Properties
As a web user, I want text to render with correct indentation, decoration, spacing, and directionality, So that text-heavy pages display properly across languages and styles.
Acceptance Criteria:
Given an element with text-indent
When the page is rendered
Then the first line of the block is indented by the specified amount per CSS 2.1 §16.1
Given an element with text-decoration: underline | overline | line-through (including inherited/accumulated values)
When the page is rendered
Then the decorations are drawn correctly and propagate to inline descendants per CSS 2.1 §16.3
Given an element with word-spacing or letter-spacing
When the page is rendered
Then additional spacing is applied between words or characters respectively
Given an element with direction: rtl and unicode-bidi
When the page is rendered
Then text is laid out right-to-left with correct bidi reordering per CSS 2.1 §9.10
And golden tests cover each text property, checklist is updated, and just ci passes.
Story 1.10: Font Properties
As a web user, I want font styles to render correctly including shorthand declarations and variant styles, So that typography on web pages matches the designer's intent.
Acceptance Criteria:
Given an element with the font shorthand property
When the page is rendered
Then all font sub-properties (style, variant, weight, size, line-height, family) are parsed and applied correctly per CSS 2.1 §15.8
Given an element with font-variant: small-caps
When the page is rendered
Then lowercase characters are rendered as small capital letters
Given a CSS value using ex units
When the page is rendered
Then the unit resolves to the x-height of the element's font per CSS 2.1 §4.3.2
Given font metrics from the bundled font set When computing line-height and baseline alignment Then the correct ascent, descent, and x-height values are used for layout calculations
And golden tests cover font shorthand, small-caps, and ex units, checklist is updated, and just ci passes.
Story 1.11: Overflow
As a web user, I want content that exceeds its container to be clipped or scrollable as specified, So that pages with constrained containers display correctly.
Acceptance Criteria:
Given an element with overflow: hidden and content exceeding its bounds
When the page is rendered
Then overflowing content is clipped at the element's padding edge
Given an element with overflow: scroll
When the page is rendered
Then a scrolling mechanism is provided regardless of whether content overflows
Given an element with overflow: auto and content exceeding its bounds
When the page is rendered
Then a scrolling mechanism is provided only when content overflows
Given an element with overflow clipping and positioned children When the page is rendered Then clipping is applied correctly to the element's content and descendants per CSS 2.1 §11.1.1
And golden tests cover each overflow value, checklist is updated, and just ci passes.
Story 1.12: Media Rules
As a web user,
I want stylesheets imported via @import and conditional @media rules to apply correctly,
So that pages load external stylesheets and respond to media types.
Acceptance Criteria:
Given a stylesheet with @import url("other.css")
When the page is rendered
Then the imported stylesheet's rules are fetched and applied with correct cascade order per CSS 2.1 §6.3
Given a stylesheet with @import url("print.css") print
When rendering for screen media type
Then the imported stylesheet is not applied
Given a @media screen { ... } block
When rendering for screen media type
Then the rules inside the block are applied
Given a @media print { ... } block
When rendering for screen media type
Then the rules inside the block are not applied
And golden tests cover @import and @media rules, checklist is updated, and just ci passes.
Story 1.13: CSS Inheritance Completeness
As a web user, I want CSS property values to correctly inherit, reset, and cascade, So that styling behaves predictably across nested elements.
Acceptance Criteria:
Given an element with a property set to inherit
When the page is rendered
Then the element uses its parent's computed value for that property per CSS 2.1 §6.2.1
Given an element with a property set to initial
When the page is rendered
Then the element uses the property's initial value per its specification
Given an element with a property set to unset
When the page is rendered
Then the property behaves as inherit if it's an inherited property, or initial if it's not
Given all CSS 2.1 properties When checking inheritance behavior Then each property correctly defaults to inherited or non-inherited per its CSS 2.1 specification
And golden tests cover inherit/initial/unset for both inherited and non-inherited properties, checklist is updated, and just ci passes.
Epic 2: Document Completeness -- HTML5 Full Support
All HTML5 elements and document features work correctly. Full tokenizer state machine, tree builder insertion modes, DOM core APIs (DocumentFragment, insertBefore, replaceChild, live collections, querySelector/querySelectorAll), document lifecycle events, script loading modes, and base URL resolution.
FRs covered: FR1, FR6, FR12, FR13 (DOM infrastructure), FR25 Exit criterion: FR49 -- HTML5 WPT 90%+ pass rate
Story 2.1: HTML5 Tokenizer Completeness
As a web user, I want all HTML content to be parsed correctly regardless of markup patterns, So that pages render properly even with unusual or complex HTML.
Acceptance Criteria:
Given HTML content using all tokenizer states (data, RCDATA, RAWTEXT, script data, PLAINTEXT, etc.) When the HTML is parsed Then each state transition produces the correct tokens per WHATWG HTML §13.2.5
Given HTML with character references (named, numeric, hexadecimal) in various contexts When the HTML is parsed Then character references are resolved correctly per their context (attribute vs. content)
Given HTML with CDATA sections, processing instructions, and bogus comments When the HTML is parsed Then each construct is tokenized according to the spec without errors
Given malformed HTML with unclosed tags, missing quotes, and invalid characters When the HTML is parsed Then the tokenizer recovers gracefully without panics per the spec's error handling rules
And golden tests cover edge-case tokenizer states, docs/HTML5_Implementation_Checklist.md is updated, and just ci passes.
Story 2.2: Tree Builder Insertion Modes
As a web user, I want the browser to construct the correct DOM tree from any HTML document, So that page structure matches what other browsers produce.
Acceptance Criteria:
Given HTML content triggering each tree builder insertion mode (initial, before html, before head, in head, in body, in table, in select, after body, etc.) When the HTML is parsed Then elements are inserted into the correct location in the DOM tree per WHATWG HTML §13.2.6
Given HTML with implicit element creation (e.g., <td> without <table>, text before <html>)
When the HTML is parsed
Then missing elements are created automatically per the spec's implied open/close rules
Given HTML with misnested block/inline elements (e.g., <p><div></div></p>)
When the HTML is parsed
Then the tree builder splits and restructures elements per the spec
Given HTML with elements that change insertion mode (tables, select, template, etc.) When the HTML is parsed Then the correct insertion mode is activated and deactivated at the right boundaries
And WPT tree-construction tests pass for all covered insertion modes, checklist is updated, and just ci passes.
Story 2.3: Adoption Agency & Foster Parenting
As a web user, I want misnested formatting tags and misplaced table content to render correctly, So that real-world pages with imperfect HTML display as expected.
Acceptance Criteria:
Given HTML with misnested formatting elements (e.g., <b>text<i>more</b>rest</i>)
When the HTML is parsed
Then the adoption agency algorithm restructures the DOM tree so formatting is correctly applied per WHATWG HTML §13.2.6.4.7
Given the adoption agency algorithm running on deeply nested formatting (8+ levels) When the HTML is parsed Then the algorithm respects the iteration and nesting limits defined in the spec
Given HTML with non-table content directly inside <table>, <tbody>, <tr> elements
When the HTML is parsed
Then the content is foster-parented to the correct location before the table per WHATWG HTML §13.2.6.1
Given a combination of foster parenting and adoption agency in the same document When the HTML is parsed Then both algorithms interact correctly producing the spec-defined DOM tree
And WPT tree-construction tests covering adoption agency and foster parenting pass, checklist is updated, and just ci passes.
Story 2.4: DOM Tree Mutation APIs
As a web developer using JavaScript, I want to create, insert, replace, and move DOM nodes programmatically, So that dynamic web pages can modify their structure at runtime.
Acceptance Criteria:
Given JavaScript calling document.createDocumentFragment()
When nodes are appended to the fragment and the fragment is inserted into the DOM
Then all child nodes transfer to the insertion point and the fragment becomes empty per DOM §4.5
Given JavaScript calling parentNode.insertBefore(newNode, referenceNode)
When the operation completes
Then the new node is inserted before the reference node, or appended if reference is null
Given JavaScript calling parentNode.replaceChild(newChild, oldChild)
When the operation completes
Then the old child is removed and the new child takes its place in the DOM tree
Given a node being inserted that already exists elsewhere in the DOM When the insertion API is called Then the node is moved (removed from its current parent and inserted at the new location)
And integration tests verify each mutation API, docs/DOM_Implementation_Checklist.md is updated, and just ci passes.
Story 2.5: DOM Query APIs & Live Collections
As a web developer using JavaScript, I want to query the DOM by CSS selectors and access live element collections, So that scripts can efficiently find and track elements in the document.
Acceptance Criteria:
Given JavaScript calling document.querySelector(selector) with a valid CSS selector
When the query executes
Then the first matching element is returned, or null if no match exists
Given JavaScript calling document.querySelectorAll(selector)
When the query executes
Then a static NodeList of all matching elements is returned in document order
Given JavaScript calling document.getElementsByTagName(name) or document.getElementsByClassName(name)
When the DOM is subsequently modified (elements added/removed)
Then the returned HTMLCollection reflects the changes automatically (live collection)
Given complex CSS selectors (combinators, pseudo-classes like :first-child, :nth-child, attribute selectors)
When used with querySelector/querySelectorAll
Then the selectors match correctly using the existing selector matching engine
And integration tests verify query APIs and live collection behavior, DOM checklist is updated, and just ci passes.
Story 2.6: Script Loading -- async/defer
As a web user, I want pages to load faster by running scripts asynchronously or after parsing, So that script-heavy pages don't block rendering unnecessarily.
Acceptance Criteria:
Given a <script defer src="..."> element
When the HTML is parsed
Then the script is fetched in parallel with parsing and executed after the document is fully parsed, in document order per WHATWG HTML §4.12.1
Given a <script async src="..."> element
When the HTML is parsed
Then the script is fetched in parallel and executed as soon as it's available, regardless of document order
Given multiple <script defer> elements in a document
When all scripts have loaded and the document is parsed
Then they execute in the order they appear in the document
Given a <script> with both async and defer attributes
When the HTML is parsed
Then the async attribute takes precedence per the spec
And integration tests verify each loading mode's execution timing and ordering, checklist is updated, and just ci passes.
Story 2.7: Document Lifecycle
As a web developer using JavaScript, I want document lifecycle events to fire at the correct times, So that scripts can initialize at the right point in page loading.
Acceptance Criteria:
Given a page with a DOMContentLoaded event listener
When the HTML has been fully parsed (but stylesheets/images may still be loading)
Then the DOMContentLoaded event fires on the document
Given a page with a load event listener on the window
When all resources (images, stylesheets, scripts) have finished loading
Then the load event fires
Given JavaScript reading document.readyState
When the document is in different loading phases
Then it returns "loading" during parsing, "interactive" after parsing (before load), and "complete" after all resources load
Given a readystatechange event listener
When document.readyState changes
Then the event fires for each transition
And integration tests verify event timing and readyState transitions, checklist is updated, and just ci passes.
Story 2.8: iframe Support
As a web user, I want embedded content in iframes to load and render, So that pages using iframes for embedded documents display correctly.
Acceptance Criteria:
Given an <iframe src="..."> element in a page
When the page is rendered
Then the iframe's source document is fetched, parsed, and rendered within the iframe's content area
Given an iframe with width and height attributes or CSS sizing
When the page is rendered
Then the iframe's content area matches the specified dimensions
Given an iframe document with its own stylesheets and scripts When the iframe is rendered Then styles and scripts are scoped to the iframe's document and do not affect the parent
Given an iframe with srcdoc attribute
When the page is rendered
Then the inline HTML content is parsed and rendered as the iframe's document
And golden tests cover iframe rendering, checklist is updated, and just ci passes.
Story 2.9: Base URL Resolution & Image Rendering Completeness
As a web user, I want all relative URLs to resolve correctly and all image formats to render, So that pages with relative links and various image types display properly.
Acceptance Criteria:
Given a document with <base href="https://example.com/path/">
When relative URLs are resolved (in links, images, scripts, stylesheets)
Then the base URL is used instead of the document's URL per WHATWG HTML §4.2.3
Given multiple <base> elements in a document
When URLs are resolved
Then only the first <base> with an href attribute is used
Given images in PNG, JPEG, GIF, WebP, and SVG formats referenced as <img> or CSS background-image
When the page is rendered
Then each format decodes and renders correctly at the specified dimensions
Given an <img> with width/height attributes and/or CSS sizing
When the image is rendered
Then the image scales to the specified dimensions while the intrinsic aspect ratio is used for auto dimensions
And golden tests cover base URL resolution and each image format, checklists are updated, and just ci passes.
Epic 3: Interactive Web -- JavaScript Engine Maturity
JS-heavy websites function. Generators, async/await, ES modules, complete built-in coverage, and 95%+ Test262 conformance. DOM manipulation via JS bindings, full event dispatch, microtask/macrotask scheduling, Web API exposure, and robust error handling.
FRs covered: FR11, FR13 (JS bindings), FR14, FR15, FR16, FR17 Exit criterion: FR48 -- Test262 95%+ pass rate
Story 3.1: Bytecode IR Introduction
As a browser developer, I want the JavaScript engine to execute via a bytecode interpreter instead of an AST walker, So that suspension semantics (generators, async/await) can be cleanly implemented and execution performance improves.
Acceptance Criteria:
Given the existing JavaScript test suite (vendored Test262 + unit tests) When execution is switched from AST walker to bytecode interpreter Then all previously passing tests continue to pass with identical results
Given a JavaScript program When it is executed Then the js_parser produces an AST, a bytecode compiler emits bytecode instructions, and the bytecode interpreter executes them
Given the bytecode instruction set When reviewed against the ECMAScript spec Then it supports all currently implemented language features (variables, functions, closures, control flow, try/catch, classes, etc.)
Given the bytecode interpreter's execution model When a suspension point is needed (for future generators/async-await) Then the interpreter's frame/stack design supports saving and restoring execution state
And docs/js_feature_matrix.md is updated to note the bytecode transition, and just ci passes.
Story 3.2: Generators & Iterator Protocol
As a web developer using JavaScript, I want generator functions and the iterator protocol to work, So that lazy sequences, custom iterables, and for...of loops function correctly.
Acceptance Criteria:
Given a generator function declared with function*
When called
Then it returns a generator object without executing the body
Given a generator object
When next() is called
Then execution resumes from the last yield point and returns {value, done} per ECMAScript §27.5
Given a generator with yield* delegating to another iterable
When iterated
Then values from the inner iterable are yielded one at a time
Given an object implementing the iterator protocol (Symbol.iterator, next())
When used with for...of, spread syntax, or destructuring
Then the iteration protocol is followed correctly
Given a generator with return() or throw() called on it
When the method is invoked
Then the generator completes or throws at the current suspension point
And Test262 generator/iterator tests are promoted in the manifest, feature matrix is updated, and just ci passes.
Story 3.3: async/await
As a web developer using JavaScript, I want async functions and await expressions to work, So that asynchronous code can be written in a readable, sequential style.
Acceptance Criteria:
Given a function declared with async function
When called
Then it returns a Promise that resolves with the function's return value
Given an await expression inside an async function
When the awaited value is a Promise
Then execution suspends until the Promise settles, then resumes with the resolved value or throws the rejection
Given an await expression with a non-Promise value
When executed
Then the value is wrapped in a resolved Promise and execution continues
Given a try/catch block inside an async function with an awaited rejected Promise
When the Promise rejects
Then the rejection is caught by the catch block
Given multiple async functions with interleaved awaits When executed Then microtask scheduling follows the correct order per ECMAScript §27.7
And Test262 async/await tests are promoted in the manifest, feature matrix is updated, and just ci passes.
Story 3.4: ES Modules
As a web developer using JavaScript,
I want import/export statements and <script type="module"> to work,
So that modular JavaScript code loads and executes correctly.
Acceptance Criteria:
Given a <script type="module" src="..."> element
When the page is loaded
Then the module is fetched, parsed, and executed in strict mode with deferred timing per WHATWG HTML §4.12.1
Given a module with import { foo } from './other.js'
When the module is executed
Then the binding is resolved from the target module's exports per ECMAScript §16.2
Given a module with export default and named export declarations
When imported by another module
Then the exported bindings are available to the importing module
Given circular module dependencies (A imports B, B imports A) When the modules are loaded Then the module registry handles the cycle without deadlock, with uninitialized bindings where appropriate per ECMAScript §16.2.1.5.2
Given a module imported by multiple other modules When the page is loaded Then the module is fetched and evaluated exactly once (singleton semantics)
And Test262 module tests are promoted, feature matrix is updated, and just ci passes.
Story 3.5: Built-in Completeness -- Array/String/Object
As a web developer using JavaScript, I want all standard Array, String, and Object methods to be available, So that common JavaScript patterns and library code work correctly.
Acceptance Criteria:
Given Array methods (flat, flatMap, findIndex, findLast, findLastIndex, from, of, at, toReversed, toSorted, toSpliced, with, etc.) When called on arrays Then each method behaves per its ECMAScript specification
Given String methods (replaceAll, matchAll, trimStart, trimEnd, padStart, padEnd, startsWith, endsWith, at, etc.) When called on strings Then each method behaves per its ECMAScript specification
Given Object methods (fromEntries, hasOwn, entries, keys, values, assign, getOwnPropertyDescriptors, etc.) When called Then each method behaves per its ECMAScript specification
Given methods that accept callback functions (map, filter, reduce, sort, etc.) When the callback throws an error Then the error propagates correctly without corrupting internal state
And Test262 tests for each built-in are promoted in the manifest, feature matrix is updated, and just ci passes.
Story 3.6: Built-in Completeness -- Date/RegExp/Map/Set
As a web developer using JavaScript, I want Date, RegExp, Map, Set, WeakMap, and WeakSet to work completely, So that date handling, pattern matching, and collection types function correctly.
Acceptance Criteria:
Given Date construction, parsing, and formatting methods When called with various inputs (ISO strings, timestamps, individual components) Then each method behaves per ECMAScript §21.4 including edge cases (invalid dates, timezone handling)
Given RegExp with all flags (g, i, m, s, u, y, d) and advanced features (named groups, lookbehind, Unicode property escapes)
When used with test(), exec(), match(), matchAll(), replace(), split()
Then each operation behaves per ECMAScript §22.2
Given Map and Set with their full method sets (set/get/has/delete/clear/forEach/entries/keys/values) When used with various key types (objects, primitives, NaN, -0) Then each method behaves per ECMAScript §24.1-24.2
Given WeakMap and WeakSet with object keys When keys are no longer referenced elsewhere Then entries are eligible for garbage collection (not required to be immediate)
And Test262 tests for each built-in are promoted in the manifest, feature matrix is updated, and just ci passes.
Story 3.7: WeakRef, FinalizationRegistry & Strict Mode Edge Cases
As a web developer using JavaScript, I want advanced memory management APIs and complete strict mode support, So that all ECMAScript edge cases are handled correctly.
Acceptance Criteria:
Given a WeakRef wrapping an object
When deref() is called
Then the target object is returned if still alive, or undefined if collected per ECMAScript §26.1
Given a FinalizationRegistry with a registered target
When the target is garbage collected
Then the cleanup callback is eventually called with the held value per ECMAScript §26.2
Given strict mode code with assignments to undeclared variables When executed Then a ReferenceError is thrown instead of creating a global
Given strict mode edge cases (duplicate parameter names, with statement, octal literals, delete on unqualified identifiers)
When parsed or executed in strict mode
Then SyntaxError or appropriate errors are thrown per ECMAScript §10.2.1
And Test262 tests for WeakRef, FinalizationRegistry, and strict mode are promoted, feature matrix is updated, and just ci passes.
Story 3.8: DOM Bindings via web_api
As a web developer using JavaScript, I want full DOM manipulation capabilities from JavaScript, So that dynamic web pages can create, modify, and style elements at runtime.
Acceptance Criteria:
Given JavaScript calling document.createElement(tagName)
When the element is created and appended to the DOM
Then the element is rendered with correct default styling and behavior
Given JavaScript accessing element.classList (add, remove, toggle, contains)
When classes are modified
Then the element's class attribute updates and styles are recomputed on the next render
Given JavaScript accessing element.style.propertyName for reading and writing
When inline styles are set or read
Then the values affect rendering and reflect the current inline style
Given JavaScript accessing element.getAttribute(), setAttribute(), removeAttribute()
When attributes are modified
Then the DOM reflects the changes and dependent behavior updates (e.g., src triggers fetch)
Given JavaScript accessing node properties (textContent, innerHTML, childNodes, parentNode, nextSibling)
When read or written
Then the values reflect the current DOM state and mutations trigger re-rendering
And integration tests verify each binding, DOM checklist is updated, and just ci passes.
Story 3.9: Event Dispatch Completeness
As a web developer using JavaScript, I want all event types and dispatch phases to work correctly, So that interactive elements respond to user actions as expected.
Acceptance Criteria:
Given an event listener registered with addEventListener(type, handler, {capture: true})
When the event is dispatched
Then the handler fires during the capture phase (root to target) per DOM §2.9
Given mouse events (click, mousedown, mouseup, mouseover, mouseout, mousemove) When dispatched to JavaScript handlers Then event objects include correct properties (clientX, clientY, button, target)
Given keyboard events (keydown, keyup, keypress) When dispatched to JavaScript handlers Then event objects include correct properties (key, code, ctrlKey, shiftKey, altKey)
Given focus events (focus, blur, focusin, focusout) When focus changes between elements Then events fire in the correct order with correct relatedTarget values
Given event.stopPropagation() or event.stopImmediatePropagation() called in a handler
When the event continues dispatching
Then propagation stops at the current target (stopPropagation) or current handler (stopImmediatePropagation)
And integration tests verify each event type and dispatch behavior, and just ci passes.
Story 3.10: Web API Exposure
As a web developer using JavaScript, I want fetch, console, and scheduling APIs to work correctly, So that network requests, debugging, and async task scheduling function properly.
Acceptance Criteria:
Given JavaScript calling fetch(url)
When the request completes
Then a Response object is returned with correct status, headers, and body methods (text(), json(), arrayBuffer())
Given JavaScript calling console.log(), console.warn(), console.error() with multiple arguments
When executed
Then all arguments are formatted and output correctly including object inspection
Given setTimeout and setInterval with callbacks and delay values
When the event loop runs
Then callbacks execute after the specified delay in correct macrotask order per HTML §8.6
Given Promise.then() microtasks interleaved with setTimeout macrotasks
When the event loop runs
Then all microtasks drain before the next macrotask executes
Given requestAnimationFrame callbacks
When the render loop runs
Then callbacks execute before the next paint in registration order
And integration tests verify each API's behavior, and just ci passes.
Epic 4: User Input & Forms
Users fill out and submit forms on real websites. All form controls work, client-side validation provides feedback, multipart/form-data supports file uploads, focus and keyboard navigation work correctly.
FRs covered: FR26, FR27, FR28, FR29, FR30
Story 4.1: Text Inputs & Textareas
As a web user, I want to type text into input fields and textareas, So that I can enter data into forms on websites.
Acceptance Criteria:
Given an <input type="text"> element
When the user clicks on it and types
Then text appears in the input field with a visible cursor at the insertion point
Given an <input> with type="password"
When the user types
Then characters are masked (displayed as dots or asterisks)
Given an <input> with placeholder attribute and no value
When the input is rendered
Then the placeholder text is displayed in a dimmed style and disappears when the user types
Given a <textarea> element
When the user types multiple lines of text
Then the text wraps and the textarea scrolls to accommodate content exceeding its height
Given an <input> with value, maxlength, or readonly attributes
When the user interacts with it
Then the initial value is displayed, input is limited to maxlength characters, and readonly inputs reject editing
And integration tests verify each input type's behavior, golden tests cover rendering, and just ci passes.
Story 4.2: Buttons, Checkboxes & Radio Buttons
As a web user, I want to click buttons, toggle checkboxes, and select radio options, So that I can make choices and trigger actions in web forms.
Acceptance Criteria:
Given a <button> or <input type="submit"> element
When the user clicks it
Then the button's click event fires and submit buttons trigger form submission
Given an <input type="checkbox">
When the user clicks it
Then the checked state toggles and the change event fires
Given multiple <input type="radio"> elements with the same name attribute
When the user selects one
Then the previously selected radio in the group is deselected and the change event fires
Given a <label> element associated with a form control (via for attribute or nesting)
When the user clicks the label
Then the associated control is activated (focused, toggled, or clicked)
Given form controls with disabled attribute
When the user attempts to interact
Then the control does not respond and is rendered in a disabled visual style
And integration tests verify each control type, golden tests cover rendering states, and just ci passes.
Story 4.3: Select Menus & Option Elements
As a web user, I want to choose from dropdown menus on web forms, So that I can select options from predefined lists.
Acceptance Criteria:
Given a <select> element with <option> children
When the user clicks the select element
Then a dropdown list of options is displayed
Given an open select dropdown
When the user clicks an option
Then the option is selected, the dropdown closes, and the change event fires
Given a <select> with an <option selected> attribute
When the page is rendered
Then the pre-selected option is displayed as the current value
Given a <select multiple> element
When the user clicks options (with Ctrl/Cmd for multi-select)
Then multiple options can be selected simultaneously
Given a <select> with <optgroup> elements
When the dropdown is displayed
Then options are grouped under non-selectable group labels
And integration tests verify select behavior, golden tests cover dropdown rendering, and just ci passes.
Story 4.4: Form Submission
As a web user, I want forms to submit my data to the server, So that I can log in, search, and interact with web applications.
Acceptance Criteria:
Given a <form method="GET"> with filled form controls
When the form is submitted
Then form data is serialized as application/x-www-form-urlencoded and appended to the action URL as a query string
Given a <form method="POST"> with filled form controls
When the form is submitted
Then form data is serialized as application/x-www-form-urlencoded in the request body
Given a <form enctype="multipart/form-data" method="POST">
When the form is submitted
Then form data is encoded using multipart MIME format with correct boundary delimiters
Given a form with disabled controls or controls without name attributes
When the form is submitted
Then those controls are excluded from the submitted data per HTML §4.10.21.3
Given a form with action, method, and target attributes
When submitted
Then the request is sent to the action URL using the specified method
And integration tests verify each submission method and encoding, and just ci passes.
Story 4.5: Client-Side Form Validation
As a web user, I want the browser to validate my form input before submission, So that I get immediate feedback on errors without a server round-trip.
Acceptance Criteria:
Given an <input required> that is empty
When the form is submitted
Then submission is blocked and a validation message is shown on the invalid control
Given an <input pattern="[A-Z]{3}"> with a value that doesn't match
When the form is submitted
Then submission is blocked and a pattern mismatch message is shown
Given an <input type="number" min="1" max="100"> with a value outside the range
When the form is submitted
Then submission is blocked with a range overflow/underflow message
Given an <input minlength="3" maxlength="50"> with a value outside the length bounds
When the form is submitted
Then submission is blocked with a too-short/too-long message
Given an <input type="email"> or <input type="url"> with an invalid value
When the form is submitted
Then submission is blocked with a type mismatch message
Given a form with novalidate attribute or a submit button with formnovalidate
When the form is submitted
Then client-side validation is skipped
And integration tests verify each constraint type, and just ci passes.
Story 4.6: Click, Keyboard & Scroll Interaction
As a web user, I want my clicks, key presses, and scroll actions to work correctly on all page content, So that I can interact with web pages naturally.
Acceptance Criteria:
Given the user clicks on an element When the click event is processed Then the correct element receives the event based on hit testing (topmost visible element at the click coordinates)
Given the user presses keys while an element is focused When the keydown/keyup events are processed Then the correct key information is delivered to the focused element and default behaviors fire (e.g., typing in inputs, Enter on links)
Given the user scrolls via mouse wheel or trackpad When the scroll event is processed Then the correct scrollable container scrolls by the appropriate amount
Given a page with nested scrollable containers When the inner container reaches its scroll boundary Then scroll events propagate to the outer container (scroll chaining)
And integration tests verify hit testing, keyboard dispatch, and scroll behavior, and just ci passes.
Story 4.7: Focus Management & Keyboard Navigation
As a web user, I want to navigate between interactive elements using the Tab key, So that I can use web forms and pages without a mouse.
Acceptance Criteria:
Given a page with focusable elements (links, form controls, elements with tabindex) When the user presses Tab Then focus moves to the next focusable element in document order
Given the user pressing Shift+Tab When an element is focused Then focus moves to the previous focusable element in document order
Given elements with tabindex="0"
When the user tabs through the page
Then those elements are included in the tab order at their document position
Given elements with tabindex="-1"
When the user tabs through the page
Then those elements are skipped but can be focused programmatically via JavaScript
Given elements with positive tabindex values
When the user tabs through the page
Then those elements are visited first in ascending tabindex order, before tabindex="0" elements
And integration tests verify tab order with various tabindex configurations, and just ci passes.
Epic 5: Navigation & Browser Shell
Complete browsing experience -- history navigation, error pages, loading indicators, reload/stop, and polished chrome UI. Maintains already-delivered networking capabilities (cookies, caching, sessions).
FRs covered: FR18, FR19, FR20a, FR20b, FR24, FR31, FR33, FR34, FR35, FR36 (+ maintained: FR21, FR22, FR23, FR41)
Story 5.1: URL Navigation & Protocol Schemes
As a web user, I want to navigate to any URL and have the correct content load, So that I can browse websites, local files, and embedded data content.
Acceptance Criteria:
Given the user enters an HTTP or HTTPS URL in the address bar When the navigation is initiated Then the resource is fetched over the network, parsed, and rendered
Given the user enters a file:// URL
When the navigation is initiated
Then the local file is read from disk and rendered
Given the user enters a URL without a scheme (e.g., example.com)
When the navigation is initiated
Then a reasonable default scheme is prepended (e.g., https://)
And integration tests verify navigation for each protocol scheme, and just ci passes.
Story 5.2: Redirect Handling
As a web user, I want the browser to follow redirects automatically, So that I reach the correct page even when URLs have moved.
Acceptance Criteria:
Given an HTTP response with status 301 or 302 and a Location header
When the browser processes the response
Then the browser automatically navigates to the redirect target URL
Given an HTTP 303 redirect after a POST request When the browser follows the redirect Then the subsequent request uses the GET method
Given an HTTP 307 or 308 redirect When the browser follows the redirect Then the original request method and body are preserved
Given a redirect chain exceeding 20 hops When the browser follows the chain Then navigation stops and an error is displayed to the user
And integration tests verify each redirect status code and the hop limit, and just ci passes.
Story 5.3: Error Pages
As a web user, I want to see a clear error message when a page fails to load, So that I understand what went wrong instead of seeing a blank screen.
Acceptance Criteria:
Given an HTTP response with a 404 status code When the page is rendered Then the user sees an error page displaying the status code and a descriptive message
Given an HTTP response with a 500 status code When the page is rendered Then the user sees an error page indicating a server error
Given a DNS resolution failure When the navigation fails Then the user sees an error page indicating the domain could not be found
Given a connection timeout or connection refused error When the navigation fails Then the user sees an error page within 10 seconds of the failure per NFR15
Given any network or HTTP error When the error page is displayed Then the address bar still shows the attempted URL so the user can retry or edit it
And integration tests verify error page display for each failure type, and just ci passes.
Story 5.4: History Navigation
As a web user, I want to go back and forward through pages I've visited, So that I can return to previously viewed content.
Acceptance Criteria:
Given the user has navigated to 3+ pages in sequence When the user clicks the back button or presses the back shortcut Then the previous page is restored with its content re-rendered
Given the user has gone back one or more pages When the user clicks the forward button Then the next page in the forward history is restored
Given the user is on the first page in history When the back button is rendered Then it appears disabled or inactive
Given the user navigates to a new page after going back When the navigation completes Then the forward history is cleared (standard browser behavior)
And integration tests verify history navigation across 3+ entries, and just ci passes.
Story 5.5: Page Scrolling
As a web user, I want to scroll through pages that are taller or wider than my window, So that I can access all content on the page.
Acceptance Criteria:
Given a page with content taller than the viewport When the user scrolls vertically (mouse wheel, trackpad, or keyboard) Then the page content scrolls smoothly revealing content below
Given a page with content wider than the viewport When the user scrolls horizontally Then the page content scrolls horizontally revealing content to the right
Given the user presses Page Down, Page Up, Home, or End keys When the page is scrollable Then the page scrolls by the appropriate amount (viewport height for Page keys, top/bottom for Home/End)
Given the user scrolls to the top or bottom of the page When further scroll input is received in that direction Then no further scrolling occurs (scroll position clamps to content bounds)
And integration tests verify vertical/horizontal scrolling and keyboard scroll, and just ci passes.
Story 5.6: Browser Chrome Completeness
As a web user, I want a polished browser interface with working navigation controls and loading feedback, So that I have a complete browsing experience.
Acceptance Criteria:
Given the browser is running When the chrome UI is rendered Then the address bar, back/forward buttons, reload button, and stop button are visible and correctly laid out at window widths from 800px to 2560px
Given the user navigates to a page When the page is loading Then a loading indicator is visible in the chrome UI
Given a page has finished loading or failed to load When the loading completes Then the loading indicator is cleared
Given the user clicks the reload button When a page is currently displayed Then all resources are re-fetched and the page is re-rendered
Given the user clicks the stop button When a page is currently loading Then pending resource fetches are cancelled and the page displays whatever has loaded so far
Given the user navigates to a new page When the navigation completes Then the address bar updates to reflect the current URL
And integration tests verify each chrome UI behavior, and just ci passes.
Epic 6: Security, Storage & Robustness
Safe browsing with same-origin policy enforcement, URI navigation blocking, localStorage/sessionStorage for web apps, and crash-free handling of malformed input across all parsers.
FRs covered: FR38, FR39, FR42, FR50
Story 6.1: Same-Origin Policy Enforcement
As a web user, I want the browser to prevent malicious scripts from accessing my data on other sites, So that my browsing sessions are secure.
Acceptance Criteria:
Given JavaScript on origin A attempting to read DOM content from an iframe on origin B When the access is attempted Then a SecurityError is thrown and access is denied
Given JavaScript on origin A attempting to read cookies scoped to origin B When the access is attempted Then the cookies are not accessible
Given JavaScript on origin A making a fetch request to origin B without CORS headers When the response is received Then the response body is opaque and not readable by the script
Given two pages on the same origin (same scheme, host, and port) When JavaScript on one page accesses the other's resources Then access is permitted
And cross-origin integration tests verify blocked access for DOM, cookies, and fetch responses, and just ci passes.
Story 6.2: URI Navigation Blocking
As a web user,
I want the browser to block dangerous URI navigations,
So that I am protected from javascript: and data: URI attacks.
Acceptance Criteria:
Given a top-level navigation to a javascript: URI (e.g., clicking a link with href="javascript:alert(1)")
When the navigation is initiated
Then the navigation is blocked and no script is executed
Given a top-level navigation to a data: URI (e.g., data:text/html,...)
When the navigation is initiated
Then the navigation is blocked
Given a sub-resource using a data: URI (e.g., <img src="data:image/png;base64,...">)
When the resource is loaded
Then the data: URI is permitted and the resource loads correctly
Given JavaScript attempting window.location = "javascript:..." or window.location = "data:..."
When the assignment is executed
Then the navigation is blocked
And integration tests verify blocked and permitted cases for each URI scheme, and just ci passes.
Story 6.3: localStorage & sessionStorage
As a web developer using JavaScript, I want localStorage and sessionStorage APIs to work, So that web applications can persist data on the client side.
Acceptance Criteria:
Given JavaScript calling localStorage.setItem(key, value) and localStorage.getItem(key)
When the operations execute
Then the value is stored persistently and retrievable across page navigations within the same origin
Given JavaScript calling sessionStorage.setItem(key, value)
When the value is retrieved in the same browsing session
Then the value is available, but cleared when the tab/session closes
Given JavaScript calling localStorage.removeItem(key) or localStorage.clear()
When the operation executes
Then the specified key or all keys are removed from storage
Given JavaScript on origin A accessing localStorage When JavaScript on origin B attempts to access the same storage Then each origin has isolated storage and cannot access the other's data
Given localStorage data exceeding 5MB for a single origin
When a setItem call would exceed the limit
Then a QuotaExceededError is thrown
And integration tests verify getItem/setItem/removeItem/clear, storage limits, and cross-origin isolation, and just ci passes.
Story 6.4: Malformed Input Resilience
As a web user, I want the browser to handle broken or adversarial content without crashing, So that I can browse safely even on malformed pages.
Acceptance Criteria:
Given malformed HTML (unclosed tags, invalid nesting, truncated documents, binary content) When the HTML parser processes it Then parsing completes without panics, producing a best-effort DOM tree
Given malformed CSS (invalid property names, unclosed blocks, garbage bytes, deeply nested selectors) When the CSS parser processes it Then parsing completes without panics, skipping invalid rules per CSS error recovery
Given malformed JavaScript (syntax errors, deeply nested expressions, extremely long strings, invalid Unicode) When the JS parser/engine processes it Then a SyntaxError or appropriate error is reported to console.error without process termination
Given adversarial input designed to trigger resource exhaustion (billion-laughs HTML, regex backtracking, deeply recursive structures) When the parsers process it Then processing terminates gracefully within reasonable time and memory bounds
And fuzz tests and malformed-input test suites covering each parser run without panics, and just ci passes.