Compare commits

...

133 Commits

Author SHA1 Message Date
Dylan Conway
360925bb37 Merge branch 'main' into dylan/ref-string 2024-10-15 16:44:18 -07:00
Ciro Spaciari
409e674526 feat(node:http2) Implement HTTP2 server support (#14286)
Co-authored-by: cirospaciari <cirospaciari@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-15 16:28:21 -07:00
Meghan Denny
d15eadaa2c tsconfig.json: update excludes (#14578) 2024-10-15 15:39:09 -07:00
dave caruso
5532e1af10 feat(bake): hot-reloading error modal (#14573) 2024-10-15 00:02:58 -07:00
Meghan Denny
68e6304c73 node:child_process: 'ineherit' stdio should make getters be null (#14576) 2024-10-14 23:41:34 -07:00
Meghan Denny
709cd95c30 test: use isWindows from harness (#14577) 2024-10-14 21:19:09 -07:00
Meghan Denny
3830b0c499 more passing node buffer tests (#14371) 2024-10-14 20:22:14 -07:00
Meghan Denny
291b59eb19 bun-types: small fixes (#12794) 2024-10-14 20:15:03 -07:00
190n
035f97ba13 WIP: nuke EventSource as it doesn't work anyway (#14421) 2024-10-14 19:55:06 -07:00
huseeiin
fef9555f82 fix typo. constributors -> contributors (#14531) 2024-10-14 19:50:17 -07:00
Meghan Denny
ae0106b651 delete legacy node test runner (#14572) 2024-10-14 17:31:34 -07:00
Meghan Denny
355dc56db0 scripts/runner.node.mjs: print list of failing tests when run locally (#14571) 2024-10-14 17:22:06 -07:00
Jarred Sumner
5fc53353fb Allow disabling keep-alive (#14569)
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
2024-10-14 16:58:42 -07:00
dave caruso
d2fe1ce1c8 feat(bake): handle bundle errors, re-assemble full client payloads, initial error modal (#14504) 2024-10-14 16:49:38 -07:00
Jarred Sumner
29d287261b Fix several bugs when printing exceptions from Error.captureStackTrace (#14548) 2024-10-14 13:43:06 -07:00
Sebastian
6dbd679c06 docs: fix typo (#14565) 2024-10-14 13:29:28 -07:00
Meghan Denny
a5006a13a8 fetch-tcp-stress.test.ts: todo failing on macos ci (#14514) 2024-10-14 12:48:42 -07:00
Meghan Denny
bebf762bcf streams.test.js: todo failing macos test (#14513) 2024-10-14 12:48:04 -07:00
Minsoo Choo
e6ea389e4e Next.js dev server now runs on Bun (#14566) 2024-10-14 12:11:30 -07:00
Timo Sand
47ff4748bd Remove duplicate in import-json.md (#14521) 2024-10-13 15:34:38 +11:00
Don Isaac
09b031d044 fix(parser): uncaught mismatch between JSX opening/closing tags (#14528) 2024-10-12 19:49:45 -07:00
Zack Radisic
6b8fd718c2 Various CSS stuff (#14499)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-12 07:00:20 -07:00
Jarred Sumner
9ed3858e40 Some types and docs 2024-10-12 06:19:46 -07:00
Dylan Conway
6cf9c41d1f fix(install): ensure read permissions when extracting files (#14511) 2024-10-12 02:37:51 -07:00
Dylan Conway
e678a4220f Merge branch 'main' into dylan/ref-string 2024-10-12 00:49:20 -07:00
Dylan Conway
183a8f61d8 fix bun-build-api.test.ts (#14503) 2024-10-12 00:48:22 -07:00
Dylan Conway
09c57f5887 Revert "avoid integer overflow with empty string"
This reverts commit 0f2b44a889.
2024-10-12 00:43:19 -07:00
Dylan Conway
091d279b7f Revert "add test"
This reverts commit 83a8b03224.
2024-10-12 00:43:18 -07:00
Dylan Conway
83a8b03224 add test 2024-10-12 00:29:25 -07:00
Dylan Conway
0f2b44a889 avoid integer overflow with empty string 2024-10-12 00:25:24 -07:00
Dylan Conway
2d2643f2f4 make sure ref 2024-10-11 23:38:04 -07:00
Jarred Sumner
85fbd1e273 we really need a merge queue 2024-10-11 21:51:40 -07:00
Mathieu Schroeter
9744684b10 Attempt to add support for iterate() with SQLite statements (#14361) 2024-10-11 21:42:59 -07:00
Jarred Sumner
43a5c4a044 Implement Bun.inspect.table (#14486) 2024-10-11 21:35:49 -07:00
Dylan Conway
d3323c84bb fix(publish): missing bins bugfix (#14488)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-11 21:28:47 -07:00
Jarred Sumner
f870293d30 Add timeout warning (#14478) 2024-10-11 21:20:55 -07:00
Jarred Sumner
4c26a257ac Fixes #14398 (#14401) 2024-10-11 21:18:07 -07:00
Jarred Sumner
c77fc5daa0 Implement --drop (#14492)
Co-authored-by: dave caruso <me@paperdave.net>
2024-10-11 20:52:23 -07:00
Dylan Conway
bbb41beadc bump webkit (#14497) 2024-10-11 19:44:53 -07:00
Meghan Denny
3f92ec8af3 fix label in 3-typescript-bug-report.yml (#14502) 2024-10-11 19:39:30 -07:00
Dylan Conway
5fd0a61ae2 CA support for bun install (#14416) 2024-10-11 13:16:26 -07:00
Meghan Denny
9fe6e25372 pm: fix assertion failure when printing lockfile summary after adding git transitive dependency (#14461)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-11 03:43:37 -07:00
190n
50e9be0dc7 Fix napi_value<=>integer conversions and napi_create_empty_array (#14479) 2024-10-10 23:50:39 -07:00
pfg
ba9db6cdb6 Fix console.table for numeric keys (#14484) 2024-10-10 23:50:02 -07:00
Meghan Denny
25fcbed8d1 enhance Buffer.from to support (de)serialization roundtrip (#14201)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-10 22:08:16 -07:00
Meghan Denny
170fafbca9 fix fs-non-number-arguments-throw.test.js (#14312) 2024-10-10 22:07:41 -07:00
Meghan Denny
874c9dbb24 fix fs-open.test.js (#14311) 2024-10-10 22:04:33 -07:00
Jarred Sumner
05f53dc70f Fixes #14464 (#14473) 2024-10-10 21:50:03 -07:00
Meghan Denny
584a8ceb84 enable iterator-helpers in webkit (#14455) 2024-10-10 15:47:59 -07:00
Michael H
05f68d79c8 docs: --conditions flag (#14463) 2024-10-10 04:04:58 -07:00
huseeiin
e650ee7967 Update bun.d.ts (#14429) 2024-10-10 02:35:53 -07:00
190n
50bb5fa1f6 Fix napi_throw_*/napi_create_*_error (#14446) 2024-10-10 02:35:38 -07:00
Dylan Conway
3452f50c96 update webkit (#14449) 2024-10-10 02:35:23 -07:00
snwy
ff476313a8 'let' statements before using statements are now properly converted into 'var' statements (#14260) 2024-10-09 19:14:22 -07:00
Jarred Sumner
def454d859 Bump 2024-10-09 18:20:19 -07:00
Grigory
73537de184 docs(bundler): add missing codetabs closing tag (#14443) 2024-10-09 15:13:42 -07:00
Meghan Denny
1bccd62784 actions: update help text for 'needs repro' label (#14428) 2024-10-09 10:44:31 -07:00
Jarred Sumner
c608a724a6 Update installation.md 2024-10-09 02:36:24 -07:00
Meghan Denny
ca6013acef move .clang-format up a folder so it affects all our c/cpp files (#14400)
Co-authored-by: nektro <nektro@users.noreply.github.com>
2024-10-08 23:04:05 -07:00
snwy
05e1832c68 remove function hoisting from _parse (#14419) 2024-10-08 18:04:18 -07:00
Jarred Sumner
7a6d17bb99 chore: Make hash formatter reusable (#14372)
Co-authored-by: dave caruso <me@paperdave.net>
2024-10-08 13:30:17 -07:00
Ashcon Partovi
05fb367c5f Move generated files to codegen/ directory (#14392) 2024-10-08 10:32:16 -07:00
versecafe
7996d06b8f --footer esbuild & rollup style! (#14396)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-10-08 02:32:37 -07:00
Jarred Sumner
a234e067a5 Make .get() ignore Object.prototype instead of using getOwn (#14322) 2024-10-08 00:34:31 -07:00
Meghan Denny
c20901fd4e Update 7-install-crash-report.yml (#14394) 2024-10-07 20:45:30 -07:00
Meghan Denny
0d5eb73db0 test: add missing vm.runInContext stubs (#14341) 2024-10-07 20:38:31 -07:00
Kiwi
87c3b2f8d3 Update lockfile.md - fix typo (#14385) 2024-10-07 20:23:45 -07:00
Meghan Denny
1ce2d0e9f5 fix fs-read-empty-buffer.test.js (#14316) 2024-10-07 19:03:30 -07:00
Meghan Denny
c41ff9da93 fix fs-promises-file-handle-write.test.js (#14315) 2024-10-07 18:26:43 -07:00
190n
b0b38b42ba Return undefined from napi_get_property when property does not exist (#14366) 2024-10-07 18:05:31 -07:00
versecafe
62da730060 add banner, .d.ts, cli, make sourcemap compat, and add tests + docs (#14370) 2024-10-07 18:05:06 -07:00
Dylan Conway
c071415664 add bun pm whoami (#14387) 2024-10-07 17:36:14 -07:00
dave caruso
fc85a2dc92 feat(bake): add dependencies to IncrementalGraph (#14368) 2024-10-07 14:18:26 -07:00
Meghan Denny
c5b1c9e302 ci: shorten label names (#14314) 2024-10-07 11:56:37 -07:00
Jarred Sumner
65a6803093 Fixes #14345 (#14374) 2024-10-05 06:00:17 -07:00
Jarred Sumner
6ca68cab65 Update JSType (#14373) 2024-10-05 03:37:24 -07:00
Jarred Sumner
6645eafa08 do not use std.debug.print 2024-10-05 01:16:45 -07:00
Jarred Sumner
29e1ba044d Make this log better 2024-10-05 00:00:19 -07:00
Dylan Conway
fd15e22d64 comment 2024-10-04 23:38:39 -07:00
Dylan Conway
b2cb3603e2 fix(publish): ignore npm-notice when x-local-cache exists (#14352) 2024-10-04 23:36:34 -07:00
Dylan Conway
a15244a4c9 update webkit (#14364) 2024-10-04 22:32:48 -07:00
Zack Radisic
a01f9d8e1b Integrate CSS with bundler (#14281)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Zack Radisic <zackradisic@Mac.attlocal.net>
Co-authored-by: zackradisic <zackradisic@users.noreply.github.com>
Co-authored-by: Zack Radisic <zackradisic@Zacks-MBP.attlocal.net>
2024-10-04 20:23:10 -07:00
lewismiddleton
3ab3dec34d fix(docs): typo in bundler/index.md (#13370) 2024-10-04 20:21:04 -07:00
Dylan Conway
794e416642 Update CONTRIBUTING.md 2024-10-04 18:54:20 -07:00
Mathias
7885742345 fix segfault when decorating computed property #10887 (#14304) 2024-10-04 18:14:20 -07:00
versecafe
7063116c61 add missing docs for new bun pm commands (#14347) 2024-10-04 15:30:30 -07:00
Meghan Denny
4a5ec261ef node: add more passing tests (#14317) 2024-10-04 11:33:46 -07:00
Ashcon Partovi
e3f4c9fd0b ci: Fix analysis commands (#14356) 2024-10-04 09:13:23 -07:00
Dylan Conway
f307d2a6ef test(publish): ci names in user-agent (#14328) 2024-10-04 00:15:22 -07:00
dave caruso
adc86c773b chore: rename kit -> bake (#14335) 2024-10-03 15:34:53 -07:00
Dylan Conway
15427134e1 update 2024-10-03 15:11:44 -07:00
Dylan Conway
808e58cc4d update 2024-10-03 14:50:23 -07:00
Eric Liu
a375ea94ef docs: fix typo in bun publish (#14334) 2024-10-03 14:03:30 -07:00
Dylan Conway
39b1c0111e add docs for bun publish (#14327) 2024-10-03 03:41:11 -07:00
Jarred Sumner
eda608d629 Tweak how we do symbol versioning for glibc (#14272) 2024-10-03 02:42:28 -07:00
Meghan Denny
9446fd60c9 fix Buffer method aliases not being equal to each other (#14198) 2024-10-03 02:31:23 -07:00
Meghan Denny
8e5255d753 node:stream: fix setDefaultHighWaterMark (#14305) 2024-10-03 02:15:39 -07:00
Meghan Denny
13ca4544f2 enhance INVALID_ARG_TYPE and cleanup some node:buffer error handling (#14200) 2024-10-03 02:13:14 -07:00
Jarred Sumner
4d4dd1c180 Refactor node:module (#14227) 2024-10-03 00:54:56 -07:00
dave caruso
dd6554294e bake: release to canary only (#14258)
Co-authored-by: paperdave <paperdave@users.noreply.github.com>
2024-10-03 00:52:14 -07:00
Dylan Conway
50ed09654f publish help text 2024-10-02 22:57:34 -07:00
190n
0a54c24bd3 Allow throwing exceptions from napi_async_complete_callback (#14302)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2024-10-02 22:35:45 -07:00
versecafe
b39f49a5b9 remove bun pack in favor of bun pm pack (#14319) 2024-10-02 22:32:42 -07:00
snwy
e8fec640d8 hoisting of exports when there is top level using (#14313) 2024-10-02 22:32:04 -07:00
Ciro Spaciari
25abe67d43 update root certificates to NSS 3.104 (#14276) 2024-10-02 22:29:32 -07:00
Jarred Sumner
5f135a21b3 Update writing.md 2024-10-02 22:28:14 -07:00
Jarred Sumner
b88ed18245 On test timeout, kill any spawned processes (#14310) 2024-10-02 20:55:59 -07:00
Dylan Conway
f374ae6db1 add bun publish (#14215) 2024-10-02 20:47:22 -07:00
Jarred Sumner
94a656bc4f Support bundling .node files in ESM & CJS when targeting Node.js (#14294)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
2024-10-02 20:15:29 -07:00
190n
54e177e2f9 Rename internal NapiHandleScope push/pop methods to open/close (#14300) 2024-10-02 15:05:38 -07:00
Meghan Denny
39342e34b1 node: define missing constants (#14211) 2024-10-02 14:35:16 -07:00
Mathias
e1cd7e510e Update CONTRIBUTING.md, fix #14225 (#14303) 2024-10-02 13:44:54 -07:00
Meghan Denny
54a225953b use bun.String.static instead of ZigString when immediately converting to JSValue (#14169) 2024-10-02 13:02:48 -07:00
Meghan Denny
419229d950 add ERR_BUFFER_OUT_OF_BOUNDS to internal/errors (#14195) 2024-10-02 07:59:24 -07:00
Meghan Denny
b8a2a11c6f lazy load these requires so that node:cluster imports faster (#14291) 2024-10-02 02:30:19 -07:00
Meghan Denny
25083a4252 pm: print command name to stdout (#14266) 2024-10-02 02:24:37 -07:00
dave caruso
87424390e1 fix 14248 (#14277) 2024-10-02 02:23:54 -07:00
Dylan Conway
92e66691fa fix bun getcompletes index out of bounds (#14289) 2024-10-02 02:23:36 -07:00
Meghan Denny
edebd6faa3 windows: watcher: that line wasnt meant to go to stdout (#14288) 2024-10-02 00:26:20 -07:00
Meghan Denny
531d78aa97 BunProcess: dont use for-loop for isSignalName (#14285) 2024-10-01 23:42:52 -07:00
Meghan Denny
e831bbf4ca node: implement more validators in native code (#14177)
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
2024-10-01 21:55:05 -07:00
dave caruso
9870314ff6 fix 13394 (#14278) 2024-10-01 21:27:50 -07:00
Meghan Denny
e44d10cf17 node: lowercase primitive expectations of ERR_INVALID_ARG_TYPE (#14284) 2024-10-01 20:37:13 -07:00
Ashcon Partovi
db0750e90c cmake: Fix version detection 2024-10-01 15:48:13 -07:00
Ashcon Partovi
98e09efd02 cmake: Improve command detection (#14166) 2024-10-01 15:37:57 -07:00
Ashcon Partovi
944f342072 Revert "Remove old clang-tidy workflow"
This reverts commit 16917f7922.
2024-10-01 15:32:18 -07:00
Ashcon Partovi
16917f7922 Remove old clang-tidy workflow 2024-10-01 15:31:42 -07:00
Ashcon Partovi
27a157b6c1 Improve command detection in CMake 2024-10-01 13:50:15 -07:00
Jarred Sumner
07fd814629 Update index.md 2024-10-01 04:32:02 -07:00
Jarred Sumner
e348fef1c6 Update index.md 2024-10-01 04:26:19 -07:00
Jarred Sumner
68b910cbd9 Update index.md 2024-10-01 04:25:30 -07:00
Meghan Denny
e2f20d794f clang-format: add InsertNewlineAtEOF (#14267)
Co-authored-by: nektro <nektro@users.noreply.github.com>
2024-10-01 03:49:10 -07:00
Jarred Sumner
faa524bf67 Fix missing va_end call 2024-10-01 02:06:56 -07:00
715 changed files with 67055 additions and 16549 deletions

View File

@@ -13,7 +13,7 @@ steps:
group: ":darwin: aarch64"
steps:
- key: "darwin-aarch64-build-deps"
label: ":darwin: aarch64 - build-deps"
label: "build-deps"
agents:
queue: "build-darwin"
os: "darwin"
@@ -22,7 +22,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "darwin-aarch64-build-cpp"
label: ":darwin: aarch64 - build-cpp"
label: "build-cpp"
agents:
queue: "build-darwin"
os: "darwin"
@@ -33,14 +33,14 @@ steps:
- "bun run build:ci --target bun"
- key: "darwin-aarch64-build-zig"
label: ":darwin: aarch64 - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
command:
- "bun run build:ci --target bun-zig --toolchain darwin-aarch64"
- key: "darwin-aarch64-build-bun"
label: ":darwin: aarch64 - build-bun"
label: "build-bun"
agents:
queue: "build-darwin"
os: "darwin"
@@ -115,7 +115,7 @@ steps:
group: ":darwin: x64"
steps:
- key: "darwin-x64-build-deps"
label: ":darwin: x64 - build-deps"
label: "build-deps"
agents:
queue: "build-darwin"
os: "darwin"
@@ -124,7 +124,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "darwin-x64-build-cpp"
label: ":darwin: x64 - build-cpp"
label: "build-cpp"
agents:
queue: "build-darwin"
os: "darwin"
@@ -135,14 +135,14 @@ steps:
- "bun run build:ci --target bun"
- key: "darwin-x64-build-zig"
label: ":darwin: x64 - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
command:
- "bun run build:ci --target bun-zig --toolchain darwin-x64"
- key: "darwin-x64-build-bun"
label: ":darwin: x64 - build-bun"
label: "build-bun"
agents:
queue: "build-darwin"
os: "darwin"
@@ -217,7 +217,7 @@ steps:
group: ":linux: x64"
steps:
- key: "linux-x64-build-deps"
label: ":linux: x64 - build-deps"
label: "build-deps"
agents:
queue: "build-linux"
os: "linux"
@@ -226,7 +226,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "linux-x64-build-cpp"
label: ":linux: x64 - build-cpp"
label: "build-cpp"
agents:
queue: "build-linux"
os: "linux"
@@ -237,14 +237,14 @@ steps:
- "bun run build:ci --target bun"
- key: "linux-x64-build-zig"
label: ":linux: x64 - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
command:
- "bun run build:ci --target bun-zig --toolchain linux-x64"
- key: "linux-x64-build-bun"
label: ":linux: x64 - build-bun"
label: "build-bun"
agents:
queue: "build-linux"
os: "linux"
@@ -350,7 +350,7 @@ steps:
group: ":linux: x64-baseline"
steps:
- key: "linux-x64-baseline-build-deps"
label: ":linux: x64-baseline - build-deps"
label: "build-deps"
agents:
queue: "build-linux"
os: "linux"
@@ -361,7 +361,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "linux-x64-baseline-build-cpp"
label: ":linux: x64-baseline - build-cpp"
label: "build-cpp"
agents:
queue: "build-linux"
os: "linux"
@@ -373,7 +373,7 @@ steps:
- "bun run build:ci --target bun"
- key: "linux-x64-baseline-build-zig"
label: ":linux: x64-baseline - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
env:
@@ -382,7 +382,7 @@ steps:
- "bun run build:ci --target bun-zig --toolchain linux-x64-baseline"
- key: "linux-x64-baseline-build-bun"
label: ":linux: x64-baseline - build-bun"
label: "build-bun"
agents:
queue: "build-linux"
os: "linux"
@@ -489,7 +489,7 @@ steps:
group: ":linux: aarch64"
steps:
- key: "linux-aarch64-build-deps"
label: ":linux: aarch64 - build-deps"
label: "build-deps"
agents:
queue: "build-linux"
os: "linux"
@@ -498,7 +498,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "linux-aarch64-build-cpp"
label: ":linux: aarch64 - build-cpp"
label: "build-cpp"
agents:
queue: "build-linux"
os: "linux"
@@ -509,14 +509,14 @@ steps:
- "bun run build:ci --target bun"
- key: "linux-aarch64-build-zig"
label: ":linux: aarch64 - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
command:
- "bun run build:ci --target bun-zig --toolchain linux-aarch64"
- key: "linux-aarch64-build-bun"
label: ":linux: aarch64 - build-bun"
label: "build-bun"
agents:
queue: "build-linux"
os: "linux"
@@ -622,7 +622,7 @@ steps:
group: ":windows: x64"
steps:
- key: "windows-x64-build-deps"
label: ":windows: x64 - build-deps"
label: "build-deps"
agents:
queue: "build-windows"
os: "windows"
@@ -635,7 +635,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "windows-x64-build-cpp"
label: ":windows: x64 - build-cpp"
label: "build-cpp"
agents:
queue: "build-windows"
os: "windows"
@@ -650,14 +650,14 @@ steps:
- "bun run build:ci --target bun"
- key: "windows-x64-build-zig"
label: ":windows: x64 - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
command:
- "bun run build:ci --target bun-zig --toolchain windows-x64"
- key: "windows-x64-build-bun"
label: ":windows: x64 - build-bun"
label: "build-bun"
agents:
queue: "build-windows"
os: "windows"
@@ -705,7 +705,7 @@ steps:
group: ":windows: x64-baseline"
steps:
- key: "windows-x64-baseline-build-deps"
label: ":windows: x64-baseline - build-deps"
label: "build-deps"
agents:
queue: "build-windows"
os: "windows"
@@ -720,7 +720,7 @@ steps:
- "bun run build:ci --target dependencies"
- key: "windows-x64-baseline-build-cpp"
label: ":windows: x64-baseline - build-cpp"
label: "build-cpp"
agents:
queue: "build-windows"
os: "windows"
@@ -736,7 +736,7 @@ steps:
- "bun run build:ci --target bun"
- key: "windows-x64-baseline-build-zig"
label: ":windows: x64-baseline - build-zig"
label: "build-zig"
agents:
queue: "build-zig"
env:
@@ -745,7 +745,7 @@ steps:
- "bun run build:ci --target bun-zig --toolchain windows-x64-baseline"
- key: "windows-x64-baseline-build-bun"
label: ":windows: x64-baseline - build-bun"
label: "build-bun"
agents:
queue: "build-windows"
os: "windows"

View File

@@ -1,6 +1,6 @@
name: 🇹 TypeScript Type Bug Report
description: Report an issue with TypeScript types
labels: [bug, typescript]
labels: [bug, types]
body:
- type: markdown
attributes:

View File

@@ -11,8 +11,8 @@ body:
- type: textarea
id: package_json
attributes:
label: `package.json` file
description: Can you upload your `package.json` file? This helps us reproduce the crash.
label: "`package.json` file"
description: "Can you upload your `package.json` file? This helps us reproduce the crash."
render: json
- type: textarea
id: repro

View File

@@ -7,18 +7,6 @@ on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/clang-format.yml"
- ".clang-format"
- "package.json"
- "scripts/**"
- "cmake/**"
- "src/**/*.c"
- "src/**/*.cpp"
- "src/**/*.h"
- "packages/**/*.c"
- "packages/**/*.cpp"
- "packages/**/*.h"
env:
BUN_VERSION: "1.1.27"
@@ -33,14 +21,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: |
.github
.clang-format
package.json
scripts
cmake
src
packages
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
@@ -50,10 +31,9 @@ jobs:
curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s -- ${{ env.LLVM_VERSION_MAJOR }} all
- name: Clang Format
env:
ENABLE_CCACHE: OFF
LLVM_VERSION: ${{ env.LLVM_VERSION }}
run: |
bun run clang-format:diff
bun run clang-format
- name: Commit
uses: stefanzweifel/git-auto-commit-action@v5
with:

View File

@@ -7,18 +7,6 @@ on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/clang-tidy.yml"
- ".clang-tidy"
- "package.json"
- "scripts/**"
- "cmake/**"
- "src/**/*.c"
- "src/**/*.cpp"
- "src/**/*.h"
- "packages/**/*.c"
- "packages/**/*.cpp"
- "packages/**/*.h"
env:
BUN_VERSION: "1.1.27"
@@ -33,14 +21,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: |
.github
.clang-tidy
package.json
scripts
cmake
src
packages
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
@@ -50,7 +31,6 @@ jobs:
curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s -- ${{ env.LLVM_VERSION_MAJOR }} all
- name: Clang Tidy
env:
ENABLE_CCACHE: OFF
LLVM_VERSION: ${{ env.LLVM_VERSION }}
run: |
bun run clang-tidy:diff

View File

@@ -114,4 +114,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository, [Replit](https://replit.com/@replit/Bun), or [CodeSandbox](https://codesandbox.io/templates/bun). Issues marked with `needs repro` will be closed if they have no activity within 3 days.
Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository, [Replit](https://replit.com/@replit/Bun), [CodeSandbox](https://codesandbox.io/templates/bun), or provide a bulleted list of commands to run that reproduce this issue. Issues marked with `needs repro` will be closed if they have no activity within 3 days.

View File

@@ -1,30 +0,0 @@
name: lint-cpp
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && inputs.run-id || github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
inputs:
run-id:
type: string
description: The workflow ID to download artifacts (skips the build step)
# pull_request:
# paths:
# - ".github/workflows/lint-cpp.yml"
# - "**/*.cpp"
# - "vendor/**/*"
# - "CMakeLists.txt"
jobs:
lint-cpp:
if: ${{ !inputs.run-id }}
name: Lint C++
uses: ./.github/workflows/run-lint-cpp.yml
secrets: inherit
with:
pr-number: ${{ github.event.number }}

View File

@@ -7,18 +7,6 @@ on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/prettier-format.yml"
- "package.json"
- "scripts/**"
- "**.yml"
- "**.json"
- "**.js"
- "**.jsx"
- "**.ts"
- "**.tsx"
- "**.mjs"
- "**.cjs"
env:
BUN_VERSION: "1.1.27"
@@ -30,6 +18,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
@@ -38,9 +28,6 @@ jobs:
run: |
bun install
- name: Prettier Format
env:
ENABLE_CCACHE: OFF
SKIP_LLVM: ON
run: |
bun run prettier:diff
- name: Commit

View File

@@ -1,84 +0,0 @@
name: lint-cpp
permissions:
contents: read
env:
LLVM_VERSION: 18
LC_CTYPE: "en_US.UTF-8"
LC_ALL: "en_US.UTF-8"
on:
workflow_call:
inputs:
pr-number:
required: true
type: number
jobs:
lint-cpp:
name: Lint C++
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-xlarge' || 'macos-13' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: 1.1.23
- name: Install Dependencies
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
run: |
brew install \
llvm@${{ env.LLVM_VERSION }} \
ninja \
coreutils \
openssl@1.1 \
libiconv \
gnu-sed --force --overwrite
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
- name: Bun install
run: |
bun install
- name: clang-tidy
id: format
env:
CPU_TARGET: native
BUN_SILENT: 1
run: |
rm -f did_fail format.log
echo "${{ inputs.pr-number }}" > pr-number.txt
echo "pr_number=$(cat pr-number.txt)" >> $GITHUB_OUTPUT
bun run --silent build:tidy &> >(tee -p format.log) && echo 0 > did_succeed.txt
# Upload format.log as github artifact for the workflow
if [ -f did_succeed.txt ]; then
echo "0" > did_fail.txt
else
echo "1" > did_fail.txt
fi
echo "did_fail=$(cat did_fail.txt)" >> $GITHUB_OUTPUT
- name: Upload format.log
uses: actions/upload-artifact@v4
with:
name: format.log
path: format.log
- name: Upload PR
uses: actions/upload-artifact@v4
with:
name: pr-number.txt
path: pr-number.txt
- name: Upload PR
uses: actions/upload-artifact@v4
with:
name: did_fail.txt
path: did_fail.txt
- name: Fail if formatting failed
if: ${{ steps.format.outputs.did_fail == '1' }}
run: exit 1

View File

@@ -7,12 +7,6 @@ on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/zig-format.yml"
- "package.json"
- "scripts/**"
- "cmake/**"
- "src/**/*.zig"
env:
BUN_VERSION: "1.1.27"
@@ -25,21 +19,12 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: |
.github
package.json
scripts
cmake
src
packages
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Zig Format
env:
ENABLE_CCACHE: OFF
SKIP_LLVM: ON
run: |
bun run zig-format:diff
- name: Commit

4
.vscode/launch.json generated vendored
View File

@@ -172,6 +172,10 @@
"FORCE_COLOR": "1",
"BUN_DEBUG_QUIET_LOGS": "1",
"BUN_GARBAGE_COLLECTOR_LEVEL": "0",
"BUN_DEBUG_IncrementalGraph": "1",
"BUN_DEBUG_Bake": "1",
"BUN_DEBUG_reload_file_list": "1",
"GOMAXPROCS": "1",
},
"console": "internalConsole",
},

View File

@@ -43,10 +43,9 @@ include(BuildBun)
# --- Analysis ---
include(RunClangFormat)
include(RunClangTidy)
include(RunZigFormat)
if (ENABLE_PRETTIER)
if(ENABLE_ANALYSIS)
include(RunClangFormat)
include(RunClangTidy)
include(RunZigFormat)
include(RunPrettier)
endif()

View File

@@ -116,42 +116,26 @@ $ export PATH="$PATH:/usr/lib/llvm16/bin"
## Building Bun
After cloning the repository, run the following command to run the first build. This may take a while as it will clone submodules and build dependencies.
```bash
$ bun setup
```
The binary will be located at `./build/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, let's print the version number on the development build of Bun.
```bash
$ build/bun-debug --version
x.y.z_debug
```
To rebuild, you can invoke `bun run build`
After cloning the repository, run the following command to build. This may take a while as it will clone submodules and build dependencies.
```bash
$ bun run build
```
These two scripts, `setup` and `build`, are aliases to do roughly the following:
The binary will be located at `./build/debug/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, let's print the version number on the development build of Bun.
```bash
$ ./scripts/setup.sh
$ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
$ ninja -C build # 'bun run build' runs just this
$ build/debug/bun-debug --version
x.y.z_debug
```
Advanced users can pass CMake flags to customize the build.
## VSCode
VSCode is the recommended IDE for working on Bun, as it has been configured. Once opening, you can run `Extensions: Show Recommended Extensions` to install the recommended extensions for Zig and C++. ZLS is automatically configured.
If you use a different editor, make sure that you tell ZLS to use the automatically installed Zig compiler, which is located at `./.cache/zig/zig.exe`. The filename is `zig.exe` so that it works as expected on Windows, but it still works on macOS/Linux (it just has a surprising file extension).
If you use a different editor, make sure that you tell ZLS to use the automatically installed Zig compiler, which is located at `./vendor/zig/zig.exe`. The filename is `zig.exe` so that it works as expected on Windows, but it still works on macOS/Linux (it just has a surprising file extension).
We recommend adding `./build` to your `$PATH` so that you can run `bun-debug` in your terminal:
We recommend adding `./build/debug` to your `$PATH` so that you can run `bun-debug` in your terminal:
```sh
$ bun-debug
@@ -180,7 +164,7 @@ To compile a release build of Bun, run:
$ bun run build:release
```
The binary will be located at `./build-release/bun` and `./build-release/bun-profile`.
The binary will be located at `./build/release/bun` and `./build/release/bun-profile`.
### Download release build from pull requests
@@ -189,8 +173,8 @@ To save you time spent building a release build locally, we provide a way to run
To run a release build from a pull request, you can use the `bun-pr` npm package:
```sh
bunx bun-pr pr-number
bunx bun-pr branch/branch-name
bunx bun-pr <pr-number>
bunx bun-pr <branch-name>
bunx bun-pr "https://github.com/oven-sh/bun/pull/1234566"
```
@@ -222,24 +206,18 @@ $ valgrind --fair-sched=try --track-origins=yes bun-debug <args>
## Building WebKit locally + Debug mode of JSC
{% callout %}
**TODO**: This is out of date. TLDR is pass `-DUSE_DEBUG_JSC=1` or `-DWEBKIT_DIR=...` to CMake. it will probably need more fiddling. ask @paperdave if you need this.
{% /callout %}
WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:
```bash
# once you run this, `make submodule` can be used to automatically
# update WebKit and the other submodules
$ git submodule update --init --depth 1 --checkout src/bun.js/WebKit
# to make a jsc release build
$ make jsc
# JSC debug build does not work perfectly with Bun yet, this is actively being
# worked on and will eventually become the default.
$ make jsc-build-linux-compile-debug cpp
$ make jsc-build-mac-compile-debug cpp
# Clone WebKit into ./vendor/WebKit
$ git clone https://github.com/oven-sh/WebKit vendor/WebKit
# Make a debug build of JSC. This will output build artifacts in ./vendor/WebKit/WebKitBuild/Debug
# Optionally, you can use `make jsc` for a release build
$ make jsc-debug
# Build bun with the local JSC build
$ bun run build:local
```
Note that the WebKit folder, including build artifacts, is 8GB+ in size.

2
LATEST
View File

@@ -1 +1 @@
1.1.29
1.1.30

View File

@@ -1,6 +1,6 @@
import Color from "color";
import tinycolor from "tinycolor2";
import { bench, run, group } from "./runner.mjs";
import { bench, group, run } from "./runner.mjs";
const inputs = ["#f00", "rgb(255, 0, 0)", "rgba(255, 0, 0, 1)", "hsl(0, 100%, 50%)"];

View File

@@ -52,14 +52,14 @@ const BunBuildOptions = struct {
/// instead of at compile time. This is disabled in release or if this flag
/// is set (to allow CI to build a portable executable). Affected files:
///
/// - src/kit/runtime.ts (bundled)
/// - src/bake/runtime.ts (bundled)
/// - src/bun.js/api/FFI.h
///
/// A similar technique is used in C++ code for JavaScript builtins
force_embed_code: bool = false,
codegen_embed: bool = false,
/// `./build/codegen` or equivalent
generated_code_dir: []const u8,
codegen_path: []const u8,
no_llvm: bool,
cached_options_module: ?*Module = null,
@@ -71,7 +71,7 @@ const BunBuildOptions = struct {
}
pub fn shouldEmbedCode(opts: *const BunBuildOptions) bool {
return opts.optimize != .Debug or opts.force_embed_code;
return opts.optimize != .Debug or opts.codegen_embed;
}
pub fn buildOptionsModule(this: *BunBuildOptions, b: *Build) *Module {
@@ -83,10 +83,10 @@ const BunBuildOptions = struct {
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.generated_code_dir,
this.codegen_path,
}) catch @panic("OOM"));
opts.addOption(bool, "embed_code", this.shouldEmbedCode());
opts.addOption(bool, "codegen_embed", this.shouldEmbedCode());
opts.addOption(u32, "canary_revision", this.canary_revision orelse 0);
opts.addOption(bool, "is_canary", this.canary_revision != null);
opts.addOption(Version, "version", this.version);
@@ -195,12 +195,13 @@ pub fn build(b: *Build) !void {
const target = b.resolveTargetQuery(target_query);
const generated_code_dir = b.pathFromRoot(
b.option([]const u8, "generated-code", "Set the generated code directory") orelse
const codegen_path = b.pathFromRoot(
b.option([]const u8, "codegen_path", "Set the generated code directory") orelse
"build/debug/codegen",
);
const codegen_embed = b.option(bool, "codegen_embed", "If codegen files should be embedded in the binary") orelse false;
const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0";
const force_embed_js_code = b.option(bool, "force_embed_js_code", "Always embed JavaScript builtins") orelse false;
b.reference_trace = ref_trace: {
const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 16;
@@ -218,8 +219,8 @@ pub fn build(b: *Build) !void {
.os = os,
.arch = arch,
.generated_code_dir = generated_code_dir,
.force_embed_code = force_embed_js_code,
.codegen_path = codegen_path,
.codegen_embed = codegen_embed,
.no_llvm = no_llvm,
.version = try Version.parse(bun_version),
@@ -351,7 +352,7 @@ pub inline fn addMultiCheck(
.tracy_callstack_depth = root_build_options.tracy_callstack_depth,
.version = root_build_options.version,
.reported_nodejs_version = root_build_options.reported_nodejs_version,
.generated_code_dir = root_build_options.generated_code_dir,
.codegen_path = root_build_options.codegen_path,
.no_llvm = root_build_options.no_llvm,
};
@@ -475,13 +476,45 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
.{ .file = "ZigGeneratedClasses.zig", .import = "ZigGeneratedClasses" },
.{ .file = "ResolvedSourceTag.zig", .import = "ResolvedSourceTag" },
.{ .file = "ErrorCode.zig", .import = "ErrorCode" },
.{ .file = "kit.client.js", .import = "kit-codegen/kit.client.js", .enable = opts.shouldEmbedCode() },
.{ .file = "kit.server.js", .import = "kit-codegen/kit.server.js", .enable = opts.shouldEmbedCode() },
.{ .file = "runtime.out.js" },
.{ .file = "bake.client.js", .import = "bake-codegen/bake.client.js", .enable = opts.shouldEmbedCode() },
.{ .file = "bake.error.js", .import = "bake-codegen/bake.error.js", .enable = opts.shouldEmbedCode() },
.{ .file = "bake.server.js", .import = "bake-codegen/bake.server.js", .enable = opts.shouldEmbedCode() },
.{ .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/assert.js" },
.{ .file = "node-fallbacks/buffer.js" },
.{ .file = "node-fallbacks/console.js" },
.{ .file = "node-fallbacks/constants.js" },
.{ .file = "node-fallbacks/crypto.js" },
.{ .file = "node-fallbacks/domain.js" },
.{ .file = "node-fallbacks/events.js" },
.{ .file = "node-fallbacks/http.js" },
.{ .file = "node-fallbacks/https.js" },
.{ .file = "node-fallbacks/net.js" },
.{ .file = "node-fallbacks/os.js" },
.{ .file = "node-fallbacks/path.js" },
.{ .file = "node-fallbacks/process.js" },
.{ .file = "node-fallbacks/punycode.js" },
.{ .file = "node-fallbacks/querystring.js" },
.{ .file = "node-fallbacks/stream.js" },
.{ .file = "node-fallbacks/string_decoder.js" },
.{ .file = "node-fallbacks/sys.js" },
.{ .file = "node-fallbacks/timers.js" },
.{ .file = "node-fallbacks/tty.js" },
.{ .file = "node-fallbacks/url.js" },
.{ .file = "node-fallbacks/util.js" },
.{ .file = "node-fallbacks/zlib.js" },
}) |entry| {
if (!@hasField(@TypeOf(entry), "enable") or entry.enable) {
const path = b.pathJoin(&.{ opts.generated_code_dir, entry.file });
const path = b.pathJoin(&.{ opts.codegen_path, entry.file });
validateGeneratedPath(path);
obj.root_module.addAnonymousImport(entry.import, .{
const import_path = if (@hasField(@TypeOf(entry), "import"))
entry.import
else
entry.file;
obj.root_module.addAnonymousImport(import_path, .{
.root_source_file = .{ .cwd_relative = path },
});
}

View File

@@ -30,6 +30,10 @@ macro(optionx variable type description)
set(multiValueArgs)
cmake_parse_arguments(${variable} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(DEFINED ${variable})
set(${variable}_VALUE ${${variable}})
endif()
if(NOT ${type} MATCHES "^(BOOL|STRING|FILEPATH|PATH|INTERNAL)$")
set(${variable}_REGEX ${type})
set(${variable}_TYPE STRING)
@@ -65,7 +69,9 @@ macro(optionx variable type description)
message(FATAL_ERROR "Invalid ${${variable}_SOURCE}: ${${variable}_PREVIEW}=\"${${variable}}\", please use ${${variable}_PREVIEW}=<${${variable}_REGEX}>")
endif()
message(STATUS "Set ${variable}: ${${variable}}")
if(NOT ${variable}_VALUE STREQUAL ${variable})
message(STATUS "Set ${variable}: ${${variable}}")
endif()
endmacro()
# unsupported()
@@ -122,6 +128,7 @@ optionx(CACHE_PATH FILEPATH "The path to the cache directory" DEFAULT ${BUILD_PA
optionx(CACHE_STRATEGY "read-write|read-only|write-only|none" "The strategy to use for caching" DEFAULT "read-write")
optionx(CI BOOL "If CI is enabled" DEFAULT OFF)
optionx(ENABLE_ANALYSIS BOOL "If static analysis targets should be enabled" DEFAULT OFF)
if(CI)
set(WARNING FATAL_ERROR)
@@ -139,24 +146,8 @@ endif()
optionx(VENDOR_PATH FILEPATH "The path to the vendor directory" DEFAULT ${CWD}/vendor)
optionx(TMP_PATH FILEPATH "The path to the temporary directory" DEFAULT ${BUILD_PATH}/tmp)
optionx(FRESH BOOL "Set when --fresh is used" DEFAULT OFF)
optionx(CLEAN BOOL "Set when --clean is used" DEFAULT OFF)
# --- Helper functions ---
function(parse_semver value variable)
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${value}")
if(NOT match)
message(FATAL_ERROR "Invalid semver: \"${value}\"")
endif()
set(${variable}_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}" PARENT_SCOPE)
set(${variable}_VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
set(${variable}_VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
set(${variable}_VERSION_PATCH "${CMAKE_MATCH_3}" PARENT_SCOPE)
endfunction()
# setenv()
# Description:
# Sets an environment variable during the build step, and writes it to a .env file.
@@ -194,102 +185,154 @@ function(setenv variable value)
message(STATUS "Set ENV ${variable}: ${value}")
endfunction()
# check_command()
# satisfies_range()
# Description:
# Checks if a command is available, used by `find_command()` as a validator.
# Check if a version satisfies a version range
# Arguments:
# FOUND bool - The variable to set to true if the version is found
# CMD string - The executable to check the version of
function(check_command FOUND CMD)
set(${FOUND} OFF PARENT_SCOPE)
if(${CMD} MATCHES "zig")
set(CHECK_COMMAND ${CMD} version)
else()
set(CHECK_COMMAND ${CMD} --version)
endif()
execute_process(
COMMAND ${CHECK_COMMAND}
RESULT_VARIABLE RESULT
OUTPUT_VARIABLE OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT RESULT EQUAL 0 OR NOT OUTPUT)
message(DEBUG "${CHECK_COMMAND}, exited with code ${RESULT}")
# version string - The version to check (e.g. "1.2.3")
# range string - The range to check against (e.g. ">=1.2.3")
# variable string - The variable to store the result in
function(satisfies_range version range variable)
if(range STREQUAL "ignore")
set(${variable} ON PARENT_SCOPE)
return()
endif()
parse_semver(${OUTPUT} CMD)
parse_semver(${CHECK_COMMAND_VERSION} CHECK)
set(${variable} OFF PARENT_SCOPE)
if(CHECK_COMMAND_VERSION MATCHES ">=")
if(NOT CMD_VERSION VERSION_GREATER_EQUAL ${CHECK_VERSION})
message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: ${CHECK_COMMAND_VERSION}")
return()
endif()
elseif(CHECK_COMMAND_VERSION MATCHES ">")
if(NOT CMD_VERSION VERSION_GREATER ${CHECK_VERSION})
message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: ${CHECK_COMMAND_VERSION}")
return()
endif()
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${version}")
if(NOT match)
return()
endif()
set(version ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3})
string(REGEX MATCH "(>=|<=|>|<)?([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${range}")
if(NOT match)
return()
endif()
set(comparator ${CMAKE_MATCH_1})
set(range ${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${CMAKE_MATCH_4})
if(comparator STREQUAL ">=")
set(comparator VERSION_GREATER_EQUAL)
elseif(comparator STREQUAL ">")
set(comparator VERSION_GREATER)
elseif(comparator STREQUAL "<=")
set(comparator VERSION_LESS_EQUAL)
elseif(comparator STREQUAL "<")
set(comparator VERSION_LESS)
else()
if(NOT CMD_VERSION VERSION_EQUAL ${CHECK_VERSION})
message(DEBUG "${CHECK_COMMAND}, actual: ${CMD_VERSION}, expected: =${CHECK_COMMAND_VERSION}")
return()
endif()
set(comparator VERSION_EQUAL)
endif()
set(${FOUND} TRUE PARENT_SCOPE)
if(version ${comparator} ${range})
set(${variable} ON PARENT_SCOPE)
endif()
endfunction()
# find_command()
# Description:
# Finds a command, similar to `find_program()`, but allows for version checking.
# Arguments:
# VARIABLE string - The variable to set
# COMMAND string[] - The names of the command to find
# PATHS string[] - The paths to search for the command
# REQUIRED bool - If false, the command is optional
# VERSION string - The version of the command to find (e.g. "1.2.3" or ">1.2.3")
# VARIABLE string - The variable to set
# VERSION_VARIABLE string - The variable to check for the version
# COMMAND string[] - The names of the command to find
# PATHS string[] - The paths to search for the command
# REQUIRED bool - If false, the command is optional
# VERSION string - The version of the command to find (e.g. "1.2.3" or ">1.2.3")
function(find_command)
set(options)
set(args VARIABLE VERSION MIN_VERSION REQUIRED)
set(args VARIABLE VERSION_VARIABLE REQUIRED VERSION)
set(multiArgs COMMAND PATHS)
cmake_parse_arguments(CMD "${options}" "${args}" "${multiArgs}" ${ARGN})
cmake_parse_arguments(FIND "" "${args}" "${multiArgs}" ${ARGN})
if(NOT CMD_VARIABLE)
message(FATAL_ERROR "find_command: VARIABLE is required")
if(NOT FIND_VARIABLE OR NOT FIND_COMMAND)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: VARIABLE and COMMAND are required")
endif()
if(NOT CMD_COMMAND)
message(FATAL_ERROR "find_command: COMMAND is required")
if(NOT FIND_VERSION_VARIABLE)
set(FIND_VERSION_VARIABLE ${FIND_VARIABLE}_VERSION)
endif()
if(CMD_VERSION)
set(CHECK_COMMAND_VERSION ${CMD_VERSION}) # special global variable
set(CMD_VALIDATOR VALIDATOR check_command)
list(GET FIND_COMMAND 0 FIND_NAME)
if(FIND_VERSION)
optionx(${FIND_VERSION_VARIABLE} STRING "The version of ${FIND_NAME} to find" DEFAULT "${FIND_VERSION}")
function(find_command_version variable exe)
set(${variable} OFF PARENT_SCOPE)
if(${exe} MATCHES "(go|zig)(\.exe)?$")
set(command ${exe} version)
else()
set(command ${exe} --version)
endif()
execute_process(
COMMAND ${command}
RESULT_VARIABLE result
OUTPUT_VARIABLE output
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(NOT result EQUAL 0)
set(reason "exited with ${result}")
elseif(NOT output)
set(reason "no output")
else()
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" match "${output}")
if(match)
set(version ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3})
set(reason "\"${version}\"")
else()
set(reason "no version")
endif()
endif()
set_property(GLOBAL PROPERTY ${FIND_NAME} "${exe}: ${reason}" APPEND)
if(version)
satisfies_range(${version} ${${FIND_VERSION_VARIABLE}} ${variable})
set(${variable} ${${variable}} PARENT_SCOPE)
endif()
endfunction()
set(FIND_VALIDATOR VALIDATOR find_command_version)
endif()
find_program(
${CMD_VARIABLE}
NAMES ${CMD_COMMAND}
PATHS ${CMD_PATHS}
${CMD_VALIDATOR}
${FIND_VARIABLE}
NAMES ${FIND_COMMAND}
PATHS ${FIND_PATHS}
${FIND_VALIDATOR}
)
if(NOT CMD_REQUIRED STREQUAL "OFF" AND ${CMD_VARIABLE} MATCHES "NOTFOUND")
if(CMD_VERSION)
message(FATAL_ERROR "Command not found: \"${CMD_COMMAND}\" that matches version \"${CHECK_COMMAND_VERSION}\"")
if(NOT FIND_REQUIRED STREQUAL "OFF" AND ${FIND_VARIABLE} MATCHES "NOTFOUND")
set(error "Command not found: \"${FIND_NAME}\"")
if(FIND_VERSION)
set(error "${error} that satisfies version \"${${FIND_VERSION_VARIABLE}}\"")
endif()
message(FATAL_ERROR "Command not found: \"${CMD_COMMAND}\"")
get_property(FIND_RESULTS GLOBAL PROPERTY ${FIND_NAME})
if(NOT FIND_RESULTS MATCHES "NOTFOUND")
set(error "${error}\nThe following commands did not satisfy the requirement:")
foreach(result ${FIND_RESULTS})
set(error "${error}\n ${result}")
endforeach()
endif()
set(error "${error}\nTo fix this, either:
1. Install ${FIND_NAME} ${${FIND_VERSION_VARIABLE}}
2. Set -D${FIND_VERSION_VARIABLE}=<version> to require a different version
3. Set -D${FIND_VERSION_VARIABLE}=ignore to allow any version
")
message(FATAL_ERROR ${error})
endif()
if(${CMD_VARIABLE} MATCHES "NOTFOUND")
unset(${CMD_VARIABLE} PARENT_SCOPE)
if(${FIND_VARIABLE} MATCHES "NOTFOUND")
unset(${FIND_VARIABLE} PARENT_SCOPE)
else()
setx(${CMD_VARIABLE} ${${CMD_VARIABLE}} PARENT_SCOPE)
setx(${FIND_VARIABLE} ${${FIND_VARIABLE}} PARENT_SCOPE)
endif()
endfunction()

View File

@@ -1,14 +1,5 @@
# https://clang.llvm.org/docs/ClangFormat.html
find_command(
VARIABLE
CLANG_FORMAT_PROGRAM
COMMAND
clang-format
REQUIRED
OFF
)
set(CLANG_FORMAT_SOURCES ${BUN_C_SOURCES} ${BUN_CXX_SOURCES})
register_command(

View File

@@ -1,16 +1,5 @@
# https://clang.llvm.org/extra/clang-tidy/
find_command(
VARIABLE
CLANG_TIDY_PROGRAM
COMMAND
clang-tidy
VERSION
${LLVM_VERSION}
REQUIRED
OFF
)
set(CLANG_TIDY_SOURCES ${BUN_C_SOURCES} ${BUN_CXX_SOURCES})
set(CLANG_TIDY_COMMAND ${CLANG_TIDY_PROGRAM}

View File

@@ -1,7 +1,7 @@
# IWYU = "Include What You Use"
# https://include-what-you-use.org/
setx(IWYU_SOURCE_PATH ${CACHE_PATH}/iwyu-${LLVM_VERSION_MAJOR})
setx(IWYU_SOURCE_PATH ${CACHE_PATH}/iwyu-${LLVM_VERSION})
setx(IWYU_BUILD_PATH ${IWYU_SOURCE_PATH}/build)
setx(IWYU_PROGRAM ${IWYU_BUILD_PATH}/bin/include-what-you-use)
@@ -11,7 +11,7 @@ register_repository(
REPOSITORY
include-what-you-use/include-what-you-use
BRANCH
clang_${LLVM_VERSION_MAJOR}
clang_${LLVM_VERSION}
PATH
${IWYU_SOURCE_PATH}
)

View File

@@ -95,7 +95,7 @@ register_command(
if(GIT_CHANGED_SOURCES)
set(PRETTIER_CHANGED_SOURCES)
foreach(source ${PRETTIER_SOURCES})
list(FIND PRETTIER_CHANGED_SOURCES ${source} index)
list(FIND GIT_CHANGED_SOURCES ${source} index)
if(NOT ${index} EQUAL -1)
list(APPEND PRETTIER_CHANGED_SOURCES ${source})
endif()

View File

@@ -21,10 +21,16 @@ else()
set(buns ${bun})
endif()
# Some commands use this path, and some do not.
# In the future, change those commands so that generated files are written to this path.
optionx(CODEGEN_PATH FILEPATH "Path to the codegen directory" DEFAULT ${BUILD_PATH}/codegen)
if(RELEASE OR CI)
set(DEFAULT_CODEGEN_EMBED ON)
else()
set(DEFAULT_CODEGEN_EMBED OFF)
endif()
optionx(CODEGEN_EMBED BOOL "If codegen files should be embedded in the binary" DEFAULT ${DEFAULT_CODEGEN_EMBED})
if((NOT DEFINED CONFIGURE_DEPENDS AND NOT CI) OR CONFIGURE_DEPENDS)
set(CONFIGURE_DEPENDS "CONFIGURE_DEPENDS")
else()
@@ -33,39 +39,6 @@ endif()
# --- Codegen ---
set(BUN_ZIG_IDENTIFIER_SOURCE ${CWD}/src/js_lexer)
set(BUN_ZIG_IDENTIFIER_SCRIPT ${BUN_ZIG_IDENTIFIER_SOURCE}/identifier_data.zig)
file(GLOB BUN_ZIG_IDENTIFIER_SOURCES ${CONFIGURE_DEPENDS}
${BUN_ZIG_IDENTIFIER_SCRIPT}
${BUN_ZIG_IDENTIFIER_SOURCE}/*.zig
)
set(BUN_ZIG_IDENTIFIER_OUTPUTS
${BUN_ZIG_IDENTIFIER_SOURCE}/id_continue_bitset.blob
${BUN_ZIG_IDENTIFIER_SOURCE}/id_continue_bitset.meta.blob
${BUN_ZIG_IDENTIFIER_SOURCE}/id_start_bitset.blob
${BUN_ZIG_IDENTIFIER_SOURCE}/id_start_bitset.meta.blob
)
register_command(
TARGET
bun-identifier-data
COMMENT
"Generating src/js_lexer/*.blob"
COMMAND
${ZIG_EXECUTABLE}
run
${CMAKE_ZIG_FLAGS}
${BUN_ZIG_IDENTIFIER_SCRIPT}
SOURCES
${BUN_ZIG_IDENTIFIER_SOURCES}
TARGETS
clone-zig
OUTPUTS
${BUN_ZIG_IDENTIFIER_OUTPUTS}
)
set(BUN_ERROR_SOURCE ${CWD}/packages/bun-error)
file(GLOB BUN_ERROR_SOURCES ${CONFIGURE_DEPENDS}
@@ -76,7 +49,7 @@ file(GLOB BUN_ERROR_SOURCES ${CONFIGURE_DEPENDS}
${BUN_ERROR_SOURCE}/img/*
)
set(BUN_ERROR_OUTPUT ${BUN_ERROR_SOURCE}/dist)
set(BUN_ERROR_OUTPUT ${CODEGEN_PATH}/bun-error)
set(BUN_ERROR_OUTPUTS
${BUN_ERROR_OUTPUT}/index.js
${BUN_ERROR_OUTPUT}/bun-error.css
@@ -114,13 +87,13 @@ register_command(
)
set(BUN_FALLBACK_DECODER_SOURCE ${CWD}/src/fallback.ts)
set(BUN_FALLBACK_DECODER_OUTPUT ${CWD}/src/fallback.out.js)
set(BUN_FALLBACK_DECODER_OUTPUT ${CODEGEN_PATH}/fallback-decoder.js)
register_command(
TARGET
bun-fallback-decoder
COMMENT
"Building src/fallback.out.js"
"Building fallback-decoder.js"
COMMAND
${ESBUILD_EXECUTABLE} ${ESBUILD_ARGS}
${BUN_FALLBACK_DECODER_SOURCE}
@@ -137,7 +110,7 @@ register_command(
)
set(BUN_RUNTIME_JS_SOURCE ${CWD}/src/runtime.bun.js)
set(BUN_RUNTIME_JS_OUTPUT ${CWD}/src/runtime.out.js)
set(BUN_RUNTIME_JS_OUTPUT ${CODEGEN_PATH}/runtime.out.js)
register_command(
TARGET
@@ -167,7 +140,7 @@ file(GLOB BUN_NODE_FALLBACKS_SOURCES ${CONFIGURE_DEPENDS}
${BUN_NODE_FALLBACKS_SOURCE}/*.js
)
set(BUN_NODE_FALLBACKS_OUTPUT ${BUN_NODE_FALLBACKS_SOURCE}/out)
set(BUN_NODE_FALLBACKS_OUTPUT ${CODEGEN_PATH}/node-fallbacks)
set(BUN_NODE_FALLBACKS_OUTPUTS)
foreach(source ${BUN_NODE_FALLBACKS_SOURCES})
get_filename_component(filename ${source} NAME)
@@ -187,7 +160,7 @@ register_command(
TARGET
bun-node-fallbacks
COMMENT
"Building src/node-fallbacks/*.js"
"Building node-fallbacks/*.js"
CWD
${BUN_NODE_FALLBACKS_SOURCE}
COMMAND
@@ -324,40 +297,41 @@ register_command(
${BUN_JAVASCRIPT_OUTPUTS}
)
set(BUN_KIT_RUNTIME_CODEGEN_SCRIPT ${CWD}/src/codegen/kit-codegen.ts)
set(BUN_BAKE_RUNTIME_CODEGEN_SCRIPT ${CWD}/src/codegen/bake-codegen.ts)
file(GLOB_RECURSE BUN_KIT_RUNTIME_SOURCES ${CONFIGURE_DEPENDS}
${CWD}/src/kit/*.ts
${CWD}/src/kit/*/*.ts
file(GLOB_RECURSE BUN_BAKE_RUNTIME_SOURCES ${CONFIGURE_DEPENDS}
${CWD}/src/bake/*.ts
${CWD}/src/bake/*/*.ts
${CWD}/src/bake/*/*.css
)
list(APPEND BUN_KIT_RUNTIME_CODEGEN_SOURCES
list(APPEND BUN_BAKE_RUNTIME_CODEGEN_SOURCES
${CWD}/src/bun.js/bindings/InternalModuleRegistry.cpp
)
set(BUN_KIT_RUNTIME_OUTPUTS
${CODEGEN_PATH}/kit_empty_file
${CODEGEN_PATH}/kit.client.js
${CODEGEN_PATH}/kit.server.js
set(BUN_BAKE_RUNTIME_OUTPUTS
${CODEGEN_PATH}/bake.client.js
${CODEGEN_PATH}/bake.server.js
)
register_command(
TARGET
bun-kit-codegen
bun-bake-codegen
COMMENT
"Bundling Kit Runtime"
COMMAND
${BUN_EXECUTABLE}
run
${BUN_KIT_RUNTIME_CODEGEN_SCRIPT}
${BUN_BAKE_RUNTIME_CODEGEN_SCRIPT}
--debug=${DEBUG}
--codegen_root=${CODEGEN_PATH}
SOURCES
${BUN_KIT_RUNTIME_SOURCES}
${BUN_KIT_RUNTIME_CODEGEN_SOURCES}
${BUN_KIT_RUNTIME_CODEGEN_SCRIPT}
${BUN_BAKE_RUNTIME_SOURCES}
${BUN_BAKE_RUNTIME_CODEGEN_SOURCES}
${BUN_BAKE_RUNTIME_CODEGEN_SCRIPT}
OUTPUTS
${BUN_KIT_RUNTIME_OUTPUTS}
${CODEGEN_PATH}/bake_empty_file
${BUN_BAKE_RUNTIME_OUTPUTS}
)
set(BUN_JS_SINK_SCRIPT ${CWD}/src/codegen/generate-jssink.ts)
@@ -398,6 +372,7 @@ set(BUN_OBJECT_LUT_SOURCES
${CWD}/src/bun.js/bindings/BunProcess.cpp
${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp
${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp
${CWD}/src/bun.js/modules/NodeModuleModule.cpp
)
set(BUN_OBJECT_LUT_OUTPUTS
@@ -407,8 +382,10 @@ set(BUN_OBJECT_LUT_OUTPUTS
${CODEGEN_PATH}/BunProcess.lut.h
${CODEGEN_PATH}/ProcessBindingConstants.lut.h
${CODEGEN_PATH}/ProcessBindingNatives.lut.h
${CODEGEN_PATH}/NodeModuleModule.lut.h
)
macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps)
set(_tmp)
get_source_file_property(_tmp ${_source} OBJECT_DEPENDS)
@@ -487,7 +464,6 @@ list(APPEND BUN_ZIG_SOURCES
)
set(BUN_ZIG_GENERATED_SOURCES
${BUN_ZIG_IDENTIFIER_OUTPUTS}
${BUN_ERROR_OUTPUTS}
${BUN_FALLBACK_DECODER_OUTPUT}
${BUN_RUNTIME_JS_OUTPUT}
@@ -499,9 +475,9 @@ set(BUN_ZIG_GENERATED_SOURCES
# In debug builds, these are not embedded, but rather referenced at runtime.
if (DEBUG)
list(APPEND BUN_ZIG_GENERATED_SOURCES ${CODEGEN_PATH}/kit_empty_file)
list(APPEND BUN_ZIG_GENERATED_SOURCES ${CODEGEN_PATH}/bake_empty_file)
else()
list(APPEND BUN_ZIG_GENERATED_SOURCES ${BUN_KIT_RUNTIME_OUTPUTS})
list(APPEND BUN_ZIG_GENERATED_SOURCES ${BUN_BAKE_RUNTIME_OUTPUTS})
endif()
set(BUN_ZIG_OUTPUT ${BUILD_PATH}/bun-zig.o)
@@ -543,7 +519,8 @@ register_command(
-Dsha=${REVISION}
-Dreported_nodejs_version=${NODEJS_VERSION}
-Dcanary=${CANARY_REVISION}
-Dgenerated-code=${CODEGEN_PATH}
-Dcodegen_path=${CODEGEN_PATH}
-Dcodegen_embed=$<IF:$<BOOL:${CODEGEN_EMBED}>,true,false>
ARTIFACTS
${BUN_ZIG_OUTPUT}
TARGETS
@@ -570,7 +547,7 @@ file(GLOB BUN_CXX_SOURCES ${CONFIGURE_DEPENDS}
${CWD}/src/bun.js/bindings/webcrypto/*/*.cpp
${CWD}/src/bun.js/bindings/v8/*.cpp
${CWD}/src/bun.js/bindings/v8/shim/*.cpp
${CWD}/src/kit/*.cpp
${CWD}/src/bake/*.cpp
${CWD}/src/deps/*.cpp
${BUN_USOCKETS_SOURCE}/src/crypto/*.cpp
)
@@ -879,26 +856,33 @@ else()
-Wl,--as-needed
-Wl,--gc-sections
-Wl,-z,stack-size=12800000
-Wl,--wrap=fcntl
-Wl,--wrap=fcntl64
-Wl,--wrap=stat64
-Wl,--wrap=pow
-Wl,--wrap=cosf
-Wl,--wrap=exp
-Wl,--wrap=expf
-Wl,--wrap=log
-Wl,--wrap=log2
-Wl,--wrap=lstat
-Wl,--wrap=stat64
-Wl,--wrap=stat
-Wl,--wrap=fcntl
-Wl,--wrap=fcntl64
-Wl,--wrap=fmod
-Wl,--wrap=fmodf
-Wl,--wrap=fstat
-Wl,--wrap=fstatat
-Wl,--wrap=lstat64
-Wl,--wrap=fstat64
-Wl,--wrap=fstatat
-Wl,--wrap=fstatat64
-Wl,--wrap=log
-Wl,--wrap=log10f
-Wl,--wrap=log2
-Wl,--wrap=log2f
-Wl,--wrap=logf
-Wl,--wrap=lstat
-Wl,--wrap=lstat64
-Wl,--wrap=mknod
-Wl,--wrap=mknodat
-Wl,--wrap=pow
-Wl,--wrap=sincosf
-Wl,--wrap=sinf
-Wl,--wrap=stat
-Wl,--wrap=stat64
-Wl,--wrap=statx
-Wl,--wrap=fmod
-Wl,--wrap=tanf
-Wl,--compress-debug-sections=zlib
-Wl,-z,lazy
-Wl,-z,norelro

View File

@@ -11,9 +11,13 @@ find_command(
COMMAND
ccache
REQUIRED
ON
${CI}
)
if(NOT CCACHE_PROGRAM)
return()
endif()
set(CCACHE_ARGS CMAKE_C_COMPILER_LAUNCHER CMAKE_CXX_COMPILER_LAUNCHER)
foreach(arg ${CCACHE_ARGS})
setx(${arg} ${CCACHE_PROGRAM})

View File

@@ -11,7 +11,7 @@ if(NOT GIT_PROGRAM)
return()
endif()
set(GIT_DIFF_COMMAND ${GIT_PROGRAM} diff --no-color --name-only --diff-filter=AMCR)
set(GIT_DIFF_COMMAND ${GIT_PROGRAM} diff --no-color --name-only --diff-filter=AMCR origin/main HEAD)
execute_process(
COMMAND
@@ -34,5 +34,10 @@ if(NOT GIT_DIFF_RESULT EQUAL 0)
endif()
string(REPLACE "\n" ";" GIT_CHANGED_SOURCES "${GIT_DIFF}")
if(CI)
setx(GIT_CHANGED_SOURCES ${GIT_CHANGED_SOURCES})
endif()
list(TRANSFORM GIT_CHANGED_SOURCES PREPEND ${CWD}/)
list(LENGTH GIT_CHANGED_SOURCES GIT_CHANGED_SOURCES_COUNT)

View File

@@ -1,6 +1,6 @@
optionx(SKIP_LLVM BOOL "If LLVM setup should be skipped" DEFAULT OFF)
optionx(ENABLE_LLVM BOOL "If LLVM should be used for compilation" DEFAULT ON)
if(SKIP_LLVM)
if(NOT ENABLE_LLVM)
return()
endif()
@@ -11,45 +11,90 @@ else()
endif()
optionx(LLVM_VERSION STRING "The version of LLVM to use" DEFAULT ${DEFAULT_LLVM_VERSION})
parse_semver(${LLVM_VERSION} LLVM)
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" USE_LLVM_VERSION ${LLVM_VERSION})
if(USE_LLVM_VERSION)
set(LLVM_VERSION_MAJOR ${CMAKE_MATCH_1})
set(LLVM_VERSION_MINOR ${CMAKE_MATCH_2})
set(LLVM_VERSION_PATCH ${CMAKE_MATCH_3})
endif()
set(LLVM_PATHS)
if(APPLE)
execute_process(
COMMAND brew --prefix llvm@${LLVM_VERSION_MAJOR}
OUTPUT_VARIABLE DEFAULT_LLVM_PREFIX
COMMAND brew --prefix
OUTPUT_VARIABLE HOMEBREW_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(NOT DEFAULT_LLVM_PREFIX)
set(DEFAULT_LLVM_PREFIX /opt/homebrew/opt/llvm)
if(NOT HOMEBREW_PREFIX)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64")
set(HOMEBREW_PREFIX /opt/homebrew)
else()
set(HOMEBREW_PREFIX /usr/local)
endif()
endif()
list(APPEND LLVM_PATHS ${HOMEBREW_PREFIX}/opt/llvm/bin)
if(USE_LLVM_VERSION)
list(APPEND LLVM_PATHS ${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION_MAJOR}/bin)
endif()
elseif(NOT WIN32)
set(DEFAULT_LLVM_PREFIX /usr/lib/llvm-${LLVM_VERSION_MAJOR})
else()
set(DEFAULT_LLVM_PREFIX /usr/lib)
endif()
optionx(LLVM_PREFIX FILEPATH "The path to the LLVM installation" DEFAULT ${DEFAULT_LLVM_PREFIX})
set(LLVM_PATH ${LLVM_PREFIX}/bin)
if(UNIX)
list(APPEND LLVM_PATHS /usr/lib/llvm/bin)
if(USE_LLVM_VERSION)
list(APPEND LLVM_PATHS
/usr/lib/llvm-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}/bin
/usr/lib/llvm-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}/bin
/usr/lib/llvm-${LLVM_VERSION_MAJOR}/bin
)
endif()
endif()
macro(find_llvm_command variable command)
set(commands ${command})
if(USE_LLVM_VERSION)
list(APPEND commands
${command}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}
${command}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}
${command}-${LLVM_VERSION_MAJOR}
)
endif()
macro(find_llvm_command VARIABLE COMMAND)
find_command(
VARIABLE ${VARIABLE}
COMMAND ${COMMAND} ${COMMAND}-${LLVM_VERSION_MAJOR}
PATHS ${LLVM_PATH}
VARIABLE ${variable}
VERSION_VARIABLE LLVM_VERSION
COMMAND ${commands}
PATHS ${LLVM_PATHS}
VERSION ${LLVM_VERSION}
)
list(APPEND CMAKE_ARGS -D${VARIABLE}=${${VARIABLE}})
list(APPEND CMAKE_ARGS -D${variable}=${${variable}})
endmacro()
macro(find_llvm_command_no_version VARIABLE COMMAND)
macro(find_llvm_command_no_version variable command)
set(commands ${command})
if(USE_LLVM_VERSION)
list(APPEND commands
${command}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}
${command}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}
${command}-${LLVM_VERSION_MAJOR}
)
endif()
find_command(
VARIABLE ${VARIABLE}
COMMAND ${COMMAND} ${COMMAND}-${LLVM_VERSION_MAJOR}
PATHS ${LLVM_PATH}
REQUIRED ON
VARIABLE ${variable}
VERSION_VARIABLE LLVM_VERSION
COMMAND ${commands}
PATHS ${LLVM_PATHS}
)
list(APPEND CMAKE_ARGS -D${VARIABLE}=${${VARIABLE}})
list(APPEND CMAKE_ARGS -D${variable}=${${variable}})
endmacro()
if(WIN32)
@@ -69,3 +114,8 @@ else()
find_llvm_command(CMAKE_DSYMUTIL dsymutil)
endif()
endif()
if(ENABLE_ANALYSIS)
find_llvm_command(CLANG_FORMAT_PROGRAM clang-format)
find_llvm_command(CLANG_TIDY_PROGRAM clang-tidy)
endif()

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 76798f7b2fb287ee9f1ecce98bae895a2d026d93)
set(WEBKIT_VERSION 12e2f46fb01f7c5cf5a992b9414ddfaab32b7110)
endif()
if(WEBKIT_LOCAL)

View File

@@ -14,7 +14,7 @@ In Bun v1.1.9, we added support for DNS caching. This cache makes repeated conne
At the time of writing, we cache up to 255 entries for a maximum of 30 seconds (each). If any connections to a host fail, we remove the entry from the cache. When multiple connections are made to the same host simultaneously, DNS lookups are deduplicated to avoid making multiple requests for the same host.
This cache is automatically used by;
This cache is automatically used by:
- `bun install`
- `fetch()`
@@ -99,7 +99,7 @@ console.log(stats);
### Configuring DNS cache TTL
Bun defaults to 30 seconds for the TTL of DNS cache entries. To change this, you can set the envionrment variable `$BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS`. For example, to set the TTL to 5 seconds:
Bun defaults to 30 seconds for the TTL of DNS cache entries. To change this, you can set the environment variable `$BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS`. For example, to set the TTL to 5 seconds:
```sh
BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS=5 bun run my-script.ts

View File

@@ -325,6 +325,28 @@ As a performance optimization, the class constructor is not called, default init
The database columns are set as properties on the class instance.
### `.iterate()` (`@@iterator`)
Use `.iterate()` to run a query and incrementally return results. This is useful for large result sets that you want to process one row at a time without loading all the results into memory.
```ts
const query = db.query("SELECT * FROM foo");
for (const row of query.iterate()) {
console.log(row);
}
```
You can also use the `@@iterator` protocol:
```ts
const query = db.query("SELECT * FROM foo");
for (const row of query) {
console.log(row);
}
```
This feature was added in Bun v1.1.31.
### `.values()`
Use `values()` to run a query and get back all results as an array of arrays.

View File

@@ -580,6 +580,65 @@ const foo = new Foo();
console.log(foo); // => "foo"
```
## `Bun.inspect.table(tabularData, properties, options)`
Format tabular data into a string. Like [`console.table`](https://developer.mozilla.org/en-US/docs/Web/API/console/table_static), except it returns a string rather than printing to the console.
```ts
console.log(
Bun.inspect.table([
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
]),
);
//
// ┌───┬───┬───┬───┐
// │ │ a │ b │ c │
// ├───┼───┼───┼───┤
// │ 0 │ 1 │ 2 │ 3 │
// │ 1 │ 4 │ 5 │ 6 │
// │ 2 │ 7 │ 8 │ 9 │
// └───┴───┴───┴───┘
```
Additionally, you can pass an array of property names to display only a subset of properties.
```ts
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
["a", "c"],
),
);
//
// ┌───┬───┬───┐
// │ │ a │ c │
// ├───┼───┼───┤
// │ 0 │ 1 │ 3 │
// │ 1 │ 4 │ 6 │
// └───┴───┴───┘
```
You can also conditionally enable ANSI colors by passing `{ colors: true }`.
```ts
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
{
colors: true,
},
),
);
```
## `Bun.nanoseconds()`
Returns the number of nanoseconds since the current `bun` process started, as a `number`. Useful for high-precision timing and benchmarking.

View File

@@ -343,7 +343,11 @@ Depending on the target, Bun will apply different module resolution rules and op
Specifies the module format to be used in the generated bundles.
Currently the bundler only supports one module format: `"esm"`. Support for `"cjs"` and `"iife"` are planned.
Bun defaults to `"esm"`, and provides experimental support for `"cjs"` and `"iife"`.
#### `format: "esm"` - ES Module
This is the default format, which supports ES Module syntax including top-level `await`, import.meta, and more.
{% codetabs %}
@@ -361,44 +365,31 @@ $ bun build ./index.tsx --outdir ./out --format esm
{% /codetabs %}
<!-- ### `bundling`
To use ES Module syntax in browsers, set `format` to `"esm"` and make sure your `<script type="module">` tag has `type="module"` set.
Whether to enable bundling.
#### `format: "cjs"` - CommonJS
{% codetabs group="a" %}
To build a CommonJS module, set `format` to `"cjs"`. When choosing `"cjs"`, the default target changes from `"browser"` (esm) to `"node"` (cjs). CommonJS modules transpiled with `format: "cjs", target: "node"` can be executed in both Bun and Node.js (assuming the APIs in use are supported by both).
{% codetabs %}
```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
bundling: true, // default
format: "cjs",
})
```
```bash#CLI
# bundling is enabled by default
$ bun build ./index.tsx --outdir ./out
$ bun build ./index.tsx --outdir ./out --format cjs
```
{% /codetabs %}
Set to `false` to disable bundling. Instead, files will be transpiled and individually written to `outdir`.
#### `format: "iife"` - IIFE
{% codetabs group="a" %}
```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
bundling: false,
})
```
```bash#CLI
$ bun build ./index.tsx --outdir ./out --no-bundling
```
{% /codetabs %} -->
TODO: document IIFE once we support globalNames.
### `splitting`
@@ -760,7 +751,7 @@ $ bun build ./index.tsx --outdir ./out --external '*'
### `packages`
Control whatever package dependencies are included to bundle or not. Possible values: `bundle` (default), `external`. Bun threats any import which path do not start with `.`, `..` or `/` as package.
Control whatever package dependencies are included to bundle or not. Possible values: `bundle` (default), `external`. Bun treats any import which path do not start with `.`, `..` or `/` as package.
{% codetabs group="a" %}
@@ -1099,6 +1090,84 @@ $ bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:file
{% /codetabs %}
### `banner`
A banner to be added to the final bundle, this can be a directive like "use client" for react or a comment block such as a license for the code.
{% codetabs %}
```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
banner: '"use client";'
})
```
```bash#CLI
$ bun build ./index.tsx --outdir ./out --banner "\"use client\";"
```
{% /codetabs %}
### `footer`
A footer to be added to the final bundle, this can be something like a comment block for a license or just a fun easter egg.
{% codetabs %}
```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
footer: '// built with love in SF'
})
```
```bash#CLI
$ bun build ./index.tsx --outdir ./out --footer="// built with love in SF"
```
{% /codetabs %}
### `drop`
Remove function calls from a bundle. For example, `--drop=console` will remove all calls to `console.log`. Arguments to calls will also be removed, regardless of if those arguments may have side effects. Dropping `debugger` will remove all `debugger` statements.
{% codetabs %}
```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
drop: ["console", "debugger", "anyIdentifier.or.propertyAccess"],
})
```
```bash#CLI
$ bun build ./index.tsx --outdir ./out --drop=console --drop=debugger --drop=anyIdentifier.or.propertyAccess
```
{% /codetabs %}
### `experimentalCss`
Whether to enable _experimental_ support for bundling CSS files. Defaults to `false`.
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 %}
## Outputs
The `Bun.build` function returns a `Promise<BuildOutput>`, defined as:
@@ -1140,7 +1209,7 @@ Each artifact also contains the following properties:
---
- `kind`
- What kind of build output this file is. A build generates bundled entrypoints, code-split "chunks", sourcemaps, and copied assets (like images).
- What kind of build output this file is. A build generates bundled entrypoints, code-split "chunks", sourcemaps, bytecode, and copied assets (like images).
---
@@ -1159,11 +1228,6 @@ Each artifact also contains the following properties:
---
- `bytecode`
- Generate bytecode for any JavaScript/TypeScript entrypoints. This can greatly improve startup times for large applications. Only supported for `"cjs"` format, only supports `"target": "bun"` and dependent on a matching version of Bun. This adds a corresponding `.jsc` file for each entrypoint
---
- `sourcemap`
- The sourcemap file corresponding to this file, if generated. Only defined for entrypoints and chunks.
@@ -1210,6 +1274,26 @@ BuildArtifact (entry-point) {
{% /codetabs %}
### Bytecode
The `bytecode: boolean` option can be used to generate bytecode for any JavaScript/TypeScript entrypoints. This can greatly improve startup times for large applications. Only supported for `"cjs"` format, only supports `"target": "bun"` and dependent on a matching version of Bun. This adds a corresponding `.jsc` file for each entrypoint.
{% codetabs %}
```ts#JavaScript
await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
bytecode: true,
})
```
```bash#CLI
$ bun build ./index.tsx --outdir ./out --bytecode
```
{% /codetabs %}
### Executables
Bun supports "compiling" a JavaScript/TypeScript entrypoint into a standalone executable. This executable contains a copy of the Bun binary.

View File

@@ -154,8 +154,14 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
---
- `--banner`
- n/a
- Not supported
- `--banner`
- Only applies to js bundles
---
- `--footer`
- `--footer`
- Only applies to js bundles
---
@@ -184,8 +190,7 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
---
- `--drop`
- n/a
- Not supported
- `--drop`
---
@@ -195,12 +200,6 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
---
- `--footer`
- n/a
- Not supported
---
- `--global-name`
- n/a
- Not applicable, Bun does not support `iife` output at this time

View File

@@ -1,5 +1,22 @@
The `bun pm` command group provides a set of utilities for working with Bun's package manager.
## pack
To create a tarball of the current workspace:
```bash
$ bun pm pack
```
Options for the `pack` command:
- `--dry-run`: Perform all tasks except writing the tarball to disk.
- `--destination`: Specify the directory where the tarball will be saved.
- `--ignore-scripts`: Skip running pre/postpack and prepare scripts.
- `--gzip-level`: Set a custom compression level for gzip, ranging from 0 to 9 (default is 9).
## bin
To print the path to the `bin` directory for the local project:
```bash
@@ -14,6 +31,8 @@ $ bun pm bin -g
<$HOME>/.bun/bin
```
## ls
To print a list of installed dependencies in the current project and their resolved versions, excluding their dependencies.
```bash
@@ -45,6 +64,36 @@ $ bun pm ls --all
├── ...
```
## whoami
Print your npm username. Requires you to be logged in (`bunx npm login`) with credentials in either `bunfig.toml` or `.npmrc`:
```bash
$ bun pm whoami
```
## hash
To generate and print the hash of the current lockfile:
```bash
$ bun pm hash
```
To print the string used to hash the lockfile:
```bash
$ bun pm hash-string
```
To print the hash stored in the current lockfile:
```bash
$ bun pm hash-print
```
## cache
To print the path to Bun's global module cache:
```bash
@@ -57,16 +106,45 @@ To clear Bun's global module cache:
$ bun pm cache rm
```
## List global installs
## migrate
To list all globally installed packages:
To migrate another package manager's lockfile without installing anything:
```bash
$ bun pm ls -g
$ bun pm migrate
```
To list all globally installed packages, including nth-order dependencies:
## untrusted
To print current untrusted dependencies with scripts:
```bash
$ bun pm ls -g --all
$ bun pm untrusted
./node_modules/@biomejs/biome @1.8.3
» [postinstall]: node scripts/postinstall.js
These dependencies had their lifecycle scripts blocked during install.
```
## trust
To run scripts for untrusted dependencies and add to `trustedDependencies`:
```bash
$ bun pm trust <names>
```
Options for the `trust` command:
- `--all`: Trust all untrusted dependencies.
## default-trusted
To print the default trusted dependencies list:
```bash
$ bun pm default-trusted
```
see the current list on GitHub [here](https://github.com/oven-sh/bun/blob/main/src/install/default-trusted-dependencies.txt)

107
docs/cli/publish.md Normal file
View File

@@ -0,0 +1,107 @@
Use `bun publish` to publish a package to the npm registry.
`bun publish` will automatically pack your package into a tarball, strip workspace protocols from the `package.json` (resolving versions if necessary), and publish to the registry specified in your configuration files. Both `bunfig.toml` and `.npmrc` files are supported.
```sh
## Publishing the package from the current working directory
$ bun publish
## Output
bun publish v1.1.30 (ca7428e9)
packed 203B package.json
packed 224B README.md
packed 30B index.ts
packed 0.64KB tsconfig.json
Total files: 4
Shasum: 79e2b4377b63f4de38dc7ea6e5e9dbee08311a69
Integrity: sha512-6QSNlDdSwyG/+[...]X6wXHriDWr6fA==
Unpacked size: 1.1KB
Packed size: 0.76KB
Tag: latest
Access: default
Registry: http://localhost:4873/
+ publish-1@1.0.0
```
Alternatively, you can pack and publish your package separately by using `bun pm pack` followed by `bun publish` with the path to the output tarball.
```sh
$ bun pm pack
...
$ bun publish ./package.tgz
```
{% callout %}
**Note** - `bun publish` will not run lifecycle scripts (`prepublishOnly/prepack/prepare/postpack/publish/postpublish`) if a tarball path is provided. Scripts will only be run if the package is packed by `bun publish`.
{% /callout %}
### `--access`
The `--access` flag can be used to set the access level of the package being published. The access level can be one of `public` or `restricted`. Unscoped packages are always public, and attempting to publish an unscoped package with `--access restricted` will result in an error.
```sh
$ bun publish --access public
```
`--access` can also be set in the `publishConfig` field of your `package.json`.
```json
{
"publishConfig": {
"access": "restricted"
}
}
```
### `--tag`
Set the tag of the package version being published. By default, the tag is `latest`. The initial version of a package is always given the `latest` tag in addition to the specified tag.
```sh
$ bun publish --tag alpha
```
`--tag` can also be set in the `publishConfig` field of your `package.json`.
```json
{
"publishConfig": {
"tag": "next"
}
}
```
### `--dry-run`
The `--dry-run` flag can be used to simulate the publish process without actually publishing the package. This is useful for verifying the contents of the published package without actually publishing the package.
```sh
$ bun publish --dry-run
```
### `--auth-type`
If you have 2FA enabled for your npm account, `bun publish` will prompt you for a one-time password. This can be done through a browser or the CLI. The `--auth-type` flag can be used to tell the npm registry which method you prefer. The possible values are `web` and `legacy`, with `web` being the default.
```sh
$ bun publish --auth-type legacy
...
This operation requires a one-time password.
Enter OTP: 123456
...
```
### `--otp`
Provide a one-time password directly to the CLI. If the password is valid, this will skip the extra prompt for a one-time password before publishing. Example usage:
```sh
$ bun publish --otp 123456
```
### `--gzip-level`
Specify the level of gzip compression to use when packing the package. Only applies to `bun publish` without a tarball path argument. Values range from `0` to `9` (default is `9`).

View File

@@ -2,12 +2,6 @@
name: Build an app with Next.js and Bun
---
{% callout %}
The Next.js [App Router](https://nextjs.org/docs/app) currently relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
{% /callout %}
---
Initialize a Next.js app with `create-next-app`. This automatically installs dependencies using `npm`.
```sh

View File

@@ -17,7 +17,7 @@ If you are seeing one of the following errors, you are probably trying to use a
---
To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
To allow Bun to execute lifecycle scripts for a specific package, add the package to `trustedDependencies` in your package.json file. You can do this automatically by running the command `bun pm trust <pkg>`.
{% callout %}
Note that this only allows lifecycle scripts for the specific package listed in `trustedDependencies`, _not_ the dependencies of that dependency!

View File

@@ -27,16 +27,6 @@ data.version; // => "1.0.0"
data.author.name; // => "John Dough"
```
Bun also supports [Import Attributes](https://github.com/tc39/proposal-import-attributes/) and [JSON modules](https://github.com/tc39/proposal-json-modules) syntax.
```ts
import data from "./package.json" with { type: "json" };
data.name; // => "bun"
data.version; // => "1.0.0"
data.author.name; // => "John Dough"
```
---
Bun also supports [Import Attributes](https://github.com/tc39/proposal-import-attributes/) and [JSON modules](https://github.com/tc39/proposal-json-modules) syntax.

View File

@@ -16,7 +16,7 @@ Add the following to your local or global `.gitattributes` file:
*.lockb binary diff=lockb
```
Then add the following to you local git config with:
Then add the following to your local git config with:
```sh
$ git config diff.lockb.textconv bun

View File

@@ -41,7 +41,7 @@ In the root `package.json`, the `"workspaces"` key is used to indicate which sub
**Glob support** — Bun supports full glob syntax in `"workspaces"` (see [here](https://bun.sh/docs/api/glob#supported-glob-patterns) for a comprehensive list of supported syntax), _except_ for exclusions (e.g. `!**/excluded/**`), which are not implemented yet.
{% /callout %}
Each workspace has it's own `package.json` When referencing other packages in the monorepo, use `"workspace:*"` as the version field in your `package.json`.
Each workspace has it's own `package.json`. When referencing other packages in the monorepo, semver or workspace protocols (e.g. `workspace:*`) can be used as the version field in your `package.json`.
```json
{
@@ -53,10 +53,6 @@ Each workspace has it's own `package.json` When referencing other packages in th
}
```
{% callout %}
**Version support** — Bun supports simple `workspace:*` versions in `"dependencies"`. Full version syntax (e.g. `workspace:^*`) is not yet supported.
{% /callout %}
Workspaces have a couple major benefits.
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency in `package.json`. If package `b` depends on `a`, `bun install` will install your local `packages/a` directory into `node_modules` instead of downloading it from the npm registry.

View File

@@ -72,8 +72,9 @@ There are also image variants for different operating systems.
```bash
$ docker pull oven/bun:debian
$ docker pull oven/bun:slim
$ docker pull oven/bun:alpine
$ docker pull oven/bun:distroless
# alpine not recommended until #918 is fixed
# $ docker pull oven/bun:alpine
```
## Checking installation

View File

@@ -164,6 +164,9 @@ export default {
page("cli/update", "`bun update`", {
description: "Update your project's dependencies.",
}),
page("cli/publish", "`bun publish`", {
description: "Publish your package to an npm registry.",
}),
page("cli/outdated", "`bun outdated`", {
description: "Check for outdated dependencies.",
}),

View File

@@ -370,6 +370,19 @@ myorg = { username = "myusername", password = "$npm_password", url = "https://re
myorg = { token = "$npm_token", url = "https://registry.myorg.com/" }
```
### `install.ca` and `install.cafile`
To configure a CA certificate, use `install.ca` or `install.cafile` to specify a path to a CA certificate file.
```toml
[install]
# The CA certificate as a string
ca = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
# A path to a CA certificate file. The file can contain multiple certificates.
cafile = "path/to/cafile"
```
### `install.cache`
To configure the cache behavior:

View File

@@ -238,6 +238,30 @@ If `exports` is not defined, Bun falls back to `"module"` (ESM imports only) the
}
```
### Custom conditions
The `--conditions` flag allows you to specify a list of conditions to use when resolving packages from package.json `"exports"`.
This flag is supported in both `bun build` and Bun's runtime.
```sh
# Use it with bun build:
$ bun build --conditions="react-server" --target=bun ./app/foo/route.js
# Use it with bun's runtime:
$ bun --conditions="react-server" ./app/foo/route.js
```
You can also use `conditions` programmatically with `Bun.build`:
```js
await Bun.build({
conditions: ["react-server"],
target: "bun",
entryPoints: ["./app/foo/route.js"],
});
```
## Path re-mapping
In the spirit of treating TypeScript as a first-class citizen, the Bun runtime will re-map import paths according to the [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) field in `tsconfig.json`. This is a major divergence from Node.js, which doesn't support any form of import path re-mapping.

View File

@@ -76,6 +76,12 @@ test("wat", async () => {
}, 500); // test must run in <500ms
```
In `bun:test`, test timeouts throw an uncatchable exception to force the test to stop running and fail. We also kill any child processes that were spawned in the test to avoid leaving behind zombie processes lurking in the background.
### 🧟 Zombie process killer
When a test times out and processes spawned in the test via `Bun.spawn`, `Bun.spawnSync`, or `node:child_process` are not killed, they will be automatically killed and a message will be logged to the console.
## `test.skip`
Skip individual tests with `test.skip`. These tests will not be run.
@@ -324,6 +330,7 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
- [`.toContainAllValues()`](https://jest-extended.jestcommunity.dev/docs/matchers/Object#tocontainallvaluesvalues)
---
- ✅
- [`.toContainAnyValues()`](https://jest-extended.jestcommunity.dev/docs/matchers/Object#tocontainanyvaluesvalues)

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "bun",
"version": "1.1.30",
"version": "1.1.31",
"workspaces": [
"./packages/bun-types"
],
@@ -43,6 +43,7 @@
"build:release:local": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Release -DWEBKIT_LOCAL=ON -B build/release",
"build:release:with_logs": "cmake . -DCMAKE_BUILD_TYPE=Release -DENABLE_LOGS=true -GNinja -Bbuild-release && ninja -Cbuild-release",
"build:debug-zig-release": "cmake . -DCMAKE_BUILD_TYPE=Release -DZIG_OPTIMIZE=Debug -GNinja -Bbuild-debug-zig-release && ninja -Cbuild-debug-zig-release",
"css-properties": "bun run src/css/properties/generate_properties.ts",
"bump": "bun ./scripts/bump.ts",
"typecheck": "tsc --noEmit && cd test && bun run typecheck",
"fmt": "bun run prettier",
@@ -58,19 +59,20 @@
"zig:check": "bun run zig build check --summary new",
"zig:check-all": "bun run zig build check-all --summary new",
"zig:check-windows": "bun run zig build check-windows --summary new",
"cmake": "bun ./scripts/build.mjs -DCMAKE_BUILD_TYPE=Debug -B build/debug",
"clang-format": "bun run cmake --target clang-format",
"clang-format:check": "bun run cmake --target clang-format-check",
"clang-format:diff": "bun run cmake --target clang-format-diff",
"clang-tidy": "bun run cmake --target clang-tidy",
"clang-tidy:check": "bun run cmake --target clang-tidy-check",
"clang-tidy:diff": "bun run cmake --target clang-tidy-diff",
"zig-format": "bun run cmake --target zig-format",
"zig-format:check": "bun run cmake --target zig-format-check",
"zig-format:diff": "bun run cmake --target zig-format-diff",
"prettier": "bun run cmake -DENABLE_PRETTIER=ON --target prettier",
"prettier:check": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-check",
"prettier:extra": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-extra",
"prettier:diff": "bun run cmake -DENABLE_PRETTIER=ON --target prettier-diff"
"analysis": "bun ./scripts/build.mjs -DCMAKE_BUILD_TYPE=Debug -DENABLE_ANALYSIS=ON -DENABLE_CCACHE=OFF -B build/analysis",
"analysis:no-llvm": "bun run analysis -DENABLE_LLVM=OFF",
"clang-format": "bun run analysis --target clang-format",
"clang-format:check": "bun run analysis --target clang-format-check",
"clang-format:diff": "bun run analysis --target clang-format-diff",
"clang-tidy": "bun run analysis --target clang-tidy",
"clang-tidy:check": "bun run analysis --target clang-tidy-check",
"clang-tidy:diff": "bun run analysis --target clang-tidy-diff",
"zig-format": "bun run analysis:no-llvm --target zig-format",
"zig-format:check": "bun run analysis:no-llvm --target zig-format-check",
"zig-format:diff": "bun run analysis:no-llvm --target zig-format-diff",
"prettier": "bun run analysis:no-llvm --target prettier",
"prettier:check": "bun run analysis:no-llvm --target prettier-check",
"prettier:extra": "bun run analysis:no-llvm --target prettier-extra",
"prettier:diff": "bun run analysis:no-llvm --target prettier-diff"
}
}

View File

@@ -1595,6 +1595,28 @@ declare module "bun" {
* @default false
*/
bytecode?: boolean;
/**
* Add a banner to the bundled code such as "use client";
*/
banner?: string;
/**
* Add a footer to the bundled code such as a comment block like
*
* `// made with bun!`
*/
footer?: string;
/**
* **Experimental**
*
* Enable CSS support.
*/
experimentalCss?: boolean;
/**
* Drop function calls to matching property accesses.
*/
drop?: string[];
}
namespace Password {
@@ -1628,7 +1650,7 @@ declare module "bun" {
* automatically run in a worker thread.
*
* The underlying implementation of these functions are provided by the Zig
* Standard Library. Thanks to @jedisct1 and other Zig constributors for their
* Standard Library. Thanks to @jedisct1 and other Zig contributors for their
* work on this.
*
* ### Example with argon2
@@ -1731,7 +1753,7 @@ declare module "bun" {
* instead which runs in a worker thread.
*
* The underlying implementation of these functions are provided by the Zig
* Standard Library. Thanks to @jedisct1 and other Zig constributors for their
* Standard Library. Thanks to @jedisct1 and other Zig contributors for their
* work on this.
*
* ### Example with argon2
@@ -1770,7 +1792,7 @@ declare module "bun" {
* instead which runs in a worker thread.
*
* The underlying implementation of these functions are provided by the Zig
* Standard Library. Thanks to @jedisct1 and other Zig constributors for their
* Standard Library. Thanks to @jedisct1 and other Zig contributors for their
* work on this.
*
* ### Example with argon2
@@ -3001,6 +3023,7 @@ declare module "bun" {
colors?: boolean;
depth?: number;
sorted?: boolean;
compact?: boolean;
}
/**
@@ -3016,6 +3039,14 @@ declare module "bun" {
* That can be used to declare custom inspect functions.
*/
const custom: typeof import("util").inspect.custom;
/**
* Pretty-print an object or array as a table
*
* Like {@link console.table}, except it returns a string
*/
function table(tabularData: object | unknown[], properties?: string[], options?: { colors?: boolean }): string;
function table(tabularData: object | unknown[], options?: { colors?: boolean }): string;
}
interface MMapOptions {
@@ -3944,7 +3975,7 @@ declare module "bun" {
*
* In a future version of Bun, this will be used in error messages.
*/
name?: string;
name: string;
/**
* The target JavaScript environment the plugin should be applied to.
@@ -4417,15 +4448,18 @@ declare module "bun" {
hostname: string;
port: number;
tls?: TLSOptions;
exclusive?: boolean;
}
interface TCPSocketConnectOptions<Data = undefined> extends SocketOptions<Data> {
hostname: string;
port: number;
tls?: boolean;
exclusive?: boolean;
}
interface UnixSocketOptions<Data = undefined> extends SocketOptions<Data> {
tls?: TLSOptions;
unix: string;
}
@@ -5260,6 +5294,12 @@ declare module "bun" {
*/
const version: string;
/**
* The current version of Bun with the shortened commit sha of the build
* @example "v1.1.30 (d09df1af)"
*/
const version_with_sha: string;
/**
* The git sha at the time the currently-running version of Bun was compiled
* @example

View File

@@ -1838,14 +1838,6 @@ declare global {
withCredentials?: boolean;
}
interface EventSource extends Bun.EventSource {}
var EventSource: typeof globalThis extends {
onerror: any;
EventSource: infer T;
}
? T
: EventSource;
interface PromiseConstructor {
/**
* Create a deferred promise, with exposed `resolve` and `reject` methods which can be called

View File

@@ -579,6 +579,15 @@ declare module "bun:sqlite" {
*/
get(...params: ParamsType): ReturnType | null;
/**
* Execute the prepared statement and return an
*
* @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none.
*
*/
iterate(...params: ParamsType): IterableIterator<ReturnType>;
[Symbol.iterator](): IterableIterator<ReturnType>;
/**
* Execute the prepared statement. This returns `undefined`.
*

View File

@@ -208,10 +208,6 @@ const writableStream = new WritableStream();
const a = new ResolveError();
a.level;
}
{
const a = new EventSource("asdf");
a.CLOSED;
}
{
const a = new AbortController();
a;

View File

@@ -3645,7 +3645,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\006\040\006\005\026\160\002
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
@@ -7252,7 +7252,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\010\136\303\267\246\103\177\244\340
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
@@ -17020,8 +17020,14 @@ CKA_VALUE MULTILINE_OCTAL
\155\015\277\173\327\222
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# For Server Distrust After: Sun Jun 30 00:00:00 2024
CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL
\062\064\060\066\063\060\060\060\060\060\060\060\132
END
# For Email Distrust After: Sun Jun 30 00:00:00 2024
CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL
\062\064\060\066\063\060\060\060\060\060\060\060\132
END
# Trust for "GLOBALTRUST 2020"
# Issuer: CN=GLOBALTRUST 2020,O=e-commerce monitoring GmbH,C=AT
@@ -25483,3 +25489,761 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "TWCA CYBER Root CA"
#
# Issuer: CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
# Serial Number:40:01:34:8c:c2:00:00:00:00:00:00:00:01:3c:f2:c6
# Subject: CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
# Not Valid Before: Tue Nov 22 06:54:29 2022
# Not Valid After : Fri Nov 22 15:59:59 2047
# Fingerprint (SHA-256): 3F:63:BB:28:14:BE:17:4E:C8:B6:43:9C:F0:8D:6D:56:F0:B7:C4:05:88:3A:56:48:A3:34:42:4D:6B:3E:C5:58
# Fingerprint (SHA1): F6:B1:1C:1A:83:38:E9:7B:DB:B3:A8:C8:33:24:E0:2D:9C:7F:26:66
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "TWCA CYBER Root CA"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\120\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\033\060\031\006\003\125\004\003\023\022
\124\127\103\101\040\103\131\102\105\122\040\122\157\157\164\040
\103\101
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\120\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\033\060\031\006\003\125\004\003\023\022
\124\127\103\101\040\103\131\102\105\122\040\122\157\157\164\040
\103\101
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\100\001\064\214\302\000\000\000\000\000\000\000\001\074
\362\306
END
CKA_VALUE MULTILINE_OCTAL
\060\202\005\215\060\202\003\165\240\003\002\001\002\002\020\100
\001\064\214\302\000\000\000\000\000\000\000\001\074\362\306\060
\015\006\011\052\206\110\206\367\015\001\001\014\005\000\060\120
\061\013\060\011\006\003\125\004\006\023\002\124\127\061\022\060
\020\006\003\125\004\012\023\011\124\101\111\127\101\116\055\103
\101\061\020\060\016\006\003\125\004\013\023\007\122\157\157\164
\040\103\101\061\033\060\031\006\003\125\004\003\023\022\124\127
\103\101\040\103\131\102\105\122\040\122\157\157\164\040\103\101
\060\036\027\015\062\062\061\061\062\062\060\066\065\064\062\071
\132\027\015\064\067\061\061\062\062\061\065\065\071\065\071\132
\060\120\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\033\060\031\006\003\125\004\003\023\022
\124\127\103\101\040\103\131\102\105\122\040\122\157\157\164\040
\103\101\060\202\002\042\060\015\006\011\052\206\110\206\367\015
\001\001\001\005\000\003\202\002\017\000\060\202\002\012\002\202
\002\001\000\306\370\312\036\331\011\040\176\035\154\116\316\217
\343\107\063\104\234\307\311\151\252\072\133\170\356\160\322\222
\370\004\263\122\122\035\147\162\050\241\337\213\135\225\012\376
\352\315\355\367\051\316\360\157\177\254\315\075\357\263\034\105
\152\367\050\220\361\141\127\305\014\304\243\120\135\336\324\265
\313\031\312\200\271\165\316\051\316\322\205\042\354\002\143\314
\104\060\040\332\352\221\133\126\346\035\034\325\235\146\307\077
\337\206\312\113\123\304\331\215\262\035\352\370\334\047\123\243
\107\341\141\314\175\265\260\370\356\163\221\305\316\163\157\316
\356\020\037\032\006\317\351\047\140\305\117\031\344\353\316\042
\046\105\327\140\231\335\316\117\067\340\177\347\143\255\260\270
\131\270\320\006\150\065\140\323\066\256\161\103\004\361\151\145
\170\174\363\037\363\312\050\237\132\040\225\146\264\315\267\356
\217\170\244\105\030\351\046\057\215\233\051\050\261\244\267\072
\155\271\324\034\070\162\105\130\261\136\353\360\050\233\267\202
\312\375\317\326\063\017\237\373\227\236\261\034\234\236\352\137
\136\333\252\335\124\351\060\041\050\155\216\171\363\165\222\214
\046\376\334\305\366\303\260\337\104\131\103\243\266\003\050\366
\010\060\252\015\063\341\357\234\251\007\042\343\131\133\100\217
\332\210\267\151\010\250\267\043\056\104\011\131\067\133\307\343
\027\362\042\353\156\071\122\305\336\124\247\230\311\113\040\225
\334\106\211\137\264\022\371\205\051\216\353\310\047\025\040\300
\113\324\314\174\014\154\064\014\046\233\046\061\246\074\247\366
\331\320\113\242\144\377\073\231\101\162\301\340\160\227\361\044
\273\053\304\164\042\261\254\153\042\062\044\323\170\052\300\300
\241\057\361\122\005\311\077\357\166\146\342\105\330\015\075\255
\225\310\307\211\046\310\017\256\247\003\056\373\301\137\372\040
\341\160\255\260\145\040\067\063\140\260\325\257\327\014\034\302
\220\160\327\112\030\274\176\001\260\260\353\025\036\104\006\315
\244\117\350\014\321\303\040\020\341\124\145\236\266\121\320\032
\166\153\102\132\130\166\064\352\267\067\031\256\056\165\371\226
\345\301\131\367\224\127\051\045\215\072\114\253\115\232\101\320
\137\046\003\002\003\001\000\001\243\143\060\141\060\016\006\003
\125\035\017\001\001\377\004\004\003\002\001\006\060\017\006\003
\125\035\023\001\001\377\004\005\060\003\001\001\377\060\037\006
\003\125\035\043\004\030\060\026\200\024\235\205\141\024\174\301
\142\157\227\150\344\117\067\100\341\255\340\015\126\067\060\035
\006\003\125\035\016\004\026\004\024\235\205\141\024\174\301\142
\157\227\150\344\117\067\100\341\255\340\015\126\067\060\015\006
\011\052\206\110\206\367\015\001\001\014\005\000\003\202\002\001
\000\144\217\172\304\142\016\265\210\314\270\307\206\016\241\112
\026\315\160\013\267\247\205\013\263\166\266\017\247\377\010\213
\013\045\317\250\324\203\165\052\270\226\210\266\373\337\055\055
\264\151\123\041\065\127\326\211\115\163\277\151\217\160\243\141
\314\232\333\036\232\340\040\370\154\273\233\042\235\135\204\061
\232\054\212\335\152\241\327\050\151\312\376\166\125\172\106\147
\353\314\103\210\026\242\003\326\271\027\370\031\154\155\043\002
\177\361\137\320\012\051\043\073\321\252\012\355\251\027\046\124
\012\115\302\245\115\370\305\375\270\201\317\053\054\170\243\147
\114\251\007\232\363\337\136\373\174\365\211\315\164\227\141\020
\152\007\053\201\132\322\216\267\347\040\321\040\156\044\250\204
\047\241\127\254\252\125\130\057\334\331\312\372\150\004\236\355
\104\044\371\164\100\073\043\063\253\203\132\030\046\102\266\155
\124\265\026\140\060\154\261\240\370\270\101\240\135\111\111\322
\145\005\072\352\376\235\141\274\206\331\277\336\323\272\072\261
\177\176\222\064\216\311\000\156\334\230\275\334\354\200\005\255
\002\075\337\145\355\013\003\367\367\026\204\004\061\272\223\224
\330\362\022\370\212\343\277\102\257\247\324\315\021\027\026\310
\102\035\024\250\102\366\322\100\206\240\117\043\312\226\105\126
\140\006\315\267\125\001\246\001\224\145\376\156\005\011\272\264
\244\252\342\357\130\276\275\047\126\330\357\163\161\133\104\063
\362\232\162\352\260\136\076\156\251\122\133\354\160\155\265\207
\217\067\136\074\214\234\316\344\360\316\014\147\101\314\316\366
\200\253\116\314\114\126\365\301\141\131\223\264\076\246\332\270
\067\022\237\052\062\343\213\270\041\354\303\053\145\014\357\042
\336\210\051\073\114\327\372\376\267\341\107\276\234\076\076\203
\373\121\135\365\150\367\056\041\205\334\277\361\132\342\174\327
\305\344\203\301\152\353\272\200\132\336\134\055\160\166\370\310
\345\207\207\312\240\235\241\345\042\022\047\017\104\075\035\154
\352\324\302\213\057\157\171\253\177\120\246\304\031\247\241\172
\267\226\371\301\037\142\132\242\103\007\100\136\046\306\254\355
\256\160\026\305\252\312\162\212\115\260\317\001\213\003\077\156
\327
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "TWCA CYBER Root CA"
# Issuer: CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
# Serial Number:40:01:34:8c:c2:00:00:00:00:00:00:00:01:3c:f2:c6
# Subject: CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
# Not Valid Before: Tue Nov 22 06:54:29 2022
# Not Valid After : Fri Nov 22 15:59:59 2047
# Fingerprint (SHA-256): 3F:63:BB:28:14:BE:17:4E:C8:B6:43:9C:F0:8D:6D:56:F0:B7:C4:05:88:3A:56:48:A3:34:42:4D:6B:3E:C5:58
# Fingerprint (SHA1): F6:B1:1C:1A:83:38:E9:7B:DB:B3:A8:C8:33:24:E0:2D:9C:7F:26:66
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "TWCA CYBER Root CA"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\366\261\034\032\203\070\351\173\333\263\250\310\063\044\340\055
\234\177\046\146
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\013\063\240\227\122\225\324\251\375\273\333\156\243\125\133\121
END
CKA_ISSUER MULTILINE_OCTAL
\060\120\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\033\060\031\006\003\125\004\003\023\022
\124\127\103\101\040\103\131\102\105\122\040\122\157\157\164\040
\103\101
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\100\001\064\214\302\000\000\000\000\000\000\000\001\074
\362\306
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "TWCA Global Root CA G2"
#
# Issuer: CN=TWCA Global Root CA G2,OU=Root CA,O=TAIWAN-CA,C=TW
# Serial Number:40:01:34:8c:c2:00:00:00:00:00:00:00:01:97:58:f4
# Subject: CN=TWCA Global Root CA G2,OU=Root CA,O=TAIWAN-CA,C=TW
# Not Valid Before: Tue Nov 22 06:42:21 2022
# Not Valid After : Fri Nov 22 15:59:59 2047
# Fingerprint (SHA-256): 3A:00:72:D4:9F:FC:04:E9:96:C5:9A:EB:75:99:1D:3C:34:0F:36:15:D6:FD:4D:CE:90:AC:0B:3D:88:EA:D4:F4
# Fingerprint (SHA1): 73:FE:92:2F:83:63:91:FF:C8:C6:C4:DA:D6:20:2F:6B:07:2E:7F:1B
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "TWCA Global Root CA G2"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\124\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\037\060\035\006\003\125\004\003\023\026
\124\127\103\101\040\107\154\157\142\141\154\040\122\157\157\164
\040\103\101\040\107\062
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\124\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\037\060\035\006\003\125\004\003\023\026
\124\127\103\101\040\107\154\157\142\141\154\040\122\157\157\164
\040\103\101\040\107\062
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\100\001\064\214\302\000\000\000\000\000\000\000\001\227
\130\364
END
CKA_VALUE MULTILINE_OCTAL
\060\202\005\225\060\202\003\175\240\003\002\001\002\002\020\100
\001\064\214\302\000\000\000\000\000\000\000\001\227\130\364\060
\015\006\011\052\206\110\206\367\015\001\001\014\005\000\060\124
\061\013\060\011\006\003\125\004\006\023\002\124\127\061\022\060
\020\006\003\125\004\012\023\011\124\101\111\127\101\116\055\103
\101\061\020\060\016\006\003\125\004\013\023\007\122\157\157\164
\040\103\101\061\037\060\035\006\003\125\004\003\023\026\124\127
\103\101\040\107\154\157\142\141\154\040\122\157\157\164\040\103
\101\040\107\062\060\036\027\015\062\062\061\061\062\062\060\066
\064\062\062\061\132\027\015\064\067\061\061\062\062\061\065\065
\071\065\071\132\060\124\061\013\060\011\006\003\125\004\006\023
\002\124\127\061\022\060\020\006\003\125\004\012\023\011\124\101
\111\127\101\116\055\103\101\061\020\060\016\006\003\125\004\013
\023\007\122\157\157\164\040\103\101\061\037\060\035\006\003\125
\004\003\023\026\124\127\103\101\040\107\154\157\142\141\154\040
\122\157\157\164\040\103\101\040\107\062\060\202\002\042\060\015
\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\002
\017\000\060\202\002\012\002\202\002\001\000\252\016\325\040\222
\001\255\202\371\014\010\221\064\153\212\026\320\106\026\377\003
\270\330\215\352\223\064\373\377\053\275\375\156\252\334\233\362
\206\201\125\365\211\034\304\215\165\152\130\170\221\023\036\002
\023\160\075\357\276\012\347\000\217\270\061\345\164\305\060\276
\377\175\326\231\345\302\102\243\317\041\326\263\010\177\221\325
\141\346\242\225\020\015\357\136\227\013\111\070\325\042\260\327
\213\131\157\237\065\233\177\322\221\314\172\177\273\240\237\336
\125\063\366\113\215\012\352\175\011\300\171\334\275\104\342\376
\034\347\144\041\050\317\004\112\342\264\277\206\171\052\273\016
\223\311\217\136\254\060\071\122\220\007\271\352\234\046\102\024
\304\147\106\376\321\032\150\241\076\120\031\243\046\012\047\051
\220\302\366\264\353\163\232\170\036\341\230\364\145\014\065\041
\006\370\013\336\142\345\115\301\263\135\331\271\372\141\227\052
\343\352\307\104\125\044\222\376\022\247\077\304\167\340\055\002
\201\007\325\373\175\346\020\236\072\264\250\357\354\373\120\352
\065\317\314\176\273\102\271\104\154\122\351\277\052\162\037\077
\336\233\160\351\334\132\305\073\273\277\360\131\205\257\057\301
\260\024\171\005\254\165\237\045\365\021\047\006\140\041\307\155
\145\276\250\211\234\345\254\106\337\370\135\104\003\215\140\275
\367\261\015\314\057\357\101\124\057\356\153\225\271\116\174\064
\337\073\371\167\235\175\315\007\075\034\006\063\022\200\354\162
\234\362\055\202\332\325\073\304\307\371\004\303\144\002\174\365
\065\140\247\264\106\051\056\033\357\245\130\200\056\172\211\121
\070\066\074\375\241\167\270\200\060\320\212\336\215\247\064\046
\354\043\273\030\125\030\066\105\356\355\001\006\252\115\277\144
\014\312\230\227\032\061\002\146\370\170\150\133\210\337\011\250
\347\233\372\064\155\160\034\041\255\010\213\362\241\266\254\166
\152\277\361\200\045\000\276\074\036\115\256\271\074\266\225\143
\275\153\176\107\022\220\125\105\021\215\354\027\037\301\276\047
\201\223\127\143\151\000\046\167\213\303\131\345\173\321\015\104
\362\250\360\367\205\232\005\367\302\056\160\232\223\205\330\225
\220\061\220\124\246\354\013\237\067\105\017\002\003\001\000\001
\243\143\060\141\060\016\006\003\125\035\017\001\001\377\004\004
\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005
\060\003\001\001\377\060\037\006\003\125\035\043\004\030\060\026
\200\024\222\214\324\066\321\133\107\123\304\161\015\204\335\144
\052\365\066\144\100\347\060\035\006\003\125\035\016\004\026\004
\024\222\214\324\066\321\133\107\123\304\161\015\204\335\144\052
\365\066\144\100\347\060\015\006\011\052\206\110\206\367\015\001
\001\014\005\000\003\202\002\001\000\045\374\113\332\220\264\332
\165\347\101\072\201\321\246\376\240\152\363\030\161\142\152\044
\010\213\251\172\115\311\125\316\317\020\050\056\004\031\226\005
\317\135\002\040\052\073\263\125\077\001\315\102\315\262\167\355
\377\165\363\174\167\333\226\245\317\214\147\006\364\244\233\162
\366\041\111\011\230\243\062\136\167\132\143\011\357\142\103\227
\002\070\265\352\074\030\120\150\374\131\133\331\171\324\361\344
\126\110\023\126\330\323\161\013\136\170\224\070\021\105\372\005
\027\365\016\165\036\142\122\141\106\272\056\031\255\206\264\210
\017\261\120\346\100\000\064\032\225\235\223\340\121\371\324\125
\106\351\225\074\045\206\056\227\327\001\061\030\104\354\034\140
\351\175\151\257\062\370\227\100\045\044\266\215\032\125\074\305
\267\367\274\006\122\073\161\060\160\076\161\027\176\361\146\004
\136\135\274\212\061\103\246\222\035\173\124\322\245\066\213\157
\215\326\136\332\324\303\056\035\337\071\125\140\202\060\236\047
\377\216\200\335\143\114\246\125\065\330\320\063\251\200\155\076
\136\235\314\250\147\200\146\372\231\127\014\122\312\031\165\260
\070\065\125\052\201\305\214\036\126\327\137\220\362\040\330\332
\340\146\161\351\262\170\253\147\271\044\156\153\066\162\374\157
\215\375\177\162\071\050\147\122\221\005\037\127\145\322\243\247
\015\141\372\241\347\325\065\106\225\311\006\207\366\060\354\062
\121\251\254\126\300\041\116\243\024\164\005\072\274\343\277\155
\075\116\077\136\245\244\155\051\277\204\121\165\123\216\206\032
\365\121\160\052\015\034\116\100\341\375\243\343\245\053\147\220
\222\307\154\256\205\277\072\233\027\025\312\234\052\223\324\115
\071\015\274\040\010\243\215\210\154\011\015\214\256\104\041\115
\311\161\354\330\046\327\027\236\055\021\030\074\243\042\175\270
\047\124\277\150\310\073\102\314\217\136\116\347\334\302\305\372
\152\104\017\215\126\210\172\337\211\204\154\240\263\076\075\361
\145\000\011\210\352\052\353\100\316\263\135\254\062\027\256\301
\233\351\320\301\365\111\224\335\247\316\174\132\007\353\256\040
\234\027\060\222\151\223\162\363\232\133\161\233\376\152\337\172
\060\151\216\263\056\333\017\054\335
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "TWCA Global Root CA G2"
# Issuer: CN=TWCA Global Root CA G2,OU=Root CA,O=TAIWAN-CA,C=TW
# Serial Number:40:01:34:8c:c2:00:00:00:00:00:00:00:01:97:58:f4
# Subject: CN=TWCA Global Root CA G2,OU=Root CA,O=TAIWAN-CA,C=TW
# Not Valid Before: Tue Nov 22 06:42:21 2022
# Not Valid After : Fri Nov 22 15:59:59 2047
# Fingerprint (SHA-256): 3A:00:72:D4:9F:FC:04:E9:96:C5:9A:EB:75:99:1D:3C:34:0F:36:15:D6:FD:4D:CE:90:AC:0B:3D:88:EA:D4:F4
# Fingerprint (SHA1): 73:FE:92:2F:83:63:91:FF:C8:C6:C4:DA:D6:20:2F:6B:07:2E:7F:1B
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "TWCA Global Root CA G2"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\163\376\222\057\203\143\221\377\310\306\304\332\326\040\057\153
\007\056\177\033
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\023\215\135\372\031\265\346\253\144\173\020\164\160\032\043\056
END
CKA_ISSUER MULTILINE_OCTAL
\060\124\061\013\060\011\006\003\125\004\006\023\002\124\127\061
\022\060\020\006\003\125\004\012\023\011\124\101\111\127\101\116
\055\103\101\061\020\060\016\006\003\125\004\013\023\007\122\157
\157\164\040\103\101\061\037\060\035\006\003\125\004\003\023\026
\124\127\103\101\040\107\154\157\142\141\154\040\122\157\157\164
\040\103\101\040\107\062
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\020\100\001\064\214\302\000\000\000\000\000\000\000\001\227
\130\364
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "SecureSign Root CA12"
#
# Issuer: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:66:f9:c7:c1:af:ec:c2:51:b4:ed:53:97:e6:e6:82:c3:2b:1c:90:16
# Subject: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 05:36:46 2020
# Not Valid After : Sun Apr 08 05:36:46 2040
# Fingerprint (SHA-256): 3F:03:4B:B5:70:4D:44:B2:D0:85:45:A0:20:57:DE:93:EB:F3:90:5F:CE:72:1A:CB:C7:30:C0:6D:DA:EE:90:4E
# Fingerprint (SHA1): 7A:22:1E:3D:DE:1B:06:AC:9E:C8:47:70:16:8E:3C:E5:F7:6B:06:F4
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA12"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\062
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\062
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\146\371\307\301\257\354\302\121\264\355\123\227\346\346
\202\303\053\034\220\026
END
CKA_VALUE MULTILINE_OCTAL
\060\202\003\162\060\202\002\132\240\003\002\001\002\002\024\146
\371\307\301\257\354\302\121\264\355\123\227\346\346\202\303\053
\034\220\026\060\015\006\011\052\206\110\206\367\015\001\001\013
\005\000\060\121\061\013\060\011\006\003\125\004\006\023\002\112
\120\061\043\060\041\006\003\125\004\012\023\032\103\171\142\145
\162\164\162\165\163\164\040\112\141\160\141\156\040\103\157\056
\054\040\114\164\144\056\061\035\060\033\006\003\125\004\003\023
\024\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164
\040\103\101\061\062\060\036\027\015\062\060\060\064\060\070\060
\065\063\066\064\066\132\027\015\064\060\060\064\060\070\060\065
\063\066\064\066\132\060\121\061\013\060\011\006\003\125\004\006
\023\002\112\120\061\043\060\041\006\003\125\004\012\023\032\103
\171\142\145\162\164\162\165\163\164\040\112\141\160\141\156\040
\103\157\056\054\040\114\164\144\056\061\035\060\033\006\003\125
\004\003\023\024\123\145\143\165\162\145\123\151\147\156\040\122
\157\157\164\040\103\101\061\062\060\202\001\042\060\015\006\011
\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017\000
\060\202\001\012\002\202\001\001\000\272\071\301\067\172\150\105
\053\024\264\353\344\023\353\127\165\043\115\217\044\055\026\350
\256\216\311\175\244\127\073\052\166\045\063\203\154\352\062\212
\224\233\116\074\226\344\375\121\277\231\311\223\176\277\371\255
\247\262\110\053\007\034\047\365\114\274\160\022\167\244\205\124
\265\375\220\172\344\243\344\121\130\003\315\020\171\171\356\153
\223\037\144\216\153\144\253\243\023\343\161\376\175\253\234\335
\047\123\067\263\252\030\302\131\046\354\133\037\322\346\145\174
\357\223\275\330\130\134\013\300\343\145\157\074\307\312\131\343
\376\156\137\254\203\276\375\135\045\116\052\051\073\326\013\253
\027\062\170\244\341\076\224\106\276\142\156\233\336\106\250\261
\026\347\205\156\364\010\100\105\021\240\236\124\104\204\367\330
\066\316\365\120\107\334\054\060\233\356\300\365\226\322\376\011
\206\307\006\131\256\117\256\216\021\230\173\363\013\122\252\142
\046\252\041\337\216\045\063\171\227\026\111\215\365\076\325\107
\237\067\061\111\063\162\005\115\014\266\125\214\361\127\217\212
\207\321\255\305\021\022\071\240\255\002\003\001\000\001\243\102
\060\100\060\017\006\003\125\035\023\001\001\377\004\005\060\003
\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003
\002\001\006\060\035\006\003\125\035\016\004\026\004\024\127\064
\363\164\317\004\113\325\045\346\361\100\266\054\114\331\055\351
\240\255\060\015\006\011\052\206\110\206\367\015\001\001\013\005
\000\003\202\001\001\000\076\273\333\027\026\322\362\024\001\040
\054\070\203\113\255\276\312\205\172\232\266\233\153\246\341\374
\245\072\254\255\264\050\072\257\327\001\203\111\053\143\242\335
\232\144\016\230\134\157\335\216\273\212\124\042\055\112\023\363
\256\100\103\333\117\221\267\206\032\354\000\264\101\201\244\117
\372\152\213\210\263\166\010\162\052\111\100\303\323\303\205\211
\230\020\245\235\157\031\267\273\317\172\145\125\333\067\353\074
\212\162\062\227\036\232\051\076\255\215\346\243\033\155\365\165
\032\346\260\150\271\133\242\356\151\107\047\065\241\206\231\200
\363\063\113\341\153\244\046\303\357\164\131\154\172\242\144\266
\036\104\303\120\340\017\071\075\251\063\361\245\363\322\275\142
\204\254\216\034\251\315\132\275\067\073\156\012\042\264\364\025
\347\221\130\305\072\104\323\225\050\331\300\145\351\162\312\320
\017\275\037\263\025\331\251\343\244\107\011\236\340\313\067\373
\375\275\227\325\276\030\032\151\242\071\201\331\032\365\253\177
\310\343\342\147\013\235\364\014\352\124\337\322\262\257\261\042
\361\040\337\274\104\034
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "SecureSign Root CA12"
# Issuer: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:66:f9:c7:c1:af:ec:c2:51:b4:ed:53:97:e6:e6:82:c3:2b:1c:90:16
# Subject: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 05:36:46 2020
# Not Valid After : Sun Apr 08 05:36:46 2040
# Fingerprint (SHA-256): 3F:03:4B:B5:70:4D:44:B2:D0:85:45:A0:20:57:DE:93:EB:F3:90:5F:CE:72:1A:CB:C7:30:C0:6D:DA:EE:90:4E
# Fingerprint (SHA1): 7A:22:1E:3D:DE:1B:06:AC:9E:C8:47:70:16:8E:3C:E5:F7:6B:06:F4
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA12"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\172\042\036\075\336\033\006\254\236\310\107\160\026\216\074\345
\367\153\006\364
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\306\211\312\144\102\233\142\010\111\013\036\177\351\007\075\350
END
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\062
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\146\371\307\301\257\354\302\121\264\355\123\227\346\346
\202\303\053\034\220\026
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "SecureSign Root CA14"
#
# Issuer: CN=SecureSign Root CA14,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:64:db:5a:0c:20:4e:e8:d7:29:77:c8:50:27:a2:5a:27:dd:2d:f2:cb
# Subject: CN=SecureSign Root CA14,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 07:06:19 2020
# Not Valid After : Sat Apr 08 07:06:19 2045
# Fingerprint (SHA-256): 4B:00:9C:10:34:49:4F:9A:B5:6B:BA:3B:A1:D6:27:31:FC:4D:20:D8:95:5A:DC:EC:10:A9:25:60:72:61:E3:38
# Fingerprint (SHA1): DD:50:C0:F7:79:B3:64:2E:74:A2:B8:9D:9F:D3:40:DD:BB:F0:F2:4F
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA14"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\064
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\064
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\144\333\132\014\040\116\350\327\051\167\310\120\047\242
\132\047\335\055\362\313
END
CKA_VALUE MULTILINE_OCTAL
\060\202\005\162\060\202\003\132\240\003\002\001\002\002\024\144
\333\132\014\040\116\350\327\051\167\310\120\047\242\132\047\335
\055\362\313\060\015\006\011\052\206\110\206\367\015\001\001\014
\005\000\060\121\061\013\060\011\006\003\125\004\006\023\002\112
\120\061\043\060\041\006\003\125\004\012\023\032\103\171\142\145
\162\164\162\165\163\164\040\112\141\160\141\156\040\103\157\056
\054\040\114\164\144\056\061\035\060\033\006\003\125\004\003\023
\024\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164
\040\103\101\061\064\060\036\027\015\062\060\060\064\060\070\060
\067\060\066\061\071\132\027\015\064\065\060\064\060\070\060\067
\060\066\061\071\132\060\121\061\013\060\011\006\003\125\004\006
\023\002\112\120\061\043\060\041\006\003\125\004\012\023\032\103
\171\142\145\162\164\162\165\163\164\040\112\141\160\141\156\040
\103\157\056\054\040\114\164\144\056\061\035\060\033\006\003\125
\004\003\023\024\123\145\143\165\162\145\123\151\147\156\040\122
\157\157\164\040\103\101\061\064\060\202\002\042\060\015\006\011
\052\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000
\060\202\002\012\002\202\002\001\000\305\322\172\241\326\212\277
\026\061\320\230\321\072\224\374\132\270\156\042\301\142\367\247
\012\047\357\120\366\056\261\236\150\022\360\154\044\143\071\361
\360\337\020\306\336\267\122\040\325\122\133\102\231\236\363\240
\276\122\037\137\314\147\155\247\056\120\242\301\227\215\266\370
\225\365\260\272\334\235\340\276\313\337\367\070\362\107\365\246
\232\222\225\052\142\131\120\013\242\261\065\347\145\262\141\262
\352\222\161\151\344\051\360\117\201\201\004\074\262\245\133\324
\305\250\131\147\173\125\034\111\253\172\235\302\347\163\115\357
\315\011\302\304\127\022\333\001\016\043\171\011\007\073\242\350
\374\212\317\217\300\106\044\234\070\047\340\203\235\033\240\277
\170\025\020\353\206\116\012\132\375\337\332\054\202\176\356\312
\366\051\341\372\161\241\367\210\150\234\234\360\215\276\017\111
\221\330\352\072\371\375\320\150\161\333\351\265\053\116\202\222
\157\146\037\340\360\334\114\354\312\321\352\272\164\006\371\263
\204\220\224\321\137\216\163\031\020\135\002\345\160\245\300\020
\320\020\174\157\305\130\111\264\260\156\232\332\175\225\365\314
\332\002\257\270\054\175\171\217\276\103\361\371\050\050\215\011
\103\370\010\335\153\310\213\054\044\261\215\122\007\275\170\233
\313\312\150\262\244\335\014\114\171\140\306\231\321\223\361\060
\032\007\323\256\042\302\352\316\361\204\011\314\340\024\156\177
\077\176\322\202\205\254\334\251\026\116\205\240\140\313\366\234
\327\310\263\216\355\306\233\230\165\015\125\350\137\345\225\213
\002\244\256\103\051\050\021\244\346\022\060\001\113\165\153\036
\146\235\171\057\245\166\057\035\100\264\155\311\175\171\010\354
\321\152\266\135\052\262\245\146\275\153\205\364\164\126\303\365
\347\165\122\050\054\245\377\146\107\245\324\376\376\236\124\277
\145\176\001\326\060\217\245\066\234\242\120\034\356\070\200\001
\110\306\307\164\364\306\254\303\100\111\026\141\164\054\257\214
\157\065\355\173\030\000\133\066\074\234\120\015\312\222\063\020
\361\046\111\155\337\165\044\067\202\042\327\350\226\375\025\113
\002\226\076\007\162\225\176\253\075\114\056\327\312\360\337\340
\130\077\055\057\004\232\070\243\001\002\003\001\000\001\243\102
\060\100\060\017\006\003\125\035\023\001\001\377\004\005\060\003
\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003
\002\001\006\060\035\006\003\125\035\016\004\026\004\024\006\223
\243\012\136\050\151\067\252\141\035\353\353\374\055\157\043\344
\363\240\060\015\006\011\052\206\110\206\367\015\001\001\014\005
\000\003\202\002\001\000\226\200\162\011\006\176\234\314\223\004
\026\273\240\072\215\222\116\267\021\032\012\161\161\020\315\004
\255\177\245\105\120\020\146\116\112\101\242\003\331\021\117\172
\067\271\113\342\306\217\062\146\165\045\373\353\316\077\003\051
\046\215\270\026\035\366\037\063\156\110\346\350\370\127\262\033
\171\337\073\207\012\342\144\272\000\312\154\357\176\320\043\353
\170\217\377\144\233\064\067\237\065\145\242\244\000\075\022\043
\226\130\135\312\143\207\306\243\007\210\115\347\151\166\212\123
\315\361\117\354\102\362\223\343\231\244\067\074\207\270\142\333
\360\354\037\067\077\067\137\103\314\121\235\265\360\227\302\267
\205\152\150\013\104\036\345\121\356\223\316\113\156\206\301\322
\014\044\131\066\032\237\054\221\217\343\030\333\224\225\012\355
\221\252\016\231\334\226\123\343\141\203\306\026\272\043\272\334
\335\176\032\306\173\102\266\331\132\005\334\232\137\325\337\270
\332\107\175\332\070\333\254\071\325\036\153\154\052\027\214\141
\315\261\155\162\001\303\303\040\000\142\150\026\061\325\166\252
\206\273\016\252\236\306\371\360\331\370\015\041\002\344\305\050
\026\131\021\271\331\151\163\052\222\170\270\222\127\233\010\362
\072\345\057\225\260\130\267\153\040\024\155\024\357\012\274\176
\330\125\330\210\332\057\372\031\245\373\213\340\177\071\365\162
\053\205\304\054\254\357\031\105\222\114\263\141\007\334\115\037
\156\322\201\023\134\232\363\022\147\203\317\233\077\213\237\235
\244\271\250\226\003\172\305\356\040\336\063\332\057\236\032\172
\164\036\341\356\314\132\072\004\335\263\032\004\250\024\143\254
\267\107\022\203\232\154\365\346\351\025\025\221\032\204\031\016
\224\104\347\022\216\045\133\200\147\031\334\143\223\020\013\145
\056\212\372\011\232\116\332\206\050\175\252\141\065\330\016\247
\050\032\273\122\340\170\370\154\272\154\260\156\271\207\136\351
\231\065\067\361\075\144\053\251\240\064\223\317\143\057\325\201
\337\256\143\047\245\036\116\215\334\051\170\131\370\371\241\040
\214\247\046\100\156\202\162\315\170\262\310\217\074\036\163\347
\301\037\277\317\316\245\052\233\333\104\144\062\240\273\177\134
\045\023\110\265\177\222
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "SecureSign Root CA14"
# Issuer: CN=SecureSign Root CA14,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:64:db:5a:0c:20:4e:e8:d7:29:77:c8:50:27:a2:5a:27:dd:2d:f2:cb
# Subject: CN=SecureSign Root CA14,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 07:06:19 2020
# Not Valid After : Sat Apr 08 07:06:19 2045
# Fingerprint (SHA-256): 4B:00:9C:10:34:49:4F:9A:B5:6B:BA:3B:A1:D6:27:31:FC:4D:20:D8:95:5A:DC:EC:10:A9:25:60:72:61:E3:38
# Fingerprint (SHA1): DD:50:C0:F7:79:B3:64:2E:74:A2:B8:9D:9F:D3:40:DD:BB:F0:F2:4F
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA14"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\335\120\300\367\171\263\144\056\164\242\270\235\237\323\100\335
\273\360\362\117
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\161\015\162\372\222\031\145\136\211\004\254\026\063\360\274\325
END
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\064
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\144\333\132\014\040\116\350\327\051\167\310\120\047\242
\132\047\335\055\362\313
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "SecureSign Root CA15"
#
# Issuer: CN=SecureSign Root CA15,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:16:15:c7:c3:d8:49:a7:be:69:0c:8a:88:ed:f0:70:f9:dd:b7:3e:87
# Subject: CN=SecureSign Root CA15,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 08:32:56 2020
# Not Valid After : Sat Apr 08 08:32:56 2045
# Fingerprint (SHA-256): E7:78:F0:F0:95:FE:84:37:29:CD:1A:00:82:17:9E:53:14:A9:C2:91:44:28:05:E1:FB:1D:8F:B6:B8:88:6C:3A
# Fingerprint (SHA1): CB:BA:83:C8:C1:5A:5D:F1:F9:73:6F:CA:D7:EF:28:13:06:4A:07:7D
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA15"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\065
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\065
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\026\025\307\303\330\111\247\276\151\014\212\210\355\360
\160\371\335\267\076\207
END
CKA_VALUE MULTILINE_OCTAL
\060\202\002\043\060\202\001\251\240\003\002\001\002\002\024\026
\025\307\303\330\111\247\276\151\014\212\210\355\360\160\371\335
\267\076\207\060\012\006\010\052\206\110\316\075\004\003\003\060
\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061\043
\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164\162
\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040\114
\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123\145
\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103\101
\061\065\060\036\027\015\062\060\060\064\060\070\060\070\063\062
\065\066\132\027\015\064\065\060\064\060\070\060\070\063\062\065
\066\132\060\121\061\013\060\011\006\003\125\004\006\023\002\112
\120\061\043\060\041\006\003\125\004\012\023\032\103\171\142\145
\162\164\162\165\163\164\040\112\141\160\141\156\040\103\157\056
\054\040\114\164\144\056\061\035\060\033\006\003\125\004\003\023
\024\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164
\040\103\101\061\065\060\166\060\020\006\007\052\206\110\316\075
\002\001\006\005\053\201\004\000\042\003\142\000\004\013\120\164
\215\144\062\231\231\263\322\140\010\270\042\216\106\164\054\170
\300\053\104\055\155\137\035\311\256\113\122\040\203\075\270\024
\155\123\207\140\236\137\154\205\333\006\024\225\340\307\050\377
\235\137\344\252\361\263\213\155\355\117\057\113\311\112\224\221
\144\165\376\001\354\301\330\353\172\224\170\126\030\103\137\153
\201\313\366\274\332\264\014\266\051\223\010\151\217\243\102\060
\100\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001
\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003\002
\001\006\060\035\006\003\125\035\016\004\026\004\024\353\101\310
\256\374\325\236\121\110\365\275\213\364\207\040\223\101\053\323
\364\060\012\006\010\052\206\110\316\075\004\003\003\003\150\000
\060\145\002\061\000\331\056\211\176\136\116\244\021\007\275\131
\302\007\336\253\062\070\123\052\106\104\006\027\172\316\121\351
\340\377\146\055\011\116\340\117\364\005\321\205\366\065\140\334
\365\162\263\106\175\002\060\104\230\106\032\202\205\036\141\151
\211\113\007\113\146\265\236\252\272\240\036\101\331\001\164\072
\156\105\072\211\200\031\173\062\230\125\143\253\353\143\156\223
\155\253\033\011\140\061\116
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE
CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE
# Trust for "SecureSign Root CA15"
# Issuer: CN=SecureSign Root CA15,O="Cybertrust Japan Co., Ltd.",C=JP
# Serial Number:16:15:c7:c3:d8:49:a7:be:69:0c:8a:88:ed:f0:70:f9:dd:b7:3e:87
# Subject: CN=SecureSign Root CA15,O="Cybertrust Japan Co., Ltd.",C=JP
# Not Valid Before: Wed Apr 08 08:32:56 2020
# Not Valid After : Sat Apr 08 08:32:56 2045
# Fingerprint (SHA-256): E7:78:F0:F0:95:FE:84:37:29:CD:1A:00:82:17:9E:53:14:A9:C2:91:44:28:05:E1:FB:1D:8F:B6:B8:88:6C:3A
# Fingerprint (SHA1): CB:BA:83:C8:C1:5A:5D:F1:F9:73:6F:CA:D7:EF:28:13:06:4A:07:7D
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "SecureSign Root CA15"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\313\272\203\310\301\132\135\361\371\163\157\312\327\357\050\023
\006\112\007\175
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\023\060\374\304\142\246\251\336\265\301\150\257\265\322\061\107
END
CKA_ISSUER MULTILINE_OCTAL
\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061
\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164
\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040
\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123
\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103
\101\061\065
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\024\026\025\307\303\330\111\247\276\151\014\212\210\355\360
\160\371\335\267\076\207
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE

View File

@@ -278,11 +278,11 @@ struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *
return context;
}
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_bun_socket_context_options_t options) {
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_bun_socket_context_options_t options, enum create_bun_socket_error_t *err) {
#ifndef LIBUS_NO_SSL
if (ssl) {
/* This function will call us, again, with SSL = false and a bigger ext_size */
return (struct us_socket_context_t *) us_internal_bun_create_ssl_socket_context(loop, context_ext_size, options);
return (struct us_socket_context_t *) us_internal_bun_create_ssl_socket_context(loop, context_ext_size, options, err);
}
#endif

View File

@@ -1104,7 +1104,8 @@ int us_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
}
SSL_CTX *create_ssl_context_from_bun_options(
struct us_bun_socket_context_options_t options) {
struct us_bun_socket_context_options_t options,
enum create_bun_socket_error_t *err) {
/* Create the context */
SSL_CTX *ssl_context = SSL_CTX_new(TLS_method());
@@ -1174,6 +1175,7 @@ SSL_CTX *create_ssl_context_from_bun_options(
STACK_OF(X509_NAME) * ca_list;
ca_list = SSL_load_client_CA_file(options.ca_file_name);
if (ca_list == NULL) {
*err = CREATE_BUN_SOCKET_ERROR_LOAD_CA_FILE;
free_ssl_context(ssl_context);
return NULL;
}
@@ -1181,6 +1183,7 @@ SSL_CTX *create_ssl_context_from_bun_options(
SSL_CTX_set_client_CA_list(ssl_context, ca_list);
if (SSL_CTX_load_verify_locations(ssl_context, options.ca_file_name,
NULL) != 1) {
*err = CREATE_BUN_SOCKET_ERROR_INVALID_CA_FILE;
free_ssl_context(ssl_context);
return NULL;
}
@@ -1203,6 +1206,7 @@ SSL_CTX *create_ssl_context_from_bun_options(
}
if (!add_ca_cert_to_ctx_store(ssl_context, options.ca[i], cert_store)) {
*err = CREATE_BUN_SOCKET_ERROR_INVALID_CA;
free_ssl_context(ssl_context);
return NULL;
}
@@ -1338,7 +1342,8 @@ void us_bun_internal_ssl_socket_context_add_server_name(
struct us_bun_socket_context_options_t options, void *user) {
/* Try and construct an SSL_CTX from options */
SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options);
enum create_bun_socket_error_t err = CREATE_BUN_SOCKET_ERROR_NONE;
SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options, &err);
/* Attach the user data to this context */
if (1 != SSL_CTX_set_ex_data(ssl_context, 0, user)) {
@@ -1468,14 +1473,15 @@ struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
struct us_internal_ssl_socket_context_t *
us_internal_bun_create_ssl_socket_context(
struct us_loop_t *loop, int context_ext_size,
struct us_bun_socket_context_options_t options) {
struct us_bun_socket_context_options_t options,
enum create_bun_socket_error_t *err) {
/* If we haven't initialized the loop data yet, do so .
* This is needed because loop data holds shared OpenSSL data and
* the function is also responsible for initializing OpenSSL */
us_internal_init_loop_ssl_data(loop);
/* First of all we try and create the SSL context from options */
SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options);
SSL_CTX *ssl_context = create_ssl_context_from_bun_options(options, err);
if (!ssl_context) {
/* We simply fail early if we cannot even create the OpenSSL context */
return NULL;
@@ -1487,7 +1493,7 @@ us_internal_bun_create_ssl_socket_context(
(struct us_internal_ssl_socket_context_t *)us_create_bun_socket_context(
0, loop,
sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size,
options);
options, err);
/* I guess this is the only optional callback */
context->on_server_name = NULL;
@@ -1983,9 +1989,10 @@ struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
struct us_socket_context_t *old_context = us_socket_context(0, s);
us_socket_context_ref(0,old_context);
enum create_bun_socket_error_t err = CREATE_BUN_SOCKET_ERROR_NONE;
struct us_socket_context_t *context = us_create_bun_socket_context(
1, old_context->loop, sizeof(struct us_wrapped_socket_context_t),
options);
options, &err);
// Handle SSL context creation failure
if (UNLIKELY(!context)) {

View File

@@ -3614,4 +3614,101 @@ static struct us_cert_string_t root_certs[] = {
"fKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFwhVmpHqTm6iMxoAACMQD94viz\n"
"rxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQpYXFuXqUPoeovQA=\n"
"-----END CERTIFICATE-----",.len=917},
/* TWCA CYBER Root CA */
{.str="-----BEGIN CERTIFICATE-----\n"
"MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYD\n"
"VQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQD\n"
"ExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQ\n"
"MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRsw\n"
"GQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n"
"AoICAQDG+Moe2Qkgfh1sTs6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33\n"
"Kc7wb3+szT3vsxxFavcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYd\n"
"HNWdZsc/34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i\n"
"JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjp\n"
"Ji+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY55\n"
"83WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP2oi3aQiotyMuRAlZN1vH4xfy\n"
"IutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZ\n"
"QXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff\n"
"+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0Ja\n"
"WHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMC\n"
"AQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd\n"
"BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIBAGSPesRi\n"
"DrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olNc79p\n"
"j3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x\n"
"X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o63\n"
"5yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1J\n"
"SdJlBTrq/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4\n"
"iuO/Qq+n1M0RFxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY\n"
"73NxW0Qz8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4\n"
"NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrr\n"
"uoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0Be\n"
"Jsas7a5wFsWqynKKTbDPAYsDP27X\n"
"-----END CERTIFICATE-----",.len=1980},
/* SecureSign Root CA12 */
{.str="-----BEGIN CERTIFICATE-----\n"
"MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTEL\n"
"MAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYD\n"
"VQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2\n"
"NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRk\n"
"LjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n"
"DwAwggEKAoIBAQC6OcE3emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048\n"
"luT9Ub+ZyZN+v/mtp7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPj\n"
"cf59q5zdJ1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur\n"
"FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5P\n"
"ro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMB\n"
"AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0\n"
"zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOCAQEAPrvbFxbS8hQBICw4g0utvsqF\n"
"epq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGB\n"
"pE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBo\n"
"uVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7\n"
"bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/\n"
"yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==\n"
"-----END CERTIFICATE-----",.len=1254},
/* SecureSign Root CA14 */
{.str="-----BEGIN CERTIFICATE-----\n"
"MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTEL\n"
"MAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYD\n"
"VQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2\n"
"MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRk\n"
"LjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4IC\n"
"DwAwggIKAoICAQDF0nqh1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG\n"
"3rdSINVSW0KZnvOgvlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6Kx\n"
"NedlsmGy6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo\n"
"/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn9\n"
"0Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbpra\n"
"fZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH\n"
"064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18izju3Gm5h1DVXoX+WViwKkrkMpKBGk\n"
"5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6e\n"
"VL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt\n"
"33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMB\n"
"Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk\n"
"86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0ErX+lRVAQ\n"
"Zk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoAymzv\n"
"ftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds\n"
"Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPj\n"
"YYPGFrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHV\n"
"dqqGuw6qnsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI\n"
"2i/6GaX7i+B/OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDe\n"
"M9ovnhp6dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl\n"
"Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6Ue\n"
"To3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S\n"
"-----END CERTIFICATE-----",.len=1943},
/* SecureSign Root CA15 */
{.str="-----BEGIN CERTIFICATE-----\n"
"MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkG\n"
"A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQD\n"
"ExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZa\n"
"MFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEd\n"
"MBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQL\n"
"UHSNZDKZmbPSYAi4Io5GdCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq\n"
"8bOLbe1PL0vJSpSRZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB\n"
"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT\n"
"9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO\n"
"4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr\n"
"62Nuk22rGwlgMU4=\n"
"-----END CERTIFICATE-----",.len=800},
};

View File

@@ -330,7 +330,8 @@ struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
struct us_internal_ssl_socket_context_t *
us_internal_bun_create_ssl_socket_context(
struct us_loop_t *loop, int context_ext_size,
struct us_bun_socket_context_options_t options);
struct us_bun_socket_context_options_t options,
enum create_bun_socket_error_t *err);
void us_internal_ssl_socket_context_free(
us_internal_ssl_socket_context_r context);

View File

@@ -246,8 +246,16 @@ void *us_socket_context_get_native_handle(int ssl, us_socket_context_r context);
/* A socket context holds shared callbacks and user data extension for associated sockets */
struct us_socket_context_t *us_create_socket_context(int ssl, us_loop_r loop,
int ext_size, struct us_socket_context_options_t options) nonnull_fn_decl;
enum create_bun_socket_error_t {
CREATE_BUN_SOCKET_ERROR_NONE = 0,
CREATE_BUN_SOCKET_ERROR_LOAD_CA_FILE,
CREATE_BUN_SOCKET_ERROR_INVALID_CA_FILE,
CREATE_BUN_SOCKET_ERROR_INVALID_CA,
};
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop,
int ext_size, struct us_bun_socket_context_options_t options);
int ext_size, struct us_bun_socket_context_options_t options, enum create_bun_socket_error_t *err);
/* Delete resources allocated at creation time (will call unref now and only free when ref count == 0). */
void us_socket_context_free(int ssl, us_socket_context_r context) nonnull_fn_decl;

View File

@@ -433,7 +433,8 @@ public:
static HttpContext *create(Loop *loop, us_bun_socket_context_options_t options = {}) {
HttpContext *httpContext;
httpContext = (HttpContext *) us_create_bun_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData<SSL>), options);
enum create_bun_socket_error_t err = CREATE_BUN_SOCKET_ERROR_NONE;
httpContext = (HttpContext *) us_create_bun_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData<SSL>), options, &err);
if (!httpContext) {
return nullptr;

View File

@@ -0,0 +1,58 @@
--- a/libarchive/archive_write_add_filter_gzip.c
+++ b/libarchive/archive_write_add_filter_gzip.c
@@ -58,6 +58,7 @@ archive_write_set_compression_gzip(struct archive *a)
struct private_data {
int compression_level;
int timestamp;
+ unsigned char os;
#ifdef HAVE_ZLIB_H
z_stream stream;
int64_t total_in;
@@ -106,6 +107,7 @@ archive_write_add_filter_gzip(struct archive *_a)
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
+ data->os = 3; /* default Unix */
f->data = data;
f->open = &archive_compressor_gzip_open;
f->options = &archive_compressor_gzip_options;
@@ -166,6 +168,30 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
return (ARCHIVE_OK);
}
+ if (strcmp(key, "os") == 0) {
+ if (value == NULL)
+ return (ARCHIVE_WARN);
+
+ if (strcmp(value, "FAT") == 0) data->os = 0;
+ else if (strcmp(value, "Amiga") == 0) data->os = 1;
+ else if (strcmp(value, "VMS") == 0 || strcmp(value, "OpenVMS") == 0) data->os = 2;
+ else if (strcmp(value, "Unix") == 0) data->os = 3;
+ else if (strcmp(value, "VM") == 0 || strcmp(value, "VM/CMS") == 0) data->os = 4;
+ else if (strcmp(value, "Atari TOS") == 0) data->os = 5;
+ else if (strcmp(value, "HPFS") == 0) data->os = 6;
+ else if (strcmp(value, "Macintosh") == 0) data->os = 7;
+ else if (strcmp(value, "Z-System") == 0) data->os = 8;
+ else if (strcmp(value, "CP/M") == 0) data->os = 9;
+ else if (strcmp(value, "TOPS-20") == 0) data->os = 10;
+ else if (strcmp(value, "NTFS") == 0) data->os = 11;
+ else if (strcmp(value, "QDOS") == 0) data->os = 12;
+ else if (strcmp(value, "Acorn RISCOS") == 0) data->os = 13;
+ else if (strcmp(value, "Unknown") == 0) data->os = 255;
+ else return (ARCHIVE_WARN);
+
+ return (ARCHIVE_OK);
+ }
+
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
* a suitable error if no one used this option. */
@@ -226,7 +252,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->compressed[8] = 4;
else
data->compressed[8] = 0;
- data->compressed[9] = 3; /* OS=Unix */
+ data->compressed[9] = data->os;
data->stream.next_out += 10;
data->stream.avail_out -= 10;

View File

@@ -3,16 +3,6 @@ pub usingnamespace @import("./src/main.zig");
/// These functions are used throughout Bun's codebase.
pub const bun = @import("./src/bun.zig");
pub const content = struct {
pub const error_js_path = "packages/bun-error/dist/index.js";
pub const error_js = @embedFile(error_js_path);
pub const error_css_path = "packages/bun-error/dist/bun-error.css";
pub const error_css_path_dev = "packages/bun-error/bun-error.css";
pub const error_css = @embedFile(error_css_path);
};
pub const completions = struct {
pub const bash = @embedFile("./completions/bun.bash");
pub const zsh = @embedFile("./completions/bun.zsh");

View File

@@ -2,16 +2,6 @@ pub usingnamespace @import("src/main_wasm.zig");
pub const bun = @import("src/bun.zig");
pub const content = struct {
pub const error_js_path = "packages/bun-error/dist/index.js";
pub const error_js = @embedFile(error_js_path);
pub const error_css_path = "packages/bun-error/dist/bun-error.css";
pub const error_css_path_dev = "packages/bun-error/bun-error.css";
pub const error_css = @embedFile(error_css_path);
};
pub const completions = struct {};
pub const is_bindgen = true;
pub const JavaScriptCore = struct {

View File

@@ -233,8 +233,13 @@ async function runTests() {
reportOutputToGitHubAction("failing_tests", markdown);
}
if (!isCI) console.log("-------");
if (!isCI) console.log("passing", results.length - failedTests.length, "/", results.length);
if (!isCI) {
console.log("-------");
console.log("passing", results.length - failedTests.length, "/", results.length);
for (const { testPath } of failedTests) {
console.log("-", testPath);
}
}
return results;
}

View File

@@ -73,6 +73,7 @@ IncludeIsMainRegex: "(Test)?$"
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertNewlineAtEOF: true
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true

View File

@@ -1039,7 +1039,7 @@ pub const StandaloneModuleGraph = struct {
bun.JSAst.Expr.Data.Store.reset();
bun.JSAst.Stmt.Data.Store.reset();
}
var json = bun.JSON.ParseJSON(&json_src, &log, arena, false) catch
var json = bun.JSON.parse(&json_src, &log, arena, false) catch
return error.InvalidSourceMap;
const mappings_str = json.get("mappings") orelse

View File

@@ -1635,6 +1635,8 @@ pub const Api = struct {
/// define
define: ?StringMap = null,
drop: []const []const u8 = &.{},
/// preserve_symlinks
preserve_symlinks: ?bool = null,
@@ -1749,9 +1751,7 @@ pub const Api = struct {
15 => {
this.target = try reader.readValue(Target);
},
16 => {
this.serve = try reader.readValue(bool);
},
16 => {},
17 => {
this.env_files = try reader.readArray([]const u8);
},
@@ -2976,6 +2976,13 @@ pub const Api = struct {
/// concurrent_scripts
concurrent_scripts: ?u32 = null,
cafile: ?[]const u8 = null,
ca: ?union(enum) {
str: []const u8,
list: []const []const u8,
} = null,
pub fn decode(reader: anytype) anyerror!BunInstall {
var this = std.mem.zeroes(BunInstall);

View File

@@ -31,7 +31,6 @@ pub const RefCtx = struct {
/// In some parts of Bun, we have many different IDs pointing to different things.
/// It's easy for them to get mixed up, so we use this type to make sure we don't.
///
pub const Index = packed struct(u32) {
value: Int,
@@ -48,8 +47,8 @@ pub const Index = packed struct(u32) {
pub const invalid = Index{ .value = std.math.maxInt(Int) };
pub const runtime = Index{ .value = 0 };
pub const kit_server_data = Index{ .value = 1 };
pub const kit_client_data = Index{ .value = 2 };
pub const bake_server_data = Index{ .value = 1 };
pub const bake_client_data = Index{ .value = 2 };
pub const Int = u32;
@@ -114,7 +113,7 @@ pub const Ref = packed struct(u64) {
allocated_name,
source_contents_slice,
symbol,
} = .invalid,
},
source_index: Int = 0,

View File

@@ -14,6 +14,29 @@ pub fn BabyList(comptime Type: type) type {
pub const Elem = Type;
pub fn parse(input: *bun.css.Parser) bun.css.Result(ListType) {
return switch (input.parseCommaSeparated(Type, bun.css.generic.parseFor(Type))) {
.result => |v| return .{ .result = ListType{
.ptr = v.items.ptr,
.len = @intCast(v.items.len),
.cap = @intCast(v.capacity),
} },
.err => |e| return .{ .err = e },
};
}
pub fn toCss(this: *const ListType, comptime W: type, dest: *bun.css.Printer(W)) bun.css.PrintErr!void {
return bun.css.to_css.fromBabyList(Type, this, W, dest);
}
pub fn eql(lhs: *const ListType, rhs: *const ListType) bool {
if (lhs.len != rhs.len) return false;
for (lhs.sliceConst(), rhs.sliceConst()) |*a, *b| {
if (!bun.css.generic.eql(Type, a, b)) return false;
}
return true;
}
pub fn set(this: *@This(), slice_: []Type) void {
this.ptr = slice_.ptr;
this.len = @as(u32, @truncate(slice_.len));
@@ -29,6 +52,12 @@ pub fn BabyList(comptime Type: type) type {
this.* = .{};
}
pub fn shrinkAndFree(this: *@This(), allocator: std.mem.Allocator, size: usize) void {
var list_ = this.listManaged(allocator);
list_.shrinkAndFree(size);
this.update(list_);
}
pub fn orderedRemove(this: *@This(), index: usize) Type {
var l = this.list();
defer this.update(l);
@@ -41,6 +70,12 @@ pub fn BabyList(comptime Type: type) type {
return l.swapRemove(index);
}
pub fn sortAsc(
this: *@This(),
) void {
bun.strings.sortAsc(this.slice());
}
pub fn contains(this: @This(), item: []const Type) bool {
return this.len > 0 and @intFromPtr(item.ptr) >= @intFromPtr(this.ptr) and @intFromPtr(item.ptr) < @intFromPtr(this.ptr) + this.len;
}
@@ -77,8 +112,17 @@ pub fn BabyList(comptime Type: type) type {
};
}
fn assertValidDeepClone(comptime T: type) void {
return switch (T) {
bun.JSAst.Expr, bun.JSAst.G.Property, bun.css.ImportConditions => {},
else => {
@compileError("Unsupported type for BabyList.deepClone(): " ++ @typeName(Type));
},
};
}
pub fn deepClone(this: @This(), allocator: std.mem.Allocator) !@This() {
if (comptime Type != bun.JSAst.Expr and Type != bun.JSAst.G.Property) @compileError("Unsupported type for BabyList.deepClone()");
assertValidDeepClone(Type);
var list_ = try initCapacity(allocator, this.len);
for (this.slice()) |item| {
list_.appendAssumeCapacity(try item.deepClone(allocator));
@@ -87,6 +131,17 @@ pub fn BabyList(comptime Type: type) type {
return list_;
}
/// Same as `deepClone` but doesn't return an error
pub fn deepClone2(this: @This(), allocator: std.mem.Allocator) @This() {
assertValidDeepClone(Type);
var list_ = initCapacity(allocator, this.len) catch bun.outOfMemory();
for (this.slice()) |item| {
list_.appendAssumeCapacity(item.deepClone(allocator));
}
return list_;
}
pub fn clearRetainingCapacity(this: *@This()) void {
this.len = 0;
}
@@ -264,6 +319,11 @@ pub fn BabyList(comptime Type: type) type {
return this.ptr[0..this.len];
}
pub fn sliceConst(this: *const ListType) callconv(bun.callconv_inline) []const Type {
@setRuntimeSafety(false);
return this.ptr[0..this.len];
}
pub fn write(this: *@This(), allocator: std.mem.Allocator, str: []const u8) !u32 {
if (comptime Type != u8)
@compileError("Unsupported for type " ++ @typeName(Type));

View File

@@ -0,0 +1,118 @@
#include "BakeDevGlobalObject.h"
#include "JSNextTickQueue.h"
#include "JavaScriptCore/GlobalObjectMethodTable.h"
#include "JavaScriptCore/JSInternalPromise.h"
#include "ProcessIdentifier.h"
#include "headers-handwritten.h"
namespace Bake {
extern "C" void BakeInitProcessIdentifier()
{
// assert is on main thread
WebCore::Process::identifier();
}
JSC::JSInternalPromise*
moduleLoaderImportModule(JSC::JSGlobalObject* jsGlobalObject,
JSC::JSModuleLoader*, JSC::JSString* moduleNameValue,
JSC::JSValue parameters,
const JSC::SourceOrigin& sourceOrigin)
{
// TODO: forward this to the runtime?
JSC::VM& vm = jsGlobalObject->vm();
auto err = JSC::createTypeError(
jsGlobalObject,
WTF::makeString(
"Dynamic import should have been replaced with a hook into the module runtime"_s));
auto* promise = JSC::JSInternalPromise::create(
vm, jsGlobalObject->internalPromiseStructure());
promise->reject(jsGlobalObject, err);
return promise;
}
#define INHERIT_HOOK_METHOD(name) \
Zig::GlobalObject::s_globalObjectMethodTable.name
const JSC::GlobalObjectMethodTable DevGlobalObject::s_globalObjectMethodTable = {
INHERIT_HOOK_METHOD(supportsRichSourceInfo),
INHERIT_HOOK_METHOD(shouldInterruptScript),
INHERIT_HOOK_METHOD(javaScriptRuntimeFlags),
INHERIT_HOOK_METHOD(queueMicrotaskToEventLoop),
INHERIT_HOOK_METHOD(shouldInterruptScriptBeforeTimeout),
moduleLoaderImportModule,
INHERIT_HOOK_METHOD(moduleLoaderResolve),
INHERIT_HOOK_METHOD(moduleLoaderFetch),
INHERIT_HOOK_METHOD(moduleLoaderCreateImportMetaProperties),
INHERIT_HOOK_METHOD(moduleLoaderEvaluate),
INHERIT_HOOK_METHOD(promiseRejectionTracker),
INHERIT_HOOK_METHOD(reportUncaughtExceptionAtEventLoop),
INHERIT_HOOK_METHOD(currentScriptExecutionOwner),
INHERIT_HOOK_METHOD(scriptExecutionStatus),
INHERIT_HOOK_METHOD(reportViolationForUnsafeEval),
INHERIT_HOOK_METHOD(defaultLanguage),
INHERIT_HOOK_METHOD(compileStreaming),
INHERIT_HOOK_METHOD(instantiateStreaming),
INHERIT_HOOK_METHOD(deriveShadowRealmGlobalObject),
INHERIT_HOOK_METHOD(codeForEval),
INHERIT_HOOK_METHOD(canCompileStrings),
};
DevGlobalObject*
DevGlobalObject::create(JSC::VM& vm, JSC::Structure* structure,
const JSC::GlobalObjectMethodTable* methodTable)
{
DevGlobalObject* ptr = new (NotNull, JSC::allocateCell<DevGlobalObject>(vm))
DevGlobalObject(vm, structure, methodTable);
ptr->finishCreation(vm);
return ptr;
}
void DevGlobalObject::finishCreation(JSC::VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
}
extern "C" BunVirtualMachine* Bun__getVM();
// A lot of this function is taken from 'Zig__GlobalObject__create'
extern "C" DevGlobalObject* BakeCreateDevGlobal(DevServer* owner,
void* console)
{
JSC::VM& vm = JSC::VM::create(JSC::HeapType::Large).leakRef();
vm.heap.acquireAccess();
JSC::JSLockHolder locker(vm);
BunVirtualMachine* bunVM = Bun__getVM();
WebCore::JSVMClientData::create(&vm, bunVM);
JSC::Structure* structure = DevGlobalObject::createStructure(vm);
DevGlobalObject* global = DevGlobalObject::create(
vm, structure, &DevGlobalObject::s_globalObjectMethodTable);
if (!global)
BUN_PANIC("Failed to create DevGlobalObject");
global->m_devServer = owner;
global->m_bunVM = bunVM;
JSC::gcProtect(global);
global->setConsole(console);
global->setStackTraceLimit(10); // Node.js defaults to 10
// TODO: it segfaults! process.nextTick is scoped out for now i guess!
// vm.setOnComputeErrorInfo(computeErrorInfoWrapper);
// vm.setOnEachMicrotaskTick([global](JSC::VM &vm) -> void {
// if (auto nextTickQueue = global->m_nextTickQueue.get()) {
// global->resetOnEachMicrotaskTick();
// // Bun::JSNextTickQueue *queue =
// // jsCast<Bun::JSNextTickQueue *>(nextTickQueue);
// // queue->drain(vm, global);
// return;
// }
// });
return global;
}
}; // namespace Bake

View File

@@ -2,7 +2,7 @@
#include "root.h"
#include "ZigGlobalObject.h"
namespace Kit {
namespace Bake {
struct DevServer; // DevServer.zig
struct Route; // DevServer.zig
@@ -18,10 +18,10 @@ public:
return nullptr;
return WebCore::subspaceForImpl<DevGlobalObject, WebCore::UseCustomHeapCellType::Yes>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceForKitGlobalScope.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForKitGlobalScope = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceForKitGlobalScope.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForKitGlobalScope = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_clientSubspaceForBakeGlobalScope.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBakeGlobalScope = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceForBakeGlobalScope.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForBakeGlobalScope = std::forward<decltype(space)>(space); },
[](auto& server) -> JSC::HeapCellType& { return server.m_heapCellTypeForJSWorkerGlobalScope; });
}
@@ -37,6 +37,7 @@ public:
};
// Zig API
extern "C" void KitInitProcessIdentifier();
extern "C" DevGlobalObject* KitCreateDevGlobal(DevServer* owner, void* console);
}; // namespace Kit

View File

@@ -0,0 +1,79 @@
// clang-format off
#include "BakeDevSourceProvider.h"
#include "BakeDevGlobalObject.h"
#include "JavaScriptCore/Completion.h"
#include "JavaScriptCore/Identifier.h"
#include "JavaScriptCore/JSCJSValue.h"
#include "JavaScriptCore/JSCast.h"
#include "JavaScriptCore/JSLock.h"
#include "JavaScriptCore/JSMap.h"
#include "JavaScriptCore/JSModuleLoader.h"
#include "JavaScriptCore/JSString.h"
#include "JavaScriptCore/JSModuleNamespaceObject.h"
namespace Bake {
extern "C" LoadServerCodeResult BakeLoadInitialServerCode(DevGlobalObject* global, BunString source) {
JSC::VM& vm = global->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
String string = "bake://server.js"_s;
JSC::SourceOrigin origin = JSC::SourceOrigin(WTF::URL(string));
JSC::SourceCode sourceCode = JSC::SourceCode(DevSourceProvider::create(
source.toWTFString(),
origin,
WTFMove(string),
WTF::TextPosition(),
JSC::SourceProviderSourceType::Module
));
JSC::JSString* key = JSC::jsString(vm, string);
global->moduleLoader()->provideFetch(global, key, sourceCode);
RETURN_IF_EXCEPTION(scope, {});
JSC::JSInternalPromise* internalPromise = global->moduleLoader()->loadAndEvaluateModule(global, key, JSC::jsUndefined(), JSC::jsUndefined());
RETURN_IF_EXCEPTION(scope, {});
return { internalPromise, key };
}
extern "C" JSC::EncodedJSValue BakeLoadServerHmrPatch(DevGlobalObject* global, BunString source) {
JSC::VM&vm=global->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
String string = "bake://server.patch.js"_s;
JSC::SourceOrigin origin = JSC::SourceOrigin(WTF::URL(string));
JSC::SourceCode sourceCode = JSC::SourceCode(DevSourceProvider::create(
source.toWTFString(),
origin,
WTFMove(string),
WTF::TextPosition(),
JSC::SourceProviderSourceType::Program
));
JSC::JSValue result = vm.interpreter.executeProgram(sourceCode, global, global);
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode({}));
RELEASE_ASSERT(result);
return JSC::JSValue::encode(result);
}
extern "C" JSC::EncodedJSValue BakeGetRequestHandlerFromModule(
DevGlobalObject* global,
JSC::JSString* key
) {
JSC::VM&vm = global->vm();
JSC::JSMap* map = JSC::jsCast<JSC::JSMap*>(
global->moduleLoader()->getDirect(
vm, JSC::Identifier::fromString(global->vm(), "registry"_s)
));
JSC::JSValue entry = map->get(global, key);
ASSERT(entry.isObject()); // should have called BakeLoadServerCode and wait for that promise
JSC::JSValue module = entry.getObject()->get(global, JSC::Identifier::fromString(global->vm(), "module"_s));
ASSERT(module.isCell());
JSC::JSModuleNamespaceObject* namespaceObject = global->moduleLoader()->getModuleNamespaceObject(global, module);
ASSERT(namespaceObject);
return JSC::JSValue::encode(namespaceObject->get(global, vm.propertyNames->defaultKeyword));
}
} // namespace Bake

View File

@@ -1,30 +1,30 @@
#pragma once
#include "root.h"
#include "headers-handwritten.h"
#include "KitDevGlobalObject.h"
#include "BakeDevGlobalObject.h"
#include "JavaScriptCore/SourceOrigin.h"
namespace Kit {
namespace Bake {
struct LoadServerCodeResult {
JSC::JSInternalPromise* promise;
JSC::JSString* key;
};
class KitSourceProvider final : public JSC::StringSourceProvider {
class DevSourceProvider final : public JSC::StringSourceProvider {
public:
static Ref<KitSourceProvider> create(
static Ref<DevSourceProvider> create(
const String& source,
const JSC::SourceOrigin& sourceOrigin,
String&& sourceURL,
const TextPosition& startPosition,
JSC::SourceProviderSourceType sourceType
) {
return adoptRef(*new KitSourceProvider(source, sourceOrigin, WTFMove(sourceURL), startPosition, sourceType));
return adoptRef(*new DevSourceProvider(source, sourceOrigin, WTFMove(sourceURL), startPosition, sourceType));
}
private:
KitSourceProvider(
DevSourceProvider(
const String& source,
const JSC::SourceOrigin& sourceOrigin,
String&& sourceURL,
@@ -41,7 +41,8 @@ private:
};
// Zig API
extern "C" LoadServerCodeResult KitLoadServerCode(DevGlobalObject* global, BunString source);
extern "C" JSC::EncodedJSValue KitGetRequestHandlerFromModule(DevGlobalObject* global, JSC::JSString* encodedModule);
extern "C" LoadServerCodeResult BakeLoadInitialServerCode(DevGlobalObject* global, BunString source);
extern "C" JSC::EncodedJSValue BakeLoadServerHmrPatch(DevGlobalObject* global, BunString source);
extern "C" JSC::EncodedJSValue BakeGetRequestHandlerFromModule(DevGlobalObject* global, JSC::JSString* encodedModule);
} // namespace Kit
} // namespace Bake

3317
src/bake/DevServer.zig Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,18 @@
declare module 'bun' {
declare namespace Kit {
declare module "bun" {
declare function wipDevServerExpectHugeBreakingChanges(options: Bake.Options): never;
declare namespace Bake {
interface Options {
/**
* Use "react" to use the built-in React framework preset.
* Bun provides built-in support for using React as a framework by
* passing 'react-server-components' as the framework name.
*
* Has external dependencies:
* ```
* bun i react@experimental react-dom@experimental react-server-dom-webpack@experimental react-refresh@experimental
* ```
*/
framework?: Framework | 'react' | undefined;
framework: Framework | "react-server-components";
/**
* Route patterns must be statically known.
@@ -12,9 +20,9 @@ declare module 'bun' {
*/
routes: Record<RoutePattern, RouteOptions>;
// TODO: expose bundler options. things like minifySyntax may not be disabled
// TODO: many other options
}
/**
* A "Framework" in our eyes is simply a set of bundler options that a
* framework author would set in order to integrate framework code with the
@@ -27,22 +35,26 @@ declare module 'bun' {
* This file is the true entrypoint of the server application. This module
* must `export default` a fetch function, which takes a request and the
* bundled route module, and returns a response. See `ServerEntryPoint`
*
*
* When `serverComponents` is configured, this can access the component
* manifest using the special 'bun:kit/server' import:
*
* import { serverManifest } from 'bun:kit/server'
* manifest using the special 'bun:bake/server' import:
*
* import { serverManifest } from 'bun:bake/server'
*/
serverEntryPoint: ImportSource;
/**
* This file is the true entrypoint of the client application.
*
*
* When `serverComponents` is configured, this can access the component
* manifest using the special 'bun:kit/client' import:
*
* import { clientManifest } from 'bun:kit/client'
* manifest using the special 'bun:bake/client' import:
*
* import { clientManifest } from 'bun:bake/client'
*/
clientEntryPoint: ImportSource;
/**
* Add extra modules
*/
builtInModules: Record<string, BuiltInModule>;
/**
* Bun offers integration for React's Server Components with an
* interface that is generic enough to adapt to any framework.
@@ -52,9 +64,11 @@ declare module 'bun' {
* While it is unlikely that Fast Refresh is useful outside of
* React, it can be enabled regardless.
*/
reactFastRefresh?: ReactFastRefreshOptions | undefined;
reactFastRefresh?: ReactFastRefreshOptions | true | undefined;
}
type BuiltInModule = { code: string } | { path: string };
/**
* A high-level overview of what server components means exists
* in the React Docs: https://react.dev/reference/rsc/server-components
@@ -78,11 +92,11 @@ declare module 'bun' {
* despite running in the same process. This facilitates different aspects
* of the server and client react runtimes, such as `async` components only
* being available on the server.
*
* To cross from the server graph to the SSR graph, use the bun_kit_graph
*
* To cross from the server graph to the SSR graph, use the bun_bake_graph
* import attribute:
*
* import * as ReactDOM from 'react-dom/server' with { bun_kit_graph: 'ssr' };
*
* import * as ReactDOM from 'react-dom/server' with { bun_bake_graph: 'ssr' };
*
* Since these models are so subtley different, there is no default value
* provided for this.
@@ -109,29 +123,41 @@ declare module 'bun' {
* // name the user has given.
* "ClientComp",
* );
*
*
* Additionally, the bundler will assemble a component manifest to be used
* during rendering.
*/
serverRegisterClientReferenceExport: string | undefined;
}
/** Customize the React Fast Refresh transform. */
interface ReactFastRefreshOptions {
/** @default "react-refresh/runtime" */
importSource: ImportSource | undefined;
}
/// Will be resolved from the point of view of the framework user's project root
/// Examples: `react-dom`, `./entry_point.tsx`, `/absolute/path.js`
type ImportSource = string;
interface ServerEntryPoint {
/// The framework implementation decides and enforces the shape
/// of the route module. Bun passes it as an opaque value.
/**
* The framework implementation decides and enforces the shape
* of the route module. Bun passes it as an opaque value.
*/
default: (request: Request, routeModule: unknown, routeMetadata: RouteMetadata) => Response;
}
interface ClientEntryPoint {
/**
* Called when server-side code is changed. This can be used to fetch a
* non-html version of the updated page to perform a faster reload.
*
* Tree-shaken away in production builds.
*/
onServerSideReload?: () => void;
}
interface RouteMetadata {
/** A list of css files that the route will need to be styled */
styles: string[];
@@ -139,13 +165,13 @@ declare module 'bun' {
scripts: string[];
}
}
// declare class Kit {
// constructor(options: Kit.Options);
// declare class Bake {
// constructor(options: Bake.Options);
// }
}
declare module 'bun:kit/server' {
declare module "bun:bake/server" {
// NOTE: The format of these manifests will likely be customizable in the future.
/**
@@ -165,7 +191,7 @@ declare module 'bun:kit/server' {
declare const actionManifest: never;
}
declare module 'bun:kit/client' {
declare module "bun:bake/client" {
/**
* Entries in this manifest can be loaded by using dynamic `await import()` or
* `require`. The bundler currently ensures that all modules are ready.
@@ -175,11 +201,11 @@ declare module 'bun:kit/client' {
declare interface ReactClientManifest {
[id: string]: {
[name: string]: {
[name: string]: {
/** Valid specifier to import */
specifier: string,
specifier: string;
/** Export name */
name: string,
name: string;
};
};
}
@@ -188,21 +214,21 @@ declare interface ReactServerManifest {
/**
* Concatenation of the component file ID and the instance id with '#'
* Example: 'components/Navbar.tsx#default' (dev) or 'l2#a' (prod/minified)
*
*
* The component file ID and the instance id are both passed to `registerClientReference`
*/
[combinedComponentId: string]: {
/**
* The `id` in ReactClientManifest.
* Correlates but is not required to be the filename
*/
id: string;
/**
* The `name` in ReactServerManifest
* Correlates but is not required to be the export name
*/
name: string;
/** Currently not implemented; always an empty array */
chunks: [];
/**
* The `id` in ReactClientManifest.
* Correlates but is not required to be the filename
*/
id: string;
/**
* The `name` in ReactServerManifest
* Correlates but is not required to be the export name
*/
name: string;
/** Currently not implemented; always an empty array */
chunks: [];
};
}
}

70
src/bake/bake.private.d.ts vendored Normal file
View File

@@ -0,0 +1,70 @@
type Id = string;
/** Index with same usage as `IncrementalGraph(.client).Index` */
type FileIndex = number;
interface Config {
// Server + Client
main: Id;
// Server
separateSSRGraph?: true;
// Client
/** If available, this is the Id of `react-refresh/runtime` */
refresh?: Id;
/**
* A list of "roots" that the client is aware of. This includes
* the framework entry point, as well as every client component.
*/
roots: FileIndex[];
}
/**
* All modules for the initial bundle.
*/
declare const input_graph: Record<string, ModuleLoadFunction>;
declare const config: Config;
/**
* The runtime is bundled for server and client, which influences
* how hmr connection should be established, as well if there is
* a window to visually display errors with.
*/
declare const side: "client" | "server";
/*
* This variable becomes the default export. Kit uses this
* interface as opposed to a WebSocket connection.
*/
declare var server_exports: {
handleRequest: (req: Request, meta: HandleRequestMeta, id: Id) => any;
registerUpdate: (
modules: any,
componentManifestAdd: null | string[],
componentManifestDelete: null | string[],
) => void;
};
interface HandleRequestMeta {
// url for script tag
clientEntryPoint: string;
}
/*
* If you are running a debug build of Bun. These debug builds should provide
* helpful information to someone working on the bundler itself.
*/
declare const IS_BUN_DEVELOPMENT: any;
// shims for experimental react types
declare module "react" {
export function use<T>(promise: Promise<T>): T;
}
declare module "react-server-dom-webpack/client.browser" {
export function createFromReadableStream<T = any>(readable: ReadableStream, manifest?: any): Promise<T>;
}
declare module "react-server-dom-webpack/server.browser" {
export function renderToReadableStream<T = any>(element: JSX.Element, manifest: any): ReadableStream;
}

390
src/bake/bake.zig Normal file
View File

@@ -0,0 +1,390 @@
//! Bake is Bun's toolkit for building client+server web applications. It
//! combines `Bun.build` and `Bun.serve`, providing a hot-reloading development
//! server, server components, and other integrations. Instead of taking the
//! role as a framework, Bake is tool for frameworks to build on top of.
/// Temporary function to invoke dev server via JavaScript. Will be
/// replaced with a user-facing API. Refs the event loop forever.
pub fn jsWipDevServer(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue {
if (!bun.FeatureFlags.bake) return .undefined;
BakeInitProcessIdentifier();
bun.Output.warn(
\\Be advised that Bun Bake is highly experimental, and its API
\\will have breaking changes. Join the <magenta>#bake<r> Discord
\\channel to help us find bugs: <blue>https://bun.sh/discord<r>
\\
\\
, .{});
bun.Output.flush();
const options = devServerOptionsFromJs(global, callframe.argument(0)) catch {
if (!global.hasException())
global.throwInvalidArguments("invalid arguments", .{});
return .zero;
};
// TODO: this should inherit the current VM, running on the main thread.
const t = std.Thread.spawn(.{}, wipDevServer, .{options}) catch @panic("Failed to start");
t.detach();
{
var futex = std.atomic.Value(u32).init(0);
while (true) std.Thread.Futex.wait(&futex, 0);
}
}
extern fn BakeInitProcessIdentifier() void;
/// A "Framework" in our eyes is simply set of bundler options that a framework
/// author would set in order to integrate the framework with the application.
///
/// Full documentation on these fields is located in the TypeScript definitions.
pub const Framework = struct {
entry_client: []const u8,
entry_server: []const u8,
server_components: ?ServerComponents = null,
react_fast_refresh: ?ReactFastRefresh = null,
built_in_modules: bun.StringArrayHashMapUnmanaged(BuiltInModule) = .{},
/// Bun provides built-in support for using React as a framework.
/// Depends on externally provided React
///
/// $ bun i react@experimental react-dom@experimental react-server-dom-webpack@experimental react-refresh@experimental
pub fn react() Framework {
return .{
.server_components = .{
.separate_ssr_graph = true,
.server_runtime_import = "react-server-dom-webpack/server",
// .client_runtime_import = "react-server-dom-webpack/client",
},
.react_fast_refresh = .{},
.entry_client = "bun-framework-rsc/client.tsx",
.entry_server = "bun-framework-rsc/server.tsx",
.built_in_modules = bun.StringArrayHashMapUnmanaged(BuiltInModule).init(bun.default_allocator, &.{
"bun-framework-rsc/client.tsx",
"bun-framework-rsc/server.tsx",
"bun-framework-rsc/ssr.tsx",
}, if (Environment.codegen_embed) &.{
.{ .code = @embedFile("./bun-framework-rsc/client.tsx") },
.{ .code = @embedFile("./bun-framework-rsc/server.tsx") },
.{ .code = @embedFile("./bun-framework-rsc/ssr.tsx") },
} else &.{
.{ .code = bun.runtimeEmbedFile(.src, "bake/bun-framework-rsc/client.tsx") },
.{ .code = bun.runtimeEmbedFile(.src, "bake/bun-framework-rsc/server.tsx") },
.{ .code = bun.runtimeEmbedFile(.src, "bake/bun-framework-rsc/ssr.tsx") },
}) catch bun.outOfMemory(),
};
}
const BuiltInModule = union(enum) {
import: []const u8,
code: []const u8,
};
const ServerComponents = struct {
separate_ssr_graph: bool = false,
server_runtime_import: []const u8,
// client_runtime_import: []const u8,
server_register_client_reference: []const u8 = "registerClientReference",
server_register_server_reference: []const u8 = "registerServerReference",
client_register_server_reference: []const u8 = "registerServerReference",
};
const ReactFastRefresh = struct {
import_source: []const u8 = "react-refresh/runtime",
};
/// Given a Framework configuration, this returns another one with all modules resolved.
///
/// All resolution errors will happen before returning error.ModuleNotFound
/// Details written into `r.log`
pub fn resolve(f: Framework, server: *bun.resolver.Resolver, client: *bun.resolver.Resolver) !Framework {
var clone = f;
var had_errors: bool = false;
f.resolveHelper(client, &clone.entry_client, &had_errors, "client entrypoint");
f.resolveHelper(server, &clone.entry_server, &had_errors, "server entrypoint");
if (clone.react_fast_refresh) |*react_fast_refresh| {
f.resolveHelper(client, &react_fast_refresh.import_source, &had_errors, "react refresh runtime");
}
if (clone.server_components) |*sc| {
f.resolveHelper(server, &sc.server_runtime_import, &had_errors, "server components runtime");
// f.resolveHelper(client, &sc.client_runtime_import, &had_errors);
}
if (had_errors) return error.ModuleNotFound;
return clone;
}
inline fn resolveHelper(f: *const Framework, r: *bun.resolver.Resolver, path: *[]const u8, had_errors: *bool, desc: []const u8) void {
if (f.built_in_modules.get(path.*)) |mod| {
switch (mod) {
.import => |p| path.* = p,
.code => {},
}
return;
}
var result = r.resolve(r.fs.top_level_dir, path.*, .stmt) catch |err| {
bun.Output.err(err, "Failed to resolve '{s}' for framework ({s})", .{ path.*, desc });
had_errors.* = true;
return;
};
path.* = result.path().?.text; // TODO: what is the lifetime of this string
}
// TODO: This function always leaks memory.
// `Framework` has no way to specify what is allocated, nor should it.
fn fromJS(opts: JSValue, global: *JSC.JSGlobalObject) !Framework {
if (opts.isString()) {
const str = opts.toBunString(global);
defer str.deref();
if (str.eqlComptime("react-server-components")) {
return Framework.react();
}
}
if (!opts.isObject()) {
global.throwInvalidArguments("Framework must be an object", .{});
return error.JSError;
}
return .{
.entry_server = brk: {
const prop: JSValue = opts.get(global, "serverEntryPoint") orelse {
if (!global.hasException())
global.throwInvalidArguments("Missing 'framework.serverEntryPoint'", .{});
return error.JSError;
};
const str = prop.toBunString(global);
defer str.deref();
if (global.hasException())
return error.JSError;
// Leak
break :brk str.toUTF8(bun.default_allocator).slice();
},
.entry_client = brk: {
const prop: JSValue = opts.get(global, "clientEntryPoint") orelse {
if (!global.hasException())
global.throwInvalidArguments("Missing 'framework.clientEntryPoint'", .{});
return error.JSError;
};
const str = prop.toBunString(global);
defer str.deref();
if (global.hasException())
return error.JSError;
// Leak
break :brk str.toUTF8(bun.default_allocator).slice();
},
.react_fast_refresh = brk: {
const rfr: JSValue = opts.get(global, "reactFastRefresh") orelse {
if (global.hasException())
return error.JSError;
break :brk null;
};
if (rfr == .true) break :brk .{};
if (rfr == .false or rfr == .null or rfr == .undefined) break :brk null;
if (!rfr.isObject()) {
global.throwInvalidArguments("'framework.reactFastRefresh' must be an object or 'true'", .{});
return error.JSError;
}
// in addition to here, this import isnt actually wired up to js_parser where the default is hardcoded.
bun.todoPanic(@src(), "custom react-fast-refresh import source", .{});
},
.server_components = sc: {
const sc: JSValue = opts.get(global, "serverComponents") orelse {
if (global.hasException())
return error.JSError;
break :sc null;
};
if (sc == .null or sc == .undefined) break :sc null;
break :sc .{
// .client_runtime_import = "",
.separate_ssr_graph = brk: {
const prop: JSValue = sc.get(global, "separateSSRGraph") orelse {
if (!global.hasException())
global.throwInvalidArguments("Missing 'framework.serverComponents.separateSSRGraph'", .{});
return error.JSError;
};
if (prop == .true) break :brk true;
if (prop == .false) break :brk false;
global.throwInvalidArguments("'framework.serverComponents.separateSSRGraph' must be a boolean", .{});
return error.JSError;
},
.server_runtime_import = brk: {
const prop: JSValue = sc.get(global, "serverRuntimeImportSource") orelse {
if (!global.hasException())
global.throwInvalidArguments("Missing 'framework.serverComponents.serverRuntimeImportSource'", .{});
return error.JSError;
};
const str = prop.toBunString(global);
defer str.deref();
if (global.hasException())
return error.JSError;
// Leak
break :brk str.toUTF8(bun.default_allocator).slice();
},
.server_register_client_reference = brk: {
const prop: JSValue = sc.get(global, "serverRegisterClientReferenceExport") orelse {
if (!global.hasException())
global.throwInvalidArguments("Missing 'framework.serverComponents.serverRegisterClientReferenceExport'", .{});
return error.JSError;
};
const str = prop.toBunString(global);
defer str.deref();
if (global.hasException())
return error.JSError;
// Leak
break :brk str.toUTF8(bun.default_allocator).slice();
},
};
},
};
}
};
// TODO: this function leaks memory and bad error handling, but that is OK since
// this API is not finalized.
fn devServerOptionsFromJs(global: *JSC.JSGlobalObject, options: JSValue) !DevServer.Options {
if (!options.isObject()) return error.Invalid;
const routes_js = try options.getArray(global, "routes") orelse return error.Invalid;
const len = routes_js.getLength(global);
const routes = try bun.default_allocator.alloc(DevServer.Route, len);
var it = routes_js.arrayIterator(global);
var i: usize = 0;
while (it.next()) |route| : (i += 1) {
if (!route.isObject()) return error.Invalid;
const pattern_js = route.get(global, "pattern") orelse return error.Invalid;
if (!pattern_js.isString()) return error.Invalid;
const entry_point_js = route.get(global, "entrypoint") orelse return error.Invalid;
if (!entry_point_js.isString()) return error.Invalid;
const pattern = pattern_js.toBunString(global).toUTF8(bun.default_allocator);
defer pattern.deinit();
// TODO: this dupe is stupid
const pattern_z = try bun.default_allocator.dupeZ(u8, pattern.slice());
const entry_point = entry_point_js.toBunString(global).toUTF8(bun.default_allocator).slice(); // leak
routes[i] = .{
.pattern = pattern_z,
.entry_point = entry_point,
};
}
const framework_js = options.get(global, "framework") orelse {
return error.Invalid;
};
const framework = try Framework.fromJS(framework_js, global);
return .{
.cwd = bun.getcwdAlloc(bun.default_allocator) catch bun.outOfMemory(),
.routes = routes,
.framework = framework,
};
}
export fn Bun__getTemporaryDevServer(global: *JSC.JSGlobalObject) JSValue {
if (!bun.FeatureFlags.bake) return .undefined;
return JSC.JSFunction.create(global, "wipDevServer", bun.JSC.toJSHostFunction(jsWipDevServer), 0, .{});
}
pub fn wipDevServer(options: DevServer.Options) noreturn {
bun.Output.Source.configureNamedThread("Dev Server");
const dev = DevServer.init(options) catch |err| switch (err) {
error.FrameworkInitialization => bun.Global.exit(1),
else => {
bun.handleErrorReturnTrace(err, @errorReturnTrace());
bun.Output.panic("Failed to init DevServer: {}", .{err});
},
};
dev.runLoopForever();
}
pub fn getHmrRuntime(mode: Side) []const u8 {
return if (Environment.codegen_embed)
switch (mode) {
.client => @embedFile("bake-codegen/bake.client.js"),
.server => @embedFile("bake-codegen/bake.server.js"),
}
else switch (mode) {
inline else => |m| bun.runtimeEmbedFile(.codegen_eager, "bake." ++ @tagName(m) ++ ".js"),
};
}
pub const Mode = enum { production, development };
pub const Side = enum { client, server };
pub const Graph = enum(u2) {
client,
server,
/// Only used when Framework has .server_components.separate_ssr_graph set
ssr,
};
pub fn addImportMetaDefines(
allocator: std.mem.Allocator,
define: *bun.options.Define,
mode: Mode,
side: Side,
) !void {
const Define = bun.options.Define;
// The following are from Vite: https://vitejs.dev/guide/env-and-mode
// TODO: MODE, BASE_URL
try define.insert(
allocator,
"import.meta.env.DEV",
Define.Data.initBoolean(mode == .development),
);
try define.insert(
allocator,
"import.meta.env.PROD",
Define.Data.initBoolean(mode == .production),
);
try define.insert(
allocator,
"import.meta.env.SSR",
Define.Data.initBoolean(side == .server),
);
}
pub const server_virtual_source: bun.logger.Source = .{
.path = bun.fs.Path.initForKitBuiltIn("bun", "bake/server"),
.key_path = bun.fs.Path.initForKitBuiltIn("bun", "bake/server"),
.contents = "", // Virtual
.index = bun.JSAst.Index.bake_server_data,
};
pub const client_virtual_source: bun.logger.Source = .{
.path = bun.fs.Path.initForKitBuiltIn("bun", "bake/client"),
.key_path = bun.fs.Path.initForKitBuiltIn("bun", "bake/client"),
.contents = "", // Virtual
.index = bun.JSAst.Index.bake_client_data,
};
pub const DevServer = @import("./DevServer.zig");
const std = @import("std");
const bun = @import("root").bun;
const Environment = bun.Environment;
const JSC = bun.JSC;
const JSValue = JSC.JSValue;

View File

@@ -0,0 +1,41 @@
/// <reference lib="dom" />
import { use } from "react";
import { hydrateRoot } from "react-dom/client";
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
function assertionFailed(msg: string) {
throw new Error(`Assertion Failure: ${msg}. This is a bug in Bun's React integration`);
}
// Client-side entry point expects an RSC payload. In development, let's fail
// loudly if this is somehow missing.
const initialPayload = document.getElementById("rsc_payload");
if (import.meta.env.DEV) {
if (!initialPayload) assertionFailed("Missing #rsc_payload in HTML response");
}
// React takes in a ReadableStream with the payload.
let promise = createFromReadableStream(new Response(initialPayload!.innerText).body!);
initialPayload!.remove();
const Async = () => use(promise);
const root = hydrateRoot(document, <Async />, {
// handle `onUncaughtError` here
});
export async function onServerSideReload() {
const response = await fetch(location.href, {
headers: {
Accept: "text/x-component",
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
promise = createFromReadableStream(response.body!);
root.render(<Async />);
}
globalThis.onServerSideReload = onServerSideReload;

View File

@@ -0,0 +1,71 @@
import type { Bake } from "bun";
import { renderToReadableStream } from "react-server-dom-webpack/server.browser";
import { renderToHtml } from "bun-framework-rsc/ssr.tsx" with { bunBakeGraph: "ssr" };
import { serverManifest } from "bun:bake/server";
// `server.tsx` exports a function to be used for handling user routes. It takes
// in the Request object, the route's module, and extra route metadata.
export default async function (request: Request, route: any, meta: Bake.RouteMetadata): Promise<Response> {
// TODO: be able to signal to Bake that Accept may include this, so that
// static pages can be pre-rendered both as RSC payload + HTML.
// The framework generally has two rendering modes.
// - Standard browser navigation
// - Client-side navigation
//
// For React, this means we will always perform `renderToReadableStream` to
// generate the RSC payload, but only generate HTML for the former of these
// rendering modes. This is signaled by `client.tsx` via the `Accept` header.
const skipSSR = request.headers.get("Accept")?.includes("text/x-component");
const Route = route.default;
const page = (
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Bun + React Server Components</title>
{meta.styles.map(url => (
<link key={url} rel="stylesheet" href={url} />
))}
</head>
<body>
<Route />
</body>
</html>
);
// This renders Server Components to a ReadableStream "RSC Payload"
const rscPayload = renderToReadableStream(page, serverManifest);
if (skipSSR) {
return new Response(rscPayload, {
status: 200,
headers: { "Content-Type": "text/x-component" },
});
}
// One straem is used to render SSR. The second is embedded into the html for browser hydration.
// Note: This approach does not stream the response.
const [rscPayload1, rscPayload2] = rscPayload.tee();
const rscPayloadBuffer = Bun.readableStreamToText(rscPayload1);
const rw = new HTMLRewriter();
rw.on("body", {
element(element) {
element.onEndTag(async end => {
end.before(
`<script id="rsc_payload" type="json">${await rscPayloadBuffer}</script>` +
meta.scripts.map(url => `<script src=${JSON.stringify(url)}></script>`).join(""),
{ html: true },
);
});
},
});
// TODO: readableStreamToText is needed due to https://github.com/oven-sh/bun/issues/14216
const output = await Bun.readableStreamToText(await renderToHtml(rscPayload2));
return rw.transform(
new Response(output, {
headers: {
"Content-Type": "text/html; charset=utf8",
},
}),
);
}

View File

@@ -0,0 +1,16 @@
// This file is loaded in the SSR graph, meaning the `react-server` condition is
// no longer set. This means we can import client components, using `react-dom`
// to perform SSR from the RSC payload.
import { use } from "react";
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
import { renderToReadableStream } from "react-dom/server";
import { clientManifest } from "bun:bake/server";
export function renderToHtml(rscPayload: ReadableStream): Promise<ReadableStream> {
const promise = createFromReadableStream(rscPayload, {
moduleMap: clientManifest,
moduleLoading: { prefix: "" },
});
const Async = () => use(promise);
return renderToReadableStream(<Async />);
}

View File

@@ -0,0 +1,82 @@
// This implements error deserialization from the WebSocket protocol
import { BundlerMessageLevel } from "../enums";
import { DataViewReader } from "./reader";
export interface DeserializedFailure {
// If not specified, it is a client-side error.
file: string | null;
messages: BundlerMessage[];
};
export interface BundlerMessage {
kind: "bundler";
level: BundlerMessageLevel;
message: string;
location: BundlerMessageLocation | null;
notes: BundlerNote[];
}
export interface BundlerMessageLocation {
/** One-based */
line: number;
/** One-based */
column: number;
/** Byte length */
length: number;
lineText: string;
}
export interface BundlerNote {
message: string;
location: BundlerMessageLocation | null;
}
export function decodeSerializedError(reader: DataViewReader) {
const kind = reader.u8();
if (kind >= 0 && kind <= 4) {
return readLogMsg(reader, kind);
} else {
throw new Error("TODO: JS Errors");
}
}
/** First byte is already read in. */
function readLogMsg(r: DataViewReader, level: BundlerMessageLevel) {
const message = r.string32();
const location = readBundlerMessageLocationOrNull(r);
const noteCount = r.u32();
const notes = new Array(noteCount);
for (let i = 0; i < noteCount; i++) {
notes[i] = readLogData(r);
}
return {
kind: 'bundler',
level,
message,
location,
notes,
};
}
function readLogData(r: DataViewReader): BundlerNote | null {
return {
message: r.string32(),
location: readBundlerMessageLocationOrNull(r),
};
}
function readBundlerMessageLocationOrNull(r: DataViewReader): BundlerMessageLocation | null {
const line = r.u32();
if (line == 0) return null;
const column = r.u32();
const length = r.u32();
const lineText = r.string32();
return {
line,
column,
length,
lineText,
};
}

View File

176
src/bake/client/overlay.css Normal file
View File

@@ -0,0 +1,176 @@
/*
* This file is mounted within Shadow DOM so interference with
* the user's application causes no issue. This sheet is used to
* style error popups and other elements provided by DevServer.
*/
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.root {
color-scheme: light dark;
--modal-bg: light-dark(#efefef, #202020);
--modal-text: light-dark(#0a0a0a, #fafafa);
--modal-text-faded: light-dark(#0a0a0a88, #fafafa88);
--item-bg: light-dark(#d4d4d4, #0f0f0f);
--item-bg-hover: light-dark(#cccccc, #171717);
--red: #ff5858;
--log-error: light-dark(#dc0000, #ff5858);
--log-warn: light-dark(#eab308, #fbbf24);
--log-note: light-dark(#008ae6, #22d3ee);
--log-colon: light-dark(#888, #888);
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
code,
.file-name,
.message {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.modal {
color: var(--modal-text);
background-color: var(--modal-bg);
border-top: 8px solid var(--red);
border-radius: 8px;
margin: 4rem 2rem 2rem 2rem;
max-width: 940px;
width: 100%;
box-shadow:
0 2px 6px #0004,
0 2px 32px #0003;
}
header {
margin: 1rem 1rem;
color: var(--red);
font-size: 2rem;
font-weight: bold;
}
footer {
color: var(--modal-text-faded);
margin: 1rem;
}
pre {
font: unset;
}
.message-group {
display: flex;
flex-direction: column;
background-color: var(--item-bg);
}
/* this is a <button> */
.file-name {
appearance: none;
background-color: transparent;
border: none;
font-size: unset;
font-weight: bold;
padding: 0.5rem 1rem;
text-align: left;
cursor: pointer;
}
/* .file-name:hover,
.file-name:focus-visible {
background-color: var(--item-bg-hover);
}
.file-name::after {
color: var(--modal-text-faded);
font-size: 70%;
}
.file-name:hover::after {
content: " (click to open in editor)";
} */
.message {
margin: 1rem;
margin-bottom: 0;
}
button+.message {
margin-top: 0.5rem;
}
.message-text>span {
color: var(--color);
}
.log-error {
--color: var(--log-error);
font-weight: bold;
}
.log-warn {
--color: var(--log-warn);
}
.log-note {
--color: var(--log-note);
}
.log-colon {
--color: var(--log-colon);
}
.code-line {
display: flex;
margin: 0.5rem 0;
}
.line-num {
color: var(--modal-text-faded);
margin-right: 10px;
}
.highlight-wrap {
color: transparent;
user-select: none;
pointer-events: none;
transform: translateY(-20px);
margin-bottom: -5px;
}
.highlight-wrap .line {
margin-left: 10px;
text-decoration: underline;
text-decoration-style: wavy;
text-decoration-color: var(--color);
}
@media (prefers-color-scheme: light) {
.log-warn,
.log-note {
font-weight: bold;
}
}

252
src/bake/client/overlay.ts Normal file
View File

@@ -0,0 +1,252 @@
// This file implements the UI for error modals. Since using a framework like
// React could collide with the user's code (consider React DevTools), this
// entire modal is written from scratch using the standard DOM APIs. All CSS is
// scoped in `overlay.css`, and all elements exist under a shadow root. These
// constraints make the overlay simple to understand and work on.
//
// This file has two consumers:
// - The bundler error page which embeds a list of bundler errors to render.
// - The client runtime, for when reloading errors happen.
// Both use a WebSocket to coordinate followup updates, when new errors are
// added or previous ones are solved.
import { BundlerMessageLevel } from "../enums";
import { css } from "../macros" with { type: "macro" };
import { BundlerMessage, BundlerMessageLocation, BundlerNote, decodeSerializedError, type DeserializedFailure } from "./error-serialization";
import { DataViewReader } from "./reader";
if (side !== "client") throw new Error("Not client side!");
// I would have used JSX, but TypeScript types interfere in odd ways.
function elem(tagName: string, props?: null | Record<string, string>, children?: (HTMLElement | Text)[]) {
const node = document.createElement(tagName);
if (props)
for (let key in props) {
node.setAttribute(key, props[key]);
}
if (children)
for (const child of children) {
node.appendChild(child);
}
return node;
}
function elemText(tagName: string, props: null | Record<string, string>, innerHTML: string) {
const node = document.createElement(tagName);
if (props)
for (let key in props) {
node.setAttribute(key, props[key]);
}
node.textContent = innerHTML;
return node;
}
const textNode = (str = "") => document.createTextNode(str);
/**
* 32-bit integer corresponding to `SerializedFailure.Owner.Packed`
* It is never decoded client-side; treat this as an opaque identifier.
*/
type ErrorId = number;
const errors = new Map<ErrorId, DeserializedFailure>();
const errorDoms = new Map<ErrorId, ErrorDomNodes>();
const updatedErrorOwners = new Set<ErrorId>();
let domShadowRoot: HTMLElement;
let domModalTitle: Text;
let domErrorList: HTMLElement;
interface ErrorDomNodes {
root: HTMLElement;
title: Text;
messages: HTMLElement[];
}
/**
* Initial mount is done lazily. The modal starts invisible, controlled
* by `setModalVisible`.
*/
function mountModal() {
if (domModalTitle) return;
domShadowRoot = elem("bun-hmr", {
style:
"position:absolute!important;" +
"display:none!important;" +
"top:0!important;" +
"left:0!important;" +
"width:100%!important;" +
"height:100%!important;" +
"background:#8883!important",
});
const shadow = domShadowRoot.attachShadow({ mode: "open" });
const sheet = new CSSStyleSheet();
sheet.replace(css("client/overlay.css", IS_BUN_DEVELOPMENT));
shadow.adoptedStyleSheets = [sheet];
const root = elem("div", { class: "root" }, [
elem("div", { class: "modal" }, [
elem("header", null, [(domModalTitle = textNode())]),
(domErrorList = elem("div", { class: "error-list" })),
elem("footer", null, [
// TODO: for HMR turn this into a clickable thing + say it can be dismissed
textNode("Errors during a build can only be dismissed fixing them."),
]),
]),
]);
shadow.appendChild(root);
document.body.appendChild(domShadowRoot);
}
let isModalVisible = false;
function setModalVisible(visible: boolean) {
if (isModalVisible === visible || !domShadowRoot) return;
isModalVisible = visible;
domShadowRoot.style.display = visible ? "block" : "none";
}
/** Handler for `MessageId.errors` websocket packet */
export function onErrorMessage(view: DataView) {
const reader = new DataViewReader(view, 1);
const removedCount = reader.u32();
for (let i = 0; i < removedCount; i++) {
const removed = reader.u32();
updatedErrorOwners.add(removed);
errors.delete(removed);
}
while (reader.hasMoreData()) {
decodeAndAppendError(reader);
}
updateErrorOverlay();
}
export function onErrorClearedMessage() {
errors.keys().forEach(key => updatedErrorOwners.add(key));
errors.clear();
updateErrorOverlay();
}
/**
* Call this for each error, then call `updateErrorOverlay` to commit the
* changes to the UI in one smooth motion.
*/
export function decodeAndAppendError(r: DataViewReader) {
const owner = r.u32();
const file = r.string32() || null;
const messageCount = r.u32();
const messages = new Array(messageCount);
for (let i = 0; i < messageCount; i++) {
messages[i] = decodeSerializedError(r);
}
errors.set(owner, { file, messages });
updatedErrorOwners.add(owner);
}
export function updateErrorOverlay() {
console.log(errors, updatedErrorOwners);
if (errors.size === 0) {
setModalVisible(false);
return;
}
mountModal();
let totalCount = 0;
for (const owner of updatedErrorOwners) {
const data = errors.get(owner);
let dom = errorDoms.get(owner);
// If this failure was removed, delete it.
if (!data) {
dom?.root.remove();
errorDoms.delete(owner);
continue;
}
totalCount += data.messages.length;
// Create the element for the root if it does not yet exist.
if (!dom) {
let title;
const root = elem("div", { class: "message-group" }, [
elem("button", { class: "file-name" }, [
title = textNode()
]),
]);
dom = { root, title, messages: [] };
// TODO: sorted insert?
domErrorList.appendChild(root);
errorDoms.set(owner, dom);
} else {
// For simplicity, messages are not reused, even if left unchanged.
dom.messages.forEach(msg => msg.remove());
}
// Update the DOM with the new data.
dom.title.textContent = data.file;
for (const msg of data.messages) {
const domMessage = renderBundlerMessage(msg);
dom.root.appendChild(domMessage);
dom.messages.push(domMessage);
}
}
domModalTitle.textContent = `${errors.size} Build Error${errors.size !== 1 ? "s" : ""}`;
updatedErrorOwners.clear();
setModalVisible(true);
}
const bundleLogLevelToName = [
"error",
"warn",
"note",
"debug",
"verbose",
];
function renderBundlerMessage(msg: BundlerMessage) {
return elem('div', { class: 'message' }, [
renderErrorMessageLine(msg.level, msg.message),
...msg.location ? renderCodeLine(msg.location, msg.level) : [],
...msg.notes.map(renderNote),
].flat(1));
}
function renderErrorMessageLine(level: BundlerMessageLevel, text: string) {
const levelName = bundleLogLevelToName[level];
if(IS_BUN_DEVELOPMENT && !levelName) {
throw new Error("Unknown log level: " + level);
}
return elem('div', { class: 'message-text' } , [
elemText('span', { class: 'log-' + levelName }, levelName),
elemText('span', { class: 'log-colon' }, ': '),
elemText('span', { class: 'log-text' }, text),
]);
}
function renderCodeLine(location: BundlerMessageLocation, level: BundlerMessageLevel) {
return [
elem('div', { class: 'code-line' }, [
elemText('code', { class: 'line-num' }, `${location.line}`),
elemText('pre', { class: 'code-view' }, location.lineText),
]),
elem('div', { class: 'highlight-wrap log-' + bundleLogLevelToName[level] }, [
elemText('span', { class: 'space' }, '_'.repeat(`${location.line}`.length + location.column - 1)),
elemText('span', { class: 'line' }, '_'.repeat(location.length)),
])
];
}
function renderNote(note: BundlerNote) {
return [
renderErrorMessageLine(BundlerMessageLevel.note, note.message),
...note.location ? renderCodeLine(note.location, BundlerMessageLevel.note) : [],
];
}

43
src/bake/client/reader.ts Normal file
View File

@@ -0,0 +1,43 @@
import { td } from "../shared";
export class DataViewReader {
view: DataView;
cursor: number;
constructor(view: DataView, cursor: number = 0) {
this.view = view;
this.cursor = cursor;
}
u32() {
const value = this.view.getUint32(this.cursor, true);
this.cursor += 4;
return value;
}
u16() {
const value = this.view.getUint16(this.cursor, true);
this.cursor += 2;
return value;
}
u8() {
const value = this.view.getUint8(this.cursor);
this.cursor += 1;
return value;
}
stringWithLength(byteLength: number) {
const str = td.decode(this.view.buffer.slice(this.cursor, this.cursor + byteLength));
this.cursor += byteLength;
return str;
}
string32() {
return this.stringWithLength(this.u32());
}
hasMoreData() {
return this.cursor < this.view.byteLength;
}
}

6
src/bake/client/route.ts Normal file
View File

@@ -0,0 +1,6 @@
export function routeMatch(routeId: number, routePattern: string) {
console.log(`routeMatch(${routeId}, ${routePattern})`);
// TODO: pattern parsing
// TODO: use routeId to cache the current route to avoid reparsing text we dont care about
return routePattern === location.pathname;
}

View File

@@ -0,0 +1,85 @@
const isLocal = location.host === "localhost" || location.host === "127.0.0.1";
function wait() {
return new Promise<void>(done => {
let timer;
const onTimeout = () => {
if (timer !== null) clearTimeout(timer);
document.removeEventListener("focus", onTimeout);
done();
};
document.addEventListener("focus", onTimeout);
timer = setTimeout(
() => {
timer = null;
onTimeout();
},
isLocal ? 2_500 : 30_000,
);
});
}
export function initWebSocket(handlers: Record<number, (dv: DataView) => void>) {
let firstConnection = true;
function onOpen() {
if (firstConnection) {
firstConnection = false;
console.info("[Bun] Hot-module-reloading socket connected, waiting for changes...");
}
}
function onMessage(ev: MessageEvent<string | ArrayBuffer>) {
const { data } = ev;
if (typeof data === "object") {
const view = new DataView(data);
if (IS_BUN_DEVELOPMENT) {
console.info("[WS] " + String.fromCharCode(view.getUint8(0)));
}
handlers[view.getUint8(0)]?.(view);
}
}
function onError(ev: Event) {
console.error(ev);
}
async function onClose() {
console.warn("[Bun] Hot-module-reloading socket disconnected, reconnecting...");
while (true) {
await wait();
// Note: Cannot use Promise.withResolvers due to lacking support on iOS
let done;
const promise = new Promise<boolean>(cb => (done = cb));
ws = new WebSocket("/_bun/hmr");
ws.binaryType = "arraybuffer";
ws.onopen = () => {
console.info("[Bun] Reconnected");
done(true);
onOpen();
ws.onerror = onError;
};
ws.onmessage = onMessage;
ws.onerror = ev => {
onError(ev);
done(false);
};
if (await promise) {
break;
}
}
}
let ws = new WebSocket("/_bun/hmr");
ws.binaryType = "arraybuffer";
ws.onopen = onOpen;
ws.onmessage = onMessage;
ws.onclose = onClose;
ws.onerror = onError;
}

26
src/bake/enums.ts Normal file
View File

@@ -0,0 +1,26 @@
// TODO: generate this using information in DevServer.zig
export const enum MessageId {
/// Version packet
version = 86,
/// When visualization mode is enabled, this packet contains
/// the entire serialized IncrementalGraph state.
visualizer = 118,
/// Sent on a successful bundle, containing client code.
hot_update = 40,
/// Sent on a successful bundle, containing a list of
/// routes that are updated.
route_update = 82,
/// Sent when the list of errors changes.
errors = 69,
/// Sent when all errors are cleared. Semi-redundant
errors_cleared = 99,
}
export const enum BundlerMessageLevel {
err = 0,
warn = 1,
note = 2,
debug = 3,
verbose = 4,
}

185
src/bake/hmr-module.ts Normal file
View File

@@ -0,0 +1,185 @@
import * as runtimeHelpers from "../runtime.bun.js";
let refreshRuntime: any;
const registry = new Map<Id, HotModule>();
export type ModuleLoadFunction = (module: HotModule) => void;
export type ExportsCallbackFunction = (new_exports: any) => void;
export const enum State {
Loading,
Boundary,
Error,
}
export const enum LoadModuleType {
AssertPresent,
UserDynamic,
}
/**
* This object is passed as the CommonJS "module", but has a bunch of
* non-standard properties that are used for implementing hot-module reloading.
* It is unacceptable for users to depend on these properties, and it will not
* be considered a breaking change when these internals are altered.
*/
export class HotModule<E = any> {
id: Id;
exports: E = {} as E;
_state = State.Loading;
_ext_exports = undefined;
__esModule = false;
_import_meta: ImportMeta | undefined = undefined;
_cached_failure: any = undefined;
// modules that import THIS module
_deps: Map<HotModule, ExportsCallbackFunction | undefined> = new Map();
constructor(id: Id) {
this.id = id;
}
require(id: Id, onReload?: ExportsCallbackFunction) {
const mod = loadModule(id, LoadModuleType.UserDynamic);
mod._deps.set(this, onReload);
return mod.exports;
}
importSync(id: Id, onReload?: ExportsCallbackFunction) {
const mod = loadModule(id, LoadModuleType.AssertPresent);
// insert into the map if not present
mod._deps.set(this, onReload);
const { exports, __esModule } = mod;
return __esModule ? exports : (mod._ext_exports ??= { ...exports, default: exports });
}
async dynamicImport(specifier: string, opts?: ImportCallOptions) {
const mod = loadModule(specifier, LoadModuleType.UserDynamic);
// insert into the map if not present
mod._deps.set(this, mod._deps.get(this));
const { exports, __esModule } = mod;
return __esModule ? exports : (mod._ext_exports ??= { ...exports, default: exports });
}
importMeta() {
return (this._import_meta ??= initImportMeta(this));
}
/** Server-only */
declare importBuiltin: (id: string) => any;
}
if (side === "server") {
HotModule.prototype.importBuiltin = function (id: string) {
return import.meta.require(id);
};
}
function initImportMeta(m: HotModule): ImportMeta {
throw new Error("TODO: import meta object");
}
/**
* Load a module by ID. Use `type` to specify if the module is supposed to be
* present, or is something a user is able to dynamically specify.
*/
export function loadModule<T = any>(key: Id, type: LoadModuleType): HotModule<T> {
let module = registry.get(key);
if (module) {
// Preserve failures until they are re-saved.
if (module._state == State.Error) throw module._cached_failure;
return module;
}
module = new HotModule(key);
const load = input_graph[key];
if (!load) {
if (type == LoadModuleType.AssertPresent) {
throw new Error(
`Failed to load bundled module '${key}'. This is not a dynamic import, and therefore is a bug in Bun Kit's bundler.`,
);
} else {
throw new Error(
`Failed to resolve dynamic import '${key}'. In Bun Kit, all imports must be statically known at compile time so that the bundler can trace everything.`,
);
}
}
try {
registry.set(key, module);
load(module);
} catch (err) {
module._cached_failure = err;
module._state = State.Error;
throw err;
}
return module;
}
export const getModule = registry.get.bind(registry);
export function replaceModule(key: Id, load: ModuleLoadFunction) {
const module = registry.get(key);
if (module) {
module.exports = {};
load(module);
const { exports } = module;
for (const updater of module._deps.values()) {
updater?.(exports);
}
}
}
export function replaceModules(modules: any) {
for (const k in modules) {
input_graph[k] = modules[k];
}
for (const k in modules) {
try {
replaceModule(k, modules[k]);
} catch (err) {
// TODO: overlay for client
console.error(err);
}
}
if (side === "client" && refreshRuntime) {
refreshRuntime.performReactRefresh(window);
}
}
{
const runtime = new HotModule("bun:wrap");
runtime.exports = runtimeHelpers;
runtime.__esModule = true;
registry.set("bun:wrap", runtime);
}
export const serverManifest = {};
export const clientManifest = {};
if (side === "server") {
const server_module = new HotModule("bun:bake/server");
server_module.__esModule = true;
server_module.exports = { serverManifest, clientManifest };
registry.set(server_module.id, server_module);
}
if (side === "client") {
const { refresh } = config;
if (refresh) {
refreshRuntime = loadModule(refresh, LoadModuleType.AssertPresent).exports;
refreshRuntime.injectIntoGlobalHook(window);
}
}
// TODO: Remove this after `react-server-dom-bun` is uploaded
globalThis.__webpack_require__ = (id: string) => {
if (side == "server" && config.separateSSRGraph && !id.startsWith("ssr:")) {
return loadModule("ssr:" + id, LoadModuleType.UserDynamic).exports;
} else {
return loadModule(id, LoadModuleType.UserDynamic).exports;
}
};
runtimeHelpers.__name(HotModule.prototype.importSync, "<HMR runtime> importSync");
runtimeHelpers.__name(HotModule.prototype.require, "<HMR runtime> require");
runtimeHelpers.__name(loadModule, "<HMR runtime> loadModule");

75
src/bake/hmr-protocol.md Normal file
View File

@@ -0,0 +1,75 @@
# Kit's WebSocket Protocol
This format is only intended for communication for the browser build of
`hmr-runtime.ts` <-> `DevServer.zig`. Server-side HMR is implemented using a
different interface. This document is aimed for contributors to these
two components; Any other use-case is unsupported.
Every message is to use `.binary`/`ArrayBuffer` transport mode. The first byte
indicates a Message ID, with the length being inferred by the payload size.
All integers are in little-endian
## Client->Server messages
### `v`
Subscribe to visualizer packets (`v`)
## Server->Client messages
### `V`
Version payload. Sent on connection startup. The client should issue a hard-reload
when it does not match the embedded version.
Example:
```
V1.1.30-canary.37+117e1b388
```
### `(`
Hot-module-reloading patch. The entire payload is UTF-8 Encoded JavaScript Payload.
### `R` - Route reload request
Server-side code has reloaded. Client should either refetch the route or perform a hard reload.
- `u32`: Number of updated routes
- For each route:
- `u32`: Route ID
- `u16`: Length of route name.
- `[n]u8`: Route name in UTF-8 encoded text.
### `e` - Error status update
- `u32`: Number of errors removed
- For each removed error:
- `u32` Error owner
- Remainder of payload is repeating each error object:
- `u32` Error owner
- Error Payload
### `v`
Payload for `incremental_visualizer.html`. This can be accessed via `/_bun/incremental_visualizer`.
- `u32`: Number of files in client graph
- For each file in client graph
- `u32`: Length of name. If zero then no other fields are provided.
- `[n]u8`: File path in UTF-8 encoded text
- `u8`: If file is stale, set 1
- `u8`: If file is in server graph, set 1
- `u8`: If file is in ssr graph, set 1
- `u8`: If file is a server-side route root, set 1
- `u8`: If file is a server-side component boundary file, set 1
- `u32`: Number of files in the server graph
- For each file in server graph, repeat the same parser for the clienr graph
- `u32`: Number of client edges. For each,
- `u32`: File index of the dependency file
- `u32`: File index of the imported file
- `u32`: Number of server edges. For each,
- `u32`: File index of the dependency file
- `u32`: File index of the imported file

View File

@@ -0,0 +1,78 @@
// This file is the entrypoint to the hot-module-reloading runtime
// In the browser, this uses a WebSocket to communicate with the bundler.
import { loadModule, LoadModuleType, replaceModules } from "./hmr-module";
import { onErrorClearedMessage, onErrorMessage } from "./client/overlay";
import { Bake } from "bun";
import { td } from "./shared";
import { DataViewReader } from "./client/reader";
import { routeMatch } from "./client/route";
import { initWebSocket } from "./client/websocket";
import { MessageId } from "./enums";
if (typeof IS_BUN_DEVELOPMENT !== "boolean") {
throw new Error("DCE is configured incorrectly");
}
async function performRouteReload() {
console.info("[Bun] Server-side code changed, reloading!");
if (onServerSideReload) {
try {
await onServerSideReload();
return;
} catch (err) {
console.error("Failed to perform Server-side reload.");
console.error(err);
console.error("The page will hard-reload now.");
if (IS_BUN_DEVELOPMENT) {
// return showErrorOverlay(err);
}
}
}
// Fallback for when reloading fails or is not implemented by the framework is
// to hard-reload.
location.reload();
}
let main;
try {
main = loadModule<Bake.ClientEntryPoint>(config.main, LoadModuleType.AssertPresent);
var { onServerSideReload, ...rest } = main.exports;
if (Object.keys(rest).length > 0) {
console.warn(
`Framework client entry point (${config.main}) exported unknown properties, found: ${Object.keys(rest).join(", ")}`,
);
}
} catch (e) {
// showErrorOverlay(e);
console.error(e);
}
initWebSocket({
[MessageId.version](view) {
// TODO: config.version and verify everything is sane
console.log("VERSION: ", td.decode(view.buffer.slice(1)));
},
[MessageId.hot_update](view) {
const code = td.decode(view.buffer);
const modules = (0, eval)(code);
replaceModules(modules);
},
[MessageId.errors]: onErrorMessage,
[MessageId.errors_cleared]: onErrorClearedMessage,
[MessageId.route_update](view) {
const reader = new DataViewReader(view, 1);
let routeCount = reader.u32();
while (routeCount > 0) {
routeCount -= 1;
const routeId = reader.u32();
const routePattern = reader.stringWithLength(reader.u16());
if (routeMatch(routeId, routePattern)) {
performRouteReload();
break;
}
}
},
});

View File

@@ -0,0 +1,60 @@
// When a bundling error happens, we cannot load any of the users code, since
// that code expects the SSR step to succeed. This version of client just opens
// a websocket and listens only for error resolution events, and reloads the
// page.
//
// This is embedded in `DevServer.sendSerializedFailures`. SSR is
// left unused for simplicity; a flash of unstyled content is
// stopped by the fact this script runs synchronously.
import { decodeAndAppendError, onErrorMessage, updateErrorOverlay } from "./client/overlay";
import { DataViewReader } from "./client/reader";
import { routeMatch } from "./client/route";
import { initWebSocket } from "./client/websocket";
import { MessageId } from "./enums";
/** Injected by DevServer */
declare const error: Uint8Array;
{
const reader = new DataViewReader(new DataView(error.buffer), 0);
while (reader.hasMoreData()) {
decodeAndAppendError(reader);
}
updateErrorOverlay();
}
let firstVersionPacket = true;
initWebSocket({
[MessageId.version](dv) {
if (firstVersionPacket) {
firstVersionPacket = false;
} else {
// On re-connection, the server may have restarted. The route that was
// requested could be in unqueued state. A reload is the only way to
// ensure this bundle is enqueued.
location.reload();
}
},
[MessageId.errors]: onErrorMessage,
[MessageId.route_update](view) {
const reader = new DataViewReader(view, 1);
let routeCount = reader.u32();
while (routeCount > 0) {
routeCount -= 1;
const routeId = reader.u32();
const routePattern = reader.stringWithLength(reader.u16());
if (routeMatch(routeId, routePattern)) {
location.reload();
break;
}
}
},
[MessageId.errors_cleared]() {
location.reload();
},
});

View File

@@ -0,0 +1,68 @@
// This file is the entrypoint to the hot-module-reloading runtime.
// On the server, communication is facilitated using the default
// export, which is assigned via `server_exports`.
import type { Bake } from "bun";
import { loadModule, LoadModuleType, replaceModules, clientManifest, serverManifest, getModule } from "./hmr-module";
if (typeof IS_BUN_DEVELOPMENT !== "boolean") {
throw new Error("DCE is configured incorrectly");
}
// Server Side
server_exports = {
async handleRequest(req, { clientEntryPoint }, requested_id) {
const serverRenderer = loadModule<Bake.ServerEntryPoint>(config.main, LoadModuleType.AssertPresent).exports.default;
if (!serverRenderer) {
throw new Error('Framework server entrypoint is missing a "default" export.');
}
if (typeof serverRenderer !== "function") {
throw new Error('Framework server entrypoint\'s "default" export is not a function.');
}
const response = await serverRenderer(req, loadModule(requested_id, LoadModuleType.AssertPresent).exports, {
styles: [],
scripts: [clientEntryPoint],
});
if (!(response instanceof Response)) {
throw new Error(`Server-side request handler was expected to return a Response object.`);
}
// TODO: support streaming
return await response.text();
},
registerUpdate(modules, componentManifestAdd, componentManifestDelete) {
replaceModules(modules);
if (componentManifestAdd) {
for (const uid of componentManifestAdd) {
try {
const mod = loadModule(uid, LoadModuleType.AssertPresent);
const { exports, __esModule } = mod;
const exp = __esModule ? exports : (mod._ext_exports ??= { ...exports, default: exports });
for (const exportName of Object.keys(exp)) {
serverManifest[uid] = {
id: uid,
name: exportName,
chunks: [],
};
}
} catch (err) {
console.log(err);
}
}
}
if (componentManifestDelete) {
for (const fileName of componentManifestDelete) {
const client = clientManifest[fileName];
for (const exportName in client) {
delete serverManifest[`${fileName}#${exportName}`];
}
delete clientManifest[fileName];
}
}
},
};

View File

@@ -0,0 +1,345 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>IncrementalGraph Visualization</title>
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<style>
html,
body {
background-color: #1e1e2e;
color: #cdd6f4;
font-family: sans-serif;
}
#network {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
}
h1 {
position: fixed;
top: 1rem;
left: 1rem;
pointer-events: none;
font-size: 1rem;
margin: 0;
z-index: 100;
}
#stat {
font-weight: normal;
}
</style>
</head>
<body>
<h1>IncrementalGraph Visualization <span id="stat"></span></h1>
<div id="network"></div>
<script>
// Connect to HMR WebSocket and enable visualization packets. This
// serializes the both `IncrementalGraph`s in full and sends them
// over the wire. A visualization is provided by `vis.js`. Support
//
// Script written partially by ChatGPT
const c = {
// Derived from mocha theme on https://catppuccin.com/palette
red: "#f38ba8",
green: "#a6e3a1",
mauve: "#cba6f7",
gray: "#7f849c",
orange: "#fab387",
sky: "#89dceb",
blue: "#89b4fa",
yellow: "#f9e2af",
};
const ws = new WebSocket(location.origin + "/_bun/hmr");
ws.binaryType = "arraybuffer"; // We are expecting binary data
ws.onopen = function () {
ws.send(new Uint8Array([118])); // Send 'v' byte to initiate connection
};
// Store nodes and edges
let clientFiles = [];
let serverFiles = [];
let clientEdges = [];
let serverEdges = [];
let currentEdgeIds = new Set();
let currentNodeIds = new Set();
let isFirst = true;
// When a message is received
ws.onmessage = function (event) {
const buffer = new Uint8Array(event.data);
// Only process messages starting with 'v' (ASCII code 118)
if (buffer[0] !== 118) return;
console.log("Got Event");
let offset = 1; // Skip the 'v' byte
// Parse client files
const clientFileCount = readUint32(buffer, offset);
offset += 4;
clientFiles = parseFiles(buffer, clientFileCount, offset);
offset = clientFiles.offset;
clientFiles = clientFiles.files;
// Parse server files
const serverFileCount = readUint32(buffer, offset);
offset += 4;
serverFiles = parseFiles(buffer, serverFileCount, offset);
offset = serverFiles.offset;
serverFiles = serverFiles.files;
// Parse client edges
const clientEdgeCount = readUint32(buffer, offset);
offset += 4;
clientEdges = parseEdges(buffer, clientEdgeCount, offset);
offset = clientEdges.offset;
clientEdges = clientEdges.edges;
// Parse server edges
const serverEdgeCount = readUint32(buffer, offset);
offset += 4;
serverEdges = parseEdges(buffer, serverEdgeCount, offset);
offset = serverEdges.offset;
serverEdges = serverEdges.edges;
// Update the graph visualization
updateGraph();
};
// Helper to read 4-byte unsigned int
function readUint32(buffer, offset) {
return buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24);
}
function basename(path) {
return path.slice(path.lastIndexOf("/") + 1);
}
// Parse the files from the buffer
function parseFiles(buffer, count, offset) {
const files = [];
for (let i = 0; i < count; i++) {
const nameLength = readUint32(buffer, offset);
offset += 4;
// If the name length is 0, it's a deleted file
if (nameLength === 0) {
files.push({ id: i, deleted: true });
continue;
}
const nameBytes = buffer.slice(offset, offset + nameLength);
const name = new TextDecoder().decode(nameBytes);
offset += nameLength;
const isStale = buffer[offset++] === 1;
const isServer = buffer[offset++] === 1;
const isSSR = buffer[offset++] === 1;
const isRoute = buffer[offset++] === 1;
const isFramework = buffer[offset++] === 1;
const isBoundary = buffer[offset++] === 1;
files.push({
id: i,
name,
isStale,
isServer,
isSSR,
isRoute,
isFramework,
isBoundary,
});
}
return { files, offset };
}
// Parse the edges from the buffer
function parseEdges(buffer, count, offset) {
const edges = [];
for (let i = 0; i < count; i++) {
const from = readUint32(buffer, offset);
offset += 4;
const to = readUint32(buffer, offset);
offset += 4;
edges.push({ from, to });
}
return { edges, offset };
}
// Initialize Vis.js network
const nodes = new vis.DataSet();
const edges = new vis.DataSet();
const container = document.getElementById("network");
const data = { nodes, edges };
const options = {};
const network = new vis.Network(container, data, options);
// Helper function to add or update nodes in the graph
function updateNode(id, file, group) {
const label = basename(file.name);
const color = file.name.includes("/node_modules/")
? c.gray
: file.isStale
? c.red
: file.isBoundary
? c.orange
: group === "client"
? c.mauve
: file.isRoute
? c.blue
: file.isSSR
? file.isServer
? c.yellow
: c.green
: c.sky;
const props = {
id,
label,
shape: "dot",
color: color,
borderWidth: file.isRoute ? 3 : 1,
group,
font: file.name.includes("/node_modules/") ? "10px sans-serif #cdd6f488" : "20px sans-serif #cdd6f4",
};
if (nodes.get(id)) {
nodes.update(props);
} else {
nodes.add(props);
}
}
// Helper function to remove a node by ID
function removeNode(id) {
nodes.remove({ id });
}
// Helper function to add or update edges in the graph
const edgeProps = { arrows: "to" };
function updateEdge(id, from, to, variant) {
const prop =
variant === "normal"
? { id, from, to, arrows: "to" }
: variant === "client"
? { id, from, to, arrows: "to,from", color: "#ffffff99", width: 2, label: "[use client]" }
: { id, from, to };
if (edges.get(id)) {
edges.update(prop);
} else {
edges.add(prop);
}
}
// Helper to remove all edges of a node
function removeEdges(nodeId) {
const edgesToRemove = edges.get({
filter: edge => edge.from === nodeId || edge.to === nodeId,
});
edges.remove(edgesToRemove.map(e => e.id));
}
// Function to update the entire graph when new data is received
function updateGraph() {
const newEdgeIds = new Set(); // Track new edges
const newNodeIds = new Set(); // Track new nodes
const boundaries = new Map();
// Update server files
serverFiles.forEach((file, index) => {
const id = `S_${file.name}`;
if (file.deleted) {
removeNode(id);
removeEdges(id);
} else {
updateNode(id, file, "server");
}
if (file.isBoundary) {
boundaries.set(file.name, { server: index, client: -1 });
}
newNodeIds.add(id); // Track this node
});
// Update client files
clientFiles.forEach((file, index) => {
const id = `C_${file.name}`;
if (file.deleted) {
removeNode(id);
removeEdges(id);
return;
}
updateNode(id, file, "client");
const b = boundaries.get(file.name);
if (b) {
b.client = index;
}
newNodeIds.add(id); // Track this node
});
// Update client edges
clientEdges.forEach((edge, index) => {
const id = `C_edge_${index}`;
updateEdge(id, `C_${clientFiles[edge.from].name}`, `C_${clientFiles[edge.to].name}`, "normal");
newEdgeIds.add(id); // Track this edge
});
// Update server edges
serverEdges.forEach((edge, index) => {
const id = `S_edge_${index}`;
updateEdge(id, `S_${serverFiles[edge.from].name}`, `S_${serverFiles[edge.to].name}`, "normal");
newEdgeIds.add(id); // Track this edge
});
boundaries.forEach(({ server, client }) => {
if (client === -1) return;
const id = `S_edge_bound_${server}_${client}`;
updateEdge(id, `S_${serverFiles[server].name}`, `C_${clientFiles[client].name}`, "client");
newEdgeIds.add(id); // Track this edge
});
// Remove edges that are no longer present
currentEdgeIds.forEach(id => {
if (!newEdgeIds.has(id)) {
edges.remove(id);
}
});
// Remove nodes that are no longer present
currentNodeIds.forEach(id => {
if (!newNodeIds.has(id)) {
nodes.remove(id);
}
});
// Update the currentEdgeIds set to the new one
currentEdgeIds = newEdgeIds;
currentNodeIds = newNodeIds;
if (isFirst) {
network.stabilize();
isFirst = false;
}
document.getElementById("stat").innerText =
`(server: ${serverFiles.length} files, ${serverEdges.length} edges; client: ${clientFiles.length} files, ${clientEdges.length} edges; ${boundaries.size} boundaries)`;
}
</script>
</body>
</html>

16
src/bake/macros.ts Normal file
View File

@@ -0,0 +1,16 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
// @ts-ignore
export async function css(file: string, is_development: boolean): string {
// TODO: CI does not have `experimentalCss`
// const { success, stdout, stderr } = await Bun.spawnSync({
// cmd: [process.execPath, "build", file, "--experimental-css", ...(is_development ? [] : ["--minify"])],
// cwd: import.meta.dir,
// stdio: ["ignore", "pipe", "pipe"],
// });
// if (!success) throw new Error(stderr.toString("utf-8"));
// return stdout.toString("utf-8");
return readFileSync(resolve(import.meta.dir, file)).toString('utf-8');
}

3
src/bake/package.json Normal file
View File

@@ -0,0 +1,3 @@
{
"sideEffects": false
}

1
src/bake/shared.ts Normal file
View File

@@ -0,0 +1 @@
export const td = /* #__PURE__ */ new TextDecoder();

View File

@@ -12,7 +12,10 @@
"downlevelIteration": true,
"esModuleInterop": true,
"skipLibCheck": true,
"jsx": "react-jsx",
"jsx": "react",
"paths": {
"bun-framework-rsc/*": ["./bun-framework-rsc/*"]
}
},
"include": ["./hmr-runtime-types.d.ts", "*.ts"]
}
"include": ["**/*.ts", "**/*.tsx"]
}

View File

@@ -39,6 +39,14 @@ pub fn Bitflags(comptime T: type) type {
this.* = bitwiseOr(this.*, other);
}
pub inline fn remove(this: *T, other: T) void {
this.* = bitwiseAnd(this.*, ~other);
}
pub inline fn maskOut(this: T, other: T) T {
return @bitCast(asBits(this) & ~asBits(other));
}
pub fn contains(lhs: T, rhs: T) bool {
return @as(IntType, @bitCast(lhs)) & @as(IntType, @bitCast(rhs)) != 0;
}
@@ -55,8 +63,16 @@ pub fn Bitflags(comptime T: type) type {
return asBits(lhs) == asBits(rhs);
}
pub fn eql(lhs: T, rhs: T) bool {
return eq(lhs, rhs);
}
pub fn neq(lhs: T, rhs: T) bool {
return asBits(lhs) != asBits(rhs);
}
pub fn hash(this: *const T, hasher: *std.hash.Wyhash) void {
hasher.update(std.mem.asBytes(this));
}
};
}

View File

@@ -112,7 +112,7 @@ pub const BuildMessage = struct {
_: *JSC.CallFrame,
) JSC.JSValue {
var object = JSC.JSValue.createEmptyObject(globalThis, 4);
object.put(globalThis, ZigString.static("name"), ZigString.init("BuildMessage").toJS(globalThis));
object.put(globalThis, ZigString.static("name"), bun.String.static("BuildMessage").toJS(globalThis));
object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis));
object.put(globalThis, ZigString.static("message"), this.getMessage(globalThis));
object.put(globalThis, ZigString.static("level"), this.getLevel(globalThis));

View File

@@ -219,7 +219,7 @@ pub fn messageWithTypeAndLevel(
}
}
const TablePrinter = struct {
pub const TablePrinter = struct {
const Column = struct {
name: String,
width: u32 = 1,
@@ -342,7 +342,7 @@ const TablePrinter = struct {
// - otherwise: iterate the object properties, and create the columns on-demand
if (!this.properties.isUndefined()) {
for (columns.items[1..]) |*column| {
if (row_value.getWithString(this.globalObject, column.name)) |value| {
if (row_value.getOwn(this.globalObject, column.name)) |value| {
column.width = @max(column.width, this.getWidthForValue(value));
}
}
@@ -436,7 +436,7 @@ const TablePrinter = struct {
value = row_value;
}
} else if (row_value.isObject()) {
value = row_value.getWithString(this.globalObject, col.name) orelse JSValue.zero;
value = row_value.getOwn(this.globalObject, col.name) orelse JSValue.zero;
}
if (value.isEmpty()) {
@@ -666,6 +666,69 @@ pub const FormatOptions = struct {
ordered_properties: bool = false,
quote_strings: bool = false,
max_depth: u16 = 2,
single_line: bool = false,
pub fn fromJS(formatOptions: *FormatOptions, globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue) !void {
const arg1 = arguments[0];
if (arg1.isObject()) {
if (arg1.getTruthy(globalThis, "depth")) |opt| {
if (opt.isInt32()) {
const arg = opt.toInt32();
if (arg < 0) {
globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
return error.JSError;
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (opt.isNumber()) {
const v = opt.coerce(f64, globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
globalThis.throwInvalidArguments("expected depth to be an integer, got {d}", .{v});
return error.JSError;
}
}
}
if (try arg1.getOptional(globalThis, "colors", bool)) |opt| {
formatOptions.enable_colors = opt;
}
if (try arg1.getOptional(globalThis, "sorted", bool)) |opt| {
formatOptions.ordered_properties = opt;
}
if (try arg1.getOptional(globalThis, "compact", bool)) |opt| {
formatOptions.single_line = opt;
}
} else {
// formatOptions.show_hidden = arg1.toBoolean();
if (arguments.len > 0) {
var depthArg = arg1;
if (depthArg.isInt32()) {
const arg = depthArg.toInt32();
if (arg < 0) {
globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
return error.JSError;
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (depthArg.isNumber()) {
const v = depthArg.coerce(f64, globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
globalThis.throwInvalidArguments("expected depth to be an integer, got {d}", .{v});
return error.JSError;
}
}
if (arguments.len > 1 and !arguments[1].isEmptyOrUndefinedOrNull()) {
formatOptions.enable_colors = arguments[1].coerce(bool, globalThis);
if (globalThis.hasException()) {
return error.JSError;
}
}
}
}
}
};
pub fn format2(
@@ -694,6 +757,7 @@ pub fn format2(
.ordered_properties = options.ordered_properties,
.quote_strings = options.quote_strings,
.max_depth = options.max_depth,
.single_line = options.single_line,
};
const tag = ConsoleObject.Formatter.Tag.get(vals[0], global);
@@ -771,6 +835,7 @@ pub fn format2(
.globalThis = global,
.ordered_properties = options.ordered_properties,
.quote_strings = options.quote_strings,
.single_line = options.single_line,
};
var tag: ConsoleObject.Formatter.Tag.Result = undefined;
@@ -1138,13 +1203,18 @@ pub const Formatter = struct {
.Symbol => .Symbol,
.BooleanObject => .Boolean,
.JSFunction => .Function,
.JSWeakMap, JSValue.JSType.JSMap => .Map,
.JSMapIterator => .MapIterator,
.JSSetIterator => .SetIterator,
.JSWeakSet, JSValue.JSType.JSSet => .Set,
.WeakMap, JSValue.JSType.Map => .Map,
.MapIterator => .MapIterator,
.SetIterator => .SetIterator,
.WeakSet, JSValue.JSType.Set => .Set,
.JSDate => .JSON,
.JSPromise => .Promise,
.WrapForValidIterator,
.RegExpStringIterator,
.JSArrayIterator,
.Iterator,
.IteratorHelper,
.Object,
.FinalObject,
.ModuleNamespaceObject,
@@ -1778,7 +1848,7 @@ pub const Formatter = struct {
writer.print(
comptime Output.prettyFmt("<r><green>{s}<r><d>:<r> ", enable_ansi_colors),
.{JSPrinter.formatJSONString(key.slice())},
.{bun.fmt.formatJSONString(key.slice())},
);
}
} else if (Environment.isDebug and is_private_symbol) {
@@ -2433,7 +2503,7 @@ pub const Formatter = struct {
this.quote_strings = true;
defer this.quote_strings = prev_quote_strings;
const map_name = if (value.jsType() == .JSWeakMap) "WeakMap" else "Map";
const map_name = if (value.jsType() == .WeakMap) "WeakMap" else "Map";
if (length == 0) {
return writer.print("{s} {{}}", .{map_name});
@@ -2541,7 +2611,7 @@ pub const Formatter = struct {
this.writeIndent(Writer, writer_) catch {};
}
const set_name = if (value.jsType() == .JSWeakSet) "WeakSet" else "Set";
const set_name = if (value.jsType() == .WeakSet) "WeakSet" else "Set";
if (length == 0) {
return writer.print("{s} {{}}", .{set_name});

View File

@@ -142,7 +142,7 @@ pub const ResolveMessage = struct {
_: *JSC.CallFrame,
) JSC.JSValue {
var object = JSC.JSValue.createEmptyObject(globalThis, 7);
object.put(globalThis, ZigString.static("name"), ZigString.init("ResolveMessage").toJS(globalThis));
object.put(globalThis, ZigString.static("name"), bun.String.static("ResolveMessage").toJS(globalThis));
object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis));
object.put(globalThis, ZigString.static("message"), this.getMessage(globalThis));
object.put(globalThis, ZigString.static("level"), this.getLevel(globalThis));

View File

@@ -10,8 +10,12 @@ const conv = std.builtin.CallingConvention.Unspecified;
pub const BunObject = struct {
// --- Callbacks ---
pub const allocUnsafe = toJSCallback(Bun.allocUnsafe);
pub const braces = toJSCallback(Bun.braces);
pub const build = toJSCallback(Bun.JSBundler.buildFn);
pub const color = bun.css.CssColor.jsFunctionColor;
pub const connect = toJSCallback(JSC.wrapStaticMethod(JSC.API.Listener, "connect", false));
pub const createParsedShellScript = toJSCallback(bun.shell.ParsedShellScript.createParsedShellScript);
pub const createShellInterpreter = toJSCallback(bun.shell.Interpreter.createShellInterpreter);
pub const deflateSync = toJSCallback(JSZlib.deflateSync);
pub const file = toJSCallback(WebCore.Blob.constructBunFile);
pub const gc = toJSCallback(Bun.runGC);
@@ -22,7 +26,6 @@ pub const BunObject = struct {
pub const inflateSync = toJSCallback(JSZlib.inflateSync);
pub const jest = toJSCallback(@import("../test/jest.zig").Jest.call);
pub const listen = toJSCallback(JSC.wrapStaticMethod(JSC.API.Listener, "listen", false));
pub const udpSocket = toJSCallback(JSC.wrapStaticMethod(JSC.API.UDPSocket, "udpSocket", false));
pub const mmap = toJSCallback(Bun.mmapFile);
pub const nanoseconds = toJSCallback(Bun.nanoseconds);
pub const openInEditor = toJSCallback(Bun.openInEditor);
@@ -31,24 +34,22 @@ pub const BunObject = struct {
pub const resolveSync = toJSCallback(Bun.resolveSync);
pub const serve = toJSCallback(Bun.serve);
pub const sha = toJSCallback(JSC.wrapStaticMethod(Crypto.SHA512_256, "hash_", true));
pub const shellEscape = toJSCallback(Bun.shellEscape);
pub const shrink = toJSCallback(Bun.shrink);
pub const sleepSync = toJSCallback(Bun.sleepSync);
pub const spawn = toJSCallback(JSC.wrapStaticMethod(JSC.Subprocess, "spawn", false));
pub const spawnSync = toJSCallback(JSC.wrapStaticMethod(JSC.Subprocess, "spawnSync", false));
pub const stringWidth = toJSCallback(Bun.stringWidth);
pub const udpSocket = toJSCallback(JSC.wrapStaticMethod(JSC.API.UDPSocket, "udpSocket", false));
pub const which = toJSCallback(Bun.which);
pub const write = toJSCallback(JSC.WebCore.Blob.writeFile);
pub const stringWidth = toJSCallback(Bun.stringWidth);
pub const braces = toJSCallback(Bun.braces);
pub const shellEscape = toJSCallback(Bun.shellEscape);
pub const createParsedShellScript = toJSCallback(bun.shell.ParsedShellScript.createParsedShellScript);
pub const createShellInterpreter = toJSCallback(bun.shell.Interpreter.createShellInterpreter);
pub const color = bun.css.CssColor.jsFunctionColor;
// --- Callbacks ---
// --- Getters ---
pub const CryptoHasher = toJSGetter(Crypto.CryptoHasher.getter);
pub const FFI = toJSGetter(Bun.FFIObject.getter);
pub const FileSystemRouter = toJSGetter(Bun.getFileSystemRouter);
pub const Glob = toJSGetter(Bun.getGlobConstructor);
pub const MD4 = toJSGetter(Crypto.MD4.getter);
pub const MD5 = toJSGetter(Crypto.MD5.getter);
pub const SHA1 = toJSGetter(Crypto.SHA1.getter);
@@ -58,21 +59,20 @@ pub const BunObject = struct {
pub const SHA512 = toJSGetter(Crypto.SHA512.getter);
pub const SHA512_256 = toJSGetter(Crypto.SHA512_256.getter);
pub const TOML = toJSGetter(Bun.getTOMLObject);
pub const Glob = toJSGetter(Bun.getGlobConstructor);
pub const Transpiler = toJSGetter(Bun.getTranspilerConstructor);
pub const argv = toJSGetter(Bun.getArgv);
pub const cwd = toJSGetter(Bun.getCWD);
pub const embeddedFiles = toJSGetter(Bun.getEmbeddedFiles);
pub const enableANSIColors = toJSGetter(Bun.enableANSIColors);
pub const hash = toJSGetter(Bun.getHashObject);
pub const inspect = toJSGetter(Bun.getInspect);
pub const main = toJSGetter(Bun.getMain);
pub const origin = toJSGetter(Bun.getOrigin);
pub const semver = toJSGetter(Bun.getSemver);
pub const stderr = toJSGetter(Bun.getStderr);
pub const stdin = toJSGetter(Bun.getStdin);
pub const stdout = toJSGetter(Bun.getStdout);
pub const unsafe = toJSGetter(Bun.getUnsafe);
pub const semver = toJSGetter(Bun.getSemver);
pub const embeddedFiles = toJSGetter(Bun.getEmbeddedFiles);
// --- Getters ---
fn getterName(comptime baseName: anytype) [:0]const u8 {
@@ -329,11 +329,11 @@ pub fn braces(
if (arguments.nextEat()) |opts_val| {
if (opts_val.isObject()) {
if (comptime bun.Environment.allow_assert) {
if (opts_val.getOwnTruthy(globalThis, "tokenize")) |tokenize_val| {
if (opts_val.getTruthy(globalThis, "tokenize")) |tokenize_val| {
tokenize = if (tokenize_val.isBoolean()) tokenize_val.asBoolean() else false;
}
if (opts_val.getOwnTruthy(globalThis, "parse")) |tokenize_val| {
if (opts_val.getTruthy(globalThis, "parse")) |tokenize_val| {
parse = if (tokenize_val.isBoolean()) tokenize_val.asBoolean() else false;
}
}
@@ -461,11 +461,11 @@ pub fn which(
if (arguments.nextEat()) |arg| {
if (!arg.isEmptyOrUndefinedOrNull() and arg.isObject()) {
if (arg.getOwn(globalThis, "PATH")) |str_| {
if (arg.get(globalThis, "PATH")) |str_| {
path_str = str_.toSlice(globalThis, globalThis.bunVM().allocator);
}
if (arg.getOwn(globalThis, "cwd")) |str_| {
if (arg.get(globalThis, "cwd")) |str_| {
cwd_str = str_.toSlice(globalThis, globalThis.bunVM().allocator);
}
}
@@ -483,6 +483,81 @@ pub fn which(
return JSC.JSValue.jsNull();
}
pub fn inspectTable(
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
) callconv(JSC.conv) JSC.JSValue {
var args_buf = callframe.argumentsUndef(5);
var all_arguments = args_buf.mut();
if (all_arguments[0].isUndefined() or all_arguments[0].isNull())
return bun.String.empty.toJS(globalThis);
for (all_arguments) |arg| {
arg.protect();
}
defer {
for (all_arguments) |arg| {
arg.unprotect();
}
}
var arguments = all_arguments[0..];
if (!arguments[1].isArray()) {
arguments[2] = arguments[1];
arguments[1] = .undefined;
}
var formatOptions = ConsoleObject.FormatOptions{
.enable_colors = false,
.add_newline = false,
.flush = false,
.max_depth = 5,
.quote_strings = true,
.ordered_properties = false,
.single_line = true,
};
if (arguments[2].isObject()) {
formatOptions.fromJS(globalThis, arguments[2..]) catch return .zero;
}
const value = arguments[0];
// very stable memory address
var array = MutableString.init(getAllocator(globalThis), 0) catch bun.outOfMemory();
defer array.deinit();
var buffered_writer_ = MutableString.BufferedWriter{ .context = &array };
var buffered_writer = &buffered_writer_;
const writer = buffered_writer.writer();
const Writer = @TypeOf(writer);
const properties = if (arguments[1].jsType().isArray()) arguments[1] else JSValue.undefined;
var table_printer = ConsoleObject.TablePrinter.init(
globalThis,
.Log,
value,
properties,
);
table_printer.value_formatter.depth = formatOptions.max_depth;
table_printer.value_formatter.ordered_properties = formatOptions.ordered_properties;
table_printer.value_formatter.single_line = formatOptions.single_line;
switch (formatOptions.enable_colors) {
inline else => |colors| table_printer.printTable(Writer, writer, colors) catch {
if (!globalThis.hasException())
globalThis.throwOutOfMemory();
return .zero;
},
}
buffered_writer.flush() catch return {
globalThis.throwOutOfMemory();
return .zero;
};
var out = bun.String.createUTF8(array.slice());
return out.transferToJS(globalThis);
}
pub fn inspect(
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
@@ -508,62 +583,10 @@ pub fn inspect(
.quote_strings = true,
.ordered_properties = false,
};
const value = arguments[0];
if (arguments.len > 1) {
const arg1 = arguments[1];
if (arg1.isObject()) {
if (arg1.getOwnTruthy(globalThis, "depth")) |opt| {
if (opt.isInt32()) {
const arg = opt.toInt32();
if (arg < 0) {
globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
return .zero;
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (opt.isNumber()) {
const v = opt.coerce(f64, globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
globalThis.throwInvalidArguments("expected depth to be an integer, got {d}", .{v});
return .zero;
}
}
}
if (arg1.getOptional(globalThis, "colors", bool) catch return .zero) |opt| {
formatOptions.enable_colors = opt;
}
if (arg1.getOptional(globalThis, "sorted", bool) catch return .zero) |opt| {
formatOptions.ordered_properties = opt;
}
} else {
// formatOptions.show_hidden = arg1.toBoolean();
if (arguments.len > 2) {
var depthArg = arguments[1];
if (depthArg.isInt32()) {
const arg = depthArg.toInt32();
if (arg < 0) {
globalThis.throwInvalidArguments("expected depth to be greater than or equal to 0, got {d}", .{arg});
return .zero;
}
formatOptions.max_depth = @as(u16, @truncate(@as(u32, @intCast(@min(arg, std.math.maxInt(u16))))));
} else if (depthArg.isNumber()) {
const v = depthArg.coerce(f64, globalThis);
if (std.math.isInf(v)) {
formatOptions.max_depth = std.math.maxInt(u16);
} else {
globalThis.throwInvalidArguments("expected depth to be an integer, got {d}", .{v});
return .zero;
}
}
if (arguments.len > 3) {
formatOptions.enable_colors = arguments[2].toBoolean();
}
}
}
formatOptions.fromJS(globalThis, arguments[1..]) catch return .zero;
}
const value = arguments[0];
// very stable memory address
var array = MutableString.init(getAllocator(globalThis), 0) catch unreachable;
@@ -590,7 +613,7 @@ pub fn inspect(
// we are going to always clone to keep things simple for now
// the common case here will be stack-allocated, so it should be fine
var out = ZigString.init(array.toOwnedSliceLeaky()).withEncoding();
var out = ZigString.init(array.slice()).withEncoding();
const ret = out.toJS(globalThis);
array.deinit();
return ret;
@@ -600,6 +623,7 @@ pub fn getInspect(globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.JSVal
const fun = JSC.createCallback(globalObject, ZigString.static("inspect"), 2, inspect);
var str = ZigString.init("nodejs.util.inspect.custom");
fun.put(globalObject, ZigString.static("custom"), JSC.JSValue.symbolFor(globalObject, &str));
fun.put(globalObject, ZigString.static("table"), JSC.createCallback(globalObject, ZigString.static("table"), 3, inspectTable));
return fun;
}
@@ -779,7 +803,7 @@ pub fn openInEditor(
if (arguments.nextEat()) |opts| {
if (!opts.isUndefinedOrNull()) {
if (opts.getOwnTruthy(globalThis, "editor")) |editor_val| {
if (opts.getTruthy(globalThis, "editor")) |editor_val| {
var sliced = editor_val.toSlice(globalThis, arguments.arena.allocator());
const prev_name = edit.name;
@@ -799,11 +823,11 @@ pub fn openInEditor(
}
}
if (opts.getOwnTruthy(globalThis, "line")) |line_| {
if (opts.getTruthy(globalThis, "line")) |line_| {
line = line_.toSlice(globalThis, arguments.arena.allocator()).slice();
}
if (opts.getOwnTruthy(globalThis, "column")) |column_| {
if (opts.getTruthy(globalThis, "column")) |column_| {
column = column_.toSlice(globalThis, arguments.arena.allocator()).slice();
}
}
@@ -1711,7 +1735,7 @@ pub const Crypto = struct {
pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) ?Value {
if (value.isObject()) {
if (value.getOwnTruthy(globalObject, "algorithm")) |algorithm_value| {
if (value.getTruthy(globalObject, "algorithm")) |algorithm_value| {
if (!algorithm_value.isString()) {
globalObject.throwInvalidArgumentType("hash", "algorithm", "string");
return null;
@@ -1728,7 +1752,7 @@ pub const Crypto = struct {
.bcrypt = PasswordObject.Algorithm.Value.bcrpyt_default,
};
if (value.getOwnTruthy(globalObject, "cost")) |rounds_value| {
if (value.getTruthy(globalObject, "cost")) |rounds_value| {
if (!rounds_value.isNumber()) {
globalObject.throwInvalidArgumentType("hash", "cost", "number");
return null;
@@ -1749,7 +1773,7 @@ pub const Crypto = struct {
inline .argon2id, .argon2d, .argon2i => |tag| {
var argon = Algorithm.Argon2Params{};
if (value.getOwnTruthy(globalObject, "timeCost")) |time_value| {
if (value.getTruthy(globalObject, "timeCost")) |time_value| {
if (!time_value.isNumber()) {
globalObject.throwInvalidArgumentType("hash", "timeCost", "number");
return null;
@@ -1765,7 +1789,7 @@ pub const Crypto = struct {
argon.time_cost = @as(u32, @intCast(time_cost));
}
if (value.getOwnTruthy(globalObject, "memoryCost")) |memory_value| {
if (value.getTruthy(globalObject, "memoryCost")) |memory_value| {
if (!memory_value.isNumber()) {
globalObject.throwInvalidArgumentType("hash", "memoryCost", "number");
return null;
@@ -3435,7 +3459,7 @@ pub export fn Bun__escapeHTML16(globalObject: *JSC.JSGlobalObject, input_value:
assert(len > 0);
const input_slice = ptr[0..len];
const escaped = strings.escapeHTMLForUTF16Input(globalObject.bunVM().allocator, input_slice) catch {
globalObject.vm().throwError(globalObject, ZigString.init("Out of memory").toJS(globalObject));
globalObject.vm().throwError(globalObject, bun.String.static("Out of memory").toJS(globalObject));
return .undefined;
};
@@ -3481,7 +3505,7 @@ pub export fn Bun__escapeHTML8(globalObject: *JSC.JSGlobalObject, input_value: J
const allocator = if (input_slice.len <= 32) stack_allocator.get() else stack_allocator.fallback_allocator;
const escaped = strings.escapeHTMLForLatin1Input(allocator, input_slice) catch {
globalObject.vm().throwError(globalObject, ZigString.init("Out of memory").toJS(globalObject));
globalObject.vm().throwError(globalObject, bun.String.static("Out of memory").toJS(globalObject));
return .undefined;
};
@@ -3932,7 +3956,7 @@ const TOMLObject = struct {
return .zero;
};
const slice = writer.ctx.buffer.toOwnedSliceLeaky();
const slice = writer.ctx.buffer.slice();
var out = bun.String.fromUTF8(slice);
defer out.deref();
@@ -4599,11 +4623,11 @@ fn stringWidth(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC
var ambiguous_as_wide = false;
if (options_object.isObject()) {
if (options_object.getOwnTruthy(globalObject, "countAnsiEscapeCodes")) |count_ansi_escapes_value| {
if (options_object.getTruthy(globalObject, "countAnsiEscapeCodes")) |count_ansi_escapes_value| {
if (count_ansi_escapes_value.isBoolean())
count_ansi_escapes = count_ansi_escapes_value.toBoolean();
}
if (options_object.getOwnTruthy(globalObject, "ambiguousIsNarrow")) |ambiguous_is_narrow| {
if (options_object.getTruthy(globalObject, "ambiguousIsNarrow")) |ambiguous_is_narrow| {
if (ambiguous_is_narrow.isBoolean())
ambiguous_as_wide = !ambiguous_is_narrow.toBoolean();
}
@@ -4784,7 +4808,7 @@ pub const JSZlib = struct {
library = .zlib;
}
if (options_val.getOwnTruthy(globalThis, "library")) |library_value| {
if (options_val.getTruthy(globalThis, "library")) |library_value| {
if (!library_value.isString()) {
globalThis.throwInvalidArguments("Expected library to be a string", .{});
return .zero;
@@ -4911,7 +4935,7 @@ pub const JSZlib = struct {
library = .zlib;
}
if (options_val.getOwnTruthy(globalThis, "library")) |library_value| {
if (options_val.getTruthy(globalThis, "library")) |library_value| {
if (!library_value.isString()) {
globalThis.throwInvalidArguments("Expected library to be a string", .{});
return .zero;

View File

@@ -60,8 +60,8 @@ typedef enum {
napi_detachable_arraybuffer_expected,
napi_would_deadlock // unused
} napi_status;
void* NapiHandleScope__push(void* jsGlobalObject, bool detached);
void NapiHandleScope__pop(void* jsGlobalObject, void* handleScope);
void* NapiHandleScope__open(void* jsGlobalObject, bool detached);
void NapiHandleScope__close(void* jsGlobalObject, void* handleScope);
#endif

View File

@@ -72,6 +72,10 @@ pub const JSBundler = struct {
packages: options.PackagesOption = .bundle,
format: options.Format = .esm,
bytecode: bool = false,
banner: OwnedString = OwnedString.initEmpty(bun.default_allocator),
footer: OwnedString = OwnedString.initEmpty(bun.default_allocator),
experimental_css: bool = false,
drop: bun.StringSet = bun.StringSet.init(bun.default_allocator),
pub const List = bun.StringArrayHashMapUnmanaged(Config);
@@ -94,6 +98,10 @@ pub const JSBundler = struct {
errdefer this.deinit(allocator);
errdefer if (plugins.*) |plugin| plugin.deinit();
if (config.getTruthy(globalThis, "experimentalCss")) |enable_css| {
this.experimental_css = if (enable_css.isBoolean()) enable_css.toBoolean() else false;
}
// Plugins must be resolved first as they are allowed to mutate the config JSValue
if (try config.getArray(globalThis, "plugins")) |array| {
var iter = array.arrayIterator(globalThis);
@@ -103,7 +111,7 @@ pub const JSBundler = struct {
return error.JSError;
}
if (plugin.getOwnOptional(globalThis, "name", ZigString.Slice) catch null) |slice| {
if (plugin.getOptional(globalThis, "name", ZigString.Slice) catch null) |slice| {
defer slice.deinit();
if (slice.len == 0) {
globalThis.throwInvalidArguments("Expected plugin to have a non-empty name", .{});
@@ -147,13 +155,13 @@ pub const JSBundler = struct {
}
}
if (config.getOwnTruthy(globalThis, "macros")) |macros_flag| {
if (config.getTruthy(globalThis, "macros")) |macros_flag| {
if (!macros_flag.coerce(bool, globalThis)) {
this.no_macros = true;
}
}
if (try config.getOwnOptional(globalThis, "bytecode", bool)) |bytecode| {
if (try config.getOptional(globalThis, "bytecode", bool)) |bytecode| {
this.bytecode = bytecode;
if (bytecode) {
@@ -163,7 +171,7 @@ pub const JSBundler = struct {
}
}
if (try config.getOwnOptionalEnum(globalThis, "target", options.Target)) |target| {
if (try config.getOptionalEnum(globalThis, "target", options.Target)) |target| {
this.target = target;
if (target != .bun and this.bytecode) {
@@ -173,13 +181,23 @@ pub const JSBundler = struct {
}
var has_out_dir = false;
if (try config.getOwnOptional(globalThis, "outdir", ZigString.Slice)) |slice| {
if (try config.getOptional(globalThis, "outdir", ZigString.Slice)) |slice| {
defer slice.deinit();
try this.outdir.appendSliceExact(slice.slice());
has_out_dir = true;
}
if (config.getOwnTruthy(globalThis, "sourcemap")) |source_map_js| {
if (try config.getOptional(globalThis, "banner", ZigString.Slice)) |slice| {
defer slice.deinit();
try this.banner.appendSliceExact(slice.slice());
}
if (try config.getOptional(globalThis, "footer", ZigString.Slice)) |slice| {
defer slice.deinit();
try this.footer.appendSliceExact(slice.slice());
}
if (config.getTruthy(globalThis, "sourcemap")) |source_map_js| {
if (bun.FeatureFlags.breaking_changes_1_2 and config.isBoolean()) {
if (source_map_js == .true) {
this.source_map = if (has_out_dir)
@@ -196,11 +214,11 @@ pub const JSBundler = struct {
}
}
if (try config.getOwnOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
if (try config.getOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
this.packages = packages;
}
if (try config.getOwnOptionalEnum(globalThis, "format", options.Format)) |format| {
if (try config.getOptionalEnum(globalThis, "format", options.Format)) |format| {
this.format = format;
if (this.bytecode and format != .cjs) {
@@ -209,28 +227,28 @@ pub const JSBundler = struct {
}
}
// if (try config.getOwnOptional(globalThis, "hot", bool)) |hot| {
// if (try config.getOptional(globalThis, "hot", bool)) |hot| {
// this.hot = hot;
// }
if (try config.getOwnOptional(globalThis, "splitting", bool)) |hot| {
if (try config.getOptional(globalThis, "splitting", bool)) |hot| {
this.code_splitting = hot;
}
if (config.getOwnTruthy(globalThis, "minify")) |hot| {
if (config.getTruthy(globalThis, "minify")) |hot| {
if (hot.isBoolean()) {
const value = hot.coerce(bool, globalThis);
this.minify.whitespace = value;
this.minify.syntax = value;
this.minify.identifiers = value;
} else if (hot.isObject()) {
if (try hot.getOwnOptional(globalThis, "whitespace", bool)) |whitespace| {
if (try hot.getOptional(globalThis, "whitespace", bool)) |whitespace| {
this.minify.whitespace = whitespace;
}
if (try hot.getOwnOptional(globalThis, "syntax", bool)) |syntax| {
if (try hot.getOptional(globalThis, "syntax", bool)) |syntax| {
this.minify.syntax = syntax;
}
if (try hot.getOwnOptional(globalThis, "identifiers", bool)) |syntax| {
if (try hot.getOptional(globalThis, "identifiers", bool)) |syntax| {
this.minify.identifiers = syntax;
}
} else {
@@ -254,19 +272,19 @@ pub const JSBundler = struct {
return error.JSError;
}
if (config.getOwnTruthy(globalThis, "emitDCEAnnotations")) |flag| {
if (config.getTruthy(globalThis, "emitDCEAnnotations")) |flag| {
if (flag.coerce(bool, globalThis)) {
this.emit_dce_annotations = true;
}
}
if (config.getOwnTruthy(globalThis, "ignoreDCEAnnotations")) |flag| {
if (config.getTruthy(globalThis, "ignoreDCEAnnotations")) |flag| {
if (flag.coerce(bool, globalThis)) {
this.ignore_dce_annotations = true;
}
}
if (config.getOwnTruthy(globalThis, "conditions")) |conditions_value| {
if (config.getTruthy(globalThis, "conditions")) |conditions_value| {
if (conditions_value.isString()) {
var slice = conditions_value.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{});
@@ -292,7 +310,7 @@ pub const JSBundler = struct {
{
const path: ZigString.Slice = brk: {
if (try config.getOwnOptional(globalThis, "root", ZigString.Slice)) |slice| {
if (try config.getOptional(globalThis, "root", ZigString.Slice)) |slice| {
break :brk slice;
}
@@ -333,21 +351,33 @@ pub const JSBundler = struct {
}
}
// if (try config.getOwnOptional(globalThis, "dir", ZigString.Slice)) |slice| {
if (try config.getOwnArray(globalThis, "drop")) |drops| {
var iter = drops.arrayIterator(globalThis);
while (iter.next()) |entry| {
var slice = entry.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected drop to be an array of strings", .{});
return error.JSError;
};
defer slice.deinit();
try this.drop.insert(slice.slice());
}
}
// if (try config.getOptional(globalThis, "dir", ZigString.Slice)) |slice| {
// defer slice.deinit();
// this.appendSliceExact(slice.slice()) catch unreachable;
// } else {
// this.appendSliceExact(globalThis.bunVM().bundler.fs.top_level_dir) catch unreachable;
// }
if (try config.getOwnOptional(globalThis, "publicPath", ZigString.Slice)) |slice| {
if (try config.getOptional(globalThis, "publicPath", ZigString.Slice)) |slice| {
defer slice.deinit();
try this.public_path.appendSliceExact(slice.slice());
}
if (config.getOwnTruthy(globalThis, "naming")) |naming| {
if (config.getTruthy(globalThis, "naming")) |naming| {
if (naming.isString()) {
if (try config.getOwnOptional(globalThis, "naming", ZigString.Slice)) |slice| {
if (try config.getOptional(globalThis, "naming", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
try this.names.owned_entry_point.appendSliceExact("./");
@@ -356,7 +386,7 @@ pub const JSBundler = struct {
this.names.entry_point.data = this.names.owned_entry_point.list.items;
}
} else if (naming.isObject()) {
if (try naming.getOwnOptional(globalThis, "entry", ZigString.Slice)) |slice| {
if (try naming.getOptional(globalThis, "entry", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
try this.names.owned_entry_point.appendSliceExact("./");
@@ -365,7 +395,7 @@ pub const JSBundler = struct {
this.names.entry_point.data = this.names.owned_entry_point.list.items;
}
if (try naming.getOwnOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
if (try naming.getOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
try this.names.owned_chunk.appendSliceExact("./");
@@ -374,7 +404,7 @@ pub const JSBundler = struct {
this.names.chunk.data = this.names.owned_chunk.list.items;
}
if (try naming.getOwnOptional(globalThis, "asset", ZigString.Slice)) |slice| {
if (try naming.getOptional(globalThis, "asset", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
try this.names.owned_asset.appendSliceExact("./");
@@ -526,6 +556,9 @@ pub const JSBundler = struct {
self.rootdir.deinit();
self.public_path.deinit();
self.conditions.deinit();
self.drop.deinit();
self.banner.deinit();
self.footer.deinit();
}
};
@@ -1139,7 +1172,7 @@ pub const BuildArtifact = struct {
globalThis: *JSC.JSGlobalObject,
) JSValue {
var buf: [512]u8 = undefined;
const out = std.fmt.bufPrint(&buf, "{any}", .{options.PathTemplate.hashFormatter(this.hash)}) catch @panic("Unexpected");
const out = std.fmt.bufPrint(&buf, "{any}", .{bun.fmt.truncatedHash32(this.hash)}) catch @panic("Unexpected");
return ZigString.init(out).toJS(globalThis);
}
@@ -1223,7 +1256,7 @@ pub const BuildArtifact = struct {
"<r>hash<r>: <green>\"{any}\"<r>",
enable_ansi_colors,
),
.{options.PathTemplate.hashFormatter(this.hash)},
.{bun.fmt.truncatedHash32(this.hash)},
);
}

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