Compare commits

...

356 Commits

Author SHA1 Message Date
Don Isaac
a232ee9473 refactor: move string code to string module 2025-03-02 13:58:24 -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
Jarred Sumner
baee1c10d3 Fix flaky patch test (#17301) 2025-02-13 00:22:05 -08:00
Meghan Denny
6353fa4806 node:buffer: fix read (#17299) 2025-02-12 23:37:36 -08:00
chloe caruso
f17ce2b756 hmr fixes (#17239)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-12 23:14:02 -08:00
Meghan Denny
c445cdaf13 cpp: fix asan error in process.setuid/setgid (#17300) 2025-02-12 23:13:07 -08:00
190n
ea65a2ad48 Bump WebKit (#17095)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-12 22:08:53 -08:00
pfg
eb145870cb Remove @intFromPtr(...) == 0 (#17276) 2025-02-12 20:18:03 -08:00
Jarred Sumner
2ea879e29b Add a couple guides 2025-02-12 17:32:16 -08:00
Jarred Sumner
a127f1ab59 Add v8 heap snapshot guide 2025-02-12 17:22:30 -08:00
Shlomo
506ea28b36 feat: load full certificate bundles from NODE_EXTRA_CA_CERTS (#16782) 2025-02-12 11:42:31 -08:00
Jarred Sumner
23ba9af43c Remove two usages of cppFn() (#17278) 2025-02-11 21:33:43 -08:00
Ciro Spaciari
1bb1f59b9e fix(sql) fix fragments containing fragments + concat syntax for parameters (#17273) 2025-02-11 20:08:58 -08:00
Ciro Spaciari
7403088c3b fix(sql) fix ready for query state (#17272) 2025-02-11 20:08:10 -08:00
chloe caruso
2b97d61deb chore: remove some trivial usage of usingnamespace (#17268) 2025-02-11 19:38:52 -08:00
chloe caruso
e22c6c5dbe fix a crash when trying to throw the error for onEnd ($notImplementedIssueFn) (#17271) 2025-02-11 19:38:10 -08:00
Meghan Denny
bdccbbc828 node: fix Buffer.from(arrayBuffer) (#17267) 2025-02-11 18:10:43 -08:00
Zack Radisic
0b6d468b74 CSS fix parsing of @-webkit-keyframes (#17266) 2025-02-11 16:19:33 -08:00
Meghan Denny
251c2b7d06 node:fs: windows: fix integer cast truncating bits when using too large of a mode (#17249) 2025-02-11 00:12:28 -08:00
Zack Radisic
321500c625 CSS stress tests, some fixes (#17131) 2025-02-10 20:56:30 -08:00
Ciro Spaciari
3a231a62b4 fix(sql) fix support for binary numeric values (#17245) 2025-02-10 19:25:52 -08:00
Meghan Denny
7adb2b9502 fix memory leak in ERR_INVALID_ARG_TYPE (#17169) 2025-02-10 18:50:49 -08:00
Vinícius Jardim
c2edbe848f docs(shell): fix incorrect output on "awaiting" example (#17152) 2025-02-10 17:20:18 -08:00
Jarred Sumner
02d4534561 Add =<val> to --help flags that accept values (#17237) 2025-02-10 17:19:09 -08:00
Snoep
cfebfe7731 Added Windows-specific instructions for Bun PATH setup (#17186) 2025-02-10 15:45:14 -08:00
Jarred Sumner
14b93e2ab9 Display CLI usage in docs 2025-02-10 06:48:07 -08:00
Jarred Sumner
9755e02e17 Update bun outdateddocs 2025-02-10 03:53:59 -08:00
Jarred Sumner
a23c11e381 Support BUN_PUBLIC_* and other env options in HTML imports (#17227)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-02-10 02:09:48 -08:00
Meghan Denny
d814f3e6d8 meta: fix disabling of clangd auto header insertion (#17172) 2025-02-10 02:04:21 -08:00
Minsoo Choo
4a7e56b532 Fix latest version display from update-sqlite (#17209) 2025-02-10 02:02:38 -08:00
Jarred Sumner
fb0f28aab9 Remove a .vscode/launch.json config that is rarely used 2025-02-09 22:55:13 -08:00
Jarred Sumner
ba8573494a Add shadcn, tailwind and react detection & templates to bun create. Also: bun install --analyze <files...> (#17035) 2025-02-09 09:36:57 -08:00
github-actions[bot]
14164920b5 deps: update sqlite to 3.490.0 (#17201)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2025-02-09 00:36:36 -08:00
Dylan Conway
2644bad5d4 Fix lexing out of bounds by one (#17168) 2025-02-08 05:23:41 -08:00
Michael H
584db03a74 bun pm pack support "files" starting with ./ (#17135)
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-02-08 01:27:15 -08:00
chloe caruso
f912e0abc4 hot module reloading for HTML import development mode (#16955) 2025-02-08 00:31:30 -08:00
Ciro Spaciari
6e887c8e45 fix(sql) fix TLS verify modes (#17129) 2025-02-07 23:23:05 -08:00
Meghan Denny
374195ea30 node: fix test-buffer-backing-arraybuffer.js (#17161) 2025-02-07 23:22:03 -08:00
Ciro Spaciari
0da7025fb0 fix(sql) decode options from URI properly (#17156) 2025-02-07 15:43:23 -08:00
Meghan Denny
180500181f js: fix Buffer constructor and Buffer.from (#16731) 2025-02-07 15:13:21 -08:00
Ciro Spaciari
c970922456 fix(sql) expose alias in SQLOption type (#17122) 2025-02-06 19:14:34 -08:00
Jarred Sumner
93af28751f Update CMakeLists.txt 2025-02-06 18:07:55 -08:00
190n
4d2a8650e5 test: bump pglite version (#17117) 2025-02-06 14:33:44 -08:00
Don Isaac
146ec7791b fix(node/assert): port more test cases from node (#16895)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-02-06 14:29:59 -08:00
Ciro Spaciari
253faed1cf fix(sql) types (#17118) 2025-02-06 13:37:58 -08:00
Ciro Spaciari
1fe2c3b426 feat(sql) support retrieving array values (#17094) 2025-02-06 02:45:05 -08:00
Jarred Sumner
fad856c03c Support fs.stat, fs.existsSync, fs.readFile, fs.promises.stat, fs.promises.readFile in bun build --compile (#17102)
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2025-02-06 00:06:52 -08:00
Jarred Sumner
2770ecad5c Fixes #16995 (#17101) 2025-02-05 22:35:53 -08:00
Michael H
1684c6246d fix bunx on windows with postinstall scripts (#17076) 2025-02-05 22:31:42 -08:00
Jarred Sumner
d2cdb5031d Fix potential crash when printing errors in bun install (#17027) 2025-02-05 22:17:02 -08:00
pfg
0c8658b350 Fix test-fs-promises-writefile.js on windows (#17053) 2025-02-05 22:12:52 -08:00
pfg
fc7bd569f5 Fix UAF in throwCommandNotFound (#17097) 2025-02-05 21:22:52 -08:00
pfg
5620a7dfac Enable asan on debug macos aarch64 builds (#17058) 2025-02-05 17:24:32 -08:00
Bartłomiej Kalemba
1ccc13ecf7 docs(bunfig): update test runner options (#17040) 2025-02-04 23:56:12 -08:00
Dylan Conway
4d004b90ca Fix bun.lock formatting of bin (#17041) 2025-02-04 23:55:57 -08:00
Zack Radisic
dcf0b719a5 CSS Fixes: light dark, color down-leveling bugs, implement minify for box-shadow (#17055) 2025-02-04 22:50:41 -08:00
Meghan Denny
8634ee3065 fix test-buffer-copy.js (#16640) 2025-02-04 20:19:22 -08:00
Meghan Denny
1819b01932 node: fix test-buffer-fill.js (#16738) 2025-02-04 19:52:11 -08:00
Meghan Denny
b39d84690c implement process.binding('buffer') (#16741)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-02-04 17:59:48 -08:00
Kai Tamkun
d63fe71a6d Fix node:dgram addMembership/dropMembership segfault (#17049) 2025-02-04 15:22:44 -08:00
Dylan Conway
fa55ca31e1 Fix occasional crash on FilePoll deinit (#17050) 2025-02-04 15:22:28 -08:00
190n
a8d159da22 Fix napi_is_buffer/napi_is_typedarray to match Node.js (#17034) 2025-02-03 21:49:27 -08:00
Jarred Sumner
0861c03b37 Fix memory leak in the SQL query string (#17026)
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
2025-02-03 17:38:17 -08:00
Jarred Sumner
7a918d24a7 Fix loading react-jsxdev instead of react-jsx (#17013)
Co-authored-by: chloe caruso <git@paperclover.net>
2025-02-03 14:10:09 -08:00
Bkh
7bef462257 Fix typo in html.ts (#17023) 2025-02-03 12:28:19 -08:00
Jarred Sumner
9cfa3a558b Bump 2025-02-03 07:15:33 -08:00
Jarred Sumner
97ae35dfde Update html.md 2025-02-03 04:08:46 -08:00
Jarred Sumner
1ea14f483c Introduce bun ./index.html (#16993) 2025-02-03 04:06:12 -08:00
Jarred Sumner
ec751159c6 Update typescript.md 2025-02-03 02:40:20 -08:00
Minsoo Choo
fa502506e5 Fix formatting for extern "c" (#16983) 2025-02-02 21:34:58 -08:00
Dylan Conway
06b16fc11e fix 16939 (#16991) 2025-02-02 21:31:40 -08:00
Ciro Spaciari
00a5c4af5a fix(sql) disable idle timeout when still processing data (#16984) 2025-02-02 21:27:22 -08:00
Dylan Conway
cc68f4f025 Fix occasional crash starting debugger thread (#16989) 2025-02-02 05:11:15 -08:00
Jarred Sumner
aac951bd47 Move semver-related structs into their own files (#16987) 2025-02-02 00:20:45 -08:00
Meghan Denny
34419c5f0d zig: only call strlen/wcslen in indexOfSentinel if libc is linked (#16986) 2025-02-01 23:59:45 -08:00
Jarred Sumner
1595b1cc2b Disable stop if necessary timer (#16962) 2025-02-01 22:56:34 -08:00
Michael H
5366c9db33 hopefully auto pr to DT (#16956) 2025-02-01 22:55:19 -08:00
Okinea Dev
87281b6d48 fix: add file association for *.mdc files (#16963) 2025-02-01 22:18:17 -08:00
Jarred Sumner
43fd9326ba Use a more reliable zig download url 2025-02-01 22:12:22 -08:00
Meghan Denny
26d3688e53 zig: update to 0.14.0-dev (#16862)
Co-authored-by: nektro <5464072+nektro@users.noreply.github.com>
2025-02-01 01:11:02 -08:00
pfg
1ddf3fc097 Fix fetch with formdata on some servers (#16947) 2025-01-31 22:39:43 -08:00
Dylan Conway
73bcff9d01 fix 16842 (#16952) 2025-01-31 22:39:30 -08:00
Jarred Sumner
c1708ea6ab Try bringing release/acquire heap access back (#16865)
Co-authored-by: Ben Grant <ben@bun.sh>
2025-01-31 16:13:03 -08:00
Meghan Denny
447121235c node:vm: this error was super confusing without the period 2025-01-31 15:54:06 -08:00
Jarred Sumner
1fa42d81af Bump 2025-01-31 07:08:40 -08:00
Jarred Sumner
22a23add8d Fix import("bun") in Vite (#16938) 2025-01-31 06:34:14 -08:00
Dylan Conway
d4ce421982 Fix node:fs memory leak with AbortSignal (#16788)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-31 05:25:53 -08:00
chloe caruso
322098fa54 allow resolution to work when the source file does not exist (#16851)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-31 05:24:57 -08:00
Jarred Sumner
9acb72d2ad Correctly handle __esModule for loader: "object" (#16885)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2025-01-31 05:24:33 -08:00
Ciro Spaciari
25f6cbd471 fix(s3) fix queue and multipart flow (#16890)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-31 05:19:23 -08:00
Dylan Conway
b098c9ed89 fix(fs): WriteStream pending write fastpath (#16856)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-31 05:14:41 -08:00
Jarred Sumner
212944a5b6 Reduce memory usage of fs.readdir withFileTypes (#16897) 2025-01-31 04:25:58 -08:00
Jarred Sumner
61bf221510 Get pnpm to run inside bun (#16934) 2025-01-31 04:22:03 -08:00
Michael H
891057cd20 fix bun init -h (#16896) 2025-01-31 04:15:44 -08:00
Don Isaac
c51196a8dc fix(install): crash from invalid SemVer with extra wildcard (#16489) 2025-01-31 04:14:53 -08:00
Zack Radisic
f6ec0da125 Various CSS fixing and stability stuff (#16889) 2025-01-31 03:47:49 -08:00
Jarred Sumner
b59b793a32 Fix lifetime issue in BunString (#16930) 2025-01-30 20:46:19 -08:00
Matt Sutkowski
3a4df79a64 chore(docs): remove await from migrate cmd in drizzle.md (#16919) 2025-01-30 17:09:16 -08:00
190n
91f2be57b5 fix(node:os): loadavg() return values on Darwin (#16922) 2025-01-30 17:08:44 -08:00
Don Isaac
b612bc4f47 feat(node/fs): add fs.glob, fs.globSync, and fs.promises.glob (#16676) 2025-01-30 13:20:19 -08:00
Don Isaac
f454c27365 fix: Bun.deepEquals on empty objects with the same prototype (#16894)
Co-authored-by: DonIsaac <22823424+DonIsaac@users.noreply.github.com>
2025-01-30 12:12:51 -08:00
Ciro Spaciari
892764ec43 fix(sql) fix execution queue (#16854) 2025-01-29 23:52:19 -08:00
190n
574a41b03f chore: bump to v1.2.1 (#16891) 2025-01-29 20:19:12 -08:00
Don Isaac
c8f8d2c0bb fix(node/http): re-export WebSocket, CloseEvent, and MessageEvent (#16888) 2025-01-29 18:52:02 -08:00
Meghan Denny
29839737df cpp: synchronize on JSC::getVM since its more likely to be forward compatible (#16688) 2025-01-29 15:50:57 -08:00
Jarred Sumner
4d5ece3f63 Run stopIfNecessary GC timer more (#16871) 2025-01-29 14:40:51 -08:00
Meghan Denny
93a89e5866 meta: update bun.locks with bun 1.2 (#16867)
Co-authored-by: nektro <5464072+nektro@users.noreply.github.com>
2025-01-29 01:47:43 -08:00
Meghan Denny
676e8d1632 zig: delete is_bindgen (#16858) 2025-01-28 23:51:24 -08:00
Meghan Denny
5633ec4334 docker: fix distroless build (#16820) 2025-01-28 18:08:40 -08:00
Meghan Denny
160bf9d563 zig: make install.Resolution.init() not use anytype (#16852) 2025-01-28 18:08:10 -08:00
190n
af27f9e697 Allow WTF timers to participate in the event loop (#15557)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: 190n <190n@users.noreply.github.com>
Co-authored-by: 190n <7763597+190n@users.noreply.github.com>
2025-01-28 17:47:53 -08:00
Jarred Sumner
f826586e78 Remove incorrect assertion 2025-01-28 17:38:52 -08:00
Jarred Sumner
c8344dd3ed Deflake AsyncLocalStorage test 2025-01-28 17:36:29 -08:00
pfg
76f5c91ffb Regression test for 16702 (#16853) 2025-01-28 17:23:57 -08:00
Jarred Sumner
ea301d7235 More docs on fetch 2025-01-28 15:28:15 -08:00
Don Isaac
33fefdda6b fix(node/fs): better validation in fs.Dir (#16806) 2025-01-28 13:38:28 -08:00
Jarred Sumner
8c75c777c2 Update http.md 2025-01-28 00:56:56 -08:00
Jarred Sumner
1da2f4c0ec More Bun.serve() docs 2025-01-28 00:55:54 -08:00
Michael H
e8a0464f03 docs: for fullstack let people know to install bun-plugin-tailwind (#16826) 2025-01-27 21:47:28 -08:00
Aiello
dd93f08215 feat(resolver): Add NODE_PATH support (#14089)
Co-authored-by: chloe caruso <git@paperclover.net>
2025-01-27 20:16:04 -08:00
190n
71eb1476db Fix crash when napi_register_module_v1 returns nullptr (#16816) 2025-01-27 20:13:22 -08:00
Michael H
f8cbb32343 bun build --env defaults to disable now (#16822) 2025-01-27 18:54:17 -08:00
chloe caruso
c08f4abb6a fix(node:fs): set allow above root (#16814)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-01-27 16:02:15 -08:00
Jarred Sumner
ce532901ce Support disabling minification in Bun.serve with development: false (#16796) 2025-01-27 06:51:40 -08:00
Jarred Sumner
68ee83067e Revert "Rewrite the internal Web Stream native bindings to use less m… (#16795) 2025-01-27 05:39:37 -08:00
Jarred Sumner
0d73927440 Add a way to disable RWF_NONBLOCK 2025-01-27 04:27:41 -08:00
Jarred Sumner
06a7499853 Add a couple more assertions (#16791) 2025-01-27 02:48:37 -08:00
Jarred Sumner
5262c7bffd Fixes Bun.fileURLToPath throwing error when it should not (#16789) 2025-01-27 02:14:03 -08:00
Jarred Sumner
cd53d32ccf Fix memory leak in certain cases when long URLs are passed to req.url (#16787) 2025-01-26 23:16:35 -08:00
Jarred Sumner
843cb38d3b Fix memory leak in pathToFileURL (#16784) 2025-01-26 22:35:45 -08:00
Dylan Conway
7410da9c71 fix(install): bun.lockb -> bun.lock with incorrect optional peer dependencies (#16743)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-26 04:29:54 -08:00
Jarred Sumner
77be87b0a7 Fix process.stdin.ref (#16767) 2025-01-26 03:51:16 -08:00
Jarred Sumner
89eea169c0 Fixes #16739 (#16744) 2025-01-26 02:21:40 -08:00
Jarred Sumner
75a95aa5fa Rewrite the internal Web Stream native bindings to use less memory (#16349) 2025-01-26 00:04:39 -08:00
Jarred Sumner
e1d86087f3 bump 2025-01-25 23:08:31 -08:00
Jarred Sumner
55198771a1 Remove unnecessary scope in fs stream (#16754) 2025-01-25 21:08:02 -08:00
Jarred Sumner
0768baf605 Fix Windows EOF double free (#16750) 2025-01-25 03:55:28 -08:00
Jarred Sumner
6367ecc7d5 Fix bug causing AbortSignal to sometimes collect too early (#16748) 2025-01-25 03:37:46 -08:00
Jarred Sumner
f3b0f1fba0 Don't check if the same files exist 248 extra times (#16747) 2025-01-25 02:14:13 -08:00
Meghan Denny
5711073007 ci: set build-zig timeout to 25 minutes (#16745) 2025-01-25 00:56:52 -08:00
Jarred Sumner
f1cfb10658 Update buffer-create.mjs 2025-01-24 23:37:41 -08:00
Ciro Spaciari
23b64f782b toSliced2 becomes toSlice to make sure that exceptions are handled properly (#16734) 2025-01-24 23:27:08 -08:00
pfg
ee1932e92c Don't run json files (#16733) 2025-01-24 22:08:01 -08:00
Meghan Denny
e5b9082319 fix test-buffer-zero-fill-cli.js (#16633) 2025-01-24 21:04:07 -08:00
Ciro Spaciari
4703c81413 fix(expected) dont need to clone string (#16736) 2025-01-24 21:01:28 -08:00
Jarred Sumner
ccb094b7a8 Fix under-reporting memory usage for strings (#16737) 2025-01-24 20:45:34 -08:00
190n
32f5db2df1 Fix bugs in Workers (#16735) 2025-01-24 20:06:16 -08:00
Kai Tamkun
b3e75cee8b dgram: reuseAddr/reusePort fixes (#16677) 2025-01-24 18:51:50 -08:00
Jarred Sumner
8c2c6fe548 Add x25519 support to generateKeyPair (#16725)
Co-authored-by: João Lucas de Oliveira Lopes <55464917+jlucaso1@users.noreply.github.com>
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
2025-01-24 18:49:05 -08:00
Dylan Conway
8e2cf8665a fix(publish): "tarball" and "_attachment" path fix (#16630) 2025-01-24 18:48:42 -08:00
Don Isaac
fb0f54840e fix(node/url): respect process.noDeprecation in url.parse() (#16641)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-24 18:47:19 -08:00
Meghan Denny
7d7a306313 js: Buffer: alias toString as toLocaleString (#16732) 2025-01-24 18:43:08 -08:00
Meghan Denny
d414c78e01 fix test-buffer-concat.js (#16638) 2025-01-24 18:42:44 -08:00
pfg
108b1c7324 Allow indented inline snapshots (#16685) 2025-01-24 18:13:27 -08:00
Ciro Spaciari
8889882719 fix(socket) use the right signature (#16729) 2025-01-24 18:12:55 -08:00
Michael H
4084092627 update bun.lock types (#16687) 2025-01-24 17:13:31 -08:00
Meghan Denny
cc3994cfba js: ERR_INVALID_ARG_TYPE and ERR_BUFFER_OUT_OF_BOUNDS fixes (#16629) 2025-01-24 17:03:31 -08:00
Andrew Barba
8f821b791a bun-lambda: fix http v2 event query parsing (#16684) 2025-01-24 06:45:44 -08:00
Don Isaac
0d53353d36 fix(node/fs): fs.close and fs.Dir.closeSync (#16686) 2025-01-24 05:58:07 -08:00
Jarred Sumner
f7c5b0d5fc Fix Stat constructor, remove native code allocation for stat objects (#16694) 2025-01-24 04:40:00 -08:00
Ani Betts
40d150be5e node: Fix race condition with accessing stdioOptions (#16670) 2025-01-23 18:56:24 -08:00
Kory Smith
24f824c09d Fixes typo where "affect" should have been "effect" (#16660) 2025-01-23 18:54:17 -08:00
tsingkwai
7830e15650 Added command: publish to fish completions (#16593) 2025-01-23 05:15:35 -08:00
Inqnuam
98c7b8452d feat(s3Client): add support for AWS S3 Object Storage Class (#16617) 2025-01-23 05:11:41 -08:00
Jarred Sumner
b54f3f33f0 Clean up node:fs utimes, futimes , and lutimes (#16634) 2025-01-23 05:09:07 -08:00
Meghan Denny
8882615b02 js: add buffer tests that pass now (#16635) 2025-01-23 03:26:16 -08:00
Zack Radisic
70ed282773 CSS fix bug with merging style rules, fix unnecessary backslash, more tests (#16628) 2025-01-22 19:17:42 -08:00
Jarred Sumner
ba2bd5cff4 Fixes #16620 (#16621) 2025-01-22 18:07:27 -08:00
Meghan Denny
f1a5ac4fd3 js: fix printing of empty Symbol's (#16626) 2025-01-22 17:39:50 -08:00
Alistair Smith
4641b6184c docs: enhance S3 presigned urls (#16618) 2025-01-22 16:02:59 -08:00
Meghan Denny
1e75cd5448 fix test/cli/hot/hot.test.ts (#16586) 2025-01-22 10:59:32 -08:00
Alistair Smith
48088d7acb docs: fix s3 presign typo (#16604) 2025-01-22 09:56:13 -08:00
pfg
b0c5a7655d Update docs for bun.lock (#16585) 2025-01-21 22:09:23 -08:00
Ciro Spaciari
5d98e64fd6 make s3 a default client (#16574) 2025-01-21 22:08:52 -08:00
Don Isaac
2cf247a855 chore: remove accidentally-committed files (#16582) 2025-01-21 15:34:41 -08:00
Ciro Spaciari
e44e25ed26 fix(http2) remove queue (#16573)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-21 14:23:23 -08:00
chloe caruso
5819fe49a7 node fs compat pr #2 (#16422)
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Meghan Denny <meghan@bun.sh>
Co-authored-by: dylan-conway <35280289+dylan-conway@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-21 10:28:35 -08:00
Jarred Sumner
427f60c7b2 Update README.md 2025-01-21 07:55:41 -08:00
Jarred Sumner
3395435c6a benches 2025-01-21 07:55:41 -08:00
Jarred Sumner
246936a7a4 Add express folder 2025-01-21 07:55:41 -08:00
Meghan Denny
af79cebf9e unflag experimental css and html (#16561)
Co-authored-by: nektro <5464072+nektro@users.noreply.github.com>
Co-authored-by: Zack Radisic <56137411+zackradisic@users.noreply.github.com>
2025-01-21 06:44:54 -08:00
chloe caruso
4645eb82b0 chore: bump to v1.2 (#16565) 2025-01-21 06:42:03 -08:00
Jarred Sumner
990c84a13b Update sql.md 2025-01-21 04:13:35 -08:00
Ciro Spaciari
16054fa5e8 SQL documentation (#16557)
Co-authored-by: Meghan Denny <meghan@bun.sh>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-21 04:08:16 -08:00
Zack Radisic
703b9962c7 CSS tests and bundler plugins in serve (#16558) 2025-01-21 01:16:48 -08:00
Meghan Denny
86af0f6534 packages/bun-types: remove bun.lockb (#16555) 2025-01-20 23:21:23 -08:00
Dylan Conway
0a7cc1f1c2 Make bun.lock the default for new projects (#16540) 2025-01-20 23:17:52 -08:00
Meghan Denny
c37c5bfc03 pm: fixes for global installs in docker (#14896) 2025-01-20 23:13:47 -08:00
Meghan Denny
27d9cfaf79 bun-types: depend on @types/node@* (#16556) 2025-01-20 23:12:54 -08:00
pfg
1fd7ed6751 Fix typescript emitDecoratorMetadata for getters (#16389)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-01-20 22:14:04 -08:00
1999 changed files with 168488 additions and 48129 deletions

View File

@@ -391,6 +391,8 @@ function getBuildEnv(target, options) {
ENABLE_ASSERTIONS: release ? "OFF" : "ON",
ENABLE_LOGS: release ? "OFF" : "ON",
ABI: abi === "musl" ? "musl" : undefined,
CMAKE_TLS_VERIFY: "0",
};
}
@@ -462,6 +464,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,
};
}
@@ -618,6 +621,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]
@@ -1096,6 +1114,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() {
@@ -227,7 +238,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

@@ -6,6 +6,3 @@ CompileFlags:
Diagnostics:
UnusedIncludes: None
HeaderInsertion:
IncludeBlocks: Preserve # Do not auto-include headers.

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

@@ -0,0 +1,408 @@
---
description: JavaScript class implemented in C++
globs: *.cpp
---
# Implementing JavaScript classes in C++
If there is a publicly accessible Constructor and Prototype, then there are 3 classes:
- IF there are C++ class members we need a destructor, so `class Foo : public JSC::DestructibleObject`, if no C++ class fields (only JS properties) then we don't need a class at all usually. We can instead use JSC::constructEmptyObject(vm, structure) and `putDirectOffset` like in [NodeFSBinding.cpp](mdc:src/bun.js/bindings/NodeFSBinding.cpp).
- class FooPrototype : public JSC::JSNonFinalObject
- class FooConstructor : public JSC::InternalFunction
If there is no publicly accessible Constructor, just the Prototype and the class is necessary. In some cases, we can avoid the prototype entirely (but that's rare).
If there are C++ fields on the Foo class, the Foo class will need an iso subspace added to [DOMClientIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h) and [DOMIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMIsoSubspaces.h). Prototype and Constructor do not need subspaces.
Usually you'll need to #include "root.h" at the top of C++ files or you'll get lint errors.
Generally, defining the subspace looks like this:
```c++
class Foo : public JSC::DestructibleObject {
// ...
template<typename MyClassT, JSC::SubspaceAccess mode>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
return WebCore::subspaceForImpl<MyClassT, WebCore::UseCustomHeapCellType::No>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceFor${MyClassT}.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceFor${MyClassT} = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceFo${MyClassT}.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceFor${MyClassT} = std::forward<decltype(space)>(space); });
}
```
It's better to put it in the .cpp file instead of the .h file, when possible.
## Defining properties
Define properties on the prototype. Use a const HashTableValues like this:
```C++
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckEmail);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckHost);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIP);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIssued);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckPrivateKey);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToLegacyObject);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToString);
static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncVerify);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_ca);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint256);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint512);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subject);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subjectAltName);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_infoAccess);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_keyUsage);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuer);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuerCertificate);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_publicKey);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_raw);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_serialNumber);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFrom);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validTo);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFromDate);
static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validToDate);
static const HashTableValue JSX509CertificatePrototypeTableValues[] = {
{ "ca"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_ca, 0 } },
{ "checkEmail"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckEmail, 2 } },
{ "checkHost"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckHost, 2 } },
{ "checkIP"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIP, 1 } },
{ "checkIssued"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIssued, 1 } },
{ "checkPrivateKey"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckPrivateKey, 1 } },
{ "fingerprint"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint, 0 } },
{ "fingerprint256"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint256, 0 } },
{ "fingerprint512"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint512, 0 } },
{ "infoAccess"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_infoAccess, 0 } },
{ "issuer"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuer, 0 } },
{ "issuerCertificate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuerCertificate, 0 } },
{ "keyUsage"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_keyUsage, 0 } },
{ "publicKey"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_publicKey, 0 } },
{ "raw"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_raw, 0 } },
{ "serialNumber"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_serialNumber, 0 } },
{ "subject"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subject, 0 } },
{ "subjectAltName"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subjectAltName, 0 } },
{ "toJSON"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToJSON, 0 } },
{ "toLegacyObject"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToLegacyObject, 0 } },
{ "toString"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToString, 0 } },
{ "validFrom"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFrom, 0 } },
{ "validFromDate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFromDate, 0 } },
{ "validTo"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validTo, 0 } },
{ "validToDate"_s, static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validToDate, 0 } },
{ "verify"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncVerify, 1 } },
};
```
### Creating a prototype class
Follow a pattern like this:
```c++
class JSX509CertificatePrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;
static constexpr unsigned StructureFlags = Base::StructureFlags;
static JSX509CertificatePrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
{
JSX509CertificatePrototype* prototype = new (NotNull, allocateCell<JSX509CertificatePrototype>(vm)) JSX509CertificatePrototype(vm, structure);
prototype->finishCreation(vm);
return prototype;
}
template<typename, JSC::SubspaceAccess>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
return &vm.plainObjectSpace();
}
DECLARE_INFO;
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
structure->setMayBePrototype(true);
return structure;
}
private:
JSX509CertificatePrototype(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure)
{
}
void finishCreation(JSC::VM& vm);
};
const ClassInfo JSX509CertificatePrototype::s_info = { "X509Certificate"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSX509CertificatePrototype) };
void JSX509CertificatePrototype::finishCreation(VM& vm)
{
Base::finishCreation(vm);
reifyStaticProperties(vm, JSX509Certificate::info(), JSX509CertificatePrototypeTableValues, *this);
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}
} // namespace Bun
```
### Getter definition:
```C++
JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_ca, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSX509Certificate* thisObject = jsDynamicCast<JSX509Certificate*>(JSValue::decode(thisValue));
if (UNLIKELY(!thisObject)) {
Bun::throwThisTypeError(*globalObject, scope, "JSX509Certificate"_s, "ca"_s);
return {};
}
return JSValue::encode(jsBoolean(thisObject->view().isCA()));
}
```
### Setter definition
```C++
JSC_DEFINE_CUSTOM_SETTER(jsImportMetaObjectSetter_require, (JSGlobalObject * jsGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, PropertyName propertyName))
{
ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
if (UNLIKELY(!thisObject))
return false;
JSValue value = JSValue::decode(encodedValue);
if (!value.isCell()) {
// TODO:
return true;
}
thisObject->requireProperty.set(thisObject->vm(), thisObject, value.asCell());
return true;
}
```
### Function definition
```C++
JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
auto *thisObject = jsDynamicCast<MyClassT*>(callFrame->thisValue());
if (UNLIKELY(!thisObject)) {
Bun::throwThisTypeError(*globalObject, scope, "MyClass"_s, "myFunctionName"_s);
return {};
}
return JSValue::encode(functionThatReturnsJSValue(vm, globalObject, thisObject));
}
```
### Constructor definition
```C++
JSC_DECLARE_HOST_FUNCTION(callStats);
JSC_DECLARE_HOST_FUNCTION(constructStats);
class JSStatsConstructor final : public JSC::InternalFunction {
public:
using Base = JSC::InternalFunction;
static constexpr unsigned StructureFlags = Base::StructureFlags;
static JSStatsConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype)
{
JSStatsConstructor* constructor = new (NotNull, JSC::allocateCell<JSStatsConstructor>(vm)) JSStatsConstructor(vm, structure);
constructor->finishCreation(vm, prototype);
return constructor;
}
DECLARE_INFO;
template<typename CellType, JSC::SubspaceAccess>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
return &vm.internalFunctionSpace();
}
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
}
private:
JSStatsConstructor(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure, callStats, constructStats)
{
}
void finishCreation(JSC::VM& vm, JSC::JSObject* prototype)
{
Base::finishCreation(vm, 0, "Stats"_s);
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
}
};
```
### Structure caching
If there's a class, prototype, and constructor:
1. Add the `JSC::LazyClassStructure` to [ZigGlobalObject.h](mdc:src/bun.js/bindings/ZigGlobalObject.h)
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++#ZigGlobalObject.cpp
void GlobalObject::finishCreation(VM& vm) {
// ...
m_JSStatsBigIntClassStructure.initLater(
[](LazyClassStructure::Initializer& init) {
// Call the function to initialize our class structure.
Bun::initJSBigIntStatsClassStructure(init);
});
```
Then, implement the function that creates the structure:
```c++
void setupX509CertificateClassStructure(LazyClassStructure::Initializer& init)
{
auto* prototypeStructure = JSX509CertificatePrototype::createStructure(init.vm, init.global, init.global->objectPrototype());
auto* prototype = JSX509CertificatePrototype::create(init.vm, init.global, prototypeStructure);
auto* constructorStructure = JSX509CertificateConstructor::createStructure(init.vm, init.global, init.global->functionPrototype());
auto* constructor = JSX509CertificateConstructor::create(init.vm, init.global, constructorStructure, prototype);
auto* structure = JSX509Certificate::createStructure(init.vm, init.global, prototype);
init.setPrototype(prototype);
init.setStructure(structure);
init.setConstructor(constructor);
}
```
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++
JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
if (!callFrame->argumentCount()) {
Bun::throwError(globalObject, scope, ErrorCode::ERR_MISSING_ARGS, "X509Certificate constructor requires at least one argument"_s);
return {};
}
JSValue arg = callFrame->uncheckedArgument(0);
if (!arg.isCell()) {
Bun::throwError(globalObject, scope, ErrorCode::ERR_INVALID_ARG_TYPE, "X509Certificate constructor argument must be a Buffer, TypedArray, or string"_s);
return {};
}
auto* zigGlobalObject = defaultGlobalObject(globalObject);
Structure* structure = zigGlobalObject->m_JSX509CertificateClassStructure.get(zigGlobalObject);
JSValue newTarget = callFrame->newTarget();
if (UNLIKELY(zigGlobalObject->m_JSX509CertificateClassStructure.constructor(zigGlobalObject) != newTarget)) {
auto scope = DECLARE_THROW_SCOPE(vm);
if (!newTarget) {
throwTypeError(globalObject, scope, "Class constructor X509Certificate cannot be invoked without 'new'"_s);
return {};
}
auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject()));
RETURN_IF_EXCEPTION(scope, {});
structure = InternalFunction::createSubclassStructure(
globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure());
scope.release();
}
return JSValue::encode(createX509Certificate(vm, globalObject, structure, arg));
}
```
### Expose to Zig
To expose the constructor to zig:
```c++
extern "C" JSC::EncodedJSValue Bun__JSBigIntStatsObjectConstructor(Zig::GlobalObject* globalobject)
{
return JSValue::encode(globalobject->m_JSStatsBigIntClassStructure.constructor(globalobject));
}
```
Zig:
```zig
extern "c" fn Bun__JSBigIntStatsObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue;
pub const getBigIntStatsConstructor = Bun__JSBigIntStatsObjectConstructor;
```
To create an object (instance) of a JS class defined in C++ from Zig, follow the __toJS convention like this:
```c++
// X509* is whatever we need to create the object
extern "C" EncodedJSValue Bun__X509__toJS(Zig::GlobalObject* globalObject, X509* cert)
{
// ... implementation details
auto* structure = globalObject->m_JSX509CertificateClassStructure.get(globalObject);
return JSValue::encode(JSX509Certificate::create(globalObject->vm(), structure, globalObject, WTFMove(cert)));
}
```
And from Zig:
```zig
const X509 = opaque {
// ... class
extern fn Bun__X509__toJS(*JSC.JSGlobalObject, *X509) JSC.JSValue;
pub fn toJS(this: *X509, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
return Bun__X509__toJS(globalObject, this);
}
};
```

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

1
.gitattributes vendored
View File

@@ -15,6 +15,7 @@
*.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.mdc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.mjs text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.mts text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

View File

@@ -4,7 +4,7 @@ description: An internal version of the 'oven-sh/setup-bun' action.
inputs:
bun-version:
type: string
description: "The version of bun to install: 'latest', 'canary', 'bun-v1.0.0', etc."
description: "The version of bun to install: 'latest', 'canary', 'bun-v1.2.0', etc."
default: latest
required: false
baseline:

View File

@@ -10,7 +10,7 @@ on:
merge_group:
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
LLVM_VERSION: "18.1.8"
LLVM_VERSION_MAJOR: "18"

View File

@@ -10,7 +10,7 @@ on:
merge_group:
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
LLVM_VERSION: "18.1.8"
LLVM_VERSION_MAJOR: "18"

View File

@@ -5,7 +5,7 @@ on:
workflow_dispatch:
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
OXLINT_VERSION: "0.15.0"
jobs:

View File

@@ -10,7 +10,7 @@ on:
merge_group:
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
jobs:
prettier-format:

View File

@@ -44,6 +44,10 @@ on:
description: Should types be released to npm?
type: boolean
default: false
use-definitelytyped:
description: "Should types be PR'd to DefinitelyTyped?"
type: boolean
default: false
jobs:
sign:
@@ -66,7 +70,7 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: "1.1.44"
bun-version: "1.2.3"
- name: Install Dependencies
run: bun install
- name: Sign Release
@@ -94,7 +98,7 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: "1.1.44"
bun-version: "1.2.3"
- name: Install Dependencies
run: bun install
- name: Release
@@ -123,7 +127,7 @@ jobs:
if: ${{ env.BUN_VERSION != 'canary' }}
uses: ./.github/actions/setup-bun
with:
bun-version: "1.1.44"
bun-version: "1.2.3"
- name: Setup Bun
if: ${{ env.BUN_VERSION == 'canary' }}
uses: ./.github/actions/setup-bun
@@ -155,6 +159,52 @@ jobs:
with:
package: packages/bun-types/package.json
token: ${{ secrets.NPM_TOKEN }}
definitelytyped:
name: Make pr to DefinitelyTyped to update `bun-types` version
runs-on: ubuntu-latest
needs: npm-types
if: ${{ github.event_name == 'release' || github.event.inputs.use-definitelytyped == 'true' }}
permissions:
contents: read
steps:
- 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: ./bun/.github/actions/setup-bun
with:
bun-version: "1.2.0"
- id: bun-version
run: echo "BUN_VERSION=${BUN_VERSION#bun-v}" >> "$GITHUB_OUTPUT"
- name: Update bun-types version in package.json
run: |
bun -e '
const file = Bun.file("./types/bun/package.json");
const json = await file.json();
const version = "${{ steps.bun-version.outputs.BUN_VERSION }}";
json.dependencies["bun-types"] = version;
json.version = version.slice(0, version.lastIndexOf(".")) + ".9999";
await file.write(JSON.stringify(json, null, 4) + "\n");
'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
if: ${{ env.BUN_LATEST == 'true' && env.BUN_VERSION != 'canary'}}
with:
token: ${{ secrets.ROBOBUN_TOKEN }}
add-paths: ./types/bun/package.json
title: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}"
commit-message: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}"
body: |
Update `bun-types` version to ${{ steps.bun-version.outputs.BUN_VERSION }}
https://bun.sh/blog/${{ env.BUN_VERSION }}
push-to-fork: oven-sh/DefinitelyTyped
branch: ${{env.BUN_VERSION}}
docker:
name: Release to Dockerhub
runs-on: ubuntu-latest
@@ -181,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
@@ -189,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: |
@@ -206,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
@@ -265,7 +315,7 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: "1.1.44"
bun-version: "1.2.0"
- name: Install Dependencies
run: bun install
- name: Release
@@ -309,7 +359,7 @@ jobs:
uses: ./.github/actions/setup-bun
if: ${{ env.BUN_LATEST == 'true' }}
with:
bun-version: "1.1.44"
bun-version: "1.2.0"
- name: Bump version
uses: ./.github/actions/bump
if: ${{ env.BUN_LATEST == 'true' }}

View File

@@ -4,7 +4,7 @@ permissions:
contents: read
env:
LLVM_VERSION: 16
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
on:
workflow_call:

View File

@@ -9,7 +9,7 @@ on:
required: true
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
jobs:
bump:

View File

@@ -55,7 +55,7 @@ jobs:
# Convert numeric version to semantic version for display
LATEST_MAJOR=$((10#$LATEST_VERSION_NUM / 1000000))
LATEST_MINOR=$((($LATEST_VERSION_NUM / 1000) % 1000))
LATEST_MINOR=$((($LATEST_VERSION_NUM / 10000) % 100))
LATEST_PATCH=$((10#$LATEST_VERSION_NUM % 1000))
LATEST_VERSION="$LATEST_MAJOR.$LATEST_MINOR.$LATEST_PATCH"

View File

@@ -10,7 +10,7 @@ on:
merge_group:
env:
BUN_VERSION: "1.1.44"
BUN_VERSION: "1.2.0"
jobs:
zig-format:

6
.gitignore vendored
View File

@@ -16,6 +16,7 @@
.vscode/clang*
.vscode/cpp*
.zig-cache
.bake-debug
*.a
*.bc
*.big
@@ -151,6 +152,7 @@ src/bake/generated.ts
test/cli/install/registry/packages/publish-pkg-*
test/cli/install/registry/packages/@secret/publish-pkg-8
test/js/third_party/prisma/prisma/sqlite/dev.db-journal
tmp
# Dependencies
/vendor
@@ -178,4 +180,6 @@ test/js/third_party/prisma/prisma/sqlite/dev.db-journal
.buildkite/ci.yml
*.sock
scratch*.{js,ts,tsx,cjs,mjs}
scratch*.{js,ts,tsx,cjs,mjs}
*.bun-build

View File

@@ -7,3 +7,4 @@ src/react-refresh.js
*.min.js
test/snippets
test/js/node/test
bun.lock

4
.vscode/launch.json generated vendored
View File

@@ -736,6 +736,10 @@
"name": "BUN_DEBUG_QUIET_LOGS",
"value": "1",
},
{
"name": "BUN_DEBUG_SYS",
"value": "1",
},
{
"name": "BUN_GARBAGE_COLLECTOR_LEVEL",
"value": "2",

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]": {
@@ -63,6 +64,7 @@
"editor.tabSize": 4,
"editor.defaultFormatter": "xaver.clang-format",
},
"clangd.arguments": ["--header-insertion=never"],
// JavaScript
"prettier.enable": true,
@@ -140,6 +142,7 @@
},
"files.associations": {
"*.idl": "cpp",
"*.mdc": "markdown",
"array": "cpp",
},
"C_Cpp.files.exclude": {

View File

@@ -12,6 +12,12 @@ list(APPEND CMAKE_MODULE_PATH
include(Policies)
include(Globals)
if (CMAKE_HOST_WIN32)
# Workaround for TLS certificate verification issue on Windows when downloading from GitHub
# Remove this once we've bumped the CI machines build image
set(CMAKE_TLS_VERIFY 0)
endif()
# --- Compilers ---
if(CMAKE_HOST_APPLE)

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

2
LATEST
View File

@@ -1 +1 @@
1.1.44
1.2.4

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-16 2>/dev/null || which clang 2>/dev/null)
REAL_CXX = $(shell which clang++-16 2>/dev/null || which clang++ 2>/dev/null)
CLANG_FORMAT = $(shell which clang-format-16 2>/dev/null || which clang-format 2>/dev/null)
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)
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@16)
LLVM_PREFIX = $(shell brew --prefix llvm@18)
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@16' or set LLVM_PREFIX=/path/to/llvm")
LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@18' 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-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
-DCMAKE_RANLIB=$(which llvm-18-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-16 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
AR = $(shell which llvm-ar-18 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
endif
OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE)
@@ -286,7 +286,7 @@ STRIP=/usr/bin/strip
endif
ifeq ($(OS_NAME),linux)
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-16 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-18 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 "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@16"; exit 1; fi
@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
@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)
@@ -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
@@ -1261,6 +1261,7 @@ jsc-build-mac-compile:
-DBUN_FAST_TLS=ON \
-DENABLE_FTL_JIT=ON \
-DUSE_BUN_JSC_ADDITIONS=ON \
-DUSE_BUN_EVENT_LOOP=ON \
-G Ninja \
$(CMAKE_FLAGS_WITHOUT_RELEASE) \
-DPTHREAD_JIT_PERMISSIONS_API=1 \
@@ -1284,6 +1285,7 @@ jsc-build-mac-compile-lto:
-DUSE_THIN_ARCHIVES=OFF \
-DBUN_FAST_TLS=ON \
-DUSE_BUN_JSC_ADDITIONS=ON \
-DUSE_BUN_EVENT_LOOP=ON \
-DCMAKE_C_FLAGS="-flto=full" \
-DCMAKE_CXX_FLAGS="-flto=full" \
-DENABLE_FTL_JIT=ON \
@@ -1299,6 +1301,7 @@ jsc-build-mac-compile-lto:
.PHONY: jsc-build-mac-compile-debug
jsc-build-mac-compile-debug:
mkdir -p $(WEBKIT_DEBUG_DIR) $(WEBKIT_DIR);
# to disable asan, remove -DENABLE_SANITIZERS=address and add -DENABLE_MALLOC_HEAP_BREAKDOWN=ON
cd $(WEBKIT_DEBUG_DIR) && \
ICU_INCLUDE_DIRS="$(HOMEBREW_PREFIX)opt/icu4c/include" \
cmake \
@@ -1307,9 +1310,9 @@ jsc-build-mac-compile-debug:
-DCMAKE_BUILD_TYPE=Debug \
-DUSE_THIN_ARCHIVES=OFF \
-DENABLE_FTL_JIT=ON \
-DENABLE_MALLOC_HEAP_BREAKDOWN=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DUSE_BUN_JSC_ADDITIONS=ON \
-DUSE_BUN_EVENT_LOOP=ON \
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
-G Ninja \
@@ -1318,6 +1321,7 @@ jsc-build-mac-compile-debug:
-DUSE_PTHREAD_JIT_PERMISSIONS_API=ON \
-DENABLE_REMOTE_INSPECTOR=ON \
-DUSE_VISIBILITY_ATTRIBUTE=1 \
-DENABLE_SANITIZERS=address \
$(WEBKIT_DIR) \
$(WEBKIT_DEBUG_DIR) && \
CFLAGS="$(CFLAGS) -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -ffat-lto-objects" \
@@ -1334,6 +1338,7 @@ jsc-build-linux-compile-config:
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
-DUSE_THIN_ARCHIVES=OFF \
-DUSE_BUN_JSC_ADDITIONS=ON \
-DUSE_BUN_EVENT_LOOP=ON \
-DENABLE_FTL_JIT=ON \
-DENABLE_REMOTE_INSPECTOR=ON \
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
@@ -1357,6 +1362,7 @@ jsc-build-linux-compile-config-debug:
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
-DUSE_THIN_ARCHIVES=OFF \
-DUSE_BUN_JSC_ADDITIONS=ON \
-DUSE_BUN_EVENT_LOOP=ON \
-DENABLE_FTL_JIT=ON \
-DENABLE_REMOTE_INSPECTOR=ON \
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
@@ -1375,14 +1381,14 @@ jsc-build-linux-compile-config-debug:
jsc-build-linux-compile-build:
mkdir -p $(WEBKIT_RELEASE_DIR) && \
cd $(WEBKIT_RELEASE_DIR) && \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \
cmake --build $(WEBKIT_RELEASE_DIR) --config relwithdebuginfo --target jsc
.PHONY: jsc-build-linux-compile-build-debug
jsc-build-linux-compile-build-debug:
mkdir -p $(WEBKIT_DEBUG_DIR) && \
cd $(WEBKIT_DEBUG_DIR) && \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \
cmake --build $(WEBKIT_DEBUG_DIR) --config Debug --target jsc

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "bench",

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "expect-to-equal",
@@ -136,7 +136,7 @@
"@jest/console": ["@jest/console@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "slash": "^3.0.0" } }, "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A=="],
"@jest/core": ["@jest/core@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/reporters": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.4.3", "jest-config": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-resolve-dependencies": "^29.4.3", "jest-runner": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" } }, "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ=="],
"@jest/core": ["@jest/core@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/reporters": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.4.3", "jest-config": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-resolve-dependencies": "^29.4.3", "jest-runner": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ=="],
"@jest/environment": ["@jest/environment@29.4.3", "", { "dependencies": { "@jest/fake-timers": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "jest-mock": "^29.4.3" } }, "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA=="],
@@ -148,7 +148,7 @@
"@jest/globals": ["@jest/globals@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/types": "^29.4.3", "jest-mock": "^29.4.3" } }, "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA=="],
"@jest/reporters": ["@jest/reporters@29.4.3", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" } }, "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg=="],
"@jest/reporters": ["@jest/reporters@29.4.3", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg=="],
"@jest/schemas": ["@jest/schemas@29.4.3", "", { "dependencies": { "@sinclair/typebox": "^0.25.16" } }, "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg=="],
@@ -384,13 +384,13 @@
"istanbul-reports": ["istanbul-reports@3.1.5", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w=="],
"jest": ["jest@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/types": "^29.4.3", "import-local": "^3.0.2", "jest-cli": "^29.4.3" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "bin": { "jest": "bin/jest.js" } }, "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA=="],
"jest": ["jest@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/types": "^29.4.3", "import-local": "^3.0.2", "jest-cli": "^29.4.3" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA=="],
"jest-changed-files": ["jest-changed-files@29.4.3", "", { "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" } }, "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ=="],
"jest-circus": ["jest-circus@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.4.3", "jest-matcher-utils": "^29.4.3", "jest-message-util": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "p-limit": "^3.1.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw=="],
"jest-cli": ["jest-cli@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "bin": { "jest": "bin/jest.js" } }, "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg=="],
"jest-cli": ["jest-cli@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg=="],
"jest-config": ["jest-config@29.4.3", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.4.3", "@jest/types": "^29.4.3", "babel-jest": "^29.4.3", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.4.3", "jest-environment-node": "^29.4.3", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-runner": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "peerDependencies": { "@types/node": "*", "ts-node": ">=9.0.0" }, "optionalPeers": ["ts-node"] }, "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ=="],
@@ -600,7 +600,7 @@
"vite": ["vite@4.1.2", "", { "dependencies": { "esbuild": "^0.16.14", "fsevents": "~2.3.2", "postcss": "^8.4.21", "resolve": "^1.22.1", "rollup": "^3.10.0" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["less", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-MWDb9Rfy3DI8omDQySbMK93nQqStwbsQWejXRY2EBzEWKmLAXWb1mkI9Yw2IJrc+oCvPCI1Os5xSSIBYY6DEAw=="],
"vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="],
"vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="],
"walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],

175
bench/express/.gitignore vendored Normal file
View File

@@ -0,0 +1,175 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Caches
.cache
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

37
bench/express/README.md Normal file
View File

@@ -0,0 +1,37 @@
# express benchmark
This benchmarks a hello world express server.
To install dependencies:
```bash
bun install
```
To run in Bun:
```sh
bun ./express.mjs
```
To run in Node:
```sh
node ./express.mjs
```
To run in Deno:
```sh
deno run -A ./express.mjs
```
To benchmark each runtime:
```bash
oha http://localhost:3000 -n 500000 -H "Accept-Encoding: identity"
```
We recommend using `oha` or `bombardier` for benchmarking. We do not recommend using `ab`, as it uses HTTP/1.0 which stopped being used by web browsers in the early 2000s. We also do not recommend using autocannon, as the node:http client is not performant enough to measure the throughput of Bun's HTTP server.
Note the `Accept-Encoding: identity` header exists to prevent Deno's HTTP server from compressing the response.

BIN
bench/express/bun.lockb Executable file

Binary file not shown.

14
bench/express/express.mjs Normal file
View File

@@ -0,0 +1,14 @@
// See the README.md for more information
import express from "express";
const app = express();
const port = process.env.PORT || 3000;
let i = 0;
app.get("/", (req, res) => {
res.send("Hello World! (request number: " + i++ + ")");
});
app.listen(port, () => {
console.log(`Express server listening on port ${port}`);
});

View File

@@ -0,0 +1,14 @@
{
"name": "express",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"express": "5"
}
}

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "bench",

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

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "bench",

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "simple-react",
@@ -1045,7 +1045,7 @@
"ncp": ["ncp@2.0.0", "", { "bin": { "ncp": "./bin/ncp" } }, "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="],
"next": ["next@12.3.4", "", { "dependencies": { "@next/env": "12.3.4", "@next/swc-android-arm-eabi": "12.3.4", "@next/swc-android-arm64": "12.3.4", "@next/swc-darwin-arm64": "12.3.4", "@next/swc-darwin-x64": "12.3.4", "@next/swc-freebsd-x64": "12.3.4", "@next/swc-linux-arm-gnueabihf": "12.3.4", "@next/swc-linux-arm64-gnu": "12.3.4", "@next/swc-linux-arm64-musl": "12.3.4", "@next/swc-linux-x64-gnu": "12.3.4", "@next/swc-linux-x64-musl": "12.3.4", "@next/swc-win32-arm64-msvc": "12.3.4", "@next/swc-win32-ia32-msvc": "12.3.4", "@next/swc-win32-x64-msvc": "12.3.4", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.0.7", "use-sync-external-store": "1.2.0" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", "react": "^17.0.2 || ^18.0.0-0", "react-dom": "^17.0.2 || ^18.0.0-0", "sass": "^1.3.0" }, "optionalPeers": ["node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ=="],
"next": ["next@12.3.4", "", { "dependencies": { "@next/env": "12.3.4", "@next/swc-android-arm-eabi": "12.3.4", "@next/swc-android-arm64": "12.3.4", "@next/swc-darwin-arm64": "12.3.4", "@next/swc-darwin-x64": "12.3.4", "@next/swc-freebsd-x64": "12.3.4", "@next/swc-linux-arm-gnueabihf": "12.3.4", "@next/swc-linux-arm64-gnu": "12.3.4", "@next/swc-linux-arm64-musl": "12.3.4", "@next/swc-linux-x64-gnu": "12.3.4", "@next/swc-linux-x64-musl": "12.3.4", "@next/swc-win32-arm64-msvc": "12.3.4", "@next/swc-win32-ia32-msvc": "12.3.4", "@next/swc-win32-x64-msvc": "12.3.4", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.0.7", "use-sync-external-store": "1.2.0" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", "react": "^17.0.2 || ^18.0.0-0", "react-dom": "^17.0.2 || ^18.0.0-0", "sass": "^1.3.0" }, "optionalPeers": ["fibers", "node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ=="],
"nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="],
@@ -1649,7 +1649,7 @@
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
"ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="],
"ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="],
"xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="],
@@ -1701,7 +1701,7 @@
"@parcel/packager-js/globals": ["globals@13.20.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ=="],
"@parcel/reporter-dev-server/ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="],
"@parcel/reporter-dev-server/ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="],
"@parcel/transformer-babel/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="],

View File

@@ -23,7 +23,7 @@ $ hyperfine --prepare 'rm -rf node_modules' --runs 1 'bun install' 'pnpm install
To run the benchmark with offline mode but without lockfiles:
```sh
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 'rm bun.lockb && bun install' 'rm pnpm-lock.yaml && pnpm install --prefer-offline' 'rm yarn.lock && yarn --offline' 'rm package-lock.json && npm install --prefer-offline'
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 'rm bun.lock && bun install' 'rm pnpm-lock.yaml && pnpm install --prefer-offline' 'rm yarn.lock && yarn --offline' 'rm package-lock.json && npm install --prefer-offline'
```
##

175
bench/postgres/.gitignore vendored Normal file
View File

@@ -0,0 +1,175 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Caches
.cache
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

27
bench/postgres/README.md Normal file
View File

@@ -0,0 +1,27 @@
# Postgres table load benchmark
To install dependencies:
```bash
bun install
```
To run in Bun:
```bash
bun ./index.mjs
```
To run in Node.js:
```bash
node index.mjs
```
To run in Deno:
```bash
deno run -A index.mjs
```
You will need a localhost Postgres server running.

BIN
bench/postgres/bun.lockb Executable file

Binary file not shown.

47
bench/postgres/index.mjs Normal file
View File

@@ -0,0 +1,47 @@
const isBun = typeof globalThis?.Bun?.sql !== "undefined";
import postgres from "postgres";
const sql = isBun ? Bun.sql : postgres;
// Create the table if it doesn't exist
await sql`
CREATE TABLE IF NOT EXISTS "users_bun_bench" (
id SERIAL PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
dob TEXT NOT NULL
)
`;
// Check if users already exist
const existingUsers = await sql`SELECT COUNT(*) as count FROM "users_bun_bench"`;
if (+(existingUsers?.[0]?.count ?? existingUsers?.count) < 100) {
// Generate 100 users if none exist
const users = Array.from({ length: 100 }, (_, i) => ({
first_name: `FirstName${i}`,
last_name: `LastName${i}`,
email: `user${i}@example.com`,
dob: new Date(1970 + Math.floor(Math.random() * 30), Math.floor(Math.random() * 12), Math.floor(Math.random() * 28))
.toISOString()
.split("T")[0],
}));
// Insert all users
await sql`
INSERT INTO users_bun_bench (first_name, last_name, email, dob) ${sql(users)}
`;
}
const type = isBun ? "Bun.sql" : "postgres";
console.time(type);
let promises = [];
for (let i = 0; i < 100_000; i++) {
promises.push(sql`SELECT * FROM "users_bun_bench" LIMIT 100`);
if (i % 100 === 0 && promises.length > 1) {
await Promise.all(promises);
promises.length = 0;
}
}
await Promise.all(promises);
console.timeEnd(type);

View File

@@ -0,0 +1,14 @@
{
"name": "postgres",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"postgres": "^3.4.5"
}
}

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "react-hello-world",

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "scan",

View File

@@ -25,6 +25,10 @@ bench("Buffer.from('short string')", () => {
return Buffer.from("short string");
});
bench("new Buffer('short string')", () => {
return new Buffer("short string");
});
const loooong = "long string".repeat(9999).split("").join(" ");
bench("Buffer.byteLength('long string'.repeat(9999))", () => {
return Buffer.byteLength(loooong);
@@ -45,6 +49,14 @@ bench("Buffer.from(Uint8Array(0))", () => {
return Buffer.from(empty);
});
bench("new Buffer(ArrayBuffer(100))", () => {
return new Buffer(hundred);
});
bench("new Buffer(Uint8Array(100))", () => {
return new Buffer(hundredArray);
});
bench("new Buffer(Uint8Array(0))", () => {
return new Buffer(empty);
});

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"));

View File

@@ -1,7 +1,7 @@
// import { Buffer } from "buffer";
var buf = new Buffer(1024);
var view = new DataView(buf.buffer);
var INTERVAL = 9999999;
var INTERVAL = 9_999_999;
var time = (name, fn) => {
for (let i = 0; i < INTERVAL; i++) fn();

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,25 @@
import { posix } from "path";
import { bench, run } from "../runner.mjs";
const pathConfigurations = [
["", ""],
[".", "."],
["/foo/bar", "/foo/bar"],
["/foo/bar/baz", "/foo/bar"],
["/foo/bar", "/foo/bar/baz"],
["/foo/bar/baz", "/foo/bar/qux"],
["/foo/bar/baz", "/foo/bar/baz/qux"],
["/foo/bar/baz", "/foo/bar/baz/qux/quux"],
["/", "/foo"],
["/foo", "/"],
["foo/bar/baz", "foo/bar/qux"],
["../foo/bar", "../foo/baz"],
];
pathConfigurations.forEach(([from, to]) => {
bench(`relative(${JSON.stringify(from)}, ${JSON.stringify(to)})`, () => {
globalThis.abc = posix.relative(from, to);
});
});
await run();

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "bench",

View File

@@ -1,4 +1,4 @@
import { Database } from "https://deno.land/x/sqlite3@0.11.1/mod.ts";
import { Database } from "https://deno.land/x/sqlite3@0.12.0/mod.ts";
import { bench, run } from "../runner.mjs";
const db = new Database("./src/northwind.sqlite");

82
bench/sqlite/deno.lock generated Normal file
View File

@@ -0,0 +1,82 @@
{
"version": "4",
"specifiers": {
"jsr:@denosaurs/plug@1": "1.0.6",
"jsr:@std/assert@0.217": "0.217.0",
"jsr:@std/assert@0.221": "0.221.0",
"jsr:@std/encoding@0.221": "0.221.0",
"jsr:@std/fmt@0.221": "0.221.0",
"jsr:@std/fs@0.221": "0.221.0",
"jsr:@std/path@0.217": "0.217.0",
"jsr:@std/path@0.221": "0.221.0"
},
"jsr": {
"@denosaurs/plug@1.0.6": {
"integrity": "6cf5b9daba7799837b9ffbe89f3450510f588fafef8115ddab1ff0be9cb7c1a7",
"dependencies": [
"jsr:@std/encoding",
"jsr:@std/fmt",
"jsr:@std/fs",
"jsr:@std/path@0.221"
]
},
"@std/assert@0.217.0": {
"integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642"
},
"@std/assert@0.221.0": {
"integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a"
},
"@std/encoding@0.221.0": {
"integrity": "d1dd76ef0dc5d14088411e6dc1dede53bf8308c95d1537df1214c97137208e45"
},
"@std/fmt@0.221.0": {
"integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a"
},
"@std/fs@0.221.0": {
"integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286",
"dependencies": [
"jsr:@std/assert@0.221",
"jsr:@std/path@0.221"
]
},
"@std/path@0.217.0": {
"integrity": "1217cc25534bca9a2f672d7fe7c6f356e4027df400c0e85c0ef3e4343bc67d11",
"dependencies": [
"jsr:@std/assert@0.217"
]
},
"@std/path@0.221.0": {
"integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095",
"dependencies": [
"jsr:@std/assert@0.221"
]
}
},
"remote": {
"https://deno.land/x/sqlite3@0.11.1/deno.json": "77126f50d0efce1375173fae94d4df7f732cd25f05d8aa74f8ff801ef4d85caf",
"https://deno.land/x/sqlite3@0.11.1/deps.ts": "d2f23a4489d27ed7ba1f601b86a85ff488a87603e4be7a15f3ea15154fc288ec",
"https://deno.land/x/sqlite3@0.11.1/mod.ts": "3169f246c0eddd6ed82862758f4109f167b7ba5538236240fbb26a129f1bc16c",
"https://deno.land/x/sqlite3@0.11.1/src/blob.ts": "3681353b3c97bc43f9b02f8d1c3269c0dc4eb9cb5d3af16c7ce4d1e1ec7507c4",
"https://deno.land/x/sqlite3@0.11.1/src/constants.ts": "85fd27aa6e199093f25f5f437052e16fd0e0870b96ca9b24a98e04ddc8b7d006",
"https://deno.land/x/sqlite3@0.11.1/src/database.ts": "063281b9b4340c781ba611cb5fef7ab0fc885cb87ed4c8ec123fd772e0da5f8b",
"https://deno.land/x/sqlite3@0.11.1/src/ffi.ts": "6648dc15f10312df9d2fc8e6e2be230d82a552f28b8f77d03f32bbfba9198888",
"https://deno.land/x/sqlite3@0.11.1/src/statement.ts": "5fe86e1a0136a259c055a03988e74490d9d131c058b4c1a18385a6770cd47e2a",
"https://deno.land/x/sqlite3@0.11.1/src/util.ts": "c6604183d2ec5fb17fa0a018572ed5f2317b319dbd7bf48d88a5d06ff25b2cc3",
"https://deno.land/x/sqlite3@0.12.0/deno.json": "b03d6de05f953886662ea987212539af8456a91352684c84af2188520449d42a",
"https://deno.land/x/sqlite3@0.12.0/deps.ts": "d2f23a4489d27ed7ba1f601b86a85ff488a87603e4be7a15f3ea15154fc288ec",
"https://deno.land/x/sqlite3@0.12.0/mod.ts": "3169f246c0eddd6ed82862758f4109f167b7ba5538236240fbb26a129f1bc16c",
"https://deno.land/x/sqlite3@0.12.0/src/blob.ts": "330886fae9714e4a612786f44d8117d65f91e778cf3f40de59b34879fc7ca9ab",
"https://deno.land/x/sqlite3@0.12.0/src/constants.ts": "85fd27aa6e199093f25f5f437052e16fd0e0870b96ca9b24a98e04ddc8b7d006",
"https://deno.land/x/sqlite3@0.12.0/src/database.ts": "4d380d7f0e5a2cf74635a9fcd2b4e27373533f2816cde5357067e51fd22ad8d0",
"https://deno.land/x/sqlite3@0.12.0/src/ffi.ts": "795b598eeae4d12f182e7bcdab524b74b0f01d6deae7f4d8ce63f25c06a46154",
"https://deno.land/x/sqlite3@0.12.0/src/statement.ts": "e8ccde898aef47c7a2514953aca5359a44a285bc3dc0de5819d66f891f477be1",
"https://deno.land/x/sqlite3@0.12.0/src/util.ts": "c6604183d2ec5fb17fa0a018572ed5f2317b319dbd7bf48d88a5d06ff25b2cc3"
},
"workspace": {
"packageJson": {
"dependencies": [
"npm:better-sqlite3@8.5.0"
]
}
}
}

View File

@@ -1,5 +1,5 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "websocket-server",

View File

@@ -19,15 +19,16 @@ 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.13.0";
const recommended_zig_version = "0.14.0-dev.2987+183bb8b08";
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," ++
"Bun requires Zig version " ++ recommended_zig_version ++ " (found " ++
builtin.zig_version_string ++ "). 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.",
);
}
@@ -46,6 +47,7 @@ const BunBuildOptions = struct {
sha: []const u8,
/// enable debug logs in release builds
enable_logs: bool = false,
enable_asan: bool,
tracy_callstack_depth: u16,
reported_nodejs_version: Version,
/// To make iterating on some '@embedFile's faster, we load them at runtime
@@ -81,10 +83,7 @@ const BunBuildOptions = struct {
var opts = b.addOptions();
opts.addOption([]const u8, "base_path", b.pathFromRoot("."));
opts.addOption([]const u8, "codegen_path", std.fs.path.resolve(b.graph.arena, &.{
b.build_root.path.?,
this.codegen_path,
}) catch @panic("OOM"));
opts.addOption([]const u8, "codegen_path", std.fs.path.resolve(b.graph.arena, &.{ b.build_root.path.?, this.codegen_path }) catch @panic("OOM"));
opts.addOption(bool, "codegen_embed", this.shouldEmbedCode());
opts.addOption(u32, "canary_revision", this.canary_revision orelse 0);
@@ -152,8 +151,7 @@ pub fn getCpuModel(os: OperatingSystem, arch: Arch) ?Target.Query.CpuModel {
pub fn build(b: *Build) !void {
std.log.info("zig compiler v{s}", .{builtin.zig_version_string});
b.zig_lib_dir = b.zig_lib_dir orelse b.path("vendor/zig/lib");
checked_file_exists = std.AutoHashMap(u64, void).init(b.allocator);
// TODO: Upgrade path for 0.14.0
// b.graph.zig_lib_directory = brk: {
@@ -208,7 +206,7 @@ pub fn build(b: *Build) !void {
const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0";
b.reference_trace = ref_trace: {
const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 16;
const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 24;
break :ref_trace if (trace == 0) null else trace;
};
@@ -276,6 +274,7 @@ pub fn build(b: *Build) !void {
.tracy_callstack_depth = b.option(u16, "tracy_callstack_depth", "") orelse 10,
.enable_logs = b.option(bool, "enable_logs", "Enable logs in release") orelse false,
.enable_asan = b.option(bool, "enable_asan", "Enable asan") orelse false,
};
// zig build obj
@@ -330,11 +329,25 @@ pub fn build(b: *Build) !void {
.{ .os = .windows, .arch = .x86_64 },
});
}
{
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 },
});
}
{
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 },
});
}
// zig build translate-c-headers
{
const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out");
step.dependOn(&b.addInstallFile(getTranslateC(b, b.host, .Debug).getOutput(), "translated-c-headers.zig").step);
step.dependOn(&b.addInstallFile(getTranslateC(b, b.graph.host, .Debug).getOutput(), "translated-c-headers.zig").step);
}
// zig build enum-extractor
@@ -362,7 +375,7 @@ pub fn addMultiCheck(
const check_target = b.resolveTargetQuery(.{
.os_tag = OperatingSystem.stdOSTag(check.os),
.cpu_arch = check.arch,
.cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_cpu_arch,
.cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_arch_os,
.os_version_min = getOSVersionMin(check.os),
.glibc_version = if (check.musl) null else getOSGlibCVersion(check.os),
});
@@ -380,6 +393,7 @@ pub fn addMultiCheck(
.reported_nodejs_version = root_build_options.reported_nodejs_version,
.codegen_path = root_build_options.codegen_path,
.no_llvm = root_build_options.no_llvm,
.enable_asan = root_build_options.enable_asan,
};
var obj = addBunObject(b, &options);
@@ -413,7 +427,7 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
.name = if (opts.optimize == .Debug) "bun-debug" else "bun",
.root_source_file = switch (opts.os) {
.wasm => b.path("root_wasm.zig"),
else => b.path("root.zig"),
else => b.path("src/main.zig"),
// else => b.path("root_css.zig"),
},
.target = opts.target,
@@ -427,8 +441,15 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
.omit_frame_pointer = false,
.strip = false, // stripped at the end
});
if (opts.enable_asan) {
if (@hasField(Build.Module, "sanitize_address")) {
obj.root_module.sanitize_address = true;
} else {
const fail_step = b.addFail("asan is not supported on this platform");
obj.step.dependOn(&fail_step.step);
}
}
obj.bundle_compiler_rt = false;
obj.formatted_panics = true;
obj.root_module.omit_frame_pointer = false;
// Link libc
@@ -481,25 +502,21 @@ pub fn addInstallObjectFile(
}, b.fmt("{s}.o", .{name})).step;
}
var checked_file_exists: std.AutoHashMap(u64, void) = undefined;
fn exists(path: []const u8) bool {
const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false;
file.close();
const entry = checked_file_exists.getOrPut(std.hash.Wyhash.hash(0, path)) catch unreachable;
if (entry.found_existing) {
// It would've panicked.
return true;
}
std.fs.accessAbsolute(path, .{ .mode = .read_only }) catch return false;
return true;
}
fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
const os = opts.os;
const io_path = switch (os) {
.mac => "src/io/io_darwin.zig",
.linux => "src/io/io_linux.zig",
.windows => "src/io/io_windows.zig",
else => "src/io/io_stub.zig",
};
obj.root_module.addAnonymousImport("async_io", .{
.root_source_file = b.path(io_path),
});
const zlib_internal_path = switch (os) {
.windows => "src/deps/zlib.win32.zig",
.linux, .mac => "src/deps/zlib.posix.zig",
@@ -532,6 +549,7 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
.{ .file = "bun-error/index.js", .enable = opts.shouldEmbedCode() },
.{ .file = "bun-error/bun-error.css", .enable = opts.shouldEmbedCode() },
.{ .file = "fallback-decoder.js", .enable = opts.shouldEmbedCode() },
.{ .file = "node-fallbacks/react-refresh.js", .enable = opts.shouldEmbedCode() },
.{ .file = "node-fallbacks/assert.js", .enable = opts.shouldEmbedCode() },
.{ .file = "node-fallbacks/buffer.js", .enable = opts.shouldEmbedCode() },
.{ .file = "node-fallbacks/console.js", .enable = opts.shouldEmbedCode() },
@@ -568,6 +586,15 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
});
}
}
inline for (.{
.{ .import = "completions-bash", .file = b.path("completions/bun.bash") },
.{ .import = "completions-zsh", .file = b.path("completions/bun.zsh") },
.{ .import = "completions-fish", .file = b.path("completions/bun.fish") },
}) |entry| {
obj.root_module.addAnonymousImport(entry.import, .{
.root_source_file = entry.file,
});
}
if (os == .windows) {
obj.root_module.addAnonymousImport("bun_shim_impl.exe", .{
@@ -607,7 +634,7 @@ const WindowsShim = struct {
.optimize = .ReleaseFast,
.use_llvm = true,
.use_lld = true,
.unwind_tables = false,
.unwind_tables = .none,
.omit_frame_pointer = true,
.strip = true,
.linkage = .static,

View File

@@ -1,11 +1,11 @@
{
"lockfileVersion": 0,
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "bun",
"devDependencies": {
"@mdn/browser-compat-data": "~5.5.28",
"@types/bun": "^1.1.3",
"@types/bun": "*",
"@types/react": "^18.3.3",
"@typescript-eslint/eslint-plugin": "^7.11.0",
"@typescript-eslint/parser": "^7.11.0",
@@ -28,7 +28,7 @@
"packages/bun-types": {
"name": "bun-types",
"dependencies": {
"@types/node": "~20.12.8",
"@types/node": "*",
"@types/ws": "~8.5.10",
},
"devDependencies": {
@@ -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.6", "", { "dependencies": { "bun-types": "1.1.17" } }, "sha512-uJgKjTdX0GkWEHZzQzFsJkWp5+43ZS7HC8sZPFnOwnSo1AsNl2q9o2bFeS23disNDqbggEgyFkKCHl/w8iZsMA=="],
"@types/bun": ["@types/bun@1.1.17", "", { "dependencies": { "bun-types": "1.1.44" } }, "sha512-zZt0Kao/8hAwNOXh4bmt8nKbMEd4QD8n7PeTGF+NZTVY5ouXhU/TX7jUj4He1p7mgY+WdplnU1B6MB1j17vdzg=="],
"@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@20.12.14", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
"@types/node": ["@types/node@22.10.7", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg=="],
"@types/prop-types": ["@types/prop-types@15.7.12", "", {}, "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="],
@@ -257,7 +257,7 @@
"builtins": ["builtins@1.0.3", "", {}, "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ=="],
"bun-types": ["bun-types@workspace:packages/bun-types", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" }, "devDependencies": { "@biomejs/biome": "^1.5.3", "@definitelytyped/dtslint": "^0.0.199", "@definitelytyped/eslint-plugin": "^0.0.197", "typescript": "^5.0.2" } }],
"bun-types": ["bun-types@workspace:packages/bun-types"],
"call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="],
@@ -265,7 +265,7 @@
"camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="],
"caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
"caniuse-lite": ["caniuse-lite@1.0.30001695", "", {}, "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw=="],
"capital-case": ["capital-case@1.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case-first": "^2.0.2" } }, "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A=="],
@@ -845,7 +845,7 @@
"unbox-primitive": ["unbox-primitive@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw=="],
"undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
"update-browserslist-db": ["update-browserslist-db@1.1.0", "", { "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ=="],
@@ -915,17 +915,21 @@
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@types/ws/@types/node": ["@types/node@20.12.14", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"are-we-there-yet/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
"autoprefixer/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
"babel-code-frame/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="],
"babel-code-frame/js-tokens": ["js-tokens@3.0.2", "", {}, "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg=="],
"bun-types/typescript": ["typescript@5.5.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ=="],
"browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="],
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
@@ -1003,6 +1007,8 @@
"@definitelytyped/utils/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
"@types/ws/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"are-we-there-yet/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],

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

@@ -44,6 +44,13 @@ if(WIN32)
)
endif()
if(ENABLE_ASAN)
register_compiler_flags(
DESCRIPTION "Enable AddressSanitizer"
-fsanitize=address
)
endif()
# --- Optimization level ---
if(DEBUG)
register_compiler_flags(

View File

@@ -86,6 +86,11 @@ optionx(ENABLE_LTO BOOL "If LTO (link-time optimization) should be used" DEFAULT
if(LINUX)
optionx(ENABLE_VALGRIND BOOL "If Valgrind support should be enabled" DEFAULT OFF)
endif()
if(DEBUG AND APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT ON)
else()
optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT OFF)
endif()
optionx(ENABLE_PRETTIER BOOL "If prettier should be ran" DEFAULT OFF)

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,17 +28,16 @@ else()
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
set(ZIG_NAME zig-${ZIG_OS}-${ZIG_ARCH}-${ZIG_VERSION})
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://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILENAME})
set(ZIG_DOWNLOAD_URL https://github.com/oven-sh/zig/releases/download/autobuild-${ZIG_COMMIT}/${ZIG_FILENAME})
execute_process(
COMMAND
@@ -62,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

@@ -179,6 +179,32 @@ register_command(
${BUN_NODE_FALLBACKS_OUTPUTS}
)
# An embedded copy of react-refresh is used when the user forgets to install it.
# The library is not versioned alongside React.
set(BUN_REACT_REFRESH_OUTPUT ${BUN_NODE_FALLBACKS_OUTPUT}/react-refresh.js)
register_command(
TARGET
bun-node-fallbacks-react-refresh
COMMENT
"Building node-fallbacks/react-refresh.js"
CWD
${BUN_NODE_FALLBACKS_SOURCE}
COMMAND
${BUN_EXECUTABLE} build
${BUN_NODE_FALLBACKS_SOURCE}/node_modules/react-refresh/cjs/react-refresh-runtime.development.js
--outfile=${BUN_REACT_REFRESH_OUTPUT}
--target=browser
--format=cjs
--minify
--define:process.env.NODE_ENV=\"'development'\"
SOURCES
${BUN_NODE_FALLBACKS_SOURCE}/package.json
${BUN_NODE_FALLBACKS_SOURCE}/bun.lock
${BUN_NODE_FALLBACKS_NODE_MODULES}
OUTPUTS
${BUN_REACT_REFRESH_OUTPUT}
)
set(BUN_ERROR_CODE_SCRIPT ${CWD}/src/codegen/generate-node-errors.ts)
set(BUN_ERROR_CODE_SOURCES
@@ -228,6 +254,7 @@ set(BUN_ZIG_GENERATED_CLASSES_OUTPUTS
${CODEGEN_PATH}/ZigGeneratedClasses+DOMIsoSubspaces.h
${CODEGEN_PATH}/ZigGeneratedClasses+lazyStructureImpl.h
${CODEGEN_PATH}/ZigGeneratedClasses.zig
${CODEGEN_PATH}/ZigGeneratedClasses.lut.txt
)
register_command(
@@ -403,9 +430,12 @@ set(BUN_OBJECT_LUT_SOURCES
${CWD}/src/bun.js/bindings/ZigGlobalObject.lut.txt
${CWD}/src/bun.js/bindings/JSBuffer.cpp
${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
)
set(BUN_OBJECT_LUT_OUTPUTS
@@ -413,9 +443,12 @@ set(BUN_OBJECT_LUT_OUTPUTS
${CODEGEN_PATH}/ZigGlobalObject.lut.h
${CODEGEN_PATH}/JSBuffer.lut.h
${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
)
macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps)
@@ -447,6 +480,8 @@ foreach(i RANGE 0 ${BUN_OBJECT_LUT_SOURCES_MAX_INDEX})
bun-codegen-lut-${filename}
COMMENT
"Generating ${filename}.lut.h"
DEPENDS
${BUN_OBJECT_LUT_SOURCE}
COMMAND
${BUN_EXECUTABLE}
run
@@ -478,6 +513,8 @@ WEBKIT_ADD_SOURCE_DEPENDENCIES(
${CODEGEN_PATH}/ZigGlobalObject.lut.h
)
WEBKIT_ADD_SOURCE_DEPENDENCIES(
${CWD}/src/bun.js/bindings/InternalModuleRegistry.cpp
${CODEGEN_PATH}/InternalModuleRegistryConstants.h
@@ -491,8 +528,7 @@ file(GLOB_RECURSE BUN_ZIG_SOURCES ${CONFIGURE_DEPENDS}
list(APPEND BUN_ZIG_SOURCES
${CWD}/build.zig
${CWD}/root.zig
${CWD}/root_wasm.zig
${CWD}/src/main.zig
${BUN_BINDGEN_ZIG_OUTPUTS}
)
@@ -501,6 +537,7 @@ set(BUN_ZIG_GENERATED_SOURCES
${BUN_FALLBACK_DECODER_OUTPUT}
${BUN_RUNTIME_JS_OUTPUT}
${BUN_NODE_FALLBACKS_OUTPUTS}
${BUN_REACT_REFRESH_OUTPUT}
${BUN_ERROR_CODE_OUTPUTS}
${BUN_ZIG_GENERATED_CLASSES_OUTPUTS}
${BUN_JAVASCRIPT_OUTPUTS}
@@ -585,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
@@ -722,6 +760,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
@@ -820,6 +859,15 @@ if(NOT WIN32)
)
endif()
if (ENABLE_ASAN)
target_compile_options(${bun} PUBLIC
-fsanitize=address
)
target_link_libraries(${bun} PUBLIC
-fsanitize=address
)
endif()
target_compile_options(${bun} PUBLIC
-Werror=return-type
-Werror=return-stack-address
@@ -1045,6 +1093,7 @@ add_custom_target(dependencies DEPENDS ${BUN_TARGETS})
if(APPLE)
target_link_libraries(${bun} PRIVATE icucore resolv)
target_compile_definitions(${bun} PRIVATE U_DISABLE_RENAMING=1)
endif()
if(USE_STATIC_SQLITE)

View File

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

View File

@@ -4,7 +4,7 @@ register_repository(
REPOSITORY
oven-sh/mimalloc
COMMIT
82b2c2277a4d570187c07b376557dc5bde81d848
7a4d7b8d18f8159a808aade63eb93ea6abd06924
)
set(MIMALLOC_CMAKE_ARGS
@@ -19,6 +19,10 @@ set(MIMALLOC_CMAKE_ARGS
-DMI_SKIP_COLLECT_ON_EXIT=ON
)
if(ENABLE_ASAN)
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_TRACK_ASAN=ON)
endif()
if(DEBUG)
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_DEBUG_FULL=ON)
endif()
@@ -27,13 +31,7 @@ if(ENABLE_VALGRIND)
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_VALGRIND=ON)
endif()
if(WIN32)
if(DEBUG)
set(MIMALLOC_LIBRARY mimalloc-static-debug)
else()
set(MIMALLOC_LIBRARY mimalloc-static)
endif()
elseif(DEBUG)
if(DEBUG)
set(MIMALLOC_LIBRARY mimalloc-debug)
else()
set(MIMALLOC_LIBRARY mimalloc)

View File

@@ -9,6 +9,14 @@ find_command(
>=1.1.26
)
if (NOT CI)
# If node.js is not installed, it is extremely easy to make this path point to
# a tempdir such as /private/tmp/bun-node-ce532901c/bun, which may cause this
# CMake configuration break after tempdir is cleaned up (ex. after reboot).
get_filename_component(BUN_EXECUTABLE ${BUN_EXECUTABLE} REALPATH)
set(BUN_EXECUTABLE ${BUN_EXECUTABLE} CACHE FILEPATH "Bun executable" FORCE)
endif()
# If this is not set, some advanced features are not checked.
# https://github.com/oven-sh/bun/blob/cd7f6a1589db7f1e39dc4e3f4a17234afbe7826c/src/bun.js/javascript.zig#L1069-L1072
setenv(BUN_GARBAGE_COLLECTOR_LEVEL 1)

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 9e3b60e4a6438d20ee6f8aa5bec6b71d2b7d213f)
set(WEBKIT_VERSION f14adff4c39ba08174b84a942f9584028fc9a7ae)
endif()
string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX)
@@ -79,6 +79,10 @@ else()
set(WEBKIT_SUFFIX "${WEBKIT_SUFFIX}")
endif()
if(ENABLE_ASAN)
set(WEBKIT_SUFFIX "${WEBKIT_SUFFIX}-asan")
endif()
set(WEBKIT_NAME bun-webkit-${WEBKIT_OS}-${WEBKIT_ARCH}${WEBKIT_SUFFIX})
set(WEBKIT_FILENAME ${WEBKIT_NAME}.tar.gz)
setx(WEBKIT_DOWNLOAD_URL https://github.com/oven-sh/WebKit/releases/download/autobuild-${WEBKIT_VERSION}/${WEBKIT_FILENAME})

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.13.0")
optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "131a009ba2eb127a3447d05b9e12f710429aa5ee")
set(ZIG_COMMIT "bb9d6ab2c0bbbf20cc24dad03e88f3b3ffdb7de7")
optionx(ZIG_TARGET STRING "The zig target to use" DEFAULT ${DEFAULT_ZIG_TARGET})
if(CMAKE_BUILD_TYPE STREQUAL "Release")
@@ -77,8 +76,8 @@ 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
SOURCES
${CWD}/cmake/scripts/DownloadZig.cmake

View File

@@ -183,3 +183,4 @@ complete -c bun -n "__fish_use_subcommand" -a "unlink" -d "Unregister a local np
complete -c bun -n "__fish_use_subcommand" -a "pm" -d "Additional package management utilities" -f
complete -c bun -n "__fish_use_subcommand" -a "x" -d "Execute a package binary, installing if needed" -f
complete -c bun -n "__fish_use_subcommand" -a "outdated" -d "Display the latest versions of outdated dependencies" -f
complete -c bun -n "__fish_use_subcommand" -a "publish" -d "Publish your package from local to npm" -f

View File

@@ -57,6 +57,8 @@ ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
COPY --from=build /usr/local/bin/bun /usr/local/bin/
COPY docker-entrypoint.sh /usr/local/bin/
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
# Temporarily use the `build`-stage /tmp folder to access the glibc APKs:
RUN --mount=type=bind,from=build,source=/tmp,target=/tmp \

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
@@ -68,6 +68,8 @@ ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
RUN groupadd bun \
--gid 1000 \

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
@@ -60,6 +60,8 @@ FROM debian:bullseye
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
# Disable the runtime transpiler cache by default inside Docker containers.
# On ephemeral containers, the cache is not useful

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
@@ -67,12 +67,18 @@ ARG BUN_INSTALL_BIN=/usr/local/bin
ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
COPY --from=build /usr/local/bin/bun /usr/local/bin/
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
# Temporarily use the `build`-stage image binaries to create a symlink:
RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \
--mount=type=bind,from=build,source=/bin,target=/bin <<EOF
--mount=type=bind,from=build,source=/bin,target=/bin \
--mount=type=bind,from=build,source=/usr/lib,target=/usr/lib \
--mount=type=bind,from=build,source=/lib,target=/lib \
<<EOF
ln -s /usr/local/bin/bun /usr/local/bin/bunx
which bunx
mkdir -p /usr/local/bun-node-fallback-bin
ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/nodebun
EOF
ENTRYPOINT ["/usr/local/bin/bun"]

View File

@@ -111,6 +111,38 @@ const reader = stream.getReader();
const { value, done } = await reader.read();
```
### Streaming request bodies
You can also stream data in request bodies using a `ReadableStream`:
```ts
const stream = new ReadableStream({
start(controller) {
controller.enqueue("Hello");
controller.enqueue(" ");
controller.enqueue("World");
controller.close();
},
});
const response = await fetch("http://example.com", {
method: "POST",
body: stream,
});
```
When using streams with HTTP(S):
- The data is streamed directly to the network without buffering the entire body in memory
- If the connection is lost, the stream will be canceled
- The `Content-Length` header is not automatically set unless the stream has a known size
When using streams with S3:
- For PUT/POST requests, Bun automatically uses multipart upload
- The stream is consumed in chunks and uploaded in parallel
- Progress can be monitored through the S3 options
### Fetching a URL with a timeout
To fetch a URL with a timeout, use `AbortSignal.timeout`:
@@ -180,6 +212,116 @@ await fetch("https://example.com", {
This is similar to how it works in Node's `net` module.
#### Disable TLS validation
To disable TLS validation, set `rejectUnauthorized` to `false`:
```ts
await fetch("https://example.com", {
tls: {
rejectUnauthorized: false,
},
});
```
This is especially useful to avoid SSL errors when using self-signed certificates, but this disables TLS validation and should be used with caution.
### Request options
In addition to the standard fetch options, Bun provides several extensions:
```ts
const response = await fetch("http://example.com", {
// Control automatic response decompression (default: true)
decompress: true,
// Disable connection reuse for this request
keepalive: false,
// Debug logging level
verbose: true, // or "curl" for more detailed output
});
```
### Protocol support
Beyond HTTP(S), Bun's fetch supports several additional protocols:
#### S3 URLs - `s3://`
Bun supports fetching from S3 buckets directly.
```ts
// Using environment variables for credentials
const response = await fetch("s3://my-bucket/path/to/object");
// Or passing credentials explicitly
const response = await fetch("s3://my-bucket/path/to/object", {
s3: {
accessKeyId: "YOUR_ACCESS_KEY",
secretAccessKey: "YOUR_SECRET_KEY",
region: "us-east-1",
},
});
```
Note: Only PUT and POST methods support request bodies when using S3. For uploads, Bun automatically uses multipart upload for streaming bodies.
You can read more about Bun's S3 support in the [S3](https://bun.sh/docs/api/s3) documentation.
#### File URLs - `file://`
You can fetch local files using the `file:` protocol:
```ts
const response = await fetch("file:///path/to/file.txt");
const text = await response.text();
```
On Windows, paths are automatically normalized:
```ts
// Both work on Windows
const response = await fetch("file:///C:/path/to/file.txt");
const response2 = await fetch("file:///c:/path\\to/file.txt");
```
#### Data URLs - `data:`
Bun supports the `data:` URL scheme:
```ts
const response = await fetch("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==");
const text = await response.text(); // "Hello, World!"
```
#### Blob URLs - `blob:`
You can fetch blobs using URLs created by `URL.createObjectURL()`:
```ts
const blob = new Blob(["Hello, World!"], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const response = await fetch(url);
```
### Error handling
Bun's fetch implementation includes several specific error cases:
- Using a request body with GET/HEAD methods will throw an error (which is expected for the fetch API)
- Attempting to use both `proxy` and `unix` options together will throw an error
- TLS certificate validation failures when `rejectUnauthorized` is true (or undefined)
- S3 operations may throw specific errors related to authentication or permissions
### Content-Type handling
Bun automatically sets the `Content-Type` header for request bodies when not explicitly provided:
- For `Blob` objects, uses the blob's `type`
- For `FormData`, sets appropriate multipart boundary
- For JSON objects, sets `application/json`
## Debugging
To help with debugging, you can pass `verbose: true` to `fetch`:
@@ -306,3 +448,16 @@ import { write } from "bun";
await write("output.txt", response);
```
### Implementation details
- Connection pooling is enabled by default but can be disabled per-request with `keepalive: false`. The `"Connection: close"` header can also be used to disable keep-alive.
- Large file uploads are optimized using the operating system's `sendfile` syscall under specific conditions:
- The file must be larger than 32KB
- The request must not be using a proxy
- On macOS, only regular files (not pipes, sockets, or devices) can use `sendfile`
- When these conditions aren't met, or when using S3/streaming uploads, Bun falls back to reading the file into memory
- This optimization is particularly effective for HTTP (not HTTPS) requests where the file can be sent directly from the kernel to the network stack
- S3 operations automatically handle signing requests and merging authentication headers
Note: Many of these features are Bun-specific extensions to the standard fetch API.

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 %}

File diff suppressed because it is too large Load Diff

View File

@@ -68,7 +68,6 @@ const client = new S3Client({
});
// Bun.s3 is a global singleton that is equivalent to `new Bun.S3Client()`
Bun.s3 = client;
```
### Working with S3 Files
@@ -172,11 +171,24 @@ When your production service needs to let users upload files to your server, it'
To facilitate this, you can presign URLs for S3 files. This generates a URL with a signature that allows a user to securely upload that specific file to S3, without exposing your credentials or granting them unnecessary access to your bucket.
The default behaviour is to generate a `GET` URL that expires in 24 hours. Bun attempts to infer the content type from the file extension. If inference is not possible, it will default to `application/octet-stream`.
```ts
import { s3 } from "bun";
// Generate a presigned URL that expires in 24 hours (default)
const url = s3.presign("my-file.txt", {
const download = s3.presign("my-file.txt"); // GET, text/plain, expires in 24 hours
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
});
// You can call .presign() if on a file reference, but avoid doing so
// unless you already have a reference (to avoid memory usage).
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
expiresIn: 3600, // 1 hour
});
```
@@ -349,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.
@@ -375,7 +437,7 @@ If the `S3_*` environment variable is not set, Bun will also check for the `AWS_
These environment variables are read from [`.env` files](/docs/runtime/env) or from the process environment at initialization time (`process.env` is not used for this).
These defaults are overridden by the options you pass to `s3(credentials)`, `new Bun.S3Client(credentials)`, or any of the methods that accept credentials. So if, for example, you use the same credentials for different buckets, you can set the credentials once in your `.env` file and then pass `bucket: "my-bucket"` to the `s3()` helper function without having to specify all the credentials again.
These defaults are overridden by the options you pass to `s3.file(credentials)`, `new Bun.S3Client(credentials)`, or any of the methods that accept credentials. So if, for example, you use the same credentials for different buckets, you can set the credentials once in your `.env` file and then pass `bucket: "my-bucket"` to the `s3.file()` function without having to specify all the credentials again.
### `S3Client` objects
@@ -459,7 +521,7 @@ const exists = await client.exists("my-file.txt");
## `S3File`
`S3File` instances are created by calling the `S3` instance method or the `s3()` helper function. Like `Bun.file()`, `S3File` instances are lazy. They don't refer to something that necessarily exists at the time of creation. That's why all the methods that don't involve network requests are fully synchronous.
`S3File` instances are created by calling the `S3Client` instance method or the `s3.file()` function. Like `Bun.file()`, `S3File` instances are lazy. They don't refer to something that necessarily exists at the time of creation. That's why all the methods that don't involve network requests are fully synchronous.
```ts
interface S3File extends Blob {
@@ -482,7 +544,7 @@ interface S3File extends Blob {
| Response
| Request,
options?: BlobPropertyBag,
): Promise<void>;
): Promise<number>;
exists(options?: S3Options): Promise<boolean>;
unlink(options?: S3Options): Promise<void>;
@@ -600,7 +662,9 @@ const exists = await S3Client.exists("my-file.txt", credentials);
The same method also works on `S3File` instances.
```ts
const s3file = Bun.s3("my-file.txt", {
import { s3 } from "bun";
const s3file = s3.file("my-file.txt", {
...credentials,
});
const exists = await s3file.exists();

674
docs/api/sql.md Normal file
View File

@@ -0,0 +1,674 @@
Bun provides native bindings for working with PostgreSQL databases with a modern, Promise-based API. The interface is designed to be simple and performant, using tagged template literals for queries and offering features like connection pooling, transactions, and prepared statements.
```ts
import { sql } from "bun";
const users = await sql`
SELECT * FROM users
WHERE active = ${true}
LIMIT ${10}
`;
// Select with multiple conditions
const activeUsers = await sql`
SELECT *
FROM users
WHERE active = ${true}
AND age >= ${18}
`;
```
{% features title="Features" %}
{% icon size=20 name="Shield" /%} Tagged template literals to protect against SQL injection
{% icon size=20 name="GitMerge" /%} Transactions
{% icon size=20 name="Variable" /%} Named & positional parameters
{% icon size=20 name="Network" /%} Connection pooling
{% icon size=20 name="Binary" /%} `BigInt` support
{% icon size=20 name="Key" /%} SASL Auth support (SCRAM-SHA-256), MD5, and Clear Text
{% icon size=20 name="Timer" /%} Connection timeouts
{% icon size=20 name="Database" /%} Returning rows as data objects, arrays of arrays, or `Buffer`
{% icon size=20 name="Code" /%} Binary protocol support makes it faster
{% icon size=20 name="Lock" /%} TLS support (and auth mode)
{% icon size=20 name="Settings" /%} Automatic configuration with environment variable
{% /features %}
### Inserting data
You can pass JavaScript values directly to the SQL template literal and escaping will be handled for you.
```ts
import { sql } from "bun";
// Basic insert with direct values
const [user] = await sql`
INSERT INTO users (name, email)
VALUES (${name}, ${email})
RETURNING *
`;
// Using object helper for cleaner syntax
const userData = {
name: "Alice",
email: "alice@example.com",
};
const [newUser] = await sql`
INSERT INTO users ${sql(userData)}
RETURNING *
`;
// Expands to: INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')
```
### Bulk Insert
You can also pass arrays of objects to the SQL template literal and it will be expanded to a `INSERT INTO ... VALUES ...` statement.
```ts
const users = [
{ name: "Alice", email: "alice@example.com" },
{ name: "Bob", email: "bob@example.com" },
{ name: "Charlie", email: "charlie@example.com" },
];
await sql`INSERT INTO users ${sql(users)}`;
```
### Picking columns to insert
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 = {
name: "Alice",
email: "alice@example.com",
age: 25,
};
await sql`INSERT INTO users ${sql(user, "name", "email")}`;
// Only inserts name and email columns, ignoring other fields
```
## Query Results
By default, Bun's SQL client returns query results as arrays of objects, where each object represents a row with column names as keys. However, there are cases where you might want the data in a different format. The client provides two additional methods for this purpose.
### `sql``.values()` format
The `sql``.values()` method returns rows as arrays of values rather than objects. Each row becomes an array where the values are in the same order as the columns in your query.
```ts
const rows = await sql`SELECT * FROM users`.values();
console.log(rows);
```
This returns something like:
```ts
[
["Alice", "alice@example.com"],
["Bob", "bob@example.com"],
];
```
`sql``.values()` is especially useful if duplicate column names are returned in the query results. When using objects (the default), the last column name is used as the key in the object, which means duplicate column names overwrite each other &mdash; but when using `sql``.values()`, each column is present in the array so you can access the values of duplicate columns by index.
### `sql``.raw()` format
The `.raw()` method returns rows as arrays of `Buffer` objects. This can be useful for working with binary data or for performance reasons.
```ts
const rows = await sql`SELECT * FROM users`.raw();
console.log(rows); // [[Buffer, Buffer], [Buffer, Buffer], [Buffer, Buffer]]
```
## SQL Fragments
A common need in database applications is the ability to construct queries dynamically based on runtime conditions. Bun provides safe ways to do this without risking SQL injection.
### Dynamic Table Names
When you need to reference tables or schemas dynamically, use the `sql()` helper to ensure proper escaping:
```ts
// Safely reference tables dynamically
await sql`SELECT * FROM ${sql("users")}`;
// With schema qualification
await sql`SELECT * FROM ${sql("public.users")}`;
```
### Conditional Queries
You can use the `sql()` helper to build queries with conditional clauses. This allows you to create flexible queries that adapt to your application's needs:
```ts
// Optional WHERE clauses
const filterAge = true;
const minAge = 21;
const ageFilter = sql`AND age > ${minAge}`;
await sql`
SELECT * FROM users
WHERE active = ${true}
${filterAge ? ageFilter : sql``}
`;
```
### Dynamic columns in updates
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 " + dangerous + " FROM users WHERE id = $1",
[id],
);
```
#### What is SQL Injection?
{% image href="https://xkcd.com/327/" src="https://imgs.xkcd.com/comics/exploits_of_a_mom.png" /%}
### Execute and Cancelling Queries
Bun's SQL is lazy that means its will only start executing when awaited or executed with `.execute()`.
You can cancel a query that is currently executing by calling the `cancel()` method on the query object.
```ts
const query = await sql`SELECT * FROM users`.execute();
setTimeout(() => query.cancel(), 100);
await query;
```
## Database Environment Variables
`sql` connection parameters can be configured using environment variables. The client checks these variables in a specific order of precedence.
The following environment variables can be used to define the connection URL:
| Environment Variable | Description |
| --------------------------- | ------------------------------------------ |
| `POSTGRES_URL` | Primary connection URL for PostgreSQL |
| `DATABASE_URL` | Alternative connection URL |
| `PGURL` | Alternative connection URL |
| `PG_URL` | Alternative connection URL |
| `TLS_POSTGRES_DATABASE_URL` | SSL/TLS-enabled connection URL |
| `TLS_DATABASE_URL` | Alternative SSL/TLS-enabled connection URL |
If no connection URL is provided, the system checks for the following individual parameters:
| Environment Variable | Fallback Variables | Default Value | Description |
| -------------------- | ---------------------------- | ------------- | ----------------- |
| `PGHOST` | - | `localhost` | Database host |
| `PGPORT` | - | `5432` | Database port |
| `PGUSERNAME` | `PGUSER`, `USER`, `USERNAME` | `postgres` | Database user |
| `PGPASSWORD` | - | (empty) | Database password |
| `PGDATABASE` | - | username | Database name |
## Connection Options
You can configure your database connection manually by passing options to the SQL constructor:
```ts
import { SQL } from "bun";
const db = new SQL({
// Required
url: "postgres://user:pass@localhost:5432/dbname",
// Optional configuration
hostname: "localhost",
port: 5432,
database: "myapp",
username: "dbuser",
password: "secretpass",
// Connection pool settings
max: 20, // Maximum connections in pool
idleTimeout: 30, // Close idle connections after 30s
maxLifetime: 0, // Connection lifetime in seconds (0 = forever)
connectionTimeout: 30, // Timeout when establishing new connections
// SSL/TLS options
tls: true,
// tls: {
// rejectUnauthorized: true,
// requestCert: true,
// ca: "path/to/ca.pem",
// key: "path/to/key.pem",
// cert: "path/to/cert.pem",
// checkServerIdentity(hostname, cert) {
// ...
// },
// },
// Callbacks
onconnect: client => {
console.log("Connected to database");
},
onclose: client => {
console.log("Connection closed");
},
});
```
## 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.
The `BEGIN` command is sent automatically, including any optional configurations you specify. If an error occurs during the transaction, a `ROLLBACK` is triggered to release the reserved connection and ensure the process continues smoothly.
### Basic Transactions
```ts
await sql.begin(async tx => {
// All queries in this function run in a transaction
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
await tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`;
// Transaction automatically commits if no errors are thrown
// Rolls back if any error occurs
});
```
It's also possible to pipeline the requests in a transaction if needed by returning an array with queries from the callback function like this:
```ts
await sql.begin(async tx => {
return [
tx`INSERT INTO users (name) VALUES (${"Alice"})`,
tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`,
];
});
```
### Savepoints
Savepoints in SQL create intermediate checkpoints within a transaction, enabling partial rollbacks without affecting the entire operation. They are useful in complex transactions, allowing error recovery and maintaining consistent results.
```ts
await sql.begin(async tx => {
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
await tx.savepoint(async sp => {
// This part can be rolled back separately
await sp`UPDATE users SET status = 'active'`;
if (someCondition) {
throw new Error("Rollback to savepoint");
}
});
// Continue with transaction even if savepoint rolled back
await tx`INSERT INTO audit_log (action) VALUES ('user_created')`;
});
```
### Distributed Transactions
Two-Phase Commit (2PC) is a distributed transaction protocol where Phase 1 has the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes either committing or rolling back based on the coordinator's decision. This process ensures data durability and proper lock management.
In PostgreSQL and MySQL, distributed transactions persist beyond their original session, allowing privileged users or coordinators to commit or rollback them later. This supports robust distributed transactions, recovery processes, and administrative operations.
Each database system implements distributed transactions differently:
PostgreSQL natively supports them through prepared transactions, while MySQL uses XA Transactions.
If any exceptions occur during the distributed transaction and aren't caught, the system will automatically rollback all changes. When everything proceeds normally, you maintain the flexibility to either commit or rollback the transaction later.
```ts
// Begin a distributed transaction
await sql.beginDistributed("tx1", async tx => {
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
});
// Later, commit or rollback
await sql.commitDistributed("tx1");
// or
await sql.rollbackDistributed("tx1");
```
## Authentication
Bun supports SCRAM-SHA-256 (SASL), MD5, and Clear Text authentication. SASL is recommended for better security. Check [Postgres SASL Authentication](https://www.postgresql.org/docs/current/sasl-authentication.html) for more information.
### SSL Modes Overview
PostgreSQL supports different SSL/TLS modes to control how secure connections are established. These modes determine the behavior when connecting and the level of certificate verification performed.
```ts
const sql = new SQL({
hostname: "localhost",
username: "user",
password: "password",
ssl: "disable", // | "prefer" | "require" | "verify-ca" | "verify-full"
});
```
| SSL Mode | Description |
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
| `disable` | No SSL/TLS used. Connections fail if server requires SSL. |
| `prefer` | Tries SSL first, falls back to non-SSL if SSL fails. Default mode if none specified. |
| `require` | Requires SSL without certificate verification. Fails if SSL cannot be established. |
| `verify-ca` | Verifies server certificate is signed by trusted CA. Fails if verification fails. |
| `verify-full` | Most secure mode. Verifies certificate and hostname match. Protects against untrusted certificates and MITM attacks. |
### Using With Connection Strings
The SSL mode can also be specified in connection strings:
```ts
// Using prefer mode
const sql = new SQL("postgres://user:password@localhost/mydb?sslmode=prefer");
// Using verify-full mode
const sql = new SQL(
"postgres://user:password@localhost/mydb?sslmode=verify-full",
);
```
## Connection Pooling
Bun's SQL client automatically manages a connection pool, which is a pool of database connections that are reused for multiple queries. This helps to reduce the overhead of establishing and closing connections for each query, and it also helps to manage the number of concurrent connections to the database.
```ts
const db = new SQL({
// Pool configuration
max: 20, // Maximum 20 concurrent connections
idleTimeout: 30, // Close idle connections after 30s
maxLifetime: 3600, // Max connection lifetime 1 hour
connectionTimeout: 10, // Connection timeout 10s
});
```
No connection will be made until a query is made.
```ts
const sql = Bun.sql(); // no connection are created
await sql`...`; // pool is started until max is reached (if possible), first available connection is used
await sql`...`; // previous connection is reused
// two connections are used now at the same time
await Promise.all([
sql`INSERT INTO users ${sql({ name: "Alice" })}`,
sql`UPDATE users SET name = ${user.name} WHERE id = ${user.id}`,
]);
await sql.close(); // await all queries to finish and close all connections from the pool
await sql.close({ timeout: 5 }); // wait 5 seconds and close all connections from the pool
await sql.close({ timeout: 0 }); // close all connections from the pool immediately
```
## Reserved Connections
Bun enables you to reserve a connection from the pool, and returns a client that wraps the single connection. This can be used for running queries on an isolated connection.
```ts
// Get exclusive connection from pool
const reserved = await sql.reserve();
try {
await reserved`INSERT INTO users (name) VALUES (${"Alice"})`;
} finally {
// Important: Release connection back to pool
reserved.release();
}
// Or using Symbol.dispose
{
using reserved = await sql.reserve();
await reserved`SELECT 1`;
} // 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:
### Connection Errors
| Connection Errors | Description |
| --------------------------------- | ---------------------------------------------------- |
| `ERR_POSTGRES_CONNECTION_CLOSED` | Connection was terminated or never established |
| `ERR_POSTGRES_CONNECTION_TIMEOUT` | Failed to establish connection within timeout period |
| `ERR_POSTGRES_IDLE_TIMEOUT` | Connection closed due to inactivity |
| `ERR_POSTGRES_LIFETIME_TIMEOUT` | Connection exceeded maximum lifetime |
| `ERR_POSTGRES_TLS_NOT_AVAILABLE` | SSL/TLS connection not available |
| `ERR_POSTGRES_TLS_UPGRADE_FAILED` | Failed to upgrade connection to SSL/TLS |
### Authentication Errors
| Authentication Errors | Description |
| ------------------------------------------------ | ---------------------------------------- |
| `ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2` | Password authentication failed |
| `ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD` | Server requested unknown auth method |
| `ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD` | Server requested unsupported auth method |
| `ERR_POSTGRES_INVALID_SERVER_KEY` | Invalid server key during authentication |
| `ERR_POSTGRES_INVALID_SERVER_SIGNATURE` | Invalid server signature |
| `ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64` | Invalid SASL signature encoding |
| `ERR_POSTGRES_SASL_SIGNATURE_MISMATCH` | SASL signature verification failed |
### Query Errors
| Query Errors | Description |
| ------------------------------------ | ------------------------------------------ |
| `ERR_POSTGRES_SYNTAX_ERROR` | Invalid SQL syntax (extends `SyntaxError`) |
| `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
| Data Type Errors | Description |
| ------------------------------------------------------- | ------------------------------------- |
| `ERR_POSTGRES_INVALID_BINARY_DATA` | Invalid binary data format |
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE` | Invalid byte sequence |
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING` | Encoding error |
| `ERR_POSTGRES_INVALID_CHARACTER` | Invalid character in data |
| `ERR_POSTGRES_OVERFLOW` | Numeric overflow |
| `ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT` | Unsupported binary format |
| `ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE` | Integer size not supported |
| `ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET` | Multidimensional arrays not supported |
| `ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET` | NULL values in arrays not supported |
### Protocol Errors
| Protocol Errors | Description |
| --------------------------------------- | --------------------------- |
| `ERR_POSTGRES_EXPECTED_REQUEST` | Expected client request |
| `ERR_POSTGRES_EXPECTED_STATEMENT` | Expected prepared statement |
| `ERR_POSTGRES_INVALID_BACKEND_KEY_DATA` | Invalid backend key data |
| `ERR_POSTGRES_INVALID_MESSAGE` | Invalid protocol message |
| `ERR_POSTGRES_INVALID_MESSAGE_LENGTH` | Invalid message length |
| `ERR_POSTGRES_UNEXPECTED_MESSAGE` | Unexpected message type |
### Transaction Errors
| Transaction Errors | Description |
| ---------------------------------------- | ------------------------------------- |
| `ERR_POSTGRES_UNSAFE_TRANSACTION` | Unsafe transaction operation detected |
| `ERR_POSTGRES_INVALID_TRANSACTION_STATE` | Invalid transaction state |
## Numbers and BigInt
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";
const [{ x, y }] = await sql`SELECT 9223372036854777 as x, 12345 as y`;
console.log(typeof x, x); // "string" "9223372036854777"
console.log(typeof y, y); // "number" 12345
```
## BigInt Instead of Strings
If you need large numbers as BigInt instead of strings, you can enable this by setting the `bigint` option to `true` when initializing the SQL client:
```ts
const sql = new SQL({
bigint: true,
});
const [{ x }] = await sql`SELECT 9223372036854777 as x`;
console.log(typeof x, x); // "bigint" 9223372036854777n
```
## Roadmap
There's still some things we haven't finished yet.
- Connection preloading via `--db-preconnect` Bun CLI flag
- MySQL support: [we're working on it](https://github.com/oven-sh/bun/pull/15274)
- SQLite support: planned, but not started. Ideally, we implement it natively instead of wrapping `bun:sqlite`.
- Column name transforms (e.g. `snake_case` to `camelCase`). This is mostly blocked on a unicode-aware implementation of changing the case in C++ using WebKit's `WTF::String`.
- Column type transforms
### Postgres-specific features
We haven't implemented these yet:
- `COPY` support
- `LISTEN` support
- `NOTIFY` support
We also haven't implemented some of the more uncommon features like:
- GSSAPI authentication
- `SCRAM-SHA-256-PLUS` support
- Point & PostGIS types
- All the multi-dimensional integer array types (only a couple of the types are supported)
## Frequently Asked Questions
> Why is this `Bun.sql` and not `Bun.postgres`?
The plan is to add more database drivers in the future.
> Why not just use an existing library?
npm packages like postgres.js, pg, and node-postgres can be used in Bun too. They're great options.
Two reasons why:
1. We think it's simpler for developers to have a database driver built into Bun. The time you spend library shopping is time you could be building your app.
2. We leverage some JavaScriptCore engine internals to make it faster to create objects that would be difficult to implement in a library
## Credits
Huge thanks to [@porsager](https://github.com/porsager)'s [postgres.js](https://github.com/porsager/postgres) for the inspiration for the API interface.

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.

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.
@@ -196,6 +198,8 @@ import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
const bytes = await file(icon).arrayBuffer();
// await fs.promises.readFile(icon)
// fs.readFileSync(icon)
```
### Embed SQLite databases
@@ -292,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,43 +1,57 @@
As of Bun v1.1.44, we've added initial support for bundling frontend apps directly in Bun's HTTP server: `Bun.serve()`. 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 your 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";
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}`);
```
You'll need to run your app with `bun --experimental-html` to enable this feature:
```bash
$ bun --experimental-html run app.ts
$ bun run app.ts
```
## HTML imports are routes
@@ -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,
}
@@ -109,11 +123,11 @@ To use React in your client-side code, import `react-dom/client` and render your
{% codetabs %}
```ts#src/backend.ts
import dashboard from "./public/dashboard.html";
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,
}
@@ -198,6 +212,59 @@ When serving your app in production, set `development: false` in `Bun.serve()`.
- Enables `Cache-Control` headers and `ETag` headers
- Minifies JavaScript/TypeScript/TSX/JSX files
## Plugins
Bun's [bundler plugins](https://bun.sh/docs/bundler/plugins) are also supported when bundling static routes.
To configure plugins for `Bun.serve`, add a `plugins` array in the `[serve.static]` section of your `bunfig.toml`.
### Using TailwindCSS in HTML routes
For example, enable TailwindCSS on your routes by installing and adding the `bun-plugin-tailwind` plugin:
```sh
$ bun add bun-plugin-tailwind
```
```toml#bunfig.toml
[serve.static]
plugins = ["bun-plugin-tailwind"]
```
This will allow you to use TailwindCSS utility classes in your HTML and CSS files. All you need to do is import `tailwindcss` somewhere:
```html#index.html
<!doctype html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="tailwindcss" />
</head>
<body>
<!-- the rest of your HTML... -->
</body>
</html>
```
Or in your CSS:
```css#style.css
@import "tailwindcss";
```
### Custom plugins
Any JS file or module which exports a [valid bundler plugin object](https://bun.sh/docs/bundler/plugins#usage) (essentially an object with a `name` and `setup` field) can be placed inside the `plugins` array:
```toml#bunfig.toml
[serve.static]
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.
@@ -242,6 +309,5 @@ 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.
- ~Client-side hot reloading isn't wired up yet. It will be in the future.~ New in Bun v1.2.3
- This doesn't support `bun build` yet. It also will in the future.
- We haven't figured out plugins yet. This probably will live in `bunfig.toml` with the same API as in `Bun.build` otherwise.

View File

@@ -1,4 +1,4 @@
As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else.
Bun's bundler has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else.
```html#index.html
<!doctype html>
@@ -13,49 +13,228 @@ As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build sta
</html>
```
One command is all you need (won't be experimental after Bun v1.2):
To get started, pass HTML files to `bun`.
{% bunDevServerTerminal alt="bun ./index.html" path="./index.html" routes="" /%}
Bun's development server provides powerful features with zero configuration:
- **Automatic Bundling** - Bundles and serves your HTML, JavaScript, and CSS
- **Multi-Entry Support** - Handles multiple HTML entry points and glob entry points
- **Modern JavaScript** - TypeScript & JSX support out of the box
- **Smart Configuration** - Reads `tsconfig.json` for paths, JSX options, experimental decorators, and more
- **Plugins** - Plugins for TailwindCSS and more
- **ESM & CommonJS** - Use ESM and CommonJS in your JavaScript, TypeScript, and JSX files
- **CSS Bundling & Minification** - Bundles CSS from `<link>` tags and `@import` statements
- **Asset Management**
- Automatic copying & hashing of images and assets
- Rewrites asset paths in JavaScript, CSS, and HTML
## Single Page Apps (SPA)
When you pass a single .html file to Bun, Bun will use it as a fallback route for all paths. This makes it perfect for single page apps that use client-side routing:
{% bunDevServerTerminal alt="bun index.html" path="index.html" routes="" /%}
Your React or other SPA will work out of the box — no configuration needed. All routes like `/about`, `/users/123`, etc. will serve the same HTML file, letting your client-side router handle the navigation.
```html#index.html
<!doctype html>
<html>
<head>
<title>My SPA</title>
<script src="./app.tsx" type="module"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
```
## Multi-page apps (MPA)
Some projects have several separate routes or HTML files as entry points. To support multiple entry points, pass them all to `bun`
{% bunDevServerTerminal alt="bun ./index.html ./about.html" path="./index.html ./about.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%}
This will serve:
- `index.html` at `/`
- `about.html` at `/about`
### Glob patterns
To specify multiple files, you can use glob patterns that end in `.html`:
{% bunDevServerTerminal alt="bun ./**/*.html" path="./**/*.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%}
### Path normalization
The base path is chosen from the longest common prefix among all the files.
{% bunDevServerTerminal alt="bun ./index.html ./about/index.html ./about/foo/index.html" path="./index.html ./about/index.html ./about/foo/index.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about/index.html\"}, {\"path\": \"/about/foo\", \"file\": \"./about/foo/index.html\"}]" /%}
## JavaScript, TypeScript, and JSX
Bun's transpiler natively implements JavaScript, TypeScript, and JSX support. [Learn more about loaders in Bun](/docs/bundler/loaders).
Bun's transpiler is also used at runtime.
### ES Modules & CommonJS
You can use ESM and CJS in your JavaScript, TypeScript, and JSX files. Bun will handle the transpilation and bundling automatically.
There is no pre-build or separate optimization step. It's all done at the same time.
Learn more about [module resolution in Bun](/docs/runtime/modules).
## CSS
Bun's CSS parser is also natively implemented (clocking in around 58,000 lines of Zig).
It's also a CSS bundler. You can use `@import` in your CSS files to import other CSS files.
For example:
```css#styles.css
@import "./abc.css";
.container {
background-color: blue;
}
```
```css#abc.css
body {
background-color: red;
}
```
This outputs:
```css#styles.css
body {
background-color: red;
}
.container {
background-color: blue;
}
```
### Referencing local assets in CSS
You can reference local assets in your CSS files.
```css#styles.css
body {
background-image: url("./logo.png");
}
```
This will copy `./logo.png` to the output directory and rewrite the path in the CSS file to include a content hash.
```css#styles.css
body {
background-image: url("./logo-[ABC123].png");
}
```
### Importing CSS in JavaScript
To associate a CSS file with a JavaScript file, you can import it in your JavaScript file.
```ts#app.ts
import "./styles.css";
import "./more-styles.css";
```
This generates `./app.css` and `./app.js` in the output directory. All CSS files imported from JavaScript will be bundled into a single CSS file per entry point. If you import the same CSS file from multiple JavaScript files, it will only be included once in the output CSS file.
## Plugins
The dev server supports plugins.
### Tailwind CSS
To use TailwindCSS, install the `bun-plugin-tailwind` plugin:
```bash
# Or any npm client
$ bun install --dev bun-plugin-tailwind
```
Then, add the plugin to your `bunfig.toml`:
```toml
[serve.static]
plugins = ["bun-plugin-tailwind"]
```
Then, reference TailwindCSS in your HTML via `<link>` tag, `@import` in CSS, or `import` in JavaScript.
{% codetabs %}
```html#index.html
<!-- Reference TailwindCSS in your HTML -->
<link rel="stylesheet" href="tailwindcss" />
```
```css#styles.css
/* Import TailwindCSS in your CSS */
@import "tailwindcss";
```
```ts#app.ts
/* Import TailwindCSS in your JavaScript */
import "tailwindcss";
```
{% /codetabs %}
Only one of those are necessary, not all three.
## Keyboard Shortcuts
While the server is running:
- `o + Enter` - Open in browser
- `c + Enter` - Clear console
- `q + Enter` (or Ctrl+C) - Quit server
## Build for Production
When you're ready to deploy, use `bun build` to create optimized production bundles:
{% codetabs %}
```bash#CLI
$ bun build --experimental-html --experimental-css ./index.html --outdir=dist
$ bun build ./index.html --minify --outdir=dist
```
```ts#API
Bun.build({
entrypoints: ["./index.html"],
outdir: "./dist",
// On by default in Bun v1.2+
html: true,
experimentalCss: true,
minify: {
whitespace: true,
identifiers: true,
syntax: true,
}
});
```
{% /codetabs %}
Bun automatically:
Currently, plugins are only supported through `Bun.build`'s API or through `bunfig.toml` with the frontend dev server - not yet supported in `bun build`'s CLI.
- Bundles, tree-shakes, and optimizes your JavaScript, JSX and TypeScript
- Bundles and optimizes your CSS
- Copies & hashes images and other assets
- Updates all references to local files or packages in your HTML
### Watch Mode
## Zero Config, Maximum Performance
The HTML bundler is enabled by default after Bun v1.2+. Drop in your existing HTML files and Bun will handle:
- **TypeScript & JSX** - Write modern JavaScript for browsers without the setup
- **CSS** - Bundle CSS stylesheets directly from `<link rel="stylesheet">` or `@import`
- **Images & Assets** - Automatic copying & hashing & rewriting of assets in JavaScript, CSS, and HTML
## Watch mode
You can run `bun build --watch` to watch for changes and rebuild automatically.
You can run `bun build --watch` to watch for changes and rebuild automatically. This works nicely for library development.
You've never seen a watch mode this fast.
## Plugin API
### Plugin API
Need more control? Configure the bundler through the JavaScript API and use Bun's builtin `HTMLRewriter` to preprocess HTML.
@@ -63,8 +242,6 @@ Need more control? Configure the bundler through the JavaScript API and use Bun'
await Bun.build({
entrypoints: ["./index.html"],
outdir: "./dist",
html: true,
experimentalCss: true,
minify: true,
plugins: [
@@ -108,3 +285,22 @@ Bun automatically handles all common web assets:
- Any `<link>` tag with an `href` attribute pointing to a local file is rewritten to the new path, and hashed
All paths are resolved relative to your HTML file, making it easy to organize your project however you want.
## This is a work in progress
- No HMR support yet
- Need more plugins
- Need more configuration options for things like asset handling
- Need a way to configure CORS, headers, etc.
If you want to submit a PR, most of the [code is here](https://github.com/oven-sh/bun/blob/main/src/js/internal/html.ts). You could even copy paste that file into your project and use it as a starting point.
## How this works
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 `"routes"` option in `Bun.serve`.
Learn more in [the full-stack docs](/docs/bundler/fullstack).

View File

@@ -1258,30 +1258,6 @@ $ bun build ./index.tsx --outdir ./out --drop=console --drop=debugger --drop=any
{% /codetabs %}
### `experimentalCss`
Whether to enable _experimental_ support for bundling CSS files. Defaults to `false`. In 1.2, this property will be deleted, and CSS bundling will always be enabled.
This supports bundling CSS files imported from JS, as well as CSS entrypoints.
{% codetabs group="a" %}
```ts#JavaScript
const result = await Bun.build({
entrypoints: ["./index.ts"],
experimentalCss: true,
});
// => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
```
{% /codetabs %}
### `throw`
If set to `true`, `Bun.build` will throw on build failure. See the section ["Logs and Errors"](#logs-and-errors) for more details on the error message structure.
In 1.2, this will default to `true`, with the previous behavior as `throw: false`
## Outputs
The `Bun.build` function returns a `Promise<BuildOutput>`, defined as:
@@ -1422,7 +1398,8 @@ Refer to [Bundler > Executables](https://bun.sh/docs/bundler/executables) for co
## Logs and errors
<!-- 1.2 documentation -->
<!-- On failure, `Bun.build` returns a rejected promise with an `AggregateError`. This can be logged to the console for pretty printing of the error list, or programmatically read with a `try`/`catch` block.
On failure, `Bun.build` returns a rejected promise with an `AggregateError`. This can be logged to the console for pretty printing of the error list, or programmatically read with a `try`/`catch` block.
```ts
try {
@@ -1482,70 +1459,6 @@ if (result.logs.length > 0) {
console.warn(message);
}
}
``` -->
By default, `Bun.build` only throws if invalid options are provided. Read the `success` property to determine if the build was successful; the `logs` property will contain additional details.
```ts
const result = await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
});
if (!result.success) {
console.error("Build failed");
for (const message of result.logs) {
// Bun will pretty print the message object
console.error(message);
}
}
```
Each message is either a `BuildMessage` or `ResolveMessage` object, which can be used to trace what problems happened in the build.
```ts
class BuildMessage {
name: string;
position?: Position;
message: string;
level: "error" | "warning" | "info" | "debug" | "verbose";
}
class ResolveMessage extends BuildMessage {
code: string;
referrer: string;
specifier: string;
importKind: ImportKind;
}
```
If you want to throw an error from a failed build, consider passing the logs to an `AggregateError`. If uncaught, Bun will pretty-print the contained messages nicely.
```ts
if (!result.success) {
throw new AggregateError(result.logs, "Build failed");
}
```
In Bun 1.2, throwing an aggregate error like this will become the default beahavior. You can opt-into it early using the `throw: true` option.
```ts
try {
const result = await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
});
} catch (e) {
// TypeScript does not allow annotations on the catch clause
const error = e as AggregateError;
console.error("Build Failed");
// Example: Using the built-in formatter
console.error(error);
// Example: Serializing the failure as a JSON string.
console.error(JSON.stringify(error, null, 2));
}
```
## Reference
@@ -1646,13 +1559,6 @@ interface BuildConfig {
*/
footer?: string;
/**
* **Experimental**
*
* Enable CSS support.
*/
experimentalCss?: boolean;
/**
* Drop function calls to matching property accesses.
*/
@@ -1723,3 +1629,5 @@ declare class ResolveMessage {
toString(): string;
}
```
{% bunCLIUsage command="build" /%}

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