v0.1.11
CDP sessions are now isolated and safe to run concurrently, DOM traversal and template handling are substantially more browser-compatible, sequential embedded Browser sessions no longer share fetch state, and the MCP and release paths received additional hardening. 81 commits since v0.1.10.
Highlights
• Concurrent CDP sessions no longer share V8 state. Each connection owns its runtime and browser context, preventing cross-isolate aborts and stopping cookies, headers, targets, and User-Agent overrides from leaking between clients (#435, #456).
• TreeWalker, NodeIterator, templates, and fragments now behave like real DOM APIs. Traversal follows document order in both directions, filters handle FILTER_SKIP and FILTER_REJECT correctly, <template>.content exposes parsed markup, and inserting a DocumentFragment moves its children rather than attaching the fragment itself (#447, #454, #464, #465, #466, #471, #472, #476).
• Network activity is observable and isolated. Scripted fetch()/XHR requests emit CDP Network events, passive request/response callbacks can be detached, and callbacks stay scoped to the page that registered them (#414, #415, #416).
• Long-lived processes are safer. Scripted requests now use the owning BrowserContext client instead of process-global fetch state, allowing sequential in-process Browser instances to run concurrent fetch/XHR workloads without sharing stale async network state (#502).
CDP and networking
• CDP WebSocket responses can use frames up to 64 MiB (#405).
• DOM.getDocument depth is bounded so deeply nested pages cannot crash a worker (#396).
• Client-controlled log previews are truncated on UTF-8 character boundaries (#397).
• Input.dispatchKeyEvent correctly escapes backslashes in key and code (#437).
• Execution-context ids are pruned when Runtime.executionContextsCleared is emitted (#413).
• Script-initiated requests emit Network.requestWillBeSent, response, loading, and body events (#415).
• Passive request/response callbacks can be removed and do not bleed across pages (#414, #416).
• Cookies without an explicit Path default to the request directory, and cookies are keyed by (name, path) so same-name cookies on different paths can coexist (#403, #438).
DOM and Web APIs
• structuredClone now preserves CryptoKey objects, ArrayBuffers and typed-array views, cyclic graphs, Error.cause, and own __proto__ properties (#390, #421, #425).
• HTMLFormElement.submit() bypasses the cancelable submit event as browsers do, while requestSubmit() follows the interactive submission path and validates its submitter (#395, #426).
• Document.adoptNode() and Element.toggleAttribute() are available (#392).
• NodeFilter exposes the complete standard constant set (#440).
• Element.scroll(), scrollTo(), and scrollBy() update scrollTop/scrollLeft; direct scroll assignments and window scrolling dispatch scroll events (#431, #458, #470).
• navigator.connection now has working EventTarget listener storage (#455).
• Dynamically inserted stylesheet links fire load and error events (#412).
• Iframe document and element listeners receive their registered events (#479).
• Parsed SVG elements retain their SVG namespace, so href and className expose the correct SVGAnimatedString behavior (#485).
• new Image() no longer throws when page instrumentation has made its src property non-configurable (#418).
• DOM comment serialization neutralizes every invalid comment terminator, not only --> (#402).
Runtime and performance
• Dynamically inserted external scripts receive a bounded settle window so direct and nested script chains can finish and dispatch load (#477).
• Template serialization reads template metadata by reference instead of cloning every element and its attributes (#480).
• Runtime test fixtures now follow the same initialization order as production pages (#473).
• Navigator fingerprint properties live on the Navigator prototype instead of being exposed as instance properties (#388).
MCP and security
• SSE keep-alive streams run independently and no longer block every later MCP request (#493).
• MCP request lines, headers, and bodies share a bounded read deadline, preventing stalled or byte-dribbling clients from monopolizing the sequential server (#505).
• quinn-proto was updated to 0.11.15 for the remote memory-exhaustion fix in GHSA-4w2j-m93h-cj5j (#487).
Release artifacts
Release downloads now make the transport choice explicit:
• Standard archives keep the lean default binary and retain the existing filenames.
• Archives ending in -stealth contain the required wreq/BoringSSL build for TLS impersonation.
• Both variants are built and smoke-tested independently; a failed stealth build can no longer silently publish a default binary in its place.
• Stealth build dependencies are documented, and macOS SDK flags are no longer injected into Linux builds (#506).
Contributors
Thanks to @flowowcoding, @mnaza, @IrishWhiskey, @sicko7947, @BrandNewJimZhang, @Sycatle, @lisa0314, @j00jun, and @ulises2k for contributions to this release.
Full Changelog: v0.1.10...v0.1.11