mirror of
https://github.com/oven-sh/bun
synced 2026-02-18 14:51:52 +00:00
Compare commits
552 Commits
bun-v0.1.9
...
bun-v0.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57e5c35277 | ||
|
|
8b4c3ec0c7 | ||
|
|
9c7eb75a9a | ||
|
|
b0fe167910 | ||
|
|
6223030360 | ||
|
|
1835e4b9f9 | ||
|
|
8ca49f906a | ||
|
|
dac6c48b1e | ||
|
|
2b0694ec8c | ||
|
|
26bfc4f0a3 | ||
|
|
fbec10758b | ||
|
|
30d43b027f | ||
|
|
693b1c9b23 | ||
|
|
ce0efc37cc | ||
|
|
11c105aa1d | ||
|
|
9167aedcc8 | ||
|
|
fc4c3e3199 | ||
|
|
61a8490c66 | ||
|
|
abd6e496ab | ||
|
|
8e1b2ba32e | ||
|
|
c7fc8fdf96 | ||
|
|
7f4bb93782 | ||
|
|
a10a8e9c70 | ||
|
|
b595ddf20d | ||
|
|
4bd9b20c8a | ||
|
|
9190061ba4 | ||
|
|
41f9fd85f6 | ||
|
|
cdff2697ef | ||
|
|
ca02695993 | ||
|
|
9a2f2a94bf | ||
|
|
e22c245d08 | ||
|
|
171242680d | ||
|
|
5995f2ed71 | ||
|
|
abbde39a02 | ||
|
|
e1a17aff4c | ||
|
|
b8c5646c49 | ||
|
|
62b0b601c2 | ||
|
|
e43b4815b5 | ||
|
|
923d9c1bbb | ||
|
|
e3a6007a76 | ||
|
|
00ae8f79e4 | ||
|
|
dc1330aef5 | ||
|
|
3c1e3792d6 | ||
|
|
603164e66a | ||
|
|
f19b5ce409 | ||
|
|
f356da1b5e | ||
|
|
07a2f80cbc | ||
|
|
2888f43c8a | ||
|
|
697e105ffa | ||
|
|
5d7174d789 | ||
|
|
ab3b072249 | ||
|
|
690e79445d | ||
|
|
bce68bc898 | ||
|
|
94091a7522 | ||
|
|
2852520d90 | ||
|
|
abf3a13433 | ||
|
|
cebd351e61 | ||
|
|
19cff80af8 | ||
|
|
9830e50a29 | ||
|
|
820e6605f8 | ||
|
|
c06bba77d4 | ||
|
|
4ba217bc42 | ||
|
|
a42a9e901c | ||
|
|
3482d76175 | ||
|
|
63c9315b24 | ||
|
|
40126bbe60 | ||
|
|
70615f4036 | ||
|
|
1b1b96aff8 | ||
|
|
de1e963ffa | ||
|
|
a299b1b8e3 | ||
|
|
4cc0eebf4b | ||
|
|
b1e97edc59 | ||
|
|
a56dfe486b | ||
|
|
e9c3529476 | ||
|
|
c9a4bdf44d | ||
|
|
c6fe82018a | ||
|
|
3016723198 | ||
|
|
e453b949dd | ||
|
|
1236e3f59c | ||
|
|
c6d314e954 | ||
|
|
2c548d45f8 | ||
|
|
4c741cc8b6 | ||
|
|
4b5af13ac0 | ||
|
|
35cbfa63a6 | ||
|
|
dd84681d30 | ||
|
|
0a1fca5d7d | ||
|
|
af033c02c5 | ||
|
|
40506e33e7 | ||
|
|
b542921f3d | ||
|
|
b0a7f8df92 | ||
|
|
32e16bda23 | ||
|
|
e32ada318a | ||
|
|
b011610bb3 | ||
|
|
723c7c56dc | ||
|
|
6b7a0c1d3f | ||
|
|
22f7981cff | ||
|
|
ad29d9ffb3 | ||
|
|
8200f43a04 | ||
|
|
3fceae8070 | ||
|
|
8cd8e34719 | ||
|
|
930981c9d9 | ||
|
|
f8b22d51a9 | ||
|
|
2b1b7eb6b3 | ||
|
|
e241e503b7 | ||
|
|
39940ec1f5 | ||
|
|
f725b7e1ab | ||
|
|
da66bed946 | ||
|
|
58fe024aea | ||
|
|
6205cf3fe4 | ||
|
|
fb6c87da07 | ||
|
|
d0fb442c59 | ||
|
|
1c949354c6 | ||
|
|
3a042cdb48 | ||
|
|
a97914fff3 | ||
|
|
ec00838a03 | ||
|
|
860bd53fb3 | ||
|
|
477638435c | ||
|
|
cb384dfa29 | ||
|
|
dd15a98879 | ||
|
|
6b2637468c | ||
|
|
ab4f4bca6d | ||
|
|
73a611a3b9 | ||
|
|
c5333ab597 | ||
|
|
75e8c4699c | ||
|
|
8fcb0ff0b6 | ||
|
|
dbd569d2ab | ||
|
|
40eca63653 | ||
|
|
e7eadcde5a | ||
|
|
36adee4dc8 | ||
|
|
9fe1ad93cb | ||
|
|
8311761c82 | ||
|
|
8702f965a2 | ||
|
|
888a685e26 | ||
|
|
51c1d18e68 | ||
|
|
af6476ca74 | ||
|
|
614d256cb6 | ||
|
|
3867431ed1 | ||
|
|
1f7f5646de | ||
|
|
40623cf967 | ||
|
|
d07e4f8bd1 | ||
|
|
e4bf189e9d | ||
|
|
2292ef8d0e | ||
|
|
a114af4eea | ||
|
|
5152aebde1 | ||
|
|
1310a1d99e | ||
|
|
a20d3eaebb | ||
|
|
3cc61f8e30 | ||
|
|
ef2c9c330c | ||
|
|
5db06105ba | ||
|
|
24433ceb27 | ||
|
|
ff797f7410 | ||
|
|
cef32c1123 | ||
|
|
50d4cedd92 | ||
|
|
27ad376071 | ||
|
|
eebcd30067 | ||
|
|
1afe2f05dc | ||
|
|
170e3117d7 | ||
|
|
fc08e69039 | ||
|
|
25918ddd2a | ||
|
|
edfd2af949 | ||
|
|
dffaeaca1e | ||
|
|
88bdae8218 | ||
|
|
fdfe00452b | ||
|
|
b38d553d60 | ||
|
|
0833275f03 | ||
|
|
4252d015ca | ||
|
|
9fd0072740 | ||
|
|
4dbbdb1671 | ||
|
|
4b5c9acc72 | ||
|
|
b63218206d | ||
|
|
349ccf229b | ||
|
|
85602b406a | ||
|
|
cc6077fbf5 | ||
|
|
495534a054 | ||
|
|
57513f38d3 | ||
|
|
0b3abf2c78 | ||
|
|
9294ef73b7 | ||
|
|
36ec06493e | ||
|
|
6068ad15d4 | ||
|
|
c2c9173eff | ||
|
|
99e7856269 | ||
|
|
1355d415e9 | ||
|
|
410059c9f3 | ||
|
|
80096884f6 | ||
|
|
d2dd2ae306 | ||
|
|
5c3ce875b2 | ||
|
|
6970250b57 | ||
|
|
c880c53199 | ||
|
|
75371d1462 | ||
|
|
2c762f47c9 | ||
|
|
3246efa580 | ||
|
|
4060afb7c7 | ||
|
|
e4d3f51161 | ||
|
|
1777e9d0b1 | ||
|
|
707b454bf4 | ||
|
|
ca4c99b1bf | ||
|
|
a302549d3e | ||
|
|
1a7418e890 | ||
|
|
c1219a3b48 | ||
|
|
632e4ac6ac | ||
|
|
18ae17871d | ||
|
|
09ebb217dd | ||
|
|
dbccfc2b26 | ||
|
|
28f7240dd3 | ||
|
|
9f10956ce1 | ||
|
|
c9a50b2f2d | ||
|
|
d683d7185d | ||
|
|
fc13938fc6 | ||
|
|
f8e8b10e10 | ||
|
|
050292229f | ||
|
|
906e97223a | ||
|
|
dc10b24730 | ||
|
|
d3ef6c330a | ||
|
|
4700762132 | ||
|
|
08d606c3d7 | ||
|
|
ed82b919a0 | ||
|
|
4fa065180b | ||
|
|
cd9b47315c | ||
|
|
062c3948ba | ||
|
|
bff3b902e8 | ||
|
|
3b4900193b | ||
|
|
bab317edd1 | ||
|
|
1dac9248ad | ||
|
|
c57b32fa0c | ||
|
|
43c22b4411 | ||
|
|
bee72be733 | ||
|
|
ea159b6004 | ||
|
|
ac72f28fc8 | ||
|
|
e4e7966d64 | ||
|
|
48cb526e0b | ||
|
|
fd6d28a9fa | ||
|
|
944dc988bf | ||
|
|
2fac218a36 | ||
|
|
16c184efdf | ||
|
|
6b5c49c269 | ||
|
|
af6a43c49b | ||
|
|
18310cfd7c | ||
|
|
9046767da4 | ||
|
|
f70c83345a | ||
|
|
52f5f9545a | ||
|
|
1434fb66d3 | ||
|
|
f325a0016b | ||
|
|
9d7bcac680 | ||
|
|
8d11ab3c35 | ||
|
|
56e491ad8a | ||
|
|
9296a369de | ||
|
|
9050e6ee87 | ||
|
|
84af4f0133 | ||
|
|
6338413696 | ||
|
|
fbec7bda6a | ||
|
|
0f371a2869 | ||
|
|
c30346cf5d | ||
|
|
64ef2389dc | ||
|
|
6ec55cbeeb | ||
|
|
3430cdd91b | ||
|
|
9702568161 | ||
|
|
016a9d6535 | ||
|
|
9f10c1a805 | ||
|
|
7631a47612 | ||
|
|
b8851143f9 | ||
|
|
f3028ff6f3 | ||
|
|
3d35fae890 | ||
|
|
1636291b03 | ||
|
|
e69e8d35b9 | ||
|
|
9438540bf9 | ||
|
|
d34179b9eb | ||
|
|
90074ce98c | ||
|
|
fd0054a800 | ||
|
|
0fb5f15673 | ||
|
|
16929129f0 | ||
|
|
524e48a81d | ||
|
|
76b1a3a88d | ||
|
|
b74351e55f | ||
|
|
a1b4dc42cb | ||
|
|
5ae5125919 | ||
|
|
82a68cd3da | ||
|
|
a41150836a | ||
|
|
e637b43117 | ||
|
|
443ba0f396 | ||
|
|
71ea4a2c9b | ||
|
|
a8ab18bd50 | ||
|
|
ce91423a19 | ||
|
|
5875d1419b | ||
|
|
24a9bc23b7 | ||
|
|
97c3688788 | ||
|
|
0b915b1dd2 | ||
|
|
5fcbfa780f | ||
|
|
a736010fdd | ||
|
|
b733125085 | ||
|
|
5ef36f1b6f | ||
|
|
7cc772cd39 | ||
|
|
7ae73fad68 | ||
|
|
96dcfd3cfe | ||
|
|
9833841101 | ||
|
|
1cd67b62e9 | ||
|
|
ffde9f7842 | ||
|
|
2819509786 | ||
|
|
5b222996c8 | ||
|
|
62e22b2995 | ||
|
|
2346be55fc | ||
|
|
61d0c4042b | ||
|
|
de0b373c7c | ||
|
|
2c1926993b | ||
|
|
e14a3af491 | ||
|
|
0968fd339f | ||
|
|
2ca1861a54 | ||
|
|
ce9daa4857 | ||
|
|
e15fb6b9b2 | ||
|
|
f1ffc72a62 | ||
|
|
37eee4235d | ||
|
|
871d530d6a | ||
|
|
16b1e84138 | ||
|
|
100ce7b62f | ||
|
|
c01cba3ab5 | ||
|
|
ef1607c088 | ||
|
|
123e8c8d2b | ||
|
|
9667eec9de | ||
|
|
26625f3e2a | ||
|
|
e94e6d8d95 | ||
|
|
f0bc50eb71 | ||
|
|
6163fb830e | ||
|
|
167948f5c3 | ||
|
|
37d191bc02 | ||
|
|
da7b648971 | ||
|
|
8b7f43f855 | ||
|
|
21770eb0f3 | ||
|
|
17be8023d9 | ||
|
|
9754c5b32b | ||
|
|
a16cb39423 | ||
|
|
dfefb05b10 | ||
|
|
55bdf2682c | ||
|
|
3a50ae92ec | ||
|
|
fe77f6a2f3 | ||
|
|
cd35218141 | ||
|
|
daeef8d5b3 | ||
|
|
184230058a | ||
|
|
a08b323e61 | ||
|
|
745cc5c655 | ||
|
|
3719c3b736 | ||
|
|
0e424de684 | ||
|
|
285ef0ca01 | ||
|
|
ce0df52b7e | ||
|
|
e03204dccf | ||
|
|
0dea2d8515 | ||
|
|
31469bb05b | ||
|
|
b4f8e5cdb9 | ||
|
|
cefec77646 | ||
|
|
7c7adc1361 | ||
|
|
af6609b0a3 | ||
|
|
3ae950d829 | ||
|
|
c2f64d4da1 | ||
|
|
9b941dd800 | ||
|
|
4b9f6baf79 | ||
|
|
a675cbd13b | ||
|
|
bd77afb2df | ||
|
|
681f5a521f | ||
|
|
f55b9a8530 | ||
|
|
da6f954e0d | ||
|
|
453eaf6871 | ||
|
|
0ce709d96a | ||
|
|
fd808dec52 | ||
|
|
ac949f8181 | ||
|
|
48c2c8c049 | ||
|
|
2e2e134a1b | ||
|
|
4e8bd97d9c | ||
|
|
a31eb6a80c | ||
|
|
b0dd7bee5b | ||
|
|
a291c1676f | ||
|
|
7bfa302b75 | ||
|
|
0935ab14d6 | ||
|
|
9797b676b1 | ||
|
|
2b02f7eb99 | ||
|
|
71e2c26577 | ||
|
|
b78b36ce33 | ||
|
|
0130efeedf | ||
|
|
35b51fcbb5 | ||
|
|
9a5aa059f9 | ||
|
|
8b91360a33 | ||
|
|
85d80d8fb7 | ||
|
|
695da9ee29 | ||
|
|
d114e9040b | ||
|
|
c600196b1a | ||
|
|
3d8edcb77b | ||
|
|
f496740c19 | ||
|
|
0c2a207d82 | ||
|
|
e9c456ff5c | ||
|
|
bcbe1b410a | ||
|
|
206820d27a | ||
|
|
8d8b72cf3f | ||
|
|
a3cc9aaf6f | ||
|
|
812424bf46 | ||
|
|
8af05c28a3 | ||
|
|
970600724d | ||
|
|
c038f513d3 | ||
|
|
1e5978ad4f | ||
|
|
2dbc991af9 | ||
|
|
c4b9c12677 | ||
|
|
d7759b88ee | ||
|
|
25e4fcf5c8 | ||
|
|
ce382788b0 | ||
|
|
c7874ed3fe | ||
|
|
65affacc50 | ||
|
|
6e9159a9ad | ||
|
|
dda23a6076 | ||
|
|
8d71a931a3 | ||
|
|
0a67d7e951 | ||
|
|
52f3377d9e | ||
|
|
b24a9b29d7 | ||
|
|
bac93e14ad | ||
|
|
1454e448e6 | ||
|
|
9b16e245ba | ||
|
|
c2f59e72d6 | ||
|
|
7a5cfc4bae | ||
|
|
f5129dbd1a | ||
|
|
07cbc0193a | ||
|
|
1c1346dfa9 | ||
|
|
58af6db3a7 | ||
|
|
342234eb64 | ||
|
|
93cfc7edbb | ||
|
|
5b6a2d9efe | ||
|
|
5ddfd912ef | ||
|
|
e9cc9ae816 | ||
|
|
ba2a7d72e7 | ||
|
|
308affdcf0 | ||
|
|
07e2c898c6 | ||
|
|
b9fad14f87 | ||
|
|
5a71521021 | ||
|
|
11aa17a57c | ||
|
|
d2397b60e7 | ||
|
|
c31422b308 | ||
|
|
7ea9909618 | ||
|
|
62fa5d59cb | ||
|
|
7acf5d3831 | ||
|
|
1112eb75e3 | ||
|
|
ef268c5ee5 | ||
|
|
15b7f9793f | ||
|
|
04cc1968db | ||
|
|
4891be8d0d | ||
|
|
cc46604bdb | ||
|
|
bcbd448767 | ||
|
|
892c020b00 | ||
|
|
8e5b1c44bc | ||
|
|
2340e7e6e5 | ||
|
|
98ecfc4f76 | ||
|
|
0ca42e81f3 | ||
|
|
8b2d07e82e | ||
|
|
3e9f7ab3e4 | ||
|
|
89524d55bd | ||
|
|
2dc07d7505 | ||
|
|
4e73726bee | ||
|
|
dfc27e3c30 | ||
|
|
c78f7463a9 | ||
|
|
793a42e7f5 | ||
|
|
700c31dd13 | ||
|
|
f023b89b73 | ||
|
|
5eb431dcd0 | ||
|
|
5d99398850 | ||
|
|
43fc696d7b | ||
|
|
bfe9d594a9 | ||
|
|
8651799097 | ||
|
|
9d8fb81413 | ||
|
|
34c0f77319 | ||
|
|
7b628ca09c | ||
|
|
5dc260d07e | ||
|
|
86ac5f09bc | ||
|
|
1c492e2791 | ||
|
|
d7dbe6f329 | ||
|
|
c1734c6ec5 | ||
|
|
b2141a204f | ||
|
|
ce90e0c372 | ||
|
|
296fb41e92 | ||
|
|
30992a8b05 | ||
|
|
af5c4dedca | ||
|
|
8b3afa5831 | ||
|
|
574ecfb9c4 | ||
|
|
466f9a3eb0 | ||
|
|
6644c2fd17 | ||
|
|
49447decdd | ||
|
|
4720270763 | ||
|
|
e49dcfeff7 | ||
|
|
70e778c2a8 | ||
|
|
975477d0f0 | ||
|
|
1580b5fb56 | ||
|
|
ebf4ac4e83 | ||
|
|
64b3d28d41 | ||
|
|
07a4b26697 | ||
|
|
cf55a38879 | ||
|
|
7a734e0a28 | ||
|
|
e0b35b3086 | ||
|
|
49bec758b7 | ||
|
|
950d03a9ea | ||
|
|
e6a1209c53 | ||
|
|
f2316a8eda | ||
|
|
8f58e07ea1 | ||
|
|
9943ca916d | ||
|
|
75a76fb836 | ||
|
|
2a0ab2aa9b | ||
|
|
fd5398ce80 | ||
|
|
633bef7ef1 | ||
|
|
fcd09abec6 | ||
|
|
38071ce9d5 | ||
|
|
8642ac8e86 | ||
|
|
57d6ef26e9 | ||
|
|
6a38441562 | ||
|
|
4b8409096d | ||
|
|
39dc989915 | ||
|
|
5273415ce5 | ||
|
|
47a91e7457 | ||
|
|
f5c6875da5 | ||
|
|
eec11a6651 | ||
|
|
b95e6602c3 | ||
|
|
6897372258 | ||
|
|
ee1d506d06 | ||
|
|
d620500757 | ||
|
|
65dd2214d9 | ||
|
|
3d8bc140aa | ||
|
|
d8f40e080d | ||
|
|
6ab53fca36 | ||
|
|
8fafc2f9ed | ||
|
|
c4580ee2ca | ||
|
|
a8fa61ed68 | ||
|
|
f3779b8e73 | ||
|
|
ca5b996299 | ||
|
|
baf218c233 | ||
|
|
7880e6e6c8 | ||
|
|
97305b7461 | ||
|
|
1fca65fdf6 | ||
|
|
aaa019ce37 | ||
|
|
32d2be0d08 | ||
|
|
83e4d04ce7 | ||
|
|
8901d23685 | ||
|
|
98a03c192d | ||
|
|
f4419bd240 | ||
|
|
07e1a158e9 | ||
|
|
2641884342 | ||
|
|
b1bc549cf7 | ||
|
|
8cf57eb582 | ||
|
|
aa404ded34 | ||
|
|
eee5046b82 | ||
|
|
9222a5d376 | ||
|
|
0a0f8ff41c | ||
|
|
fe7180bc74 | ||
|
|
bdf733973c | ||
|
|
0f45386673 | ||
|
|
88d2a97670 | ||
|
|
922c361f6a | ||
|
|
0e4db0b28f | ||
|
|
d150a2f4dd | ||
|
|
5eeb704f25 | ||
|
|
e3c2a95e5f | ||
|
|
e45ddc086f | ||
|
|
51ced7d3e3 |
@@ -28,7 +28,7 @@ fi
|
||||
|
||||
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
|
||||
rm -f /etc/profile.d/00-restore-env.sh
|
||||
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" >/etc/profile.d/00-restore-env.sh
|
||||
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
|
||||
chmod +x /etc/profile.d/00-restore-env.sh
|
||||
|
||||
# If in automatic mode, determine if a user already exists, if not use vscode
|
||||
@@ -36,7 +36,7 @@ if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
||||
USERNAME=""
|
||||
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
|
||||
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
|
||||
if id -u ${CURRENT_USER} >/dev/null 2>&1; then
|
||||
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
|
||||
USERNAME=${CURRENT_USER}
|
||||
break
|
||||
fi
|
||||
@@ -61,7 +61,8 @@ fi
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Function to call apt-get if needed
|
||||
apt_get_update_if_needed() {
|
||||
apt_get_update_if_needed()
|
||||
{
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
@@ -101,7 +102,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
libkrb5-3 \
|
||||
libgssapi-krb5-2 \
|
||||
libicu[0-9][0-9] \
|
||||
liblttng-ust0 \
|
||||
liblttng-ust[0-9] \
|
||||
libstdc++6 \
|
||||
zlib1g \
|
||||
locales \
|
||||
@@ -112,7 +113,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
manpages \
|
||||
manpages-dev \
|
||||
init-system-helpers"
|
||||
|
||||
|
||||
# Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian
|
||||
if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then
|
||||
# Bring in variables from /etc/os-release like VERSION_CODENAME
|
||||
@@ -123,7 +124,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
|
||||
# Handle bullseye location for security https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html
|
||||
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
|
||||
@@ -139,7 +140,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
|
||||
package_list="${package_list} libssl1.1"
|
||||
fi
|
||||
|
||||
|
||||
# Install appropriate version of libssl1.0.x if available
|
||||
libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
|
||||
if [ "$(echo "$LIlibssl_packageBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
|
||||
@@ -153,10 +154,10 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
fi
|
||||
|
||||
echo "Packages to verify are installed: ${package_list}"
|
||||
apt-get -y install --no-install-recommends ${package_list} 2> >(grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2)
|
||||
|
||||
apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
|
||||
|
||||
# Install git if not already installed (may be more recent than distro version)
|
||||
if ! type git >/dev/null 2>&1; then
|
||||
if ! type git > /dev/null 2>&1; then
|
||||
apt-get -y install --no-install-recommends git
|
||||
fi
|
||||
|
||||
@@ -172,22 +173,22 @@ fi
|
||||
|
||||
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
|
||||
# Common need for both applications and things like the agnoster ZSH theme.
|
||||
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen >/dev/null; then
|
||||
echo "en_US.UTF-8 UTF-8" >>/etc/locale.gen
|
||||
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
|
||||
locale-gen
|
||||
LOCALE_ALREADY_SET="true"
|
||||
fi
|
||||
|
||||
# Create or update a non-root user to match UID/GID.
|
||||
group_name="${USERNAME}"
|
||||
if id -u ${USERNAME} >/dev/null 2>&1; then
|
||||
if id -u ${USERNAME} > /dev/null 2>&1; then
|
||||
# User exists, update if needed
|
||||
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
|
||||
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
|
||||
group_name="$(id -gn $USERNAME)"
|
||||
groupmod --gid $USER_GID ${group_name}
|
||||
usermod --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
|
||||
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
|
||||
usermod --uid $USER_UID $USERNAME
|
||||
fi
|
||||
else
|
||||
@@ -197,42 +198,43 @@ else
|
||||
else
|
||||
groupadd --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "${USER_UID}" = "automatic" ]; then
|
||||
if [ "${USER_UID}" = "automatic" ]; then
|
||||
useradd -s /bin/bash --gid $USERNAME -m $USERNAME
|
||||
else
|
||||
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add add sudo support for non-root user
|
||||
# Add sudo support for non-root user
|
||||
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
|
||||
echo $USERNAME ALL=\(root\) NOPASSWD:ALL >/etc/sudoers.d/$USERNAME
|
||||
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
|
||||
chmod 0440 /etc/sudoers.d/$USERNAME
|
||||
EXISTING_NON_ROOT_USER="${USERNAME}"
|
||||
fi
|
||||
|
||||
# ** Shell customization section **
|
||||
if [ "${USERNAME}" = "root" ]; then
|
||||
if [ "${USERNAME}" = "root" ]; then
|
||||
user_rc_path="/root"
|
||||
else
|
||||
user_rc_path="/home/${USERNAME}"
|
||||
fi
|
||||
|
||||
# Restore user .bashrc defaults from skeleton file if it doesn't exist or is empty
|
||||
if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ]; then
|
||||
cp /etc/skel/.bashrc "${user_rc_path}/.bashrc"
|
||||
if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ] ; then
|
||||
cp /etc/skel/.bashrc "${user_rc_path}/.bashrc"
|
||||
fi
|
||||
|
||||
# Restore user .profile defaults from skeleton file if it doesn't exist or is empty
|
||||
if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ]; then
|
||||
cp /etc/skel/.profile "${user_rc_path}/.profile"
|
||||
if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ] ; then
|
||||
cp /etc/skel/.profile "${user_rc_path}/.profile"
|
||||
fi
|
||||
|
||||
# .bashrc/.zshrc snippet
|
||||
rc_snippet="$(
|
||||
cat <<'EOF'
|
||||
rc_snippet="$(cat << 'EOF'
|
||||
|
||||
if [ -z "${USER}" ]; then export USER=$(whoami); fi
|
||||
if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi
|
||||
|
||||
# Display optional first run image specific notice if configured and terminal is interactive
|
||||
if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then
|
||||
if [ -f "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" ]; then
|
||||
@@ -244,6 +246,7 @@ if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespace
|
||||
# Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it
|
||||
((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &)
|
||||
fi
|
||||
|
||||
# Set the default git editor if not already set
|
||||
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
|
||||
if [ "${TERM_PROGRAM}" = "vscode" ]; then
|
||||
@@ -254,16 +257,20 @@ if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
# code shim, it fallbacks to code-insiders if code is not available
|
||||
cat <<'EOF' >/usr/local/bin/code
|
||||
cat << 'EOF' > /usr/local/bin/code
|
||||
#!/bin/sh
|
||||
|
||||
get_in_path_except_current() {
|
||||
which -a "$1" | grep -A1 "$0" | grep -v "$0"
|
||||
}
|
||||
|
||||
code="$(get_in_path_except_current code)"
|
||||
|
||||
if [ -n "$code" ]; then
|
||||
exec "$code" "$@"
|
||||
elif [ "$(command -v code-insiders)" ]; then
|
||||
@@ -276,21 +283,21 @@ EOF
|
||||
chmod +x /usr/local/bin/code
|
||||
|
||||
# systemctl shim - tells people to use 'service' if systemd is not running
|
||||
cat <<'EOF' >/usr/local/bin/systemctl
|
||||
cat << 'EOF' > /usr/local/bin/systemctl
|
||||
#!/bin/sh
|
||||
set -e
|
||||
if [ -d "/run/systemd/system" ]; then
|
||||
exec /bin/systemctl/systemctl "$@"
|
||||
exec /bin/systemctl "$@"
|
||||
else
|
||||
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services intead. e.g.: \n\nservice --status-all'
|
||||
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services instead. e.g.: \n\nservice --status-all'
|
||||
fi
|
||||
EOF
|
||||
chmod +x /usr/local/bin/systemctl
|
||||
|
||||
# Codespaces bash and OMZ themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
|
||||
codespaces_bash="$(
|
||||
cat \
|
||||
<<'EOF'
|
||||
codespaces_bash="$(cat \
|
||||
<<'EOF'
|
||||
|
||||
# Codespaces bash prompt theme
|
||||
__bash_prompt() {
|
||||
local userpart='`export XIT=$? \
|
||||
@@ -313,12 +320,12 @@ __bash_prompt() {
|
||||
unset -f __bash_prompt
|
||||
}
|
||||
__bash_prompt
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
codespaces_zsh="$(
|
||||
cat \
|
||||
<<'EOF'
|
||||
codespaces_zsh="$(cat \
|
||||
<<'EOF'
|
||||
# Codespaces zsh prompt theme
|
||||
__zsh_prompt() {
|
||||
local prompt_username
|
||||
@@ -338,17 +345,18 @@ ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
|
||||
ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[yellow]%}✗%{$fg_bold[cyan]%})"
|
||||
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[cyan]%})"
|
||||
__zsh_prompt
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Add RC snippet and custom bash prompt
|
||||
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
|
||||
echo "${rc_snippet}" >>/etc/bash.bashrc
|
||||
echo "${codespaces_bash}" >>"${user_rc_path}/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >>"${user_rc_path}/.bashrc"
|
||||
echo "${rc_snippet}" >> /etc/bash.bashrc
|
||||
echo "${codespaces_bash}" >> "${user_rc_path}/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >> "${user_rc_path}/.bashrc"
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
echo "${codespaces_bash}" >>"/root/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >>"/root/.bashrc"
|
||||
echo "${codespaces_bash}" >> "/root/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc"
|
||||
fi
|
||||
chown ${USERNAME}:${group_name} "${user_rc_path}/.bashrc"
|
||||
RC_SNIPPET_ALREADY_ADDED="true"
|
||||
@@ -356,12 +364,12 @@ fi
|
||||
|
||||
# Optionally install and configure zsh and Oh My Zsh!
|
||||
if [ "${INSTALL_ZSH}" = "true" ]; then
|
||||
if ! type zsh >/dev/null 2>&1; then
|
||||
if ! type zsh > /dev/null 2>&1; then
|
||||
apt_get_update_if_needed
|
||||
apt-get install -y zsh
|
||||
fi
|
||||
if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
|
||||
echo "${rc_snippet}" >>/etc/zsh/zshrc
|
||||
echo "${rc_snippet}" >> /etc/zsh/zshrc
|
||||
ZSH_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
@@ -380,11 +388,11 @@ if [ "${INSTALL_ZSH}" = "true" ]; then
|
||||
-c fetch.fsck.zeroPaddedFilemode=ignore \
|
||||
-c receive.fsck.zeroPaddedFilemode=ignore \
|
||||
"https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1
|
||||
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" >${user_rc_file}
|
||||
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file}
|
||||
sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${user_rc_file}
|
||||
|
||||
mkdir -p ${oh_my_install_dir}/custom/themes
|
||||
echo "${codespaces_zsh}" >"${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
|
||||
echo "${codespaces_zsh}" > "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
|
||||
# Shrink git while still enabling updates
|
||||
cd "${oh_my_install_dir}"
|
||||
git repack -a -d -f --depth=1 --window=1
|
||||
@@ -397,10 +405,10 @@ if [ "${INSTALL_ZSH}" = "true" ]; then
|
||||
fi
|
||||
|
||||
# Persist image metadata info, script if meta.env found in same directory
|
||||
meta_info_script="$(
|
||||
cat <<'EOF'
|
||||
meta_info_script="$(cat << 'EOF'
|
||||
#!/bin/sh
|
||||
. /usr/local/etc/vscode-dev-containers/meta.env
|
||||
|
||||
# Minimal output
|
||||
if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then
|
||||
echo "${VERSION}"
|
||||
@@ -412,6 +420,7 @@ elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] |
|
||||
echo "${CONTENTS_URL}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#Full output
|
||||
echo
|
||||
echo "Development container image information"
|
||||
@@ -429,7 +438,7 @@ EOF
|
||||
if [ -f "${SCRIPT_DIR}/meta.env" ]; then
|
||||
mkdir -p /usr/local/etc/vscode-dev-containers/
|
||||
cp -f "${SCRIPT_DIR}/meta.env" /usr/local/etc/vscode-dev-containers/meta.env
|
||||
echo "${meta_info_script}" >/usr/local/bin/devcontainer-info
|
||||
echo "${meta_info_script}" > /usr/local/bin/devcontainer-info
|
||||
chmod +x /usr/local/bin/devcontainer-info
|
||||
fi
|
||||
|
||||
@@ -440,6 +449,6 @@ echo -e "\
|
||||
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
|
||||
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
|
||||
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
|
||||
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" >"${MARKER_FILE}"
|
||||
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
|
||||
|
||||
echo "Done!"
|
||||
echo "Done!"
|
||||
@@ -156,6 +156,23 @@ check_packages() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Fall back on direct download if no apt package exists
|
||||
# Fetches .deb file to be installed with dpkg
|
||||
install_deb_using_github() {
|
||||
check_packages wget
|
||||
arch=$(dpkg --print-architecture)
|
||||
|
||||
find_version_from_git_tags CLI_VERSION https://github.com/cli/cli
|
||||
cli_filename="gh_${CLI_VERSION}_linux_${arch}.deb"
|
||||
|
||||
mkdir -p /tmp/ghcli
|
||||
pushd /tmp/ghcli
|
||||
wget https://github.com/cli/cli/releases/download/v${CLI_VERSION}/${cli_filename}
|
||||
dpkg -i /tmp/ghcli/${cli_filename}
|
||||
popd
|
||||
rm -rf /tmp/ghcli
|
||||
}
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing
|
||||
@@ -175,11 +192,16 @@ fi
|
||||
|
||||
# Install the GitHub CLI
|
||||
echo "Downloading github CLI..."
|
||||
# Import key safely (new method rather than deprecated apt-key approach) and install
|
||||
. /etc/os-release
|
||||
receive_gpg_keys GITHUB_CLI_ARCHIVE_GPG_KEY /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages ${VERSION_CODENAME} main" >/etc/apt/sources.list.d/github-cli.list
|
||||
apt-get update
|
||||
apt-get -y install "gh${version_suffix}"
|
||||
rm -rf "/tmp/gh/gnupg"
|
||||
|
||||
install_deb_using_github
|
||||
|
||||
# Method below does not work until cli/cli#6175 is fixed
|
||||
# # Import key safely (new method rather than deprecated apt-key approach) and install
|
||||
# . /etc/os-release
|
||||
# receive_gpg_keys GITHUB_CLI_ARCHIVE_GPG_KEY /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" >/etc/apt/sources.list.d/github-cli.list
|
||||
# apt-get update
|
||||
# apt-get -y install "gh${version_suffix}"
|
||||
# rm -rf "/tmp/gh/gnupg"
|
||||
|
||||
echo "Done!"
|
||||
|
||||
2
.github/labels.yml
vendored
2
.github/labels.yml
vendored
@@ -24,6 +24,8 @@
|
||||
color: 'c66037'
|
||||
- name: 'node.js'
|
||||
color: '0E8A16'
|
||||
- name: 'napi'
|
||||
color: 'BE05D2'
|
||||
- name: 'esm<>cjs'
|
||||
color: '7dcde3'
|
||||
- name: 'performance'
|
||||
|
||||
10
.github/workflows/bun-linux-build.yml
vendored
10
.github/workflows/bun-linux-build.yml
vendored
@@ -37,21 +37,21 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: linux-amd64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
- cpu: westmere
|
||||
tag: linux-x64-baseline
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: linux-amd64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
- cpu: native
|
||||
tag: linux-aarch64
|
||||
arch: aarch64
|
||||
build_arch: arm64
|
||||
runner: linux-arm64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-arm64-lto"
|
||||
|
||||
steps:
|
||||
@@ -76,8 +76,8 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
cache-from: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.build_arch}}
|
||||
cache-to: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.build_arch}},mode=max
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
ARCH=${{matrix.arch}}
|
||||
BUILDARCH=${{matrix.build_arch}}
|
||||
|
||||
20
.github/workflows/bun-mac-aarch64.yml
vendored
20
.github/workflows/bun-mac-aarch64.yml
vendored
@@ -63,8 +63,8 @@ jobs:
|
||||
context: .
|
||||
push: false
|
||||
tags: ghcr.io/oven-sh/bun-obj:${{github.sha}}-${{matrix.cpu}}-${{matrix.arch}}-macos
|
||||
cache-from: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos
|
||||
cache-to: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos,mode=max
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
ARCH=${{ matrix.arch }}
|
||||
BUILDARCH=amd64
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: westmere
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: native
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
tag: bun-darwin-aarch64
|
||||
obj: bun-obj-darwin-aarch64
|
||||
artifact: bun-obj-darwin-aarch64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
dependencies: true
|
||||
compile_obj: true
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -233,14 +233,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: native
|
||||
arch: aarch64
|
||||
tag: bun-darwin-aarch64
|
||||
obj: bun-obj-darwin-aarch64
|
||||
package: bun-darwin-aarch64
|
||||
artifact: bun-obj-darwin-aarch64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
20
.github/workflows/bun-mac-x64-baseline.yml
vendored
20
.github/workflows/bun-mac-x64-baseline.yml
vendored
@@ -63,8 +63,8 @@ jobs:
|
||||
context: .
|
||||
push: false
|
||||
tags: ghcr.io/oven-sh/bun-obj:${{github.sha}}-${{matrix.cpu}}-${{matrix.arch}}-macos-baseline
|
||||
cache-from: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos-baseline
|
||||
cache-to: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos-baseline,mode=max
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
ARCH=${{ matrix.arch }}
|
||||
BUILDARCH=amd64
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: westmere
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -227,14 +227,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: native
|
||||
# arch: aarch64
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# package: bun-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
21
.github/workflows/bun-mac-x64.yml
vendored
21
.github/workflows/bun-mac-x64.yml
vendored
@@ -62,9 +62,8 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
tags: ghcr.io/oven-sh/bun-obj:${{github.sha}}-${{matrix.cpu}}-${{matrix.arch}}-macos
|
||||
cache-from: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos
|
||||
cache-to: type=registry,ref=ghcr.io/oven-sh/bun-obj:buildcache-bust-3--${{matrix.cpu}}-${{matrix.arch}}-macos,mode=max
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=min
|
||||
build-args: |
|
||||
ARCH=${{ matrix.arch }}
|
||||
BUILDARCH=amd64
|
||||
@@ -91,7 +90,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: haswell
|
||||
@@ -100,7 +99,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: westmere
|
||||
@@ -109,7 +108,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: haswell
|
||||
@@ -118,7 +117,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -126,7 +125,7 @@ jobs:
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -221,7 +220,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: haswell
|
||||
arch: x86_64
|
||||
tag: bun-darwin-x64
|
||||
@@ -229,14 +228,14 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: native
|
||||
# arch: aarch64
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# package: bun-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -103,3 +103,4 @@ src/runtime.version
|
||||
*.sqlite
|
||||
*.database
|
||||
*.db
|
||||
misctools/machbench
|
||||
|
||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -7,7 +7,7 @@ shallow = true
|
||||
fetchRecurseSubmodules = false
|
||||
[submodule "src/javascript/jsc/WebKit"]
|
||||
path = src/bun.js/WebKit
|
||||
url = https://github.com/Jarred-Sumner/WebKit.git
|
||||
url = https://github.com/oven-sh/WebKit.git
|
||||
ignore = dirty
|
||||
depth = 1
|
||||
update = none
|
||||
@@ -69,3 +69,10 @@ ignore = dirty
|
||||
depth = 1
|
||||
shallow = true
|
||||
fetchRecurseSubmodules = false
|
||||
[submodule "src/deps/oniguruma"]
|
||||
path = src/deps/oniguruma
|
||||
url = https://github.com/kkos/oniguruma
|
||||
ignore = dirty
|
||||
depth = 1
|
||||
shallow = true
|
||||
fetchRecurseSubmodules = false
|
||||
|
||||
41
.vscode/c_cpp_properties.json
vendored
41
.vscode/c_cpp_properties.json
vendored
@@ -4,22 +4,35 @@
|
||||
"name": "Mac",
|
||||
"forcedInclude": ["${workspaceFolder}/src/bun.js/bindings/root.h"],
|
||||
"includePath": [
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/WTF/Headers",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/*",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/bindings/",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/Source/bmalloc/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/"
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/*",
|
||||
"${workspaceFolder}/src/bun.js/bindings/",
|
||||
"${workspaceFolder}/src/bun.js/builtins/",
|
||||
"${workspaceFolder}/src/bun.js/builtins/cpp",
|
||||
"${workspaceFolder}/src/bun.js/bindings/WebCore/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/Source/bmalloc/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/",
|
||||
"${workspaceFolder}/../webkit-build/include/",
|
||||
"${workspaceFolder}/src/deps",
|
||||
"${workspaceFolder}/src/deps/uws/uSockets/src"
|
||||
],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${workspaceFolder}/src/bun.js/bindings/*",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/WebKitBuild/Release/*",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/bindings/**",
|
||||
"${workspaceFolder}/src/JavaScript/jsc/WebKit/Source/bmalloc/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/"
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/*",
|
||||
"${workspaceFolder}/src/bun.js/bindings/**",
|
||||
"${workspaceFolder}/src/bun.js/modules/**",
|
||||
"${workspaceFolder}/src/bun.js/builtins/**",
|
||||
"${workspaceFolder}/src/bun.js/builtins/cpp/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/Source/bmalloc/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/",
|
||||
"${workspaceFolder}/../webkit-build/include/",
|
||||
"${workspaceFolder}/src/deps",
|
||||
"${workspaceFolder}/src/deps/uws/uSockets/src"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ".vscode/cppdb"
|
||||
@@ -36,9 +49,9 @@
|
||||
"DU_DISABLE_RENAMING=1"
|
||||
],
|
||||
"macFrameworkPath": [],
|
||||
"compilerPath": "/usr/local/opt/llvm/bin/clang",
|
||||
"compilerPath": "clang++",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++11",
|
||||
"cppStandard": "c++20",
|
||||
"intelliSenseMode": "macos-clang-x64"
|
||||
}
|
||||
],
|
||||
|
||||
2
.vscode/launch.json
generated
vendored
2
.vscode/launch.json
generated
vendored
@@ -6,7 +6,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun test",
|
||||
"program": "bun-debug",
|
||||
"args": ["wiptest", "jsc"],
|
||||
"args": ["wiptest", "${file}"],
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
|
||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@@ -164,7 +164,21 @@
|
||||
"numeric": "cpp",
|
||||
"set": "cpp",
|
||||
"__memory": "cpp",
|
||||
"memory_resource": "cpp"
|
||||
"memory_resource": "cpp",
|
||||
"resource.h": "c",
|
||||
"sysinfo.h": "c",
|
||||
"*.tcc": "cpp",
|
||||
"list": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"variant": "cpp",
|
||||
"sysctl.h": "c",
|
||||
"interface_adresses.h": "c",
|
||||
"interface_addresses.h": "c",
|
||||
"ctype.h": "c",
|
||||
"ethernet.h": "c",
|
||||
"inet.h": "c",
|
||||
"packet.h": "c"
|
||||
},
|
||||
"cmake.configureOnOpen": false
|
||||
}
|
||||
|
||||
12
CODE_OF_CONDUCT.md
Normal file
12
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## Code of conduct
|
||||
|
||||
- We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
|
||||
- Please avoid using overtly sexual aliases or other nicknames that might detract from a friendly, safe and welcoming environment for all.
|
||||
- Please be kind and courteous. There’s no need to be mean or rude.
|
||||
- Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
|
||||
- Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
|
||||
- We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term “harassment” as including the definition in the [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md); if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don’t tolerate behavior that excludes people in socially marginalized groups.
|
||||
- Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or an employee of Oven immediately. Whether you’re a regular contributor or a newcomer, we care about making this community a safe place for you and we’ve got your back.
|
||||
- Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
|
||||
|
||||
This code of conduct is adapted from the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct).
|
||||
45
Dockerfile
45
Dockerfile
@@ -16,7 +16,7 @@ ARG WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/$WEBKIT_TAG/
|
||||
|
||||
ARG ZIG_URL="https://github.com/oven-sh/zig/releases/download/$ZIG_TAG/zig-linux-$BUILDARCH.zip"
|
||||
ARG GIT_SHA=""
|
||||
ARG BUN_BASE_VERSION=0.1
|
||||
ARG BUN_BASE_VERSION=0.2
|
||||
|
||||
|
||||
FROM bitnami/minideb:bullseye as bun-base
|
||||
@@ -183,8 +183,29 @@ RUN install_packages autoconf automake libtool pkg-config
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/libarchive ${BUN_DIR}/src/deps/libarchive
|
||||
|
||||
RUN cd $BUN_DIR && \
|
||||
make libarchive && rm -rf src/deps/libarchive Makefile
|
||||
|
||||
FROM bun-base as oniguruma
|
||||
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG GITHUB_WORKSPACE
|
||||
ARG ZIG_PATH
|
||||
# Directory extracts to "bun-webkit"
|
||||
ARG WEBKIT_DIR
|
||||
ARG BUN_RELEASE_DIR
|
||||
ARG BUN_DEPS_OUT_DIR
|
||||
ARG BUN_DIR
|
||||
ARG CPU_TARGET
|
||||
ENV CPU_TARGET=${CPU_TARGET}
|
||||
|
||||
RUN install_packages autoconf automake libtool pkg-config
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/oniguruma ${BUN_DIR}/src/deps/oniguruma
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
RUN make libarchive && rm -rf src/deps/libarchive Makefile
|
||||
RUN make oniguruma && rm -rf src/deps/oniguruma Makefile
|
||||
|
||||
FROM bun-base as tinycc
|
||||
|
||||
@@ -456,15 +477,16 @@ WORKDIR $BUN_DIR
|
||||
ENV JSC_BASE_DIR=${WEBKIT_DIR}
|
||||
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
|
||||
|
||||
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=mimalloc ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=oniguruma ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=picohttp ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libbacktrace ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=base64 ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
|
||||
@@ -515,18 +537,19 @@ WORKDIR $BUN_DIR
|
||||
ENV JSC_BASE_DIR=${WEBKIT_DIR}
|
||||
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
|
||||
|
||||
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=base64 ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libbacktrace ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=mimalloc ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=oniguruma ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=picohttp ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=sqlite ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libbacktrace ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=base64 ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=sqlite ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=build_release_obj /*.o /tmp
|
||||
COPY --from=build_release_cpp /*.o ${BUN_DIR}/src/bun.js/bindings-obj/
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ ARG BUN_RELEASE_DIR=${GITHUB_WORKSPACE}/bun-release
|
||||
ARG BUN_DEPS_OUT_DIR=${GITHUB_WORKSPACE}/bun-deps
|
||||
ARG BUN_DIR=${GITHUB_WORKSPACE}/bun
|
||||
|
||||
FROM --platform=linux/${BUILDARCH} ubuntu:20.04 as bun.devcontainer
|
||||
FROM --platform=linux/${BUILDARCH} ubuntu:22.04 as bun.devcontainer
|
||||
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG GITHUB_WORKSPACE
|
||||
@@ -88,7 +88,7 @@ RUN cd $GITHUB_WORKSPACE && \
|
||||
rm zig-linux-$BUILDARCH.zip;
|
||||
|
||||
RUN cd $GITHUB_WORKSPACE && \
|
||||
curl -o bun-webkit-linux-$BUILDARCH.tar.gz -L https://github.com/oven-sh/WebKit/releases/download/aug12-2/bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
curl -o bun-webkit-linux-$BUILDARCH.tar.gz -L https://github.com/oven-sh/WebKit/releases/download/oct8/bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
tar -xzf bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
rm bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
cat $WEBKIT_OUT_DIR/include/cmakeconfig.h > /dev/null
|
||||
|
||||
150
Makefile
150
Makefile
@@ -35,6 +35,7 @@ NATIVE_OR_OLD_MARCH = -march=westmere
|
||||
endif
|
||||
|
||||
MIN_MACOS_VERSION ?= $(DEFAULT_MIN_MACOS_VERSION)
|
||||
BUN_BASE_VERSION = 0.2
|
||||
|
||||
AR=
|
||||
|
||||
@@ -50,7 +51,7 @@ RELEASE_BUN = $(PACKAGE_DIR)/bun
|
||||
DEBUG_BIN = $(DEBUG_PACKAGE_DIR)/
|
||||
DEBUG_BUN = $(DEBUG_BIN)/bun-debug
|
||||
BUILD_ID = $(shell cat ./build-id)
|
||||
PACKAGE_JSON_VERSION = 0.1.$(BUILD_ID)
|
||||
PACKAGE_JSON_VERSION = $(BUN_BASE_VERSION).$(BUILD_ID)
|
||||
BUN_BUILD_TAG = bun-v$(PACKAGE_JSON_VERSION)
|
||||
BUN_RELEASE_BIN = $(PACKAGE_DIR)/bun
|
||||
PRETTIER ?= $(shell which prettier || echo "./node_modules/.bin/prettier")
|
||||
@@ -227,7 +228,7 @@ STRIP=/usr/bin/strip
|
||||
endif
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
STRIP=$(which llvm-strip || which llvm-strip-13 || which strip || echo "Missing strip")
|
||||
STRIP=$(shell which llvm-strip || which llvm-strip-13 || which strip || echo "Missing strip")
|
||||
endif
|
||||
|
||||
|
||||
@@ -235,27 +236,37 @@ HOMEBREW_PREFIX ?= $(BREW_PREFIX_PATH)
|
||||
|
||||
|
||||
SRC_DIR := src/bun.js/bindings
|
||||
MODULES_DIR := src/bun.js/modules
|
||||
OBJ_DIR ?= src/bun.js/bindings-obj
|
||||
DEBUG_OBJ_DIR := src/bun.js/debug-bindings-obj
|
||||
|
||||
SRC_PATH := $(realpath $(SRC_DIR))
|
||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
|
||||
MODULES_FILES := $(wildcard $(MODULES_DIR)/*.cpp)
|
||||
SRC_WEBCORE_FILES := $(wildcard $(SRC_DIR)/webcore/*.cpp)
|
||||
SRC_SQLITE_FILES := $(wildcard $(SRC_DIR)/sqlite/*.cpp)
|
||||
SRC_NODE_OS_FILES := $(wildcard $(SRC_DIR)/node_os/*.cpp)
|
||||
SRC_IO_FILES := $(wildcard src/io/*.cpp)
|
||||
SRC_BUILTINS_FILES := $(wildcard src/bun.js/builtins/*.cpp)
|
||||
|
||||
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
|
||||
WEBCORE_OBJ_FILES := $(patsubst $(SRC_DIR)/webcore/%.cpp,$(OBJ_DIR)/%.o,$(SRC_WEBCORE_FILES))
|
||||
SQLITE_OBJ_FILES := $(patsubst $(SRC_DIR)/sqlite/%.cpp,$(OBJ_DIR)/%.o,$(SRC_SQLITE_FILES))
|
||||
NODE_OS_OBJ_FILES := $(patsubst $(SRC_DIR)/node_os/%.cpp,$(OBJ_DIR)/%.o,$(SRC_NODE_OS_FILES))
|
||||
BUILTINS_OBJ_FILES := $(patsubst src/bun.js/builtins/%.cpp,$(OBJ_DIR)/%.o,$(SRC_BUILTINS_FILES))
|
||||
IO_FILES := $(patsubst src/io/%.cpp,$(OBJ_DIR)/%.o,$(SRC_IO_FILES))
|
||||
MODULES_OBJ_FILES := $(patsubst $(MODULES_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(MODULES_FILES))
|
||||
|
||||
DEBUG_OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_FILES))
|
||||
DEBUG_WEBCORE_OBJ_FILES := $(patsubst $(SRC_DIR)/webcore/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_WEBCORE_FILES))
|
||||
DEBUG_SQLITE_OBJ_FILES := $(patsubst $(SRC_DIR)/sqlite/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_SQLITE_FILES))
|
||||
DEBUG_NODE_OS_OBJ_FILES := $(patsubst $(SRC_DIR)/node_os/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_NODE_OS_FILES))
|
||||
DEBUG_BUILTINS_OBJ_FILES := $(patsubst src/bun.js/builtins/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_BUILTINS_FILES))
|
||||
DEBUG_IO_FILES := $(patsubst src/io/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(SRC_IO_FILES))
|
||||
DEBUG_MODULES_OBJ_FILES := $(patsubst $(MODULES_DIR)/%.cpp,$(DEBUG_OBJ_DIR)/%.o,$(MODULES_FILES))
|
||||
|
||||
BINDINGS_OBJ := $(OBJ_FILES) $(WEBCORE_OBJ_FILES) $(SQLITE_OBJ_FILES) $(BUILTINS_OBJ_FILES)
|
||||
DEBUG_BINDINGS_OBJ := $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES)
|
||||
BINDINGS_OBJ := $(OBJ_FILES) $(WEBCORE_OBJ_FILES) $(SQLITE_OBJ_FILES) $(NODE_OS_OBJ_FILES) $(BUILTINS_OBJ_FILES) $(IO_FILES) $(MODULES_OBJ_FILES)
|
||||
DEBUG_BINDINGS_OBJ := $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_NODE_OS_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES) $(DEBUG_IO_FILES) $(DEBUG_MODULES_OBJ_FILES)
|
||||
|
||||
MAC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders \
|
||||
-I$(WEBKIT_RELEASE_DIR)/WTF/Headers \
|
||||
@@ -266,6 +277,7 @@ MAC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders \
|
||||
-Isrc/bun.js/bindings/webcore \
|
||||
-Isrc/bun.js/bindings/sqlite \
|
||||
-Isrc/bun.js/builtins/cpp \
|
||||
-Isrc/bun.js/bindings/node_os \
|
||||
-Isrc/bun.js/modules \
|
||||
-I$(WEBKIT_DIR)/Source/bmalloc \
|
||||
-I$(WEBKIT_DIR)/Source \
|
||||
@@ -277,6 +289,7 @@ LINUX_INCLUDE_DIRS := -I$(JSC_INCLUDE_DIR) \
|
||||
-Isrc/bun.js/bindings/webcore \
|
||||
-Isrc/bun.js/bindings/sqlite \
|
||||
-Isrc/bun.js/builtins/cpp \
|
||||
-Isrc/bun.js/bindings/node_os \
|
||||
-Isrc/bun.js/modules \
|
||||
-I$(ZLIB_INCLUDE_DIR)
|
||||
|
||||
@@ -381,7 +394,8 @@ MINIMUM_ARCHIVE_FILES = -L$(BUN_DEPS_OUT_DIR) \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-llolhtml \
|
||||
$(BUN_DEPS_OUT_DIR)/libbacktrace.a
|
||||
-lonig \
|
||||
$(BUN_DEPS_OUT_DIR)/libbacktrace.a \
|
||||
|
||||
ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MINIMUM_ARCHIVE_FILES) \
|
||||
-larchive \
|
||||
@@ -428,7 +442,7 @@ BUN_LLD_FLAGS_WITHOUT_JSC = $(ARCHIVE_FILES) \
|
||||
|
||||
BUN_LLD_FLAGS = $(BUN_LLD_FLAGS_WITHOUT_JSC) $(JSC_FILES) $(BINDINGS_OBJ)
|
||||
BUN_LLD_FLAGS_DEBUG = $(BUN_LLD_FLAGS_WITHOUT_JSC) $(JSC_FILES_DEBUG) $(DEBUG_BINDINGS_OBJ)
|
||||
BUN_LLD_FLAGS_FAST = $(BUN_LLD_FLAGS_DEBUG)
|
||||
BUN_LLD_FLAGS_FAST = $(BUN_LLD_FLAGS_WITHOUT_JSC) $(JSC_FILES_DEBUG) $(BINDINGS_OBJ)
|
||||
|
||||
CLANG_VERSION = $(shell $(CC) --version | awk '/version/ {for(i=1; i<=NF; i++){if($$i=="version"){split($$(i+1),v,".");print v[1]}}}')
|
||||
|
||||
@@ -470,9 +484,13 @@ builtins: ## to generate builtins
|
||||
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --force
|
||||
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --wrappers-only
|
||||
rm -rf /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1
|
||||
echo -e '// clang-format off\nnamespace Zig { class GlobalObject; }' >> /tmp/1.h
|
||||
echo -e '// clang-format off\nnamespace Zig { class GlobalObject; }\n#include "root.h"\n' >> /tmp/1.h
|
||||
cat /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h > src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1
|
||||
mv src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1 src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h
|
||||
rm -rf /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1
|
||||
echo -e '// clang-format off\nnamespace Zig { class GlobalObject; }\n#include "root.h"\n' >> /tmp/1.h
|
||||
cat /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.cpp > src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.cpp.1
|
||||
mv src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.cpp.1 src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.cpp
|
||||
$(SED) -i -e 's/class JSDOMGlobalObject/using JSDOMGlobalObject = Zig::GlobalObject/' src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h
|
||||
# this is the one we actually build
|
||||
mv src/bun.js/builtins/cpp/*JSBuiltin*.cpp src/bun.js/builtins
|
||||
@@ -481,7 +499,7 @@ builtins: ## to generate builtins
|
||||
generate-builtins: builtins
|
||||
|
||||
.PHONY: tinycc
|
||||
vendor-without-check: npm-install node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive libbacktrace lolhtml usockets uws base64 tinycc
|
||||
vendor-without-check: npm-install node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive libbacktrace lolhtml usockets uws base64 tinycc oniguruma
|
||||
|
||||
BUN_TYPES_REPO_PATH ?= $(realpath ../bun-types)
|
||||
|
||||
@@ -535,6 +553,13 @@ libbacktrace:
|
||||
make -j$(CPUS) && \
|
||||
cp ./.libs/libbacktrace.a $(BUN_DEPS_OUT_DIR)/libbacktrace.a
|
||||
|
||||
.PHONY: oniguruma
|
||||
oniguruma:
|
||||
cd $(BUN_DEPS_DIR)/oniguruma && \
|
||||
autoreconf -vfi && \
|
||||
CFLAGS="$(CFLAGS)" CC=$(CC) ./configure && \
|
||||
make -j${CPUS} && \
|
||||
cp ./src/.libs/libonig.a $(BUN_DEPS_OUT_DIR)/libonig.a
|
||||
|
||||
sqlite:
|
||||
|
||||
@@ -746,9 +771,9 @@ generate-install-script:
|
||||
@esbuild --log-level=error --define:BUN_VERSION="\"$(PACKAGE_JSON_VERSION)\"" --define:process.env.NODE_ENV="\"production\"" --platform=node --format=cjs $(PACKAGES_REALPATH)/bun/install.ts > $(PACKAGES_REALPATH)/bun/install.js
|
||||
|
||||
.PHONY: fetch
|
||||
fetch:
|
||||
fetch: $(IO_FILES)
|
||||
$(ZIG) build -Drelease-fast fetch-obj
|
||||
$(CXX) $(PACKAGE_DIR)/fetch.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/fetch $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
$(CXX) $(PACKAGE_DIR)/fetch.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/fetch $(IO_FILES) $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
rm -rf $(PACKAGE_DIR)/fetch.o
|
||||
|
||||
.PHONY: sha
|
||||
@@ -758,19 +783,31 @@ sha:
|
||||
rm -rf $(PACKAGE_DIR)/sha.o
|
||||
|
||||
.PHONY: fetch-debug
|
||||
fetch-debug:
|
||||
fetch-debug: $(IO_FILES)
|
||||
$(ZIG) build fetch-obj
|
||||
$(CXX) $(DEBUG_PACKAGE_DIR)/fetch.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/fetch $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
$(CXX) $(DEBUG_PACKAGE_DIR)/fetch.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/fetch $(DEBUG_IO_FILES) $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
|
||||
.PHONY: machbench-debug
|
||||
machbench-debug: $(IO_FILES)
|
||||
$(ZIG) build machbench-obj
|
||||
$(CXX) $(DEBUG_PACKAGE_DIR)/machbench.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/machbench $(DEBUG_IO_FILES) $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
|
||||
.PHONY: machbench
|
||||
machbench: $(IO_FILES)
|
||||
$(ZIG) build -Drelease-fast machbench-obj
|
||||
$(CXX) $(PACKAGE_DIR)/machbench.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/machbench $(IO_FILES) $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
rm -rf $(PACKAGE_DIR)/machbench.o
|
||||
|
||||
|
||||
.PHONY: httpbench-debug
|
||||
httpbench-debug:
|
||||
httpbench-debug: $(IO_FILES)
|
||||
$(ZIG) build httpbench-obj
|
||||
$(CXX) $(DEBUG_PACKAGE_DIR)/httpbench.o -fuse-ld=lld -g -o ./misctools/http_bench $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
$(CXX) $(IO_FILES) $(DEBUG_PACKAGE_DIR)/httpbench.o -g -o ./misctools/http_bench $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
|
||||
.PHONY: httpbench-release
|
||||
httpbench-release:
|
||||
httpbench-release: $(IO_FILES)
|
||||
$(ZIG) build -Drelease-fast httpbench-obj
|
||||
$(CXX) $(PACKAGE_DIR)/httpbench.o -march=native -mtune=native -fuse-ld=lld -g $(OPTIMIZATION_LEVEL) -o ./misctools/http_bench $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
$(CXX) $(PACKAGE_DIR)/httpbench.o -g $(OPTIMIZATION_LEVEL) -o ./misctools/httpbench $(IO_FILES) $(DEFAULT_LINKER_FLAGS) -lc $(MINIMUM_ARCHIVE_FILES)
|
||||
rm -rf $(PACKAGE_DIR)/httpbench.o
|
||||
|
||||
.PHONY: check-glibc-version-dependency
|
||||
@@ -783,7 +820,7 @@ ifeq ($(OS_NAME),darwin)
|
||||
|
||||
# Hardened runtime will not work with debugging
|
||||
bun-codesign-debug:
|
||||
codesign --entitlements $(realpath entitlements.plist) --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvvv --deep --strict $(DEBUG_BUN)
|
||||
codesign --entitlements $(realpath entitlements.debug.plist) --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvvv --deep --strict $(DEBUG_BUN)
|
||||
|
||||
bun-codesign-release-local:
|
||||
codesign --entitlements $(realpath entitlements.plist) --options runtime --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvvv --deep --strict $(RELEASE_BUN)
|
||||
@@ -814,7 +851,7 @@ clone-submodules:
|
||||
git -c submodule."src/bun.js/WebKit".update=none submodule update --init --recursive --depth=1 --progress
|
||||
|
||||
.PHONY: devcontainer
|
||||
devcontainer: clone-submodules libbacktrace mimalloc zlib libarchive boringssl picohttp identifier-cache node-fallbacks npm-install api analytics bun_error fallback_decoder bindings uws lolhtml usockets base64 tinycc runtime_js_dev sqlite dev
|
||||
devcontainer: $(OBJ_DIR) $(DEBUG_OBJ_DIR) clone-submodules libbacktrace mimalloc zlib libarchive boringssl picohttp identifier-cache node-fallbacks npm-install api analytics bun_error fallback_decoder bindings uws lolhtml usockets base64 tinycc runtime_js_dev sqlite dev
|
||||
|
||||
.PHONY: devcontainer-build
|
||||
devcontainer-build:
|
||||
@@ -831,7 +868,7 @@ headers:
|
||||
rm -f /tmp/build-jsc-headers src/bun.js/bindings/headers.zig
|
||||
touch src/bun.js/bindings/headers.zig
|
||||
$(ZIG) build headers-obj
|
||||
$(CXX) $(PLATFORM_LINKER_FLAGS) $(JSC_FILES_DEBUG) ${ICU_FLAGS} $(BUN_LLD_FLAGS_WITHOUT_JSC) -g $(DEBUG_BIN)/headers.o -W -o /tmp/build-jsc-headers -lc;
|
||||
$(CXX) $(PLATFORM_LINKER_FLAGS) $(JSC_FILES_DEBUG) ${ICU_FLAGS} $(DEBUG_IO_FILES) $(BUN_LLD_FLAGS_WITHOUT_JSC) -g $(DEBUG_BIN)/headers.o -W -o /tmp/build-jsc-headers -lc;
|
||||
/tmp/build-jsc-headers
|
||||
$(ZIG) translate-c src/bun.js/bindings/headers.h > src/bun.js/bindings/headers.zig
|
||||
$(BUN_OR_NODE) misctools/headers-cleaner.js
|
||||
@@ -844,7 +881,7 @@ MIMALLOC_OVERRIDE_FLAG ?=
|
||||
|
||||
|
||||
bump:
|
||||
expr 0.1.0 + 1 > build-id
|
||||
expr 0.2.0 + 1 > build-id
|
||||
|
||||
.PHONY: identifier-cache
|
||||
identifier-cache:
|
||||
@@ -1130,6 +1167,7 @@ jsc-copy-headers:
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/CommonSlowPaths.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/CommonSlowPaths.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/DirectArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/DirectArguments.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/GenericArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/GenericArguments.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/SamplingProfiler.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/SamplingProfiler.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/ScopedArguments.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/ScopedArguments.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSLexicalEnvironment.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/jit/JITDisassembler.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JITDisassembler.h
|
||||
@@ -1282,8 +1320,13 @@ clean: clean-bindings
|
||||
(cd $(BUN_DEPS_DIR)/picohttp && make clean) || echo "";
|
||||
(cd $(BUN_DEPS_DIR)/zlib && make clean) || echo "";
|
||||
|
||||
release-bindings: $(OBJ_DIR) $(OBJ_FILES) $(WEBCORE_OBJ_FILES) $(SQLITE_OBJ_FILES) $(BUILTINS_OBJ_FILES)
|
||||
bindings: $(DEBUG_OBJ_DIR) $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES)
|
||||
.PHONY: release-bindings
|
||||
release-bindings: $(OBJ_DIR) $(OBJ_FILES) $(WEBCORE_OBJ_FILES) $(SQLITE_OBJ_FILES) $(NODE_OS_OBJ_FILES) $(BUILTINS_OBJ_FILES) $(IO_FILES) $(MODULES_OBJ_FILES)
|
||||
|
||||
# Do not add $(DEBUG_DIR) to this list
|
||||
# It will break caching, causing you to have to wait for every .cpp file to rebuild.
|
||||
.PHONY: bindings
|
||||
bindings: $(DEBUG_OBJ_DIR) $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_NODE_OS_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES) $(DEBUG_IO_FILES) $(DEBUG_MODULES_OBJ_FILES)
|
||||
|
||||
.PHONY: jsc-bindings-mac
|
||||
jsc-bindings-mac: bindings
|
||||
@@ -1444,6 +1487,16 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: src/bun.js/modules/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) $(UWS_INCLUDE) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/webcore/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
@@ -1464,6 +1517,26 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/sqlite/%.cpp
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: src/io/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/node_os/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: src/bun.js/builtins/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
@@ -1498,6 +1571,17 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/webcore/%.cpp
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
$(DEBUG_OBJ_DIR)/%.o: src/io/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
|
||||
# $(DEBUG_OBJ_DIR) is not included here because it breaks
|
||||
# detecting if a file needs to be rebuilt
|
||||
$(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/sqlite/%.cpp
|
||||
@@ -1510,6 +1594,18 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/sqlite/%.cpp
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
# $(DEBUG_OBJ_DIR) is not included here because it breaks
|
||||
# detecting if a file needs to be rebuilt
|
||||
$(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/node_os/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
# $(DEBUG_OBJ_DIR) is not included here because it breaks
|
||||
# detecting if a file needs to be rebuilt
|
||||
$(DEBUG_OBJ_DIR)/%.o: src/bun.js/builtins/%.cpp
|
||||
@@ -1522,6 +1618,16 @@ $(DEBUG_OBJ_DIR)/%.o: src/bun.js/builtins/%.cpp
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
$(DEBUG_OBJ_DIR)/%.o: src/bun.js/modules/%.cpp
|
||||
$(CXX) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM_FOR_DEBUG) \
|
||||
-g3 -c -o $@ $<
|
||||
|
||||
sizegen:
|
||||
mkdir -p $(BUN_TMP_DIR)
|
||||
$(CXX) src/bun.js/headergen/sizegen.cpp -Wl,-dead_strip -Wl,-dead_strip_dylibs -fuse-ld=lld -o $(BUN_TMP_DIR)/sizegen $(CLANG_FLAGS) -O1
|
||||
|
||||
849
README.md
849
README.md
@@ -38,6 +38,24 @@ docker run --rm --init --ulimit memlock=-1:-1 jarredsumner/bun:edge
|
||||
|
||||
If using Linux, kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1.
|
||||
|
||||
## Upgrade
|
||||
|
||||
To upgrade to the latest version of Bun, run:
|
||||
|
||||
```sh
|
||||
bun upgrade
|
||||
```
|
||||
|
||||
Bun automatically releases a canary build on every commit to `main`. To upgrade to the latest canary build, run:
|
||||
|
||||
```sh
|
||||
bun upgrade --canary
|
||||
```
|
||||
|
||||
[View canary build](https://github.com/oven-sh/bun/releases/tag/canary)
|
||||
|
||||
<sup>Canary builds are released without automated tests</sup>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
@@ -109,8 +127,11 @@ If using Linux, kernel version 5.6 or higher is strongly recommended, but the mi
|
||||
- [`bun completions`](#bun-completions)
|
||||
- [`Bun.serve` - fast HTTP server](#bunserve---fast-http-server)
|
||||
- [Usage](#usage-1)
|
||||
- [HTTPS](#https-with-bunserve)
|
||||
- [WebSockets](#websockets-with-bunserve)
|
||||
- [Error handling](#error-handling)
|
||||
- [`Bun.write` – optimizing I/O](#bunwrite--optimizing-io)
|
||||
- [`Bun.spawn` - spawn processes](#bunspawn)
|
||||
- [bun:sqlite (SQLite3 module)](#bunsqlite-sqlite3-module)
|
||||
- [bun:sqlite Benchmark](#bunsqlite-benchmark)
|
||||
- [Getting started with bun:sqlite](#getting-started-with-bunsqlite)
|
||||
@@ -535,7 +556,6 @@ You can see [Bun's Roadmap](https://github.com/oven-sh/bun/issues/159), but here
|
||||
| ------------------------------------------------------------------------------------- | -------------- |
|
||||
| Web Streams with Fetch API | bun.js |
|
||||
| Web Streams with HTMLRewriter | bun.js |
|
||||
| WebSocket Server | bun.js |
|
||||
| Package hoisting that matches npm behavior | bun install |
|
||||
| Source Maps (unbundled is supported) | JS Bundler |
|
||||
| Source Maps | CSS |
|
||||
@@ -544,7 +564,6 @@ You can see [Bun's Roadmap](https://github.com/oven-sh/bun/issues/159), but here
|
||||
| CSS Parser (it only bundles) | CSS |
|
||||
| Tree-shaking | JavaScript |
|
||||
| Tree-shaking | CSS |
|
||||
| [`extends`](https://www.typescriptlang.org/tsconfig#extends) in tsconfig.json | TS Transpiler |
|
||||
| [TypeScript Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html) | TS Transpiler |
|
||||
| `@jsxPragma` comments | JS Transpiler |
|
||||
| Sharing `.bun` files | bun |
|
||||
@@ -647,7 +666,7 @@ editor = "code"
|
||||
|
||||
TODO: list each property name
|
||||
|
||||
### Loaders
|
||||
## Loaders
|
||||
|
||||
A loader determines how to map imports & file extensions to transforms and output.
|
||||
|
||||
@@ -678,7 +697,7 @@ bun --loader=.js:js
|
||||
|
||||
This will disable JSX transforms for `.js` files.
|
||||
|
||||
### CSS in JS
|
||||
#### CSS in JS (bun dev only)
|
||||
|
||||
When importing CSS in JavaScript-like loaders, CSS is treated special.
|
||||
|
||||
@@ -1310,6 +1329,106 @@ bun run relay-compiler --schema foo.graphql
|
||||
|
||||
`bun run` supports lifecycle hooks like `post${task}` and `pre{task}`. If they exist, they will run, matching the behavior of npm clients. If the `pre${task}` fails, the next task will not be run. There is currently no flag to skip these lifecycle tasks if they exist, if you want that file an issue.
|
||||
|
||||
### `bun --hot`
|
||||
|
||||
`bun --hot` enables hot reloading of code in Bun's JavaScript runtime. This is a very experimental feature available in Bun v0.2.0.
|
||||
|
||||
Unlike file watchers like `nodemon`, `bun --hot` can keep stateful objects like the HTTP server running.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th width="800" align="center">
|
||||
Bun v0.2.0
|
||||
</th>
|
||||
<th width="800" align="center">
|
||||
Nodemon
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||

|
||||
|
||||
To use it with Bun's HTTP server (automatic):
|
||||
|
||||
`server.ts`:
|
||||
|
||||
```ts
|
||||
// The global object is preserved across code reloads
|
||||
// You can use it to store state, for now until Bun implements import.meta.hot.
|
||||
const reloadCount = globalThis.reloadCount || 0;
|
||||
globalThis.reloadCount = reloadCount + 1;
|
||||
|
||||
export default {
|
||||
fetch(req: Request) {
|
||||
return new Response(`Code reloaded ${reloadCount} times`, {
|
||||
headers: { "content-type": "text/plain" },
|
||||
});
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Then, run:
|
||||
|
||||
```bash
|
||||
bun --hot server.ts
|
||||
```
|
||||
|
||||
You can also use `bun run`:
|
||||
|
||||
```bash
|
||||
bun run --hot server.ts
|
||||
```
|
||||
|
||||
To use it manually:
|
||||
|
||||
```ts
|
||||
// The global object is preserved across code reloads
|
||||
// You can use it to store state, for now until Bun implements import.meta.hot.
|
||||
const reloadCount = globalThis.reloadCount || 0;
|
||||
globalThis.reloadCount = reloadCount + 1;
|
||||
|
||||
const reloadServer = (globalThis.reloadServer ||= (() => {
|
||||
let server;
|
||||
return (handler) => {
|
||||
if (server) {
|
||||
// call `server.reload` to reload the server
|
||||
server.reload(handler);
|
||||
} else {
|
||||
server = Bun.serve(handler);
|
||||
}
|
||||
return server;
|
||||
};
|
||||
})());
|
||||
|
||||
const handler = {
|
||||
fetch(req: Request) {
|
||||
return new Response(`Code reloaded ${reloadCount} times`, {
|
||||
headers: { "content-type": "text/plain" },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
reloadServer(handler);
|
||||
```
|
||||
|
||||
In a future version of Bun, support for Vite's `import.meta.hot` is planned to enable better lifecycle management for hot reloading and to align with the ecosystem.
|
||||
|
||||
#### How `bun --hot` works
|
||||
|
||||
`bun --hot` monitors imported files for changes and reloads them. It does not monitor files that are not imported and it does not monitor `node_modules`.
|
||||
|
||||
On reload, it resets the internal `require` cache and ES module registry (`Loader.registry`).
|
||||
|
||||
Then:
|
||||
|
||||
- It runs the garbage collector synchronously (to minimize memory leaks, at the cost of runtime performance)
|
||||
- Bun re-transpiles all of your code from scratch (including sourcemaps)
|
||||
- JavaScriptCore (the engine) re-evaluates the code.
|
||||
|
||||
Traditional file watchers restart the entire process which means that HTTP servers and other stateful objects are lost. `bun --hot` does not restart the process, so it preserves _some_ state across reloads to be less intrusive.
|
||||
|
||||
This implementation isn't particularly optimized. It re-transpiles files that haven't changed. It makes no attempt at incremental compilation. It's a starting point.
|
||||
|
||||
### `bun create`
|
||||
|
||||
`bun create` is a fast way to create a new project from a template.
|
||||
@@ -1336,7 +1455,7 @@ Create from a GitHub repo:
|
||||
bun create ahfarmer/calculator ./app
|
||||
```
|
||||
|
||||
To see a list of examples, run:
|
||||
To see a list of templates, run:
|
||||
|
||||
```bash
|
||||
bun create
|
||||
@@ -1358,7 +1477,7 @@ Note: you don’t need `bun create` to use bun. You don’t need any configurati
|
||||
|
||||
If you have your own boilerplate you prefer using, copy it into `$HOME/.bun-create/my-boilerplate-name`.
|
||||
|
||||
Before checking bun’s examples folder, `bun create` checks for a local folder matching the input in:
|
||||
Before checking bun’s templates on npmjs, `bun create` checks for a local folder matching the input in:
|
||||
|
||||
- `$BUN_CREATE_DIR/`
|
||||
- `$HOME/.bun-create/`
|
||||
@@ -1408,7 +1527,7 @@ By default, `bun create` will cancel if there are existing files it would overwr
|
||||
|
||||
#### Publishing a new template
|
||||
|
||||
Clone this repository and a new folder in `examples/` with your new template. The `package.json` must have a `name` that starts with `@bun-examples/`. Do not worry about publishing it, that will happen automatically after the PR is merged.
|
||||
Clone [https://github.com/bun-community/create-templates/](https://github.com/bun-community/create-templates/) and create a new folder in root directory with your new template. The `package.json` must have a `name` that starts with `@bun-examples/`. Do not worry about publishing it, that will happen automatically after the PR is merged.
|
||||
|
||||
Make sure to include a `.gitignore` that includes `node_modules` so that `node_modules` aren’t checked in to git when people download the template.
|
||||
|
||||
@@ -1426,10 +1545,11 @@ Warning: **This will always delete everything in destination-dir**.
|
||||
|
||||
The `bun-create` section of `package.json` is automatically removed from the `package.json` on disk. This lets you add create-only steps without waiting for an extra package to install.
|
||||
|
||||
There are currently two options:
|
||||
There are currently three options:
|
||||
|
||||
- `postinstall`
|
||||
- `preinstall`
|
||||
- `start` (customize the displayed start command)
|
||||
|
||||
They can be an array of strings or one string. An array of steps will be executed in order.
|
||||
|
||||
@@ -1452,7 +1572,8 @@ Here is an example:
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"bun-create": {
|
||||
"postinstall": ["bun bun --use next"]
|
||||
"postinstall": ["bun bun --use next"],
|
||||
"start": "bun run echo 'Hello world!'"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1680,6 +1801,174 @@ This command installs completions for `zsh` and/or `fish`. It runs automatically
|
||||
|
||||
If you want to copy the completions manually, run `bun completions > path-to-file`. If you know the completions directory to install them to, run `bun completions /path/to/directory`.
|
||||
|
||||
## Loader API
|
||||
|
||||
Bun v0.1.11 introduces custom loaders.
|
||||
|
||||
- import and require `.svelte`, `.vue`, `.yaml`, `.scss`, `.less` and other file extensions that Bun doesn't implement a builtin loader for
|
||||
- Dynamically generate ESM & CJS modules
|
||||
|
||||
**YAML loader via `js-yaml`**
|
||||
|
||||
This is an `"object"` loader. `object` loaders let you return a JS object that Bun converts to an ESM & CJS module.
|
||||
|
||||
Plugin implementation (`my-yaml-plugin.js`)
|
||||
|
||||
```js
|
||||
import { plugin } from "bun";
|
||||
|
||||
plugin({
|
||||
name: "YAML",
|
||||
|
||||
setup(builder) {
|
||||
const { load } = require("js-yaml");
|
||||
const { readFileSync } = require("fs");
|
||||
// Run this function on any import that ends with .yaml or .yml
|
||||
builder.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
|
||||
// Read the YAML file from disk
|
||||
const text = readFileSync(args.path, "utf8");
|
||||
|
||||
// parse the YAML file with js-yaml
|
||||
const exports = load(text);
|
||||
|
||||
return {
|
||||
// Copy the keys and values from the parsed YAML file into the ESM module namespace object
|
||||
exports,
|
||||
|
||||
// we're returning an object
|
||||
loader: "object",
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Plugin usage:
|
||||
|
||||
```js
|
||||
import "./my-yaml-plugin.js";
|
||||
import { hello } from "./myfile.yaml";
|
||||
|
||||
console.log(hello); // "world"
|
||||
```
|
||||
|
||||
**Svelte loader using `svelte/compiler`**
|
||||
|
||||
This is a `"js"` loader, which lets you return a JS string or `ArrayBufferView` that Bun converts to an ESM & CJS module.
|
||||
|
||||
Plugin implementation (`myplugin.js`)
|
||||
|
||||
```js
|
||||
import { plugin } from "bun";
|
||||
|
||||
await plugin({
|
||||
name: "svelte loader",
|
||||
async setup(builder) {
|
||||
const { compile } = await import("svelte/compiler");
|
||||
const { readFileSync } = await import("fs");
|
||||
|
||||
// Register a loader for .svelte files
|
||||
builder.onLoad({ filter: /\.svelte$/ }, ({ path }) => ({
|
||||
// Run the Svelte compiler on the import path
|
||||
contents: compile(readFileSync(path, "utf8"), {
|
||||
filename: path,
|
||||
generate: "ssr",
|
||||
}).js.code,
|
||||
|
||||
// Set the loader to "js"
|
||||
// This runs it through Bun's transpiler
|
||||
loader: "js",
|
||||
}));
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Note: in a production implementation, you'd want to cache the compiled output and include additional error handling.
|
||||
|
||||
Plugin usage:
|
||||
|
||||
```js
|
||||
import "./myplugin.js";
|
||||
import MySvelteComponent from "./component.svelte";
|
||||
|
||||
console.log(mySvelteComponent.render());
|
||||
```
|
||||
|
||||
### Loader API Reference
|
||||
|
||||
Bun's loader API interface is loosely based on [esbuild](https://esbuild.github.io/plugins). Some esbuild plugins "just work" in Bun.
|
||||
|
||||
MDX:
|
||||
|
||||
```jsx
|
||||
import { plugin } from "bun";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
// it's the esbuild plugin, but it works using Bun's transpiler.
|
||||
import mdx from "@mdx-js/esbuild";
|
||||
|
||||
plugin(mdx());
|
||||
|
||||
import Foo from "./bar.mdx";
|
||||
console.log(renderToStaticMarkup(<Foo />));
|
||||
```
|
||||
|
||||
At the core of the loader API are `filter` and `namespace`. `filter` is a RegExp matched against import paths. `namespace` is a prefix inserted into the import path (unlike esbuild, Bun inserts the prefix into transpiled output). For example, if you have a loader with a `filter` of `\.yaml$` and a `namespace` of `yaml:`, then the import path `./myfile.yaml` will be transformed to `yaml:./myfile.yaml`.
|
||||
|
||||
**`plugin` function**
|
||||
|
||||
At the top-level, a `plugin` function exported from `"bun"` expects a `"name"` string and a `"setup"` function that takes a `builder` object.
|
||||
|
||||
For plugins to automatically activate, the `plugin` function must be from an import statement like this:
|
||||
|
||||
```js
|
||||
import { plugin } from "bun";
|
||||
|
||||
// This automatically activates on import
|
||||
plugin({
|
||||
name: "my plugin",
|
||||
setup(builder) {},
|
||||
});
|
||||
|
||||
/* Bun.plugin() does not automatically activate. */
|
||||
```
|
||||
|
||||
Inside the `setup` function, you can:
|
||||
|
||||
- register loaders using `builder.onLoad()`
|
||||
- register resolvers using `builder.onResolve()`
|
||||
|
||||
Internally, Bun's transpiler automatically turns `plugin()` calls into separate files (at most 1 per file). This lets loaders activate before the rest of your application runs with zero configuration.
|
||||
|
||||
#### `builder.onLoad({ filter, namespace?: "optional-namespace" }, callback)`
|
||||
|
||||
`builder.onLoad()` registers a loader for a matching `filter` RegExp and `namespace` string.
|
||||
|
||||
The `callback` function is called with an `args` object that contains the following properties:
|
||||
|
||||
- `path`: the path of the file being loaded
|
||||
|
||||
For now, that's the only property. More will likely be added in the future.
|
||||
|
||||
**Loader types**
|
||||
|
||||
There are different types of loaders:
|
||||
|
||||
- `"js"`, `"jsx"`, `"ts"`, `"tsx"`: these loaders run the source text through Bun's transpiler
|
||||
- `"json"`, `"toml"`: these loaders run the source text through Bun's built-in parsers
|
||||
- `"object"`: this loader inserts a new ECMAScript Module into the ECMAScript Module registry by copying all the keys and values from the `"exports"` object into the [Module Namespace Object](https://tc39.es/ecma262/#module-namespace-exotic-object)
|
||||
|
||||
The `callback` function expects a return value that contains `contents` and `loader` properties,
|
||||
unless the loader is `"object"`.
|
||||
|
||||
`"contents"` is the source code. It can be a string or an `ArrayBufferView`.
|
||||
|
||||
`"loader"` is the loader type. It can be `"js"`, `"jsx"`, `"ts"`, `"tsx"`, `"json"`, `"toml"`, or `"object"`.
|
||||
|
||||
If `"loader"` is `"object"`, the `callback` function expects a `"exports"` object instead of `"contents"`. The keys and values will be copied onto the ESM module namespace object.
|
||||
|
||||
`"object"` loaders are useful when the return value is parsed into an object, like when parsing YAML, JSON, or other data formats. Most loader APIs force you to stringify values and parse again. This loader lets you skip that step, which improves performance and is a little easier sometimes.
|
||||
|
||||
## `Bun.serve` - fast HTTP server
|
||||
|
||||
For a hello world HTTP server that writes "bun!", `Bun.serve` serves about 2.5x more requests per second than node.js on Linux:
|
||||
@@ -1785,7 +2074,468 @@ const server = Bun.serve({
|
||||
server.stop();
|
||||
```
|
||||
|
||||
The interface for `Bun.serve` is based on what [Cloudflare Workers](https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/#module-workers-in-the-dashboard) does.
|
||||
### HTTPS with Bun.serve()
|
||||
|
||||
`Bun.serve()` has builtin support for TLS (HTTPS). Pass `keyFile` and `certFile` option to enable HTTPS.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
},
|
||||
/**
|
||||
* File path to a TLS key
|
||||
*
|
||||
* To enable TLS, this option is required.
|
||||
*/
|
||||
keyFile: "./key.pem",
|
||||
/**
|
||||
* File path to a TLS certificate
|
||||
*
|
||||
* To enable TLS, this option is required.
|
||||
*/
|
||||
certFile: "./cert.pem",
|
||||
|
||||
/**
|
||||
* Optional SSL options
|
||||
*/
|
||||
// passphrase?: string;
|
||||
// caFile?: string;
|
||||
// dhParamsFile?: string;
|
||||
// lowMemoryMode?: boolean;
|
||||
});
|
||||
```
|
||||
|
||||
### WebSockets with Bun.serve()
|
||||
|
||||
`Bun.serve()` has builtin support for server-side websockets (as of Bun v0.2.1).
|
||||
|
||||
Features:
|
||||
|
||||
- Compression (pass `perMessageDeflate: true`)
|
||||
- HTTPS
|
||||
- Pubsub / broadcast support with MQTT-like topics
|
||||
|
||||
It's also fast. For [a chatroom](./bench/websocket-server/) on Linux x64:
|
||||
|
||||
| Messages sent per second | Runtime |
|
||||
| ------------------------ | ------------------------------ |
|
||||
| ~700,000 | (`Bun.serve`) Bun v0.2.1 (x64) |
|
||||
| ~100,000 | (`ws`) Node v18.10.0 (x64) |
|
||||
|
||||
Here is an example that echoes back any message it receives:
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
websocket: {
|
||||
message(ws, message) {
|
||||
ws.send(message);
|
||||
},
|
||||
},
|
||||
|
||||
fetch(req, server) {
|
||||
// Upgrade to a ServerWebSocket if we can
|
||||
// This automatically checks for the `Sec-WebSocket-Key` header
|
||||
// meaning you don't have to check headers, you can just call `upgrade()`
|
||||
if (server.upgrade(req))
|
||||
// When upgrading, we return undefined since we don't want to send a Response
|
||||
return;
|
||||
|
||||
return new Response("Regular HTTP response");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Here is a more complete example:
|
||||
|
||||
```ts
|
||||
type User = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
Bun.serve<User>({
|
||||
fetch(req, server) {
|
||||
if (req.url === "/chat") {
|
||||
if (
|
||||
server.upgrade(req, {
|
||||
// This User object becomes ws.data
|
||||
data: {
|
||||
name: new URL(req.url).searchParams.get("name") || "Friend",
|
||||
},
|
||||
// Pass along some headers to the client
|
||||
headers: {
|
||||
"Set-Cookie": "name=" + new URL(req.url).searchParams.get("name"),
|
||||
},
|
||||
})
|
||||
)
|
||||
return;
|
||||
}
|
||||
|
||||
return new Response("Expected a websocket connection", { status: 400 });
|
||||
},
|
||||
|
||||
websocket: {
|
||||
open(ws) {
|
||||
console.log("WebSocket opened");
|
||||
|
||||
// subscribe to "the-group-chat" topic
|
||||
ws.subscribe("the-group-chat");
|
||||
},
|
||||
|
||||
message(ws, message) {
|
||||
// In a group chat, we want to broadcast to everyone
|
||||
// so we use publish()
|
||||
ws.publish("the-group-chat", `${ws.data.name}: ${message}`);
|
||||
|
||||
},
|
||||
|
||||
close(ws, code, reason) {
|
||||
ws.publish("the-group-chat", `${ws.data.name} left the chat`);
|
||||
},
|
||||
|
||||
drain(ws) {
|
||||
console.log("Please send me data. I am ready to receive it.");
|
||||
},
|
||||
|
||||
// enable compression
|
||||
perMessageDeflate: true,
|
||||
/*
|
||||
* perMessageDeflate: {
|
||||
**
|
||||
* Enable compression on the {@link ServerWebSocket}
|
||||
*
|
||||
* @default false
|
||||
*
|
||||
* `true` is equivalent to `"shared"
|
||||
compress?: WebSocketCompressor | false | true;
|
||||
**
|
||||
* Configure decompression
|
||||
*
|
||||
* @default false
|
||||
*
|
||||
* `true` is equivalent to `"shared"
|
||||
decompress?: WebSocketCompressor | false | true;
|
||||
*/
|
||||
|
||||
/**
|
||||
* The maximum size of a message
|
||||
*/
|
||||
// maxPayloadLength?: number;
|
||||
/**
|
||||
* After a connection has not received a message for this many seconds, it will be closed.
|
||||
* @default 120 (2 minutes)
|
||||
*/
|
||||
// idleTimeout?: number;
|
||||
/**
|
||||
* The maximum number of bytes that can be buffered for a single connection.
|
||||
* @default 16MB
|
||||
*/
|
||||
// backpressureLimit?: number;
|
||||
/**
|
||||
* Close the connection if the backpressure limit is reached.
|
||||
* @default false
|
||||
*/
|
||||
// closeOnBackpressureLimit?: boolean;
|
||||
|
||||
// this makes it so ws.data shows up as a Request object
|
||||
},
|
||||
// TLS is also supported with WebSockets
|
||||
/**
|
||||
* File path to a TLS key
|
||||
*
|
||||
* To enable TLS, this option is required.
|
||||
*/
|
||||
// keyFile: "./key.pem",
|
||||
/**
|
||||
* File path to a TLS certificate
|
||||
*
|
||||
* To enable TLS, this option is required.
|
||||
*/
|
||||
// certFile: "./cert.pem",
|
||||
});
|
||||
```
|
||||
|
||||
#### ServerWebSocket vs WebSocket
|
||||
|
||||
For server websocket connections, Bun exposes a `ServerWebSocket` class which is similar to the web-standard `WebSocket` class used for websocket client connections, but with a few differences:
|
||||
|
||||
##### Headers
|
||||
|
||||
`ServerWebSocket` supports passing headers. This is useful for setting cookies or other headers that you want to send to the client before the connection is upgraded.
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
fetch(req, server) {
|
||||
if (
|
||||
server.upgrade(req, { headers: { "Set-Cookie": "name=HiThereMyNameIs" } })
|
||||
)
|
||||
return;
|
||||
},
|
||||
websocket: {
|
||||
message(ws, message) {
|
||||
ws.send(message);
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The web-standard `WebSocket` API does not let you specify headers.
|
||||
|
||||
##### Publish/subscribe
|
||||
|
||||
`ServerWebSocket` has `publish()`, `subscribe()`, and `unsubscribe` methods which let you broadcast the same message to all clients connected to a topic in one line of code.
|
||||
|
||||
```ts
|
||||
ws.publish("stock-prices/GOOG", `${price}`);
|
||||
```
|
||||
|
||||
##### Backpressure
|
||||
|
||||
`ServerWebSocket.send` returns a number that indicates:
|
||||
|
||||
- `0` if the message was dropped due to a connection issue
|
||||
- `-1` if the message was enqueued but there is backpressure
|
||||
- any other number indicates the number of bytes sent
|
||||
|
||||
This lets you have **better control over backpressure in your server**.
|
||||
|
||||
You can also enable/disable compression per message with the `compress` option:
|
||||
|
||||
```ts
|
||||
// this will compress
|
||||
ws.send("Hello".repeat(1000), true);
|
||||
```
|
||||
|
||||
`WebSocket.send` returns `undefined` and does not indicate backpressure, which can cause issues if you are sending a lot of data.
|
||||
|
||||
`ServerWebSocket` also supports a `drain` callback that runs when the connection is ready to receive more data.
|
||||
|
||||
##### Callbacks are per server instead of per socket
|
||||
|
||||
`ServerWebSocket` expects you to pass a `WebSocketHandler` object to the `Bun.serve()` method which has methods for `open`, `message`, `close`, `drain`, and `error`. This is different than the client-side `WebSocket` class which extends `EventTarget` (onmessage, onopen, onclose),
|
||||
|
||||
Clients tend to not have many socket connections open so an event-based API makes sense.
|
||||
|
||||
But servers tend to have **many** socket connections open, which means:
|
||||
|
||||
- Time spent adding/removing event listeners for each connection adds up
|
||||
- Extra memory spent on storing references to callbacks function for each connection
|
||||
- Usually, people create new functions for each connection, which also means more memory
|
||||
|
||||
So, instead of using an event-based API, `ServerWebSocket` expects you to pass a single object with methods for each event in `Bun.serve()` and it is reused for each connection.
|
||||
|
||||
This leads to less memory usage and less time spent adding/removing event listeners.
|
||||
|
||||
---
|
||||
|
||||
The interface for `Bun.serve` is loosely based on what [Cloudflare Workers](https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/#module-workers-in-the-dashboard) does.
|
||||
|
||||
The HTTP server and server-side websockets are based on [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
||||
|
||||
## `Bun.spawn` – spawn a process
|
||||
|
||||
`Bun.spawn` lets you quickly spawn a process. Available as of Bun v0.2.0.
|
||||
|
||||
```ts
|
||||
import { spawn } from "bun";
|
||||
|
||||
const { stdout } = spawn(["esbuild"], {
|
||||
stdin: await fetch(
|
||||
"https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js"
|
||||
),
|
||||
});
|
||||
|
||||
const text = await new Response(stdout).text();
|
||||
console.log(text); // "const input = "hello world".repeat(400); ..."
|
||||
```
|
||||
|
||||
Bun.spawn spawns processes 60% faster than Node.js' `child_process`.
|
||||
|
||||
```zig
|
||||
❯ bun spawn.mjs
|
||||
cpu: Apple M1 Max
|
||||
runtime: bun 0.2.0 (arm64-darwin)
|
||||
|
||||
benchmark time (avg) (min … max) p75 p99 p995
|
||||
--------------------------------------------------------- -----------------------------
|
||||
spawnSync echo hi 888.14 µs/iter (821.83 µs … 1.2 ms) 905.92 µs 1 ms 1.03 ms
|
||||
|
||||
❯ node spawn.node.mjs
|
||||
cpu: Apple M1 Max
|
||||
runtime: node v18.9.1 (arm64-darwin)
|
||||
|
||||
benchmark time (avg) (min … max) p75 p99 p995
|
||||
--------------------------------------------------------- -----------------------------
|
||||
spawnSync echo hi 1.47 ms/iter (1.14 ms … 2.64 ms) 1.57 ms 2.37 ms 2.52 ms
|
||||
```
|
||||
|
||||
Synchronous example:
|
||||
|
||||
```ts
|
||||
import { spawnSync } from "bun";
|
||||
|
||||
const { stdout } = spawnSync(["echo", "hi"]);
|
||||
|
||||
// When using spawnSync, stdout is a Buffer
|
||||
// this lets you read from it synchronously
|
||||
const text = stdout.toString();
|
||||
|
||||
console.log(text); // "hi\n"
|
||||
```
|
||||
|
||||
You can pass an object as the second argument to customize the process:
|
||||
|
||||
```ts
|
||||
import { spawn } from "bun";
|
||||
|
||||
const { stdout } = spawn(["printenv", "FOO"], {
|
||||
cwd: "/tmp",
|
||||
|
||||
env: {
|
||||
...process.env,
|
||||
FOO: "bar",
|
||||
},
|
||||
|
||||
// Disable stdin
|
||||
stdin: null,
|
||||
|
||||
// Allow us to read from stdout
|
||||
stdout: "pipe",
|
||||
|
||||
// Point stderr to write to "/tmp/stderr.log"
|
||||
stderr: Bun.file("/tmp/stderr.log"),
|
||||
});
|
||||
|
||||
const text = await new Response(stdout).text();
|
||||
console.log(text); // "bar\n"
|
||||
```
|
||||
|
||||
You can also pass a `Bun.file` for `stdin`:
|
||||
|
||||
```ts
|
||||
import { spawn, file, write } from "bun";
|
||||
|
||||
await write("/tmp/foo.txt", "hi");
|
||||
const { stdout } = spawn(["cat"], {
|
||||
// Set /tmp/foo.txt as stdin
|
||||
stdin: file("/tmp/foo.txt"),
|
||||
});
|
||||
|
||||
const text = await new Response(stdout).text();
|
||||
console.log(text); // "hi\n"
|
||||
```
|
||||
|
||||
`stdin` also accepts a TypedArray:
|
||||
|
||||
```ts
|
||||
import { spawn } from "bun";
|
||||
|
||||
const { stdout } = spawn(["cat"], {
|
||||
stdin: new TextEncoder().encode("hi"),
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const text = await new Response(stdout).text();
|
||||
console.log(text); // "hi\n"
|
||||
```
|
||||
|
||||
`Bun.spawn` also supports incrementally writing to stdin:
|
||||
|
||||
> :warning: **This API is a little buggy right now**
|
||||
|
||||
```ts
|
||||
import { spawn } from "bun";
|
||||
|
||||
const { stdin, stdout } = spawn(["cat"], {
|
||||
stdin: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
// You can pass it strings or TypedArrays
|
||||
// Write "hi" to stdin
|
||||
stdin.write("hi");
|
||||
|
||||
// By default, stdin is buffered so you need to call flush() to send it
|
||||
stdin.flush(true);
|
||||
|
||||
// When you're done, call end()
|
||||
stdin.end();
|
||||
|
||||
const text = await new Response(stdout).text();
|
||||
console.log(text); // "hi\n"
|
||||
```
|
||||
|
||||
Under the hood, `Bun.spawn` and `Bun.spawnSync` use [`posix_spawn(3)`](https://man7.org/linux/man-pages/man3/posix_spawn.3.html).
|
||||
|
||||
**stdin**
|
||||
|
||||
`stdin` can be one of:
|
||||
|
||||
- `Bun.file()`
|
||||
- `null` (no stdin)
|
||||
- `ArrayBufferView`
|
||||
- `Response`, `Request` with a buffered body or from `fetch()`. `ReadableStream` is not supported yet (TODO)
|
||||
- `number` (file descriptor)
|
||||
- `"pipe"` (default), which returns a `FileSink` for fast incremental writing
|
||||
- `"inherit"` which will inherit the parent's stdin
|
||||
|
||||
**stdout** and **stderr**
|
||||
|
||||
`stdout` and `stderr` can be one of:
|
||||
|
||||
- `Bun.file()`
|
||||
- `null` (disable)
|
||||
- `number` (file descriptor)
|
||||
- `"pipe"` (default for `stdout`), returns a `ReadableStream`
|
||||
- `"inherit"` (default for `stderr`) which will inherit the parent's stdout/stderr
|
||||
|
||||
**When to use `Bun.spawn` vs `Bun.spawnSync`**
|
||||
|
||||
There are three main differences between `Bun.spawn` and `Bun.spawnSync`.
|
||||
|
||||
1. `Bun.spawnSync` blocks the event loop until the subprocess exits. For HTTP servers, you probably should avoid using `Bun.spawnSync` but for CLI apps, you probably should use `Bun.spawnSync`.
|
||||
|
||||
2. `spawnSync` returns a different object for `stdout` and `stderr` so you can read the data synchronously.
|
||||
|
||||
| `spawn` | `spawnSync` |
|
||||
| ---------------- | ----------- |
|
||||
| `ReadableStream` | `Buffer` |
|
||||
|
||||
3. `Bun.spawn` supports incrementally writing to `stdin`.
|
||||
|
||||
If you need to read from `stdout` or `stderr` synchronously, you should use `Bun.spawnSync`. Otherwise, `Bun.spawn` is preferred.
|
||||
|
||||
**More details**
|
||||
|
||||
`Bun.spawn` returns a `Subprocess` object.
|
||||
|
||||
More complete types are available in [`bun-types`](https://github.com/oven-sh/bun-types).
|
||||
|
||||
```ts
|
||||
interface Subprocess {
|
||||
readonly pid: number;
|
||||
readonly stdin: FileSink | undefined;
|
||||
readonly stdout: ReadableStream | number | undefined;
|
||||
readonly stderr: ReadableStream | number | undefined;
|
||||
|
||||
readonly exitCode: number | undefined;
|
||||
|
||||
// Wait for the process to exit
|
||||
readonly exited: Promise<number>;
|
||||
|
||||
// Keep Bun's process alive until the subprocess exits
|
||||
ref(): void;
|
||||
|
||||
// Don't keep Bun's process alive until the subprocess exits
|
||||
unref(): void;
|
||||
|
||||
// Kill the process
|
||||
kill(code?: number): void;
|
||||
readonly killed: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## `Bun.write` – optimizing I/O
|
||||
|
||||
@@ -1895,7 +2645,7 @@ db.query("SELECT * FROM foo WHERE greeting = $greeting").get({
|
||||
|
||||
### bun:sqlite Benchmark
|
||||
|
||||
Database: [Northwind Traders](https://github.com/jpwhite3/northwind-SQLite3/blob/master/Northwind_large.sqlite.zip).
|
||||
Database: [Northwind Traders](https://github.com/jpwhite3/northwind-SQLite3/blob/46d5f8a64f396f87cd374d1600dbf521523980e8/Northwind_large.sqlite.zip).
|
||||
|
||||
This benchmark can be run from [./bench/sqlite](./bench/sqlite).
|
||||
|
||||
@@ -2656,11 +3406,13 @@ rustc --crate-type cdylib add.rs
|
||||
| i8 | `int8_t` | `int8_t` |
|
||||
| i16 | `int16_t` | `int16_t` |
|
||||
| i32 | `int32_t` | `int32_t`, `int` |
|
||||
| i64 | `int64_t` | `int32_t` |
|
||||
| i64 | `int64_t` | `int64_t` |
|
||||
| i64_fast | `int64_t` | |
|
||||
| u8 | `uint8_t` | `uint8_t` |
|
||||
| u16 | `uint16_t` | `uint16_t` |
|
||||
| u32 | `uint32_t` | `uint32_t` |
|
||||
| u64 | `uint64_t` | `uint32_t` |
|
||||
| u64 | `uint64_t` | `uint64_t` |
|
||||
| u64_fast | `uint64_t` | |
|
||||
| f32 | `float` | `float` |
|
||||
| f64 | `double` | `double` |
|
||||
| bool | `bool` | |
|
||||
@@ -2831,6 +3583,56 @@ const myPtr = ptr(myTypedArray);
|
||||
myTypedArray = new Uint8Array(toArrayBuffer(myPtr, 0, 32), 0, 32);
|
||||
```
|
||||
|
||||
**To read data from a pointer**
|
||||
|
||||
You have two options.
|
||||
|
||||
For long-lived pointers, a `DataView` is the fastest option:
|
||||
|
||||
```ts
|
||||
import { toArrayBuffer } from "bun:ffi";
|
||||
var myDataView = new DataView(toArrayBuffer(myPtr, 0, 32));
|
||||
|
||||
console.log(
|
||||
myDataView.getUint8(0, true),
|
||||
myDataView.getUint8(1, true),
|
||||
myDataView.getUint8(2, true),
|
||||
myDataView.getUint8(3, true)
|
||||
);
|
||||
```
|
||||
|
||||
For short-lived pointers, `read` is the fastest option:
|
||||
|
||||
_Available in Bun v0.1.12+_
|
||||
|
||||
```ts
|
||||
import { read } from "bun:ffi";
|
||||
|
||||
console.log(
|
||||
// ptr, byteOffset
|
||||
read.u8(myPtr, 0),
|
||||
read.u8(myPtr, 1),
|
||||
read.u8(myPtr, 2),
|
||||
read.u8(myPtr, 3)
|
||||
);
|
||||
```
|
||||
|
||||
`read` behaves similarly to `DataView`, but it can be faster because it doesn't need to create a `DataView` or `ArrayBuffer`.
|
||||
|
||||
| `FFIType` | `read` function |
|
||||
| --------- | --------------- |
|
||||
| ptr | `read.ptr` |
|
||||
| i8 | `read.i8` |
|
||||
| i16 | `read.i16` |
|
||||
| i32 | `read.i32` |
|
||||
| i64 | `read.i64` |
|
||||
| u8 | `read.u8` |
|
||||
| u16 | `read.u16` |
|
||||
| u32 | `read.u32` |
|
||||
| u64 | `read.u64` |
|
||||
| f32 | `read.f32` |
|
||||
| f64 | `read.f64` |
|
||||
|
||||
**Memory management with pointers**:
|
||||
|
||||
`bun:ffi` does not manage memory for you because it doesn't have the information necessary. You must free the memory when you're done with it.
|
||||
@@ -2924,7 +3726,7 @@ const out = encode_png(
|
||||
);
|
||||
```
|
||||
|
||||
The [auto-generated wrapper](https://github.com/oven-sh/bun/blob/c6d732eee2721cd6191672cbe2c57fb17c3fffe4/src/bun.js/ffi.exports.js#L146-L148) converts the pointer to a TypedArray
|
||||
The [auto-generated wrapper](https://github.com/oven-sh/bun/blob/6a65631cbdcae75bfa1e64323a6ad613a922cd1a/src/bun.js/ffi.exports.js#L180-L182) converts the pointer to a TypedArray
|
||||
|
||||
<details>
|
||||
|
||||
@@ -3023,7 +3825,7 @@ require("./my-node-module.node");
|
||||
import.meta.require("./my-node-module.node");
|
||||
```
|
||||
|
||||
Bun doesn't currently support dynamic requires, but `import.meta.require` is an escape hatch for that. It uses a [JavaScriptCore built-in function](https://github.com/oven-sh/bun/blob/aa87d40f4b7fdfb52575f44d151906ddba6a82d0/src/bun.js/bindings/builtins/js/JSZigGlobalObject.js#L26).
|
||||
Bun doesn't currently support dynamic requires, but `import.meta.require` is an escape hatch for that. It uses a [JavaScriptCore built-in function](https://github.com/oven-sh/bun/blob/aa87d40f4b7fdfb52575f44d151906ddba6a82d0/src/javascript/jsc/bindings/builtins/js/JSZigGlobalObject.js#L26).
|
||||
|
||||
### `Bun.Transpiler`
|
||||
|
||||
@@ -3318,7 +4120,12 @@ For compatibility reasons, these NPM packages are embedded into bun’s binary a
|
||||
|
||||
## Developing bun
|
||||
|
||||
Estimated: 30-90 minutes :(
|
||||
Some links you should read about JavaScriptCore, the JavaScript engine Bun uses:
|
||||
|
||||
- https://webkit.org/blog/12967/understanding-gc-in-jsc-from-scratch/
|
||||
- https://webkit.org/blog/7122/introducing-riptide-webkits-retreating-wavefront-concurrent-garbage-collector/
|
||||
|
||||
To get your development environment configured, expect it to take 30-90 minutes :(
|
||||
|
||||
### VSCode Dev Container (Linux)
|
||||
|
||||
@@ -3400,16 +4207,18 @@ To install the zig binary:
|
||||
|
||||
```bash
|
||||
# Custom path for the custom zig install
|
||||
mkdir -p ~/.bun-tools
|
||||
mkdir -p $HOME/.bun-tools
|
||||
|
||||
# Requires jq & grab latest binary
|
||||
curl -o zig.tar.gz -sL https://github.com/oven-sh/zig/releases/download/jul1/zig-macos-$(uname -m).tar.gz
|
||||
|
||||
# This will extract to $HOME/.bun-tools/zig
|
||||
tar -xvf zig.tar.gz -C $HOME/.bun-tools/
|
||||
rm zig.tar.gz
|
||||
|
||||
# Make sure it gets trusted
|
||||
xattr -dr com.apple.quarantine .bun-tools/zig/zig
|
||||
# If you get an error 'No such xattr: com.apple.quarantine', that means it's already trusted and you can continue
|
||||
xattr -d com.apple.quarantine $HOME/.bun-tools/zig/zig
|
||||
```
|
||||
|
||||
Now you'll need to add Zig to your PATH.
|
||||
@@ -3447,8 +4256,8 @@ In `bun`:
|
||||
|
||||
```bash
|
||||
# If you omit --depth=1, `git submodule update` will take 17.5 minutes on 1gbps internet, mostly due to WebKit.
|
||||
git submodule update --init --recursive --progress --depth=1
|
||||
make vendor identifier-cache jsc dev
|
||||
git submodule update --init --recursive --progress --depth=1 --checkout
|
||||
make vendor identifier-cache bindings jsc dev
|
||||
```
|
||||
|
||||
#### Verify it worked (macOS)
|
||||
|
||||
17
bench/fetch/bun.js
Normal file
17
bench/fetch/bun.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const count = 100;
|
||||
|
||||
bench(`fetch(https://example.com) x ${count}`, async () => {
|
||||
const requests = new Array(count);
|
||||
|
||||
for (let i = 0; i < requests.length; i++) {
|
||||
requests[i] = fetch(`https://www.example.com/?cachebust=${i}`).then((r) =>
|
||||
r.text()
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(requests);
|
||||
});
|
||||
|
||||
await run();
|
||||
17
bench/fetch/deno.js
Normal file
17
bench/fetch/deno.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { bench, run } from "https://esm.run/mitata";
|
||||
|
||||
const count = 100;
|
||||
|
||||
bench(`fetch(https://example.com) x ${count}`, async () => {
|
||||
const requests = new Array(count);
|
||||
|
||||
for (let i = 0; i < requests.length; i++) {
|
||||
requests[i] = fetch(`https://www.example.com/?cachebust=${i}`).then((r) =>
|
||||
r.text()
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(requests);
|
||||
});
|
||||
|
||||
await run();
|
||||
17
bench/fetch/node.mjs
Normal file
17
bench/fetch/node.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const count = 100;
|
||||
|
||||
bench(`fetch(https://example.com) x ${count}`, async () => {
|
||||
const requests = new Array(count);
|
||||
|
||||
for (let i = 0; i < requests.length; i++) {
|
||||
requests[i] = fetch(`https://www.example.com/?cachebust=${i}`).then((r) =>
|
||||
r.text()
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(requests);
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ptr, dlopen, CString, toBuffer } from "bun:ffi";
|
||||
import { run, bench, group } from "mitata";
|
||||
import { ptr, dlopen, CString } from "bun:ffi";
|
||||
const { napiNoop, napiHash, napiString } = require("./src/ffi_napi_bench.node");
|
||||
|
||||
const { napiNoop, napiHash, napiString } = require(import.meta.dir +
|
||||
"/src/ffi_napi_bench.node");
|
||||
|
||||
const {
|
||||
symbols: {
|
||||
@@ -8,7 +10,7 @@ const {
|
||||
ffi_hash: { native: ffi_hash },
|
||||
ffi_string: { native: ffi_string },
|
||||
},
|
||||
} = dlopen("./src/ffi_napi_bench.node", {
|
||||
} = dlopen(import.meta.dir + "/src/ffi_napi_bench.node", {
|
||||
ffi_noop: { args: [], returns: "void" },
|
||||
ffi_string: { args: [], returns: "ptr" },
|
||||
ffi_hash: { args: ["ptr", "u32"], returns: "u32" },
|
||||
|
||||
@@ -11,7 +11,7 @@ const {
|
||||
} = Deno.dlopen(path, {
|
||||
ffi_noop: { parameters: [], result: "void" },
|
||||
ffi_string: { parameters: [], result: "pointer" },
|
||||
ffi_hash: { parameters: ["pointer", "u32"], result: "u32" },
|
||||
ffi_hash: { parameters: ["buffer", "u32"], result: "u32" },
|
||||
});
|
||||
|
||||
const bytes = new Uint8Array(64);
|
||||
@@ -19,9 +19,7 @@ const bytes = new Uint8Array(64);
|
||||
group("deno:ffi", () => {
|
||||
bench("noop", () => ffi_noop());
|
||||
bench("hash", () => ffi_hash(bytes, bytes.byteLength));
|
||||
bench("c string", () =>
|
||||
new Deno.UnsafePointerView(ffi_string()).getCString()
|
||||
);
|
||||
bench("c string", () => Deno.UnsafePointerView.getCString(ffi_string()));
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
2
bench/modules/node_os/.env
Normal file
2
bench/modules/node_os/.env
Normal file
@@ -0,0 +1,2 @@
|
||||
BUN=bun
|
||||
NODE=node
|
||||
22
bench/modules/node_os/bun.js
Normal file
22
bench/modules/node_os/bun.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { cpus, endianness, arch, uptime, networkInterfaces, getPriority, totalmem, freemem, homedir, hostname, loadavg, platform, release, setPriority, tmpdir, type, userInfo, version } from "node:os";
|
||||
|
||||
bench("cpus()", () => cpus());
|
||||
bench("networkInterfaces()", () => networkInterfaces());
|
||||
bench("arch()", () => arch());
|
||||
bench("endianness()", () => endianness());
|
||||
bench("freemem()", () => freemem());
|
||||
bench("totalmem()", () => totalmem());
|
||||
bench("getPriority()", () => getPriority());
|
||||
bench("homedir()", () => homedir());
|
||||
bench("hostname()", () => hostname());
|
||||
bench("loadavg()", () => loadavg());
|
||||
bench("platform()", () => platform());
|
||||
bench("release()", () => release());
|
||||
bench("setPriority(2)", () => setPriority(2));
|
||||
bench("tmpdir()", () => tmpdir());
|
||||
bench("type()", () => type());
|
||||
bench("uptime()", () => uptime());
|
||||
bench("userInfo()", () => userInfo());
|
||||
bench("version()", () => version());
|
||||
await run();
|
||||
22
bench/modules/node_os/node.mjs
Normal file
22
bench/modules/node_os/node.mjs
Normal file
@@ -0,0 +1,22 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { cpus, endianness, arch, uptime, networkInterfaces, getPriority, totalmem, freemem, homedir, hostname, loadavg, platform, release, setPriority, tmpdir, type, userInfo, version } from "node:os";
|
||||
|
||||
bench("cpus()", () => cpus());
|
||||
bench("networkInterfaces()", () => networkInterfaces());
|
||||
bench("arch()", () => arch());
|
||||
bench("endianness()", () => endianness());
|
||||
bench("freemem()", () => freemem());
|
||||
bench("totalmem()", () => totalmem());
|
||||
bench("getPriority()", () => getPriority());
|
||||
bench("homedir()", () => homedir());
|
||||
bench("hostname()", () => hostname());
|
||||
bench("loadavg()", () => loadavg());
|
||||
bench("platform()", () => platform());
|
||||
bench("release()", () => release());
|
||||
bench("setPriority(2)", () => setPriority(2));
|
||||
bench("tmpdir()", () => tmpdir());
|
||||
bench("type()", () => type());
|
||||
bench("uptime()", () => uptime());
|
||||
bench("userInfo()", () => userInfo());
|
||||
bench("version()", () => version());
|
||||
await run();
|
||||
10
bench/modules/node_os/package.json
Normal file
10
bench/modules/node_os/package.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "bench",
|
||||
"scripts": {
|
||||
"deps": "exit 0",
|
||||
"build": "exit 0",
|
||||
"bench:bun": "$BUN bun.js",
|
||||
"bench:node": "$NODE node.mjs",
|
||||
"bench": "bun run bench:bun && bun run bench:node"
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
"log": "cd log && bun run deps && bun run build && bun run bench",
|
||||
"gzip": "cd gzip && bun run deps && bun run build && bun run bench",
|
||||
"async": "cd async && bun run deps && bun run build && bun run bench",
|
||||
"sqlite": "cd sqlite && bun run deps && bun run build && bun run bench"
|
||||
"sqlite": "cd sqlite && bun run deps && bun run build && bun run bench",
|
||||
"modules:node_os": "cd modules/node_os && bun run deps &&bun run build && bun run bench"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { renderToReadableStream } from "https://esm.run/react-dom/server";
|
||||
import { serve } from "https://deno.land/std@0.146.0/http/server.ts";
|
||||
import * as React from "https://esm.run/react";
|
||||
|
||||
const App = () => (
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<p>This is an example.</p>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
@@ -17,7 +17,7 @@ const headers = {
|
||||
},
|
||||
};
|
||||
|
||||
await serve(
|
||||
Deno.serve(
|
||||
async (req) => {
|
||||
return new Response(await renderToReadableStream(<App />), headers);
|
||||
},
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { renderToReadableStream } from "../../test/bun.js/reactdom-bun.js";
|
||||
// to run this:
|
||||
// bun --jsx-production react-hello-world.jsx
|
||||
|
||||
// This will become the official react-dom/server.bun build a little later
|
||||
// It will be the default when you import from "react-dom/server"
|
||||
// That will work via the "bun" package.json export condition (which bun already supports)
|
||||
import { renderToReadableStream } from "../../test/bun.js/react-dom-server.bun";
|
||||
const headers = {
|
||||
headers: {
|
||||
"Content-Type": "text/html",
|
||||
"Cache-Control": "no-transform", // set to match the Deno benchmark, which requires this for an apples to apples comparison
|
||||
},
|
||||
};
|
||||
|
||||
@@ -11,12 +15,17 @@ const App = () => (
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<p>This is an example.</p>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
export default {
|
||||
const port = Number(process.env.PORT || 3001);
|
||||
Bun.serve({
|
||||
port,
|
||||
async fetch(req) {
|
||||
return new Response(await renderToReadableStream(<App />), headers);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
console.log(`Server running on\n http://localhost:${port}`);
|
||||
|
||||
56
bench/snippets/array-map.mjs
Normal file
56
bench/snippets/array-map.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
// https://github.com/oven-sh/bun/issues/1096
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const identity = (x) => x;
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
var array = new Array(i);
|
||||
for (let j = 0; j < i; j++) {
|
||||
array[j] = 1;
|
||||
}
|
||||
|
||||
bench("Array.map x " + i, () => array.map(identity));
|
||||
}
|
||||
|
||||
bench("inline Array.map x 0", () => [].map(identity));
|
||||
bench("inline Array.map x 1", () => [1].map(identity));
|
||||
bench("inline Array.map x 2", () => [1, 1].map(identity));
|
||||
bench("inline Array.map x 3", () => [1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 4", () => [1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 5", () => [1, 1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 6", () => [1, 1, 1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 7", () => [1, 1, 1, 1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 8", () => [1, 1, 1, 1, 1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 9", () => [1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity));
|
||||
bench("inline Array.map x 10", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 11", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 12", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 13", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 14", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 15", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 16", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 17", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 18", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
bench("inline Array.map x 19", () =>
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].map(identity)
|
||||
);
|
||||
|
||||
await run();
|
||||
18
bench/snippets/async-overhead.mjs
Normal file
18
bench/snippets/async-overhead.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
bench("noop", function () {});
|
||||
bench("async function(){}", async function () {});
|
||||
bench("await 1", async function () {
|
||||
return await 1;
|
||||
});
|
||||
bench("await new Promise(resolve => resolve())", async function () {
|
||||
await new Promise((resolve) => resolve());
|
||||
});
|
||||
bench(
|
||||
"Promise.all(Array.from({length: 100}, () => new Promise((resolve) => resolve())))",
|
||||
async function () {
|
||||
return Promise.all(Array.from({ length: 100 }, () => Promise.resolve(1)));
|
||||
}
|
||||
);
|
||||
|
||||
await run();
|
||||
30
bench/snippets/blob.mjs
Normal file
30
bench/snippets/blob.mjs
Normal file
@@ -0,0 +1,30 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
bench("new Blob(['hello world'])", function () {
|
||||
return new Blob(["hello world"]);
|
||||
});
|
||||
|
||||
var small = new Blob([JSON.stringify("hello world ")]);
|
||||
bench("blob.text(small string)", function () {
|
||||
return small.text();
|
||||
});
|
||||
|
||||
bench("blob.arrayBuffer(small string)", function () {
|
||||
return small.arrayBuffer();
|
||||
});
|
||||
|
||||
// if (Blob.prototype.json) {
|
||||
// bench("blob.json(small string)", function () {
|
||||
// return small.json();
|
||||
// });
|
||||
// }
|
||||
|
||||
bench("blob.slice()", function () {
|
||||
return small.slice();
|
||||
});
|
||||
|
||||
if ((await small.text()) !== JSON.stringify("hello world ")) {
|
||||
throw new Error("blob.text() failed");
|
||||
}
|
||||
|
||||
await run();
|
||||
25
bench/snippets/crypto.mjs
Normal file
25
bench/snippets/crypto.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
// so it can run in environments without node module resolution
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
var crypto = globalThis.crypto;
|
||||
|
||||
if (!crypto) {
|
||||
crypto = await import("node:crypto");
|
||||
}
|
||||
|
||||
var foo = new Uint8Array(65536);
|
||||
bench("crypto.getRandomValues(65536)", () => {
|
||||
crypto.getRandomValues(foo);
|
||||
});
|
||||
|
||||
var small = new Uint8Array(32);
|
||||
bench("crypto.getRandomValues(32)", () => {
|
||||
crypto.getRandomValues(small);
|
||||
});
|
||||
|
||||
bench("crypto.randomUUID()", () => {
|
||||
// node uses a rope string for each hex byte so any subsequent operation after creating it is slow
|
||||
return crypto.randomUUID()[2];
|
||||
});
|
||||
|
||||
await run();
|
||||
49
bench/snippets/emitter.js
Normal file
49
bench/snippets/emitter.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const EventEmitter = require("events").EventEmitter;
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const emitter = new EventEmitter();
|
||||
const event = new Event("hello");
|
||||
emitter.on("hello", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
var id = 0;
|
||||
bench("EventEmitter.emit", () => {
|
||||
emitter.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
bench("EventEmitter.on x 10_000 (handler)", () => {
|
||||
var cb = () => {
|
||||
event.preventDefault();
|
||||
};
|
||||
emitter.on("hey", cb);
|
||||
for (let i = 0; i < 10_000; i++)
|
||||
emitter.emit("hey", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
emitter.off("hey", cb);
|
||||
});
|
||||
|
||||
var target = new EventTarget();
|
||||
target.addEventListener("hello", (event) => {});
|
||||
bench("EventTarget.dispatch", () => {
|
||||
target.dispatchEvent(event);
|
||||
});
|
||||
|
||||
var hey = new Event("hey");
|
||||
|
||||
bench("EventTarget.on x 10_000 (handler)", () => {
|
||||
var handler = (event) => {};
|
||||
target.addEventListener("hey", handler);
|
||||
|
||||
for (let i = 0; i < 10_000; i++) target.dispatchEvent(hey);
|
||||
target.removeEventListener("hey", handler);
|
||||
});
|
||||
|
||||
await run();
|
||||
12
bench/snippets/index-of.mjs
Normal file
12
bench/snippets/index-of.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const input =
|
||||
"Hello, World! foo bar baz qux quux corge grault garply waldo fred plugh xyzzy thud z a b c d e f g h i j k l m n o p q r s t u v w x y z".split(
|
||||
" "
|
||||
);
|
||||
|
||||
bench(`Array.indexOf`, () => {
|
||||
return input.indexOf("thud");
|
||||
});
|
||||
|
||||
await run();
|
||||
64
bench/snippets/object-entries.mjs
Normal file
64
bench/snippets/object-entries.mjs
Normal file
@@ -0,0 +1,64 @@
|
||||
// so it can run in environments without node module resolution
|
||||
import { bench, run } from "../../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
const obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
e: 5,
|
||||
f: 6,
|
||||
g: 7,
|
||||
h: 8,
|
||||
i: 9,
|
||||
j: 10,
|
||||
k: 11,
|
||||
l: 12,
|
||||
m: 13,
|
||||
n: 14,
|
||||
o: 15,
|
||||
p: 16,
|
||||
q: 17,
|
||||
r: 18,
|
||||
s: 19,
|
||||
t: 20,
|
||||
u: 21,
|
||||
v: 22,
|
||||
w: 23,
|
||||
x: 24,
|
||||
y: 25,
|
||||
z: 26,
|
||||
};
|
||||
|
||||
bench("Object.entries(26 keys)", () => {
|
||||
var k;
|
||||
for (let [key, value] of Object.entries(obj)) {
|
||||
value = key;
|
||||
}
|
||||
return k;
|
||||
});
|
||||
|
||||
bench("Object.keys(26 keys)", () => {
|
||||
var k;
|
||||
for (let [key, value] of Object.keys(obj)) {
|
||||
value = key;
|
||||
}
|
||||
return k;
|
||||
});
|
||||
|
||||
bench("Object.entries(2 keys)", () => {
|
||||
var k;
|
||||
for (let [key, value] of Object.entries({ a: 1, b: 2 })) {
|
||||
value = key;
|
||||
}
|
||||
return k;
|
||||
});
|
||||
|
||||
bench("Object.keys(2 keys)", () => {
|
||||
var k;
|
||||
for (let item of Object.keys({ a: 1, b: 2 })) {
|
||||
}
|
||||
return k;
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,6 +1,6 @@
|
||||
import { bench, group, run } from "mitata";
|
||||
import { renderToReadableStream } from "react-dom/cjs/react-dom-server.browser.production.min";
|
||||
import { renderToReadableStream as renderToReadableStreamBun } from "../test/bun.js/reactdom-bun";
|
||||
import { renderToReadableStream as renderToReadableStreamBun } from "../test/bun.js/react-dom-server.bun";
|
||||
|
||||
const App = () => (
|
||||
<div>
|
||||
|
||||
13
bench/snippets/readdir.mjs
Normal file
13
bench/snippets/readdir.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { readdirSync } from "fs";
|
||||
import { bench, run } from "mitata";
|
||||
import { argv } from "process";
|
||||
|
||||
const dir = argv.length > 2 ? argv[2] : "/tmp";
|
||||
|
||||
const count = readdirSync(dir).length;
|
||||
bench(`readdir("${dir}")`, () => {
|
||||
readdirSync(dir, { withFileTypes: true });
|
||||
});
|
||||
|
||||
await run();
|
||||
console.log("\n\nFor", count, "files/dirs in", dir);
|
||||
16
bench/snippets/return-await.mjs
Normal file
16
bench/snippets/return-await.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
bench("return await Promise.resolve(1)", async function () {
|
||||
return await Promise.resolve(1);
|
||||
});
|
||||
|
||||
bench("return Promise.resolve(1) (async fn)", async function () {
|
||||
return Promise.resolve(1);
|
||||
});
|
||||
|
||||
bench("return await 1", async function () {
|
||||
return await 1;
|
||||
});
|
||||
|
||||
|
||||
await run();
|
||||
16
bench/snippets/set-timeout.mjs
Normal file
16
bench/snippets/set-timeout.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
bench("setTimeout(, 4) 100 times", async () => {
|
||||
var i = 100;
|
||||
while (--i >= 0) {
|
||||
await new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 4);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
run({}).then(() => {});
|
||||
}, 1);
|
||||
7
bench/snippets/sha512.deno.mjs
Normal file
7
bench/snippets/sha512.deno.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Sha512 } from "https://deno.land/std/hash/sha512.ts";
|
||||
|
||||
import { bench, run } from "https://esm.run/mitata";
|
||||
|
||||
bench("Sha512", () => new Sha512().update("hello world").arrayBuffer());
|
||||
|
||||
await run();
|
||||
8
bench/snippets/sha512.js
Normal file
8
bench/snippets/sha512.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { SHA512 } from "bun";
|
||||
|
||||
bench('SHA512.hash("hello world")', () => {
|
||||
SHA512.hash("hello world");
|
||||
});
|
||||
|
||||
await run();
|
||||
8
bench/snippets/sha512.node.mjs
Normal file
8
bench/snippets/sha512.node.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { createHash } from "crypto";
|
||||
|
||||
bench('createHash("sha256").update("hello world").digest()', () => {
|
||||
createHash("sha256").update("hello world").digest();
|
||||
});
|
||||
|
||||
await run();
|
||||
13
bench/snippets/spawn-hugemem.mjs
Normal file
13
bench/snippets/spawn-hugemem.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { spawnSync } from "bun";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
var memory = new Uint8Array(128 * 1024 * 1024);
|
||||
memory.fill(10);
|
||||
// prevent memory from being garbage collected
|
||||
globalThis.memory = memory;
|
||||
|
||||
bench("spawnSync echo hi", () => {
|
||||
spawnSync({ cmd: ["echo", "hi"] });
|
||||
});
|
||||
|
||||
await run();
|
||||
13
bench/snippets/spawn-hugemem.node.mjs
Normal file
13
bench/snippets/spawn-hugemem.node.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { spawnSync } from "child_process";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
var memory = new Uint8Array(128 * 1024 * 1024);
|
||||
memory.fill(10);
|
||||
// prevent memory from being garbage collected
|
||||
globalThis.memory = memory;
|
||||
|
||||
bench("spawnSync echo hi", () => {
|
||||
spawnSync("echo", ["hi"], { encoding: "buffer", shell: false });
|
||||
});
|
||||
|
||||
await run();
|
||||
8
bench/snippets/spawn.mjs
Normal file
8
bench/snippets/spawn.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { spawnSync } from "bun";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
bench("spawnSync echo hi", () => {
|
||||
spawnSync({ cmd: ["echo", "hi"] });
|
||||
});
|
||||
|
||||
await run();
|
||||
8
bench/snippets/spawn.node.mjs
Normal file
8
bench/snippets/spawn.node.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { spawnSync } from "child_process";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
bench("spawnSync echo hi", () => {
|
||||
spawnSync("echo", ["hi"], { encoding: "buffer", shell: false });
|
||||
});
|
||||
|
||||
await run();
|
||||
24
bench/snippets/write.bun.js
Normal file
24
bench/snippets/write.bun.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { write } from "bun";
|
||||
import { openSync } from "fs";
|
||||
|
||||
bench('write(/tmp/foo.txt, "short string")', async () => {
|
||||
await write("/tmp/foo.txt", "short string");
|
||||
});
|
||||
|
||||
const buffer = Buffer.from("short string");
|
||||
bench('write(/tmp/foo.txt, Buffer.from("short string"))', async () => {
|
||||
await write("/tmp/foo.txt", buffer);
|
||||
});
|
||||
|
||||
const fd = openSync("/tmp/foo.txt", "w");
|
||||
|
||||
bench('write(fd, "short string")', async () => {
|
||||
await write(fd, "short string");
|
||||
});
|
||||
|
||||
bench('write(fd, Buffer.from("short string"))', async () => {
|
||||
await write(fd, buffer);
|
||||
});
|
||||
|
||||
await run();
|
||||
27
bench/snippets/write.node.mjs
Normal file
27
bench/snippets/write.node.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { openSync } from "fs";
|
||||
import { writeFile } from "fs/promises";
|
||||
import { writeSync as write } from "fs";
|
||||
|
||||
bench("writeFile(/tmp/foo.txt, short string)", async () => {
|
||||
await writeFile("/tmp/foo.txt", "short string", "utf8");
|
||||
});
|
||||
|
||||
const buffer = Buffer.from("short string");
|
||||
bench("writeFile(/tmp/foo.txt, Buffer.from(short string))", async () => {
|
||||
await writeFile("/tmp/foo.txt", buffer);
|
||||
});
|
||||
|
||||
const fd = openSync("/tmp/foo.txt", "w");
|
||||
|
||||
bench("write(fd, short string)", () => {
|
||||
const bytesWritten = write(fd, "short string", "utf8");
|
||||
if (bytesWritten !== 12) throw new Error("wrote !== 12");
|
||||
});
|
||||
|
||||
bench("write(fd, Uint8Array(short string))", () => {
|
||||
const bytesWritten = write(fd, buffer);
|
||||
if (bytesWritten !== 12) throw new Error("wrote !== 12");
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,26 +1,26 @@
|
||||
import { DB } from "https://deno.land/x/sqlite/mod.ts";
|
||||
import { Database } from "https://deno.land/x/sqlite3@0.6.1/mod.ts";
|
||||
import { run, bench } from "../node_modules/mitata/src/cli.mjs";
|
||||
|
||||
const db = new DB("./src/northwind.sqlite");
|
||||
const db = new Database("./src/northwind.sqlite");
|
||||
|
||||
{
|
||||
const sql = db.prepareQuery(`SELECT * FROM "Order"`);
|
||||
const sql = db.prepare(`SELECT * FROM "Order"`);
|
||||
bench('SELECT * FROM "Order"', () => {
|
||||
sql.allEntries();
|
||||
sql.all();
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const sql = db.prepareQuery(`SELECT * FROM "Product"`);
|
||||
const sql = db.prepare(`SELECT * FROM "Product"`);
|
||||
bench('SELECT * FROM "Product"', () => {
|
||||
sql.allEntries();
|
||||
sql.all();
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const sql = db.prepareQuery(`SELECT * FROM "OrderDetail"`);
|
||||
const sql = db.prepare(`SELECT * FROM "OrderDetail"`);
|
||||
bench('SELECT * FROM "OrderDetail"', () => {
|
||||
sql.allEntries();
|
||||
sql.all();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
169
bench/websocket-server/.gitignore
vendored
Normal file
169
bench/websocket-server/.gitignore
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Logs
|
||||
|
||||
logs
|
||||
_.log
|
||||
npm-debug.log_
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# Runtime data
|
||||
|
||||
pids
|
||||
_.pid
|
||||
_.seed
|
||||
\*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
||||
coverage
|
||||
\*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
|
||||
\*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
|
||||
\*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
|
||||
.cache/
|
||||
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.\*
|
||||
39
bench/websocket-server/README.md
Normal file
39
bench/websocket-server/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# websocket-server
|
||||
|
||||
This benchmarks a websocket server intended as a simple but very active chat room.
|
||||
|
||||
First, start the server. By default, it will wait for 16 clients which the client script will handle.
|
||||
|
||||
Run in Bun (`Bun.serve`):
|
||||
|
||||
```bash
|
||||
bun ./chat-server.bun.js
|
||||
```
|
||||
|
||||
Run in Node (`"ws"` package):
|
||||
|
||||
```bash
|
||||
node ./chat-server.node.mjs
|
||||
```
|
||||
|
||||
Run in Deno (`Deno.serve`):
|
||||
|
||||
```bash
|
||||
deno run -A --unstable ./chat-server.deno.mjs
|
||||
```
|
||||
|
||||
Then, run the client script. By default, it will connect 16 clients. This client script can run in Bun, Node, or Deno
|
||||
|
||||
```bash
|
||||
node ./chat-client.mjs
|
||||
```
|
||||
|
||||
The client script loops through a list of messages for each connected client and sends a message.
|
||||
|
||||
For example, when the client sends `"foo"`, the server sends back `"John: foo"` so that all members of the chatroom receive the message.
|
||||
|
||||
The client script waits until it receives all the messages for each client before sending the next batch of messages.
|
||||
|
||||
TODO: once Deno lands their performance improvements, increase the client count (it was originally going to be 32 or 64, but that would've exluded Deno from the benchmark)
|
||||
|
||||
This project was created using `bun init` in bun v0.2.1. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||
182
bench/websocket-server/chat-client.mjs
Normal file
182
bench/websocket-server/chat-client.mjs
Normal file
@@ -0,0 +1,182 @@
|
||||
const env =
|
||||
"process" in globalThis
|
||||
? process.env
|
||||
: "Deno" in globalThis
|
||||
? Deno.env.toObject()
|
||||
: {};
|
||||
|
||||
const SERVER = env.SERVER || "ws://0.0.0.0:4001";
|
||||
const WebSocket = globalThis.WebSocket || (await import("ws")).WebSocket;
|
||||
const LOG_MESSAGES = env.LOG_MESSAGES === "1";
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(env.CLIENTS_COUNT || "", 10) || 16;
|
||||
const DELAY = 64;
|
||||
const MESSAGES_TO_SEND = Array.from({ length: 32 }, () => [
|
||||
"Hello World!",
|
||||
"Hello World! 1",
|
||||
"Hello World! 2",
|
||||
"Hello World! 3",
|
||||
"Hello World! 4",
|
||||
"Hello World! 5",
|
||||
"Hello World! 6",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"Hello World! 7",
|
||||
"Hello World! 8",
|
||||
"Hello World! 9",
|
||||
"What is the meaning of life?",
|
||||
"where is the bathroom?",
|
||||
"zoo",
|
||||
"kangaroo",
|
||||
"erlang",
|
||||
"elixir",
|
||||
"bun",
|
||||
"mochi",
|
||||
"typescript",
|
||||
"javascript",
|
||||
]).flat();
|
||||
|
||||
const NAMES = Array.from({ length: 50 }, (a, i) => [
|
||||
"Alice" + i,
|
||||
"Bob" + i,
|
||||
"Charlie" + i,
|
||||
"David" + i,
|
||||
"Eve" + i,
|
||||
"Frank" + i,
|
||||
"Grace" + i,
|
||||
"Heidi" + i,
|
||||
"Ivan" + i,
|
||||
"Judy" + i,
|
||||
"Karl" + i,
|
||||
"Linda" + i,
|
||||
"Mike" + i,
|
||||
"Nancy" + i,
|
||||
"Oscar" + i,
|
||||
"Peggy" + i,
|
||||
"Quentin" + i,
|
||||
"Ruth" + i,
|
||||
"Steve" + i,
|
||||
"Trudy" + i,
|
||||
"Ursula" + i,
|
||||
"Victor" + i,
|
||||
"Wendy" + i,
|
||||
"Xavier" + i,
|
||||
"Yvonne" + i,
|
||||
"Zach" + i,
|
||||
])
|
||||
.flat()
|
||||
.slice(0, CLIENTS_TO_WAIT_FOR);
|
||||
|
||||
console.log(`Connecting ${CLIENTS_TO_WAIT_FOR} WebSocket clients...`);
|
||||
console.time(`All ${CLIENTS_TO_WAIT_FOR} clients connected`);
|
||||
|
||||
var remainingClients = CLIENTS_TO_WAIT_FOR;
|
||||
var promises = [];
|
||||
|
||||
const clients = new Array(CLIENTS_TO_WAIT_FOR);
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
clients[i] = new WebSocket(`${SERVER}?name=${NAMES[i]}`);
|
||||
promises.push(
|
||||
new Promise((resolve, reject) => {
|
||||
clients[i].onmessage = (event) => {
|
||||
resolve();
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
console.timeEnd(`All ${clients.length} clients connected`);
|
||||
|
||||
var received = 0;
|
||||
var total = 0;
|
||||
var more = false;
|
||||
var remaining;
|
||||
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
clients[i].onmessage = (event) => {
|
||||
if (LOG_MESSAGES) console.log(event.data);
|
||||
received++;
|
||||
remaining--;
|
||||
|
||||
if (remaining === 0) {
|
||||
more = true;
|
||||
remaining = total;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// each message is supposed to be received
|
||||
// by each client
|
||||
// so its an extra loop
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
for (let j = 0; j < MESSAGES_TO_SEND.length; j++) {
|
||||
for (let k = 0; k < CLIENTS_TO_WAIT_FOR; k++) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
remaining = total;
|
||||
|
||||
function restart() {
|
||||
for (let i = 0; i < CLIENTS_TO_WAIT_FOR; i++) {
|
||||
for (let j = 0; j < MESSAGES_TO_SEND.length; j++) {
|
||||
clients[i].send(MESSAGES_TO_SEND[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var runs = [];
|
||||
setInterval(() => {
|
||||
const last = received;
|
||||
runs.push(last);
|
||||
received = 0;
|
||||
console.log(
|
||||
last,
|
||||
`messages per second (${CLIENTS_TO_WAIT_FOR} clients x ${MESSAGES_TO_SEND.length} msg, min delay: ${DELAY}ms)`
|
||||
);
|
||||
|
||||
if (runs.length >= 10) {
|
||||
console.log("10 runs");
|
||||
console.log(JSON.stringify(runs, null, 2));
|
||||
if ("process" in globalThis) process.exit(0);
|
||||
runs.length = 0;
|
||||
}
|
||||
}, 1000);
|
||||
var isRestarting = false;
|
||||
setInterval(() => {
|
||||
if (more && !isRestarting) {
|
||||
more = false;
|
||||
isRestarting = true;
|
||||
restart();
|
||||
isRestarting = false;
|
||||
}
|
||||
}, DELAY);
|
||||
restart();
|
||||
56
bench/websocket-server/chat-server.bun.js
Normal file
56
bench/websocket-server/chat-server.bun.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 16;
|
||||
var remainingClients = CLIENTS_TO_WAIT_FOR;
|
||||
const COMPRESS = process.env.COMPRESS === "1";
|
||||
const port = process.PORT || 4001;
|
||||
|
||||
const server = Bun.serve({
|
||||
port: port,
|
||||
websocket: {
|
||||
open(ws) {
|
||||
ws.subscribe("room");
|
||||
|
||||
remainingClients--;
|
||||
console.log(`${ws.data.name} connected (${remainingClients} remain)`);
|
||||
|
||||
if (remainingClients === 0) {
|
||||
console.log("All clients connected");
|
||||
setTimeout(() => {
|
||||
console.log('Starting benchmark by sending "ready" message');
|
||||
ws.publishText("room", `ready`);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
message(ws, msg) {
|
||||
const out = `${ws.data.name}: ${msg}`;
|
||||
if (ws.publishText("room", out) !== out.length) {
|
||||
throw new Error("Failed to publish message");
|
||||
}
|
||||
},
|
||||
close(ws) {
|
||||
remainingClients++;
|
||||
},
|
||||
|
||||
perMessageDeflate: false,
|
||||
},
|
||||
|
||||
fetch(req, server) {
|
||||
if (
|
||||
server.upgrade(req, {
|
||||
data: {
|
||||
name:
|
||||
new URL(req.url).searchParams.get("name") ||
|
||||
"Client #" + (CLIENTS_TO_WAIT_FOR - remainingClients),
|
||||
},
|
||||
})
|
||||
)
|
||||
return;
|
||||
|
||||
return new Response("Error");
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Waiting for ${remainingClients} clients to connect...\n`,
|
||||
` http://${server.hostname}:${port}/`
|
||||
);
|
||||
48
bench/websocket-server/chat-server.deno.mjs
Normal file
48
bench/websocket-server/chat-server.deno.mjs
Normal file
@@ -0,0 +1,48 @@
|
||||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const port = Deno.env.get("PORT") || 4001;
|
||||
const CLIENTS_TO_WAIT_FOR =
|
||||
parseInt(Deno.env.get("CLIENTS_COUNT") || "", 10) || 16;
|
||||
|
||||
var clients = [];
|
||||
async function reqHandler(req) {
|
||||
if (req.headers.get("upgrade") != "websocket") {
|
||||
return new Response(null, { status: 501 });
|
||||
}
|
||||
const { socket: client, response } = Deno.upgradeWebSocket(req);
|
||||
|
||||
clients.push(client);
|
||||
const name = new URL(req.url).searchParams.get("name");
|
||||
|
||||
console.log(
|
||||
`${name} connected (${CLIENTS_TO_WAIT_FOR - clients.length} remain)`
|
||||
);
|
||||
|
||||
client.onmessage = (event) => {
|
||||
const msg = `${name}: ${event.data}`;
|
||||
for (let client of clients) {
|
||||
client.send(msg);
|
||||
}
|
||||
};
|
||||
client.onclose = () => {
|
||||
clients.splice(clients.indexOf(client), 1);
|
||||
};
|
||||
|
||||
if (clients.length === CLIENTS_TO_WAIT_FOR) {
|
||||
sendReadyMessage();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
function sendReadyMessage() {
|
||||
console.log("All clients connected");
|
||||
setTimeout(() => {
|
||||
console.log("Starting benchmark");
|
||||
for (let client of clients) {
|
||||
client.send(`ready`);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
console.log(`Waiting for ${CLIENTS_TO_WAIT_FOR} clients to connect..`);
|
||||
|
||||
Deno.serve(reqHandler, { port });
|
||||
52
bench/websocket-server/chat-server.node.mjs
Normal file
52
bench/websocket-server/chat-server.node.mjs
Normal file
@@ -0,0 +1,52 @@
|
||||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const port = process.env.PORT || 4001;
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 16;
|
||||
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
var WebSocketServer = require("ws").Server,
|
||||
config = {
|
||||
host: "0.0.0.0",
|
||||
port,
|
||||
},
|
||||
wss = new WebSocketServer(config, function () {
|
||||
console.log(`Waiting for ${CLIENTS_TO_WAIT_FOR} clients to connect..`);
|
||||
});
|
||||
|
||||
var clients = [];
|
||||
|
||||
wss.on("connection", function (ws, { url }) {
|
||||
const name = new URL(new URL(url, "http://localhost:3000")).searchParams.get(
|
||||
"name"
|
||||
);
|
||||
console.log(
|
||||
`${name} connected (${CLIENTS_TO_WAIT_FOR - clients.length} remain)`
|
||||
);
|
||||
clients.push(ws);
|
||||
|
||||
ws.on("message", function (message) {
|
||||
const out = `${name}: ${message}`;
|
||||
for (let client of clients) {
|
||||
client.send(out);
|
||||
}
|
||||
});
|
||||
|
||||
// when a connection is closed
|
||||
ws.on("close", function (ws) {
|
||||
clients.splice(clients.indexOf(ws), 1);
|
||||
});
|
||||
|
||||
if (clients.length === CLIENTS_TO_WAIT_FOR) {
|
||||
sendReadyMessage();
|
||||
}
|
||||
});
|
||||
|
||||
function sendReadyMessage() {
|
||||
console.log("All clients connected");
|
||||
setTimeout(() => {
|
||||
console.log("Starting benchmark");
|
||||
for (let client of clients) {
|
||||
client.send(`ready`);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
13
bench/websocket-server/package.json
Normal file
13
bench/websocket-server/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "websocket-server",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"bun-types": "^0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.7",
|
||||
"utf-8-validate": "^5.0.10",
|
||||
"ws": "^8.9.0"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,11 @@
|
||||
"lib": ["ESNext"],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "node",
|
||||
|
||||
// so that if your project isn't using TypeScript, it still has autocomplete
|
||||
"allowJs": true,
|
||||
|
||||
// "bun-types" is the important part
|
||||
"types": ["bun-types"]
|
||||
}
|
||||
250
build.zig
250
build.zig
@@ -132,7 +132,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
|
||||
};
|
||||
|
||||
io.dependencies = &.{analytics};
|
||||
|
||||
uws.dependencies = &.{boringssl};
|
||||
javascript_core.dependencies = &.{ http, strings, picohttp, io, uws };
|
||||
http.dependencies = &.{
|
||||
strings,
|
||||
@@ -140,6 +140,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
|
||||
io,
|
||||
boringssl,
|
||||
thread_pool,
|
||||
uws,
|
||||
};
|
||||
thread_pool.dependencies = &.{ io, http };
|
||||
http.dependencies = &.{
|
||||
@@ -148,6 +149,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
|
||||
io,
|
||||
boringssl,
|
||||
thread_pool,
|
||||
uws,
|
||||
};
|
||||
thread_pool.dependencies = &.{ io, http };
|
||||
|
||||
@@ -169,6 +171,25 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar
|
||||
step.addPackage(lol_html);
|
||||
step.addPackage(uws);
|
||||
}
|
||||
|
||||
const BunBuildOptions = struct {
|
||||
canary: bool = false,
|
||||
sha: [:0]const u8 = "",
|
||||
baseline: bool = false,
|
||||
bindgen: bool = false,
|
||||
sizegen: bool = false,
|
||||
|
||||
pub fn step(this: BunBuildOptions, b: anytype) *std.build.OptionsStep {
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(@TypeOf(this.canary), "is_canary", this.canary);
|
||||
opts.addOption(@TypeOf(this.sha), "sha", this.sha);
|
||||
opts.addOption(@TypeOf(this.baseline), "baseline", this.baseline);
|
||||
opts.addOption(@TypeOf(this.bindgen), "bindgen", this.bindgen);
|
||||
opts.addOption(@TypeOf(this.sizegen), "sizegen", this.sizegen);
|
||||
return opts;
|
||||
}
|
||||
};
|
||||
|
||||
var output_dir: []const u8 = "";
|
||||
fn panicIfNotFound(comptime filepath: []const u8) []const u8 {
|
||||
var file = std.fs.cwd().openFile(filepath, .{ .mode = .read_only }) catch |err| {
|
||||
@@ -219,7 +240,6 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
mode = b.standardReleaseOptions();
|
||||
|
||||
const cwd: []const u8 = b.pathFromRoot(".");
|
||||
var exe: *std.build.LibExeObjStep = undefined;
|
||||
var output_dir_buf = std.mem.zeroes([4096]u8);
|
||||
var bin_label = if (mode == std.builtin.Mode.Debug) "packages/debug-bun-" else "packages/bun-";
|
||||
@@ -281,8 +301,6 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
exe.setBuildMode(mode);
|
||||
b.install_path = output_dir;
|
||||
|
||||
var typings_exe = b.addExecutable("typescript-decls", "src/typegen.zig");
|
||||
|
||||
const min_version: std.builtin.Version = if (target.getOsTag() != .freestanding)
|
||||
target.getOsVersionMin().semver
|
||||
else .{ .major = 0, .minor = 0, .patch = 0 };
|
||||
@@ -305,53 +323,47 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var obj_step = b.step("obj", "Build bun as a .o file");
|
||||
var obj = b.addObject(bun_executable_name, exe.root_src.?.path);
|
||||
|
||||
const is_baseline = arch.isX86() and (target.cpu_model == .baseline or
|
||||
!std.Target.x86.featureSetHas(target.getCpuFeatures(), .avx2));
|
||||
var default_build_options: BunBuildOptions = brk: {
|
||||
const is_baseline = arch.isX86() and (target.cpu_model == .baseline or
|
||||
!std.Target.x86.featureSetHas(target.getCpuFeatures(), .avx2));
|
||||
|
||||
var git_sha: [:0]const u8 = "";
|
||||
if (std.os.getenvZ("GITHUB_SHA") orelse std.os.getenvZ("GIT_SHA")) |sha| {
|
||||
git_sha = std.heap.page_allocator.dupeZ(u8, sha) catch unreachable;
|
||||
} else {
|
||||
sha: {
|
||||
const result = std.ChildProcess.exec(.{
|
||||
.allocator = std.heap.page_allocator,
|
||||
.argv = &.{
|
||||
"git",
|
||||
"rev-parse",
|
||||
"--short",
|
||||
"HEAD",
|
||||
},
|
||||
.cwd = b.pathFromRoot("."),
|
||||
.expand_arg0 = .expand,
|
||||
}) catch {
|
||||
std.debug.print("Warning: failed to get git HEAD", .{});
|
||||
break :sha;
|
||||
};
|
||||
var git_sha: [:0]const u8 = "";
|
||||
if (std.os.getenvZ("GITHUB_SHA") orelse std.os.getenvZ("GIT_SHA")) |sha| {
|
||||
git_sha = std.heap.page_allocator.dupeZ(u8, sha) catch unreachable;
|
||||
} else {
|
||||
sha: {
|
||||
const result = std.ChildProcess.exec(.{
|
||||
.allocator = std.heap.page_allocator,
|
||||
.argv = &.{
|
||||
"git",
|
||||
"rev-parse",
|
||||
"--short",
|
||||
"HEAD",
|
||||
},
|
||||
.cwd = b.pathFromRoot("."),
|
||||
.expand_arg0 = .expand,
|
||||
}) catch {
|
||||
std.debug.print("Warning: failed to get git HEAD", .{});
|
||||
break :sha;
|
||||
};
|
||||
|
||||
git_sha = std.heap.page_allocator.dupeZ(u8, std.mem.trim(u8, result.stdout, "\n \t")) catch unreachable;
|
||||
git_sha = std.heap.page_allocator.dupeZ(u8, std.mem.trim(u8, result.stdout, "\n \t")) catch unreachable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const is_canary = (std.os.getenvZ("BUN_CANARY") orelse "0")[0] == '1';
|
||||
const is_canary = (std.os.getenvZ("BUN_CANARY") orelse "0")[0] == '1';
|
||||
break :brk .{
|
||||
.canary = is_canary,
|
||||
.sha = git_sha,
|
||||
.baseline = is_baseline,
|
||||
.bindgen = false,
|
||||
};
|
||||
};
|
||||
|
||||
{
|
||||
obj.setTarget(target);
|
||||
addPicoHTTP(obj, false);
|
||||
obj.setMainPkgPath(b.pathFromRoot("."));
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
|
||||
try addInternalPackages(
|
||||
obj,
|
||||
@@ -359,7 +371,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
target,
|
||||
);
|
||||
|
||||
if (is_baseline) {
|
||||
if (default_build_options.baseline) {
|
||||
obj.target.cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 };
|
||||
} else if (arch.isX86()) {
|
||||
obj.target.cpu_model = .{ .explicit = &std.Target.x86.cpu.haswell };
|
||||
@@ -386,7 +398,13 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
obj.setOutputDir(output_dir);
|
||||
obj.setBuildMode(mode);
|
||||
|
||||
obj.addOptions("build_options", opts);
|
||||
var actual_build_options = default_build_options;
|
||||
if (b.option(bool, "generate-sizes", "Generate sizes of things") orelse false) {
|
||||
actual_build_options.sizegen = true;
|
||||
obj.setOutputDir(b.pathFromRoot("misctools/sizegen"));
|
||||
}
|
||||
|
||||
obj.addOptions("build_options", actual_build_options.step(b));
|
||||
|
||||
obj.linkLibC();
|
||||
|
||||
@@ -412,21 +430,9 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("headers", "src/bindgen.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var headers_opts = b.addOptions();
|
||||
headers_opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
true,
|
||||
);
|
||||
headers_opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
headers_opts.addOption([:0]const u8, "sha", git_sha);
|
||||
headers_opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", headers_opts);
|
||||
|
||||
var headers_build_options = default_build_options;
|
||||
headers_build_options.bindgen = true;
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
headers_obj.linkLibCpp();
|
||||
}
|
||||
|
||||
@@ -446,21 +452,15 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("httpbench", "misctools/http_bench.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
{
|
||||
const headers_step = b.step("machbench-obj", "Build Machbench tool (object files)");
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("machbench", "misctools/machbench.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -468,21 +468,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("fetch", "misctools/fetch.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -490,21 +476,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addExecutable("string-bench", "src/bench/string-handling.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -512,21 +484,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("sha", "src/sha.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -534,21 +492,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addExecutable("vlq-bench", "src/sourcemap/vlq_bench.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -556,21 +500,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
var headers_obj: *std.build.LibExeObjStep = b.addObject("tgz", "misctools/tgz.zig");
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
var opts = b.addOptions();
|
||||
opts.addOption(
|
||||
bool,
|
||||
"bindgen",
|
||||
false,
|
||||
);
|
||||
|
||||
opts.addOption(
|
||||
bool,
|
||||
"baseline",
|
||||
is_baseline,
|
||||
);
|
||||
opts.addOption([:0]const u8, "sha", git_sha);
|
||||
opts.addOption(bool, "is_canary", is_canary);
|
||||
headers_obj.addOptions("build_options", opts);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -589,12 +519,14 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
|
||||
try configureObjectStep(b, headers_obj, target, obj.main_pkg_path.?);
|
||||
try linkObjectFiles(b, headers_obj, target);
|
||||
|
||||
{
|
||||
var before = b.addLog("\x1b[" ++ color_map.get("magenta").? ++ "\x1b[" ++ color_map.get("b").? ++ "[{s} tests]" ++ "\x1b[" ++ color_map.get("d").? ++ " ----\n\n" ++ "\x1b[0m", .{"bun"});
|
||||
var after = b.addLog("\x1b[" ++ color_map.get("d").? ++ "–––---\n\n" ++ "\x1b[0m", .{});
|
||||
headers_step.dependOn(&before.step);
|
||||
headers_step.dependOn(&headers_obj.step);
|
||||
headers_step.dependOn(&after.step);
|
||||
headers_obj.addOptions("build_options", default_build_options.step(b));
|
||||
}
|
||||
|
||||
for (headers_obj.packages.items) |pkg_| {
|
||||
@@ -604,7 +536,10 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
|
||||
test_.setMainPkgPath(obj.main_pkg_path.?);
|
||||
test_.setTarget(target);
|
||||
try configureObjectStep(b, test_, target, obj.main_pkg_path.?);
|
||||
try linkObjectFiles(b, test_, target);
|
||||
test_.addOptions("build_options", default_build_options.step(b));
|
||||
|
||||
if (pkg.dependencies) |children| {
|
||||
test_.packages = std.ArrayList(std.build.Pkg).init(b.allocator);
|
||||
try test_.packages.appendSlice(children);
|
||||
@@ -617,25 +552,6 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
headers_step.dependOn(&after.step);
|
||||
}
|
||||
}
|
||||
|
||||
try configureObjectStep(b, typings_exe, target, obj.main_pkg_path.?);
|
||||
try linkObjectFiles(b, typings_exe, target);
|
||||
|
||||
var typings_cmd: *std.build.RunStep = typings_exe.run();
|
||||
typings_cmd.cwd = cwd;
|
||||
typings_cmd.addArg(cwd);
|
||||
typings_cmd.addArg("types");
|
||||
typings_cmd.step.dependOn(&typings_exe.step);
|
||||
if (target.getOsTag() == .macos) {
|
||||
typings_exe.linkSystemLibrary("icucore");
|
||||
typings_exe.linkSystemLibrary("iconv");
|
||||
typings_exe.addLibPath(
|
||||
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib",
|
||||
);
|
||||
}
|
||||
|
||||
var typings_step = b.step("types", "Build TypeScript types");
|
||||
typings_step.dependOn(&typings_cmd.step);
|
||||
}
|
||||
|
||||
pub var original_make_fn: ?fn (step: *std.build.Step) anyerror!void = null;
|
||||
|
||||
@@ -75,13 +75,16 @@ complete -c bun \
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -s 'u' -l 'origin' -r -d 'Server URL. Rewrites import paths'
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -s 'p' -l 'port' -r -d 'Port number to start server from'
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -s 'p' -l 'port' -r -d 'Port number to start server from'
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -s 'd' -l 'define' -r -d 'Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:\"development\"'
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -s 'e' -l 'external' -r -d 'Exclude module from transpilation (can use * wildcards). ex: -e react'
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -l 'use' -r -d 'Use a framework (ex: next)'
|
||||
complete -c bun \
|
||||
-n "not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) install remove add;" --no-files -l 'hot' -r -d 'Enable hot reloading in Bun\'s JavaScript runtime'
|
||||
|
||||
complete -c bun \
|
||||
-n "bun_fish_is_nth_token 1; and not __fish_seen_subcommand_from $bun_builtin_cmds; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) and __fish_use_subcommand" -a 'dev' -d 'Start dev server'
|
||||
complete -c bun \
|
||||
|
||||
@@ -409,6 +409,7 @@ _bun() {
|
||||
'--version[Show version and exit]' \
|
||||
'-V[Show version and exit]' \
|
||||
'--cwd[Change directory]:cwd' \
|
||||
'--hot[Enable hot reloading]' \
|
||||
'--help[Show command help]' \
|
||||
'-h[Show command help]' \
|
||||
'--all[]' &&
|
||||
|
||||
@@ -10,7 +10,7 @@ WORKDIR /tmp
|
||||
RUN apk --no-cache add unzip
|
||||
|
||||
# get bun
|
||||
ADD https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip
|
||||
ADD https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip bun-linux-x64.zip
|
||||
RUN unzip bun-linux-x64.zip
|
||||
|
||||
# get glibc
|
||||
|
||||
5
docs/runtime/streams.md
Normal file
5
docs/runtime/streams.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Streams in Bun
|
||||
|
||||
Bun supports Web Streams ([`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) first and partially supports Node.js [`"stream"`](https://nodejs.org/api/stream.html).
|
||||
|
||||
## `ReadableStream`
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "@bun-examples/blank",
|
||||
"version": "0.0.3",
|
||||
"module": "src/index.js",
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
## Getting Started
|
||||
|
||||
### Cloning the repo
|
||||
|
||||
```sh
|
||||
bun create blank ./NAME_HERE
|
||||
```
|
||||
|
||||
### Execute a file (eg. src/index.js)
|
||||
|
||||
```sh
|
||||
bun run ./src/index.js
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
console.log('Hello, World!');
|
||||
42
examples/bun-bakery/.gitignore
vendored
42
examples/bun-bakery/.gitignore
vendored
@@ -1,42 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
**/*.trace
|
||||
**/*.zip
|
||||
**/*.tar.gz
|
||||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,42 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
**/*.trace
|
||||
**/*.zip
|
||||
**/*.tar.gz
|
||||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
@@ -1,8 +0,0 @@
|
||||
import {Router} from "@kapsonfire/bun-bakery"
|
||||
|
||||
|
||||
new Router({
|
||||
port: 3000,
|
||||
assetsPath: import.meta.dir + '/assets/',
|
||||
routesPath: import.meta.dir + '/routes/'
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": "1.0.4",
|
||||
"name": "@bun-examples/bun-bakery",
|
||||
"dependencies": {
|
||||
"@kapsonfire/bun-bakery": "^0.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import {Context} from "@kapsonfire/bun-bakery"
|
||||
|
||||
export async function GET(ctx: Context) {
|
||||
ctx.sendHTML('<img src="/assets/bunbakery.png"><h1>Hello World!</h1>');
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": ["bun-types"],
|
||||
"module": "esnext",
|
||||
"moduleResolution": "Node"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
DISCORD_APP_ID=
|
||||
DISCORD_BOT_TOKEN=
|
||||
DISCORD_PUBLIC_KEY=
|
||||
88
examples/discord-interactions/.gitignore
vendored
88
examples/discord-interactions/.gitignore
vendored
@@ -1,88 +0,0 @@
|
||||
/data
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
#config file
|
||||
config.json
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# pm2
|
||||
.pm2
|
||||
.pm2.bak
|
||||
@@ -1,15 +0,0 @@
|
||||
# /create with Bun runtime
|
||||
|
||||
A [slash-create](https://npm.im/slash-create) template, using [Bun runtime](https://bun.sh).
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Cloning the repo
|
||||
|
||||
```sh
|
||||
bun create discord-interactions interactions-bot
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
To run this locally, rename `.env.example` to `.env` and fill in the variables, then run `bun run.js` to start a local dev environment and use something similar to [ngrok](https://ngrok.com/) or [cloudflare](https://www.cloudflare.com/) to tunnel it to a URL.
|
||||
@@ -1,39 +0,0 @@
|
||||
import { join, extname } from 'path';
|
||||
import { Creator } from 'slash-create';
|
||||
import { readdirSync, lstatSync } from 'fs';
|
||||
import { FetchRequestHandler } from './rest.js';
|
||||
export { default as BunServer } from './server.js';
|
||||
|
||||
export class BunSlashCreator extends Creator {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.requestHandler = new FetchRequestHandler(this);
|
||||
}
|
||||
|
||||
async registerCommandsIn(commandPath, customExtensions = []) {
|
||||
const commands = [];
|
||||
const extensions = ['.js', '.ts', '.mjs', '.cjs', ...customExtensions];
|
||||
|
||||
for (const path of find_files_with_extension(commandPath, extensions)) {
|
||||
try {
|
||||
commands.push(await import(path));
|
||||
} catch (error) {
|
||||
this.emit('error', new Error(`Failed to load command ${filePath}: ${e}`));
|
||||
}
|
||||
}
|
||||
|
||||
return this.registerCommands(commands, true);
|
||||
}
|
||||
}
|
||||
|
||||
function find_files_with_extension(path, extensions, names = []) {
|
||||
for (const name of readdirSync(path)) {
|
||||
const p = join(path, name);
|
||||
const stat = lstatSync(p);
|
||||
|
||||
if (extensions.includes(extname(name))) names.push(p);
|
||||
else if (stat.isDirectory()) find_files_with_extension(p, extensions, names);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import { RequestHandler } from 'slash-create';
|
||||
import { MultipartData } from 'slash-create/lib/util/multipartData.js';
|
||||
|
||||
export class FetchRequestHandler extends RequestHandler {
|
||||
toString() {
|
||||
return '[RequestHandler]';
|
||||
}
|
||||
|
||||
async request(method, url, auth = true, body, file) {
|
||||
const creator = this._creator;
|
||||
|
||||
const headers = {
|
||||
'user-agent': this.userAgent,
|
||||
'x-ratelimit-precision': 'millisecond',
|
||||
};
|
||||
|
||||
if (auth) {
|
||||
headers.authorization = creator.options.token;
|
||||
if (!headers.authorization) throw new Error('No token was set in the SlashCreator.');
|
||||
}
|
||||
|
||||
if (body) {
|
||||
if (method !== 'GET' && method !== 'DELETE') {
|
||||
body = JSON.stringify(body);
|
||||
headers['content-type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
|
||||
if (file) {
|
||||
if (Array.isArray(file)) {}
|
||||
else if (file.file) file = [file];
|
||||
else throw new Error('Invalid file object.');
|
||||
|
||||
const form = new MultipartData();
|
||||
headers['content-type'] = `multipart/form-data; boundary=${form.boundary}`;
|
||||
|
||||
for (const f of file) form.attach(f.name, f.file, f.name);
|
||||
if (body) form.attach('payload_json', JSON.stringify(body));
|
||||
|
||||
body = Buffer.concat(form.finish());
|
||||
}
|
||||
|
||||
const res = await fetch('https://discord.com' + this.baseURL + url, { body, method, headers });
|
||||
|
||||
if (res.ok) return res.json();
|
||||
throw new Error(`${method} got ${res.status} - ${await res.text()}`);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import { Server } from 'slash-create';
|
||||
import { MultipartData } from 'slash-create/lib/util/multipartData.js';
|
||||
|
||||
export default class BunServer extends Server {
|
||||
#server = null;
|
||||
#handler = null;
|
||||
isWebserver = true;
|
||||
|
||||
constructor() {
|
||||
super({ alreadyListening: true });
|
||||
}
|
||||
|
||||
createEndpoint(path, handler) {
|
||||
this.#handler = handler;
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.#server) this.#server.close();
|
||||
else throw new Error('BunServer not started');
|
||||
}
|
||||
|
||||
listen(port, options = {}) {
|
||||
const getHandler = () => this.#handler;
|
||||
|
||||
this.#server = Bun.serve({
|
||||
port,
|
||||
...options,
|
||||
|
||||
async fetch(req) {
|
||||
const handler = getHandler();
|
||||
if (!handler) return new Response('Server has no handler.', { status: 503 });
|
||||
if (req.method !== 'POST') return new Response('Server only supports POST requests.', { status: 405 });
|
||||
|
||||
const reqHeaders = Object.fromEntries(req.headers.entries());
|
||||
|
||||
const reqBody = await req.json();
|
||||
|
||||
return await new Promise(async (ok, err) => {
|
||||
try {
|
||||
await handler({
|
||||
request: req,
|
||||
body: reqBody,
|
||||
response: null,
|
||||
headers: reqHeaders,
|
||||
}, response => {
|
||||
let body = response.body;
|
||||
const headers = new Headers();
|
||||
|
||||
if (response.headers) {
|
||||
for (const key in response.headers) {
|
||||
headers.set(key, response.headers[key]);
|
||||
}
|
||||
}
|
||||
|
||||
if ('string' !== typeof body) {
|
||||
body = JSON.stringify(body);
|
||||
headers.set('content-type', 'application/json');
|
||||
}
|
||||
|
||||
if (response.files) {
|
||||
const form = new MultipartData();
|
||||
headers.set('content-type', `multipart/form-data; boundary=${form.boundary}`);
|
||||
|
||||
form.attach('payload_json', body);
|
||||
for (const file of response.files) form.attach(file.name, file.file, file.name);
|
||||
|
||||
body = Buffer.concat(form.finish());
|
||||
}
|
||||
|
||||
ok(new Response(body, { headers, status: response.status }));
|
||||
});
|
||||
} catch (error) {
|
||||
err(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import { SlashCommand, ApplicationCommandType } from 'slash-create';
|
||||
|
||||
export default class AvatarCommand extends SlashCommand {
|
||||
constructor(creator) {
|
||||
super(creator, {
|
||||
// You must specify a type for context menu commands, but defaults
|
||||
// to `CHAT_INPUT`, or regular slash commands.
|
||||
type: ApplicationCommandType.USER,
|
||||
name: 'Get Avatar URL',
|
||||
});
|
||||
|
||||
this.filePath = __filename;
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
// The target user can be accessed from here
|
||||
// You can also use `ctx.targetMember` for member properties
|
||||
const target = ctx.targetUser;
|
||||
return `${target.username}'s Avatar: ${target.avatarURL}`;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { SlashCommand, CommandOptionType } from 'slash-create';
|
||||
|
||||
export default class HelloCommand extends SlashCommand {
|
||||
constructor(creator) {
|
||||
super(creator, {
|
||||
name: 'hello',
|
||||
description: 'Says hello to you.',
|
||||
options: [{
|
||||
type: CommandOptionType.STRING,
|
||||
name: 'food',
|
||||
description: 'What food do you like?'
|
||||
}]
|
||||
});
|
||||
|
||||
this.filePath = __filename;
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
return ctx.options.food ? `You like ${ctx.options.food}? Nice!` : `Hello, ${ctx.user.username}!`;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { SlashCommand, ComponentType, TextInputStyle } from 'slash-create';
|
||||
|
||||
export default class ModalCommand extends SlashCommand {
|
||||
constructor(creator) {
|
||||
super(creator, {
|
||||
name: 'modal',
|
||||
description: 'Send a cool modal.'
|
||||
});
|
||||
|
||||
this.filePath = __filename;
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
// You can send a modal this way
|
||||
// Keep in mind providing a callback is optional, but no callback requires the custom_id to be defined.
|
||||
ctx.sendModal(
|
||||
{
|
||||
title: 'Example Modal',
|
||||
components: [
|
||||
{
|
||||
type: ComponentType.ACTION_ROW,
|
||||
components: [
|
||||
{
|
||||
type: ComponentType.TEXT_INPUT,
|
||||
label: 'Text Input',
|
||||
style: TextInputStyle.SHORT,
|
||||
custom_id: 'text_input',
|
||||
placeholder: 'Type something...'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: ComponentType.ACTION_ROW,
|
||||
components: [
|
||||
{
|
||||
type: ComponentType.TEXT_INPUT,
|
||||
label: 'Long Text Input',
|
||||
style: TextInputStyle.PARAGRAPH,
|
||||
custom_id: 'long_text_input',
|
||||
placeholder: 'Type something...'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
(mctx) => {
|
||||
mctx.send(`Your input: ${mctx.values.text_input}\nYour long input: ${mctx.values.long_text_input}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/data
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
#config file
|
||||
config.json
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# pm2
|
||||
.pm2
|
||||
.pm2.bak
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"version": "0.0.9",
|
||||
"name": "@bun-examples/discord-interactions",
|
||||
"dependencies": {
|
||||
"slash-create": "^5.7.0"
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
Error.captureStackTrace = () => {};
|
||||
Buffer.isBuffer = Buffer.isBuffer.bind(Buffer);
|
||||
@@ -1,22 +0,0 @@
|
||||
// polyfill v8 and node (TODO: fix in bun)
|
||||
import './polyfill.js';
|
||||
|
||||
import path from 'node:path';
|
||||
import { BunServer, BunSlashCreator } from './bun_shim/index.js';
|
||||
|
||||
const client = new BunSlashCreator({
|
||||
token: process.env.DISCORD_BOT_TOKEN,
|
||||
publicKey: process.env.DISCORD_PUBLIC_KEY,
|
||||
applicationID: process.env.DISCORD_APP_ID,
|
||||
});
|
||||
|
||||
// client.on('debug', console.log);
|
||||
client.on('error', console.error);
|
||||
|
||||
client.withServer(new BunServer());
|
||||
await client.registerCommandsIn(path.join(__dirname, 'commands'));
|
||||
|
||||
client.syncCommands();
|
||||
await client.server.listen(1337);
|
||||
|
||||
// client.server.stop(); // stop server
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"version": "1.0.4",
|
||||
"name": "@bun-examples/hono",
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"hono": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "bun run src/index.ts"
|
||||
},
|
||||
"module": "src/index.js"
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,21 +0,0 @@
|
||||
# Hono with Bun runtime
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Cloning the repo
|
||||
|
||||
```sh
|
||||
bun create hono ./NAME_HERE
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```
|
||||
bun run start
|
||||
```
|
||||
|
||||
Open http://localhost:3000 with your browser to see the result.
|
||||
|
||||
### For more information
|
||||
|
||||
See <https://honojs.dev/>
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Hono } from "hono";
|
||||
import { serveStatic } from 'hono/serve-static.bun';
|
||||
|
||||
const port = parseInt(process.env.PORT) || 3000;
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
app.use('/favicon.ico', serveStatic({ path: './public/favicon.ico' }));
|
||||
|
||||
app.get("/", (c) => {
|
||||
return c.json({ message: "Hello World!" });
|
||||
});
|
||||
|
||||
console.log(`Running at http://localhost:${port}`);
|
||||
|
||||
export default {
|
||||
port,
|
||||
fetch: app.fetch
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext"],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "node",
|
||||
// "bun-types" is the important part
|
||||
"types": ["bun-types"]
|
||||
}
|
||||
}
|
||||
16
examples/http-request-body.ts
Normal file
16
examples/http-request-body.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { serve } from "bun";
|
||||
|
||||
serve({
|
||||
async fetch(req) {
|
||||
// body is a ReadableStream
|
||||
const body = req.body;
|
||||
|
||||
const writer = Bun.file(`upload.${Date.now()}.txt`).writer();
|
||||
for await (const chunk of body) {
|
||||
writer.write(chunk);
|
||||
}
|
||||
const wrote = await writer.end();
|
||||
|
||||
return Response.json({ wrote, type: req.headers.get("Content-Type") });
|
||||
},
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
# KingWorld with Bun runtime
|
||||
|
||||
## Getting Started
|
||||
To get started with this template, simply paste this command into your terminal:
|
||||
```bash
|
||||
bun create kingworld ./kingworld-example
|
||||
```
|
||||
|
||||
## Development
|
||||
KingWorld uses `nodemon` for auto reload. To start the development server run:
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
|
||||
Open http://localhost:3000/ with your browser to see the result.
|
||||
Binary file not shown.
@@ -1,42 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
**/*.trace
|
||||
**/*.zip
|
||||
**/*.tar.gz
|
||||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"restartable": "rs",
|
||||
"ignore": [".git", "node_modules/", "__tests__", "test"],
|
||||
"exec": "bun src/index.ts",
|
||||
"ext": "js, json, ts"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "kingworld",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "nodemon --config nodemon.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"kingworld": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest",
|
||||
"nodemon": "^2.0.19"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import KingWorld from 'kingworld'
|
||||
|
||||
new KingWorld()
|
||||
.get("/", () => "Hello KingWorld")
|
||||
.listen(3000)
|
||||
|
||||
console.log('🦊 KINGWORLD is running at :3000')
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user