- Add line:col source locations in runtime error messages (PR 5) - Consolidate info! → debug! logging, add debug_span! for event loop, dispatch, and microtask drain (PR 6) - Add 14 integration tests across js_events, js_dom_tests, js_tests, and js_scheduling for edge cases (PR 7) - Add JS feature matrix and conformance report documentation (PR 8) - Update CLAUDE.md with JS262 harness commands and doc references - Mark Milestone 6 Phase 5 complete in plan doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.6 KiB
Milestone 6 Phased Implementation Plan
Purpose
Milestone 6 adds JavaScript execution and minimal DOM bindings. This is high-risk work that touches parser, VM semantics, DOM mutation, event ordering, and runtime scheduling. This plan splits implementation into small phases with strict testing gates so correctness stays ahead of feature growth.
Scope and Non-Goals
In scope for Milestone 6:
- Interpreter-first JavaScript execution
- Minimal DOM bindings used by common scripts
- Event dispatch for basic user interaction
- Microtask queue and minimal Promise behavior
- Runtime integration with deterministic scheduling for tests
Out of scope for Milestone 6:
- JIT or performance-tier execution
- Worker threads
- Fetch/XHR/WebRTC/service workers
- Full WebIDL coverage
- Broad conformance parity with modern browsers
Global Constraints
- No
unsafeoutsidecrates/platform/**orcrates/graphics/**. - No cross-layer dependency violations.
- Every bug fix adds a regression test.
- Deterministic ordering in test mode for tasks, microtasks, and timer-like work.
- Keep vertical slices mergeable: each phase should ship behind stable tests before starting the next.
Current Baseline
The workspace already has scaffolding:
crates/js_parser: parser crate existscrates/js_vm: VM facade existscrates/js: engine wrapper over parser + VMcrates/web_api: bridge layer todom+jscrates/browser_runtime: callsweb_api.tick()in runtime loop
Phase 1 starts from this baseline and replaces no-op behavior incrementally.
Phase Plan
Phase 1: Deterministic JS Runtime Skeleton
Goal:
- Execute basic scripts deterministically with observable results.
Implementation:
- Define explicit runtime state machine in
js_vm(created, primed, running, failed). - Add minimal value model and evaluation pipeline for literals, variables, arithmetic, and function calls needed by tests.
- Make
js::JsEngine::executereturn structured errors (parse/runtime categories). - Add deterministic VM hooks for test-controlled randomness/time when needed.
Testing gate:
- Unit tests in
crates/js_parserfor parse success/failure boundaries. - Unit tests in
crates/js_vmfor evaluation semantics and error classes. - Integration tests in
crates/jsfor parse + execute end-to-end. - At least one regression test fixture for each bug found during phase.
Exit criteria:
- Script execution results are stable across repeated runs.
- Parser vs runtime error classification is covered by tests.
Phase 2: Minimal DOM Read/Write Bindings
Goal:
- Allow scripts to inspect and mutate document content through a narrow API.
Implementation:
- Introduce a minimal binding surface in
web_api:documentgetElementByIdor equivalent single-node lookuptextContentread/writecreateElement+ append/remove basics
- Define explicit conversion/error behavior between JS values and DOM operations.
- Keep DOM binding implementation localized to
web_api; avoid pushing JS types intodom.
Testing gate:
- Unit tests in
crates/web_apifor binding behavior and error mapping. - Unit tests in
crates/domfor mutation invariants hit by bindings. - Integration tests proving script-driven DOM mutation updates observable document state.
- Regression test per fixed bug.
Exit criteria:
- Scripts can create, find, and mutate simple DOM structures.
- DOM invariants remain valid after JS-driven mutations.
Phase 3: Event Dispatch and Listener Model (Basic)
Goal:
- Support basic interaction scripting (
clickpath first).
Implementation:
- Add listener registration/removal for a small event subset.
- Implement deterministic capture/target/bubble behavior for supported event types, or explicitly constrain to target/bubble and document the limitation.
- Connect platform input path to DOM event dispatch through runtime/web_api boundary.
- Ensure re-entrancy policy is explicit and test-covered.
Testing gate:
- Unit tests for listener lifecycle and event propagation order.
- Integration tests from synthetic input to JS callback execution.
- Negative tests for edge cases (removed listeners, exceptions in handlers).
- Regression test per fixed bug.
Exit criteria:
- Click-like events reach registered JS listeners in deterministic order.
- Event handler exceptions are surfaced without corrupting runtime state.
Phase 4: Task and Microtask Scheduling
Goal:
- Establish a correct event loop checkpoint model before broader async APIs.
Implementation:
- Introduce runtime-managed task queue and microtask queue contracts.
- Define microtask checkpoint rules (for example: drain after task completion and at explicit runtime boundaries).
- Add minimal Promise support tied to the microtask queue.
- Keep scheduling logic in runtime/web_api boundaries; avoid leaking queue internals into unrelated crates.
Testing gate:
- Unit tests for queue ordering, starvation prevention, and nested microtask behavior.
- Integration tests covering task -> microtask -> render/update ordering.
- Determinism tests that rerun scenarios multiple times with identical outcomes.
- Regression test per fixed bug.
Exit criteria:
- Promise callbacks run in expected microtask order for supported semantics.
- Task/microtask ordering is deterministic in CI and local test runs.
Phase 5: Conformance Slice, Hardening, and Rollout
Goal:
- Convert the minimal implementation into a maintainable, test-protected baseline.
Implementation:
- Add a curated conformance subset (Test262/WPT-style cases that match implemented features).
- Add known-failure tracking for unsupported features with clear triage labels.
- Improve diagnostics: structured errors and trace points across parser/VM/web_api/runtime.
- Remove or isolate temporary scaffolding introduced in prior phases.
Testing gate:
- Curated JS conformance shard in CI for implemented syntax/semantics.
- Curated DOM/event tests in integration harness.
- Sanitizer and stability runs (
just ci; plusjust sanon Linux nightly toolchain). - Zero untriaged flakiness for newly added Milestone 6 tests.
Exit criteria:
- Milestone 6 feature set is documented, tested, and stable.
- New failures are either fixed or explicitly tracked as known limitations.
Status: Complete. Phase 5 delivered:
- JS262 conformance harness with 99 tests (78 pass, 21 known-fail)
- Source locations (line:col) in runtime error messages
- Consolidated debug-level tracing spans
- Integration test hardening (14 new edge-case tests)
- Feature matrix and conformance report documentation
- See
docs/js_feature_matrix.mdanddocs/js_conformance_report.md
Test Strategy by Layer (Milestone 6)
- Unit tests: parser, VM semantics, bindings, event propagation internals.
- Integration tests:
js+web_api+dom+browser_runtimebehavior. - Conformance shards: small curated Test262/WPT-like slices for implemented features only.
- Regression tests: mandatory for every bug fixed.
- Determinism tests: repeated-run checks for queue/event ordering.
Placement:
- Crate internals: inline
#[cfg(test)]modules. - Cross-crate behavior: root
tests/integration suites withCargo.tomltest entries as needed.
Merge Policy and Phase Sequencing
- Do not overlap phases in one large PR.
- Each phase should land in small PRs with green CI.
- If a phase reveals missing abstractions, add them with tests first, then continue feature work.
- If quality gate is red, stop feature expansion and fix test reliability/correctness first.
Deliverables Checklist
For each phase:
- Implementation completed for the phase goal only
- Test gates satisfied
- New regressions covered by permanent tests
- Known limitations updated where applicable
- CI green (
just ci; andjust sanwhen applicable)