Compare commits

..

351 Commits

Author SHA1 Message Date
Meghan Denny
7b566e2cfc Revert "yay"
This reverts commit 6ae4158762.
2025-03-21 13:52:15 -07:00
chloe caruso
6ae4158762 yay 2025-03-21 13:40:51 -07:00
190n
8dc95b041a Fix bun --inspect-brk hanging (#18362) 2025-03-21 13:35:39 -07:00
Meghan Denny
211fd4fa06 deps: bump WebKit (#18349) 2025-03-21 04:40:45 -07:00
Dylan Conway
10665821c4 node:crypto: move Cipheriv and Decipheriv to native code (#18342) 2025-03-21 02:52:52 -07:00
Dylan Conway
a3585ff961 node:crypto: implement hkdf and hkdfSync (#18312) 2025-03-21 01:03:01 -07:00
Meghan Denny
2aeff10a85 [publish images] 2025-03-20 21:46:15 -07:00
Meghan Denny
f2c8e63ae1 update to llvm 19 and c++ 23 (#18317)
Co-authored-by: nektro <5464072+nektro@users.noreply.github.com>
2025-03-20 21:44:19 -07:00
pfg
40bfda0f87 Remove debug assertion failure for missing error code in switch case (#18345) 2025-03-20 21:29:12 -07:00
Jarred Sumner
9888570456 Introduce Bun.Cookie & Bun.CookieMap & request.cookies (in BunRequest) (#18073)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: pfg <pfg@pfg.pw>
2025-03-20 21:29:00 -07:00
Vincent (Wen Yu) Ge
a1690cd708 Trivial formatting fix in S3 docs (#18346) 2025-03-20 20:15:04 -07:00
Meghan Denny
e602e2b887 Revert "disallow test() within test()" (#18338) 2025-03-20 20:12:20 -07:00
Don Isaac
eae2d61f12 fix(node): add all already-passing tests (#18299) 2025-03-20 20:04:08 -07:00
Jarred Sumner
8e246e1e67 Add precompiled header (#18321) 2025-03-20 19:27:46 -07:00
Kai Tamkun
f30ca39242 More node:http compatibility (#18339)
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
2025-03-20 19:16:35 -07:00
Zack Radisic
9f68db4818 Implement vm.compileFunction and fix some node:vm tests (#18285) 2025-03-20 19:08:07 -07:00
Meghan Denny
f1cd5abfaa ci: compress libbun-profile.a before uploading (#18322) 2025-03-20 14:13:45 -07:00
Don Isaac
a8a7da3466 fix(spawn): memory leak in "pipe"d stdout/stderr (#18316)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-20 12:15:32 -07:00
Jarred Sumner
da9c980d26 Fix shell crash in load test (#18320) 2025-03-20 11:36:43 -07:00
nmarks
27cf0d5eaf Remove references to developers former name (#18319)
Co-authored-by: chloe caruso <git@paperclover.net>
2025-03-20 00:53:46 -07:00
chloe caruso
b5cbf16cb8 module pr 2 (#18266) 2025-03-20 00:45:44 -07:00
Meghan Denny
2024fa09d7 js: fix many typescript errors (#18272)
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-03-19 22:39:24 -07:00
Jarred Sumner
46b2a58c25 Small improvements to internal types 2025-03-19 19:26:13 -07:00
Don Isaac
d871b2ebdc fix(node): fix several whatwg tests (#18296) 2025-03-19 18:27:30 -07:00
Jarred Sumner
dc51dab7bc Sort some arrays 2025-03-19 15:45:38 -07:00
Jarred Sumner
e39305dd91 Remove deprecated shim wrapper for zig <> c++ fns (#18269)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-03-19 15:40:08 -07:00
Ashcon Partovi
6e1f1c4da7 Initial support for node:test (#18140) 2025-03-19 11:49:00 -07:00
Alistair Smith
21a42a0dee types: update Uint8Array methods (#18305) 2025-03-19 10:59:33 -07:00
Don Isaac
982083b3e9 fix(node/http): misc fixes (#18294) 2025-03-18 21:22:39 -07:00
Jarred Sumner
40e222c43b Reduce binary size by 400 KB (#18280)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-03-18 21:02:01 -07:00
Kai Tamkun
c8634668e7 Fix connection event being emitted multiple times per socket in node:http (#18295) 2025-03-18 21:01:07 -07:00
Don Isaac
fa9bb75ad3 fix(uws): make Socket bindings safer (#18286)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
Co-authored-by: chloe caruso <git@paperclover.net>
2025-03-18 19:38:15 -07:00
Don Isaac
c47e402025 fix: crash in Bun.inspect.table (#18256)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-03-18 18:56:56 -07:00
Meghan Denny
a3f48c1d47 ci: include version diffs in dependency update pr descriptions (#18283) 2025-03-18 17:03:48 -07:00
Ben Grant
de048cb474 [publish images] 2025-03-18 11:52:58 -07:00
190n
0c5ee31707 Correctly handle unknown type in FileSystem.DirEntry.addEntry (#18172)
Co-authored-by: 190n <7763597+190n@users.noreply.github.com>
2025-03-18 11:50:15 -07:00
Dylan Conway
c820b0c5e1 node:crypto: implement generatePrime(Sync) and checkPrime(Sync) (#18268) 2025-03-18 11:48:24 -07:00
Don Isaac
d09e381cbc fix(css): :global in css modules (#18257) 2025-03-17 17:15:54 -07:00
190n
53d631f1bd chore: address review feedback from #17820 (#18261) 2025-03-17 16:38:34 -07:00
pfg
74768449bc disallow test() within test() (#18203) 2025-03-15 21:34:35 -07:00
github-actions[bot]
294adc2269 deps: update lolhtml to v2.2.0 (#18222)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-03-15 21:33:41 -07:00
Ciro Spaciari
ff97424667 fix(SQL) implement unix socket support (#18196)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-15 11:51:20 -07:00
Meghan Denny
cbf8d7cad6 empty commit to verify CI post- image publish 2025-03-15 01:16:29 -07:00
Meghan Denny
0c41951b58 [publish images] 2025-03-14 23:55:35 -07:00
Meghan Denny
50b36696f8 ci: upgrade to alpine 3.21 (#18054) 2025-03-14 23:52:39 -07:00
190n
de4182f305 chore: upgrade zig to 0.14.0 (#17820)
Co-authored-by: 190n <7763597+190n@users.noreply.github.com>
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
Co-authored-by: pfg <pfg@pfg.pw>
Co-authored-by: pfgithub <6010774+pfgithub@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-03-14 22:13:31 -07:00
Dylan Conway
4214cc0aaa followup #18044 and #17850 (#18205) 2025-03-14 21:26:12 -07:00
chloe caruso
d1c77f5061 fix dev server regressions from 1.2.5's hmr rewrite (#18109)
Co-authored-by: Zack Radisic <zack@theradisic.com>
Co-authored-by: zackradisic <56137411+zackradisic@users.noreply.github.com>
2025-03-14 21:24:14 -07:00
190n
45e01cdaf2 Mark other PGlite test as TODO on Linux x64 (#18201) 2025-03-14 19:02:45 -07:00
pfg
2fc19daeec Update spawn docs to add timeout and resourceUsage (#18204) 2025-03-14 19:02:22 -07:00
chloe caruso
60c0b9ab96 fix debug windows build (#18178) 2025-03-14 15:25:35 -07:00
Ciro Spaciari
7f948f9c3e fix(sql) fix query parameters options (#18194) 2025-03-14 13:39:55 -07:00
Meghan Denny
66fb9f1097 test: install detect-libc (#18185) 2025-03-14 09:49:19 -07:00
Don Isaac
062a5b9bf8 fix(shell): remove unecessary allocations when printing errors (#17898) 2025-03-14 08:45:34 -07:00
Ciro Spaciari
5bedf15462 fix(crypto) Fix ED25519 from private (#18188) 2025-03-13 23:18:48 -07:00
Meghan Denny
d7aee40387 node: fix test-buffer-creation-regression.js (#18184) 2025-03-13 21:44:43 -07:00
Don Isaac
26f08fabd7 fix(ShadowRealm): give global objects a unique execution context id (#18179) 2025-03-13 21:00:35 -07:00
Jarred Sumner
05b48ce57c Implement node:crypto DiffieHellman (in native code) (#17850)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-03-13 20:26:25 -07:00
Don Isaac
1ed87f4e83 fix: deadlock in Cow debug checks (#18173)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-03-13 16:42:06 -07:00
Niklas Mollenhauer
b089558674 fix: removal of trailing slash in s3 presign (#18158) 2025-03-13 13:19:04 -07:00
Ciro Spaciari
45df1dbba0 fix(usockets) only add socket and context to the free list after socket on_close callback returns (#18144) 2025-03-13 12:45:53 -07:00
Ciro Spaciari
beb32770f0 fix(tests) move to the right folder (#18130) 2025-03-13 12:40:49 -07:00
Meghan Denny
3eec297282 js: no longer provide our own 'detect-libc' (#18138) 2025-03-13 12:40:37 -07:00
Don Isaac
b0b6c979ee fix(bun-plugin-svelte): handle "svelte" export conditions (#18150) 2025-03-13 12:40:22 -07:00
Indigo
7d69ac03ec sqlite: Enable passing options to Database.deserialize to enable strict mode (#17726)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-13 12:36:51 -07:00
Ashcon Partovi
d7e08abce8 Fix setTimeout(() => {}) from emitting a warning (#18160) 2025-03-13 11:37:48 -07:00
Nicholas Lister
d907942966 docs: fix typos in plugins.md (#18163) 2025-03-13 11:05:21 -07:00
aab
fe0e737f7b types: fix error for Uint8Array.fromBase64 (#18153) 2025-03-13 09:03:45 -07:00
Alistair Smith
8da959df85 fix: Move ShellError inside bun module decl (#18149) 2025-03-12 21:57:04 -07:00
pfg
d7a047a533 Fix #18131 (global catch-all route does not work with callback handler) (#18148) 2025-03-12 21:39:31 -07:00
Meghan Denny
c260223127 node: fix test-tls-translate-peer-certificate.js (#18136) 2025-03-12 21:00:22 -07:00
Meghan Denny
e834a80b7b node: fix test-tls-timeout-server-2.js (#18143) 2025-03-12 19:31:22 -07:00
pfg
7011dd6524 Update webkit build instructions (#18142) 2025-03-12 18:15:35 -07:00
190n
cde668b54c Better edge case handling in napi_value<->String conversion (#18107) 2025-03-12 18:15:00 -07:00
Zack Radisic
01db86e915 Fix #18064 (#18134) 2025-03-12 16:08:16 -07:00
chloe caruso
85376147a4 node:module compatibility pt 1 (#18106) 2025-03-12 15:47:41 -07:00
Meghan Denny
d2ecce272c node: fix test-net-server-close-before-calling-lookup-callback.js (#18103) 2025-03-12 14:21:24 -07:00
Meghan Denny
7ee0b428d6 node: fix test-tls-connect-simple.js (#18094) 2025-03-12 14:20:39 -07:00
Meghan Denny
9482e4c86a node: fix test-tls-close-event-after-write.js (#18098) 2025-03-12 14:20:14 -07:00
Meghan Denny
42276a9500 node: fix test-tls-connect-hwm-option.js (#18096) 2025-03-12 14:20:02 -07:00
Kai Tamkun
ae8f78c84d UDP: reset cached address and remoteAddress properties (#18043) 2025-03-12 14:19:44 -07:00
Meghan Denny
9636852224 node: fix test-tls-client-abort2.js (#18099) 2025-03-12 14:19:22 -07:00
Meghan Denny
5f72715a42 node: fix test-tls-invoke-queued.js (#18091) 2025-03-12 14:19:08 -07:00
Ciro Spaciari
c60b5dd4d6 compat(http) more compat in http (#18074) 2025-03-12 14:18:51 -07:00
Meghan Denny
42c474a21f node: fix test-net-socket-end-callback.js (#18102) 2025-03-12 14:17:29 -07:00
Meghan Denny
04078fbf61 node: fix test-tls-0-dns-altname.js (#18100) 2025-03-12 14:17:18 -07:00
Zack Radisic
28ebbb3f20 Fix node:vm test (#18081) 2025-03-12 14:16:03 -07:00
ippsav
96fa32bcc1 Fix transpiler encoding issue (#18057) 2025-03-12 13:58:53 -07:00
Pham Minh Triet
b3246b6971 fix(docs): remove extra character (#18123) 2025-03-12 13:26:27 -07:00
Meghan Denny
0345414ded node: fix test-net-reuseport.js (#18104) 2025-03-12 12:25:39 -07:00
Alistair Smith
01d214b276 Fix some higher priority @types/bun issues (devserver, serve) (#18121) 2025-03-12 18:38:31 +00:00
pfg
fdd181d68d Even more child process tests passing (#18052) 2025-03-11 22:52:12 -07:00
pfg
5c7df736bf Bring back btjs (#18108) 2025-03-11 22:51:05 -07:00
Meghan Denny
29870cb572 node: fix test-tls-interleave.js (#18092) 2025-03-11 20:33:42 -07:00
Meghan Denny
32223e90e3 node: fix test-tls-transport-destroy-after-own-gc.js (#18087) 2025-03-11 20:33:25 -07:00
Meghan Denny
31198cdbd9 node: fix test-tls-connect-pipe.js (#18095) 2025-03-11 20:33:13 -07:00
Meghan Denny
971f2b1ed7 node: fix test-tls-destroy-whilst-write.js (#18093) 2025-03-11 20:32:52 -07:00
chloe caruso
832cf91e88 remove a memory leak in bun.String.concat/createFromConcat (#18084) 2025-03-11 20:30:51 -07:00
Kai Tamkun
2e010073aa Fix express responses dying early (#18080) 2025-03-11 19:53:50 -07:00
Ciro Spaciari
4c93b72906 compat(http2) more http2 compatibility improvements (#18060)
Co-authored-by: cirospaciari <6379399+cirospaciari@users.noreply.github.com>
2025-03-11 19:46:05 -07:00
Meghan Denny
7091fd5791 node: fix test-tls-write-error.js (#18082) 2025-03-11 18:46:15 -07:00
Meghan Denny
e5edd388a0 node: fix test-tls-use-after-free-regression.js (#18085) 2025-03-11 18:45:12 -07:00
Meghan Denny
b887270e25 node: fix test-tls-no-rsa-key.js (#18090) 2025-03-11 18:40:30 -07:00
Meghan Denny
fc0d0ad8d3 node: fix test-tls-set-encoding.js (#18088) 2025-03-11 18:39:15 -07:00
Dylan Conway
ddfc8555f7 crypto: fix test-crypto-random.js (#18044)
Co-authored-by: Meghan Denny <meghan@bun.sh>
2025-03-11 18:21:20 -07:00
Meghan Denny
6d0739f7d9 js: de-class-ify node:tls.TLSSocket (#18058) 2025-03-11 16:37:50 -07:00
Don Isaac
fdd750e4b5 docs(bun-plugin-svelte): add example (#18076) 2025-03-11 14:39:10 -07:00
Don Isaac
9a5afe371a fix(bun-plugin-svelte): fix svelte module imports (#18042) 2025-03-11 12:01:15 -07:00
Dylan Conway
5123561889 fix assertion in JSBuffer.cpp (#18048) 2025-03-11 10:20:15 -07:00
Meghan Denny
ba7f59355f js: de-class-ify node:net.Socket (#17997) 2025-03-10 23:37:11 -07:00
Michael H
a79f92df9e CI: fix canary uploading for x64 macos (#18053) 2025-03-10 21:59:13 -07:00
Meghan Denny
8bc88763ec Bump 2025-03-10 21:06:52 -07:00
Kai Tamkun
4a0e982bb2 node:http improvements (#17093)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Pham Minh Triet <92496972+Nanome203@users.noreply.github.com>
Co-authored-by: snwy <snwy@snwy.me>
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
Co-authored-by: cirospaciari <cirospaciari@users.noreply.github.com>
Co-authored-by: Ben Grant <ben@bun.sh>
2025-03-10 20:19:29 -07:00
Ciro Spaciari
013fdddc6e feat(CSRF) implement Bun.CSRF (#18045)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-10 17:51:57 -07:00
190n
a9ca465ad0 Bump WebKit (#18039) 2025-03-10 12:39:20 -07:00
Alistair Smith
cd4d75ee7b Fix type error for base64 operations (#18034)
Co-authored-by: azom <dev@azom.ca>
2025-03-10 09:40:29 -07:00
pfg
aa2e109f5f Add launch configuration for rr (#17963) 2025-03-09 00:19:20 -08:00
Dylan Conway
45e3c9da70 Add destroy and destructors to Hmac, Verify, Sign, and Hash (#17996) 2025-03-07 22:55:39 -08:00
Jarred Sumner
cee026b87e Micro optimize latin1IdentifierContinueLength (#17972) 2025-03-07 21:46:14 -08:00
Dylan Conway
1a68ce05dc Add a few passing tests for node:crypto (#17987) 2025-03-07 20:53:06 -08:00
Don Isaac
bf0253df1d fix(cli): ignore --loader flag when running as node (#17992) 2025-03-07 20:32:07 -08:00
Jarred Sumner
2e3e6a15e0 Make TimeoutObject 8 bytes smaller (#17976)
Co-authored-by: Ben Grant <ben@bun.sh>
2025-03-07 20:07:31 -08:00
chloe caruso
589fa6274d dev server: forgotten changes (#17985)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-07 17:53:07 -08:00
Pham Minh Triet
4cf0d39e58 fix(docs): typo in css.md (#17973) 2025-03-07 17:28:45 -08:00
Kilian Brachtendorf
a1952c71f7 docs: add note about bun publish respecting NPM_CONFIG_TOKEN (#17975) 2025-03-07 17:28:16 -08:00
Dylan Conway
48df26462d fix test-crypto-randomuuid.js (#17955) 2025-03-07 17:05:17 -08:00
chloe caruso
66cf62c3c4 dev server: rewrite HMRModule, support sync esm + hot.accept (#17954)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-07 15:12:16 -08:00
Meghan Denny
9d6729fef3 docs: simplify bundler headings 2025-03-07 01:34:01 -08:00
Meghan Denny
20144ced54 docs: bundler/css.md: remove redundant heading 2025-03-07 01:22:18 -08:00
Meghan Denny
2e6cbd9a4d node: update test/common (#17786) 2025-03-07 00:32:23 -08:00
Meghan Denny
85f49a7a1a node: fix test-net-server-listen-options-signal.js (#17782)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-07 00:32:05 -08:00
Meghan Denny
6ba858dfbb node: fix test-net-connect-reset.js (#17823) 2025-03-07 00:31:41 -08:00
Meghan Denny
7b423d5ff8 node: fix test-warn-stream-wrap.js (#17937) 2025-03-07 00:30:56 -08:00
Dylan Conway
ae19729a72 node:crypto: native Hmac and Hash (#17920) 2025-03-06 23:52:10 -08:00
190n
2d45ae7441 Undo WebKit/WebKit#41727 (#17957) 2025-03-06 23:35:46 -08:00
Zack Radisic
e6cb0de539 CSS modules (#17958) 2025-03-06 23:35:06 -08:00
Jarred Sumner
924e50b6e9 Faster new TextDecoder() (#17964) 2025-03-06 23:33:31 -08:00
190n
1d32e78cf4 Do not idle in the event loop if there are pending immediate tasks (#17901) 2025-03-06 20:35:16 -08:00
Jarred Sumner
b5bca2d976 Bump WebKit (#17960) 2025-03-06 20:32:49 -08:00
Meghan Denny
1acd4039b6 fix test-net-better-error-messages-listen.js (#17888)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-06 19:47:12 -08:00
Meghan Denny
438ec5d1eb node: fix test-event-capture-rejections.js (#17953)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-06 19:46:40 -08:00
Meghan Denny
1a9cadf5f4 node: fix test-file-write-stream2.js (#17931) 2025-03-06 19:45:03 -08:00
Meghan Denny
304b471281 node: fix test-file-write-stream4.js (#17934) 2025-03-06 19:44:55 -08:00
Meghan Denny
6028683f87 node: fix test-stream-promises.js (#17936) 2025-03-06 19:44:45 -08:00
Reilly O'Donnell
0b58e791b3 feat(bun/test): Allow numbers, functions, and classes (anonymous and named) as first arg to describe blocks (#17218)
Co-authored-by: Don Isaac <donald.isaac@gmail.com>
2025-03-06 19:39:22 -08:00
Jacob Barrieault
1570d4f0a7 Fix 14585 — unminified identifier collisions (#17930) 2025-03-06 15:06:30 -08:00
malone hedges
b6b6efc839 Remove completed task (#17948) 2025-03-06 15:04:50 -08:00
pfg
d502df353c Support import with { type: "json" } and others (#16624) 2025-03-06 15:04:29 -08:00
Meghan Denny
7161326baa ci: make sure we're running the sequential node tests too (#17928) 2025-03-06 15:04:21 -08:00
Meghan Denny
903d6d058c node: fix test-file-write-stream3.js (#17933) 2025-03-06 15:03:10 -08:00
Ciro Spaciari
96b305389f automate root certs (#16549) 2025-03-06 14:40:52 -08:00
Ciro Spaciari
2a74f0d8f4 update(crypto) update root certificates to NSS 3.108 (#17950) 2025-03-06 14:40:36 -08:00
Pranav Joglekar
6e99733320 improv: display String objects similar to node (#17761) 2025-03-06 14:33:51 -08:00
Jarred Sumner
94ab3007a4 Add missing exception check in MessageEvent::create 2025-03-06 01:55:28 -08:00
190n
4645c309ca chore(CI): skip pglite.test.ts on linux x64 (#17814) 2025-03-05 20:46:21 -08:00
Meghan Denny
852830eb54 node: skip these buffer tests (#17929) 2025-03-05 19:35:19 -08:00
Don Isaac
4840217156 fix(node/net): infinite loop when connect is called without args (#17921) 2025-03-05 19:00:08 -08:00
Meghan Denny
78fb3ce64d node: fix test-net-server-try-ports.js (#17910) 2025-03-05 16:13:33 -08:00
Meghan Denny
368ddfdd14 node: fix test-net-server-options.js (#17909) 2025-03-05 16:13:17 -08:00
Meghan Denny
f9ebabe898 node: fix test-net-listen-ipv6only.js (#17908) 2025-03-05 16:13:04 -08:00
Mark Sheinkman
60eb2c4ecb vscode extention - support test names with special characters (#17915) 2025-03-05 14:49:49 -08:00
Jarred Sumner
8a177f6c85 Adjust flipping logic 2025-03-04 22:57:02 -08:00
Jarred Sumner
5053d0eaaf Flip shouldDisableStopIfNecessaryTimer 2025-03-04 22:56:10 -08:00
Jarred Sumner
6ec2b98336 Add BUN_DISABLE_STOP_IF_NECESSARY_TIMER env var 2025-03-04 20:57:26 -08:00
Meghan Denny
bae0921ef7 ci: this can take longer when CI is backed up 2025-03-04 20:00:59 -08:00
Meghan Denny
7eab65df99 cmd: tidy spacing in bun init (#17659) 2025-03-04 19:14:33 -08:00
Don Isaac
a41d773aaa feat: support Svelte in bundler and dev server (#17735) 2025-03-04 14:16:18 -08:00
Don Isaac
4ef7a43939 chore: add assertf and releaseAssert (#17859)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
Co-authored-by: chloe caruso <git@paperclover.net>
2025-03-04 12:50:59 -08:00
Jarred Sumner
7dc2e8e98e Add workaround (#17893) 2025-03-04 05:07:01 -08:00
Jarred Sumner
63636f19f1 Revert "Upgrade mimalloc" due to memory usage regression (#17892) 2025-03-04 04:50:39 -08:00
Jarred Sumner
23314188ca Deflake test/js/fs/promises
1 in 10000 is not random enough
2025-03-04 02:37:41 -08:00
Jarred Sumner
d429e35cdf Smaller musl builds (#17890) 2025-03-04 02:10:22 -08:00
Meghan Denny
99d85be529 node: fix test-net-connect-options-invalid.js (#17824) 2025-03-03 21:57:13 -08:00
Meghan Denny
2d0cadc949 node: fix test-net-server-unref-persistent.js (#17751) 2025-03-03 21:56:28 -08:00
pfg
821f42dd8e upgrade webkit (#17889) 2025-03-03 21:38:05 -08:00
James Hudon
0d4bd61ae0 rm unused PackageJSON.hash field (#17880) 2025-03-03 20:51:00 -08:00
chloe caruso
483302d09d dev server: fix some small css bugs (#17883) 2025-03-03 20:37:39 -08:00
Don Isaac
5aa2913bce test(bun/net): add TCP socket tests (#17520) 2025-03-03 20:30:47 -08:00
Kai Tamkun
1803f73b15 Improve uWS route performance (#17884) 2025-03-03 18:24:35 -08:00
Alistair Smith
9141337c7d Fix some issues in Bun types (#17424)
Co-authored-by: Michael H <git@riskymh.dev>
2025-03-03 16:04:12 -08:00
Don Isaac
70dbf582a6 fix(bunfig): fix and test preloads (#16329) 2025-03-03 15:45:18 -08:00
chloe caruso
1a6a34700f chore: less usingnamespace, deprecate bun.C in favor of automatic translate-c (#17830) 2025-03-03 15:04:21 -08:00
Don Isaac
6e140b4b13 feat(test): add test.failing (#17864)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-03-03 14:45:34 -08:00
Mayfield
ac07af11de Update nodejs-apis.md -> node:util compatible methods (#17858) 2025-03-03 12:14:50 -08:00
Jarred Sumner
078318f33c Split up bindings.zig into many files (#17831)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-03-01 03:12:00 -08:00
Dylan Conway
a620db7025 Fix incorrect string indexing in Git config parsing (#17832) 2025-03-01 03:10:53 -08:00
Dylan Conway
99cbdfb004 node:crypto: move Sign and Verify to c++ (#17692)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-03-01 03:01:39 -08:00
Jarred Sumner
887173c3c3 Split up exports.zig into files (#17827)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-03-01 01:20:50 -08:00
Dylan Conway
184506ae86 fix debug build 2025-03-01 00:27:00 -08:00
chloe caruso
25c95f3bdc hmr stability fixes (#17794) 2025-03-01 00:07:20 -08:00
Jarred Sumner
1bf13aa671 Upgrade mimalloc (#17817) 2025-02-28 21:48:34 -08:00
Jarred Sumner
671d876cf3 WebKit upgrade (#17818) 2025-02-28 21:27:31 -08:00
Ciro Spaciari
50856459e6 fix(http) dont drop numeric headers (#17769)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-28 20:15:49 -08:00
Meghan Denny
8db2844e80 node: fix test-net-write-arguments.js (#17742) 2025-02-28 20:15:39 -08:00
Meghan Denny
2d74c0162a node: fix test-util-parse-env.js (#17701) 2025-02-28 20:15:18 -08:00
Meghan Denny
7882418c5f node: fix test-net-localerror.js (#17806) 2025-02-28 19:26:20 -08:00
Ciro Spaciari
01fb872095 fix(serve) fix WS upgrade with routes (#17805) 2025-02-28 19:25:55 -08:00
Meghan Denny
12a2f412fc node: fix test-net-listen-close-server.js (#17809) 2025-02-28 19:24:59 -08:00
190n
ee6bdc1588 Restore TimerHeap but with behavior matching Node.js (#17811) 2025-02-28 19:24:30 -08:00
Meghan Denny
11979f69eb node: fix test-net-server-call-listen-multiple-times.js (#17785) 2025-02-27 23:03:48 -08:00
Ciro Spaciari
65b8b220d2 fix(new File()) fix name with empty body (#17783) 2025-02-27 23:03:15 -08:00
Jarred Sumner
c9e4153826 Fix hypothetical OOB in toml parser (#17789) 2025-02-27 21:22:04 -08:00
Dylan Conway
febf6593a6 fix(install): loading bun.lock with workspace overrides (#17779) 2025-02-27 17:17:20 -08:00
chloe caruso
e7790894d9 elaborate on error "Expected Sink" (#15234)
Co-authored-by: paperdave <paperdave@users.noreply.github.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-02-27 17:08:00 -08:00
Jarred Sumner
cef38030df Micro-optimize sourcemaps (#17757)
Co-authored-by: chloe caruso <git@paperclover.net>
2025-02-27 16:25:49 -08:00
chloe caruso
2fb121e2ed restore stubbed code paths in OutputFile.writeToDisk (#15278) 2025-02-27 15:42:21 -08:00
pfg
7ad46cb118 Add back banned words (#17057)
Co-authored-by: Ben Grant <ben@bun.sh>
Co-authored-by: Meghan Denny <meghan@bun.sh>
2025-02-27 15:19:15 -08:00
chloe caruso
4f58ff7933 changes to JSC.Strong, fix memory leaks in dev server (#17738) 2025-02-27 15:09:35 -08:00
Ashcon Partovi
838c3bbb8b Add cursor rules for writing tests 2025-02-27 14:09:38 -08:00
Johannes Przymusinski
fe49ac1a3d docs: remove random blog post link in docs (#17775) 2025-02-27 13:43:25 -08:00
190n
fbe4d57bae chore: disable TimerList logging by default (#17770) 2025-02-27 12:53:35 -08:00
Ciro Spaciari
f4937678e4 fix(node:http/Bun.serve) Allow Strict-Transport-Security in http (#17768) 2025-02-27 11:27:07 -08:00
Don Isaac
b124ba056c fix(ipc): check for empty IPC messages (#17753) 2025-02-27 06:12:46 -08:00
Jarred Sumner
0237baee92 Zero out sensitive memory before freeing (#17750) 2025-02-26 23:34:50 -08:00
Meghan Denny
cc481465b5 node: fix test-net-socket-timeout.js (#17745) 2025-02-26 22:41:38 -08:00
pfg
7a033e49c5 Support 'bun init <folder>' (#17743) 2025-02-26 22:41:12 -08:00
Meghan Denny
59551ebc79 node: assert a few more messages (#17703) 2025-02-26 22:20:27 -08:00
Meghan Denny
ad766f2402 node: fix test-net-socket-no-halfopen-enforcer.js (#17747) 2025-02-26 22:15:27 -08:00
190n
efabdcbe1f Start fixing bugs discovered by Node.js's Node-API tests (#14501)
Co-authored-by: Kai Tamkun <kai@tamkun.io>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Ashcon Partovi <ashcon@partovi.net>
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
Co-authored-by: 190n <190n@users.noreply.github.com>
2025-02-26 22:11:42 -08:00
pfg
174a0f70df return null rather than process.stdin on child process (#17741) 2025-02-26 20:47:49 -08:00
Meghan Denny
deeebf0538 node:perf_hooks: fixes 17716 (#17739) 2025-02-26 19:36:41 -08:00
Edu
63bc08e3ca Document workspace version publishing behavior (#15248)
Co-authored-by: Alistair Smith <hi@alistair.sh>
2025-02-26 19:00:00 -08:00
Jarred Sumner
d09daca867 Bump 2025-02-26 16:46:24 -08:00
190n
b3edef5989 node:timers fixes (#16855) 2025-02-26 16:45:02 -08:00
Bryce
baca1f4634 Fix VSCode Extension to Support Next.js Route Group File Paths on CodeLens Actions (#17724) 2025-02-26 16:27:20 -08:00
Meghan Denny
8bb6dd3cee node: fix test-util-text-decoder.js (#17700) 2025-02-26 16:03:55 -08:00
Ciro Spaciari
215da32660 fix(docs) fix insert docs and add update + where in (#17728) 2025-02-26 16:03:37 -08:00
Ciro Spaciari
5c6e20aeb4 fix(sql) fix state being set to prepared too soon (#17732) 2025-02-26 16:02:51 -08:00
Ashcon Partovi
1060558456 Fix Jest globals not being available in non-entrypoint files (#17734) 2025-02-26 16:02:15 -08:00
Ashcon Partovi
a2d028462b Remove unused ci/ directory 2025-02-26 09:17:43 -08:00
daniellionel01
ec4b9d198b Fix broken links to Web inspector (#17722) 2025-02-26 09:11:06 -08:00
Dylan Conway
fd9a5ea668 use path.joinAbsStringBuf in bun outdated (#17706)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-26 00:37:35 -08:00
Jarred Sumner
e8249d885c Fixes #17698 2025-02-25 23:45:43 -08:00
chloe caruso
ac8fb0e1f5 fix(bundler): bundling invalid html / export star as / react refresh fixes (#17685) 2025-02-25 22:04:10 -08:00
versecafe
39fdabc364 Add bun pm pack --filename for Yarn compatibility (#17628) 2025-02-25 21:17:04 -08:00
Meghan Denny
144a9c2f6d node: fix buffer.writeBigInt return value (#17695) 2025-02-25 20:47:55 -08:00
Ciro Spaciari
caff4e6008 fix(sql) fix SQL fragments handling and expand support for helpers (#17691) 2025-02-25 19:46:53 -08:00
Jarred Sumner
1322adbb16 Update executables.md 2025-02-25 18:43:37 -08:00
Jarred Sumner
11e5a6a2c7 Update codesign-macos-executable.md 2025-02-25 18:35:51 -08:00
Jarred Sumner
a130816004 Update codesign-macos-executable.md 2025-02-25 18:27:43 -08:00
Jarred Sumner
f4e0684603 Add codesigning guide 2025-02-25 18:25:54 -08:00
Meghan Denny
2db9ab4c72 synchronize all impls of ERR_INVALID_ARG_TYPE (#17158) 2025-02-25 15:35:14 -08:00
Don Isaac
2f48282cbd feat(build): PluginBuilder supports method chaining (#17683) 2025-02-25 14:44:49 -08:00
Meghan Denny
1574df835e zig: make JSValue.toBunString use JSError (#17648) 2025-02-25 13:04:44 -08:00
Dylan Conway
04973a1520 fix: bun.lock with bundledDependencies regression (#17665) 2025-02-25 02:33:47 -08:00
Pranav Joglekar
4e3c9bc1d1 feat: Support codesigning macOS executables in bun build --compile (#17207)
Co-authored-by: pfg <pfg@pfg.pw>
2025-02-25 01:34:11 -08:00
daniellionel01
d4c1114f9d Fix Broken Links in http.md (#17662) 2025-02-25 01:27:30 -08:00
Meghan Denny
b829590356 node: remove NotImplementedError exception in perf_hooks (#17651) 2025-02-24 22:10:22 -08:00
pfg
04f985523b Fix bun init on windows (#17656) 2025-02-24 22:08:02 -08:00
Kai Tamkun
32e6049be0 Don't pass bare Exceptions to JS in node:net (#17639) 2025-02-24 20:08:33 -08:00
Meghan Denny
94274b7198 node: fix test-buffer-alloc.js (#17642) 2025-02-24 20:08:09 -08:00
Meghan Denny
46246bb526 node: fix test-buffer-badhex.js (#17644) 2025-02-24 20:07:42 -08:00
Ciro Spaciari
09ab840114 fix(sql) fix binary detection + fix custom types (#17635) 2025-02-24 20:07:16 -08:00
pfg
211824bb3e fix fake resume triggering real ref() (#17640) 2025-02-24 20:03:33 -08:00
Meghan Denny
b7e5a38975 node: bun wants to skip these (#17646) 2025-02-24 20:02:56 -08:00
chloe caruso
cbeffe1b48 hmr7 (#17641) 2025-02-24 20:02:38 -08:00
pfg
a8c8fa15b9 Fix bake codegen on windows (#17654) 2025-02-24 19:57:35 -08:00
190n
032f99285c Bump WebKit (#17647) 2025-02-24 19:55:44 -08:00
Don Isaac
db5b915559 fix(node/net): better net.Server compatibility (#17638) 2025-02-24 19:24:10 -08:00
Michael H
445fe2ac4a fix --print process.argv <args> (#17251) 2025-02-24 15:39:47 -08:00
Meghan Denny
82c26f0a58 node: Buffer.prototype.indexOf on number wasn't relative to buffer start (#17631)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-24 14:26:40 -08:00
Don Isaac
943dc53a3b fix(ffi): make using tinycc bindings safer (#17397)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-02-24 11:23:26 -08:00
Don Isaac
61edc58362 feat(node/net): add SocketAddress (#17154)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-02-24 11:18:16 -08:00
dy0gu
7a35567b45 docs: improve command line environment variable tips (#16490)
Co-authored-by: Michael H <git@riskymh.dev>
2025-02-24 10:19:41 -08:00
Dylan Conway
47f9bb84e8 fix: invalid json import regression (#17612) 2025-02-24 01:57:29 -08:00
Jarred Sumner
b02156e793 Introduce dedicated I/O threadpool for Bun.build on macOS & Windows (#17577) 2025-02-23 22:07:05 -08:00
Jarred Sumner
6aa62fe4bf Mimick C wrapping behavior in stat & timespec (#17584) 2025-02-23 01:17:29 -08:00
github-actions[bot]
2206c14314 deps: update sqlite to 3.49.100 (#17585)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-02-23 01:16:42 -08:00
dalaoshu
5167ed20f9 fix(Glob): avoid exiting skip_brace early (#17582) 2025-02-22 23:14:08 -08:00
Michael H
0bb0bf7c08 DefinitelyTyped release PR fix (#17545) 2025-02-22 16:49:22 -08:00
Galo Benjamín Bello Ponce
4978fb8baf docs: add supported formats in cli docs (#17556) 2025-02-22 16:48:42 -08:00
Jarred Sumner
c2a9cf5bbd Fixes #17568 (#17572) 2025-02-22 16:48:20 -08:00
Jake Boone
d474b54ad1 Avoid animations for prefers-reduced-motion in bun init templates (#17565) 2025-02-22 16:44:55 -08:00
Jarred Sumner
9503f7b0b9 Bump 2025-02-22 15:27:40 -08:00
Jarred Sumner
01d932d7e4 Github actions 2025-02-22 15:26:28 -08:00
Jarred Sumner
5c8da4436c Github actions 2025-02-22 15:12:40 -08:00
Meghan Denny
d862966631 node: test-buffer-write.js (#17450) 2025-02-22 00:24:44 -08:00
Dylan Conway
f6c3b92f73 better test for #17516 (#17530) 2025-02-22 00:24:21 -08:00
Jarred Sumner
363bdf5c6c Add small file read optimization (#17533) 2025-02-22 00:23:32 -08:00
Meghan Denny
04703bd3cc zig: catch JSValue.toZigString/getZigString thrown exceptions (#17508) 2025-02-21 22:55:03 -08:00
Dylan Conway
8c4d3ff801 fix(crypto): reset zig hashers on digest (#17539) 2025-02-21 21:26:49 -08:00
chloe caruso
fb6f7e43d8 Dev Server: improve react refresh and export default handling (#17538) 2025-02-21 20:08:21 -08:00
Galo Benjamín Bello Ponce
78f4b20600 docs: fix shell's docs typo (#17536) 2025-02-21 19:18:30 -08:00
Kai Tamkun
bda1ad192d Fix EINVAL when setting IPv6 multicast membership (#17478) 2025-02-21 18:34:40 -08:00
Dylan Conway
8f7143882e fix function pointer cast (#17534) 2025-02-21 18:33:55 -08:00
Ciro Spaciari
8f888be7d5 fix(tls) ECONNRESET behavior (#17505) 2025-02-21 18:33:42 -08:00
Meghan Denny
84ad89cc95 ci: fix create-jsx.test.ts (#17535) 2025-02-21 18:26:28 -08:00
Jarred Sumner
18440d4b11 Ben/bump webkit (#17529)
Co-authored-by: Ben Grant <ben@bun.sh>
2025-02-21 15:52:02 -08:00
Don Isaac
7f0b117496 chore(net): add TCP/TLS to feature indicators (#17475)
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
2025-02-21 14:21:32 -08:00
Ciro Spaciari
94e5071947 feat(sql) implement sql.file and dynamic passwords support (#17527) 2025-02-21 14:04:15 -08:00
Jarred Sumner
8c32eb8354 Fix create not working properly (#17465)
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
Co-authored-by: chloe caruso <git@paperclover.net>
2025-02-21 12:41:34 -08:00
chloe caruso
3b956757d9 disable async in script tags in dev server (#17517)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-21 11:28:27 -08:00
Dylan Conway
fbc4aa480b fix(Glob): multiple separated brace pairs (#17516) 2025-02-21 10:54:03 -08:00
chloe caruso
dc5fae461d Implement simple barrel file optimization (#17514)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-20 22:50:51 -08:00
Jarred Sumner
a3ea521c98 Fix mime type for assets in HTML routes (#17513)
Co-authored-by: chloe caruso <git@paperclover.net>
2025-02-20 22:30:48 -08:00
Meghan Denny
27c90786ca node: implement process.binding('fs') (#17480) 2025-02-20 22:15:01 -08:00
pfg
226275c26d bun react template: fix background position jump after two minutes (#17509) 2025-02-20 21:28:25 -08:00
chloe caruso
b082572dcb DevServer: source map and error modal improvements (#17476) 2025-02-20 16:40:57 -08:00
Meghan Denny
275a34b014 node: fix test-buffer-bigint64.js (#17452) 2025-02-20 14:16:09 -08:00
pikdum
aef6a173ee docs: update arch contributing docs (#17484) 2025-02-20 12:15:40 -08:00
Jarred Sumner
1b271fd45e Avoid creating temporary strings when throwing errors (#17179)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-02-20 12:09:27 -08:00
Jarred Sumner
6e45e3bf1e Fixes #17458 2025-02-19 21:00:19 -08:00
Ciro Spaciari
1e6fdc9f15 fix(http2) altsvc + origin support (#17438) 2025-02-19 20:55:05 -08:00
190n
9b515d74aa fix(docs): ffi is experimental (#17445) 2025-02-19 20:48:12 -08:00
190n
7c6d9cac50 Bump WebKit, re-enable IPInt (#17467) 2025-02-19 20:47:40 -08:00
Paul Golmann
4811899bc5 Do not drop empty arguments in Bun.spawn (#17269)
Co-authored-by: pfg <pfg@pfg.pw>
2025-02-19 20:46:22 -08:00
pfg
e284c500a4 Fix hmr devserver on firefox (#17477) 2025-02-19 20:45:21 -08:00
pfg
86a4f306ee Preserve zero indentation when updating inline snapshot (#16813) 2025-02-19 20:27:40 -08:00
pfg
92a91ef2fd Fix hosting destructured decl with movable initializer (#17468) 2025-02-19 20:21:52 -08:00
Dylan Conway
6b2486a95d fix flaky next-build.test.ts (#17451) 2025-02-19 12:16:21 -08:00
Ciro Spaciari
0efc4eaf97 fix(sql) allow more than 64 columns (#17444) 2025-02-18 19:37:26 -08:00
Don Isaac
f3d18fc587 fix: failing bun init test cases (#17448) 2025-02-18 16:12:56 -08:00
Jarred Sumner
9cf9a26330 Revert "fix(sql) allow more than 64 columns" (#17441) 2025-02-18 13:42:59 -08:00
Meghan Denny
5ae28d27a0 node: fix buffer includes+indexof (#16642) 2025-02-18 13:12:03 -08:00
Jarred Sumner
1de31292fb Add react, tailwind, react+tailwind+shadcn to bun init (#17282)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-02-18 10:38:37 -08:00
Ciro Spaciari
fcdddf6425 fix(sql) allow more than 64 columns (#17419) 2025-02-18 09:07:23 -08:00
Jarred Sumner
0622ad57b4 Add a couple HTMLRewriter guides 2025-02-17 19:36:21 -08:00
190n
a5fb10981b fix(docs): clarify baseline builds (#17422) 2025-02-17 17:31:10 -08:00
Carl Aiau
cc04d51dc3 fix typo in render deployment guide (#17321) 2025-02-17 17:30:08 -08:00
Dylan Conway
4d0e9a968b fix(install): don't allow overriding workspaces (#17417) 2025-02-17 15:56:41 -08:00
Ciro Spaciari
99a3b01bd0 fix(sql) calling not tagged throw errors (#17415) 2025-02-17 13:06:27 -08:00
Don Isaac
32c17d8656 fix: memory leak in code coverage (#17399) 2025-02-17 03:42:01 -08:00
Jarred Sumner
527412626a Make fetch() optional in Bun.serve() when routes are passed (#17401)
Co-authored-by: Pham Minh Triet <92496972+Nanome203@users.noreply.github.com>
2025-02-17 03:25:07 -08:00
Ciro Spaciari
0d1a00fa0f fix(sql) docs (#17389) 2025-02-16 18:59:51 -08:00
Jarred Sumner
5e4ebf4381 Update some docs 2025-02-16 05:59:42 -08:00
Jarred Sumner
31bd9a3ac0 Update upload-release.sh 2025-02-16 05:35:05 -08:00
Jarred Sumner
636d2459bb Update sql.md 2025-02-16 04:32:27 -08:00
Jarred Sumner
b89b5d5710 Add back canary discord message 2025-02-16 02:27:16 -08:00
Don Isaac
f0e7251b61 chore: remove dead in transpiler (#17379) 2025-02-16 02:20:39 -08:00
Jarred Sumner
f29e912a91 Add routes to Bun.serve() (#17357) 2025-02-16 00:42:05 -08:00
pfg
ef8bd44e98 Track performance stats (#17246)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-15 22:46:18 -08:00
Don Isaac
cdf62b35ff refactor: move string-like structs into string module (#17369) 2025-02-15 21:52:43 -08:00
Don Isaac
59f3d1ca31 refactor: remove BunString.fromJSRef (#17367) 2025-02-15 21:52:13 -08:00
Don Isaac
f1a5e78033 refactor: remove unused RefCount struct (#17370) 2025-02-15 21:50:57 -08:00
github-actions[bot]
e3e4264208 deps: update lshpack to v2.3.4 (#17374)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-02-15 21:50:41 -08:00
chloe caruso
0b6aa96672 Chloe/hmr4 (#17353)
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-15 05:45:02 -08:00
Jarred Sumner
e01548c6e9 Remove a few more usages of shim.cppFn (#17358) 2025-02-15 05:27:58 -08:00
pfg
3711280d44 Download zig from oven-sh/zig releases & auto set up zls (#17128) 2025-02-15 03:56:41 -08:00
chloe caruso
78e52006c5 Rewrite internal Web Streams to use less memory (#16860)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: pfg <pfg@pfg.pw>
2025-02-15 01:16:28 -08:00
pfg
905fbee768 Wake up stdin after it falls asleep (#17351) 2025-02-15 01:15:10 -08:00
Meghan Denny
0405e1451c node: fix test-buffer-inspect.js (#17171) 2025-02-14 23:30:46 -08:00
Meghan Denny
b418b7794a node:buffer: fix write (#17323) 2025-02-14 23:30:18 -08:00
Meghan Denny
600343fff7 node:buffer: fix test-buffer-resizable.js (#17350) 2025-02-14 23:29:09 -08:00
190n
43367817a4 Handle rejected promises in EventLoop.autoTick (#17346) 2025-02-14 17:49:30 -08:00
Meghan Denny
7b65ca2a71 Revert "assets in css files 1"
This reverts commit 29c737b2b9.
2025-02-14 17:27:33 -08:00
chloe caruso
29c737b2b9 assets in css files 1 2025-02-14 17:24:55 -08:00
Jarred Sumner
b4f34b03d6 Fix disabling HMR, add way to do /api/* and /* in static (#17333) 2025-02-14 07:43:21 -08:00
Ben Kunkle
b44769c751 Glob Match Rewrite (#16824)
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
2025-02-14 06:32:57 -08:00
chloe caruso
10663d7912 devserver: use file urls for sourcemap (#17319)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-14 01:30:03 -08:00
Ciro Spaciari
a2c64ad706 fix(sql) add prepare: false option and sql``.simple() (#17296) 2025-02-13 19:51:05 -08:00
Ciro Spaciari
79afefa488 fix(s3) Support Virtual Hosted-Style endpoints (#17292)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-13 19:47:53 -08:00
2521 changed files with 184014 additions and 55494 deletions

View File

@@ -1,12 +1,12 @@
ARG LLVM_VERSION="18"
ARG REPORTED_LLVM_VERSION="18.1.8"
ARG LLVM_VERSION="19"
ARG REPORTED_LLVM_VERSION="19.1.7"
ARG OLD_BUN_VERSION="1.1.38"
ARG DEFAULT_CFLAGS="-mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -ffunction-sections -fdata-sections -faddrsig -fno-unwind-tables -fno-asynchronous-unwind-tables"
ARG DEFAULT_CXXFLAGS="-flto=full -fwhole-program-vtables -fforce-emit-vtables"
ARG BUILDKITE_AGENT_TAGS="queue=linux,os=linux,arch=${TARGETARCH}"
FROM --platform=$BUILDPLATFORM ubuntu:20.04 as base-arm64
FROM --platform=$BUILDPLATFORM ubuntu:18.04 as base-amd64
FROM --platform=$BUILDPLATFORM ubuntu:20.04 as base-amd64
FROM base-$TARGETARCH as base
ARG LLVM_VERSION

View File

@@ -107,9 +107,9 @@ const buildPlatforms = [
{ os: "linux", arch: "aarch64", distro: "amazonlinux", release: "2023", features: ["docker"] },
{ os: "linux", arch: "x64", distro: "amazonlinux", release: "2023", features: ["docker"] },
{ os: "linux", arch: "x64", baseline: true, distro: "amazonlinux", release: "2023", features: ["docker"] },
{ os: "linux", arch: "aarch64", abi: "musl", distro: "alpine", release: "3.20" },
{ os: "linux", arch: "x64", abi: "musl", distro: "alpine", release: "3.20" },
{ os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.20" },
{ os: "linux", arch: "aarch64", abi: "musl", distro: "alpine", release: "3.21" },
{ os: "linux", arch: "x64", abi: "musl", distro: "alpine", release: "3.21" },
{ os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.21" },
{ os: "windows", arch: "x64", release: "2019" },
{ os: "windows", arch: "x64", baseline: true, release: "2019" },
];
@@ -134,9 +134,9 @@ const testPlatforms = [
{ os: "linux", arch: "x64", baseline: true, distro: "ubuntu", release: "24.04", tier: "latest" },
{ os: "linux", arch: "x64", baseline: true, distro: "ubuntu", release: "22.04", tier: "previous" },
{ os: "linux", arch: "x64", baseline: true, distro: "ubuntu", release: "20.04", tier: "oldest" },
{ os: "linux", arch: "aarch64", abi: "musl", distro: "alpine", release: "3.20", tier: "latest" },
{ os: "linux", arch: "x64", abi: "musl", distro: "alpine", release: "3.20", tier: "latest" },
{ os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.20", tier: "latest" },
{ os: "linux", arch: "aarch64", abi: "musl", distro: "alpine", release: "3.21", tier: "latest" },
{ os: "linux", arch: "x64", abi: "musl", distro: "alpine", release: "3.21", tier: "latest" },
{ os: "linux", arch: "x64", abi: "musl", baseline: true, distro: "alpine", release: "3.21", tier: "latest" },
{ os: "windows", arch: "x64", release: "2019", tier: "oldest" },
{ os: "windows", arch: "x64", release: "2019", baseline: true, tier: "oldest" },
];
@@ -323,6 +323,7 @@ function getCppAgent(platform, options) {
*/
function getZigAgent(platform, options) {
const { arch } = platform;
return {
queue: "build-zig",
};
@@ -383,15 +384,21 @@ function getBuildEnv(target, options) {
const { canary } = options;
const revision = typeof canary === "number" ? canary : 1;
const isMusl = abi === "musl";
let CMAKE_BUILD_TYPE = release ? "Release" : profile === "debug" ? "Debug" : "RelWithDebInfo";
if (isMusl && release) {
CMAKE_BUILD_TYPE = "MinSizeRel";
}
return {
CMAKE_BUILD_TYPE: release ? "Release" : profile === "debug" ? "Debug" : "RelWithDebInfo",
CMAKE_BUILD_TYPE,
ENABLE_BASELINE: baseline ? "ON" : "OFF",
ENABLE_CANARY: revision > 0 ? "ON" : "OFF",
CANARY_REVISION: revision,
ENABLE_ASSERTIONS: release ? "OFF" : "ON",
ENABLE_LOGS: release ? "OFF" : "ON",
ABI: abi === "musl" ? "musl" : undefined,
ABI: isMusl ? "musl" : undefined,
CMAKE_TLS_VERIFY: "0",
};
}
@@ -464,7 +471,7 @@ function getBuildZigStep(platform, options) {
cancel_on_build_failing: isMergeQueue(),
env: getBuildEnv(platform, options),
command: `bun run build:ci --target bun-zig --toolchain ${toolchain}`,
timeout_in_minutes: 25,
timeout_in_minutes: 35,
};
}
@@ -621,6 +628,21 @@ function getReleaseStep(buildPlatforms, options) {
};
}
/**
* @returns {Step}
*/
function getBenchmarkStep() {
return {
key: "benchmark",
label: "📊",
agents: {
queue: "build-zig",
},
command: "bun .buildkite/scripts/upload-benchmark.ts",
depends_on: [`linux-x64-build-bun`],
};
}
/**
* @typedef {Object} Pipeline
* @property {Step[]} [steps]
@@ -1099,6 +1121,8 @@ async function getPipeline(options = {}) {
steps.push(getReleaseStep(buildPlatforms, options));
}
steps.push(getBenchmarkStep());
/** @type {Map<string, GroupStep>} */
const stepsByGroup = new Map();

View File

@@ -0,0 +1,7 @@
import { getCommit, getSecret } from "../../scripts/utils.mjs";
console.log("Submitting...");
const response = await fetch(getSecret("BENCHMARK_URL") + "?tag=_&commit=" + getCommit() + "&artifact_url=_", {
method: "POST",
});
console.log("Got status " + response.status);

View File

@@ -158,25 +158,36 @@ function upload_s3_file() {
run_command aws --endpoint-url="$AWS_ENDPOINT" s3 cp "$file" "s3://$AWS_BUCKET/$folder/$file"
}
function send_bench_webhook() {
if [ -z "$BENCHMARK_URL" ]; then
echo "error: \$BENCHMARK_URL is not set"
# exit 1 # TODO: this isn't live yet
function send_discord_announcement() {
local value=$(buildkite-agent secret get "BUN_ANNOUNCE_CANARY_WEBHOOK_URL")
if [ -z "$value" ]; then
echo "warn: BUN_ANNOUNCE_CANARY_WEBHOOK_URL not set, skipping Discord announcement"
return
fi
local tag="$1"
local version="$1"
local commit="$BUILDKITE_COMMIT"
local artifact_path="${commit}"
local short_sha="${commit:0:7}"
local commit_url="https://github.com/oven-sh/bun/commit/$commit"
if [ "$tag" == "canary" ]; then
artifact_path="${commit}-canary"
if [ "$version" == "canary" ]; then
local json_payload=$(cat <<EOF
{
"embeds": [{
"title": "New Bun Canary now available",
"description": "A new canary build of Bun has been automatically uploaded ([${short_sha}](${commit_url})). To upgrade, run:\n\n\`\`\`shell\nbun upgrade --canary\n\`\`\`\nCommit: \`${commit}\`",
"color": 16023551,
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}]
}
EOF
)
curl -H "Content-Type: application/json" \
-d "$json_payload" \
-sf \
"$value" >/dev/null
fi
local artifact_url="https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/$artifact_path/bun-linux-x64.zip"
local webhook_url="$BENCHMARK_URL?tag=$tag&commit=$commit&artifact_url=$artifact_url"
curl -X POST "$webhook_url"
}
function create_release() {
@@ -190,6 +201,8 @@ function create_release() {
local artifacts=(
bun-darwin-aarch64.zip
bun-darwin-aarch64-profile.zip
bun-darwin-x64.zip
bun-darwin-x64-profile.zip
bun-linux-aarch64.zip
bun-linux-aarch64-profile.zip
bun-linux-x64.zip
@@ -227,7 +240,7 @@ function create_release() {
update_github_release "$tag"
create_sentry_release "$tag"
send_bench_webhook "$tag"
send_discord_announcement "$tag"
}
function assert_canary() {

View File

@@ -0,0 +1,27 @@
---
description: How to build Bun
globs:
---
# How to build Bun
## CMake
Bun is built using CMake, which you can find in `CMakeLists.txt` and in the `cmake/` directory.
* `CMakeLists.txt`
* `cmake/`
* `Globals.cmake` - macros and functions used by all the other files
* `Options.cmake` - build options for configuring the build (e.g. debug/release mode)
* `CompilerFlags.cmake` - compiler and linker flags used by all the targets
* `tools/` - setup scripts for various build tools (e.g. llvm, zig, webkit, rust, etc.)
* `targets/` - targets for bun and its dependencies (e.g. brotli, boringssl, libuv, etc.)
## How to
There are `package.json` scripts that make it easy to build Bun without calling CMake directly, for example:
```sh
bun run build # builds a debug build: `build/debug/bun-debug`
bun run build:release # builds a release build: `build/release/bun`
bun run build:assert # builds a release build with debug assertions: `build/assert/bun`
```

View File

@@ -0,0 +1,139 @@
---
description: Writing HMR/Dev Server tests
globs: test/bake/*
---
# Writing HMR/Dev Server tests
Dev server tests validate that hot-reloading is robust, correct, and reliable. Remember to write thorough, yet concise tests.
## File Structure
- `test/bake/bake-harness.ts` - shared utilities and test harness
- primary test functions `devTest` / `prodTest` / `devAndProductionTest`
- class `Dev` (controls subprocess for dev server)
- class `Client` (controls a happy-dom subprocess for having the page open)
- more helpers
- `test/bake/client-fixture.mjs` - subprocess for what `Client` controls. it loads a page and uses IPC to query parts of the page, run javascript, and much more.
- `test/bake/dev/*.test.ts` - these call `devTest` to test dev server and hot reloading
- `test/bake/dev-and-prod.ts` - these use `devAndProductionTest` to run the same test on dev and production mode. these tests cannot really test hot reloading for obvious reasons.
## Categories
bundle.test.ts - Bundle tests are tests concerning bundling bugs that only occur in DevServer.
css.test.ts - CSS tests concern bundling bugs with CSS files
plugins.test.ts - Plugin tests concern plugins in development mode.
ecosystem.test.ts - These tests involve ensuring certain libraries are correct. It is preferred to test more concrete bugs than testing entire packages.
esm.test.ts - ESM tests are about various esm features in development mode.
html.test.ts - HTML tests are tests relating to HTML files themselves.
react-spa.test.ts - Tests relating to React, our react-refresh transform, and basic server component transforms.
sourcemap.test.ts - Tests verifying source-maps are correct.
## `devTest` Basics
A test takes in two primary inputs: `files` and `async test(dev) {`
```ts
import { devTest, emptyHtmlFile } from "../bake-harness";
devTest("html file is watched", {
files: {
"index.html": emptyHtmlFile({
scripts: ["/script.ts"],
body: "<h1>Hello</h1>",
}),
"script.ts": `
console.log("hello");
`,
},
async test(dev) {
await dev.fetch("/").expect.toInclude("<h1>Hello</h1>");
await dev.fetch("/").expect.toInclude("<h1>Hello</h1>");
await dev.patch("index.html", {
find: "Hello",
replace: "World",
});
await dev.fetch("/").expect.toInclude("<h1>World</h1>");
// Works
await using c = await dev.client("/");
await c.expectMessage("hello");
// Editing HTML reloads
await c.expectReload(async () => {
await dev.patch("index.html", {
find: "World",
replace: "Hello",
});
await dev.fetch("/").expect.toInclude("<h1>Hello</h1>");
});
await c.expectMessage("hello");
await c.expectReload(async () => {
await dev.patch("index.html", {
find: "Hello",
replace: "Bar",
});
await dev.fetch("/").expect.toInclude("<h1>Bar</h1>");
});
await c.expectMessage("hello");
await c.expectReload(async () => {
await dev.patch("script.ts", {
find: "hello",
replace: "world",
});
});
await c.expectMessage("world");
},
});
```
`files` holds the initial state, and the callback runs with the server running. `dev.fetch()` runs HTTP requests, while `dev.client()` opens a browser instance to the code.
Functions `dev.write` and `dev.patch` and `dev.delete` mutate the filesystem. Do not use `node:fs` APIs, as the dev server ones are hooked to wait for hot-reload, and all connected clients to recieve changes.
When a change performs a hard-reload, that must be explicitly annotated with `expectReload`. This tells `client-fixture.mjs` that the test is meant to reload the page once; All other hard reloads automatically fail the test.
Client's have `console.log` instrumented, so that any unasserted logs fail the test. This makes it more obvious when an extra reload or re-evaluation. Messages are awaited via `c.expectMessage("log")` or with multiple arguments if there are multiple logs.
## Testing for bundling errors
By default, a client opening a page to an error will fail the test. This makes testing errors explicit.
```ts
devTest("import then create", {
files: {
"index.html": `
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="module" src="/script.ts"></script>
</body>
</html>
`,
"script.ts": `
import data from "./data";
console.log(data);
`,
},
async test(dev) {
const c = await dev.client("/", {
errors: ['script.ts:1:18: error: Could not resolve: "./data"'],
});
await c.expectReload(async () => {
await dev.write("data.ts", "export default 'data';");
});
await c.expectMessage("data");
},
});
```
Many functions take an options value to allow specifying it will produce errors. For example, this delete is going to cause a resolution failure.
```ts
await dev.delete("other.ts", {
errors: ['index.ts:1:16: error: Could not resolve: "./other"'],
});
```

View File

@@ -268,16 +268,16 @@ If there's a class, prototype, and constructor:
2. Initialize the class structure in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::finishCreation(VM& vm)`
3. Visit the class structure in visitChildren in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::visitChildrenImpl`
```c++
```c++#ZigGlobalObject.cpp
void GlobalObject::finishCreation(VM& vm) {
// ...
m_JSStatsBigIntClassStructure.initLater(
[](LazyClassStructure::Initializer& init) {
// Call the function to initialize our class structure.
Bun::initJSBigIntStatsClassStructure(init);
});
```
If there's only a class, use `JSC::LazyProperty<JSGlobalObject, Structure>` instead of `JSC::LazyClassStructure`.
Then, implement the function that creates the structure:
```c++
void setupX509CertificateClassStructure(LazyClassStructure::Initializer& init)
@@ -296,6 +296,36 @@ void setupX509CertificateClassStructure(LazyClassStructure::Initializer& init)
}
```
If there's only a class, use `JSC::LazyProperty<JSGlobalObject, Structure>` instead of `JSC::LazyClassStructure`:
1. Add the `JSC::LazyProperty<JSGlobalObject, Structure>` to @ZigGlobalObject.h
2. Initialize the class structure in @ZigGlobalObject.cpp in `void GlobalObject::finishCreation(VM& vm)`
3. Visit the lazy property in visitChildren in @ZigGlobalObject.cpp in `void GlobalObject::visitChildrenImpl`
void GlobalObject::finishCreation(VM& vm) {
// ...
this.m_myLazyProperty.initLater([](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) {
init.set(Bun::initMyStructure(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.owner)));
});
```
Then, implement the function that creates the structure:
```c++
Structure* setupX509CertificateStructure(JSC::VM &vm, Zig::GlobalObject* globalObject)
{
// If there is a prototype:
auto* prototypeStructure = JSX509CertificatePrototype::createStructure(init.vm, init.global, init.global->objectPrototype());
auto* prototype = JSX509CertificatePrototype::create(init.vm, init.global, prototypeStructure);
// If there is no prototype or it only has
auto* structure = JSX509Certificate::createStructure(init.vm, init.global, prototype);
init.setPrototype(prototype);
init.setStructure(structure);
init.setConstructor(constructor);
}
```
Then, use the structure by calling `globalObject.m_myStructureName.get(globalObject)`
```C++

View File

@@ -0,0 +1,91 @@
---
description: Writing tests for Bun
globs:
---
# Writing tests for Bun
## Where tests are found
You'll find all of Bun's tests in the `test/` directory.
* `test/`
* `cli/` - CLI command tests, like `bun install` or `bun init`
* `js/` - JavaScript & TypeScript tests
* `bun/` - `Bun` APIs tests, seperated by category, for example: `glob/` for `Bun.Glob` tests
* `node/` - Node.js module tests, seperated by module, for example: `assert/` for `node:assert` tests
* `test/` - Vendored Node.js tests, taken from the Node.js repository (does not conform to Bun's test style)
* `web/` - Web API tests, seperated by category, for example: `fetch/` for `Request` and `Response` tests
* `third_party/` - npm package tests, to validate that basic usage works in Bun
* `napi/` - N-API tests
* `v8/` - V8 C++ API tests
* `bundler/` - Bundler, transpiler, CSS, and `bun build` tests
* `regression/issue/[number]` - Regression tests, always make one when fixing a particular issue
## How tests are written
Bun's tests are written as JavaScript and TypeScript files with the Jest-style APIs, like `test`, `describe`, and `expect`. They are tested using Bun's own test runner, `bun test`.
```js
import { describe, test, expect } from "bun:test";
import assert, { AssertionError } from "assert";
describe("assert(expr)", () => {
test.each([true, 1, "foo"])(`assert(%p) does not throw`, expr => {
expect(() => assert(expr)).not.toThrow();
});
test.each([false, 0, "", null, undefined])(`assert(%p) throws`, expr => {
expect(() => assert(expr)).toThrow(AssertionError);
});
});
```
## Testing conventions
* See `test/harness.ts` for common test utilities and helpers
* Be rigorous and test for edge-cases and unexpected inputs
* Use data-driven tests, e.g. `test.each`, to reduce boilerplate when possible
* When you need to test Bun as a CLI, use the following pattern:
```js
import { test, expect } from "bun:test";
import { spawn } from "bun";
import { bunExe, bunEnv } from "harness";
test("bun --version", async () => {
const { exited, stdout: stdoutStream, stderr: stderrStream } = spawn({
cmd: [bunExe(), "--version"],
env: bunEnv,
stdout: "pipe",
stderr: "pipe",
});
const [ exitCode, stdout, stderr ] = await Promise.all([
exited,
new Response(stdoutStream).text(),
new Response(stderrStream).text(),
]);
expect({ exitCode, stdout, stderr }).toMatchObject({
exitCode: 0,
stdout: expect.stringContaining(Bun.version),
stderr: "",
});
});
```
## Before writing a test
* If you are fixing a bug, write the test first and make sure it fails (as expected) with the canary version of Bun
* If you are fixing a Node.js compatibility bug, create a throw-away snippet of code and test that it works as you expect in Node.js, then that it fails (as expected) with the canary version of Bun
* When the expected behaviour is ambigious, defer to matching what happens in Node.js
* Always attempt to find related tests in an existing test file before creating a new test file

View File

@@ -11,8 +11,8 @@ on:
env:
BUN_VERSION: "1.2.0"
LLVM_VERSION: "18.1.8"
LLVM_VERSION_MAJOR: "18"
LLVM_VERSION: "19.1.7"
LLVM_VERSION_MAJOR: "19"
jobs:
clang-format:

View File

@@ -11,8 +11,8 @@ on:
env:
BUN_VERSION: "1.2.0"
LLVM_VERSION: "18.1.8"
LLVM_VERSION_MAJOR: "18"
LLVM_VERSION: "19.1.7"
LLVM_VERSION_MAJOR: "19"
jobs:
clang-tidy:

55
.github/workflows/packages-ci.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Packages CI
on:
push:
branches:
- main
paths:
- "packages/**"
- .prettierrc
- .prettierignore
- tsconfig.json
- oxlint.json
- "!**/*.md"
pull_request:
branches:
- main
paths:
- "packages/**"
- .prettierrc
- .prettierignore
- tsconfig.json
- oxlint.json
- "!**/*.md"
env:
BUN_VERSION: "canary"
jobs:
bun-plugin-svelte:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: |
bun install
pushd ./packages/bun-plugin-svelte && bun install
- name: Lint
run: |
bunx oxlint@0.15 --format github --deny-warnings
bunx prettier --config ../../.prettierrc --check .
working-directory: ./packages/bun-plugin-svelte
- name: Check types
run: bun check:types
working-directory: ./packages/bun-plugin-svelte
- name: Test
run: bun test
working-directory: ./packages/bun-plugin-svelte

View File

@@ -70,7 +70,7 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: "1.2.0"
bun-version: "1.2.3"
- name: Install Dependencies
run: bun install
- name: Sign Release
@@ -98,7 +98,7 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: "1.2.0"
bun-version: "1.2.3"
- name: Install Dependencies
run: bun install
- name: Release
@@ -127,7 +127,7 @@ jobs:
if: ${{ env.BUN_VERSION != 'canary' }}
uses: ./.github/actions/setup-bun
with:
bun-version: "1.2.0"
bun-version: "1.2.3"
- name: Setup Bun
if: ${{ env.BUN_VERSION == 'canary' }}
uses: ./.github/actions/setup-bun
@@ -167,12 +167,16 @@ jobs:
permissions:
contents: read
steps:
- name: Checkout
- name: Checkout (DefinitelyTyped)
uses: actions/checkout@v4
with:
repository: DefinitelyTyped/DefinitelyTyped
- name: Checkout (bun)
uses: actions/checkout@v4
with:
path: bun
- name: Setup Bun
uses: ./.github/actions/setup-bun
uses: ./bun/.github/actions/setup-bun
with:
bun-version: "1.2.0"
- id: bun-version
@@ -227,7 +231,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker emulator
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- id: buildx
name: Setup Docker buildx
uses: docker/setup-buildx-action@v3
@@ -235,7 +239,7 @@ jobs:
platforms: linux/amd64,linux/arm64
- id: metadata
name: Setup Docker metadata
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: oven/bun
flavor: |
@@ -252,7 +256,7 @@ jobs:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push to Docker
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: ./dockerhub/${{ matrix.dir || matrix.variant }}
platforms: linux/amd64,linux/arm64

View File

@@ -3,7 +3,6 @@ name: Lint
permissions:
contents: read
env:
LLVM_VERSION: 16
BUN_VERSION: "1.2.0"
on:

View File

@@ -89,4 +89,6 @@ jobs:
Updates c-ares to version ${{ steps.check-version.outputs.tag }}
Compare: https://github.com/c-ares/c-ares/compare/${{ steps.check-version.outputs.current }}...${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-cares.yml)

View File

@@ -89,4 +89,6 @@ jobs:
Updates libarchive to version ${{ steps.check-version.outputs.tag }}
Compare: https://github.com/libarchive/libarchive/compare/${{ steps.check-version.outputs.current }}...${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-libarchive.yml)

View File

@@ -89,4 +89,6 @@ jobs:
Updates libdeflate to version ${{ steps.check-version.outputs.tag }}
Compare: https://github.com/ebiggers/libdeflate/compare/${{ steps.check-version.outputs.current }}...${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-libdeflate.yml)

View File

@@ -89,4 +89,6 @@ jobs:
Updates lolhtml to version ${{ steps.check-version.outputs.tag }}
Compare: https://github.com/cloudflare/lol-html/compare/${{ steps.check-version.outputs.current }}...${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-lolhtml.yml)

View File

@@ -89,4 +89,6 @@ jobs:
Updates lshpack to version ${{ steps.check-version.outputs.tag }}
Compare: https://github.com/litespeedtech/ls-hpack/compare/${{ steps.check-version.outputs.current }}...${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-lshpack.yml)

82
.github/workflows/update-root-certs.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: Daily Root Certs Update Check
on:
schedule:
- cron: "0 0 * * *" # Runs at 00:00 UTC every day
workflow_dispatch: # Allows manual trigger
jobs:
check-and-update:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Generate root certs and capture output
id: generate-certs
run: |
cd packages/bun-usockets/
OUTPUT=$(bun generate-root-certs.mjs -v)
echo "cert_output<<EOF" >> $GITHUB_ENV
echo "$OUTPUT" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Check for changes and stage files
id: check-changes
run: |
if [[ -n "$(git status --porcelain)" ]]; then
echo "Found changes, staging modified files..."
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Get list of modified files and add them
git status --porcelain | while read -r status file; do
# Remove leading status and whitespace
file=$(echo "$file" | sed 's/^.* //')
echo "Adding changed file: $file"
git add "$file"
done
echo "changes=true" >> $GITHUB_OUTPUT
# Store the list of changed files
CHANGED_FILES=$(git status --porcelain)
echo "changed_files<<EOF" >> $GITHUB_ENV
echo "$CHANGED_FILES" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
else
echo "No changes detected"
echo "changes=false" >> $GITHUB_OUTPUT
fi
- name: Create Pull Request
if: steps.check-changes.outputs.changes == 'true'
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "update(root_certs): Update root certificates $(date +'%Y-%m-%d')"
title: "update(root_certs) $(date +'%Y-%m-%d')"
body: |
Automated root certificates update
${{ env.cert_output }}
## Changed Files:
```
${{ env.changed_files }}
```
branch: certs/update-root-certs-${{ github.run_number }}
base: main
delete-branch: true
labels:
- "automation"
- "root-certs"

View File

@@ -106,4 +106,6 @@ jobs:
Updates SQLite to version ${{ steps.check-version.outputs.latest }}
Compare: https://sqlite.org/src/vdiff?from=${{ steps.check-version.outputs.current }}&to=${{ steps.check-version.outputs.latest }}
Auto-updated by [this workflow](https://github.com/oven-sh/bun/actions/workflows/update-sqlite3.yml)

2
.gitignore vendored
View File

@@ -181,3 +181,5 @@ tmp
.buildkite/ci.yml
*.sock
scratch*.{js,ts,tsx,cjs,mjs}
*.bun-build

View File

@@ -1,4 +1,16 @@
# command script import vendor/zig/tools/lldb_pretty_printers.py
command script import vendor/WebKit/Tools/lldb/lldb_webkit.py
# Tell LLDB what to do when the debugged process receives SIGPWR: pass it through to the process
# (-p), but do not stop the process (-s) or notify the user (-n).
#
# JSC's garbage collector sends this signal (as configured by Bun WebKit in
# Thread::initializePlatformThreading() in ThreadingPOSIX.cpp) to the JS thread to suspend or resume
# it. So stopping the process would just create noise when debugging any long-running script.
process handle -p true -s false -n false SIGPWR
# type summary add --summary-string "${var} | inner=${var[0-30]}, source=${var[33-64]}, tag=${var[31-32]}" "unsigned long"
command script import misctools/lldb/lldb_pretty_printers.py
type category enable zig.lang
type category enable zig.std
command script import misctools/lldb/lldb_webkit.py
command script delete btjs
command alias btjs p {printf("gathering btjs trace...\n");printf("%s\n", (char*)dumpBtjsTrace())}

47
.vscode/launch.json generated vendored
View File

@@ -22,7 +22,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -38,7 +37,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -60,7 +58,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -76,7 +73,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -92,7 +88,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -108,7 +103,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -125,7 +119,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -147,7 +140,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -169,7 +161,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -188,7 +179,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -203,7 +193,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -221,7 +210,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -236,7 +224,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -253,7 +240,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -275,7 +261,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -297,7 +282,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -313,7 +297,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -329,7 +312,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -345,7 +327,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -361,7 +342,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -378,7 +358,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -400,7 +379,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -421,7 +399,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
// bun test [*]
{
@@ -437,7 +414,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -452,7 +428,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -468,7 +443,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
"serverReadyAction": {
"pattern": "https://debug.bun.sh/#localhost:([0-9]+)/",
"uriFormat": "https://debug.bun.sh/#ws://localhost:%s/",
@@ -488,7 +462,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "lldb",
@@ -503,7 +476,6 @@
},
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
// Windows: bun test [file]
{
@@ -1129,7 +1101,24 @@
],
"console": "internalConsole",
// Don't pause when the GC runs while the debugger is open.
"postRunCommands": ["command source '${workspaceFolder}/misctools/lldb/lldb_commands'"],
},
{
"type": "bun",
"name": "[JS] bun test [file]",
"runtime": "${workspaceFolder}/build/debug/bun-debug",
"runtimeArgs": ["test", "${file}"],
"cwd": "${workspaceFolder}",
"env": {
"BUN_DEBUG_QUIET_LOGS": "1",
"BUN_GARBAGE_COLLECTOR_LEVEL": "2",
},
},
{
"type": "midas-rr",
"request": "attach",
"name": "rr",
"trace": "Off",
"setupCommands": ["handle SIGPWR nostop noprint pass"],
},
],
"inputs": [

View File

@@ -36,6 +36,7 @@
// "zig.buildOnSave": true,
"zig.buildFilePath": "${workspaceFolder}/build.zig",
"zig.path": "${workspaceFolder}/vendor/zig/zig.exe",
"zig.zls.path": "${workspaceFolder}/vendor/zig/zls.exe",
"zig.formattingProvider": "zls",
"zig.zls.enableInlayHints": false,
"[zig]": {
@@ -140,9 +141,11 @@
"packages/bun-uws/fuzzing": true,
},
"files.associations": {
"*.css": "tailwindcss",
"*.idl": "cpp",
"*.mdc": "markdown",
"array": "cpp",
"ios": "cpp",
},
"C_Cpp.files.exclude": {
"**/.vscode": true,

View File

@@ -67,7 +67,7 @@ $ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 18 all
```
```bash#Arch
$ sudo pacman -S llvm clang lld
$ sudo pacman -S llvm clang18 lld
```
```bash#Fedora
@@ -80,7 +80,7 @@ $ sudo zypper install clang18 lld18 llvm18
{% /codetabs %}
If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.8).
If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.7).
Make sure Clang/LLVM 18 is in your path:
@@ -205,18 +205,30 @@ WebKit is not cloned by default (to save time and disk space). To clone and buil
# Clone WebKit into ./vendor/WebKit
$ git clone https://github.com/oven-sh/WebKit vendor/WebKit
# Check out the commit hash specified in `set(WEBKIT_VERSION <commit_hash>)` in cmake/tools/SetupWebKit.cmake
$ git -C vendor/WebKit checkout <commit_hash>
# Make a debug build of JSC. This will output build artifacts in ./vendor/WebKit/WebKitBuild/Debug
# Optionally, you can use `make jsc` for a release build
$ make jsc-debug
$ make jsc-debug && rm vendor/WebKit/WebKitBuild/Debug/JavaScriptCore/DerivedSources/inspector/InspectorProtocolObjects.h
# Build bun with the local JSC build
$ bun run build:local
```
Using `bun run build:local` will build Bun in the `./build/debug-local` directory (instead of `./build/debug`), you'll have to change a couple of places to use this new directory:
- The first line in [`src/js/builtins.d.ts`](/src/js/builtins.d.ts)
- The `CompilationDatabase` line in [`.clangd` config](/.clangd) should be `CompilationDatabase: build/debug-local`
- In [`build.zig`](/build.zig), the `codegen_path` option should be `build/debug-local/codegen` (instead of `build/debug/codegen`)
- In [`.vscode/launch.json`](/.vscode/launch.json), many configurations use `./build/debug/`, change them as you see fit
Note that the WebKit folder, including build artifacts, is 8GB+ in size.
If you are using a JSC debug build and using VScode, make sure to run the `C/C++: Select a Configuration` command to configure intellisense to find the debug headers.
Note that if you change make changes to our [WebKit fork](https://github.com/oven-sh/WebKit), you will also have to change [`SetupWebKit.cmake`](/cmake/tools/SetupWebKit.cmake) to point to the commit hash.
## Troubleshooting
### 'span' file not found on Ubuntu

2
LATEST
View File

@@ -1 +1 @@
1.2.2
1.2.5

View File

@@ -91,9 +91,9 @@ ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make
# This is easier to happen than you'd expect.
# Using realpath here causes issues because clang uses clang++ as a symlink
# so if that's resolved, it won't build for C++
REAL_CC = $(shell which clang-18 2>/dev/null || which clang 2>/dev/null)
REAL_CXX = $(shell which clang++-18 2>/dev/null || which clang++ 2>/dev/null)
CLANG_FORMAT = $(shell which clang-format-18 2>/dev/null || which clang-format 2>/dev/null)
REAL_CC = $(shell which clang-19 2>/dev/null || which clang 2>/dev/null)
REAL_CXX = $(shell which clang++-19 2>/dev/null || which clang++ 2>/dev/null)
CLANG_FORMAT = $(shell which clang-format-19 2>/dev/null || which clang-format 2>/dev/null)
CC = $(REAL_CC)
CXX = $(REAL_CXX)
@@ -117,14 +117,14 @@ CC_WITH_CCACHE = $(CCACHE_PATH) $(CC)
ifeq ($(OS_NAME),darwin)
# Find LLVM
ifeq ($(wildcard $(LLVM_PREFIX)),)
LLVM_PREFIX = $(shell brew --prefix llvm@18)
LLVM_PREFIX = $(shell brew --prefix llvm@19)
endif
ifeq ($(wildcard $(LLVM_PREFIX)),)
LLVM_PREFIX = $(shell brew --prefix llvm)
endif
ifeq ($(wildcard $(LLVM_PREFIX)),)
# This is kinda ugly, but I can't find a better way to error :(
LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@18' or set LLVM_PREFIX=/path/to/llvm")
LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@19' or set LLVM_PREFIX=/path/to/llvm")
endif
LDFLAGS += -L$(LLVM_PREFIX)/lib
@@ -164,7 +164,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \
-DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \
$(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \
-DCMAKE_AR=$(AR) \
-DCMAKE_RANLIB=$(which llvm-18-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
-DCMAKE_RANLIB=$(which llvm-19-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
-DCMAKE_CXX_STANDARD=20 \
-DCMAKE_C_STANDARD=17 \
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
@@ -191,7 +191,7 @@ endif
ifeq ($(OS_NAME),linux)
LIBICONV_PATH =
AR = $(shell which llvm-ar-18 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
AR = $(shell which llvm-ar-19 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
endif
OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE)
@@ -255,7 +255,7 @@ DEFAULT_LINKER_FLAGS= -pthread -ldl
endif
ifeq ($(OS_NAME),darwin)
_MIMALLOC_OBJECT_FILE = 0
JSC_BUILD_STEPS += jsc-build-mac jsc-copy-headers
JSC_BUILD_STEPS += jsc-build-mac
JSC_BUILD_STEPS_DEBUG += jsc-build-mac-debug
_MIMALLOC_FILE = libmimalloc.a
_MIMALLOC_INPUT_PATH = libmimalloc.a
@@ -286,7 +286,7 @@ STRIP=/usr/bin/strip
endif
ifeq ($(OS_NAME),linux)
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-18 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-19 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
endif
@@ -674,7 +674,7 @@ endif
.PHONY: assert-deps
assert-deps:
@echo "Checking if the required utilities are available..."
@if [ $(CLANG_VERSION) -lt "18" ]; then echo -e "ERROR: clang version >=18 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@18"; exit 1; fi
@if [ $(CLANG_VERSION) -lt "19" ]; then echo -e "ERROR: clang version >=19 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@19"; exit 1; fi
@cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1)
@$(PYTHON) --version >/dev/null 2>&1 || (echo -e "ERROR: python is required."; exit 1)
@$(ESBUILD) --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild is required."; exit 1)
@@ -924,7 +924,7 @@ bun-codesign-release-local-debug:
.PHONY: jsc
jsc: jsc-build jsc-copy-headers jsc-bindings
jsc: jsc-build
.PHONY: jsc-debug
jsc-debug: jsc-build-debug
.PHONY: jsc-build
@@ -1154,7 +1154,7 @@ jsc-copy-headers:
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/StubInfoSummary.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/StubInfoSummary.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/CommonSlowPaths.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/CommonSlowPaths.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/DirectArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/DirectArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/GenericArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/GenericArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/GenericArgumentsImpl.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/GenericArgumentsImpl.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/SamplingProfiler.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/SamplingProfiler.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/ScopedArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/ScopedArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSLexicalEnvironment.h
@@ -1205,7 +1205,7 @@ jsc-copy-headers-debug:
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/StubInfoSummary.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/StubInfoSummary.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/CommonSlowPaths.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/CommonSlowPaths.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/DirectArguments.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/DirectArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/GenericArguments.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/GenericArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/GenericArgumentsImpl.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/GenericArgumentsImpl.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/SamplingProfiler.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/SamplingProfiler.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/ScopedArguments.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/ScopedArguments.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h $(WEBKIT_DEBUG_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSLexicalEnvironment.h

View File

@@ -0,0 +1,53 @@
import crypto from "node:crypto";
import { bench, run } from "../runner.mjs";
// Pre-generate DH params to avoid including setup in benchmarks
const dhSize = 1024; // Reduced from 2048 for faster testing
const dh = crypto.createDiffieHellman(dhSize);
const dhPrime = dh.getPrime();
const dhGenerator = dh.getGenerator();
// Classical Diffie-Hellman
bench("DH - generateKeys", () => {
const alice = crypto.createDiffieHellman(dhPrime, dhGenerator);
return alice.generateKeys();
});
bench("DH - computeSecret", () => {
// Setup
const alice = crypto.createDiffieHellman(dhPrime, dhGenerator);
const aliceKey = alice.generateKeys();
const bob = crypto.createDiffieHellman(dhPrime, dhGenerator);
const bobKey = bob.generateKeys();
// Benchmark just the secret computation
return alice.computeSecret(bobKey);
});
// ECDH with prime256v1 (P-256)
bench("ECDH-P256 - generateKeys", () => {
const ecdh = crypto.createECDH("prime256v1");
return ecdh.generateKeys();
});
bench("ECDH-P256 - computeSecret", () => {
// Setup
const alice = crypto.createECDH("prime256v1");
const aliceKey = alice.generateKeys();
const bob = crypto.createECDH("prime256v1");
const bobKey = bob.generateKeys();
// Benchmark just the secret computation
return alice.computeSecret(bobKey);
});
// ECDH with secp384r1 (P-384)
bench("ECDH-P384 - computeSecret", () => {
const alice = crypto.createECDH("secp384r1");
const aliceKey = alice.generateKeys();
const bob = crypto.createECDH("secp384r1");
const bobKey = bob.generateKeys();
return alice.computeSecret(bobKey);
});
await run();

View File

@@ -0,0 +1,44 @@
import crypto from "node:crypto";
import { bench, run } from "../runner.mjs";
function generateTestKeyPairs() {
const curves = crypto.getCurves();
const keys = {};
for (const curve of curves) {
const ecdh = crypto.createECDH(curve);
ecdh.generateKeys();
keys[curve] = {
compressed: ecdh.getPublicKey("hex", "compressed"),
uncompressed: ecdh.getPublicKey("hex", "uncompressed"),
instance: ecdh,
};
}
return keys;
}
const testKeys = generateTestKeyPairs();
bench("ECDH key format - P256 compressed to uncompressed", () => {
const publicKey = testKeys["prime256v1"].compressed;
return crypto.ECDH.convertKey(publicKey, "prime256v1", "hex", "hex", "uncompressed");
});
bench("ECDH key format - P256 uncompressed to compressed", () => {
const publicKey = testKeys["prime256v1"].uncompressed;
return crypto.ECDH.convertKey(publicKey, "prime256v1", "hex", "hex", "compressed");
});
bench("ECDH key format - P384 compressed to uncompressed", () => {
const publicKey = testKeys["secp384r1"].compressed;
return crypto.ECDH.convertKey(publicKey, "secp384r1", "hex", "hex", "uncompressed");
});
bench("ECDH key format - P384 uncompressed to compressed", () => {
const publicKey = testKeys["secp384r1"].uncompressed;
return crypto.ECDH.convertKey(publicKey, "secp384r1", "hex", "hex", "compressed");
});
await run();

50
bench/crypto/hkdf.mjs Normal file
View File

@@ -0,0 +1,50 @@
import crypto from "node:crypto";
import { bench, run } from "../runner.mjs";
// Sample keys with different lengths
const keys = {
short: "secret",
long: "this-is-a-much-longer-secret-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
};
// Test parameters
const salts = ["", "salt"];
const infos = ["", "info"];
const hashes = ["sha256", "sha512"];
const sizes = [10, 1024];
// Benchmark sync HKDF
for (const hash of hashes) {
for (const keyName of Object.keys(keys)) {
const key = keys[keyName];
for (const size of sizes) {
bench(`hkdfSync ${hash} ${keyName}-key ${size} bytes`, () => {
return crypto.hkdfSync(hash, key, "salt", "info", size);
});
}
}
}
// Benchmark different combinations of salt and info
for (const salt of salts) {
for (const info of infos) {
bench(`hkdfSync sha256 with ${salt ? "salt" : "no-salt"} and ${info ? "info" : "no-info"}`, () => {
return crypto.hkdfSync("sha256", "secret", salt, info, 64);
});
}
}
// Benchmark async HKDF (using promises for cleaner benchmark)
// Note: async benchmarks in Mitata require returning a Promise
for (const hash of hashes) {
bench(`hkdf ${hash} async`, async () => {
return new Promise((resolve, reject) => {
crypto.hkdf(hash, "secret", "salt", "info", 64, (err, derivedKey) => {
if (err) reject(err);
else resolve(derivedKey);
});
});
});
}
await run();

43
bench/crypto/primes.mjs Normal file
View File

@@ -0,0 +1,43 @@
import { checkPrime, checkPrimeSync, generatePrime, generatePrimeSync } from "node:crypto";
import { bench, run } from "../runner.mjs";
const prime512 = generatePrimeSync(512);
const prime2048 = generatePrimeSync(2048);
bench("checkPrimeSync 512", () => {
return checkPrimeSync(prime512);
});
bench("checkPrimeSync 2048", () => {
return checkPrimeSync(prime2048);
});
bench("checkPrime 512", async () => {
const promises = Array.from({ length: 10 }, () => new Promise(resolve => checkPrime(prime512, resolve)));
await Promise.all(promises);
});
bench("checkPrime 2048", async () => {
const promises = Array.from({ length: 10 }, () => new Promise(resolve => checkPrime(prime2048, resolve)));
await Promise.all(promises);
});
bench("generatePrimeSync 512", () => {
return generatePrimeSync(512);
});
bench("generatePrimeSync 2048", () => {
return generatePrimeSync(2048);
});
bench("generatePrime 512", async () => {
const promises = Array.from({ length: 10 }, () => new Promise(resolve => generatePrime(512, resolve)));
await Promise.all(promises);
});
bench("generatePrime 2048", async () => {
const promises = Array.from({ length: 10 }, () => new Promise(resolve => generatePrime(2048, resolve)));
await Promise.all(promises);
});
await run();

50
bench/crypto/random.mjs Normal file
View File

@@ -0,0 +1,50 @@
import crypto from "crypto";
import { bench, run } from "../runner.mjs";
bench("randomInt - sync", () => {
crypto.randomInt(1000);
});
bench("randomInt - async", async () => {
const { promise, resolve } = Promise.withResolvers();
crypto.randomInt(1000, () => {
resolve();
});
await promise;
});
bench("randonBytes - 32", () => {
crypto.randomBytes(32);
});
bench("randomBytes - 256", () => {
crypto.randomBytes(256);
});
const buf = Buffer.alloc(256);
bench("randomFill - 32", async () => {
const { promise, resolve } = Promise.withResolvers();
crypto.randomFill(buf, 0, 32, () => {
resolve();
});
await promise;
});
bench("randomFill - 256", async () => {
const { promise, resolve } = Promise.withResolvers();
crypto.randomFill(buf, 0, 256, () => {
resolve();
});
await promise;
});
bench("randomFillSync - 32", () => {
crypto.randomFillSync(buf, 0, 32);
});
bench("randomFillSync - 256", () => {
crypto.randomFillSync(buf, 0, 256);
});
await run();

View File

@@ -1,19 +1,27 @@
import micromatch from "micromatch";
import { Glob } from "bun";
import { bench, run } from "../runner.mjs";
const Glob = typeof Bun !== "undefined" ? Bun.Glob : undefined;
const doMatch = typeof Bun === "undefined" ? micromatch.isMatch : (a, b) => new Glob(b).match(a);
bench((Glob ? "Bun.Glob - " : "micromatch - ") + "**/*.js", () => {
doMatch("foo/bar.js", "**/*.js");
});
function benchPattern(name, glob, pattern) {
bench(name, () => {
new Glob(glob).match(pattern);
})
}
benchPattern("max-depth" , "1{2,3{4,5{6,7{8,9{a,b{c,d{e,f{g,h{i,j{k,l}}}}}}}}}}m", "13579bdfhjlm");
benchPattern("non-ascii", "😎/¢£.{ts,tsx,js,jsx}", "😎/¢£.jsx");
benchPattern("utf8", "フォルダ/**/*", "フォルダ/aaa.js");
benchPattern("non-ascii+max-depth" , "1{2,3{4,5{6,7{8,😎{a,b{c,d{e,f{g,h{i,j{k,l}}}}}}}}}}m", "1357😎bdfhjlm");
benchPattern("pretty-average", "test/{foo/**,bar}/baz", "test/bar/baz");
benchPattern("pretty-average-2", "a/**/c/*.md", "a/bb.bb/aa/b.b/aa/c/xyz.md");
benchPattern("pretty-average-3", "a/b/**/c{d,e}/**/xyz.md", "a/b/cd/xyz.md");
benchPattern("pretty-average-4", "foo/bar/**/one/**/*.*", "foo/bar/baz/one/two/three/image.png");
benchPattern("long-pretty-average", "some/**/needle.{js,tsx,mdx,ts,jsx,txt}", "some/a/bigger/path/to/the/crazy/needle.txt");
benchPattern("brackets-lots", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", "foo-bar");
bench((Glob ? "Bun.Glob - " : "micromatch - ") + "*.js", () => {
doMatch("bar.js", "*.js");
});
await run({
avg: true,
min_max: true,
percentiles: true,
});
min_max: true,
percentiles: true,
avg: true,
})

19
bench/glob/micromatch.mjs Normal file
View File

@@ -0,0 +1,19 @@
import micromatch from "micromatch";
import { bench, run } from "../runner.mjs";
const Glob = typeof Bun !== "undefined" ? Bun.Glob : undefined;
const doMatch = typeof Bun === "undefined" ? micromatch.isMatch : (a, b) => new Glob(b).match(a);
bench((Glob ? "Bun.Glob - " : "micromatch - ") + "**/*.js", () => {
doMatch("foo/bar.js", "**/*.js");
});
bench((Glob ? "Bun.Glob - " : "micromatch - ") + "*.js", () => {
doMatch("bar.js", "*.js");
});
await run({
avg: true,
min_max: true,
percentiles: true,
});

View File

@@ -12,6 +12,7 @@
"eventemitter3": "^5.0.0",
"execa": "^8.0.1",
"fast-glob": "3.3.1",
"fastify": "^5.0.0",
"fdir": "^6.1.0",
"mitata": "^1.0.25",
"react": "^18.3.1",

View File

@@ -0,0 +1,17 @@
const buf = Buffer.from(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
);
const INTERVAL = 9_999_999;
const time = (name, fn) => {
for (let i = 0; i < INTERVAL; i++) fn();
console.time(name.padEnd(30));
for (let i = 0; i < INTERVAL; i++) fn();
console.timeEnd(name.padEnd(30));
};
console.log(`Run ${new Intl.NumberFormat().format(INTERVAL)} times with a warmup:`, "\n");
time("includes true", () => buf.includes("nisi"));
time("includes false", () => buf.includes("oopwo"));

71
bench/snippets/decode.js Normal file
View File

@@ -0,0 +1,71 @@
import { bench, run } from "../runner.mjs";
let decodeURIComponentSIMD;
if (typeof Bun !== "undefined") {
({ decodeURIComponentSIMD } = await import("bun:internal-for-testing"));
}
const hugeText = Buffer.alloc(1000000, "Hello, world!").toString();
const hugeTextWithPercentAtEnd = Buffer.alloc(1000000, "Hello, world!%40").toString();
const tinyText = Buffer.alloc(100, "Hello, world!").toString();
const tinyTextWithPercentAtEnd = Buffer.alloc(100, "Hello, world!%40").toString();
const veryTinyText = Buffer.alloc(8, "a").toString();
const veryTinyTextWithPercentAtEnd = Buffer.alloc(8, "a%40").toString();
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - no % x 8 bytes", () => {
decodeURIComponentSIMD(veryTinyText);
});
bench(" decodeURIComponent - no % x 8 bytes", () => {
decodeURIComponent(veryTinyText);
});
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - yes % x 8 bytes", () => {
decodeURIComponentSIMD(veryTinyTextWithPercentAtEnd);
});
bench(" decodeURIComponent - yes % x 8 bytes", () => {
decodeURIComponent(veryTinyTextWithPercentAtEnd);
});
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - no % x 100 bytes", () => {
decodeURIComponentSIMD(tinyText);
});
bench(" decodeURIComponent - no % x 100 bytes", () => {
decodeURIComponent(tinyText);
});
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - yes % x 100 bytes", () => {
decodeURIComponentSIMD(tinyTextWithPercentAtEnd);
});
bench(" decodeURIComponent - yes % x 100 bytes", () => {
decodeURIComponent(tinyTextWithPercentAtEnd);
});
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - no % x 1 MB", () => {
decodeURIComponentSIMD(hugeText);
});
bench(" decodeURIComponent - no % x 1 MB", () => {
decodeURIComponent(hugeText);
});
decodeURIComponentSIMD &&
bench("decodeURIComponentSIMD - yes % x 1 MB", () => {
decodeURIComponentSIMD(hugeTextWithPercentAtEnd);
});
bench(" decodeURIComponent - yes % x 1 MB", () => {
decodeURIComponent(hugeTextWithPercentAtEnd);
});
await run();

View File

@@ -0,0 +1,13 @@
import express from "express";
const app = express();
const port = 3000;
var i = 0;
app.get("/", (req, res) => {
res.send("Hello World!" + i++);
});
app.listen(port, () => {
console.log(`Express app listening at http://localhost:${port}`);
});

View File

@@ -0,0 +1,20 @@
import Fastify from "fastify";
const fastify = Fastify({
logger: false,
});
fastify.get("/", async (request, reply) => {
return { hello: "world" };
});
const start = async () => {
try {
await fastify.listen({ port: 3000 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();

View File

@@ -19,16 +19,17 @@ const OperatingSystem = @import("src/env.zig").OperatingSystem;
const pathRel = fs.path.relative;
/// Do not rename this constant. It is scanned by some scripts to determine which zig version to install.
const recommended_zig_version = "0.14.0-dev.2987+183bb8b08";
const recommended_zig_version = "0.14.0";
comptime {
if (!std.mem.eql(u8, builtin.zig_version_string, recommended_zig_version)) {
@compileError(
"" ++
"Bun requires Zig version " ++ recommended_zig_version ++ ". This is" ++
"automatically configured via Bun's CMake setup. You likely meant to run" ++
"`bun setup`. If you are trying to upgrade the Zig compiler," ++
"run `./scripts/download-zig.sh master` or comment this message out.",
"Bun requires Zig version " ++ recommended_zig_version ++ ", but you have " ++
builtin.zig_version_string ++ ". This is automatically configured via Bun's " ++
"CMake setup. You likely meant to run `bun run build`. If you are trying to " ++
"upgrade the Zig compiler, edit ZIG_COMMIT in cmake/tools/SetupZig.cmake or " ++
"comment this error out.",
);
}
}
@@ -318,7 +319,21 @@ pub fn build(b: *Build) !void {
.{ .os = .linux, .arch = .aarch64 },
.{ .os = .linux, .arch = .x86_64, .musl = true },
.{ .os = .linux, .arch = .aarch64, .musl = true },
});
}, &.{ .Debug, .ReleaseFast });
}
// zig build check-all-debug
{
const step = b.step("check-all-debug", "Check for semantic analysis errors on all supported platforms in debug mode");
addMultiCheck(b, step, build_options, &.{
.{ .os = .windows, .arch = .x86_64 },
.{ .os = .mac, .arch = .x86_64 },
.{ .os = .mac, .arch = .aarch64 },
.{ .os = .linux, .arch = .x86_64 },
.{ .os = .linux, .arch = .aarch64 },
.{ .os = .linux, .arch = .x86_64, .musl = true },
.{ .os = .linux, .arch = .aarch64, .musl = true },
}, &.{.Debug});
}
// zig build check-windows
@@ -326,21 +341,21 @@ pub fn build(b: *Build) !void {
const step = b.step("check-windows", "Check for semantic analysis errors on Windows");
addMultiCheck(b, step, build_options, &.{
.{ .os = .windows, .arch = .x86_64 },
});
}, &.{ .Debug, .ReleaseFast });
}
{
const step = b.step("check-macos", "Check for semantic analysis errors on Windows");
addMultiCheck(b, step, build_options, &.{
.{ .os = .mac, .arch = .x86_64 },
.{ .os = .mac, .arch = .aarch64 },
});
}, &.{ .Debug, .ReleaseFast });
}
{
const step = b.step("check-linux", "Check for semantic analysis errors on Windows");
addMultiCheck(b, step, build_options, &.{
.{ .os = .linux, .arch = .x86_64 },
.{ .os = .linux, .arch = .aarch64 },
});
}, &.{ .Debug, .ReleaseFast });
}
// zig build translate-c-headers
@@ -368,9 +383,10 @@ pub fn addMultiCheck(
parent_step: *Step,
root_build_options: BunBuildOptions,
to_check: []const struct { os: OperatingSystem, arch: Arch, musl: bool = false },
optimize: []const std.builtin.OptimizeMode,
) void {
for (to_check) |check| {
for ([_]std.builtin.Mode{ .Debug, .ReleaseFast }) |mode| {
for (optimize) |mode| {
const check_target = b.resolveTargetQuery(.{
.os_tag = OperatingSystem.stdOSTag(check.os),
.cpu_arch = check.arch,

View File

@@ -45,21 +45,21 @@
"packages": {
"@biomejs/biome": ["@biomejs/biome@1.8.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.8.3", "@biomejs/cli-darwin-x64": "1.8.3", "@biomejs/cli-linux-arm64": "1.8.3", "@biomejs/cli-linux-arm64-musl": "1.8.3", "@biomejs/cli-linux-x64": "1.8.3", "@biomejs/cli-linux-x64-musl": "1.8.3", "@biomejs/cli-win32-arm64": "1.8.3", "@biomejs/cli-win32-x64": "1.8.3" }, "bin": { "biome": "bin/biome" } }, "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.8.3", "", { "os":"darwin", "cpu":"arm64" }, "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.8.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.8.3", "", { "os":"darwin", "cpu":"x64" }, "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.8.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.8.3", "", { "os":"linux", "cpu":"arm64" }, "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.8.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.8.3", "", { "os":"linux", "cpu":"arm64" }, "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.8.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.8.3", "", { "os":"linux", "cpu":"x64" }, "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.8.3", "", { "os": "linux", "cpu": "x64" }, "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.8.3", "", { "os":"linux", "cpu":"x64" }, "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.8.3", "", { "os": "linux", "cpu": "x64" }, "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.8.3", "", { "os":"win32", "cpu":"arm64" }, "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.8.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.8.3", "", { "os":"win32", "cpu":"x64" }, "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.8.3", "", { "os": "win32", "cpu": "x64" }, "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg=="],
"@definitelytyped/dts-critic": ["@definitelytyped/dts-critic@0.0.191", "", { "dependencies": { "@definitelytyped/header-parser": "0.0.190", "command-exists": "^1.2.9", "semver": "^7.5.4", "tmp": "^0.2.1", "typescript": "^5.2.2", "yargs": "^17.7.2" } }, "sha512-j5HK3pQYiQwSXRLJzyhXJ6KxdzLl4gXXhz3ysCtLnRQkj+zsEfloDkEZ3x2bZMWS0OsKLXmR91JeQ2/c9DFEjg=="],
@@ -75,51 +75,51 @@
"@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.39.4", "", { "dependencies": { "comment-parser": "1.3.1", "esquery": "^1.5.0", "jsdoc-type-pratt-parser": "~4.0.0" } }, "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os":"aix", "cpu":"ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os":"android", "cpu":"arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os":"android", "cpu":"arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os":"android", "cpu":"x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os":"darwin", "cpu":"arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os":"darwin", "cpu":"x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os":"freebsd", "cpu":"arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os":"freebsd", "cpu":"x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os":"linux", "cpu":"arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os":"linux", "cpu":"arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os":"linux", "cpu":"ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os":"linux", "cpu":"ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os":"linux", "cpu":"none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os":"linux", "cpu":"s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os":"linux", "cpu":"x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os":"none", "cpu":"x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os":"openbsd", "cpu":"x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os":"sunos", "cpu":"x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os":"win32", "cpu":"arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os":"win32", "cpu":"ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os":"win32", "cpu":"x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.0", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA=="],
@@ -151,13 +151,13 @@
"@qiwi/npm-registry-client": ["@qiwi/npm-registry-client@8.9.1", "", { "dependencies": { "concat-stream": "^2.0.0", "graceful-fs": "^4.2.4", "normalize-package-data": "~1.0.1 || ^2.0.0 || ^3.0.0", "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^8.0.0", "once": "^1.4.0", "request": "^2.88.2", "retry": "^0.12.0", "safe-buffer": "^5.2.1", "semver": "2 >=2.2.1 || 3.x || 4 || 5 || 7", "slide": "^1.1.6", "ssri": "^8.0.0" }, "optionalDependencies": { "npmlog": "2 || ^3.1.0 || ^4.0.0" } }, "sha512-rZF+mG+NfijR0SHphhTLHRr4aM4gtfdwoAMY6we2VGQam8vkN1cxGG1Lg/Llrj8Dd0Mu6VjdFQRyMMRZxtZR2A=="],
"@types/bun": ["@types/bun@1.1.17", "", { "dependencies": { "bun-types": "1.1.44" } }, "sha512-zZt0Kao/8hAwNOXh4bmt8nKbMEd4QD8n7PeTGF+NZTVY5ouXhU/TX7jUj4He1p7mgY+WdplnU1B6MB1j17vdzg=="],
"@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
"@types/node": ["@types/node@22.10.7", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg=="],
"@types/node": ["@types/node@22.13.5", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg=="],
"@types/prop-types": ["@types/prop-types@15.7.12", "", {}, "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="],

View File

@@ -2,3 +2,7 @@
# https://github.com/oven-sh/bun/issues/16289
[test]
preload = ["./test/js/node/harness.ts", "./test/preload.ts"]
[install]
# Node.js never auto-installs modules.
auto = "disable"

View File

@@ -1,84 +0,0 @@
# CI
This directory contains scripts for building CI images for Bun.
## Building
### `macOS`
On macOS, images are built using [`tart`](https://tart.run/), a tool that abstracts over the [`Virtualization.Framework`](https://developer.apple.com/documentation/virtualization) APIs, to run macOS VMs.
To install the dependencies required, run:
```sh
$ cd ci
$ bun run bootstrap
```
To build a vanilla macOS VM, run:
```sh
$ bun run build:darwin-aarch64-vanilla
```
This builds a vanilla macOS VM with the current macOS release on your machine. It runs scripts to disable things like spotlight and siri, but it does not install any software.
> Note: The image size is 50GB, so make sure you have enough disk space.
If you want to build a specific macOS release, you can run:
```sh
$ bun run build:darwin-aarch64-vanilla-15
```
> Note: You cannot build a newer release of macOS on an older macOS machine.
To build a macOS VM with software installed to build and test Bun, run:
```sh
$ bun run build:darwin-aarch64
```
## Running
### `macOS`
## How To
### Support a new macOS release
1. Visit [`ipsw.me`](https://ipsw.me/VirtualMac2,1) and find the IPSW of the macOS release you want to build.
2. Add an entry to [`ci/darwin/variables.pkr.hcl`](/ci/darwin/variables.pkr.hcl) with the following format:
```hcl
sonoma = {
distro = "sonoma"
release = "15"
ipsw = "https://updates.cdn-apple.com/..."
}
```
3. Add matching scripts to [`ci/package.json`](/ci/package.json) to build the image, then test it:
```sh
$ bun run build:darwin-aarch64-vanilla-15
```
> Note: If you need to troubleshoot the build, you can remove the `headless = true` property from [`ci/darwin/image-vanilla.pkr.hcl`](/ci/darwin/image-vanilla.pkr.hcl) and the VM's screen will be displayed.
4. Test and build the non-vanilla image:
```sh
$ bun run build:darwin-aarch64-15
```
This will use the vanilla image and run the [`scripts/bootstrap.sh`](/scripts/bootstrap.sh) script to install the required software to build and test Bun.
5. Publish the images:
```sh
$ bun run login
$ bun run publish:darwin-aarch64-vanilla-15
$ bun run publish:darwin-aarch64-15
```

View File

@@ -1,22 +0,0 @@
FROM alpine:edge AS build
ARG GIT_SHA
ENV GIT_SHA=${GIT_SHA}
WORKDIR /app/bun
ENV HOME=/root
COPY . .
RUN touch $HOME/.bashrc
RUN ./scripts/bootstrap.sh
RUN . $HOME/.bashrc && bun run build:release
RUN apk add file
RUN file ./build/release/bun
RUN ldd ./build/release/bun
RUN ./build/release/bun
RUN cp -R /app/bun/build/* /output
FROM scratch AS artifact
COPY --from=build /output /
# docker build -f ./ci/alpine/build.Dockerfile --progress=plain --build-arg GIT_SHA="$(git rev-parse HEAD)" --target=artifact --output type=local,dest=./build-alpine .

View File

@@ -1,20 +0,0 @@
FROM alpine:edge
ENV HOME=/root
WORKDIR /root
COPY ./build-alpine/release/bun .
COPY ./test ./test
COPY ./scripts ./scripts
COPY ./package.json ./package.json
COPY ./packages ./packages
RUN apk update
RUN apk add nodejs lsb-release-minimal git python3 npm make g++
RUN apk add file
RUN file /root/bun
RUN ldd /root/bun
RUN /root/bun
RUN ./scripts/runner.node.mjs --exec-path /root/bun
# docker build -f ./ci/alpine/test.Dockerfile --progress=plain .

View File

@@ -1,46 +0,0 @@
# Generates a vanilla macOS VM with optimized settings for virtualized environments.
# See login.sh and optimize.sh for details.
data "external-raw" "boot-script" {
program = ["sh", "-c", templatefile("scripts/boot-image.sh", var)]
}
source "tart-cli" "bun-darwin-aarch64-vanilla" {
vm_name = "bun-darwin-aarch64-vanilla-${local.release.distro}-${local.release.release}"
from_ipsw = local.release.ipsw
cpu_count = local.cpu_count
memory_gb = local.memory_gb
disk_size_gb = local.disk_size_gb
ssh_username = local.username
ssh_password = local.password
ssh_timeout = "120s"
create_grace_time = "30s"
boot_command = split("\n", data.external-raw.boot-script.result)
headless = true # Disable if you need to debug why the boot_command is not working
}
build {
sources = ["source.tart-cli.bun-darwin-aarch64-vanilla"]
provisioner "file" {
content = file("scripts/setup-login.sh")
destination = "/tmp/setup-login.sh"
}
provisioner "shell" {
inline = ["echo \"${local.password}\" | sudo -S sh -c 'sh /tmp/setup-login.sh \"${local.username}\" \"${local.password}\"'"]
}
provisioner "file" {
content = file("scripts/optimize-machine.sh")
destination = "/tmp/optimize-machine.sh"
}
provisioner "shell" {
inline = ["sudo sh /tmp/optimize-machine.sh"]
}
provisioner "shell" {
inline = ["sudo rm -rf /tmp/*"]
}
}

View File

@@ -1,44 +0,0 @@
# Generates a macOS VM with software installed to build and test Bun.
source "tart-cli" "bun-darwin-aarch64" {
vm_name = "bun-darwin-aarch64-${local.release.distro}-${local.release.release}"
vm_base_name = "bun-darwin-aarch64-vanilla-${local.release.distro}-${local.release.release}"
cpu_count = local.cpu_count
memory_gb = local.memory_gb
disk_size_gb = local.disk_size_gb
ssh_username = local.username
ssh_password = local.password
ssh_timeout = "120s"
headless = true
}
build {
sources = ["source.tart-cli.bun-darwin-aarch64"]
provisioner "file" {
content = file("../../scripts/bootstrap.sh")
destination = "/tmp/bootstrap.sh"
}
provisioner "shell" {
inline = ["CI=true sh /tmp/bootstrap.sh"]
}
provisioner "file" {
source = "darwin/plists/"
destination = "/tmp/"
}
provisioner "shell" {
inline = [
"sudo ls /tmp/",
"sudo mv /tmp/*.plist /Library/LaunchDaemons/",
"sudo chown root:wheel /Library/LaunchDaemons/*.plist",
"sudo chmod 644 /Library/LaunchDaemons/*.plist",
]
}
provisioner "shell" {
inline = ["sudo rm -rf /tmp/*"]
}
}

View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.buildkite.buildkite-agent</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/buildkite-agent</string>
<string>start</string>
</array>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false />
</dict>
<key>RunAtLoad</key>
<true />
<key>StandardOutPath</key>
<string>/var/buildkite-agent/logs/buildkite-agent.log</string>
<key>StandardErrorPath</key>
<string>/var/buildkite-agent/logs/buildkite-agent.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>BUILDKITE_AGENT_CONFIG</key>
<string>/etc/buildkite-agent/buildkite-agent.cfg</string>
</dict>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
<string>LoginWindow</string>
<string>Background</string>
<string>StandardIO</string>
<string>System</string>
</array>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.tailscale.tailscaled</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/tailscale</string>
<string>up</string>
<string>--ssh</string>
<string>--authkey</string>
<string>${TAILSCALE_AUTHKEY}</string>
</array>
<key>RunAtLoad</key>
<true />
</dict>
</plist>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.tailscale.tailscaled</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/tailscaled</string>
</array>
<key>RunAtLoad</key>
<true />
</dict>
</plist>

View File

@@ -1,124 +0,0 @@
#!/bin/sh
# This script generates the boot commands for the macOS installer GUI.
# It is run on your local machine, not inside the VM.
# Sources:
# - https://github.com/cirruslabs/macos-image-templates/blob/master/templates/vanilla-sequoia.pkr.hcl
if ! [ "${release}" ] || ! [ "${username}" ] || ! [ "${password}" ]; then
echo "Script must be run with variables: release, username, and password" >&2
exit 1
fi
# Hello, hola, bonjour, etc.
echo "<wait120s><spacebar>"
# Select Your Country and Region
echo "<wait30s>italiano<esc>english<enter>"
echo "<wait30s>united states<leftShiftOn><tab><leftShiftOff><spacebar>"
# Written and Spoken Languages
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
# Accessibility
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
# Data & Privacy
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
# Migration Assistant
echo "<wait30s><tab><tab><tab><spacebar>"
# Sign In with Your Apple ID
echo "<wait30s><leftShiftOn><tab><leftShiftOff><leftShiftOn><tab><leftShiftOff><spacebar>"
# Are you sure you want to skip signing in with an Apple ID?
echo "<wait30s><tab><spacebar>"
# Terms and Conditions
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
# I have read and agree to the macOS Software License Agreement
echo "<wait30s><tab><spacebar>"
# Create a Computer Account
echo "<wait30s>${username}<tab><tab>${password}<tab>${password}<tab><tab><tab><spacebar>"
# Enable Location Services
echo "<wait60s><leftShiftOn><tab><leftShiftOff><spacebar>"
# Are you sure you don't want to use Location Services?
echo "<wait30s><tab><spacebar>"
# Select Your Time Zone
echo "<wait30s><tab>UTC<enter><leftShiftOn><tab><leftShiftOff><spacebar>"
# Analytics
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
# Screen Time
echo "<wait30s><tab><spacebar>"
# Siri
echo "<wait30s><tab><spacebar><leftShiftOn><tab><leftShiftOff><spacebar>"
# Choose Your Look
echo "<wait30s><leftShiftOn><tab><leftShiftOff><spacebar>"
if [ "${release}" = "13" ] || [ "${release}" = "14" ]; then
# Enable Voice Over
echo "<wait30s><leftAltOn><f5><leftAltOff><wait5s>v"
else
# Welcome to Mac
echo "<wait30s><spacebar>"
# Enable Keyboard navigation
echo "<wait30s><leftAltOn><spacebar><leftAltOff>Terminal<enter>"
echo "<wait30s>defaults write NSGlobalDomain AppleKeyboardUIMode -int 3<enter>"
echo "<wait30s><leftAltOn>q<leftAltOff>"
fi
# Now that the installation is done, open "System Settings"
echo "<wait30s><leftAltOn><spacebar><leftAltOff>System Settings<enter>"
# Navigate to "Sharing"
echo "<wait30s><leftAltOn>f<leftAltOff>sharing<enter>"
if [ "${release}" = "13" ]; then
# Navigate to "Screen Sharing" and enable it
echo "<wait30s><tab><down><spacebar>"
# Navigate to "Remote Login" and enable it
echo "<wait30s><tab><tab><tab><tab><tab><tab><spacebar>"
# Open "Remote Login" details
echo "<wait30s><tab><spacebar>"
# Enable "Full Disk Access"
echo "<wait30s><tab><spacebar>"
# Click "Done"
echo "<wait30s><leftShiftOn><tab><leftShiftOff><leftShiftOn><tab><leftShiftOff><spacebar>"
# Disable Voice Over
echo "<leftAltOn><f5><leftAltOff>"
elif [ "${release}" = "14" ]; then
# Navigate to "Screen Sharing" and enable it
echo "<wait30s><tab><tab><tab><tab><tab><spacebar>"
# Navigate to "Remote Login" and enable it
echo "<wait30s><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><spacebar>"
# Disable Voice Over
echo "<wait30s><leftAltOn><f5><leftAltOff>"
elif [ "${release}" = "15" ]; then
# Navigate to "Screen Sharing" and enable it
echo "<wait30s><tab><tab><tab><tab><tab><spacebar>"
# Navigate to "Remote Login" and enable it
echo "<wait30s><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><tab><spacebar>"
fi
# Quit System Settings
echo "<wait30s><leftAltOn>q<leftAltOff>"

View File

@@ -1,122 +0,0 @@
#!/bin/sh
# This script optimizes macOS for virtualized environments.
# It disables things like spotlight, screen saver, and sleep.
# Sources:
# - https://github.com/sickcodes/osx-optimizer
# - https://github.com/koding88/MacBook-Optimization-Script
# - https://www.macstadium.com/blog/simple-optimizations-for-macos-and-ios-build-agents
if [ "$(id -u)" != "0" ]; then
echo "This script must be run using sudo." >&2
exit 1
fi
execute() {
echo "$ $@" >&2
if ! "$@"; then
echo "Command failed: $@" >&2
exit 1
fi
}
disable_software_update() {
execute softwareupdate --schedule off
execute defaults write com.apple.SoftwareUpdate AutomaticDownload -bool false
execute defaults write com.apple.SoftwareUpdate AutomaticCheckEnabled -bool false
execute defaults write com.apple.SoftwareUpdate ConfigDataInstall -int 0
execute defaults write com.apple.SoftwareUpdate CriticalUpdateInstall -int 0
execute defaults write com.apple.SoftwareUpdate ScheduleFrequency -int 0
execute defaults write com.apple.SoftwareUpdate AutomaticDownload -int 0
execute defaults write com.apple.commerce AutoUpdate -bool false
execute defaults write com.apple.commerce AutoUpdateRestartRequired -bool false
}
disable_spotlight() {
execute mdutil -i off -a
execute mdutil -E /
}
disable_siri() {
execute launchctl unload -w /System/Library/LaunchAgents/com.apple.Siri.agent.plist
execute defaults write com.apple.Siri StatusMenuVisible -bool false
execute defaults write com.apple.Siri UserHasDeclinedEnable -bool true
execute defaults write com.apple.assistant.support "Assistant Enabled" 0
}
disable_sleep() {
execute systemsetup -setsleep Never
execute systemsetup -setcomputersleep Never
execute systemsetup -setdisplaysleep Never
execute systemsetup -setharddisksleep Never
}
disable_screen_saver() {
execute defaults write com.apple.screensaver loginWindowIdleTime 0
execute defaults write com.apple.screensaver idleTime 0
}
disable_screen_lock() {
execute defaults write com.apple.loginwindow DisableScreenLock -bool true
}
disable_wallpaper() {
execute defaults write com.apple.loginwindow DesktopPicture ""
}
disable_application_state() {
execute defaults write com.apple.loginwindow TALLogoutSavesState -bool false
}
disable_accessibility() {
execute defaults write com.apple.Accessibility DifferentiateWithoutColor -int 1
execute defaults write com.apple.Accessibility ReduceMotionEnabled -int 1
execute defaults write com.apple.universalaccess reduceMotion -int 1
execute defaults write com.apple.universalaccess reduceTransparency -int 1
}
disable_dashboard() {
execute defaults write com.apple.dashboard mcx-disabled -boolean YES
execute killall Dock
}
disable_animations() {
execute defaults write NSGlobalDomain NSAutomaticWindowAnimationsEnabled -bool false
execute defaults write -g QLPanelAnimationDuration -float 0
execute defaults write com.apple.finder DisableAllAnimations -bool true
}
disable_time_machine() {
execute tmutil disable
}
enable_performance_mode() {
# https://support.apple.com/en-us/101992
if ! [ $(nvram boot-args 2>/dev/null | grep -q serverperfmode) ]; then
execute nvram boot-args="serverperfmode=1 $(nvram boot-args 2>/dev/null | cut -f 2-)"
fi
}
add_terminal_to_desktop() {
execute ln -sf /System/Applications/Utilities/Terminal.app ~/Desktop/Terminal
}
main() {
disable_software_update
disable_spotlight
disable_siri
disable_sleep
disable_screen_saver
disable_screen_lock
disable_wallpaper
disable_application_state
disable_accessibility
disable_dashboard
disable_animations
disable_time_machine
enable_performance_mode
add_terminal_to_desktop
}
main

View File

@@ -1,78 +0,0 @@
#!/bin/sh
# This script generates a /etc/kcpassword file to enable auto-login on macOS.
# Yes, this stores your password in plain text. Do NOT do this on your local machine.
# Sources:
# - https://github.com/xfreebird/kcpassword/blob/master/kcpassword
if [ "$(id -u)" != "0" ]; then
echo "This script must be run using sudo." >&2
exit 1
fi
execute() {
echo "$ $@" >&2
if ! "$@"; then
echo "Command failed: $@" >&2
exit 1
fi
}
kcpassword() {
passwd="$1"
key="7d 89 52 23 d2 bc dd ea a3 b9 1f"
passwd_hex=$(printf "%s" "$passwd" | xxd -p | tr -d '\n')
key_len=33
passwd_len=${#passwd_hex}
remainder=$((passwd_len % key_len))
if [ $remainder -ne 0 ]; then
padding=$((key_len - remainder))
passwd_hex="${passwd_hex}$(printf '%0*x' $((padding / 2)) 0)"
fi
result=""
i=0
while [ $i -lt ${#passwd_hex} ]; do
for byte in $key; do
[ $i -ge ${#passwd_hex} ] && break
p="${passwd_hex:$i:2}"
r=$(printf '%02x' $((0x$p ^ 0x$byte)))
result="${result}${r}"
i=$((i + 2))
done
done
echo "$result"
}
login() {
username="$1"
password="$2"
enable_passwordless_sudo() {
execute mkdir -p /etc/sudoers.d/
echo "${username} ALL=(ALL) NOPASSWD: ALL" | EDITOR=tee execute visudo "/etc/sudoers.d/${username}-nopasswd"
}
enable_auto_login() {
echo "00000000: 1ced 3f4a bcbc ba2c caca 4e82" | execute xxd -r - /etc/kcpassword
execute defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser "${username}"
}
disable_screen_lock() {
execute sysadminctl -screenLock off -password "${password}"
}
enable_passwordless_sudo
enable_auto_login
disable_screen_lock
}
if [ $# -ne 2 ]; then
echo "Usage: $0 <username> <password>" >&2
exit 1
fi
login "$@"

View File

@@ -1,78 +0,0 @@
packer {
required_plugins {
tart = {
version = ">= 1.12.0"
source = "github.com/cirruslabs/tart"
}
external = {
version = ">= 0.0.2"
source = "github.com/joomcode/external"
}
}
}
variable "release" {
type = number
default = 13
}
variable "username" {
type = string
default = "admin"
}
variable "password" {
type = string
default = "admin"
}
variable "cpu_count" {
type = number
default = 2
}
variable "memory_gb" {
type = number
default = 4
}
variable "disk_size_gb" {
type = number
default = 50
}
locals {
sequoia = {
tier = 1
distro = "sequoia"
release = "15"
ipsw = "https://updates.cdn-apple.com/2024FallFCS/fullrestores/062-78489/BDA44327-C79E-4608-A7E0-455A7E91911F/UniversalMac_15.0_24A335_Restore.ipsw"
}
sonoma = {
tier = 2
distro = "sonoma"
release = "14"
ipsw = "https://updates.cdn-apple.com/2023FallFCS/fullrestores/042-54934/0E101AD6-3117-4B63-9BF1-143B6DB9270A/UniversalMac_14.0_23A344_Restore.ipsw"
}
ventura = {
tier = 2
distro = "ventura"
release = "13"
ipsw = "https://updates.cdn-apple.com/2022FallFCS/fullrestores/012-92188/2C38BCD1-2BFF-4A10-B358-94E8E28BE805/UniversalMac_13.0_22A380_Restore.ipsw"
}
releases = {
15 = local.sequoia
14 = local.sonoma
13 = local.ventura
}
release = local.releases[var.release]
username = var.username
password = var.password
cpu_count = var.cpu_count
memory_gb = var.memory_gb
disk_size_gb = var.disk_size_gb
}

View File

@@ -1,18 +0,0 @@
ARG IMAGE=debian:11
FROM $IMAGE
COPY ./scripts/bootstrap.sh /tmp/bootstrap.sh
ENV CI=true
RUN sh /tmp/bootstrap.sh && rm -rf /tmp/*
WORKDIR /workspace/bun
COPY bunfig.toml bunfig.toml
COPY package.json package.json
COPY CMakeLists.txt CMakeLists.txt
COPY cmake/ cmake/
COPY scripts/ scripts/
COPY patches/ patches/
COPY *.zig ./
COPY src/ src/
COPY packages/ packages/
COPY test/ test/
RUN bun i
RUN bun run build:ci

View File

@@ -1,27 +0,0 @@
#!/bin/sh
# This script sets the hostname of the current machine.
execute() {
echo "$ $@" >&2
if ! "$@"; then
echo "Command failed: $@" >&2
exit 1
fi
}
main() {
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <hostname>" >&2
exit 1
fi
if [ -f "$(which hostnamectl)" ]; then
execute hostnamectl set-hostname "$1"
else
echo "Error: hostnamectl is not installed." >&2
exit 1
fi
}
main "$@"

View File

@@ -1,22 +0,0 @@
#!/bin/sh
# This script starts tailscale on the current machine.
execute() {
echo "$ $@" >&2
if ! "$@"; then
echo "Command failed: $@" >&2
exit 1
fi
}
main() {
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <auth-key>" >&2
exit 1
fi
execute tailscale up --reset --ssh --accept-risk=lose-ssh --auth-key="$1"
}
main "$@"

View File

@@ -1,27 +0,0 @@
{
"private": true,
"scripts": {
"bootstrap": "brew install gh jq cirruslabs/cli/tart cirruslabs/cli/sshpass hashicorp/tap/packer && packer init darwin",
"login": "token=$(gh auth token); username=$(gh api user --jq .login); echo \"Login as $username...\"; echo \"$token\" | tart login ghcr.io --username \"$username\" --password-stdin; echo \"$token\" | docker login ghcr.io --username \"$username\" --password-stdin",
"fetch:image-name": "echo ghcr.io/oven-sh/bun-vm",
"fetch:darwin-version": "echo 1",
"fetch:macos-version": "sw_vers -productVersion | cut -d. -f1",
"fetch:script-version": "cat ../scripts/bootstrap.sh | grep 'v=' | sed 's/v=\"//;s/\"//' | head -n 1",
"build:darwin-aarch64-vanilla": "packer build '-only=*.bun-darwin-aarch64-vanilla' -var release=$(bun fetch:macos-version) darwin/",
"build:darwin-aarch64-vanilla-15": "packer build '-only=*.bun-darwin-aarch64-vanilla' -var release=15 darwin/",
"build:darwin-aarch64-vanilla-14": "packer build '-only=*.bun-darwin-aarch64-vanilla' -var release=14 darwin/",
"build:darwin-aarch64-vanilla-13": "packer build '-only=*.bun-darwin-aarch64-vanilla' -var release=13 darwin/",
"build:darwin-aarch64": "packer build '-only=*.bun-darwin-aarch64' -var release=$(bun fetch:macos-version) darwin/",
"build:darwin-aarch64-15": "packer build '-only=*.bun-darwin-aarch64' -var release=15 darwin/",
"build:darwin-aarch64-14": "packer build '-only=*.bun-darwin-aarch64' -var release=14 darwin/",
"build:darwin-aarch64-13": "packer build '-only=*.bun-darwin-aarch64' -var release=13 darwin/",
"publish:darwin-aarch64-vanilla": "image=$(tart list --format json | jq -r \".[] | select(.Name | test(\\\"^bun-darwin-aarch64-vanilla-.*-$(bun fetch:macos-version)$\\\")) | .Name\" | head -n 1 | sed 's/bun-//'); tart push \"bun-$image\" \"ghcr.io/oven-sh/bun-vm:$image-v$(bun fetch:darwin-version)\"",
"publish:darwin-aarch64-vanilla-15": "tart push bun-darwin-aarch64-vanilla-sequoia-15 \"$(bun fetch:image-name):darwin-aarch64-vanilla-sequoia-15-v$(bun fetch:darwin-version)\"",
"publish:darwin-aarch64-vanilla-14": "tart push bun-darwin-aarch64-vanilla-sonoma-14 \"$(bun fetch:image-name):darwin-aarch64-vanilla-sonoma-14-v$(bun fetch:darwin-version)\"",
"publish:darwin-aarch64-vanilla-13": "tart push bun-darwin-aarch64-vanilla-ventura-13 \"$(bun fetch:image-name):darwin-aarch64-vanilla-ventura-13-v$(bun fetch:darwin-version)\"",
"publish:darwin-aarch64": "image=$(tart list --format json | jq -r \".[] | select(.Name | test(\\\"^bun-darwin-aarch64-.*-$(bun fetch:macos-version)$\\\")) | .Name\" | head -n 1 | sed 's/bun-//'); tart push \"bun-$image\" \"ghcr.io/oven-sh/bun-vm:$image-v$(bun fetch:script-version)\"",
"publish:darwin-aarch64-15": "tart push bun-darwin-aarch64-sequoia-15 \"$(bun fetch:image-name):darwin-aarch64-sequoia-15-v$(bun fetch:script-version)\"",
"publish:darwin-aarch64-14": "tart push bun-darwin-aarch64-sonoma-14 \"$(bun fetch:image-name):darwin-aarch64-sonoma-14-v$(bun fetch:script-version)\"",
"publish:darwin-aarch64-13": "tart push bun-darwin-aarch64-ventura-13 \"$(bun fetch:image-name):darwin-aarch64-ventura-13-v$(bun fetch:script-version)\""
}
}

View File

@@ -419,7 +419,15 @@ function(register_command)
list(APPEND CMD_EFFECTIVE_OUTPUTS ${artifact})
if(BUILDKITE)
file(RELATIVE_PATH filename ${BUILD_PATH} ${artifact})
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} buildkite-agent artifact upload ${filename})
if(filename STREQUAL "libbun-profile.a")
# libbun-profile.a is now over 5gb in size, compress it first
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} rm -r ${BUILD_PATH}/codegen)
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} rm -r ${CACHE_PATH})
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} gzip -6 libbun-profile.a)
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} buildkite-agent artifact upload libbun-profile.a.gz)
else()
list(APPEND CMD_COMMANDS COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} buildkite-agent artifact upload ${filename})
endif()
endif()
endforeach()

View File

@@ -1,16 +1,16 @@
get_filename_component(SCRIPT_NAME ${CMAKE_CURRENT_LIST_FILE} NAME)
message(STATUS "Running script: ${SCRIPT_NAME}")
if(NOT ZIG_PATH OR NOT ZIG_COMMIT OR NOT ZIG_VERSION)
message(FATAL_ERROR "ZIG_PATH, ZIG_COMMIT, and ZIG_VERSION are required")
if(NOT ZIG_PATH OR NOT ZIG_COMMIT)
message(FATAL_ERROR "ZIG_PATH and ZIG_COMMIT required")
endif()
if(CMAKE_HOST_APPLE)
set(ZIG_OS "macos")
set(ZIG_OS_ABI "macos-none")
elseif(CMAKE_HOST_WIN32)
set(ZIG_OS "windows")
set(ZIG_OS_ABI "windows-gnu")
elseif(CMAKE_HOST_UNIX)
set(ZIG_OS "linux")
set(ZIG_OS_ABI "linux-musl")
else()
message(FATAL_ERROR "Unsupported operating system: ${CMAKE_HOST_SYSTEM_NAME}")
endif()
@@ -28,22 +28,16 @@ else()
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
set(ZIG_ASAN "")
if(ENABLE_ASAN)
set(ZIG_ASAN "+asan")
endif()
set(ZIG_NAME zig-${ZIG_OS}-${ZIG_ARCH}-${ZIG_VERSION}${ZIG_ASAN})
set(ZIG_NAME bootstrap-${ZIG_ARCH}-${ZIG_OS_ABI})
set(ZIG_FILENAME ${ZIG_NAME}.zip)
if(CMAKE_HOST_WIN32)
set(ZIG_EXE "zig.exe")
set(ZIG_FILENAME ${ZIG_NAME}.zip)
else()
set(ZIG_EXE "zig")
set(ZIG_FILENAME ${ZIG_NAME}.tar.xz)
endif()
set(ZIG_DOWNLOAD_URL https://bun-ci-assets.bun.sh/${ZIG_FILENAME})
set(ZIG_DOWNLOAD_URL https://github.com/oven-sh/zig/releases/download/autobuild-${ZIG_COMMIT}/${ZIG_FILENAME})
execute_process(
COMMAND
@@ -67,35 +61,8 @@ if(NOT EXISTS ${ZIG_PATH}/${ZIG_EXE})
endif()
# Tools like VSCode need a stable path to the zig executable, on both Unix and Windows
# To workaround this, we create a `bun.exe` symlink on Unix.
# To workaround this, we create a `zig.exe` & `zls.exe` symlink on Unix.
if(NOT WIN32)
file(CREATE_LINK ${ZIG_PATH}/${ZIG_EXE} ${ZIG_PATH}/zig.exe SYMBOLIC)
file(CREATE_LINK ${ZIG_PATH}/zls ${ZIG_PATH}/zls.exe SYMBOLIC)
endif()
set(ZIG_REPOSITORY_PATH ${ZIG_PATH}/repository)
execute_process(
COMMAND
${CMAKE_COMMAND}
-DGIT_PATH=${ZIG_REPOSITORY_PATH}
-DGIT_REPOSITORY=oven-sh/zig
-DGIT_COMMIT=${ZIG_COMMIT}
-P ${CMAKE_CURRENT_LIST_DIR}/GitClone.cmake
ERROR_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE
ZIG_REPOSITORY_ERROR
RESULT_VARIABLE
ZIG_REPOSITORY_RESULT
)
if(NOT ZIG_REPOSITORY_RESULT EQUAL 0)
message(FATAL_ERROR "Download failed: ${ZIG_REPOSITORY_ERROR}")
endif()
file(REMOVE_RECURSE ${ZIG_PATH}/lib)
# Use copy_directory instead of file(RENAME) because there were
# race conditions in CI where some files were not copied.
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${ZIG_REPOSITORY_PATH}/lib ${ZIG_PATH}/lib)
file(REMOVE_RECURSE ${ZIG_REPOSITORY_PATH})

View File

@@ -1,8 +1,8 @@
if(DEBUG)
set(bun bun-debug)
elseif(ENABLE_SMOL)
set(bun bun-smol-profile)
set(bunStrip bun-smol)
# elseif(ENABLE_SMOL)
# set(bun bun-smol-profile)
# set(bunStrip bun-smol)
elseif(ENABLE_VALGRIND)
set(bun bun-valgrind)
elseif(ENABLE_ASSERTIONS)
@@ -432,6 +432,7 @@ set(BUN_OBJECT_LUT_SOURCES
${CWD}/src/bun.js/bindings/BunProcess.cpp
${CWD}/src/bun.js/bindings/ProcessBindingBuffer.cpp
${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp
${CWD}/src/bun.js/bindings/ProcessBindingFs.cpp
${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp
${CWD}/src/bun.js/modules/NodeModuleModule.cpp
${CODEGEN_PATH}/ZigGeneratedClasses.lut.txt
@@ -444,6 +445,7 @@ set(BUN_OBJECT_LUT_OUTPUTS
${CODEGEN_PATH}/BunProcess.lut.h
${CODEGEN_PATH}/ProcessBindingBuffer.lut.h
${CODEGEN_PATH}/ProcessBindingConstants.lut.h
${CODEGEN_PATH}/ProcessBindingFs.lut.h
${CODEGEN_PATH}/ProcessBindingNatives.lut.h
${CODEGEN_PATH}/NodeModuleModule.lut.h
${CODEGEN_PATH}/ZigGeneratedClasses.lut.h
@@ -620,6 +622,7 @@ file(GLOB BUN_CXX_SOURCES ${CONFIGURE_DEPENDS}
${CWD}/src/bun.js/bindings/sqlite/*.cpp
${CWD}/src/bun.js/bindings/webcrypto/*.cpp
${CWD}/src/bun.js/bindings/webcrypto/*/*.cpp
${CWD}/src/bun.js/bindings/node/crypto/*.cpp
${CWD}/src/bun.js/bindings/v8/*.cpp
${CWD}/src/bun.js/bindings/v8/shim/*.cpp
${CWD}/src/bake/*.cpp
@@ -735,7 +738,7 @@ endif()
# --- C/C++ Properties ---
set_target_properties(${bun} PROPERTIES
CXX_STANDARD 20
CXX_STANDARD 23
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS YES
CXX_VISIBILITY_PRESET hidden
@@ -744,6 +747,18 @@ set_target_properties(${bun} PROPERTIES
VISIBILITY_INLINES_HIDDEN YES
)
if (NOT WIN32)
# Enable precompiled headers
# Only enable in these scenarios:
# 1. NOT in CI, OR
# 2. In CI AND BUN_CPP_ONLY is enabled
if(NOT CI OR (CI AND BUN_CPP_ONLY))
target_precompile_headers(${bun} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CWD}/src/bun.js/bindings/root.h>"
)
endif()
endif()
# --- C/C++ Includes ---
if(WIN32)
@@ -757,6 +772,7 @@ target_include_directories(${bun} PRIVATE
${CWD}/src/bun.js/bindings
${CWD}/src/bun.js/bindings/webcore
${CWD}/src/bun.js/bindings/webcrypto
${CWD}/src/bun.js/bindings/node/crypto
${CWD}/src/bun.js/bindings/sqlite
${CWD}/src/bun.js/bindings/v8
${CWD}/src/bun.js/modules
@@ -897,6 +913,10 @@ if(NOT WIN32)
-Werror
)
endif()
else()
target_compile_options(${bun} PUBLIC
-Wno-nullability-completeness
)
endif()
# --- Linker options ---
@@ -939,28 +959,17 @@ endif()
if(LINUX)
if(NOT ABI STREQUAL "musl")
# on arm64
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM|arm64|ARM64|aarch64|AARCH64")
target_link_options(${bun} PUBLIC
-Wl,--wrap=exp
-Wl,--wrap=expf
-Wl,--wrap=fcntl64
-Wl,--wrap=log
-Wl,--wrap=log2
-Wl,--wrap=log2f
-Wl,--wrap=logf
-Wl,--wrap=pow
-Wl,--wrap=powf
)
else()
target_link_options(${bun} PUBLIC
-Wl,--wrap=exp
-Wl,--wrap=expf
-Wl,--wrap=log2f
-Wl,--wrap=logf
-Wl,--wrap=powf
)
endif()
target_link_options(${bun} PUBLIC
-Wl,--wrap=exp
-Wl,--wrap=expf
-Wl,--wrap=fcntl64
-Wl,--wrap=log
-Wl,--wrap=log2
-Wl,--wrap=log2f
-Wl,--wrap=logf
-Wl,--wrap=pow
-Wl,--wrap=powf
)
endif()
if(NOT ABI STREQUAL "musl")

View File

@@ -4,7 +4,7 @@ register_repository(
REPOSITORY
cloudflare/lol-html
COMMIT
4f8becea13a0021c8b71abd2dcc5899384973b66
67f1d4ffd6b74db7e053fb129dcce620193c180d
)
set(LOLHTML_CWD ${VENDOR_PATH}/lolhtml/c-api)

View File

@@ -4,7 +4,7 @@ register_repository(
REPOSITORY
litespeedtech/ls-hpack
COMMIT
32e96f10593c7cb8553cd8c9c12721100ae9e924
8905c024b6d052f083a3d11d0a169b3c2735c8a1
)
if(WIN32)

View File

@@ -120,6 +120,9 @@ foreach(i RANGE ${BUILDKITE_JOBS_MAX_INDEX})
endif()
if(BUILDKITE)
if(BUILDKITE_ARTIFACT_PATH STREQUAL "libbun-profile.a")
set(BUILDKITE_ARTIFACT_PATH libbun-profile.a.gz)
endif()
set(BUILDKITE_DOWNLOAD_COMMAND buildkite-agent artifact download ${BUILDKITE_ARTIFACT_PATH} . --build ${BUILDKITE_BUILD_UUID} --step ${BUILDKITE_JOB_ID})
else()
set(BUILDKITE_DOWNLOAD_COMMAND curl -L -o ${BUILDKITE_ARTIFACT_PATH} ${BUILDKITE_ARTIFACTS_URL}/${BUILDKITE_ARTIFACT_ID})
@@ -135,6 +138,20 @@ foreach(i RANGE ${BUILDKITE_JOBS_MAX_INDEX})
OUTPUT
${BUILD_PATH}/${BUILDKITE_ARTIFACT_PATH}
)
if(BUILDKITE_ARTIFACT_PATH STREQUAL "libbun-profile.a.gz")
add_custom_command(
COMMENT
"Unpacking libbun-profile.a.gz"
VERBATIM COMMAND
gunzip libbun-profile.a.gz
WORKING_DIRECTORY
${BUILD_PATH}
OUTPUT
${BUILD_PATH}/libbun-profile.a
DEPENDS
${BUILD_PATH}/libbun-profile.a.gz
)
endif()
endforeach()
list(APPEND BUILDKITE_JOBS_MATCH ${BUILDKITE_JOB_NAME})

View File

@@ -36,7 +36,8 @@ endif()
string(REPLACE "\n" ";" GIT_CHANGED_SOURCES "${GIT_DIFF}")
if(CI)
setx(GIT_CHANGED_SOURCES ${GIT_CHANGED_SOURCES})
set(GIT_CHANGED_SOURCES "${GIT_CHANGED_SOURCES}")
message(STATUS "Set GIT_CHANGED_SOURCES: ${GIT_CHANGED_SOURCES}")
endif()
list(TRANSFORM GIT_CHANGED_SOURCES PREPEND ${CWD}/)

View File

@@ -12,7 +12,7 @@ if(NOT ENABLE_LLVM)
return()
endif()
set(DEFAULT_LLVM_VERSION "18.1.8")
set(DEFAULT_LLVM_VERSION "19.1.7")
optionx(LLVM_VERSION STRING "The version of LLVM to use" DEFAULT ${DEFAULT_LLVM_VERSION})

View File

@@ -2,7 +2,7 @@ option(WEBKIT_VERSION "The version of WebKit to use")
option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading")
if(NOT WEBKIT_VERSION)
set(WEBKIT_VERSION 57004f91903936881b3301594d9d67708f1ff64c)
set(WEBKIT_VERSION 91bf2baced1b1309c7e05f19177c97fefec20976)
endif()
string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX)

View File

@@ -20,8 +20,7 @@ else()
unsupported(CMAKE_SYSTEM_NAME)
endif()
optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.14.0-dev.2987+183bb8b08")
optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "02c57c7ee3b8fde7528c74dd06490834d2d6fae9")
set(ZIG_COMMIT "cd1995944508e4c946deb75bd70947d302e0db37")
optionx(ZIG_TARGET STRING "The zig target to use" DEFAULT ${DEFAULT_ZIG_TARGET})
if(CMAKE_BUILD_TYPE STREQUAL "Release")
@@ -77,7 +76,6 @@ register_command(
COMMAND
${CMAKE_COMMAND}
-DZIG_PATH=${ZIG_PATH}
-DZIG_VERSION=${ZIG_VERSION}
-DZIG_COMMIT=${ZIG_COMMIT}
-DENABLE_ASAN=${ENABLE_ASAN}
-P ${CWD}/cmake/scripts/DownloadZig.cmake

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim AS build
FROM debian:bookworm-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim AS build
FROM debian:bookworm-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim AS build
FROM debian:bookworm-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest

View File

@@ -204,7 +204,7 @@ To customize the TLS validation, use the `checkServerIdentity` option in `tls`
await fetch("https://example.com", {
tls: {
checkServerIdentity: (hostname, peerCertificate) => {
// Return an error if the certificate is invalid
// Return an Error if the certificate is invalid
},
},
});

View File

@@ -1,3 +1,7 @@
{% callout %}
**⚠️ Warning** — `bun:ffi` is **experimental**, with known bugs and limitations, and should not be relied on in production. The most stable way to interact with native code from Bun is to write a [Node-API module](/docs/api/node-api).
{% /callout %}
Use the built-in `bun:ffi` module to efficiently call native libraries from JavaScript. It works with languages that support the C ABI (Zig, Rust, C/C++, C#, Nim, Kotlin, etc).
## dlopen usage (`bun:ffi`)
@@ -298,7 +302,11 @@ setTimeout(() => {
When you're done with a JSCallback, you should call `close()` to free the memory.
### Experimental thread-safe callbacks
`JSCallback` has experimental support for thread-safe callbacks. This will be needed if you pass a callback function into a different thread from it's instantiation context. You can enable it with the optional `threadsafe` option flag.
`JSCallback` has experimental support for thread-safe callbacks. This will be needed if you pass a callback function into a different thread from its instantiation context. You can enable it with the optional `threadsafe` parameter.
Currently, thread-safe callbacks work best when run from another thread that is running JavaScript code, i.e. a [`Worker`](/docs/api/workers). A future version of Bun will enable them to be called from any thread (such as new threads spawned by your native library that Bun is not aware of).
```ts
const searchIterator = new JSCallback(
(ptr, length) => /hello/.test(new CString(ptr, length)),
@@ -309,7 +317,6 @@ const searchIterator = new JSCallback(
},
);
```
Be aware that there are still cases where this does not 100% work.
{% callout %}

View File

@@ -8,19 +8,421 @@ To start a high-performance HTTP server with a clean API, the recommended approa
## `Bun.serve()`
Start an HTTP server in Bun with `Bun.serve`.
Use `Bun.serve` to start an HTTP server in Bun.
```ts
Bun.serve({
// `routes` requires Bun v1.2.3+
routes: {
// Static routes
"/api/status": new Response("OK"),
// Dynamic routes
"/users/:id": req => {
return new Response(`Hello User ${req.params.id}!`);
},
// Per-HTTP method handlers
"/api/posts": {
GET: () => new Response("List posts"),
POST: async req => {
const body = await req.json();
return Response.json({ created: true, ...body });
},
},
// Wildcard route for all routes that start with "/api/" and aren't otherwise matched
"/api/*": Response.json({ message: "Not found" }, { status: 404 }),
// Redirect from /blog/hello to /blog/hello/world
"/blog/hello": Response.redirect("/blog/hello/world"),
// Serve a file by buffering it in memory
"/favicon.ico": new Response(await Bun.file("./favicon.ico").bytes(), {
headers: {
"Content-Type": "image/x-icon",
},
}),
},
// (optional) fallback for unmatched routes:
// Required if Bun's version < 1.2.3
fetch(req) {
return new Response("Bun!");
return new Response("Not Found", { status: 404 });
},
});
```
### Routing
Routes in `Bun.serve()` receive a `BunRequest` (which extends [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)) and return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or `Promise<Response>`. This makes it easier to use the same code for both sending & receiving HTTP requests.
```ts
// Simplified for brevity
interface BunRequest<T extends string> extends Request {
params: Record<T, string>;
}
```
#### Async/await in routes
You can use async/await in route handlers to return a `Promise<Response>`.
```ts
import { sql, serve } from "bun";
serve({
port: 3001,
routes: {
"/api/version": async () => {
const [version] = await sql`SELECT version()`;
return Response.json(version);
},
},
});
```
#### Promise in routes
You can also return a `Promise<Response>` from a route handler.
```ts
import { sql, serve } from "bun";
serve({
routes: {
"/api/version": () => {
return new Promise(resolve => {
setTimeout(async () => {
const [version] = await sql`SELECT version()`;
resolve(Response.json(version));
}, 100);
});
},
},
});
```
#### Type-safe route parameters
TypeScript parses route parameters when passed as a string literal, so that your editor will show autocomplete when accessing `request.params`.
```ts
import type { BunRequest } from "bun";
Bun.serve({
routes: {
// TypeScript knows the shape of params when passed as a string literal
"/orgs/:orgId/repos/:repoId": req => {
const { orgId, repoId } = req.params;
return Response.json({ orgId, repoId });
},
"/orgs/:orgId/repos/:repoId/settings": (
// optional: you can explicitly pass a type to BunRequest:
req: BunRequest<"/orgs/:orgId/repos/:repoId/settings">,
) => {
const { orgId, repoId } = req.params;
return Response.json({ orgId, repoId });
},
},
});
```
Percent-encoded route parameter values are automatically decoded. Unicode characters are supported. Invalid unicode is replaced with the unicode replacement character `&0xFFFD;`.
### Static responses
Routes can also be `Response` objects (without the handler function). Bun.serve() optimizes it for zero-allocation dispatch - perfect for health checks, redirects, and fixed content:
```ts
Bun.serve({
routes: {
// Health checks
"/health": new Response("OK"),
"/ready": new Response("Ready", {
headers: {
// Pass custom headers
"X-Ready": "1",
},
}),
// Redirects
"/blog": Response.redirect("https://bun.sh/blog"),
// API responses
"/api/config": Response.json({
version: "1.0.0",
env: "production",
}),
},
});
```
Static responses do not allocate additional memory after initialization. You can generally expect at least a 15% performance improvement over manually returning a `Response` object.
Static route responses are cached for the lifetime of the server object. To reload static routes, call `server.reload(options)`.
```ts
const server = Bun.serve({
static: {
"/api/time": new Response(new Date().toISOString()),
},
fetch(req) {
return new Response("404!");
},
});
// Update the time every second.
setInterval(() => {
server.reload({
static: {
"/api/time": new Response(new Date().toISOString()),
},
fetch(req) {
return new Response("404!");
},
});
}, 1000);
```
Reloading routes only impact the next request. In-flight requests continue to use the old routes. After in-flight requests to old routes are finished, the old routes are freed from memory.
To simplify error handling, static routes do not support streaming response bodies from `ReadableStream` or an `AsyncIterator`. Fortunately, you can still buffer the response in memory first:
```ts
const time = await fetch("https://api.example.com/v1/data");
// Buffer the response in memory first.
const blob = await time.blob();
const server = Bun.serve({
static: {
"/api/data": new Response(blob),
},
fetch(req) {
return new Response("404!");
},
});
```
### Route precedence
Routes are matched in order of specificity:
1. Exact routes (`/users/all`)
2. Parameter routes (`/users/:id`)
3. Wildcard routes (`/users/*`)
4. Global catch-all (`/*`)
```ts
Bun.serve({
routes: {
// Most specific first
"/api/users/me": () => new Response("Current user"),
"/api/users/:id": req => new Response(`User ${req.params.id}`),
"/api/*": () => new Response("API catch-all"),
"/*": () => new Response("Global catch-all"),
},
});
```
### Per-HTTP Method Routes
Route handlers can be specialized by HTTP method:
```ts
Bun.serve({
routes: {
"/api/posts": {
// Different handlers per method
GET: () => new Response("List posts"),
POST: async req => {
const post = await req.json();
return Response.json({ id: crypto.randomUUID(), ...post });
},
PUT: async req => {
const updates = await req.json();
return Response.json({ updated: true, ...updates });
},
DELETE: () => new Response(null, { status: 204 }),
},
},
});
```
You can pass any of the following methods:
| Method | Usecase example |
| --------- | ------------------------------- |
| `GET` | Fetch a resource |
| `HEAD` | Check if a resource exists |
| `OPTIONS` | Get allowed HTTP methods (CORS) |
| `DELETE` | Delete a resource |
| `PATCH` | Update a resource |
| `POST` | Create a resource |
| `PUT` | Update a resource |
When passing a function instead of an object, all methods will be handled by that function:
```ts
const server = Bun.serve({
routes: {
"/api/version": () => Response.json({ version: "1.0.0" }),
},
});
await fetch(new URL("/api/version", server.url));
await fetch(new URL("/api/version", server.url), { method: "PUT" });
// ... etc
```
### Hot Route Reloading
Update routes without server restarts using `server.reload()`:
```ts
const server = Bun.serve({
routes: {
"/api/version": () => Response.json({ version: "1.0.0" }),
},
});
// Deploy new routes without downtime
server.reload({
routes: {
"/api/version": () => Response.json({ version: "2.0.0" }),
},
});
```
### Error Handling
Bun provides structured error handling for routes:
```ts
Bun.serve({
routes: {
// Errors are caught automatically
"/api/risky": () => {
throw new Error("Something went wrong");
},
},
// Global error handler
error(error) {
console.error(error);
return new Response(`Internal Error: ${error.message}`, {
status: 500,
headers: {
"Content-Type": "text/plain",
},
});
},
});
```
### HTML imports
To add a client-side single-page app, you can use an HTML import:
```ts
import myReactSinglePageApp from "./index.html";
Bun.serve({
routes: {
"/": myReactSinglePageApp,
},
});
```
HTML imports don't just serve HTML. It's a full-featured frontend bundler, transpiler, and toolkit built using Bun's [bundler](https://bun.sh/docs/bundler), JavaScript transpiler and CSS parser.
You can use this to build a full-featured frontend with React, TypeScript, Tailwind CSS, and more. Check out [/docs/bundler/fullstack](https://bun.sh/docs/bundler/fullstack) to learn more.
### Practical example: REST API
Here's a basic database-backed REST API using Bun's router with zero dependencies:
{% codetabs %}
```ts#server.ts
import type { Post } from "./types.ts";
import { Database } from "bun:sqlite";
const db = new Database("posts.db");
db.exec(`
CREATE TABLE IF NOT EXISTS posts (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at TEXT NOT NULL
)
`);
Bun.serve({
routes: {
// List posts
"/api/posts": {
GET: () => {
const posts = db.query("SELECT * FROM posts").all();
return Response.json(posts);
},
// Create post
POST: async req => {
const post: Omit<Post, "id" | "created_at"> = await req.json();
const id = crypto.randomUUID();
db.query(
`INSERT INTO posts (id, title, content, created_at)
VALUES (?, ?, ?, ?)`,
).run(id, post.title, post.content, new Date().toISOString());
return Response.json({ id, ...post }, { status: 201 });
},
},
// Get post by ID
"/api/posts/:id": req => {
const post = db
.query("SELECT * FROM posts WHERE id = ?")
.get(req.params.id);
if (!post) {
return new Response("Not Found", { status: 404 });
}
return Response.json(post);
},
},
error(error) {
console.error(error);
return new Response("Internal Server Error", { status: 500 });
},
});
```
```ts#types.ts
export interface Post {
id: string;
title: string;
content: string;
created_at: string;
}
```
{% /codetabs %}
### Routing performance
`Bun.serve()`'s router builds on top uWebSocket's [tree-based approach](https://github.com/oven-sh/bun/blob/0d1a00fa0f7830f8ecd99c027fce8096c9d459b6/packages/bun-uws/src/HttpRouter.h#L57-L64) to add [SIMD-accelerated route parameter decoding](https://github.com/oven-sh/bun/blob/main/src/bun.js/bindings/decodeURIComponentSIMD.cpp#L21-L271) and [JavaScriptCore structure caching](https://github.com/oven-sh/bun/blob/main/src/bun.js/bindings/ServerRouteList.cpp#L100-L101) to push the performance limits of what modern hardware allows.
### `fetch` request handler
The `fetch` handler handles incoming requests. It receives a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or `Promise<Response>`.
The `fetch` handler handles incoming requests that weren't matched by any route. It receives a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or [`Promise<Response>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
```ts
Bun.serve({
@@ -70,116 +472,6 @@ const server = Bun.serve({
});
```
### Static routes
Use the `static` option to serve static `Response` objects by route.
```ts
// Bun v1.1.27+ required
Bun.serve({
static: {
// health-check endpoint
"/api/health-check": new Response("All good!"),
// redirect from /old-link to /new-link
"/old-link": Response.redirect("/new-link", 301),
// serve static text
"/": new Response("Hello World"),
// serve a file by buffering it in memory
"/index.html": new Response(await Bun.file("./index.html").bytes(), {
headers: {
"Content-Type": "text/html",
},
}),
"/favicon.ico": new Response(await Bun.file("./favicon.ico").bytes(), {
headers: {
"Content-Type": "image/x-icon",
},
}),
// serve JSON
"/api/version.json": Response.json({ version: "1.0.0" }),
},
fetch(req) {
return new Response("404!");
},
});
```
Static routes support headers, status code, and other `Response` options.
```ts
Bun.serve({
static: {
"/api/time": new Response(new Date().toISOString(), {
headers: {
"X-Custom-Header": "Bun!",
},
}),
},
fetch(req) {
return new Response("404!");
},
});
```
Static routes can serve Response bodies faster than `fetch` handlers because they don't create `Request` objects, they don't create `AbortSignal`, they don't create additional `Response` objects. The only per-request memory allocation is the TCP/TLS socket data needed for each request.
{% note %}
`static` is experimental
{% /note %}
Static route responses are cached for the lifetime of the server object. To reload static routes, call `server.reload(options)`.
```ts
const server = Bun.serve({
static: {
"/api/time": new Response(new Date().toISOString()),
},
fetch(req) {
return new Response("404!");
},
});
// Update the time every second.
setInterval(() => {
server.reload({
static: {
"/api/time": new Response(new Date().toISOString()),
},
fetch(req) {
return new Response("404!");
},
});
}, 1000);
```
Reloading static routes only impact the next request. In-flight requests continue to use the old static routes. After in-flight requests to old static routes are finished, the old static routes are freed from memory.
To simplify error handling, static routes do not support streaming response bodies from `ReadableStream` or an `AsyncIterator`. Fortunately, you can still buffer the response in memory first:
```ts
const time = await fetch("https://api.example.com/v1/data");
// Buffer the response in memory first.
const blob = await time.blob();
const server = Bun.serve({
static: {
"/api/data": new Response(blob),
},
fetch(req) {
return new Response("404!");
},
});
```
### Changing the `port` and `hostname`
To configure which port and hostname the server will listen on, set `port` and `hostname` in the options object.
@@ -553,7 +845,7 @@ Update the server's handlers without restarting:
```ts
const server = Bun.serve({
static: {
routes: {
"/api/version": Response.json({ version: "v1" }),
},
fetch(req) {
@@ -563,7 +855,7 @@ const server = Bun.serve({
// Update to new handler
server.reload({
static: {
routes: {
"/api/version": Response.json({ version: "v2" }),
},
fetch(req) {
@@ -572,7 +864,7 @@ server.reload({
});
```
This is useful for development and hot reloading. Only `fetch`, `error`, and `static` handlers can be updated.
This is useful for development and hot reloading. Only `fetch`, `error`, and `routes` can be updated.
## Per-Request Controls

View File

@@ -12,5 +12,3 @@ Alternatively, use `process.dlopen`:
let mod = { exports: {} };
process.dlopen(mod, "./my-node-module.node");
```
Bun polyfills the [`detect-libc`](https://npmjs.com/package/detect-libc) package, which is used by many Node-API modules to detect which `.node` binding to `require`.

View File

@@ -181,8 +181,8 @@ const download = s3.presign("my-file.txt"); // GET, text/plain, expires in 24 ho
const upload = s3.presign("my-file", {
expiresIn: 3600, // 1 hour
method: 'PUT',
type: 'application/json', // No extension for inferring, so we can specify the content type to be JSON
method: "PUT",
type: "application/json", // No extension for inferring, so we can specify the content type to be JSON
});
// You can call .presign() if on a file reference, but avoid doing so
@@ -361,6 +361,56 @@ const minio = new S3Client({
});
```
### Using Bun's S3Client with supabase
To use Bun's S3 client with [supabase](https://supabase.com/), set `endpoint` to the supabase endpoint in the `S3Client` constructor. The supabase endpoint includes your account ID and /storage/v1/s3 path. Make sure to set Enable connection via S3 protocol on in the supabase dashboard in https://supabase.com/dashboard/project/<account-id>/settings/storage and to set the region informed in the same section.
```ts
import { S3Client } from "bun";
const supabase = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
region: "us-west-1",
endpoint: "https://<account-id>.supabase.co/storage/v1/s3/storage",
});
```
### Using Bun's S3Client with S3 Virtual Hosted-Style endpoints
When using a S3 Virtual Hosted-Style endpoint, you need to set the `virtualHostedStyle` option to `true` and if no endpoint is provided, Bun will use region and bucket to infer the endpoint to AWS S3, if no region is provided it will use `us-east-1`. If you provide a the endpoint, there are no need to provide the bucket name.
```ts
import { S3Client } from "bun";
// AWS S3 endpoint inferred from region and bucket
const s3 = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
virtualHostedStyle: true,
// endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com",
// region: "us-east-1",
});
// AWS S3
const s3WithEndpoint = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
endpoint: "https://<bucket-name>.s3.<region>.amazonaws.com",
virtualHostedStyle: true,
});
// Cloudflare R2
const r2WithEndpoint = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
endpoint: "https://<bucket-name>.<account-id>.r2.cloudflarestorage.com",
virtualHostedStyle: true,
});
```
## Credentials
Credentials are one of the hardest parts of using S3, and we've tried to make it as easy as possible. By default, Bun reads the following environment variables for credentials.
@@ -665,7 +715,7 @@ await S3Client.delete("my-file.txt", credentials);
await S3Client.unlink("my-file.txt", credentials);
```
## s3:// protocol
## `s3://` protocol
To make it easier to use the same code for local files and S3 files, the `s3://` protocol is supported in `fetch` and `Bun.file()`.

View File

@@ -77,6 +77,16 @@ console.log(text); // "const input = "hello world".repeat(400); ..."
---
- `ReadableStream`
- Use a readable stream as input.
---
- `Blob`
- Use a blob as input.
---
- `number`
- Read from the file with a given file descriptor.
@@ -129,13 +139,13 @@ Configure the output stream by passing one of the following values to `stdout/st
---
- `Bun.file()`
- Write to the specified file.
- `"ignore"`
- Discard the output.
---
- `null`
- Write to `/dev/null`.
- `Bun.file()`
- Write to the specified file.
---
@@ -174,7 +184,8 @@ const proc = Bun.spawn(["bun", "--version"]);
proc.kill();
proc.killed; // true
proc.kill(); // specify an exit code
proc.kill(15); // specify a signal code
proc.kill("SIGTERM"); // specify a signal name
```
The parent `bun` process will not terminate until all child processes have exited. Use `proc.unref()` to detach the child process from the parent.
@@ -184,6 +195,64 @@ const proc = Bun.spawn(["bun", "--version"]);
proc.unref();
```
## Resource usage
You can get information about the process's resource usage after it has exited:
```ts
const proc = Bun.spawn(["bun", "--version"]);
await proc.exited;
const usage = proc.resourceUsage();
console.log(`Max memory used: ${usage.maxRSS} bytes`);
console.log(`CPU time (user): ${usage.cpuTime.user} µs`);
console.log(`CPU time (system): ${usage.cpuTime.system} µs`);
```
## Using AbortSignal
You can abort a subprocess using an `AbortSignal`:
```ts
const controller = new AbortController();
const { signal } = controller;
const proc = Bun.spawn({
cmd: ["sleep", "100"],
signal,
});
// Later, to abort the process:
controller.abort();
```
## Using timeout and killSignal
You can set a timeout for a subprocess to automatically terminate after a specific duration:
```ts
// Kill the process after 5 seconds
const proc = Bun.spawn({
cmd: ["sleep", "10"],
timeout: 5000, // 5 seconds in milliseconds
});
await proc.exited; // Will resolve after 5 seconds
```
By default, timed-out processes are killed with the `SIGTERM` signal. You can specify a different signal with the `killSignal` option:
```ts
// Kill the process with SIGKILL after 5 seconds
const proc = Bun.spawn({
cmd: ["sleep", "10"],
timeout: 5000,
killSignal: "SIGKILL", // Can be string name or signal number
});
```
The `killSignal` option also controls which signal is sent when an AbortSignal is aborted.
## Inter-process communication (IPC)
Bun supports direct inter-process communication channel between two `bun` processes. To receive messages from a spawned Bun subprocess, specify an `ipc` handler.
@@ -233,11 +302,17 @@ process.send("Hello from child as string");
process.send({ message: "Hello from child as object" });
```
The `ipcMode` option controls the underlying communication format between the two processes:
The `serialization` option controls the underlying communication format between the two processes:
- `advanced`: (default) Messages are serialized using the JSC `serialize` API, which supports cloning [everything `structuredClone` supports](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). This does not support transferring ownership of objects.
- `json`: Messages are serialized using `JSON.stringify` and `JSON.parse`, which does not support as many object types as `advanced` does.
To disconnect the IPC channel from the parent process, call:
```ts
childProc.disconnect();
```
### IPC between Bun & Node.js
To use IPC between a `bun` process and a Node.js process, set `serialization: "json"` in `Bun.spawn`. This is because Node.js and Bun use different JavaScript engines with different object serialization formats.
@@ -310,7 +385,7 @@ spawnSync echo hi 1.47 ms/iter (1.14 ms … 2.64 ms) 1.57 ms 2.37 ms
## Reference
A simple reference of the Spawn API and types are shown below. The real types have complex generics to strongly type the `Subprocess` streams with the options passed to `Bun.spawn` and `Bun.spawnSync`. For full details, find these types as defined [bun.d.ts](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts).
A reference of the Spawn API and types are shown below. The real types have complex generics to strongly type the `Subprocess` streams with the options passed to `Bun.spawn` and `Bun.spawnSync`. For full details, find these types as defined [bun.d.ts](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts).
```ts
interface Bun {
@@ -329,16 +404,25 @@ interface Bun {
namespace SpawnOptions {
interface OptionsObject {
cwd?: string;
env?: Record<string, string>;
stdin?: SpawnOptions.Readable;
stdout?: SpawnOptions.Writable;
stderr?: SpawnOptions.Writable;
onExit?: (
proc: Subprocess,
env?: Record<string, string | undefined>;
stdio?: [Writable, Readable, Readable];
stdin?: Writable;
stdout?: Readable;
stderr?: Readable;
onExit?(
subprocess: Subprocess,
exitCode: number | null,
signalCode: string | null,
error: Error | null,
) => void;
signalCode: number | null,
error?: ErrorLike,
): void | Promise<void>;
ipc?(message: any, subprocess: Subprocess): void;
serialization?: "json" | "advanced";
windowsHide?: boolean;
windowsVerbatimArguments?: boolean;
argv0?: string;
signal?: AbortSignal;
timeout?: number;
killSignal?: string | number;
}
type Readable =
@@ -366,39 +450,62 @@ namespace SpawnOptions {
| Request;
}
interface Subprocess<Stdin, Stdout, Stderr> {
interface Subprocess extends AsyncDisposable {
readonly stdin: FileSink | number | undefined;
readonly stdout: ReadableStream<Uint8Array> | number | undefined;
readonly stderr: ReadableStream<Uint8Array> | number | undefined;
readonly readable: ReadableStream<Uint8Array> | number | undefined;
readonly pid: number;
// the exact stream types here are derived from the generic parameters
readonly stdin: number | ReadableStream | FileSink | undefined;
readonly stdout: number | ReadableStream | undefined;
readonly stderr: number | ReadableStream | undefined;
readonly exited: Promise<number>;
readonly exitCode: number | undefined;
readonly signalCode: Signal | null;
readonly exitCode: number | null;
readonly signalCode: NodeJS.Signals | null;
readonly killed: boolean;
kill(exitCode?: number | NodeJS.Signals): void;
ref(): void;
unref(): void;
kill(code?: number): void;
send(message: any): void;
disconnect(): void;
resourceUsage(): ResourceUsage | undefined;
}
interface SyncSubprocess<Stdout, Stderr> {
readonly pid: number;
readonly success: boolean;
// the exact buffer types here are derived from the generic parameters
readonly stdout: Buffer | undefined;
readonly stderr: Buffer | undefined;
interface SyncSubprocess {
stdout: Buffer | undefined;
stderr: Buffer | undefined;
exitCode: number;
success: boolean;
resourceUsage: ResourceUsage;
signalCode?: string;
exitedDueToTimeout?: true;
pid: number;
}
type ReadableSubprocess = Subprocess<any, "pipe", "pipe">;
type WritableSubprocess = Subprocess<"pipe", any, any>;
type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">;
type NullSubprocess = Subprocess<null, null, null>;
interface ResourceUsage {
contextSwitches: {
voluntary: number;
involuntary: number;
};
type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">;
type NullSyncSubprocess = SyncSubprocess<null, null>;
cpuTime: {
user: number;
system: number;
total: number;
};
maxRSS: number;
messages: {
sent: number;
received: number;
};
ops: {
in: number;
out: number;
};
shmSize: number;
signalCount: number;
swapCount: number;
}
type Signal =
| "SIGABRT"

View File

@@ -87,7 +87,7 @@ await sql`INSERT INTO users ${sql(users)}`;
### Picking columns to insert
You can use `sql(object, Array<string>)` to pick which columns to insert. Each of the columns must be defined on the object.
You can use `sql(object, ...string)` to pick which columns to insert. Each of the columns must be defined on the object.
```ts
const user = {
@@ -96,7 +96,7 @@ const user = {
age: 25,
};
await sql`INSERT INTO users ${sql(user, ["name", "email"])}`;
await sql`INSERT INTO users ${sql(user, "name", "email")}`;
// Only inserts name and email columns, ignoring other fields
```
@@ -165,13 +165,72 @@ await sql`
`;
```
### Unsafe Queries
### Dynamic columns in updates
You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input.
You can use `sql(object, ...string)` to pick which columns to update. Each of the columns must be defined on the object. If the columns are not informed all keys will be used to update the row.
```ts
await sql`UPDATE users SET ${sql(user, "name", "email")} WHERE id = ${user.id}`;
// uses all keys from the object to update the row
await sql`UPDATE users SET ${sql(user)} WHERE id = ${user.id}`;
```
### Dynamic values and `where in`
Value lists can also be created dynamically, making where in queries simple too. Optionally you can pass a array of objects and inform what key to use to create the list.
```ts
await sql`SELECT * FROM users WHERE id IN ${sql([1, 2, 3])}`;
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
await sql`SELECT * FROM users WHERE id IN ${sql(users, "id")}`;
```
## `sql``.simple()`
The PostgreSQL wire protocol supports two types of queries: "simple" and "extended". Simple queries can contain multiple statements but don't support parameters, while extended queries (the default) support parameters but only allow one statement.
To run multiple statements in a single query, use `sql``.simple()`:
```ts
// Multiple statements in one query
await sql`
SELECT 1;
SELECT 2;
`.simple();
```
Simple queries are often useful for database migrations and setup scripts.
Note that simple queries cannot use parameters (`${value}`). If you need parameters, you must split your query into separate statements.
### Queries in files
You can use the `sql.file` method to read a query from a file and execute it, if the file includes $1, $2, etc you can pass parameters to the query. If no parameters are used it can execute multiple commands per file.
```ts
const result = await sql.file("query.sql", [1, 2, 3]);
```
### Unsafe Queries
You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input. Executing more than one command per query is allowed if no parameters are used.
```ts
// Multiple commands without parameters
const result = await sql.unsafe(`
SELECT ${userColumns} FROM users;
SELECT ${accountColumns} FROM accounts;
`);
// Using parameters (only one command is allowed)
const result = await sql.unsafe(
"SELECT " + columns + " FROM users WHERE id = " + id,
"SELECT " + dangerous + " FROM users WHERE id = $1",
[id],
);
```
@@ -262,6 +321,21 @@ const db = new SQL({
});
```
## Dynamic passwords
When clients need to use alternative authentication schemes such as access tokens or connections to databases with rotating passwords, provide either a synchronous or asynchronous function that will resolve the dynamic password value at connection time.
```ts
import { SQL } from "bun";
const sql = new SQL(url, {
// Other connection config
...
// Password function for the database user
password: async () => await signer.getAuthToken(),
});
```
## Transactions
To start a new transaction, use `sql.begin`. This method reserves a dedicated connection for the duration of the transaction and provides a scoped `sql` instance to use within the callback function. Once the callback completes, `sql.begin` resolves with the return value of the callback.
@@ -431,6 +505,34 @@ try {
} // Automatically released
```
## Prepared Statements
By default, Bun's SQL client automatically creates named prepared statements for queries where it can be inferred that the query is static. This provides better performance. However, you can change this behavior by setting `prepare: false` in the connection options:
```ts
const sql = new SQL({
// ... other options ...
prepare: false, // Disable persisting named prepared statements on the server
});
```
When `prepare: false` is set:
Queries are still executed using the "extended" protocol, but they are executed using [unnamed prepared statements](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY), an unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued.
- Parameter binding is still safe against SQL injection
- Each query is parsed and planned from scratch by the server
- Queries will not be [pipelined](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING)
You might want to use `prepare: false` when:
- Using PGBouncer in transaction mode (though since PGBouncer 1.21.0, protocol-level named prepared statements are supported when configured properly)
- Debugging query execution plans
- Working with dynamic SQL where query plans need to be regenerated frequently
- More than one command per query will not be supported (unless you use `sql``.simple()`)
Note that disabling prepared statements may impact performance for queries that are executed frequently with different parameters, as the server needs to parse and plan each query from scratch.
## Error Handling
The client provides typed errors for different failure scenarios:
@@ -466,6 +568,7 @@ The client provides typed errors for different failure scenarios:
| `ERR_POSTGRES_SERVER_ERROR` | General error from PostgreSQL server |
| `ERR_POSTGRES_INVALID_QUERY_BINDING` | Invalid parameter binding |
| `ERR_POSTGRES_QUERY_CANCELLED` | Query was cancelled |
| `ERR_POSTGRES_NOT_TAGGED_CALL` | Query was called without a tagged call |
### Data Type Errors
@@ -501,7 +604,7 @@ The client provides typed errors for different failure scenarios:
## Numbers and BigInt
Bun's SQL client includes special handling for large numbers that exceed the range of a 53-bit integer. Heres how it works:
Bun's SQL client includes special handling for large numbers that exceed the range of a 53-bit integer. Here's how it works:
```ts
import { sql } from "bun";

View File

@@ -11,7 +11,7 @@ Bun.listen({
socket: {
data(socket, data) {}, // message received from client
open(socket) {}, // socket opened
close(socket) {}, // socket closed
close(socket, error) {}, // socket closed
drain(socket) {}, // socket ready for more data
error(socket, error) {}, // error handler
},
@@ -30,7 +30,7 @@ Bun.listen({
open(socket) {},
data(socket, data) {},
drain(socket) {},
close(socket) {},
close(socket, error) {},
error(socket, error) {},
},
});
@@ -122,7 +122,7 @@ const socket = await Bun.connect({
socket: {
data(socket, data) {},
open(socket) {},
close(socket) {},
close(socket, error) {},
drain(socket) {},
error(socket, error) {},

View File

@@ -228,3 +228,17 @@ const worker = new Worker("./i-am-smol.ts", {
{% details summary="What does `smol` mode actually do?" %}
Setting `smol: true` sets `JSC::HeapSize` to be `Small` instead of the default `Large`.
{% /details %}
## `Bun.isMainThread`
You can check if you're in the main thread by checking `Bun.isMainThread`.
```ts
if (Bun.isMainThread) {
console.log("I'm the main thread");
} else {
console.log("I'm in a worker");
}
```
This is useful for conditionally running code based on whether you're in the main thread or not.

1028
docs/bundler/css.md Normal file

File diff suppressed because it is too large Load Diff

145
docs/bundler/css_modules.md Normal file
View File

@@ -0,0 +1,145 @@
# CSS Modules
Bun's bundler also supports bundling [CSS modules](https://css-tricks.com/css-modules-part-1-need/) in addition to [regular CSS](/docs/bundler/css) with support for the following features:
- Automatically detecting CSS module files (`.module.css`) with zero configuration
- Composition (`composes` property)
- Importing CSS modules into JSX/TSX
- Warnings/errors for invalid usages of CSS modules
A CSS module is a CSS file (with the `.module.css` extension) where are all class names and animations are scoped to the file. This helps you avoid class name collisions as CSS declarations are globally scoped by default.
Under the hood, Bun's bundler transforms locally scoped class names into unique identifiers.
## Getting started
Create a CSS file with the `.module.css` extension:
```css
/* styles.module.css */
.button {
color: red;
}
/* other-styles.module.css */
.button {
color: blue;
}
```
You can then import this file, for example into a TSX file:
```tsx
import styles from "./styles.module.css";
import otherStyles from "./other-styles.module.css";
export default function App() {
return (
<>
<button className={styles.button}>Red button!</button>
<button className={otherStyles.button}>Blue button!</button>
</>
);
}
```
The `styles` object from importing the CSS module file will be an object with all class names as keys and
their unique identifiers as values:
```tsx
import styles from "./styles.module.css";
import otherStyles from "./other-styles.module.css";
console.log(styles);
console.log(otherStyles);
```
This will output:
```ts
{
button: "button_123";
}
{
button: "button_456";
}
```
As you can see, the class names are unique to each file, avoiding any collisions!
### Composition
CSS modules allow you to _compose_ class selectors together. This lets you reuse style rules across multiple classes.
For example:
```css
/* styles.module.css */
.button {
composes: background;
color: red;
}
.background {
background-color: blue;
}
```
Would be the same as writing:
```css
.button {
background-color: blue;
color: red;
}
.background {
background-color: blue;
}
```
{% callout %}
There are a couple rules to keep in mind when using `composes`:
- A `composes` property must come before any regular CSS properties or declarations
- You can only use `composes` on a **simple selector with a single class name**:
```css
#button {
/* Invalid! `#button` is not a class selector */
composes: background;
}
.button,
.button-secondary {
/* Invalid! `.button, .button-secondary` is not a simple selector */
composes: background;
}
```
{% /callout %}
### Composing from a separate CSS module file
You can also compose from a separate CSS module file:
```css
/* background.module.css */
.background {
background-color: blue;
}
/* styles.module.css */
.button {
composes: background from "./background.module.css";
color: red;
}
```
{% callout %}
When composing classes from separate files, be sure that they do not contain the same properties.
The CSS module spec says that composing classes from separate files with conflicting properties is
undefined behavior, meaning that the output may differ and be unreliable.
{% /callout %}

View File

@@ -75,14 +75,16 @@ bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp
The order of the `--target` flag does not matter, as long as they're delimited by a `-`.
| --target | Operating System | Architecture | Modern | Baseline |
| --------------------- | ---------------- | ------------ | ------ | -------- |
| bun-linux-x64 | Linux | x64 | ✅ | ✅ |
| bun-linux-arm64 | Linux | arm64 | ✅ | N/A |
| bun-windows-x64 | Windows | x64 | ✅ | ✅ |
| ~~bun-windows-arm64~~ | Windows | arm64 | ❌ | ❌ |
| bun-darwin-x64 | macOS | x64 | ✅ | ✅ |
| bun-darwin-arm64 | macOS | arm64 | ✅ | N/A |
| --target | Operating System | Architecture | Modern | Baseline | Libc |
| --------------------- | ---------------- | ------------ | ------ | -------- | ----- |
| bun-linux-x64 | Linux | x64 | ✅ | ✅ | glibc |
| bun-linux-arm64 | Linux | arm64 | ✅ | N/A | glibc |
| bun-windows-x64 | Windows | x64 | ✅ | ✅ | - |
| ~~bun-windows-arm64~~ | Windows | arm64 | ❌ | ❌ | - |
| bun-darwin-x64 | macOS | x64 | ✅ | ✅ | - |
| bun-darwin-arm64 | macOS | arm64 | ✅ | N/A | - |
| bun-linux-x64-musl | Linux | x64 | ✅ | ✅ | musl |
| bun-linux-arm64-musl | Linux | arm64 | ✅ | N/A | musl |
On x64 platforms, Bun uses SIMD optimizations which require a modern CPU supporting AVX2 instructions. The `-baseline` build of Bun is for older CPUs that don't support these optimizations. Normally, when you install Bun we automatically detect which version to use but this can be harder to do when cross-compiling since you might not know the target CPU. You usually don't need to worry about it on Darwin x64, but it is relevant for Windows x64 and Linux x64. If you or your users see `"Illegal instruction"` errors, you might need to use the baseline version.
@@ -294,6 +296,55 @@ These flags currently cannot be used when cross-compiling because they depend on
{% /callout %}
## Code signing on macOS
To codesign a standalone executable on macOS (which fixes Gatekeeper warnings), use the `codesign` command.
```sh
$ codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myapp
```
We recommend including an `entitlements.plist` file with JIT permissions.
```xml#entitlements.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
```
To codesign with JIT support, pass the `--entitlements` flag to `codesign`.
```sh
$ codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myapp
```
After codesigning, verify the executable:
```sh
$ codesign -vvv --verify ./myapp
./myapp: valid on disk
./myapp: satisfies its Designated Requirement
```
{% callout %}
Codesign support requires Bun v1.2.4 or newer.
{% /callout %}
## Unsupported CLI arguments
Currently, the `--compile` flag can only accept a single entrypoint at a time and does not support the following flags:

View File

@@ -1,36 +1,50 @@
Using `Bun.serve()`'s `static` option, you can run your frontend and backend in the same app with no extra steps.
Using `Bun.serve()`'s `routes` option, you can run your frontend and backend in the same app with no extra steps.
To get started, import HTML files and pass them to the `static` option in `Bun.serve()`.
To get started, import HTML files and pass them to the `routes` option in `Bun.serve()`.
```ts
import { sql, serve } from "bun";
import dashboard from "./dashboard.html";
import homepage from "./index.html";
const server = Bun.serve({
// Add HTML imports to `static`
static: {
// Bundle & route index.html to "/"
const server = serve({
routes: {
// ** HTML imports **
// Bundle & route index.html to "/". This uses HTMLRewriter to scan the HTML for `<script>` and `<link>` tags, run's Bun's JavaScript & CSS bundler on them, transpiles any TypeScript, JSX, and TSX, downlevels CSS with Bun's CSS parser and serves the result.
"/": homepage,
// Bundle & route dashboard.html to "/dashboard"
"/dashboard": dashboard,
// ** API endpoints ** (Bun v1.2.3+ required)
"/api/users": {
async GET(req) {
const users = await sql`SELECT * FROM users`;
return Response.json(users);
},
async POST(req) {
const { name, email } = await req.json();
const [user] =
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
return Response.json(user);
},
},
"/api/users/:id": async req => {
const { id } = req.params;
const [user] = await sql`SELECT * FROM users WHERE id = ${id}`;
return Response.json(user);
},
},
// Enable development mode for:
// - Detailed error messages
// - Rebuild on request
// - Hot reloading (Bun v1.2.3+ required)
development: true,
// Handle API requests
async fetch(req) {
// ...your API code
if (req.url.endsWith("/api/users")) {
const users = await Bun.sql`SELECT * FROM users`;
return Response.json(users);
}
// Return 404 for unmatched routes
return new Response("Not Found", { status: 404 });
},
// Prior to v1.2.3, the `fetch` option was used to handle all API requests. It is now optional.
// async fetch(req) {
// // Return 404 for unmatched routes
// return new Response("Not Found", { status: 404 });
// },
});
console.log(`Listening on ${server.url}`);
@@ -55,7 +69,7 @@ These HTML files are used as routes in Bun's dev server you can pass to `Bun.ser
```ts
Bun.serve({
static: {
routes: {
"/": homepage,
"/dashboard": dashboard,
}
@@ -113,7 +127,7 @@ import dashboard from "../public/dashboard.html";
import { serve } from "bun";
serve({
static: {
routes: {
"/": dashboard,
},
@@ -171,7 +185,7 @@ import homepage from "./index.html";
import dashboard from "./dashboard.html";
Bun.serve({
static: {
routes: {
"/": homepage,
"/dashboard": dashboard,
}
@@ -249,6 +263,8 @@ plugins = ["./my-plugin-implementation.ts"]
Bun will lazily resolve and load each plugin and use them to bundle your routes.
Note: this is currently in `bunfig.toml` to make it possible to know statically which plugins are in use when we eventually integrate this with the `bun build` CLI. These plugins work in `Bun.build()`'s JS API, but are not yet supported in the CLI.
## How this works
Bun uses [`HTMLRewriter`](/docs/api/html-rewriter) to scan for `<script>` and `<link>` tags in HTML files, uses them as entrypoints for [Bun's bundler](/docs/bundler), generates an optimized bundle for the JavaScript/TypeScript/TSX/JSX and CSS files, and serves the result.
@@ -293,5 +309,4 @@ This works similarly to how [`Bun.build` processes HTML files](/docs/bundler/htm
## This is a work in progress
- Client-side hot reloading isn't wired up yet. It will be in the future.
- This doesn't support `bun build` yet. It also will in the future.

234
docs/bundler/hmr.md Normal file
View File

@@ -0,0 +1,234 @@
Hot Module Replacement (HMR) allows you to update modules in a running
application without needing a full page reload. This preserves the application
state and improves the development experience.
HMR is enabled by default when using Bun's full-stack development server.
## `import.meta.hot` API Reference
Bun implements a client-side HMR API modeled after [Vite's `import.meta.hot` API](https://vitejs.dev/guide/api-hmr.html). It can be checked for with `if (import.meta.hot)`, tree-shaking it in production
```ts
if (import.meta.hot) {
// HMR APIs are available.
}
```
However, **this check is often not needed** as Bun will dead-code-eliminate
calls to all of the HMR APIs in production builds.
```ts
// This entire function call will be removed in production!
import.meta.hot.dispose(() => {
console.log("dispose");
});
```
For this to work, Bun forces these APIs to be called without indirection. That means the following do not work:
```ts#invalid-hmr-usage.ts
// INVALID: Assigning `hot` to a variable
const hot = import.meta.hot;
hot.accept();
// INVALID: Assigning `import.meta` to a variable
const meta = import.meta;
meta.hot.accept();
console.log(meta.hot.data);
// INVALID: Passing to a function
doSomething(import.meta.hot.dispose);
// OK: The full phrase "import.meta.hot.<API>" must be called directly:
import.meta.hot.accept();
// OK: `data` can be passed to functions:
doSomething(import.meta.hot.data);
```
{% callout %}
**Note** — The HMR API is still a work in progress. Some features are missing. HMR can be disabled in `Bun.serve` by setting the `development` option to `{ hmr: false }`.
{% endcallout %}
| | Method | Notes |
| --- | ------------------ | --------------------------------------------------------------------- |
| ✅ | `hot.accept()` | Indicate that a hot update can be replaced gracefully. |
| ✅ | `hot.data` | Persist data between module evaluations. |
| ✅ | `hot.dispose()` | Add a callback function to run when a module is about to be replaced. |
| ❌ | `hot.invalidate()` | |
| ✅ | `hot.on()` | Attach an event listener |
| ✅ | `hot.off()` | Remove an event listener from `on`. |
| ❌ | `hot.send()` | |
| 🚧 | `hot.prune()` | **NOTE**: Callback is currently never called. |
| ✅ | `hot.decline()` | No-op to match Vite's `import.meta.hot` |
### `import.meta.hot.accept()`
The `accept()` method indicates that a module can be hot-replaced. When called
without arguments, it indicates that this module can be replaced simply by
re-evaluating the file. After a hot update, importers of this module will be
automatically patched.
```ts#index.ts
import { getCount } from "./foo.ts";
console.log("count is ", getCount());
import.meta.hot.accept();
export function getNegativeCount() {
return -getCount();
}
```
This creates a hot-reloading boundary for all of the files that `index.ts`
imports. That means whenever `foo.ts` or any of its dependencies are saved, the
update will bubble up to `index.ts` will re-evaluate. Files that import
`index.ts` will then be patched to import the new version of
`getNegativeCount()`. If only `index.ts` is updated, only the one file will be
re-evaluated, and the counter in `foo.ts` is reused.
This may be used in combination with `import.meta.hot.data` to transfer state
from the previous module to the new one.
When no modules call `import.meta.hot.accept()` (and there isn't React Fast
Refresh or a plugin calling it for you), the page will reload when the file
updates, and a console warning shows which files were invalidated. This warning
is safe to ignore if it makes more sense to rely on full page reloads.
#### With callback
When provided one callback, `import.meta.hot.accept` will function how it does
in Vite. Instead of patching the importers of this module, it will call the
callback with the new module.
```ts
export const count = 0;
import.meta.hot.accept(newModule => {
if (newModule) {
// newModule is undefined when SyntaxError happened
console.log("updated: count is now ", newModule.count);
}
});
```
Prefer using `import.meta.hot.accept()` without an argument as it usually makes your code easier to understand.
#### Accepting other modules
```ts
import { count } from "./foo";
import.meta.hot.accept("./foo", () => {
if (!newModule) return;
console.log("updated: count is now ", count);
});
```
Indicates that a dependency's module can be accepted. When the dependency is updated, the callback will be called with the new module.
#### With multiple dependencies
```ts
import.meta.hot.accept(["./foo", "./bar"], newModules => {
// newModules is an array where each item corresponds to the updated module
// or undefined if that module had a syntax error
});
```
Indicates that multiple dependencies' modules can be accepted. This variant accepts an array of dependencies, where the callback will receive the updated modules, and `undefined` for any that had errors.
### `import.meta.hot.data`
`import.meta.hot.data` maintains state between module instances during hot
replacement, enabling data transfer from previous to new versions. When
`import.meta.hot.data` is written into, Bun will also mark this module as
capable of self-accepting (equivalent of calling `import.meta.hot.accept()`).
```ts
import { createRoot } from "react-dom/client";
import { App } from "./app";
const root = import.meta.hot.data.root ??= createRoot(elem);
root.render(<App />); // re-use an existing root
```
In production, `data` is inlined to be `{}`, meaning it cannot be used as a state holder.
The above pattern is recommended for stateful modules because Bun knows it can minify `{}.prop ??= value` into `value` in production.
### `import.meta.hot.dispose()`
Attaches an on-dispose callback. This is called:
- Just before the module is replaced with another copy (before the next is loaded)
- After the module is detached (removing all imports to this module, see `import.meta.hot.prune()`)
```ts
const sideEffect = setupSideEffect();
import.meta.hot.dispose(() => {
sideEffect.cleanup();
});
```
This callback is not called on route navigation or when the browser tab closes.
Returning a promise will delay module replacement until the module is disposed.
All dispose callbacks are called in parallel.
### `import.meta.hot.prune()`
Attaches an on-prune callback. This is called when all imports to this module
are removed, but the module was previously loaded.
This can be used to clean up resources that were created when the module was
loaded. Unlike `import.meta.hot.dispose()`, this pairs much better with `accept`
and `data` to manage stateful resources. A full example managing a `WebSocket`:
```ts
import { something } from "./something";
// Initialize or re-use a WebSocket connection
export const ws = (import.meta.hot.data.ws ??= new WebSocket(location.origin));
// If the module's import is removed, clean up the WebSocket connection.
import.meta.hot.prune(() => {
ws.close();
});
```
If `dispose` was used instead, the WebSocket would close and re-open on every
hot update. Both versions of the code will prevent page reloads when imported
files are updated.
### `import.meta.hot.on()` and `off()`
`on()` and `off()` are used to listen for events from the HMR runtime. Event names are prefixed with a prefix so that plugins do not conflict with each other.
```ts
import.meta.hot.on("bun:beforeUpdate", () => {
console.log("before a hot update");
});
```
When a file is replaced, all of its event listeners are automatically removed.
A list of all built-in events:
| Event | Emitted when |
| ---------------------- | ----------------------------------------------------------------------------------------------- |
| `bun:beforeUpdate` | before a hot update is applied. |
| `bun:afterUpdate` | after a hot update is applied. |
| `bun:beforeFullReload` | before a full page reload happens. |
| `bun:beforePrune` | before prune callbacks are called. |
| `bun:invalidate` | when a module is invalidated with `import.meta.hot.invalidate()` |
| `bun:error` | when a build or runtime error occurs |
| `bun:ws:disconnect` | when the HMR WebSocket connection is lost. This can indicate the development server is offline. |
| `bun:ws:connect` | when the HMR WebSocket connects or re-connects. |
For compatibility with Vite, the above events are also available via `vite:*` prefix instead of `bun:*`.

View File

@@ -301,6 +301,6 @@ This is a small wrapper around Bun's support for HTML imports in JavaScript.
### Adding a backend to your frontend
To add a backend to your frontend, you can use the `"static"` option in `Bun.serve`.
To add a backend to your frontend, you can use the `"routes"` option in `Bun.serve`.
Learn more in [the full-stack docs](/docs/bundler/fullstack).

View File

@@ -4,6 +4,12 @@ The Bun bundler implements a set of default loaders out of the box. As a rule of
Bun uses the file extension to determine which built-in _loader_ should be used to parse the file. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](https://bun.sh/docs/bundler/plugins) that extend Bun with custom loaders.
You can explicitly specify which loader to use using the 'loader' import attribute.
```ts
import my_toml from "./my_file" with { loader: "toml" };
```
## Built-in loaders
### `js`

View File

@@ -12,9 +12,12 @@ Options for the `pack` command:
- `--dry-run`: Perform all tasks except writing the tarball to disk.
- `--destination`: Specify the directory where the tarball will be saved.
- `--filename`: Specify an exact file name for the tarball to be saved at.
- `--ignore-scripts`: Skip running pre/postpack and prepare scripts.
- `--gzip-level`: Set a custom compression level for gzip, ranging from 0 to 9 (default is 9).
> Note `--filename` and `--destination` cannot be used at the same time
## bin
To print the path to the `bin` directory for the local project:

View File

@@ -82,6 +82,11 @@ The `--dry-run` flag can be used to simulate the publish process without actuall
$ bun publish --dry-run
```
### `--gzip-level`
Specify the level of gzip compression to use when packing the package. Only applies to `bun publish` without a tarball path argument. Values range from `0` to `9` (default is `9`).
{% bunCLIUsage command="publish" /%}
### `--auth-type`
If you have 2FA enabled for your npm account, `bun publish` will prompt you for a one-time password. This can be done through a browser or the CLI. The `--auth-type` flag can be used to tell the npm registry which method you prefer. The possible values are `web` and `legacy`, with `web` being the default.
@@ -102,7 +107,6 @@ Provide a one-time password directly to the CLI. If the password is valid, this
$ bun publish --otp 123456
```
### `--gzip-level`
Specify the level of gzip compression to use when packing the package. Only applies to `bun publish` without a tarball path argument. Values range from `0` to `9` (default is `9`).
{% bunCLIUsage command="publish" /%}
{% callout %}
**Note** - `bun publish` respects the `NPM_CONFIG_TOKEN` environment variable which can be used when publishing in github actions or automated workflows.
{% /callout %}

View File

@@ -70,7 +70,7 @@ In the Render UI, provide the following values during web service creation:
| ----------------- | ------------- |
| **Runtime** | `Node` |
| **Build Command** | `bun install` |
| **Start Command** | `bun app.js` |
| **Start Command** | `bun app.ts` |
---

View File

@@ -0,0 +1,68 @@
---
name: Extract links from a webpage using HTMLRewriter
---
## Extract links from a webpage
Bun's [HTMLRewriter](https://bun.sh/docs/api/html-rewriter) API can be used to efficiently extract links from HTML content. It works by chaining together CSS selectors to match the elements, text, and attributes you want to process. This is a simple example of how to extract links from a webpage. You can pass `.transform` a `Response`, `Blob`, or `string`.
```ts
async function extractLinks(url: string) {
const links = new Set<string>();
const response = await fetch(url);
const rewriter = new HTMLRewriter().on("a[href]", {
element(el) {
const href = el.getAttribute("href");
if (href) {
links.add(href);
}
},
});
// Wait for the response to be processed
await rewriter.transform(response).blob();
console.log([...links]); // ["https://bun.sh", "/docs", ...]
}
// Extract all links from the Bun website
await extractLinks("https://bun.sh");
```
---
## Convert relative URLs to absolute
When scraping websites, you often want to convert relative URLs (like `/docs`) to absolute URLs. Here's how to handle URL resolution:
```ts
async function extractLinksFromURL(url: string) {
const response = await fetch(url);
const links = new Set<string>();
const rewriter = new HTMLRewriter().on("a[href]", {
element(el) {
const href = el.getAttribute("href");
if (href) {
// Convert relative URLs to absolute
try {
const absoluteURL = new URL(href, url).href;
links.add(absoluteURL);
} catch {
links.add(href);
}
}
},
});
// Wait for the response to be processed
await rewriter.transform(response).blob();
return [...links];
}
const websiteLinks = await extractLinksFromURL("https://example.com");
```
---
See [Docs > API > HTMLRewriter](https://bun.sh/docs/api/html-rewriter) for complete documentation on HTML transformation with Bun.

View File

@@ -0,0 +1,93 @@
---
name: Extract social share images and Open Graph tags
---
## Extract social share images and Open Graph tags
Bun's [HTMLRewriter](https://bun.sh/docs/api/html-rewriter) API can be used to efficiently extract social share images and Open Graph metadata from HTML content. This is particularly useful for building link preview features, social media cards, or web scrapers. We can use HTMLRewriter to match CSS selectors to HTML elements, text, and attributes we want to process.
```ts
interface SocialMetadata {
title?: string;
description?: string;
image?: string;
url?: string;
siteName?: string;
type?: string;
}
async function extractSocialMetadata(url: string): Promise<SocialMetadata> {
const metadata: SocialMetadata = {};
const response = await fetch(url);
const rewriter = new HTMLRewriter()
// Extract Open Graph meta tags
.on('meta[property^="og:"]', {
element(el) {
const property = el.getAttribute("property");
const content = el.getAttribute("content");
if (property && content) {
// Convert "og:image" to "image" etc.
const key = property.replace("og:", "") as keyof SocialMetadata;
metadata[key] = content;
}
},
})
// Extract Twitter Card meta tags as fallback
.on('meta[name^="twitter:"]', {
element(el) {
const name = el.getAttribute("name");
const content = el.getAttribute("content");
if (name && content) {
const key = name.replace("twitter:", "") as keyof SocialMetadata;
// Only use Twitter Card data if we don't have OG data
if (!metadata[key]) {
metadata[key] = content;
}
}
},
})
// Fallback to regular meta tags
.on('meta[name="description"]', {
element(el) {
const content = el.getAttribute("content");
if (content && !metadata.description) {
metadata.description = content;
}
},
})
// Fallback to title tag
.on("title", {
text(text) {
if (!metadata.title) {
metadata.title = text.text;
}
},
});
// Process the response
await rewriter.transform(response).blob();
// Convert relative image URLs to absolute
if (metadata.image && !metadata.image.startsWith("http")) {
try {
metadata.image = new URL(metadata.image, url).href;
} catch {
// Keep the original URL if parsing fails
}
}
return metadata;
}
// Example usage
const metadata = await extractSocialMetadata("https://bun.sh");
console.log(metadata);
// {
// title: "Bun — A fast all-in-one JavaScript runtime",
// description: "Bundle, transpile, install and run JavaScript & TypeScript projects — all in Bun. Bun is a fast all-in-one JavaScript runtime & toolkit designed for speed, complete with a bundler, test runner, and Node.js-compatible package manager.",
// image: "https://bun.sh/share.jpg",
// type: "website",
// ...
// }
```

View File

@@ -0,0 +1,4 @@
{
"name": "HTMLRewriter",
"description": "A collection of guides for using the HTMLRewriter streaming HTML parser with Bun"
}

View File

@@ -0,0 +1,56 @@
---
name: Codesign a single-file JavaScript executable on macOS
description: Fix the "can't be opened because it is from an unidentified developer" Gatekeeper warning when running your JavaScript executable.
---
Compile your executable using the `--compile` flag.
```sh
$ bun build --compile ./path/to/entry.ts --outfile myapp
```
---
List your available signing identities. One of these will be your signing identity that you pass to the `codesign` command. This command requires macOS.
```sh
$ security find-identity -v -p codesigning
1. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "Developer ID Application: Your Name (ZZZZZZZZZZ)"
1 valid identities found
```
---
Optional, but recommended: create an `entitlements.plist` file with the necessary permissions for the JavaScript engine to work correctly.
```xml#entitlements.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
```
---
Sign your executable using the `codesign` command and verify it works.
```bash
$ codesign --entitlements entitlements.plist -vvvv --deep --sign "XXXXXXXXXX" ./myapp --force
$ codesign -vvv --verify ./myapp
```
---
For more information on macOS codesigning, refer to [Apple's Code Signing documentation](https://developer.apple.com/documentation/security/code_signing_services). For details about creating single-file executables with Bun, see [Standalone Executables](/docs/bundler/executables). This guide requires Bun v1.2.4 or newer.

View File

@@ -28,10 +28,21 @@ BAR=world
Variables can also be set via the command line.
```sh
{% codetabs %}
```sh#Linux/macOS
$ FOO=helloworld bun run dev
```
```sh#Windows
# Using CMD
$ set FOO=helloworld && bun run dev
# Using PowerShell
$ $env:FOO="helloworld"; bun run dev
```
{% /codetabs %}
---
See [Docs > Runtime > Environment variables](https://bun.sh/docs/runtime/env) for more information on using environment variables with Bun.

View File

@@ -8,7 +8,7 @@ VSCode extension support is currently buggy. We recommend the [Web Debugger](htt
{% /note %}
Bun speaks the [WebKit Inspector Protocol](https://github.com/oven-sh/bun/blob/main/packages/bun-vscode/types/jsc.d.ts) so you can debug your code with an interactive debugger.
Bun speaks the [WebKit Inspector Protocol](https://github.com/oven-sh/bun/blob/main/packages/bun-inspector-protocol/src/protocol/jsc/index.d.ts) so you can debug your code with an interactive debugger.
---

View File

@@ -1,7 +1,5 @@
Running `bun install` will create a lockfile called `bun.lock`.
https://bun.sh/blog/bun-lock-text-lockfile
#### Should it be committed to git?
Yes

View File

@@ -63,6 +63,20 @@ $ bun install --filter "pkg-*" --filter "!pkg-c"
$ bun install --filter "./packages/pkg-*" --filter "!pkg-c" # or --filter "!./packages/pkg-c"
```
When publishing, `workspace:` versions are replaced by the package's `package.json` version,
```
"workspace:*" -> "1.0.1"
"workspace:^" -> "^1.0.1"
"workspace:~" -> "~1.0.1"
```
Setting a specific version takes precedence over the package's `package.json` version,
```
"workspace:1.0.2" -> "1.0.2" // Even if current version is 1.0.1
```
Workspaces have a couple major benefits.
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency in `package.json`. If package `b` depends on `a`, `bun install` will install your local `packages/a` directory into `node_modules` instead of downloading it from the npm registry.

View File

@@ -147,6 +147,7 @@ If the command runs successfully but `bun --version` is not recognized, it means
[System.EnvironmentVariableTarget]::User
)
```
After running the command, restart your terminal and test with `bun --version`
{% /details %}
@@ -219,11 +220,12 @@ For convenience, here are download links for the latest version:
- [`bun-linux-aarch64.zip`](https://github.com/oven-sh/bun/releases/latest/download/bun-linux-aarch64.zip)
- [`bun-linux-aarch64-musl.zip`](https://github.com/oven-sh/bun/releases/latest/download/bun-linux-aarch64-musl.zip)
- [`bun-darwin-x64.zip`](https://github.com/oven-sh/bun/releases/latest/download/bun-darwin-x64.zip)
- [`bun-darwin-x64-baseline.zip`](https://github.com/oven-sh/bun/releases/latest/download/bun-darwin-x64-baseline.zip)
The `musl` binaries are built for distributions that do not ship with the glibc libraries by default, instead relying on musl. The two most popular distros are Void Linux and Alpine Linux, with the latter is used heavily in Docker containers. If you encounter an error like the following: `bun: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29' not found (required by bun)`, try using the musl binary. Bun's install script automatically chooses the correct binary for your system.
The `baseline` binaries are built for older CPUs which may not support AVX2 instructions. If you run into an "Illegal Instruction" error when running Bun, try using the `baseline` binaries instead. Bun's install scripts automatically chooses the correct binary for your system which helps avoid this issue. Baseline builds are slower than regular builds, so use them only if necessary.
Bun's `x64` binaries target the Haswell CPU architecture, which means they require AVX and AVX2 instructions. For Linux and Windows, the `x64-baseline` binaries are also available which target the Nehalem architecture. If you run into an "Illegal Instruction" error when running Bun, try using the `baseline` binaries instead. Bun's install scripts automatically chooses the correct binary for your system which helps avoid this issue. Baseline builds are slower than regular builds, so use them only if necessary.
Bun also publishes `darwin-x64-baseline` binaries, but these are just a copy of the `darwin-x64` ones so they still have the same CPU requirement. We only maintain these since some tools expect them to exist. Bun requires macOS 13.0 or later, which does not support any CPUs that don't meet our requirement.
<!--
## Native

View File

@@ -215,12 +215,19 @@ export default {
page("bundler", "`Bun.build`", {
description: "Bundle code for consumption in the browser with Bun's native bundler.",
}),
page("bundler/html", "Bundle frontend & static sites", {
page("bundler/html", "HTML & static sites", {
description: `Zero-config HTML bundler for single-page apps and multi-page apps. Automatic bundling, TailwindCSS plugins, TypeScript, JSX, React support, and incredibly fast builds`,
}),
page("bundler/css", "CSS", {
description: `Production ready CSS bundler with support for modern CSS features, CSS modules, and more.`,
}),
page("bundler/fullstack", "Fullstack Dev Server", {
description: "Serve your frontend and backend from the same app with Bun's dev server.",
}),
page("bundler/hmr", "Hot reloading", {
description: `Update modules in a running application without reloading the page using import.meta.hot`,
}),
page("bundler/loaders", "Loaders", {
description: "Bun's built-in loaders for the bundler and runtime",
}),

Some files were not shown because too many files have changed in this diff Show More