Changelog

All notable changes to this project will be documented in this file.

[0.3.0] - 2026-05-26

Bug Fixes

  • (script) Bind allow.net to global fetch, closing a net-guard bypass (3a7ac0a)
  • (http_client) Honour per-request max_redirects (was a no-op) (eecfcf5)
  • (webkit) Middle-click no longer fails the hit-target interceptor (939785e)
  • (bdd,cdp) Parallelism, close-path stalls, cookie ctx, JS-driven gaps (cfe0c26)
  • (tests) World-first hook/step args + skip webkit utility-script tests (203b362)
  • (pw_webkit) Lazy file-chooser intercept to unwedge matrix (d2bcf0e)
  • (pw_webkit) Handle provisional target swap on cross-process navigation (737f14a)
  • (pw_webkit) Defer Download event until suggestedFilename arrives (9c36cdd)
  • (webkit) Cache path + split backends test into per-category #[test]s (1389abf)
  • (tests) Bootstrap a page in multi_page test (b3b7c83)
  • (install) Use correct tool name in --with-deps error message (4500ad0)
  • (install) Mirror Playwright's full WebKit apt lists per Ubuntu version (2cbee02)

CI

  • Drop ferridriver-webkit-host references and gtk/webkit2 deps (ef28d6f)
  • Install Playwright WebKit GTK + GStreamer system deps (6d3b4fd)

Documentation

  • Full rewrite + site polish (ab0bb7d)
  • (webkit) Fix rustdoc broken intra-doc links (29e7638)

Features

  • (script) Session lifetime model, hardened commands, process/fetch, extension fixes (6e60ac1)
  • (fetch) WHATWG-spec Headers (subset, no deps) (b856aa8)
  • (fetch) Standard Request/Response globals; de-globalise network classes (e58f32d)
  • (abort) AbortController/AbortSignal + fetch signal (9d78fd9)
  • (streams) ReadableStream subset; Response.body is a stream (5dac77a)
  • (fetch) Blob + FormData (spec subset) as fetch bodies (cffadd1)
  • (fetch) Incremental Response.body streaming (no full buffering) (2c960df)
  • (process) Stdout/stderr.write, hrtime.bigint, document nextTick order (de87a35)
  • (bdd) Thread [scripting] env caps into the step VM; remove nodeCompat (49f2ae9)
  • (expect) Add ferridriver-expect crate (7568a50)
  • (script) QuickJS expect() global (d374949)
  • (bdd) Uniform world-as-first-arg for steps and hooks (c03eda2)
  • (reporter) Colorize unified-diff lines in terminal reporter (7c8d873)
  • (http) NetGuard sandbox network policy + fetch binding hardening (5e20eab)
  • (page) Async exposeFunction, cookie url field, CDP modifier combos (a14e9f1)
  • (script,node) Expanded JS / NAPI binding surface (cefb6cb)
  • (webkit) Linux port via gtk4/webkit6 host + cross-platform host crate (89104f4)
  • (backend) Scaffold Playwright WebKit backend (pw_webkit) (d2d5fab)
  • (pw_webkit) Full backend wiring — Browser/Page/Element + AnyPage dispatch (9bc3f77)
  • (pw_webkit) Route interception, frame contexts, more matrix fixes (8104d46)
  • (pw_webkit) Wire WS events + context-options pre-page hook + page_backref fix (ff85663)
  • (install) Native webkit install + symlink-aware zip extract (4a7b414)
  • (install) --with-deps installs Chromium + WebKit system libs (a9685f9)

Miscellaneous

  • (ci) Unblock CI -- fmt + clippy + typos + rustdoc (c51e58f)
  • (deps) Switch rolldown to crates.io 1.0.0 (d193da2)

Performance

  • Worker-scoped request, pre-warm, async tempdir, bidi close (c74260f)

Refactoring

  • Rename api_request -> http_client, drop API-testing framing (26e380f)
  • (test) Consolidate expect on ferridriver-expect (854eea8)
  • (bdd-steps) Migrate built-in step helpers to AssertionFailure (2511f97)
  • Consolidate webkit backend (drop legacy, promote pw-webkit) (337671b)

