{"slug": "bun-v1-3-4", "title": "Bun v1.3.4", "summary": "Bun v1.3.4 introduces support for the URLPattern Web API, enabling declarative pattern matching for URLs, and adds fake timers to the bun:test module for controlling time in tests. The update also includes custom proxy headers in fetch(), fixes a critical bug in http.Agent connection pooling with keepAlive, and provides various installation and upgrade methods.", "body_md": "To install Bun\ncurl -fsSL https://bun.sh/install | bash\nnpm install -g bun\npowershell -c \"irm bun.sh/install.ps1|iex\"\nscoop install bun\nbrew tap oven-sh/bun\nbrew install bun\ndocker pull oven/bun\ndocker run --rm --init --ulimit memlock=-1:-1 oven/bun\nTo upgrade Bun\nbun upgrade\nURLPattern\nAPI\nBun now supports the URLPattern\nWeb API, providing declarative pattern matching for URLs—similar to how regular expressions work for strings. This is especially useful for routing in web servers and frameworks.\n// Match URLs with a user ID parameter\nconst pattern = new URLPattern({ pathname: \"/users/:id\" });\npattern.test(\"https://example.com/users/123\"); // true\npattern.test(\"https://example.com/posts/456\"); // false\nconst result = pattern.exec(\"https://example.com/users/123\");\nconsole.log(result.pathname.groups.id); // \"123\"\n// Wildcard matching\nconst filesPattern = new URLPattern({ pathname: \"/files/*\" });\nconst match = filesPattern.exec(\"https://example.com/files/image.png\");\nconsole.log(match.pathname.groups[0]); // \"image.png\"\nThe implementation includes:\n- Constructor: Create patterns from strings or\nURLPatternInit\ndictionaries test()\n: Check if a URL matches the pattern (returns boolean)exec()\n: Extract matched groups from a URL (returnsURLPatternResult\nor null)- Pattern properties:\nprotocol\n,username\n,password\n,hostname\n,port\n,pathname\n,search\n,hash\nhasRegExpGroups\n: Detect if the pattern uses custom regular expressions\n408 Web Platform Tests pass for this implementation. Thanks to the WebKit team for implementing this!\nFake Timers for bun:test\nBun's test runner now supports fake timers, allowing you to control time in your tests without waiting for real time to pass. This is essential for testing code that relies on setTimeout\n, setInterval\n, and other timer-based APIs.\nimport { test, expect, jest } from \"bun:test\";\ntest(\"fake timers\", () => {\njest.useFakeTimers();\nlet called = false;\nsetTimeout(() => {\ncalled = true;\n}, 1000);\nexpect(called).toBe(false);\n// Advance time by 1 second\njest.advanceTimersByTime(1000);\nexpect(called).toBe(true);\njest.useRealTimers();\n});\nThe following methods are available on jest\n:\nuseFakeTimers(options?)\n— Enable fake timers, optionally setting the current time with{ now: number | Date }\nuseRealTimers()\n— Restore real timersadvanceTimersByTime(ms)\n— Advance all timers by the specified millisecondsadvanceTimersToNextTimer()\n— Advance to the next scheduled timerrunAllTimers()\n— Run all pending timersrunOnlyPendingTimers()\n— Run only currently pending timers (not ones scheduled by those timers)getTimerCount()\n— Get the number of pending timersclearAllTimers()\n— Clear all pending timersisFakeTimers()\n— Check if fake timers are active\nThanks to @pfgithub for implementing this!\nCustom Proxy Headers in fetch()\nThe fetch()\nproxy option now accepts an object format with support for custom headers sent to the proxy server. This is useful for proxy authentication tokens, custom routing headers, or any other proxy-specific configuration.\n// String format still works\nfetch(url, { proxy: \"http://proxy.example.com:8080\" });\n// New object format with custom headers\nfetch(url, {\nproxy: {\nurl: \"http://proxy.example.com:8080\",\nheaders: {\n\"Proxy-Authorization\": \"Bearer token\",\n\"X-Custom-Proxy-Header\": \"value\",\n},\n},\n});\nHeaders are sent in CONNECT\nrequests for HTTPS targets and in direct proxy requests for HTTP targets. If you provide a Proxy-Authorization\nheader, it takes precedence over credentials embedded in the proxy URL.\nhttp.Agent\nConnection Pool Now Properly Reuses Connections\nFixed a critical bug where http.Agent\nwith keepAlive: true\nwas not reusing connections in certain cases.\nimport http from \"node:http\";\nconst agent = new http.Agent({ keepAlive: true });\nhttp.request(\n{\nhostname: \"example.com\",\nport: 80,\npath: \"/\",\nagent: agent,\n},\n(res) => {\n// Connection is now properly reused on subsequent requests\n},\n);\nThree independent bugs were fixed:\n- Incorrect property name (\nkeepalive\nvskeepAlive\n) caused the user's setting to be ignored Connection: keep-alive\nrequest headers weren't being handled- Response header parsing used incorrect comparison logic and was case-sensitive (violating RFC 7230)\nStandalone Executables No Longer Load Config Files at Runtime\nStandalone executables built with bun build --compile\nnow skip loading tsconfig.json\nand package.json\nfrom the filesystem at runtime by default. This improves startup performance and prevents unexpected behavior when config files in the deployment environment differ from those used at compile time.\nIf your executable needs to read these config files at runtime, you can opt back in with the new CLI flags:\n# Enable runtime loading of tsconfig.json\nbun build --compile --compile-autoload-tsconfig ./app.ts\n# Enable runtime loading of package.json\nbun build --compile --compile-autoload-package-json ./app.ts\n# Enable both\nbun build --compile --compile-autoload-tsconfig --compile-autoload-package-json ./app.ts\nOr via the JavaScript API:\nawait Bun.build({\nentrypoints: [\"./app.ts\"],\ncompile: {\nautoloadTsconfig: true,\nautoloadPackageJson: true,\nautoloadDotenv: true,\nautoloadBunfig: true,\n},\n});\nconsole.log\nnow supports %j\nformat specifier\nThe %j\nformat specifier for console.log\nand related console methods now outputs the JSON stringified representation of a value, matching Node.js behavior.\nconsole.log(\"%j\", { foo: \"bar\" });\n// {\"foo\":\"bar\"}\nconsole.log(\"%j %s\", { status: \"ok\" }, \"done\");\n// {\"status\":\"ok\"} done\nconsole.log(\"%j\", [1, 2, 3]);\n// [1,2,3]\nPreviously, %j\nwas not recognized and was left as literal text in the output.\nSQLite 3.51.1\nbun:sqlite\nhas been updated to SQLite v3.51.1, which includes fixes for the EXISTS-to-JOIN optimization and other query planner improvements.\nBugfixes\nbun:test fixes\n- Fixed: Fuzzer-detected assertion failure in\nspyOn\nwhen used with indexed property keys (e.g.,spyOn(arr, 0)\norspyOn(arr, \"0\")\n) - Fixed: Fuzzer-detected assertion failure in\nexpect.extend()\nwhen passed objects containing non-function callables (like class constructors), now properly throws aTypeError\ninstead - Fixed: Fuzzer-detected assertion failure in\njest.mock()\nwhen called with invalid arguments (e.g., non-string first argument)\nBundler and Dev Server fixes\n- Fixed: Error message in Dev Server saying \"null\" instead of a message string in certain rare cases\n- Fixed: HMR error overlay now displays error information when\nevent.error\nis null by falling back toevent.message\n- Fixed: Out of memory errors being incorrectly thrown instead of properly handled when rejecting Promise values in the bundler\n- Fixed: Standalone executables (\nbun build --compile\n) failing to load bytecode cache due to improper 8-byte alignment in embedded Mach-O and PE sections\nbun install fixes\n- Fixed: Security scanner not collecting dependencies from workspace packages, causing it to scan only a subset of packages instead of the full dependency tree\n- Fixed: off-by-one error in the lockfile resolution bounds check during\nbun install\nwith update requests - Fixed:\nbun publish --help\nshowing incorrect--dry-run\ndescription (\"Don't install anything\" → \"Perform a dry run without making changes\")\nWindows fixes\n- Fixed:\nfs.access()\nandfs.accessSync()\nthrowingEUNKNOWN\nerrors when checking Windows named pipes (paths like\\\\.\\pipe\\my-pipe\n) - Fixed: Git dependencies on Windows with long paths now work correctly\n- Fixed: Windows console codepage not being properly saved and restored, which could cause garbled text on non-English Windows systems when using\nbunx\nNode.js compatibility improvements\n- Fixed: Fuzzer-detected issues in\nBuffer.prototype.hexSlice()\nandBuffer.prototype.toString('base64')\nnow throw proper errors instead of crashing when the output would exceed JavaScript's maximum string length - Fixed: Fuzzer-detected issues in\nBuffer.prototype.*Write\nmethods (utf8Write, base64Write, etc.) now properly handle non-numeric offset and length arguments, matching Node.js behavior where NaN offsets are treated as 0 and lengths are clamped to available buffer space instead of throwing - Fixed:\nassert.deepStrictEqual()\nincorrectly treatingNumber\nandBoolean\nwrapper objects with different values as equal (e.g.,new Number(1)\nandnew Number(2)\nwould not throw) - Fixed:\nTLSSocket.isSessionReused()\nincorrectly returningtrue\nwhensetSession()\nwas called, even if the session wasn't actually reused by the SSL layer. Now correctly uses BoringSSL'sSSL_session_reused()\nAPI for accurate session reuse detection, matching Node.js behavior - Fixed:\nnapi_typeof\nincorrectly returningnapi_string\nfor boxed String objects (new String(\"hello\")\n) instead ofnapi_object\n, now correctly matches JavaScript'stypeof\nbehavior for all boxed primitives (String, Number, Boolean) - Fixed:\nHttp2Server.setTimeout()\nandHttp2SecureServer.setTimeout()\nreturningundefined\ninstead of the server instance, breaking method chaining likeserver.setTimeout(1000).listen()\n- Fixed: crash when populating error stack traces during garbage collection (e.g., when using\nnode:readline\nwith certain packages or handling unhandled promise rejections)\nBun APIs fixes\n- Fixed:\nBun.secrets\ncrashing when called insideAsyncLocalStorage.run()\nor other async context managers - Fixed: Fuzzer-detected assertion failure in\nBun.mmap\nwhenoffset\norsize\noptions were non-numeric values likenull\nor functions. Now properly validates and rejects negative values with clear error messages - Fixed:\nBun.plugin\nnow properly returns an error instead of potentially crashing when an invalidtarget\noption is provided - Fixed:\nnew Bun.FFI.CString(ptr)\nthrowing \"function is not a constructor\" error, a regression introduced in v1.2.3 - Fixed: Fuzzer-detected assertion failure caused by calling class constructors (like\nBun.RedisClient\n) withoutnew\n. These constructors now properly throwTypeError: Class constructor X cannot be invoked without 'new'\n- Fixed: Fuzzer-detected bug when creating empty or used ReadableStream that could cause errors to be silently ignored\n- Fixed:\nGlob.scan()\nescapingcwd\nboundary when using patterns like.*/*\nor.*/**/*.ts\n, which incorrectly traversed into parent directories instead of matching hidden files/directories - Fixed: Fuzzer-detected issue in\nBun.indexOfLine\nwhen called with a non-number offset argument - Fixed: Fuzzer-detected issue in\nFormData.from()\nwhen called with very large ArrayBuffer input (>2GB) now throws a proper error\nbun:ffi fixes\n- Fixed:\nlinkSymbols\ncrashing whenptr\nfield was not a valid number or BigInt - Fixed: Incorrectly converting JavaScript numbers to FFI pointers, where identical JS number values could produce different pointer values (e.g.,\n123\nbecoming18446744073709551615\n), causing crashes when passing numeric arguments to native functions - Fixed: Crash when using libraries like\n@datadog/pprof\nthat triggered an overflow in internal bindings\nSecurity\n- Improved: Stricter validation of chunk terminators per RFC 9112\nTypeScript definitions\n- Fixed:\nBun.serve()\nnow includes theprotocol\nproperty, which was already available at runtime but missing from type definitions\nOther fixes\n- Fixed: Off-by-one error in string length boundary check that would incorrectly reject strings with length exactly equal to the maximum allowed length", "url": "https://wpnews.pro/news/bun-v1-3-4", "canonical_source": "https://bun.com/blog/bun-v1.3.4", "published_at": "2025-12-06 10:11:00+00:00", "updated_at": "2026-05-22 20:42:28.544674+00:00", "lang": "en", "topics": ["developer-tools", "open-source"], "entities": ["Bun"], "alternates": {"html": "https://wpnews.pro/news/bun-v1-3-4", "markdown": "https://wpnews.pro/news/bun-v1-3-4.md", "text": "https://wpnews.pro/news/bun-v1-3-4.txt", "jsonld": "https://wpnews.pro/news/bun-v1-3-4.jsonld"}}