Bun v1.3.12 Ships Headless Browser Automation and Native Explicit Resource Management

Bun v1.3.12 Ships Headless Browser Automation and Native Explicit Resource Management

lschvn

Bun v1.3.12 landed April 10 with one of the most ambitious feature sets in recent releases. Two standouts reshape what a JavaScript runtime can do out of the box: native headless browser automation and native support for the TC39 Explicit Resource Management proposal. Here's what changed.

Bun.WebView β€” Headless Browser Automation Built In

The headline feature is Bun.WebView, a headless browser automation API shipped directly in the runtime. No Puppeteer, no Playwright dependency β€” just a first-party API with two backends:

  • WebKit (default on macOS) β€” zero external dependencies, uses the system WKWebView
  • Chrome (cross-platform) β€” drives Chromium via the DevTools Protocol, auto-detects installed browsers or accepts a custom path

Selector-based actions auto-wait for actionability (Playwright-style), meaning an element must be attached, visible, stable, and unobscured before a click fires. All input is dispatched as OS-level events with isTrusted: true.

await using view = new Bun.WebView({ width: 800, height: 600 });

await view.navigate("https://example.com");
await view.click("a[href='/docs']");   // waits for actionability, native click
await view.scroll(0, 400);             // native wheel event, isTrusted: true

const title = await view.evaluate("document.title");
const png = await view.screenshot({ format: "jpeg", quality: 90 });
await Bun.write("page.jpg", png);

One browser subprocess is shared per Bun process; additional Bun.WebView() calls open tabs in the same instance. Raw Chrome DevTools Protocol calls are available via view.cdp(method, params) for advanced use cases.

Native using and await using in JavaScriptCore

The TC39 Explicit Resource Management proposal β€” already available in TypeScript via downleveling β€” now works natively in Bun's JavaScriptCore engine. Over 1,650 upstream WebKit commits landed in this release, bringing the using and await using declarations as a first-class language feature.

function readFile(path) {
  using file = openFile(path);   // file[Symbol.dispose]() called at end of block
  return file.read();
}

async function fetchData(url) {
  await using connection = await connect(url);  // [Symbol.asyncDispose]() awaited
  return connection.getData();
}

No transpilation step required. This aligns Bun with the native module graph and makes resource cleanup ergonomic without a utility wrapper.

URLPattern β€” Up to 2.3x Faster

URLPattern.test() and URLPattern.exec() received a significant performance overhaul. The internal regex matching now calls the compiled regex engine directly instead of allocating temporary JavaScript objects per call, eliminating up to 24 GC allocations per invocation.

BenchmarkBeforeAfterSpeedup
test() match, named groups1.05 Β΅s487 ns2.16x
test() no-match579 ns337 ns1.72x
test() match, simple971 ns426 ns2.28x
exec() match, named groups1.97 Β΅s1.38 Β΅s1.43x

As a side effect, URLPattern internals no longer pollute RegExp.lastMatch or RegExp.$N β€” previously a subtle source of bugs in mixed codebases.

In-Process Bun.cron() Scheduler

Bun.cron now has an in-process callback overload that runs a function on a cron schedule, complementing the existing OS-level variant that registers crontab/launchd/Task Scheduler entries. The in-process version is lighter, works identically across platforms, and shares state with the rest of the application directly.

Key guarantees: no overlap (the next fire is scheduled only after the handler settles), UTC scheduling, --hot safe (jobs clear before module graph re-evaluation), and disposable via using.

Other Improvements

  • UDP socket fixes: ICMP errors (port unreachable, host unreachable) are now surfaced through the error handler instead of silently closing the socket. Truncated datagrams are detectable via a new flags.truncated argument.
  • Unix domain socket lifecycle: now matches Node.js β€” binding to an existing socket correctly returns EADDRINUSE, and stop() automatically cleans up the socket file.
  • Standalone executables on Linux: bun build --compile now embeds the module graph via an ELF .bun section instead of reading from /proc/self/exe, fixing binaries with execute-only permissions.
  • SIMD optimizations: Bun.stripANSI, Bun.stringWidth, and shared ANSI helpers received SIMD acceleration (4Γ—-unrolled prologue, bulk CSI/OSC skips), with up to ~4Γ— improvement on plain ASCII input.
  • JIT improvements: faster tier-up for stable functions, Array.isArray as a JIT intrinsic, optimized String#includes, and improved BigInt arithmetic.

Upgrade with bun upgrade or install from bun.sh.

{tldr}

  • Bun.WebView brings headless browser automation with WebKit and Chrome backends, no external dependencies β€” native clicks, scrolls, screenshots, and CDP access in a single API
  • TC39's using/await using (Explicit Resource Management) is now natively supported in JavaScriptCore, eliminating the need for TypeScript downleveling for resource cleanup
  • URLPattern operations are up to 2.3Γ— faster thanks to direct regex engine calls and elimination of 24 GC allocations per call {/tldr}

Related articles

More coverage with overlapping topics and tags.

Bun Ships v1.3.11 with Native OS-Level Cron and Joins Anthropic's AI Coding Stack
bun

Bun Ships v1.3.11 with Native OS-Level Cron and Joins Anthropic's AI Coding Stack

Bun v1.3.11 drops a 4MB smaller binary, ships Bun.cron for OS-level scheduled jobs, and marks a pivotal moment as the runtime joins Anthropic to power Claude Code and future AI coding tools.
Deno 2.7 Stabilizes the Temporal API, Adds Windows ARM Support and npm Overrides
javascript

Deno 2.7 Stabilizes the Temporal API, Adds Windows ARM Support and npm Overrides

Deno 2.7 is a substantial mid-cycle release: the Temporal API is now production-ready, native Windows on ARM builds land, npm overrides work like in Node, and dozens of Node.js compatibility improvements land across worker_threads, child_process, zlib, and sqlite.
Bun vs Node vs Deno in 2026: The Runtime Showdown Nobody Asked For (But Everyone's Having)
javascript

Bun vs Node vs Deno in 2026: The Runtime Showdown Nobody Asked For (But Everyone's Having)

Three JavaScript runtimes. Three different philosophies. Independent benchmarks across HTTP throughput, cold starts, and async performance tell a clearer story than marketing ever could. Here's the brutally honest breakdown for developers choosing their next server-side JS platform.

Comments

Log in Log in to join the conversation.

No comments yet. Be the first to share your thoughts.