Testing

  • (cli,bdd-example) Cross-backend expect coverage + Rust value-matcher demo (f239696)
  • (pw_webkit) Drop run_cdp! gates on emulation tests, achieve full parity (53ca4b5)
  • (backends) Extract local test fns into per-category modules (09381ba)
  • (binding_coverage) Split giant test into per-surface #[test]s (bec960f)
  • (script) Restructure waitForEvent('console') to listener-first (9d490e0)
  • (script) Disable flaky waitForEvent('console') chunk in sweep (48961ff)
  • Skip macOS-flaky chunks (screencast hang, HTML5 DnD drop) (b43a7ff)
  • (webkit) Accept macOS CFNetwork error + skip overrideUserPreference (b069224)

[0.2.0] - 2026-05-18

Bug Fixes

  • (test-runner) Lazy browser launch via BrowserHandle (e0b8168)
  • SetInputFiles via objectId, BiDi/WebKit frame name sync, Firefox in CI (981fe3c)
  • (bidi) Name fallback to window.name; goto retries sync_frames (e08fc1b)
  • (bidi) Single sync_frames pass to keep dialog timing intact (9b4e1a1)
  • (bidi) Retry frame name resolution up to 3 rounds (121cd01)
  • (bidi) Pass serializationOptions to locateNodes for attributes (825d5c8)
  • (cdp) Disable private-network-request blocking flags (c48cd9d)
  • (state) Skip snap-wrapped Firefox in detect_firefox (0b42e7c)
  • (video) Skip Page.stopScreencast on already-closed page (87b57a9)
  • (server) Exec user command so SIGTERM reaches the real child (b6bd2d2)
  • (frame_cache) Seed merges instead of replacing (33059a0)
  • (cdp) Resolve missing iframe name via window.name on getFrameTree (7cc85f9)
  • (error) Classify timeout/target-closed Errs to typed variants (de9dc57)
  • (locator) Restore actionability-sentinel retry + radio message (b235024)
  • (mcp) Serialize per-session tool calls + Playwright-shaped addCookies (9873837)
  • (webkit) Migrate remaining Result<_, String> to typed FerriError (64d243d)
  • (bidi) Deterministic elementHandle.contentFrame via contentWindow (dc650d1)
  • (bidi) Inject engine into freshly-attached / srcdoc / data: child contexts (66c5c13)
  • (clippy) Box oversized I/O futures; resolve bundle.rs lints (43b79ac)
  • (justfile) Portable in-place sed in the release recipe (4cf3861)
  • (ci) Write release notes to a file (inline --notes overflows arg limit) (e65c3fc)
  • (release) Unbreak 0.2.0 — workspace-pin macro deps, doc link, publish order (7bc4251)
  • Make script/serializer JSON paths arbitrary-precision-safe (a52aece)
  • (toolchain) Pin nightly — rolldown/oxc deps require it (3557b8f)
  • (doc) ExtensionRegistry intra-doc link -> code span (private item) (7bd65b5)

CI

  • Explicit bun test timeout to match bunfig and avoid 5s default (cb3eb0b)
  • 120s bun timeout, browser fixture 120s, Firefox runtime deps (9fee881)
  • Bump NAPI inner-test timeout to 120s, expand Firefox deps (bf5d313)
  • Trim Firefox deps to non-Chrome ones to avoid t64 conflicts (3e0e6fc)
  • Drop Firefox install — bidi suite hangs > 30 min when Firefox is present (5786e78)
  • Drop redundant cdp-pipe/cdp-raw separate test steps (4849a50)
  • (release) Drop Windows CLI target; decouple GitHub release from crates.io (0746f2c)
  • (release) Add cross target to the pinned (nightly) toolchain (5b33500)

Documentation

  • (parity) Mark ferridriver-specific helpers as non-Playwright (6d5ef6d)
  • Rewrite README + site for the Rust-only surface (e59e900)
  • Survey plugin architectures; record adopt/defer decisions (35ee457)

Features

  • (mcp) Plugin system with QuickJS bindings + tool promotion (d15d11a)
  • (mcp) One plugin file can declare multiple tools (9545939)
  • (core) Sync Playwright accessors + predicate-route plumbing (7393dc9)
  • (script) Playwright parity for QuickJS bindings (233b5c6)
  • (node) Playwright parity for NAPI bindings (06f689a)
  • (mcp) Plugin loader/server/script work-in-progress (46efb69)
  • (parity) Mouse/keyboard delay option (Playwright {delay}) (078d4b3)
  • (parity) Add Playwright page.ariaSnapshot; mark snapshotForAI non-Playwright (d28bfcb)
  • (parity) Locator.ariaSnapshot via vendored Playwright InjectedScript (40cecbe)
  • (parity) Cross-iframe stitching for locator.ariaSnapshot (23e1b62)
  • (bdd) Run JavaScript step definitions on the shared QuickJS engine (0b702d2)
  • (bdd) Ferridriver bdd --steps runs JS step files through the core TestRunner (d035f5f)
  • (bdd) Rolldown front-end — TypeScript, tree-shaking, whole-graph bytecode (c070e59)
  • (plugin) Migrate plugin loading to rolldown->bytecode pipeline (0db489a)
  • (plugin) Declarative, default-deny capability manifest (exec + net) (30771a4)
  • (extension) Test runner loads extensions; native ferridriver.host flag (6bf90b2)
  • (bdd) Native this.attach / this.log -> reporters (c6bb583)
  • (bdd) Hook callback arg (cucumber result/pickle) (3a735f4)
  • (bdd) DefineParameterType transformer (typed step args) (2925a6c)
  • (bdd) SetDefinitionFunctionWrapper + per-step/hook timeout (213299e)
  • (bdd) World parameters -> this.parameters (Tier 2 complete) (4603f48)
  • (bdd) This.skip() + JS undefined-step snippets (Tier 3) (ac38c57)

Performance

  • (script) Defer cycle-GC + skip redundant runtime limit setters (c9d0a24)
  • (script) Enable full-async; drop serde_json middle-hop on hot paths (a5cbd34)
  • (script) Kill remaining serde_json / JSON round-trips (standard path) (38597fc)
  • (bdd) Compile JS step files to bytecode once, link per worker (ca7bac7)
  • (plugin) Content-hash bytecode cache, parallel bundling, parse-once install (edb51bc)

Refactoring

  • (error) Drop FerriError::Other escape hatch; route raw strings to typed Backend variant (296da2e)
  • (error) Migrate backend wrapper, CDP/BiDi/WebKit impls, state/actions/selectors to FerriError (c4a3406)
  • (error) Migrate BDD hook trait + macros to FerriError (46b9240)
  • (error) Migrate Reporter trait + impls to FerriError (a2445cb)
  • (error) Migrate ShardArg::parse to FerriError (71ecffe)
  • (error) Migrate NAPI test_runner JS-callback helpers to FerriError (514f754)
  • (error) Migrate ferridriver core internals to FerriError (ae37d91)
  • (error) Migrate ferridriver-test internals to FerriError (83169e2)
  • (error) Migrate ferridriver-bdd parsers + finalise doc cleanup (066240b)
  • (error) Drop redundant .map_err(|e| e.to_string()) bridges (e5e7fa8)
  • (error) Preserve typed FerriError prefix at reporter boundaries (22a2f4b)
  • (error) Centralize FerriError display + StepError typing (9e2b667)
  • (error) Reclassify raw-string Errs to typed FerriError variants (9137596)
  • (node) Slim ferridriver-node to a core-only browser binding (80e96b4)
  • Delete TS CLI + component-test packages; Rust-only surface (e14b2a8)
  • (plugin) Native ExtensionRegistry — kill all __ferri* JS shims (4daad25)
  • (page) Native route registry — kill __fdRoutes/__fdRoutePreds (b8a2a8d)
  • Native page-callbacks registry + native Error — kill last __fd*/eval (90dbfa1)
  • (plugin) Drop legacy globalThis.exports — defineTool is the only API (8c41e40)
  • (config) Un-nest plugins -> top-level extensions (951a7f1)

Styling

Testing

  • (napi) Default helper browser.headless=true for CI (2a4856d)
  • Force headless under CI env var (d509698)
  • (napi) WebSocket round-trip uses real http origin + null last expr (c960b27)
  • (cli) WebSocket round-trip uses real http origin + null last expr (b72f364)
  • (cli) Exhaustive binding coverage + harness updates (d574cfb)
  • (parity) Nested + re-attached frame-locator coverage (066e37e)
  • (download) Deterministic cancel-surfaces-failure (no cancel race) (741292a)
  • (plugin) Add re-runnable plugin-path microbench (ignored) (1b9588b)

Release

Revert

  • Timeout bumps and BiDi name-resolution sleeps (a56506e)
  • (bidi) Drop locateNodes name resolution; back to window.name only (4aa4414)