mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 23:18:47 +00:00
Compare commits
819 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fab11a527 | ||
|
|
a61953bbfd | ||
|
|
f629365cb7 | ||
|
|
cdace9bffb | ||
|
|
664119841a | ||
|
|
397182b400 | ||
|
|
752e59f23c | ||
|
|
def5a85d90 | ||
|
|
1b8f569792 | ||
|
|
183b818462 | ||
|
|
9cf868fef4 | ||
|
|
ed803f7d1c | ||
|
|
c13a27121c | ||
|
|
8c23e77e99 | ||
|
|
c99a9ba33a | ||
|
|
f75b949524 | ||
|
|
3de9ce5f30 | ||
|
|
65280853ac | ||
|
|
3a9a6c63ac | ||
|
|
360acf5a80 | ||
|
|
d432dad666 | ||
|
|
eec5bfb23a | ||
|
|
53c755467b | ||
|
|
039404800f | ||
|
|
3c4b689050 | ||
|
|
394dd86797 | ||
|
|
62bde005b2 | ||
|
|
19054ebc35 | ||
|
|
507761b463 | ||
|
|
196620183f | ||
|
|
86ad015147 | ||
|
|
db09ed15fd | ||
|
|
bf517d9f8e | ||
|
|
e9b684c972 | ||
|
|
e8f0ed3beb | ||
|
|
3ca7fde363 | ||
|
|
c2ec47ff32 | ||
|
|
26036a390b | ||
|
|
943a664224 | ||
|
|
d0664f8377 | ||
|
|
6fd0043f6b | ||
|
|
0424fd8f6e | ||
|
|
cfbd1373e2 | ||
|
|
f74585ff01 | ||
|
|
b2f8ef4dff | ||
|
|
b0e76a965d | ||
|
|
cfce38858f | ||
|
|
540740c129 | ||
|
|
b1356718ad | ||
|
|
b9b50e39d6 | ||
|
|
6c3dabd84e | ||
|
|
d4438e9496 | ||
|
|
56d591b903 | ||
|
|
0486cea35a | ||
|
|
2634c64aa3 | ||
|
|
af23dab833 | ||
|
|
9efeef2e24 | ||
|
|
67a8b75183 | ||
|
|
bdaa712357 | ||
|
|
b682e5bf59 | ||
|
|
17c348ed0a | ||
|
|
f05a38757a | ||
|
|
553a471cdf | ||
|
|
1a6a52314f | ||
|
|
47450ed12c | ||
|
|
eab7b4c3ea | ||
|
|
0329061f15 | ||
|
|
1e96cbfb02 | ||
|
|
78defe7a87 | ||
|
|
b94433ce86 | ||
|
|
ca26780b27 | ||
|
|
117cee5ca5 | ||
|
|
43ebffedcd | ||
|
|
ccb9daf7a4 | ||
|
|
c6d3b375b8 | ||
|
|
4731a460a2 | ||
|
|
99af827f25 | ||
|
|
a6ec7fe9b1 | ||
|
|
513a6d0df3 | ||
|
|
115704b27b | ||
|
|
85b81624dc | ||
|
|
cf12d80f5e | ||
|
|
58e74eadb5 | ||
|
|
be05b93f39 | ||
|
|
e25833d009 | ||
|
|
e65535cc05 | ||
|
|
74f9fabd01 | ||
|
|
8d207925d7 | ||
|
|
e0569ac47a | ||
|
|
40befd8770 | ||
|
|
6718950a39 | ||
|
|
68ac8c12c2 | ||
|
|
28d1676d50 | ||
|
|
883c4d8778 | ||
|
|
8717303a80 | ||
|
|
385d440694 | ||
|
|
b3019270c9 | ||
|
|
5d7c77aab0 | ||
|
|
2c70837ae7 | ||
|
|
bed7ff7dd0 | ||
|
|
450b066cb8 | ||
|
|
63f58f4026 | ||
|
|
009fe18fa2 | ||
|
|
40d00a961e | ||
|
|
1941dbbd71 | ||
|
|
320cdcf97e | ||
|
|
454407003e | ||
|
|
511f6bdf79 | ||
|
|
320ee6b6b7 | ||
|
|
38df5b146f | ||
|
|
25c91aecab | ||
|
|
5497accbdb | ||
|
|
182e600eb7 | ||
|
|
cb873cc081 | ||
|
|
330d19e344 | ||
|
|
2fe6a965af | ||
|
|
a32097aa9f | ||
|
|
1239c9460a | ||
|
|
f2f227720b | ||
|
|
0b183beb51 | ||
|
|
5ce393aab8 | ||
|
|
00a907c7de | ||
|
|
0665733b03 | ||
|
|
70c3371b14 | ||
|
|
0b2be88bac | ||
|
|
8297fb0d2f | ||
|
|
04925bb94c | ||
|
|
3185ca2d95 | ||
|
|
b93f304c06 | ||
|
|
a9b3d58353 | ||
|
|
cf48379921 | ||
|
|
f8026df821 | ||
|
|
fa4e5d033e | ||
|
|
1462445419 | ||
|
|
ecdf2ffa6c | ||
|
|
cd0774cd89 | ||
|
|
cf8650937a | ||
|
|
3803d39840 | ||
|
|
78081cbb40 | ||
|
|
6bdee80cfc | ||
|
|
637a38f394 | ||
|
|
190ba6b743 | ||
|
|
e2c526708a | ||
|
|
f06f178862 | ||
|
|
8275b8ccd2 | ||
|
|
d196aa2de6 | ||
|
|
bdbc21ff7b | ||
|
|
ff315a3bf2 | ||
|
|
63d265780f | ||
|
|
18a2e18ae1 | ||
|
|
76dee9312b | ||
|
|
9beccc3305 | ||
|
|
717f0a2f42 | ||
|
|
c2ebdf812b | ||
|
|
9ab2acced6 | ||
|
|
944fcebc2b | ||
|
|
9222316101 | ||
|
|
d10860d272 | ||
|
|
76fa3076cd | ||
|
|
112030481f | ||
|
|
9574db355f | ||
|
|
a4d996c337 | ||
|
|
08cf0d562a | ||
|
|
9a2c3dea88 | ||
|
|
2c9ff9584a | ||
|
|
30dde62521 | ||
|
|
928816bef0 | ||
|
|
f17655b2eb | ||
|
|
9f2dcb064d | ||
|
|
6c176cb243 | ||
|
|
e83058cfe7 | ||
|
|
aaaaf744a8 | ||
|
|
207c7eb509 | ||
|
|
505e77c2d0 | ||
|
|
ef6d25a48f | ||
|
|
c2a77cf7ec | ||
|
|
7656b4b17e | ||
|
|
25553e62c1 | ||
|
|
4f39d5b54a | ||
|
|
d9f162ff95 | ||
|
|
9bbac35fd0 | ||
|
|
eba27540b0 | ||
|
|
9cb3f3386e | ||
|
|
6c40d6f2f5 | ||
|
|
0ced5520e6 | ||
|
|
8aa5892f70 | ||
|
|
bd2563ef4c | ||
|
|
214dc039e0 | ||
|
|
e2b39d0807 | ||
|
|
7a8f57c4e5 | ||
|
|
8589ba2f17 | ||
|
|
dd8fdd87dc | ||
|
|
7b8df184b3 | ||
|
|
90991da908 | ||
|
|
404b90badc | ||
|
|
67599f97ad | ||
|
|
8b715dee5b | ||
|
|
f2983e50b7 | ||
|
|
e47a448434 | ||
|
|
de5890ff20 | ||
|
|
aae92c76a6 | ||
|
|
9ecae59bbb | ||
|
|
2ea7290172 | ||
|
|
092ada6d2f | ||
|
|
e636f1b026 | ||
|
|
54a2d89bd2 | ||
|
|
0ea59b4c93 | ||
|
|
b0d3ea5a43 | ||
|
|
a9dc5d51e3 | ||
|
|
749194378a | ||
|
|
794e657eb2 | ||
|
|
1db119ec11 | ||
|
|
413fd28120 | ||
|
|
40a9ba6340 | ||
|
|
681be10294 | ||
|
|
dccf82b1c6 | ||
|
|
5563be99d3 | ||
|
|
bcb6dc7806 | ||
|
|
dae2928620 | ||
|
|
05ef9ec141 | ||
|
|
53cc4df191 | ||
|
|
05716ff39b | ||
|
|
4f914cbfe8 | ||
|
|
da7c1d84e9 | ||
|
|
aebec5b329 | ||
|
|
c68d9ae634 | ||
|
|
bd66a9a94c | ||
|
|
1490cdc4ff | ||
|
|
97009a49bd | ||
|
|
d432448ac8 | ||
|
|
d614fdfaac | ||
|
|
0a4e476a7c | ||
|
|
9078b1286d | ||
|
|
242d8655d8 | ||
|
|
9b91e3c1a2 | ||
|
|
7a1ebec26f | ||
|
|
e7c80b90b8 | ||
|
|
e110ccf84d | ||
|
|
c2a744f0cc | ||
|
|
38168f3c85 | ||
|
|
cbaab23f6d | ||
|
|
3e5beb1279 | ||
|
|
70b9bf743c | ||
|
|
f3153fbee9 | ||
|
|
7fa71dd032 | ||
|
|
52f39d728f | ||
|
|
73eb59019a | ||
|
|
3b24305b7c | ||
|
|
1304779826 | ||
|
|
65d0884361 | ||
|
|
16fdc074ca | ||
|
|
6b35fd847f | ||
|
|
007f357495 | ||
|
|
16a7224ce5 | ||
|
|
7c44773f38 | ||
|
|
85895bd248 | ||
|
|
6c2ec2868f | ||
|
|
704ee13392 | ||
|
|
d7aebc2222 | ||
|
|
dc0d767f27 | ||
|
|
86633e0af4 | ||
|
|
ec2cf38ad8 | ||
|
|
34fd4df646 | ||
|
|
a6d54e5949 | ||
|
|
664ccec7d3 | ||
|
|
1a558ef753 | ||
|
|
f3200ac0ca | ||
|
|
011b50589c | ||
|
|
06503663b1 | ||
|
|
4c89c60867 | ||
|
|
6bfee02301 | ||
|
|
0297cb1527 | ||
|
|
4209703b35 | ||
|
|
8edeb617a8 | ||
|
|
130079b558 | ||
|
|
8356830727 | ||
|
|
5edb756533 | ||
|
|
e402159df1 | ||
|
|
8a0152e129 | ||
|
|
1f1d0bfcfb | ||
|
|
4ebf858f43 | ||
|
|
90ce74a43e | ||
|
|
e1a59d355a | ||
|
|
e154763e4d | ||
|
|
ac10a1b633 | ||
|
|
961312eab0 | ||
|
|
6ca50526d7 | ||
|
|
31976f6af1 | ||
|
|
967ccb5d50 | ||
|
|
d8135e85ca | ||
|
|
b02f097f4d | ||
|
|
4e852918a3 | ||
|
|
c76516fa38 | ||
|
|
ce77266cc5 | ||
|
|
ce9bba9dd5 | ||
|
|
e2e44661c2 | ||
|
|
601fd3ead5 | ||
|
|
07e08b086a | ||
|
|
53eb126898 | ||
|
|
6809d08a90 | ||
|
|
6402967b6d | ||
|
|
bfaf095c2e | ||
|
|
b17b61b8c6 | ||
|
|
27c88c8046 | ||
|
|
04d19d6f6a | ||
|
|
3418feb2e9 | ||
|
|
c6a3467625 | ||
|
|
636cec03e1 | ||
|
|
1ecd9f8a18 | ||
|
|
2323f5d08d | ||
|
|
311dffc690 | ||
|
|
c4f062dbf4 | ||
|
|
7ac94e5b4c | ||
|
|
aa1ad7f009 | ||
|
|
21bb3b2bdd | ||
|
|
cd49615e2c | ||
|
|
eb37794a3b | ||
|
|
da298635ef | ||
|
|
218958dbd1 | ||
|
|
1c6e464a68 | ||
|
|
9c85465a58 | ||
|
|
2eb79afb2a | ||
|
|
020cf46346 | ||
|
|
134c97a282 | ||
|
|
e2c11c4856 | ||
|
|
9ad330d917 | ||
|
|
ef89f03de6 | ||
|
|
c383c6cd81 | ||
|
|
68b4a64569 | ||
|
|
8e12999917 | ||
|
|
73e44e16ea | ||
|
|
99da0ae54b | ||
|
|
4686f5395e | ||
|
|
2dc90f3908 | ||
|
|
53ad9b922f | ||
|
|
0b365781a8 | ||
|
|
dd46c11273 | ||
|
|
8a13e02473 | ||
|
|
ed8be46a7b | ||
|
|
36866c4d79 | ||
|
|
dd58508684 | ||
|
|
9b6dc49575 | ||
|
|
723e9d1ea7 | ||
|
|
f63398ffe4 | ||
|
|
2fbf73535c | ||
|
|
ebbbd63ed6 | ||
|
|
bc28ec39cf | ||
|
|
568cadb51e | ||
|
|
0dbcb84cbe | ||
|
|
d74d95d9ab | ||
|
|
a59ddb131e | ||
|
|
8bd2b784a2 | ||
|
|
f494e1b50d | ||
|
|
112f01ca61 | ||
|
|
49231b2cb9 | ||
|
|
0179ebcb8c | ||
|
|
1790357021 | ||
|
|
105919d7ae | ||
|
|
777ee4ecec | ||
|
|
661355546a | ||
|
|
71f1aa1802 | ||
|
|
eaff66b098 | ||
|
|
b760d1da30 | ||
|
|
728c8fdcdb | ||
|
|
13b54fbdb8 | ||
|
|
9273e29f0e | ||
|
|
9f031b3642 | ||
|
|
ca3b7fa3c9 | ||
|
|
8a176913d8 | ||
|
|
570a44d73a | ||
|
|
5218a33fb6 | ||
|
|
58824ea743 | ||
|
|
99de971359 | ||
|
|
55b5aa3571 | ||
|
|
6ca20424d6 | ||
|
|
36a25c3580 | ||
|
|
13b5d9d4de | ||
|
|
fa4db1de42 | ||
|
|
2a02f3d669 | ||
|
|
75213aad37 | ||
|
|
5856639833 | ||
|
|
edeb3b48e8 | ||
|
|
3613429dc3 | ||
|
|
7917ebd58f | ||
|
|
a86d00c672 | ||
|
|
d5c51092c8 | ||
|
|
6a234e6fce | ||
|
|
dc766eb18a | ||
|
|
209dc981c0 | ||
|
|
7fc392b182 | ||
|
|
6baa08313c | ||
|
|
131ed06020 | ||
|
|
e546e4064c | ||
|
|
c39c11e101 | ||
|
|
2551210426 | ||
|
|
43abf2629f | ||
|
|
325147261f | ||
|
|
044b09afc2 | ||
|
|
9eb8eea2a8 | ||
|
|
04b4157232 | ||
|
|
a02a79e26c | ||
|
|
ae0a724981 | ||
|
|
0631f87866 | ||
|
|
4e1a81231c | ||
|
|
b566573977 | ||
|
|
666feb3b7e | ||
|
|
5ea32a976e | ||
|
|
34b0e7a2bb | ||
|
|
c5f2280489 | ||
|
|
a686b3bfc1 | ||
|
|
a1fb289c96 | ||
|
|
8ca2194a37 | ||
|
|
03904f73cc | ||
|
|
2106e1d7f6 | ||
|
|
854ddaa909 | ||
|
|
609f81a746 | ||
|
|
fd4c8fb871 | ||
|
|
bab58b7541 | ||
|
|
5c8726d602 | ||
|
|
ae7bc37e94 | ||
|
|
31ab56d362 | ||
|
|
4b333b2d35 | ||
|
|
c4c5eb2d32 | ||
|
|
e7afae305c | ||
|
|
17031936c8 | ||
|
|
b2c576bba2 | ||
|
|
4af4b508a1 | ||
|
|
0c2df4ae01 | ||
|
|
cc0d920018 | ||
|
|
438d54f186 | ||
|
|
c6e1135548 | ||
|
|
ec11170311 | ||
|
|
538bcef731 | ||
|
|
93b0e94410 | ||
|
|
963d4311e6 | ||
|
|
2f5e4fffe9 | ||
|
|
ca42c820d2 | ||
|
|
565d1689e9 | ||
|
|
59570fe237 | ||
|
|
aa8b832ef6 | ||
|
|
fa632c3331 | ||
|
|
5846ad00ed | ||
|
|
e26d3821ce | ||
|
|
fceacea37c | ||
|
|
52b7962dae | ||
|
|
386d8b7836 | ||
|
|
67ee498861 | ||
|
|
42eacaf3a9 | ||
|
|
c0cf7b4501 | ||
|
|
affd06d05c | ||
|
|
7ab8d832fb | ||
|
|
0ecdbf4793 | ||
|
|
284aaec3cd | ||
|
|
9bebb7f03d | ||
|
|
5c0a5646cd | ||
|
|
4d2c86fd5c | ||
|
|
d905dbe214 | ||
|
|
038ca83004 | ||
|
|
d377265b67 | ||
|
|
a415f482db | ||
|
|
954b6fcaf3 | ||
|
|
abe095dd1e | ||
|
|
109ebc14fd | ||
|
|
95ddfcc437 | ||
|
|
ee57935260 | ||
|
|
6bf8f6f9f2 | ||
|
|
8869bac411 | ||
|
|
f61d9ef476 | ||
|
|
3aaec120e7 | ||
|
|
c864976da6 | ||
|
|
a7f5a91cfb | ||
|
|
75816aa3ab | ||
|
|
cac7dcdc76 | ||
|
|
9c374eac96 | ||
|
|
b2e28f133e | ||
|
|
3a93ddfab3 | ||
|
|
979e999403 | ||
|
|
c2755f770c | ||
|
|
31f7f9e2dc | ||
|
|
491e8f7e00 | ||
|
|
bb96aa5156 | ||
|
|
f49a308d2c | ||
|
|
3d0ffc48cb | ||
|
|
bc7b5165be | ||
|
|
a76b07a802 | ||
|
|
33bc507f74 | ||
|
|
3345a7fc3c | ||
|
|
b26b0d886c | ||
|
|
034577c9da | ||
|
|
424717a973 | ||
|
|
e5f93ddf55 | ||
|
|
983039a18a | ||
|
|
a7a01bd52f | ||
|
|
48d726bfd0 | ||
|
|
12a342b6c0 | ||
|
|
1206352b4a | ||
|
|
9da9bac30c | ||
|
|
cd243f40ee | ||
|
|
000417731b | ||
|
|
c77518ff93 | ||
|
|
f0a795b568 | ||
|
|
aa38e51afb | ||
|
|
c21fadf9bc | ||
|
|
0db31c2b43 | ||
|
|
3a0a423bce | ||
|
|
eb90ce50c3 | ||
|
|
c3f8593f8c | ||
|
|
4cbda049e9 | ||
|
|
69396aae01 | ||
|
|
b05879e9e2 | ||
|
|
8001038376 | ||
|
|
c7cc618376 | ||
|
|
9fecb3dfb9 | ||
|
|
617226e584 | ||
|
|
c72c82b970 | ||
|
|
6cae6ebafe | ||
|
|
a2cca6e292 | ||
|
|
01d3b130a9 | ||
|
|
af46a8ded1 | ||
|
|
f00e2be548 | ||
|
|
a4fe433db7 | ||
|
|
f3833376e7 | ||
|
|
4720fa1207 | ||
|
|
df10252979 | ||
|
|
c033d55c47 | ||
|
|
c794ea7ea7 | ||
|
|
02f707f231 | ||
|
|
d356cd5d48 | ||
|
|
b83faf8018 | ||
|
|
2a73d3c793 | ||
|
|
039bbc68ad | ||
|
|
b9460087e3 | ||
|
|
c42a00f9df | ||
|
|
76b9cae259 | ||
|
|
70a87e1181 | ||
|
|
7af757d104 | ||
|
|
9c66fdc703 | ||
|
|
fec0d15c4f | ||
|
|
853e377159 | ||
|
|
8984c81961 | ||
|
|
c6f6db95ff | ||
|
|
8b2c72300c | ||
|
|
8481f2922f | ||
|
|
68e6fe00a4 | ||
|
|
3258bed1c0 | ||
|
|
32d9abcc03 | ||
|
|
0cee640199 | ||
|
|
182e8aa139 | ||
|
|
945093ee7e | ||
|
|
086ca176be | ||
|
|
292647bd53 | ||
|
|
42ded70336 | ||
|
|
3d5573921e | ||
|
|
43752ec3f0 | ||
|
|
e6e3d9e368 | ||
|
|
0de5bb22af | ||
|
|
f670c0fc18 | ||
|
|
09994d6067 | ||
|
|
f81d084f5c | ||
|
|
940c9a8185 | ||
|
|
28d7507a5d | ||
|
|
4f34d48029 | ||
|
|
c78aa5a60f | ||
|
|
7ba4ae11c9 | ||
|
|
5376b5b5d6 | ||
|
|
3ec6c9e4fb | ||
|
|
2eb885c1d8 | ||
|
|
1c46d88728 | ||
|
|
d220d9ee5a | ||
|
|
e77f593b76 | ||
|
|
b305309e64 | ||
|
|
c96f3b303b | ||
|
|
ecb0bd39b6 | ||
|
|
4e4cae0fc3 | ||
|
|
4be15cff02 | ||
|
|
f839cf1ce3 | ||
|
|
1e6a41b5cf | ||
|
|
1ed1723a2f | ||
|
|
7a0b1656c7 | ||
|
|
28f27f733b | ||
|
|
a5100ad380 | ||
|
|
16598555f1 | ||
|
|
a732999da5 | ||
|
|
6d01e6e367 | ||
|
|
50e872fc76 | ||
|
|
318879d174 | ||
|
|
ec3ed67bc9 | ||
|
|
76626ac54b | ||
|
|
116bcf4245 | ||
|
|
f2285a6d71 | ||
|
|
e682ffb61c | ||
|
|
9ebb25427a | ||
|
|
66195ffeed | ||
|
|
662335d81a | ||
|
|
d8817c2d32 | ||
|
|
15ac08474e | ||
|
|
fdfbb18531 | ||
|
|
3ed28f2828 | ||
|
|
fcf9f0a7ee | ||
|
|
33903ea892 | ||
|
|
5bd94b8f47 | ||
|
|
aa5432e162 | ||
|
|
c4c714f10b | ||
|
|
f8abd167d8 | ||
|
|
777f98bd10 | ||
|
|
30798c7078 | ||
|
|
bc7719fc28 | ||
|
|
ff63555143 | ||
|
|
069b42a7cc | ||
|
|
ceec1afec2 | ||
|
|
5ae8e5d773 | ||
|
|
4ff920c915 | ||
|
|
217501e180 | ||
|
|
ae4b65c52e | ||
|
|
ca1fe3c602 | ||
|
|
4a13a53058 | ||
|
|
5fa13625a1 | ||
|
|
bfb322d618 | ||
|
|
43865a3e29 | ||
|
|
b691212c6e | ||
|
|
69f558db8e | ||
|
|
9befbf02f1 | ||
|
|
f81c7f10f6 | ||
|
|
b9c950bfb7 | ||
|
|
6a1fbef8fd | ||
|
|
5006435234 | ||
|
|
adb451eec6 | ||
|
|
62639081c1 | ||
|
|
570ef07170 | ||
|
|
83d7ec728f | ||
|
|
9f301e13c5 | ||
|
|
f1b1dbf5cd | ||
|
|
bdbb637b3d | ||
|
|
e9e0e05156 | ||
|
|
7d94a49ef4 | ||
|
|
cbd6d24d34 | ||
|
|
b951c1f89e | ||
|
|
b78b2a3031 | ||
|
|
7dcf8b2186 | ||
|
|
8a5b8f1fca | ||
|
|
8ad9e5755d | ||
|
|
fdb7940c4e | ||
|
|
873f615358 | ||
|
|
b2af1984ed | ||
|
|
065713aeca | ||
|
|
68c092aef2 | ||
|
|
9b8054ae11 | ||
|
|
0591c6b4bb | ||
|
|
4a22fcd93c | ||
|
|
dc06caccaa | ||
|
|
e6d4b3a89a | ||
|
|
0f131a976e | ||
|
|
7f535a20a2 | ||
|
|
bac7526c03 | ||
|
|
c2a83f87d8 | ||
|
|
333b3f6beb | ||
|
|
b7ff3b0745 | ||
|
|
a1bb79f440 | ||
|
|
171ba6327d | ||
|
|
2ab797ff75 | ||
|
|
bdb1b7124a | ||
|
|
b93bdbb124 | ||
|
|
c8d06f04d3 | ||
|
|
067a0235e4 | ||
|
|
dbb2416542 | ||
|
|
51c093e24e | ||
|
|
50a18b6bac | ||
|
|
9a8d9b5e91 | ||
|
|
ef65f3c305 | ||
|
|
02eafd5019 | ||
|
|
04cd6a82b8 | ||
|
|
a2ec2ea397 | ||
|
|
f51878a8ec | ||
|
|
f18423cf45 | ||
|
|
68b9731db2 | ||
|
|
76cf465cc2 | ||
|
|
0f018ea215 | ||
|
|
a8dc41cd9f | ||
|
|
dbcaa02d89 | ||
|
|
e6b1574046 | ||
|
|
5df26a6a9b | ||
|
|
fc3331628e | ||
|
|
0ec70119f2 | ||
|
|
bf518222d4 | ||
|
|
6565bd89d5 | ||
|
|
99485bec4c | ||
|
|
0eb5103642 | ||
|
|
edd03341b1 | ||
|
|
1d2f06b37e | ||
|
|
870e5ac1dc | ||
|
|
7e296a1adc | ||
|
|
b9a705f84b | ||
|
|
d265ed80d2 | ||
|
|
fa3cfd34cb | ||
|
|
bcd67c3455 | ||
|
|
ec71e7afe4 | ||
|
|
17bca62df1 | ||
|
|
0c11762c31 | ||
|
|
fe7d5357d8 | ||
|
|
568f170e12 | ||
|
|
c87d65856c | ||
|
|
9b996e702e | ||
|
|
2cb1376a93 | ||
|
|
1f3da24fe0 | ||
|
|
c4e31551f3 | ||
|
|
52d11ce845 | ||
|
|
7d8b6d487b | ||
|
|
583c6d3644 | ||
|
|
aabb0b77ce | ||
|
|
59d7c47e3f | ||
|
|
21bc3a9c39 | ||
|
|
cfd73cec81 | ||
|
|
3e437a6ae0 | ||
|
|
d8e7436db0 | ||
|
|
f798a0cfe8 | ||
|
|
51846d0277 | ||
|
|
c4f237572d | ||
|
|
e20e695775 | ||
|
|
132ab63a32 | ||
|
|
bfd315fc72 | ||
|
|
72c2123e07 | ||
|
|
1f7d62bfd5 | ||
|
|
4d1c900cac | ||
|
|
97c522517c | ||
|
|
4c6245b2e5 | ||
|
|
b21a58e564 | ||
|
|
4df1d37ddc | ||
|
|
03ffd1c732 | ||
|
|
3e84f18cc0 | ||
|
|
42606d6aed | ||
|
|
c366b62160 | ||
|
|
42d8b7183c | ||
|
|
f9809f0044 | ||
|
|
4378ef8e97 | ||
|
|
2c1694f63b | ||
|
|
ae277a0dec | ||
|
|
473b219a37 | ||
|
|
be1833898e | ||
|
|
a64da8f0cb | ||
|
|
689434e012 | ||
|
|
a73a4d1e0b | ||
|
|
457f325773 | ||
|
|
5f80681295 | ||
|
|
fdcfcce9e7 | ||
|
|
1ca70b855c | ||
|
|
e632941c52 | ||
|
|
176fade220 | ||
|
|
110d0752f3 | ||
|
|
e24d579a32 | ||
|
|
a7c7128cd7 | ||
|
|
4c01454376 | ||
|
|
611f1d0e24 | ||
|
|
52c6609792 | ||
|
|
7057cb1982 | ||
|
|
68c1568075 | ||
|
|
4b34a7ce2a | ||
|
|
b284e09ce5 | ||
|
|
8f55f05871 | ||
|
|
58fcb60831 | ||
|
|
557aac6a34 | ||
|
|
0aab11a95d | ||
|
|
7376ae6980 | ||
|
|
148c6e7551 | ||
|
|
b0c38a3c15 | ||
|
|
756e15f6e2 | ||
|
|
10be26f011 | ||
|
|
12a0e2bfdd | ||
|
|
481f916f3f | ||
|
|
85565d95d5 | ||
|
|
fdbf8a5184 | ||
|
|
8e911d38c4 | ||
|
|
052df7d48c | ||
|
|
5990a9528f | ||
|
|
aa6801d5df | ||
|
|
d0185925ff | ||
|
|
9b6913e1a6 | ||
|
|
e2de1f5c13 | ||
|
|
2b04ef4fae | ||
|
|
8dfd3dbdbc | ||
|
|
63e2d78e76 | ||
|
|
1388ec0d60 | ||
|
|
4ba3ed512a | ||
|
|
f870f97a94 | ||
|
|
7094997eec | ||
|
|
79907fe84c | ||
|
|
1a30b4fe29 | ||
|
|
4298f36fc9 | ||
|
|
3a0735e164 | ||
|
|
42125b4351 | ||
|
|
0f2a79b9c1 | ||
|
|
62f05ec103 | ||
|
|
1f7ad0cc37 | ||
|
|
4c566f56c1 | ||
|
|
b395836080 | ||
|
|
801881dd7d | ||
|
|
7b4bba787d | ||
|
|
e95f9c6daa | ||
|
|
50bad43dbe | ||
|
|
48997eaeba | ||
|
|
f02561530f | ||
|
|
88d9bac5ec | ||
|
|
63740a382b | ||
|
|
ed1f62ffff | ||
|
|
4972934189 | ||
|
|
d73bce058a | ||
|
|
10c018df8e | ||
|
|
29969bc130 | ||
|
|
1ea74238cd | ||
|
|
3361814cab | ||
|
|
cc84c689ea | ||
|
|
b3d5f37598 | ||
|
|
31c967206a | ||
|
|
c3d402ce47 | ||
|
|
d9bdfcf131 | ||
|
|
6074d4e378 | ||
|
|
57d341f390 | ||
|
|
bf759b62c6 | ||
|
|
5b0fea7093 | ||
|
|
21002ed405 |
23
.gitattributes
vendored
23
.gitattributes
vendored
@@ -8,3 +8,26 @@ src/bun.js/bindings/sqlite/sqlite3_local.h linguist-vendored
|
||||
*.zig text eol=lf
|
||||
src/bun.js/bindings/simdutf.cpp linguist-vendored
|
||||
src/bun.js/bindings/simdutf.h linguist-vendored
|
||||
|
||||
src/js/out/WebCoreJSBuiltins.cpp linguist-generated
|
||||
src/js/out/WebCoreJSBuiltins.h linguist-generated
|
||||
src/js/out/WebCoreJSBuiltins.d.ts linguist-generated
|
||||
|
||||
src/bun.js/bindings/ZigGeneratedClasses.h linguist-generated
|
||||
src/bun.js/bindings/ZigGeneratedClasses.cpp linguist-generated
|
||||
|
||||
src/bun.js/bindings/ZigGeneratedCode.h linguist-generated
|
||||
src/bun.js/bindings/ZigGeneratedCode.cpp linguist-generated
|
||||
|
||||
src/bun.js/bindings/headers.h linguist-generated
|
||||
src/bun.js/bindings/headers.zig linguist-generated
|
||||
|
||||
src/bun.js/bindings/JSSink.h linguist-generated
|
||||
src/bun.js/bindings/JSSink.zig linguist-generated
|
||||
|
||||
src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h linguist-generated
|
||||
src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h linguist-generated
|
||||
src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h linguist-generated
|
||||
src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h linguist-generated
|
||||
|
||||
docs/**/* linguist-documentation
|
||||
|
||||
62
.github/pull_request_template.md
vendored
Normal file
62
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
### What does this PR do?
|
||||
|
||||
<!-- **Please explain what your changes do**, example: -->
|
||||
|
||||
<!--
|
||||
|
||||
This adds a new flag --bail to bun test. When set, it will stop running tests after the first failure. This is useful for CI environments where you want to fail fast.
|
||||
|
||||
-->
|
||||
|
||||
- [ ] Documentation or TypeScript types (it's okay to leave the rest blank in this case)
|
||||
- [ ] Code changes
|
||||
|
||||
### How did you verify your code works?
|
||||
|
||||
<!-- **For code changes, please include automated tests**. Feel free to uncomment the line below -->
|
||||
|
||||
<!-- I wrote automated tests -->
|
||||
|
||||
<!-- If JavaScript/TypeScript modules or builtins changed:
|
||||
|
||||
- [ ] I ran `make js` and committed the transpiled changes
|
||||
- [ ] I or my editor ran Prettier on the changed files (or I ran `bun fmt`)
|
||||
- [ ] I included a test for the new code, or an existing test covers it
|
||||
|
||||
-->
|
||||
|
||||
<!-- If Zig files changed:
|
||||
|
||||
- [ ] I checked the lifetime of memory allocated to verify it's (1) freed and (2) only freed when it should be
|
||||
- [ ] I or my editor ran `zig fmt` on the changed files
|
||||
- [ ] I included a test for the new code, or an existing test covers it
|
||||
- [ ] JSValue used outside outside of the stack is either wrapped in a JSC.Strong or is JSValueProtect'ed
|
||||
-->
|
||||
|
||||
<!-- If new methods, getters, or setters were added to a publicly exposed class:
|
||||
|
||||
- [ ] I added TypeScript types for the new methods, getters, or setters
|
||||
-->
|
||||
|
||||
<!-- If dependencies in tests changed:
|
||||
|
||||
- [ ] I made sure that specific versions of dependencies are used instead of ranged or tagged versions
|
||||
-->
|
||||
|
||||
<!-- If functions were added to exports.zig or bindings.zig
|
||||
|
||||
- [ ] I ran `make headers` to regenerate the C header file
|
||||
|
||||
-->
|
||||
|
||||
<!-- If \*.classes.ts files were added or changed:
|
||||
|
||||
- [ ] I ran `make codegen` to regenerate the C++ and Zig code
|
||||
-->
|
||||
|
||||
<!-- If a new builtin ESM/CJS module was added:
|
||||
|
||||
- [ ] I updated Aliases in `module_loader.zig` to include the new module
|
||||
- [ ] I added a test that imports the module
|
||||
- [ ] I added a test that require() the module
|
||||
-->
|
||||
3
.github/workflows/bun-deploy-site.yml
vendored
3
.github/workflows/bun-deploy-site.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
deploy:
|
||||
name: Deploy site
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
steps:
|
||||
- name: Trigger Vercel build
|
||||
run: curl ${{ secrets.VERCEL_DEPLOY_HOOK }}
|
||||
run: curl ${{ secrets.VERCEL_DEPLOY_HOOK }}
|
||||
|
||||
1
.github/workflows/bun-ecosystem-test.yml
vendored
1
.github/workflows/bun-ecosystem-test.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
test:
|
||||
name: ${{ matrix.tag }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
8
.github/workflows/bun-linux-aarch64.yml
vendored
8
.github/workflows/bun-linux-aarch64.yml
vendored
@@ -1,4 +1,9 @@
|
||||
name: bun-linux
|
||||
|
||||
concurrency:
|
||||
group: bun-linux-aarch64-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
@@ -21,6 +26,7 @@ jobs:
|
||||
linux:
|
||||
name: ${{matrix.tag}}
|
||||
runs-on: ${{matrix.runner}}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
arch: aarch64
|
||||
build_arch: arm64
|
||||
runner: linux-arm64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-arm64-lto"
|
||||
build_machine_arch: aarch64
|
||||
|
||||
|
||||
19
.github/workflows/bun-linux-build.yml
vendored
19
.github/workflows/bun-linux-build.yml
vendored
@@ -1,4 +1,9 @@
|
||||
name: bun-linux
|
||||
|
||||
concurrency:
|
||||
group: bun-linux-build-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
@@ -30,6 +35,7 @@ jobs:
|
||||
linux:
|
||||
name: ${{matrix.tag}}
|
||||
runs-on: ${{matrix.runner}}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -40,7 +46,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
- cpu: nehalem
|
||||
@@ -48,7 +54,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
|
||||
@@ -181,12 +187,17 @@ jobs:
|
||||
unzip bun-${{matrix.tag}}.zip
|
||||
cd bun-${{matrix.tag}}
|
||||
chmod +x bun
|
||||
sudo mv bun /usr/local/bin/bun
|
||||
bun --version
|
||||
pwd >> $GITHUB_PATH
|
||||
./bun --version
|
||||
- id: test
|
||||
name: Test (node runner)
|
||||
env:
|
||||
SMTP_SENDGRID_SENDER: ${{ secrets.SMTP_SENDGRID_SENDER }}
|
||||
TLS_MONGODB_DATABASE_URL: ${{ secrets.TLS_MONGODB_DATABASE_URL }}
|
||||
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
|
||||
# if: ${{github.event.inputs.use_bun == 'false'}}
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y openssl
|
||||
bun install
|
||||
bun install --cwd test
|
||||
bun install --cwd packages/bun-internal-test
|
||||
|
||||
46
.github/workflows/bun-mac-aarch64.yml
vendored
46
.github/workflows/bun-mac-aarch64.yml
vendored
@@ -1,4 +1,9 @@
|
||||
name: bun-macOS-aarch64
|
||||
|
||||
concurrency:
|
||||
group: bun-macOS-aarch64-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
@@ -28,6 +33,7 @@ jobs:
|
||||
macos-object-files:
|
||||
name: macOS Object
|
||||
runs-on: med-ubuntu
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -100,6 +106,7 @@ jobs:
|
||||
macOS-cpp:
|
||||
name: macOS C++
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -110,7 +117,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -119,7 +126,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -128,7 +135,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -137,7 +144,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: native
|
||||
@@ -145,7 +152,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/may20/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
dependencies: true
|
||||
compile_obj: true
|
||||
@@ -166,9 +173,9 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix ccache)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
@@ -237,6 +244,7 @@ jobs:
|
||||
macOS:
|
||||
name: macOS Link
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
needs: [macOS-cpp, macos-object-files]
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
@@ -249,7 +257,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -257,14 +265,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/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/may20/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -283,8 +291,8 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
@@ -388,8 +396,8 @@ jobs:
|
||||
name: Tests ${{matrix.tag}}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [macOS]
|
||||
if: github.event_name == 'pull_request'
|
||||
timeout-minutes: 10
|
||||
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 30
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
|
||||
@@ -418,10 +426,14 @@ jobs:
|
||||
unzip ${{matrix.tag}}.zip
|
||||
cd ${{matrix.tag}}
|
||||
chmod +x bun
|
||||
sudo mv bun /usr/local/bin/bun
|
||||
bun --version
|
||||
pwd >> $GITHUB_PATH
|
||||
./bun --version
|
||||
- id: test
|
||||
name: Test (node runner)
|
||||
env:
|
||||
SMTP_SENDGRID_SENDER: ${{ secrets.SMTP_SENDGRID_SENDER }}
|
||||
TLS_MONGODB_DATABASE_URL: ${{ secrets.TLS_MONGODB_DATABASE_URL }}
|
||||
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
|
||||
# if: ${{github.event.inputs.use_bun == 'false'}}
|
||||
run: |
|
||||
bun install
|
||||
|
||||
44
.github/workflows/bun-mac-x64-baseline.yml
vendored
44
.github/workflows/bun-mac-x64-baseline.yml
vendored
@@ -1,4 +1,9 @@
|
||||
name: bun-macOS-x64-baseline
|
||||
|
||||
concurrency:
|
||||
group: bun-macOS-x64-baseline-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
@@ -28,6 +33,7 @@ jobs:
|
||||
macos-object-files:
|
||||
name: macOS Object
|
||||
runs-on: med-ubuntu
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -100,6 +106,7 @@ jobs:
|
||||
macOS-cpp:
|
||||
name: macOS C++
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -110,7 +117,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -119,7 +126,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: nehalem
|
||||
@@ -128,7 +135,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -137,7 +144,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -145,7 +152,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -166,9 +173,9 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix ccache)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: ccache (dependencies)
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
@@ -238,6 +245,7 @@ jobs:
|
||||
macOS:
|
||||
name: macOS Link
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
needs: [macOS-cpp, macos-object-files]
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
@@ -250,7 +258,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -258,14 +266,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -284,8 +292,8 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: ccache (link)
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
@@ -392,7 +400,7 @@ jobs:
|
||||
name: Tests ${{matrix.tag}}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [macOS]
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 30
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
@@ -422,10 +430,14 @@ jobs:
|
||||
unzip ${{matrix.tag}}.zip
|
||||
cd ${{matrix.tag}}
|
||||
chmod +x bun
|
||||
sudo mv bun /usr/local/bin/bun
|
||||
bun --version
|
||||
pwd >> $GITHUB_PATH
|
||||
./bun --version
|
||||
- id: test
|
||||
name: Test (node runner)
|
||||
env:
|
||||
SMTP_SENDGRID_SENDER: ${{ secrets.SMTP_SENDGRID_SENDER }}
|
||||
TLS_MONGODB_DATABASE_URL: ${{ secrets.TLS_MONGODB_DATABASE_URL }}
|
||||
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
|
||||
# if: ${{github.event.inputs.use_bun == 'false'}}
|
||||
run: |
|
||||
bun install
|
||||
|
||||
42
.github/workflows/bun-mac-x64.yml
vendored
42
.github/workflows/bun-mac-x64.yml
vendored
@@ -1,4 +1,9 @@
|
||||
name: bun-macOS-x64
|
||||
|
||||
concurrency:
|
||||
group: bun-macOS-x64-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
@@ -28,6 +33,7 @@ jobs:
|
||||
macos-object-files:
|
||||
name: macOS Object
|
||||
runs-on: med-ubuntu
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -100,6 +106,7 @@ jobs:
|
||||
macOS-cpp:
|
||||
name: macOS C++
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -110,7 +117,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: haswell
|
||||
@@ -119,7 +126,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -128,7 +135,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: haswell
|
||||
@@ -137,7 +144,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -145,7 +152,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/may20/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -166,8 +173,8 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: Download WebKit
|
||||
if: matrix.compile_obj
|
||||
@@ -240,6 +247,7 @@ jobs:
|
||||
macOS:
|
||||
name: macOS Link
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
needs: [macOS-cpp, macos-object-files]
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
@@ -252,7 +260,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/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: haswell
|
||||
arch: x86_64
|
||||
tag: bun-darwin-x64
|
||||
@@ -260,14 +268,14 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/may20/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/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/may20/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-4/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -286,8 +294,8 @@ jobs:
|
||||
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
|
||||
run: |
|
||||
brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
|
||||
echo "export PATH=$(brew --prefix coreutils)/libexec/gnubin:\$PATH" >> $GITHUB_ENV
|
||||
echo "export PATH=$(brew --prefix llvm@15)/bin:\$PATH" >> $GITHUB_ENV
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@15
|
||||
- name: Download WebKit
|
||||
env:
|
||||
@@ -394,7 +402,7 @@ jobs:
|
||||
name: Tests ${{matrix.tag}}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [macOS]
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
|
||||
timeout-minutes: 30
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
@@ -424,10 +432,14 @@ jobs:
|
||||
unzip ${{matrix.tag}}.zip
|
||||
cd ${{matrix.tag}}
|
||||
chmod +x bun
|
||||
sudo mv bun /usr/local/bin/bun
|
||||
bun --version
|
||||
pwd >> $GITHUB_PATH
|
||||
./bun --version
|
||||
- id: test
|
||||
name: Test (node runner)
|
||||
env:
|
||||
SMTP_SENDGRID_SENDER: ${{ secrets.SMTP_SENDGRID_SENDER }}
|
||||
TLS_MONGODB_DATABASE_URL: ${{ secrets.TLS_MONGODB_DATABASE_URL }}
|
||||
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
|
||||
# if: ${{github.event.inputs.use_bun == 'false'}}
|
||||
run: |
|
||||
bun install
|
||||
|
||||
4
.github/workflows/bun-release-canary.yml
vendored
4
.github/workflows/bun-release-canary.yml
vendored
@@ -8,6 +8,7 @@ jobs:
|
||||
sign:
|
||||
name: Sign Release
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -40,6 +41,7 @@ jobs:
|
||||
name: Release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -108,6 +110,7 @@ jobs:
|
||||
name: Release to Dockerhub
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
@@ -149,6 +152,7 @@ jobs:
|
||||
name: Upload to S3
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: bun-release-canary
|
||||
name: bun-release-types-canary
|
||||
concurrency: release-canary
|
||||
on:
|
||||
push:
|
||||
@@ -11,6 +11,7 @@ jobs:
|
||||
npm-types:
|
||||
name: Release types to NPM
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-types
|
||||
|
||||
10
.github/workflows/bun-release.yml
vendored
10
.github/workflows/bun-release.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
sign:
|
||||
name: Sign Release
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -53,6 +54,7 @@ jobs:
|
||||
name: Release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -85,6 +87,7 @@ jobs:
|
||||
name: Release types to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-types
|
||||
@@ -127,6 +130,7 @@ jobs:
|
||||
name: Release to Dockerhub
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
@@ -152,8 +156,8 @@ jobs:
|
||||
with:
|
||||
images: oven/bun
|
||||
tags: |
|
||||
type=match,pattern=(bun-v)?(\d.\d.\d),group=2,value=${{ env.TAG }}
|
||||
type=match,pattern=(bun-v)?(\d.\d),group=2,value=${{ env.TAG }}
|
||||
type=match,pattern=(bun-v)?(\d+.\d+.\d+),group=2,value=${{ env.TAG }}
|
||||
type=match,pattern=(bun-v)?(\d+.\d+),group=2,value=${{ env.TAG }}
|
||||
- id: login
|
||||
name: Login to Docker
|
||||
uses: docker/login-action@v2
|
||||
@@ -177,6 +181,7 @@ jobs:
|
||||
name: Release to Homebrew
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
@@ -218,6 +223,7 @@ jobs:
|
||||
name: Upload to S3
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
if: github.repository_owner == 'oven-sh'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
|
||||
59
.github/workflows/bun-test.yml
vendored
59
.github/workflows/bun-test.yml
vendored
@@ -1,59 +0,0 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "The version of Bun to run"
|
||||
required: true
|
||||
default: "canary"
|
||||
type: string
|
||||
path:
|
||||
description: "The path to the test files"
|
||||
required: true
|
||||
default: "test/"
|
||||
type: string
|
||||
timeout:
|
||||
description: "The timeout per file in milliseconds"
|
||||
required: true
|
||||
default: "15000"
|
||||
type: number
|
||||
jobs:
|
||||
test:
|
||||
name: ${{ matrix.tag }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
tag: linux-x64
|
||||
url: linux/x64?avx2=true
|
||||
- os: ubuntu-latest
|
||||
tag: linux-x64-baseline
|
||||
url: linux/x64?baseline=true
|
||||
# FIXME: runner fails with "No tests found"?
|
||||
#- os: macos-latest
|
||||
# tag: darwin-x64
|
||||
# url: darwin/x64?avx2=true
|
||||
- os: macos-latest
|
||||
tag: darwin-x64-baseline
|
||||
url: darwin/x64?baseline=true
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- id: setup
|
||||
name: Setup
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-download-url: https://bun.sh/download/${{ github.event.inputs.version }}/${{ matrix.url }}
|
||||
- id: test
|
||||
name: Test
|
||||
run: |
|
||||
bun install
|
||||
bun install --cwd test
|
||||
bun x ts-node --esm .github/scripts/test-runner.ts ${{ github.event.inputs.path }} --isolated --timeout=${{ github.event.inputs.timeout }}
|
||||
34
.github/workflows/bun-typecheck.yml
vendored
34
.github/workflows/bun-typecheck.yml
vendored
@@ -1,34 +0,0 @@
|
||||
name: typecheck
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "packages/bun-types/**"
|
||||
- "test/**"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "packages/bun-types/**"
|
||||
- "test/**"
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: check-tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: canary
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
working-directory: test
|
||||
- name: Typecheck tests
|
||||
run: bun run typecheck
|
||||
4
.github/workflows/zig-fmt.yml
vendored
4
.github/workflows/zig-fmt.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: zig-fmt
|
||||
|
||||
env:
|
||||
ZIG_VERSION: 0.11.0-dev.2571+31738de28
|
||||
ZIG_VERSION: 0.11.0-dev.4006+bf827d0b5
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
run: |
|
||||
curl https://ziglang.org/builds/zig-linux-x86_64-${{env.ZIG_VERSION}}.tar.xz -L -o zig.tar.xz
|
||||
tar -xf zig.tar.xz
|
||||
sudo mv zig-linux-x86_64-${{env.ZIG_VERSION}}/zig /usr/local/bin
|
||||
echo "$(pwd)/zig-linux-x86_64-${{env.ZIG_VERSION}}" >> $GITHUB_PATH
|
||||
- name: Run zig fmt
|
||||
id: fmt
|
||||
run: |
|
||||
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -96,6 +96,8 @@ packages/bun-wasm/*.cjs
|
||||
packages/bun-wasm/*.map
|
||||
packages/bun-wasm/*.js
|
||||
packages/bun-wasm/*.d.ts
|
||||
packages/bun-wasm/*.d.cts
|
||||
packages/bun-wasm/*.d.mts
|
||||
*.bc
|
||||
|
||||
src/fallback.version
|
||||
@@ -119,3 +121,12 @@ myscript.sh
|
||||
|
||||
cold-jsc-start
|
||||
cold-jsc-start.d
|
||||
|
||||
/test.ts
|
||||
|
||||
src/js/out/modules*
|
||||
src/js/out/functions*
|
||||
src/js/out/tmp
|
||||
src/js/out/DebugPath.h
|
||||
|
||||
make-dev-stats.csv
|
||||
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -68,4 +68,10 @@ fetchRecurseSubmodules = false
|
||||
[submodule "src/deps/zstd"]
|
||||
path = src/deps/zstd
|
||||
url = https://github.com/facebook/zstd.git
|
||||
ignore = dirty
|
||||
ignore = dirty
|
||||
[submodule "src/deps/base64"]
|
||||
path = src/deps/base64
|
||||
url = https://github.com/aklomp/base64.git
|
||||
ignore = dirty
|
||||
depth = 1
|
||||
shallow = true
|
||||
@@ -1,6 +1,6 @@
|
||||
src/fallback.html
|
||||
src/bun.js/WebKit
|
||||
src/bun.js/builtins/js/*.js
|
||||
src/js/out
|
||||
src/*.out.js
|
||||
src/*out.*.js
|
||||
src/deps
|
||||
@@ -11,4 +11,3 @@ test/snapshots-no-hmr
|
||||
test/js/deno/*.test.ts
|
||||
test/js/deno/**/*.test.ts
|
||||
bench/react-hello-world/react-hello-world.node.js
|
||||
src/bun.js/builtins/WebCoreJSBuiltins.d.ts
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
quoteProps: "preserve",
|
||||
overrides: [
|
||||
{
|
||||
files: "README.md",
|
||||
files: ["*.md"],
|
||||
options: {
|
||||
printWidth: 80,
|
||||
},
|
||||
|
||||
21
.scripts/make-dev-timer.ts
Normal file
21
.scripts/make-dev-timer.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// I would have made this a bash script but there isn't an easy way to track
|
||||
// time in bash sub-second cross platform.
|
||||
import fs from "fs";
|
||||
const start = Date.now() + 5;
|
||||
const result = Bun.spawnSync(process.argv.slice(2), {
|
||||
stdio: ["inherit", "inherit", "inherit"],
|
||||
});
|
||||
const end = Date.now();
|
||||
const diff = (Math.max(Math.round(end - start), 0) / 1000).toFixed(3);
|
||||
const success = result.exitCode === 0;
|
||||
try {
|
||||
const line = `${new Date().toISOString()}, ${success ? "success" : "fail"}, ${diff}\n`;
|
||||
if (fs.existsSync(".scripts/make-dev-stats.csv")) {
|
||||
fs.appendFileSync(".scripts/make-dev-stats.csv", line);
|
||||
} else {
|
||||
fs.writeFileSync(".scripts/make-dev-stats.csv", line);
|
||||
}
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
process.exit(result.exitCode);
|
||||
15
.vscode/c_cpp_properties.json
vendored
15
.vscode/c_cpp_properties.json
vendored
@@ -15,10 +15,12 @@
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcore/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
|
||||
"${workspaceFolder}/src/bun.js/builtins/",
|
||||
"${workspaceFolder}/src/bun.js/builtins/cpp",
|
||||
"${workspaceFolder}/src/bun.js/modules/",
|
||||
"${workspaceFolder}/src/js/builtins/",
|
||||
"${workspaceFolder}/src/js/out",
|
||||
"${workspaceFolder}/src/deps/boringssl/include/",
|
||||
"${workspaceFolder}/src/deps",
|
||||
"${workspaceFolder}/src/napi/*",
|
||||
"${workspaceFolder}/src/deps/uws/uSockets/src"
|
||||
],
|
||||
"browse": {
|
||||
@@ -31,15 +33,18 @@
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/bmalloc/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/bindings/*",
|
||||
"${workspaceFolder}/src/bun.js/bindings/*",
|
||||
"${workspaceFolder}/src/napi/*",
|
||||
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcore/",
|
||||
"${workspaceFolder}/src/bun.js/builtins/*",
|
||||
"${workspaceFolder}/src/bun.js/builtins/cpp/*",
|
||||
"${workspaceFolder}/src/js/builtins/*",
|
||||
"${workspaceFolder}/src/js/out/*",
|
||||
"${workspaceFolder}/src/bun.js/modules/*",
|
||||
"${workspaceFolder}/src/deps",
|
||||
"${workspaceFolder}/src/deps/boringssl/include/",
|
||||
"${workspaceFolder}/src/deps/uws/uSockets/src"
|
||||
"${workspaceFolder}/src/deps/uws/uSockets/src",
|
||||
"${workspaceFolder}/src/napi"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ".vscode/cppdb"
|
||||
|
||||
167
.vscode/launch.json
generated
vendored
167
.vscode/launch.json
generated
vendored
@@ -1,130 +1,202 @@
|
||||
{
|
||||
// The usage of BUN_GARBAGE_COLLECTOR_LEVEL=2 is important for debugging
|
||||
// It will force the garbage collector to run after every test and every call to expect()
|
||||
// it makes our tests very slow
|
||||
// But it helps catch memory bugs
|
||||
|
||||
// SIGHUP must be ignored or the debugger will pause when a spawned subprocess exits:
|
||||
// { "initCommands": ["process handle -p false -s false -n false SIGHUP"] }
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test",
|
||||
"name": "bun test [file]",
|
||||
"program": "bun-debug",
|
||||
"args": ["test", "${file}"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
"BUN_GARBAGE_COLLECTOR_LEVEL": "2"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test --watch",
|
||||
"name": "bun test [file] (fast)",
|
||||
"program": "bun-debug",
|
||||
"args": ["--watch", "test", "${file}"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": ["test", "${file}"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test [file] (verbose)",
|
||||
"program": "bun-debug",
|
||||
"args": ["test", "${file}"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test (all)",
|
||||
"name": "bun test [file] --watch",
|
||||
"program": "bun-debug",
|
||||
"args": ["test", "--watch", "${file}"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test [file] --only",
|
||||
"program": "bun-debug",
|
||||
"args": ["test", "--only", "${file}"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test [*]",
|
||||
"program": "bun-debug",
|
||||
"args": ["test"],
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_GARBAGE_COLLECTOR_LEVEL": "2",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
"BUN_GARBAGE_COLLECTOR_LEVEL": "2"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun test [*] (fast)",
|
||||
"program": "bun-debug",
|
||||
"args": ["test"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun run current file",
|
||||
"name": "bun test [*] --only",
|
||||
"program": "bun-debug",
|
||||
"args": ["${file}"],
|
||||
"cwd": "${file}/../../",
|
||||
"args": ["test", "--only"],
|
||||
// The cwd here must be the same as in CI. Or you will cause test failures that only happen in CI.
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun run (watch)",
|
||||
"name": "bun run [file]",
|
||||
"program": "bun-debug",
|
||||
"args": ["--watch", "${file}"],
|
||||
"cwd": "${file}/../../",
|
||||
"args": ["run", "${file}", "${file}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
"FORCE_COLOR": "1",
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun run (hot)",
|
||||
"name": "bun run [file] (gc)",
|
||||
"program": "bun-debug",
|
||||
"args": ["--hot", "${file}"],
|
||||
"cwd": "${file}/../../",
|
||||
"args": ["run", "${file}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
"FORCE_COLOR": "1",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
"BUN_GARBAGE_COLLECTOR_LEVEL": "2"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun run",
|
||||
"name": "bun run [file] (verbose)",
|
||||
"program": "bun-debug",
|
||||
"args": ["check.tsx", "-c"],
|
||||
"cwd": "${env:HOME}/Build/react-ssr",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun http example",
|
||||
"program": "bun-debug",
|
||||
"args": ["run", "examples/http.ts"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": ["run", "${file}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun http file example",
|
||||
"name": "bun run [file] --watch",
|
||||
"program": "bun-debug",
|
||||
"args": ["run", "examples/bun/http-file.ts"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": ["run", "--watch", "${file}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun html-rewriter example",
|
||||
"name": "bun run [file] --hot",
|
||||
"program": "bun-debug",
|
||||
"args": ["run", "examples/bun/html-rewriter.ts"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": ["run", "--hot", "${file}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"],
|
||||
"console": "internalConsole"
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
@@ -139,12 +211,14 @@
|
||||
"request": "launch",
|
||||
"name": "bun build debug",
|
||||
"program": "bun-debug",
|
||||
"args": ["bun", "./test/fixtures/bundle/trivial/index.js"],
|
||||
"args": ["bun", "${file}"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"BUN_CONFIG_MINIFY_WHITESPACE": "1"
|
||||
}
|
||||
},
|
||||
// SIGHUP must be ignored or the debugger will pause when a spawned subprocess exits.
|
||||
"initCommands": ["process handle -p false -s false -n false SIGHUP"]
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
@@ -168,7 +242,6 @@
|
||||
"console": "internalConsole",
|
||||
"env": {}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
@@ -251,7 +324,7 @@
|
||||
"name": "bun install",
|
||||
"program": "bun-debug",
|
||||
"args": ["install"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"cwd": "${fileDirname}",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
|
||||
21
.vscode/settings.json
vendored
21
.vscode/settings.json
vendored
@@ -7,6 +7,8 @@
|
||||
"search.followSymlinks": false,
|
||||
"search.useIgnoreFiles": true,
|
||||
"zig.buildOnSave": false,
|
||||
// We do this until we upgrade to latest Zig so that zls doesn't break our code.
|
||||
"zig.formattingProvider": "extension",
|
||||
"zig.buildArgs": ["obj", "-Dfor-editor"],
|
||||
"zig.buildOption": "build",
|
||||
"zig.buildFilePath": "${workspaceFolder}/build.zig",
|
||||
@@ -37,8 +39,6 @@
|
||||
"[yaml]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"zig.beforeDebugCmd": "make build-unit ${file} ${filter} ${bin}",
|
||||
"zig.testCmd": "make test ${file} ${filter} ${bin}",
|
||||
"[markdown]": {
|
||||
"editor.unicodeHighlight.ambiguousCharacters": false,
|
||||
"editor.unicodeHighlight.invisibleCharacters": false,
|
||||
@@ -78,7 +78,8 @@
|
||||
"src/deps/c-ares": true,
|
||||
"src/deps/tinycc": true,
|
||||
"src/deps/zstd": true,
|
||||
"test/snippets/package-json-exports/_node_modules_copy": true
|
||||
"test/snippets/package-json-exports/_node_modules_copy": true,
|
||||
"src/js/out": true
|
||||
},
|
||||
"C_Cpp.files.exclude": {
|
||||
"**/.vscode": true,
|
||||
@@ -108,11 +109,6 @@
|
||||
"editor.defaultFormatter": "xaver.clang-format"
|
||||
},
|
||||
"files.associations": {
|
||||
"*.{setting,comp,fuse,fu}": "lua",
|
||||
"*.ctk": "json",
|
||||
"*.json5": "json5",
|
||||
"*.json": "jsonc",
|
||||
"*.scriptlib": "lua",
|
||||
"*.lock": "yarnlock",
|
||||
"*.idl": "cpp",
|
||||
"memory": "cpp",
|
||||
@@ -221,14 +217,7 @@
|
||||
"regex": "cpp",
|
||||
"span": "cpp",
|
||||
"valarray": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"source_location": "cpp",
|
||||
"numbers": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"stdfloat": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"cfenv": "cpp"
|
||||
"codecvt": "cpp"
|
||||
},
|
||||
"cmake.configureOnOpen": false,
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
|
||||
@@ -47,32 +47,18 @@ TODO: document this (see [`bindings.zig`](src/bun.js/bindings/bindings.zig) and
|
||||
|
||||
Copy from examples like `Subprocess` or `Response`.
|
||||
|
||||
### ESM modules
|
||||
### ESM Modules and Builtins JS
|
||||
|
||||
Bun implements ESM modules in a mix of native code and JavaScript.
|
||||
|
||||
Several Node.js modules are implemented in JavaScript and loosely based on browserify polyfills.
|
||||
|
||||
The ESM modules in Bun are located in [`src/bun.js/*.exports.js`](src/bun.js/). Unlike other code in Bun, these files are NOT transpiled. They are loaded directly into the JavaScriptCore VM. That means `require` does not work in these files. Instead, you must use `import.meta.require`, or ideally, not use require/import other files at all.
|
||||
Builtin modules in Bun are located in [`src/js`](src/js/). These files are transpiled and support a JavaScriptCore-only syntax for internal slots, which is explained further in [`src/js/README.md`](src/js/README.md).
|
||||
|
||||
Native C++ modules are in `src/bun.js/modules/`.
|
||||
|
||||
The module loader is in [`src/bun.js/module_loader.zig`](src/bun.js/module_loader.zig).
|
||||
|
||||
### JavaScript Builtins
|
||||
|
||||
JavaScript builtins are located in [`src/bun.js/builtins/*.js`](src/bun.js/builtins).
|
||||
|
||||
These files support a JavaScriptCore-only syntax for internal slots. `@` is used to access an internal slot. For example: `new @Array(123)` will create a new `Array` similar to `new Array(123)`, except if a library modifies the `Array` global, it will not affect the internal slot (`@Array`). These names must be allow-listed in `BunBuiltinNames.h` (though JavaScriptCore allowlists some names by default).
|
||||
|
||||
They can not use or reference ESM-modules. The files that end with `*Internals.js` are automatically loaded globally. Most usage of internals right now are the stream implementations (which share a lot of code from Safari/WebKit) and ImportMetaObject (which is how `require` is implemented in the runtime)
|
||||
|
||||
To regenerate the builtins:
|
||||
|
||||
```sh
|
||||
make clean-bindings && make generate-builtins && make bindings -j10
|
||||
```
|
||||
|
||||
It is recommended that you have ccache installed or else you will spend a lot of time waiting for the bindings to compile.
|
||||
|
||||
### Memory management in Bun's JavaScript runtime
|
||||
|
||||
TODO: fill this out (for now, use `JSC.Strong` in most cases)
|
||||
|
||||
28
Dockerfile
28
Dockerfile
@@ -10,9 +10,9 @@ ARG ARCH=x86_64
|
||||
ARG BUILD_MACHINE_ARCH=x86_64
|
||||
ARG TRIPLET=${ARCH}-linux-gnu
|
||||
ARG BUILDARCH=amd64
|
||||
ARG WEBKIT_TAG=may20
|
||||
ARG WEBKIT_TAG=2023-aug3-4
|
||||
ARG ZIG_TAG=jul1
|
||||
ARG ZIG_VERSION="0.11.0-dev.2571+31738de28"
|
||||
ARG ZIG_VERSION="0.11.0-dev.4006+bf827d0b5"
|
||||
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
|
||||
|
||||
ARG ZIG_FOLDERNAME=zig-linux-${BUILD_MACHINE_ARCH}-${ZIG_VERSION}
|
||||
@@ -20,7 +20,7 @@ ARG ZIG_FILENAME=${ZIG_FOLDERNAME}.tar.xz
|
||||
ARG WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/$WEBKIT_TAG/${WEBKIT_BASENAME}.tar.gz"
|
||||
ARG ZIG_URL="https://ziglang.org/builds/${ZIG_FILENAME}"
|
||||
ARG GIT_SHA=""
|
||||
ARG BUN_BASE_VERSION=0.6
|
||||
ARG BUN_BASE_VERSION=0.7
|
||||
|
||||
FROM bitnami/minideb:bullseye as bun-base
|
||||
|
||||
@@ -295,6 +295,27 @@ WORKDIR $BUN_DIR
|
||||
RUN cd $BUN_DIR && \
|
||||
make uws && rm -rf src/deps/uws Makefile
|
||||
|
||||
FROM bun-base as base64
|
||||
|
||||
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}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/base64 ${BUN_DIR}/src/deps/base64
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
|
||||
RUN cd $BUN_DIR && \
|
||||
make base64 && rm -rf src/deps/base64 Makefile
|
||||
|
||||
FROM bun-base as picohttp
|
||||
|
||||
ARG DEBIAN_FRONTEND
|
||||
@@ -556,6 +577,7 @@ 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=base64 ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
|
||||
|
||||
256
Makefile
256
Makefile
@@ -6,8 +6,6 @@ BUN_AUTO_UPDATER_REPO = Jarred-Sumner/bun-releases-for-updater
|
||||
|
||||
CMAKE_CXX_COMPILER_LAUNCHER_FLAG :=
|
||||
|
||||
|
||||
|
||||
# 'make' command will trigger the help target
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
@@ -20,6 +18,7 @@ CPU_TARGET ?= native
|
||||
MARCH_NATIVE = -mtune=$(CPU_TARGET)
|
||||
NATIVE_OR_OLD_MARCH =
|
||||
|
||||
MMD_IF_LOCAL =
|
||||
DEFAULT_MIN_MACOS_VERSION=
|
||||
ARCH_NAME :=
|
||||
DOCKER_BUILDARCH =
|
||||
@@ -39,12 +38,20 @@ NATIVE_OR_OLD_MARCH = -march=nehalem
|
||||
endif
|
||||
|
||||
MIN_MACOS_VERSION ?= $(DEFAULT_MIN_MACOS_VERSION)
|
||||
BUN_BASE_VERSION = 0.6
|
||||
BUN_BASE_VERSION = 0.7
|
||||
|
||||
CI ?= false
|
||||
|
||||
AR=
|
||||
|
||||
ifeq ($(CI), false)
|
||||
MMD_IF_LOCAL = -MMD
|
||||
endif
|
||||
|
||||
BUN_OR_NODE = $(shell which bun 2>/dev/null || which node 2>/dev/null)
|
||||
|
||||
|
||||
|
||||
CXX_VERSION=c++2a
|
||||
TRIPLET = $(OS_NAME)-$(ARCH_NAME)
|
||||
PACKAGE_NAME = bun-$(TRIPLET)
|
||||
@@ -286,14 +293,14 @@ 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)
|
||||
SRC_BUILTINS_FILES := $(wildcard src/js/out/*.cpp)
|
||||
SRC_WEBCRYPTO_FILES := $(wildcard $(SRC_DIR)/webcrypto/*.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))
|
||||
BUILTINS_OBJ_FILES := $(patsubst src/js/out/%.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))
|
||||
WEBCRYPTO_OBJ_FILES := $(patsubst $(SRC_DIR)/webcrypto/%.cpp,$(OBJ_DIR)/%.o,$(SRC_WEBCRYPTO_FILES))
|
||||
@@ -302,7 +309,7 @@ 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_BUILTINS_OBJ_FILES := $(patsubst src/js/out/%.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))
|
||||
DEBUG_WEBCRYPTO_OBJ_FILES := $(patsubst $(SRC_DIR)/webcrypto/%.cpp, $(DEBUG_OBJ_DIR)/%.o, $(SRC_WEBCRYPTO_FILES))
|
||||
@@ -323,12 +330,12 @@ ALL_JSC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/WTF/Headers \
|
||||
-I$(WEBKIT_RELEASE_DIR)/WTF/PrivateHeaders
|
||||
|
||||
SHARED_INCLUDE_DIR = -I$(realpath src/bun.js/bindings)/ \
|
||||
-I$(realpath src/bun.js/builtins/) \
|
||||
-I$(realpath src/js/builtins/) \
|
||||
-I$(realpath src/js/out/) \
|
||||
-I$(realpath src/bun.js/bindings) \
|
||||
-I$(realpath src/bun.js/bindings/webcore) \
|
||||
-I$(realpath src/bun.js/bindings/webcrypto) \
|
||||
-I$(realpath src/bun.js/bindings/sqlite) \
|
||||
-I$(realpath src/bun.js/builtins/cpp) \
|
||||
-I$(realpath src/bun.js/bindings/node_os) \
|
||||
-I$(realpath src/bun.js/modules) \
|
||||
-I$(JSC_INCLUDE_DIR)
|
||||
@@ -345,7 +352,7 @@ LINUX_INCLUDE_DIRS := $(ALL_JSC_INCLUDE_DIRS) \
|
||||
UWS_INCLUDE_DIR := -I$(BUN_DEPS_DIR)/uws/uSockets/src -I$(BUN_DEPS_DIR)/uws/src -I$(BUN_DEPS_DIR)
|
||||
|
||||
|
||||
INCLUDE_DIRS := $(UWS_INCLUDE_DIR) -I$(BUN_DEPS_DIR)/mimalloc/include -I$(BUN_DEPS_DIR)/zstd/include -Isrc/napi -I$(BUN_DEPS_DIR)/boringssl/include -I$(BUN_DEPS_DIR)/c-ares/include
|
||||
INCLUDE_DIRS := $(UWS_INCLUDE_DIR) -I$(BUN_DEPS_DIR)/mimalloc/include -I$(BUN_DEPS_DIR)/zstd/include -Isrc/napi -I$(BUN_DEPS_DIR)/boringssl/include -I$(BUN_DEPS_DIR)/c-ares/include -Isrc/bun.js/modules
|
||||
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
@@ -394,6 +401,7 @@ CLANG_FLAGS = $(INCLUDE_DIRS) \
|
||||
-DSTATICALLY_LINKED_WITH_BMALLOC=1 \
|
||||
-DBUILDING_WITH_CMAKE=1 \
|
||||
-DBUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1 \
|
||||
-DNAPI_EXPERIMENTAL=ON \
|
||||
-DNDEBUG=1 \
|
||||
-DNOMINMAX \
|
||||
-DIS_BUILD \
|
||||
@@ -446,7 +454,8 @@ MINIMUM_ARCHIVE_FILES = -L$(BUN_DEPS_OUT_DIR) \
|
||||
-ldecrepit \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-llolhtml
|
||||
-llolhtml \
|
||||
-lbase64
|
||||
|
||||
ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MINIMUM_ARCHIVE_FILES) \
|
||||
-larchive \
|
||||
@@ -546,14 +555,12 @@ tinycc:
|
||||
|
||||
PYTHON=$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null)
|
||||
|
||||
.PHONY: builtins
|
||||
builtins:
|
||||
bun src/bun.js/builtins/codegen/index.ts --minify
|
||||
|
||||
.PHONY: generate-builtins
|
||||
generate-builtins: builtins
|
||||
|
||||
.PHONY: esm
|
||||
js: # to rebundle js (rebuilding binary not needed to reload js code)
|
||||
NODE_ENV=production bun src/js/_codegen/index.ts
|
||||
|
||||
esm-debug:
|
||||
BUN_DEBUG_QUIET_LOGS=1 NODE_ENV=production bun-debug src/js/build-esm.ts
|
||||
|
||||
BUN_TYPES_REPO_PATH ?= $(realpath packages/bun-types)
|
||||
|
||||
@@ -654,8 +661,8 @@ else
|
||||
PKGNAME_NINJA := ninja-build
|
||||
endif
|
||||
|
||||
.PHONY: require
|
||||
require:
|
||||
.PHONY: assert-deps
|
||||
assert-deps:
|
||||
@echo "Checking if the required utilities are available..."
|
||||
@if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@15"; exit 1; fi
|
||||
@cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1)
|
||||
@@ -666,10 +673,25 @@ require:
|
||||
@which aclocal > /dev/null || (echo -e "ERROR: automake is required. Install with:\n\n $(POSIX_PKG_MANAGER) install automake"; exit 1)
|
||||
@which $(LIBTOOL) > /dev/null || (echo -e "ERROR: libtool is required. Install with:\n\n $(POSIX_PKG_MANAGER) install libtool"; exit 1)
|
||||
@which ninja > /dev/null || (echo -e "ERROR: Ninja is required. Install with:\n\n $(POSIX_PKG_MANAGER) install $(PKGNAME_NINJA)"; exit 1)
|
||||
@which pkg-config > /dev/null || (echo -e "ERROR: pkg-config is required. Install with:\n\n $(POSIX_PKG_MANAGER) install pkg-config"; exit 1)
|
||||
@which rustc > /dev/null || (echo -e "ERROR: rustc is required." exit 1)
|
||||
@which cargo > /dev/null || (echo -e "ERROR: cargo is required." exit 1)
|
||||
@test $(shell cargo --version | awk '{print $$2}' | cut -d. -f2) -gt 57 || (echo -e "ERROR: cargo version must be at least 1.57."; exit 1)
|
||||
@echo "You have the dependencies installed! Woo"
|
||||
|
||||
init-submodules:
|
||||
git submodule update --init --recursive --progress --depth=1 --checkout
|
||||
# the following allows you to run `make submodule` to update or init submodules. but we will exclude webkit
|
||||
# unless you explicity clone it yourself (a huge download)
|
||||
SUBMODULE_NAMES=$(shell cat .gitmodules | grep 'path = ' | awk '{print $$3}')
|
||||
ifeq ("$(wildcard src/bun.js/WebKit/.git)", "")
|
||||
SUBMODULE_NAMES := $(filter-out src/bun.js/WebKit, $(SUBMODULE_NAMES))
|
||||
endif
|
||||
|
||||
.PHONY: init-submodules
|
||||
init-submodules: submodule # (backwards-compatibility alias)
|
||||
|
||||
.PHONY: submodule
|
||||
submodule: ## to init or update all submodules
|
||||
git submodule update --init --recursive --progress --depth=1 --checkout $(SUBMODULE_NAMES)
|
||||
|
||||
.PHONY: build-obj
|
||||
build-obj:
|
||||
@@ -685,44 +707,46 @@ dev-build-obj-wasm:
|
||||
|
||||
.PHONY: dev-wasm
|
||||
dev-wasm: dev-build-obj-wasm
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
|
||||
-g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
|
||||
packages/debug-bun-freestanding-wasm32/bun-wasm.o $(OPTIMIZATION_LEVEL) --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
|
||||
-g2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \
|
||||
packages/debug-bun-freestanding-wasm32/bun-wasm.o --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
|
||||
-o packages/debug-bun-freestanding-wasm32/bun-wasm.wasm
|
||||
cp packages/debug-bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
|
||||
cp packages/debug-bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
|
||||
|
||||
.PHONY: build-obj-wasm
|
||||
build-obj-wasm:
|
||||
$(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
|
||||
-g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
|
||||
-s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \
|
||||
packages/bun-freestanding-wasm32/bun-wasm.o $(OPTIMIZATION_LEVEL) --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
|
||||
-o packages/bun-freestanding-wasm32/bun-wasm.wasm
|
||||
cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
|
||||
cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
|
||||
|
||||
.PHONY: build-obj-wasm-small
|
||||
build-obj-wasm-small:
|
||||
$(ZIG) build bun-wasm -Doptimize=ReleaseSmall -Dtarget=wasm32-freestanding
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
|
||||
-g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
|
||||
$(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding
|
||||
emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
|
||||
-Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
|
||||
$(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \
|
||||
packages/bun-freestanding-wasm32/bun-wasm.o -Oz --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
|
||||
-o packages/bun-freestanding-wasm32/bun-wasm.wasm
|
||||
cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
|
||||
cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
|
||||
|
||||
.PHONY: wasm
|
||||
wasm: api build-obj-wasm-small
|
||||
@rm -rf packages/bun-wasm/*.{d.ts,js,wasm,cjs,mjs,tsbuildinfo}
|
||||
wasm: api mimalloc-wasm build-obj-wasm-small
|
||||
@rm -rf packages/bun-wasm/*.{d.ts,d.cts,d.mts,js,wasm,cjs,mjs,tsbuildinfo}
|
||||
@cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
|
||||
@cp src/api/schema.d.ts packages/bun-wasm/schema.d.ts
|
||||
@cp src/api/schema.js packages/bun-wasm/schema.js
|
||||
@cd packages/bun-wasm && $(NPM_CLIENT) run tsc -- -p .
|
||||
@$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=esm --minify 2> /dev/null
|
||||
@cp packages/bun-wasm/index.d.ts packages/bun-wasm/index.d.cts
|
||||
@mv packages/bun-wasm/index.d.ts packages/bun-wasm/index.d.mts
|
||||
@bun build --sourcemap=external --external=fs --outdir=packages/bun-wasm --target=browser --minify ./packages/bun-wasm/index.ts
|
||||
@mv packages/bun-wasm/index.js packages/bun-wasm/index.mjs
|
||||
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.mjs.map
|
||||
@$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
|
||||
@$(ESBUILD) --sourcemap=external --external:fs --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
|
||||
@mv packages/bun-wasm/index.js packages/bun-wasm/index.cjs
|
||||
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.cjs.map
|
||||
@rm -rf packages/bun-wasm/*.tsbuildinfo
|
||||
@@ -920,6 +944,7 @@ headers:
|
||||
$(ZIG) translate-c src/bun.js/bindings/headers.h > src/bun.js/bindings/headers.zig
|
||||
$(BUN_OR_NODE) misctools/headers-cleaner.js
|
||||
$(ZIG) fmt src/bun.js/bindings/headers.zig
|
||||
$(CLANG_FORMAT) -i src/bun.js/bindings/ZigGeneratedCode.cpp
|
||||
|
||||
.PHONY: jsc-bindings-headers
|
||||
jsc-bindings-headers: headers
|
||||
@@ -1064,17 +1089,30 @@ test/wiptest/run: test/wiptest/run.o
|
||||
release-bin-dir:
|
||||
echo $(PACKAGE_DIR)
|
||||
|
||||
|
||||
.PHONY: dev-obj-track
|
||||
dev-obj-track:
|
||||
bun .scripts/make-dev-timer.ts $(ZIG) build obj -freference-trace -Dcpu="$(CPU_TARGET)"
|
||||
|
||||
.PHONY: dev-obj-notrack
|
||||
dev-obj-notrack:
|
||||
$(ZIG) build obj -freference-trace -Dcpu="$(CPU_TARGET)"
|
||||
|
||||
|
||||
.PHONY: dev-obj
|
||||
dev-obj:
|
||||
$(ZIG) build obj -freference-trace -Dcpu="$(CPU_TARGET)"
|
||||
|
||||
ifeq ($(shell which bun),)
|
||||
dev-obj : dev-obj-notrack
|
||||
else
|
||||
dev-obj : dev-obj-track
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: dev-obj-linux
|
||||
dev-obj-linux:
|
||||
$(ZIG) build obj -Dtarget=x86_64-linux-gnu -Dcpu="$(CPU_TARGET)"
|
||||
|
||||
.PHONY: dev
|
||||
dev: mkdir-dev dev-obj bun-link-lld-debug
|
||||
|
||||
mkdir-dev:
|
||||
mkdir -p $(DEBUG_PACKAGE_DIR)
|
||||
|
||||
@@ -1158,10 +1196,12 @@ jsc-build-mac-compile:
|
||||
-DPORT="JSCOnly" \
|
||||
-DENABLE_STATIC_JSC=ON \
|
||||
-DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON \
|
||||
-DCMAKE_BUILD_TYPE=relwithdebuginfo \
|
||||
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DBUN_FAST_TLS=ON \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-G Ninja \
|
||||
$(CMAKE_FLAGS_WITHOUT_RELEASE) \
|
||||
-DPTHREAD_JIT_PERMISSIONS_API=1 \
|
||||
@@ -1180,9 +1220,11 @@ jsc-build-mac-compile-lto:
|
||||
-DPORT="JSCOnly" \
|
||||
-DENABLE_STATIC_JSC=ON \
|
||||
-DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON \
|
||||
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DBUN_FAST_TLS=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DCMAKE_C_FLAGS="-flto=full" \
|
||||
-DCMAKE_CXX_FLAGS="-flto=full" \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
@@ -1207,6 +1249,8 @@ jsc-build-mac-compile-debug:
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
|
||||
-G Ninja \
|
||||
$(CMAKE_FLAGS_WITHOUT_RELEASE) \
|
||||
-DPTHREAD_JIT_PERMISSIONS_API=1 \
|
||||
@@ -1225,11 +1269,13 @@ jsc-build-linux-compile-config:
|
||||
cmake \
|
||||
-DPORT="JSCOnly" \
|
||||
-DENABLE_STATIC_JSC=ON \
|
||||
-DCMAKE_BUILD_TYPE=relwithdebuginfo \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DENABLE_REMOTE_INSPECTOR=ON \
|
||||
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
|
||||
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
|
||||
-USE_VISIBILITY_ATTRIBUTE=1 \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-G Ninja \
|
||||
@@ -1244,7 +1290,7 @@ jsc-build-linux-compile-config:
|
||||
jsc-build-linux-compile-build:
|
||||
mkdir -p $(WEBKIT_RELEASE_DIR) && \
|
||||
cd $(WEBKIT_RELEASE_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects" \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects" -DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
cmake --build $(WEBKIT_RELEASE_DIR) --config relwithdebuginfo --target jsc
|
||||
|
||||
|
||||
@@ -1341,18 +1387,24 @@ mimalloc:
|
||||
|
||||
|
||||
mimalloc-wasm:
|
||||
cd $(BUN_DEPS_DIR)/mimalloc; emcmake cmake -DMI_BUILD_SHARED=OFF -DMI_BUILD_STATIC=ON -DMI_BUILD_TESTS=OFF -DMI_BUILD_OBJECT=ON ${MIMALLOC_OVERRIDE_FLAG} -DMI_USE_CXX=ON .; emmake make;
|
||||
rm -rf $(BUN_DEPS_DIR)/mimalloc/CMakeCache* $(BUN_DEPS_DIR)/mimalloc/CMakeFiles
|
||||
cd $(BUN_DEPS_DIR)/mimalloc; emcmake cmake -DMI_BUILD_SHARED=OFF -DMI_BUILD_STATIC=ON -DMI_BUILD_TESTS=OFF -GNinja -DMI_BUILD_OBJECT=ON ${MIMALLOC_OVERRIDE_FLAG} -DMI_USE_CXX=OFF .; emmake cmake --build .;
|
||||
cp $(BUN_DEPS_DIR)/mimalloc/$(MIMALLOC_INPUT_PATH) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE).wasm
|
||||
|
||||
bun-link-lld-debug:
|
||||
# alias for link, incase anyone still types that
|
||||
.PHONY: bun-link-lld-debug
|
||||
bun-link-lld-debug: link
|
||||
|
||||
.PHONY: link
|
||||
link: ## link a debug build of bun
|
||||
$(CXX) $(BUN_LLD_FLAGS_DEBUG) $(DEBUG_FLAGS) $(SYMBOLS) \
|
||||
-g \
|
||||
$(DEBUG_BIN)/bun-debug.o \
|
||||
-W \
|
||||
-o $(DEBUG_BIN)/bun-debug
|
||||
@rm -f $(DEBUG_BIN)/bun-debug.o.o 2> /dev/null # workaround for https://github.com/ziglang/zig/issues/14080
|
||||
@rm -f $(DEBUG_BIN)/bun-debug.o.o 2> /dev/null # workaround for https://github.com/ziglang/zig/issues/14080
|
||||
|
||||
bun-link-lld-debug-no-jsc:
|
||||
link-no-jsc:
|
||||
$(CXX) $(BUN_LLD_FLAGS_WITHOUT_JSC) $(SYMBOLS) \
|
||||
-g \
|
||||
$(DEBUG_BIN)/bun-debug.o \
|
||||
@@ -1439,7 +1491,7 @@ generate-classes:
|
||||
generate-sink:
|
||||
bun src/bun.js/scripts/generate-jssink.js
|
||||
$(CLANG_FORMAT) -i src/bun.js/bindings/JSSink.cpp src/bun.js/bindings/JSSink.h
|
||||
$(WEBKIT_DIR)/Source/JavaScriptCore/create_hash_table src/bun.js/bindings/JSSink.cpp > src/bun.js/bindings/JSSinkLookupTable.h
|
||||
./src/bun.js/scripts/create_hash_table src/bun.js/bindings/JSSink.cpp > src/bun.js/bindings/JSSinkLookupTable.h
|
||||
$(SED) -i -e 's/#include "Lookup.h"//' src/bun.js/bindings/JSSinkLookupTable.h
|
||||
$(SED) -i -e 's/namespace JSC {//' src/bun.js/bindings/JSSinkLookupTable.h
|
||||
$(SED) -i -e 's/} \/\/ namespace JSC//' src/bun.js/bindings/JSSinkLookupTable.h
|
||||
@@ -1462,7 +1514,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) $(UWS_INCLUDE) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1473,7 +1525,7 @@ $(OBJ_DIR)/%.o: src/bun.js/modules/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) $(UWS_INCLUDE) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1484,7 +1536,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/webcore/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1495,7 +1547,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/sqlite/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1506,7 +1558,7 @@ $(OBJ_DIR)/%.o: src/io/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1517,18 +1569,18 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/node_os/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
$(EMIT_LLVM) \
|
||||
-c -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: src/bun.js/builtins/%.cpp
|
||||
$(OBJ_DIR)/%.o: src/js/out/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1540,7 +1592,7 @@ $(OBJ_DIR)/%.o: src/bun.js/bindings/webcrypto/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1554,7 +1606,7 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) $(UWS_INCLUDE) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1569,7 +1621,7 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/webcore/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1582,7 +1634,7 @@ $(DEBUG_OBJ_DIR)/%.o: src/io/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1598,7 +1650,7 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/sqlite/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1613,7 +1665,7 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/node_os/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1623,12 +1675,12 @@ $(DEBUG_OBJ_DIR)/%.o: $(SRC_DIR)/node_os/%.cpp
|
||||
|
||||
# $(DEBUG_OBJ_DIR) is not included here because it breaks
|
||||
# detecting if a file needs to be rebuilt
|
||||
.PHONY: src/bun.js/builtins/%.cpp
|
||||
$(DEBUG_OBJ_DIR)/%.o: src/bun.js/builtins/%.cpp
|
||||
.PHONY: src/js/out/builtins/%.cpp
|
||||
$(DEBUG_OBJ_DIR)/%.o: src/js/out/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1641,7 +1693,7 @@ $(DEBUG_OBJ_DIR)/%.o: src/bun.js/modules/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1655,7 +1707,7 @@ $(DEBUG_OBJ_DIR)/%.o: src/bun.js/bindings/webcrypto/%.cpp
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(DEBUG_OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-I$(SRC_DIR) \
|
||||
-fno-rtti \
|
||||
@@ -1673,7 +1725,7 @@ sizegen:
|
||||
# Linux uses bundled SQLite3
|
||||
ifeq ($(OS_NAME),linux)
|
||||
sqlite:
|
||||
$(CC) $(EMIT_LLVM_FOR_RELEASE) $(CFLAGS) $(INCLUDE_DIRS) -DSQLITE_ENABLE_COLUMN_METADATA= -DSQLITE_MAX_VARIABLE_NUMBER=250000 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_JSON1=1 $(SRC_DIR)/sqlite/sqlite3.c -c -o $(SQLITE_OBJECT)
|
||||
$(CC) $(EMIT_LLVM_FOR_RELEASE) $(CFLAGS) $(INCLUDE_DIRS) -DSQLITE_ENABLE_COLUMN_METADATA= -DSQLITE_MAX_VARIABLE_NUMBER=250000 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 $(SRC_DIR)/sqlite/sqlite3.c -c -o $(SQLITE_OBJECT)
|
||||
endif
|
||||
|
||||
picohttp:
|
||||
@@ -1769,7 +1821,7 @@ endif
|
||||
endif
|
||||
|
||||
.PHONY: build-unit
|
||||
build-unit: ## to build your unit tests
|
||||
build-unit: # to build your unit tests
|
||||
@rm -rf zig-out/bin/$(testname)
|
||||
@mkdir -p zig-out/bin
|
||||
zig test $(realpath $(testpath)) \
|
||||
@@ -1787,7 +1839,7 @@ build-unit: ## to build your unit tests
|
||||
cp zig-out/bin/$(testname) $(testbinpath)
|
||||
|
||||
.PHONY: run-all-unit-tests
|
||||
run-all-unit-tests: ## to run your unit tests
|
||||
run-all-unit-tests: # to run your unit tests
|
||||
@rm -rf zig-out/bin/__main_test
|
||||
@mkdir -p zig-out/bin
|
||||
zig test src/main.zig \
|
||||
@@ -1807,15 +1859,11 @@ run-all-unit-tests: ## to run your unit tests
|
||||
run-unit:
|
||||
@zig-out/bin/$(testname) $(ZIG)
|
||||
|
||||
.PHONY: help
|
||||
help: ## to print this help
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {gsub("\\\\n",sprintf("\n%22c",""), $$2);printf "\033[36m%-20s\033[0m \t\t%s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
.PHONY: test
|
||||
test: build-unit run-unit
|
||||
|
||||
.PHONY: integration-test-dev
|
||||
integration-test-dev: ## to run integration tests
|
||||
integration-test-dev: # to run integration tests
|
||||
USE_EXISTING_PROCESS=true TEST_SERVER_URL=http://localhost:3000 node test/scripts/browser.js
|
||||
|
||||
copy-install:
|
||||
@@ -1829,13 +1877,17 @@ copy-to-bun-release-dir-bin:
|
||||
|
||||
PACKAGE_MAP = --pkg-begin async_io $(BUN_DIR)/src/io/io_darwin.zig --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end --pkg-end --pkg-begin javascript_core $(BUN_DIR)/src/jsc.zig --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end --pkg-end --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end
|
||||
|
||||
.PHONY: base64
|
||||
base64:
|
||||
cd $(BUN_DEPS_DIR)/base64 && make clean && cmake $(CMAKE_FLAGS) . && make
|
||||
cp $(BUN_DEPS_DIR)/base64/libbase64.a $(BUN_DEPS_OUT_DIR)/libbase64.a
|
||||
|
||||
.PHONY: cold-jsc-start
|
||||
cold-jsc-start:
|
||||
$(CXX_WITH_CCACHE) $(CLANG_FLAGS) \
|
||||
$(MACOS_MIN_FLAG) \
|
||||
$(OPTIMIZATION_LEVEL) \
|
||||
-MMD \
|
||||
${MMD_IF_LOCAL} \
|
||||
-fno-exceptions \
|
||||
-fno-rtti \
|
||||
-ferror-limit=1000 \
|
||||
@@ -1847,30 +1899,54 @@ cold-jsc-start:
|
||||
misctools/cold-jsc-start.cpp -o cold-jsc-start
|
||||
|
||||
.PHONY: vendor-without-npm
|
||||
vendor-without-npm: node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml sqlite usockets uws tinycc c-ares zstd
|
||||
vendor-without-npm: node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml sqlite usockets uws tinycc c-ares zstd base64
|
||||
|
||||
|
||||
.PHONY: vendor-without-check
|
||||
vendor-without-check: npm-install vendor-without-npm
|
||||
|
||||
.PHONY: vendor
|
||||
vendor: require init-submodules vendor-without-check
|
||||
vendor: assert-deps submodule vendor-without-check
|
||||
|
||||
.PHONY: vendor-dev
|
||||
vendor-dev: require init-submodules npm-install-dev vendor-without-npm
|
||||
vendor-dev: assert-deps submodule npm-install-dev vendor-without-npm
|
||||
|
||||
.PHONY: bun
|
||||
bun: vendor identifier-cache build-obj bun-link-lld-release bun-codesign-release-local
|
||||
|
||||
.PHONY: regenerate-bindings
|
||||
regenerate-bindings:
|
||||
@make clean-bindings builtins
|
||||
.PHONY: cpp
|
||||
cpp: ## compile src/js/builtins + all c++ code then link
|
||||
@make clean-bindings js
|
||||
@make bindings -j$(CPU_COUNT)
|
||||
@make link
|
||||
|
||||
.PHONY: cpp
|
||||
cpp-no-link:
|
||||
@make clean-bindings js
|
||||
@make bindings -j$(CPU_COUNT)
|
||||
|
||||
.PHONY: zig
|
||||
zig: ## compile zig code then link
|
||||
@make mkdir-dev dev-obj link
|
||||
|
||||
.PHONY: zig-no-link
|
||||
zig-no-link:
|
||||
@make mkdir-dev dev-obj
|
||||
|
||||
.PHONY: dev
|
||||
dev: # combo of `make cpp` and `make zig`
|
||||
@make cpp-no-link zig-no-link -j2
|
||||
@make link
|
||||
|
||||
.PHONY: setup
|
||||
setup: vendor-dev builtins identifier-cache clean-bindings
|
||||
make jsc-check
|
||||
make bindings -j$(CPU_COUNT)
|
||||
setup: vendor-dev identifier-cache clean-bindings
|
||||
make jsc-check dev
|
||||
@echo ""
|
||||
@echo "Development environment setup complete"
|
||||
@echo "Run \`make dev\` to build \`bun-debug\`"
|
||||
@echo "First build complete!"
|
||||
@echo "\"bun-debug\" is available at $(DEBUG_BIN)/bun-debug"
|
||||
@echo ""
|
||||
|
||||
.PHONY: help
|
||||
help: ## to print this help
|
||||
@echo "For detailed build instructions, see https://bun.sh/docs/project/development"
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {gsub("\\\\n",sprintf("\n%22c",""), $$2);printf "\033[36m%-20s\033[0m \t\t%s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
## What is Bun?
|
||||
|
||||
> **Bun is still under development.** Use it to speed up your development workflows or run simpler production code in resource-constrained environments like serverless functions. We're working on more complete Node.js compatibility and integration with existing frameworks. Join the [Discord](https://bun.sh/discord) and watch the [GitHub repository](https://github.com/oven-sh/bun) to keeps tabs on future releases.
|
||||
> **Bun is still under development.** Use it to speed up your development workflows or run simpler production code in resource-constrained environments like serverless functions. We're working on more complete Node.js compatibility and integration with existing frameworks. Join the [Discord](https://bun.sh/discord) and watch the [GitHub repository](https://github.com/oven-sh/bun) to keep tabs on future releases.
|
||||
|
||||
Bun is an all-in-one toolkit for JavaScript and TypeScript apps. It ships as a single executable called `bun`.
|
||||
|
||||
|
||||
30
bench/async/AsyncLocalStorage.mjs
Normal file
30
bench/async/AsyncLocalStorage.mjs
Normal file
@@ -0,0 +1,30 @@
|
||||
// https://github.com/nodejs/node/issues/34493
|
||||
import { AsyncLocalStorage } from "async_hooks";
|
||||
const asyncLocalStorage = new AsyncLocalStorage();
|
||||
|
||||
// let fn = () => Promise.resolve(2).then(() => new Promise(resolve => queueMicrotask(resolve)));
|
||||
let fn = () => /test/.test("test");
|
||||
|
||||
let runWithExpiry = async (expiry, fn) => {
|
||||
let iterations = 0;
|
||||
while (Date.now() < expiry) {
|
||||
await fn();
|
||||
iterations++;
|
||||
}
|
||||
return iterations;
|
||||
};
|
||||
|
||||
console.log(`Performed ${await runWithExpiry(Date.now() + 1000, fn)} iterations to warmup`);
|
||||
|
||||
let withAls;
|
||||
await asyncLocalStorage.run(123, async () => {
|
||||
withAls = await runWithExpiry(Date.now() + 45000, fn);
|
||||
console.log(`Performed ${withAls} iterations (with ALS enabled)`);
|
||||
});
|
||||
|
||||
asyncLocalStorage.disable();
|
||||
|
||||
let withoutAls = await runWithExpiry(Date.now() + 45000, fn);
|
||||
console.log(`Performed ${withoutAls} iterations (with ALS disabled)`);
|
||||
|
||||
console.log("ALS penalty: " + Math.round((1 - withAls / withoutAls) * 10000) / 100 + "%");
|
||||
BIN
bench/bun.lockb
BIN
bench/bun.lockb
Binary file not shown.
@@ -3,6 +3,6 @@
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"bun-types": "^0.5.0"
|
||||
"bun-types": "^0.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
bench/emitter/implementations.mjs
Normal file
31
bench/emitter/implementations.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
import EventEmitter3 from "eventemitter3";
|
||||
import { group } from "mitata";
|
||||
import EventEmitterNative from "node:events";
|
||||
|
||||
export const implementations = [
|
||||
{
|
||||
EventEmitter: EventEmitterNative,
|
||||
name: process.isBun ? (EventEmitterNative.init ? "bun" : "C++") : "node:events",
|
||||
monkey: true,
|
||||
},
|
||||
// { EventEmitter: EventEmitter3, name: "EventEmitter3" },
|
||||
].filter(Boolean);
|
||||
|
||||
for (const impl of implementations) {
|
||||
impl.EventEmitter?.setMaxListeners?.(Infinity);
|
||||
}
|
||||
|
||||
export function groupForEmitter(name, cb) {
|
||||
if (implementations.length === 1) {
|
||||
return cb({
|
||||
...implementations[0],
|
||||
name: `${name}: ${implementations[0].name}`,
|
||||
});
|
||||
} else {
|
||||
return group(name, () => {
|
||||
for (let impl of implementations) {
|
||||
cb(impl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
96
bench/emitter/microbench.mjs
Normal file
96
bench/emitter/microbench.mjs
Normal file
@@ -0,0 +1,96 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { groupForEmitter } from "./implementations.mjs";
|
||||
|
||||
var id = 0;
|
||||
|
||||
groupForEmitter("single emit", ({ EventEmitter, name }) => {
|
||||
const emitter = new EventEmitter();
|
||||
|
||||
emitter.on("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
bench(name, () => {
|
||||
emitter.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
groupForEmitter("on x 10_000 (handler)", ({ EventEmitter, name }) => {
|
||||
const emitter = new EventEmitter();
|
||||
|
||||
bench(name, () => {
|
||||
var cb = event => {
|
||||
event.preventDefault();
|
||||
};
|
||||
emitter.on("hey", cb);
|
||||
var called = false;
|
||||
for (let i = 0; i < 10_000; i++)
|
||||
emitter.emit("hey", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
called = true;
|
||||
},
|
||||
});
|
||||
|
||||
if (!called) throw new Error("not called");
|
||||
});
|
||||
});
|
||||
|
||||
// for (let { impl: EventEmitter, name, monkey } of []) {
|
||||
// if (monkey) {
|
||||
// var monkeyEmitter = Object.assign({}, EventEmitter.prototype);
|
||||
// monkeyEmitter.on("hello", event => {
|
||||
// event.preventDefault();
|
||||
// });
|
||||
|
||||
// bench(`[monkey] ${className}.emit`, () => {
|
||||
// var called = false;
|
||||
// monkeyEmitter.emit("hello", {
|
||||
// preventDefault() {
|
||||
// id++;
|
||||
// called = true;
|
||||
// },
|
||||
// });
|
||||
|
||||
// if (!called) {
|
||||
// throw new Error("monkey failed");
|
||||
// }
|
||||
// });
|
||||
|
||||
// bench(`[monkey] ${className}.on x 10_000 (handler)`, () => {
|
||||
// var cb = () => {
|
||||
// event.preventDefault();
|
||||
// };
|
||||
// monkeyEmitter.on("hey", cb);
|
||||
// for (let i = 0; i < 10_000; i++)
|
||||
// monkey.emit("hey", {
|
||||
// preventDefault() {
|
||||
// id++;
|
||||
// },
|
||||
// });
|
||||
// monkeyEmitter.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();
|
||||
40
bench/emitter/microbench_once.mjs
Normal file
40
bench/emitter/microbench_once.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { groupForEmitter } from "./implementations.mjs";
|
||||
|
||||
var id = 0;
|
||||
|
||||
groupForEmitter("test 1", ({ EventEmitter, name }) => {
|
||||
const emitter = new EventEmitter();
|
||||
|
||||
emitter.on("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
bench(name, () => {
|
||||
emitter.once("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
emitter.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
groupForEmitter("test 2", ({ EventEmitter, name }) => {
|
||||
const emitter = new EventEmitter();
|
||||
|
||||
bench(name, () => {
|
||||
emitter.once("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
emitter.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await run();
|
||||
63
bench/emitter/realworld_stream.mjs
Normal file
63
bench/emitter/realworld_stream.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { groupForEmitter } from "./implementations.mjs";
|
||||
|
||||
// Psuedo RNG is derived from https://stackoverflow.com/a/424445
|
||||
let rngState = 123456789;
|
||||
function nextInt() {
|
||||
const m = 0x80000000; // 2**31;
|
||||
const a = 1103515245;
|
||||
const c = 12345;
|
||||
rngState = (a * rngState + c) % m;
|
||||
return rngState;
|
||||
}
|
||||
function nextRange(start, end) {
|
||||
// returns in range [start, end): including start, excluding end
|
||||
// can't modulu nextInt because of weak randomness in lower bits
|
||||
const rangeSize = end - start;
|
||||
const randomUnder1 = nextInt() / 0x7fffffff; // 2**31 - 1
|
||||
return start + Math.floor(randomUnder1 * rangeSize);
|
||||
}
|
||||
|
||||
const chunks = new Array(1024).fill(null).map((_, j) => {
|
||||
const arr = new Uint8Array(1024);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] = nextRange(0, 256);
|
||||
}
|
||||
return arr;
|
||||
});
|
||||
|
||||
groupForEmitter("stream simulation", ({ EventEmitter, name }) => {
|
||||
bench(name, () => {
|
||||
let id = 0;
|
||||
const stream = new EventEmitter();
|
||||
|
||||
stream.on("start", res => {
|
||||
if (res.status !== 200) throw new Error("not 200");
|
||||
});
|
||||
|
||||
const recived = [];
|
||||
stream.on("data", req => {
|
||||
recived.push(req);
|
||||
});
|
||||
|
||||
stream.on("end", ev => {
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
// simulate a stream
|
||||
stream.emit("start", { status: 200 });
|
||||
for (let chunk of chunks) {
|
||||
stream.emit("data", chunk);
|
||||
}
|
||||
stream.emit("end", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
|
||||
if (id !== 1) throw new Error("not implemented right");
|
||||
if (recived.length !== 1024) throw new Error("not implemented right");
|
||||
});
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -43,7 +43,7 @@ pub fn main() anyerror!void {
|
||||
var position = try std.fmt.parseInt(u32, position_str, 10);
|
||||
const filepath = try std.fs.path.resolve(allocator, &.{basepath});
|
||||
var file = try std.fs.openFileAbsolute(filepath, .{ .write = true });
|
||||
var ms = @truncate(u64, (try std.fmt.parseInt(u128, args[args.len - 1], 10)) * std.time.ns_per_ms);
|
||||
var ms = @as(u64, @truncate((try std.fmt.parseInt(u128, args[args.len - 1], 10)) * std.time.ns_per_ms));
|
||||
std.debug.assert(ms > 0);
|
||||
// std.debug.assert(std.math.isFinite(position));
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
@@ -125,30 +125,30 @@ pub fn main() anyerror!void {
|
||||
);
|
||||
};
|
||||
|
||||
counters[counter].timestamp = @truncate(u64, @intCast(u128, std.time.nanoTimestamp()) / (std.time.ns_per_ms / 10));
|
||||
counters[counter].timestamp = @as(u64, @truncate(@as(u128, @intCast(std.time.nanoTimestamp())) / (std.time.ns_per_ms / 10)));
|
||||
counters[counter].rotate = rotate % 360;
|
||||
counters[counter].percent = std.math.mod(f64, std.math.round(((progress_bar + 1.0) / destination_count) * 1000) / 1000, 100) catch 0;
|
||||
counters[counter].color_values[0] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[1] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[2] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[0] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[1] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[2] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[3] = (colors[0][0] + 1) % 256;
|
||||
counters[counter].color_values[4] = (colors[0][1] + 1) % 256;
|
||||
counters[counter].color_values[5] = (colors[0][2] + 1) % 256;
|
||||
counters[counter].color_values[6] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[7] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[8] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[6] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[7] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[8] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[9] = (colors[1][0] + 1) % 256;
|
||||
counters[counter].color_values[10] = (colors[1][1] + 1) % 256;
|
||||
counters[counter].color_values[11] = (colors[1][2] + 1) % 256;
|
||||
counters[counter].color_values[12] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[13] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[14] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[12] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[13] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[14] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[15] = (colors[2][0] + 1) % 256;
|
||||
counters[counter].color_values[16] = (colors[2][1] + 1) % 256;
|
||||
counters[counter].color_values[17] = (colors[2][2] + 1) % 256;
|
||||
counters[counter].color_values[18] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[19] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[20] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[18] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[19] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[20] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[21] = (colors[3][0] + 1) % 256;
|
||||
counters[counter].color_values[22] = (colors[3][1] + 1) % 256;
|
||||
counters[counter].color_values[23] = (colors[3][2] + 1) % 256;
|
||||
@@ -203,7 +203,7 @@ pub fn main() anyerror!void {
|
||||
_ = try recorder.wait();
|
||||
|
||||
all_timestamps[0] = wrote.len;
|
||||
for (counters) |count, i| {
|
||||
for (counters, 0..) |count, i| {
|
||||
all_timestamps[i + 1] = count.timestamp;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn main() anyerror!void {
|
||||
var position = try std.fmt.parseInt(u32, position_str, 10);
|
||||
const filepath = try std.fs.path.resolve(allocator, &.{basepath});
|
||||
var file = try std.fs.openFileAbsolute(filepath, .{ .write = true });
|
||||
var ms = @truncate(u64, (try std.fmt.parseInt(u128, args[args.len - 1], 10)) * std.time.ns_per_ms);
|
||||
var ms = @as(u64, @truncate((try std.fmt.parseInt(u128, args[args.len - 1], 10)) * std.time.ns_per_ms));
|
||||
std.debug.assert(ms > 0);
|
||||
// std.debug.assert(std.math.isFinite(position));
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
@@ -112,30 +112,30 @@ pub fn main() anyerror!void {
|
||||
\\
|
||||
++ SIMULATE_LONG_FILE;
|
||||
|
||||
counters[counter].timestamp = @truncate(u64, @intCast(u128, std.time.nanoTimestamp()) / (std.time.ns_per_ms / 10));
|
||||
counters[counter].timestamp = @as(u64, @truncate(@as(u128, @intCast(std.time.nanoTimestamp())) / (std.time.ns_per_ms / 10)));
|
||||
counters[counter].rotate = rotate % 360;
|
||||
counters[counter].percent = std.math.mod(f64, std.math.round(((progress_bar + 1.0) / destination_count) * 1000) / 1000, 100) catch 0;
|
||||
counters[counter].color_values[0] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[1] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[2] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[0][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[0] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[1] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[2] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[0][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[3] = (colors[0][0] + 1) % 256;
|
||||
counters[counter].color_values[4] = (colors[0][1] + 1) % 256;
|
||||
counters[counter].color_values[5] = (colors[0][2] + 1) % 256;
|
||||
counters[counter].color_values[6] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[7] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[8] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[1][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[6] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[7] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[8] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[1][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[9] = (colors[1][0] + 1) % 256;
|
||||
counters[counter].color_values[10] = (colors[1][1] + 1) % 256;
|
||||
counters[counter].color_values[11] = (colors[1][2] + 1) % 256;
|
||||
counters[counter].color_values[12] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[13] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[14] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[2][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[12] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[13] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[14] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[2][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[15] = (colors[2][0] + 1) % 256;
|
||||
counters[counter].color_values[16] = (colors[2][1] + 1) % 256;
|
||||
counters[counter].color_values[17] = (colors[2][2] + 1) % 256;
|
||||
counters[counter].color_values[18] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][0] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[19] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][1] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[20] = @floatToInt(u32, std.math.round(@intToFloat(f64, ((colors[3][2] + 1) % 256)) * 0.8));
|
||||
counters[counter].color_values[18] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][0] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[19] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][1] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[20] = @as(u32, @intFromFloat(std.math.round(@as(f64, @floatFromInt(((colors[3][2] + 1) % 256))) * 0.8)));
|
||||
counters[counter].color_values[21] = (colors[3][0] + 1) % 256;
|
||||
counters[counter].color_values[22] = (colors[3][1] + 1) % 256;
|
||||
counters[counter].color_values[23] = (colors[3][2] + 1) % 256;
|
||||
@@ -190,7 +190,7 @@ pub fn main() anyerror!void {
|
||||
_ = try recorder.wait();
|
||||
|
||||
all_timestamps[0] = wrote.len;
|
||||
for (counters) |count, i| {
|
||||
for (counters, 0..) |count, i| {
|
||||
all_timestamps[i + 1] = count.timestamp;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
"jsx": "react-jsx",
|
||||
"paths": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1986
bench/package-lock.json
generated
1986
bench/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"mitata": "^0.1.6",
|
||||
"esbuild": "^0.14.12",
|
||||
"@swc/core": "^1.2.133",
|
||||
"@babel/core": "^7.16.10",
|
||||
"@babel/preset-react": "^7.16.7"
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@swc/core": "^1.2.133",
|
||||
"benchmark": "^2.1.4",
|
||||
"esbuild": "^0.14.12",
|
||||
"eventemitter3": "^5.0.0",
|
||||
"mitata": "^0.1.6"
|
||||
},
|
||||
"scripts": {
|
||||
"ffi": "cd ffi && bun run deps && bun run build && bun run bench",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
bench("noop", function () {});
|
||||
bench("async function(){}", async function () {});
|
||||
|
||||
29
bench/snippets/buffer-to-string.mjs
Normal file
29
bench/snippets/buffer-to-string.mjs
Normal file
@@ -0,0 +1,29 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
import { Buffer } from "node:buffer";
|
||||
import crypto from "node:crypto";
|
||||
|
||||
const bigBuffer = Buffer.from("hello world".repeat(10000));
|
||||
const converted = bigBuffer.toString("base64");
|
||||
const uuid = crypto.randomBytes(16);
|
||||
|
||||
bench(`Buffer(${bigBuffer.byteLength}).toString('base64')`, () => {
|
||||
return bigBuffer.toString("base64");
|
||||
});
|
||||
|
||||
bench(`Buffer(${uuid.byteLength}).toString('base64')`, () => {
|
||||
return uuid.toString("base64");
|
||||
});
|
||||
|
||||
bench(`Buffer(${bigBuffer.byteLength}).toString('hex')`, () => {
|
||||
return bigBuffer.toString("hex");
|
||||
});
|
||||
|
||||
bench(`Buffer(${uuid.byteLength}).toString('hex')`, () => {
|
||||
return uuid.toString("hex");
|
||||
});
|
||||
|
||||
bench(`Buffer(${bigBuffer.byteLength}).toString('ascii')`, () => {
|
||||
return bigBuffer.toString("ascii");
|
||||
});
|
||||
|
||||
await run();
|
||||
Binary file not shown.
29
bench/snippets/crypto-2190.mjs
Normal file
29
bench/snippets/crypto-2190.mjs
Normal file
@@ -0,0 +1,29 @@
|
||||
// https://github.com/oven-sh/bun/issues/2190
|
||||
import { bench, run } from "mitata";
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
const data =
|
||||
"Delightful remarkably mr on announcing themselves entreaties favourable. About to in so terms voice at. Equal an would is found seems of. The particular friendship one sufficient terminated frequently themselves. It more shed went up is roof if loud case. Delay music in lived noise an. Beyond genius really enough passed is up.";
|
||||
|
||||
const scenarios = [
|
||||
{ alg: "md5", digest: "hex" },
|
||||
{ alg: "md5", digest: "base64" },
|
||||
{ alg: "sha1", digest: "hex" },
|
||||
{ alg: "sha1", digest: "base64" },
|
||||
{ alg: "sha256", digest: "hex" },
|
||||
{ alg: "sha256", digest: "base64" },
|
||||
];
|
||||
|
||||
for (const { alg, digest } of scenarios) {
|
||||
bench(`${alg}-${digest}`, () => {
|
||||
createHash(alg).update(data).digest(digest);
|
||||
});
|
||||
|
||||
if ("Bun" in globalThis) {
|
||||
bench(`${alg}-${digest} (Bun.CryptoHasher)`, () => {
|
||||
new Bun.CryptoHasher(alg).update(data).digest(digest);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -3,13 +3,13 @@ import { bench, run } from "./runner.mjs";
|
||||
|
||||
import crypto from "node:crypto";
|
||||
|
||||
var foo = Buffer.allocUnsafe(16384);
|
||||
var foo = Buffer.allocUnsafe(512);
|
||||
foo.fill(123);
|
||||
|
||||
// if ("Bun" in globalThis) {
|
||||
// const { CryptoHasher } = Bun;
|
||||
// bench("CryptoHasher Blake2b256", () => {
|
||||
// var hasher = new CryptoHasher("blake2b256");
|
||||
// bench("Bun.CryptoHasher(sha512)", () => {
|
||||
// var hasher = new CryptoHasher("sha512");
|
||||
// hasher.update(foo);
|
||||
// hasher.digest();
|
||||
// });
|
||||
|
||||
26
bench/snippets/crypto-stream.mjs
Normal file
26
bench/snippets/crypto-stream.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
// https://github.com/oven-sh/bun/issues/2190
|
||||
import { bench, run } from "mitata";
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
const data =
|
||||
"Delightful remarkably mr on announcing themselves entreaties favourable. About to in so terms voice at. Equal an would is found seems of. The particular friendship one sufficient terminated frequently themselves. It more shed went up is roof if loud case. Delay music in lived noise an. Beyond genius really enough passed is up.";
|
||||
|
||||
const scenarios = [
|
||||
{ alg: "md5", digest: "hex" },
|
||||
{ alg: "md5", digest: "base64" },
|
||||
{ alg: "sha1", digest: "hex" },
|
||||
{ alg: "sha1", digest: "base64" },
|
||||
{ alg: "sha256", digest: "hex" },
|
||||
{ alg: "sha256", digest: "base64" },
|
||||
];
|
||||
|
||||
for (const { alg, digest } of scenarios) {
|
||||
bench(`${alg}-${digest}`, () => {
|
||||
const hasher = createHash(alg);
|
||||
hasher.write(data);
|
||||
hasher.end();
|
||||
hasher.read();
|
||||
});
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -1,12 +1,6 @@
|
||||
// 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");
|
||||
}
|
||||
|
||||
import crypto from "node:crypto";
|
||||
var foo = new Uint8Array(65536);
|
||||
bench("crypto.getRandomValues(65536)", () => {
|
||||
crypto.getRandomValues(foo);
|
||||
@@ -22,4 +16,8 @@ bench("crypto.randomUUID()", () => {
|
||||
return crypto.randomUUID()[2];
|
||||
});
|
||||
|
||||
bench("crypto.randomInt()", () => {
|
||||
return crypto.randomInt(0, 100);
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
// **so this file can run in node**
|
||||
import { createRequire } from "node:module";
|
||||
const require = createRequire(import.meta.url);
|
||||
// --
|
||||
|
||||
const EventEmitterNative = require("node:events").EventEmitter;
|
||||
const TypedEmitter = require("tiny-typed-emitter").TypedEmitter;
|
||||
const EventEmitter3 = require("eventemitter3").EventEmitter;
|
||||
import { bench, run } from "../../node_modules/mitata/src/cli.mjs";
|
||||
const event = new Event("hello");
|
||||
var id = 0;
|
||||
for (let [EventEmitter, className] of [
|
||||
[EventEmitterNative, "EventEmitter"],
|
||||
[TypedEmitter, "TypedEmitter"],
|
||||
[EventEmitter3, "EventEmitter3"],
|
||||
]) {
|
||||
const emitter = new EventEmitter();
|
||||
|
||||
emitter.on("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
bench(`${className}.emit`, () => {
|
||||
emitter.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
bench(`${className}.on x 10_000 (handler)`, () => {
|
||||
var cb = event => {
|
||||
event.preventDefault();
|
||||
};
|
||||
emitter.on("hey", cb);
|
||||
var called = false;
|
||||
for (let i = 0; i < 10_000; i++)
|
||||
emitter.emit("hey", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
called = true;
|
||||
},
|
||||
});
|
||||
emitter.off("hey", cb);
|
||||
|
||||
if (!called) throw new Error("not called");
|
||||
});
|
||||
|
||||
if (EventEmitter !== EventEmitter3) {
|
||||
var monkey = Object.assign({}, EventEmitter.prototype);
|
||||
monkey.on("hello", event => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
bench(`[monkey] ${className}.emit`, () => {
|
||||
var called = false;
|
||||
monkey.emit("hello", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
called = true;
|
||||
},
|
||||
});
|
||||
|
||||
if (!called) {
|
||||
throw new Error("monkey failed");
|
||||
}
|
||||
});
|
||||
|
||||
bench(`[monkey] ${className}.on x 10_000 (handler)`, () => {
|
||||
var cb = () => {
|
||||
event.preventDefault();
|
||||
};
|
||||
monkey.on("hey", cb);
|
||||
for (let i = 0; i < 10_000; i++)
|
||||
monkey.emit("hey", {
|
||||
preventDefault() {
|
||||
id++;
|
||||
},
|
||||
});
|
||||
monkey.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/error-capturestack.mjs
Normal file
12
bench/snippets/error-capturestack.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
var err = new Error();
|
||||
bench("Error.captureStackTrace(err)", () => {
|
||||
Error.captureStackTrace(err);
|
||||
});
|
||||
|
||||
bench("Error.prototype.stack", () => {
|
||||
new Error().stack;
|
||||
});
|
||||
|
||||
await run();
|
||||
65
bench/snippets/module-exports-putter.cjs
Normal file
65
bench/snippets/module-exports-putter.cjs
Normal file
@@ -0,0 +1,65 @@
|
||||
// This is a stress test of some internals in How Bun does the module.exports assignment.
|
||||
// If it crashes or throws then this fails
|
||||
import("./runner.mjs").then(({ bench, run }) => {
|
||||
bench("Object.defineProperty(module, 'exports', { get() { return 42; } })", () => {
|
||||
Object.defineProperty(module, "exports", {
|
||||
get() {
|
||||
return 42;
|
||||
},
|
||||
set() {
|
||||
throw new Error("bad");
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
if (module.exports !== 42) throw new Error("bad");
|
||||
if (!Object.getOwnPropertyDescriptor(module, "exports").get) throw new Error("bad");
|
||||
});
|
||||
|
||||
bench("Object.defineProperty(module.exports = {})", () => {
|
||||
Object.defineProperty(module, "exports", {
|
||||
value: { abc: 123 },
|
||||
});
|
||||
|
||||
if (!module.exports.abc) throw new Error("bad");
|
||||
if (Object.getOwnPropertyDescriptor(module, "exports").value !== module.exports) throw new Error("bad");
|
||||
});
|
||||
|
||||
bench("module.exports = {}", () => {
|
||||
module.exports = { abc: 123 };
|
||||
|
||||
if (!module.exports.abc) throw new Error("bad");
|
||||
if (Object.getOwnPropertyDescriptor(module, "exports").value !== module.exports) throw new Error("bad");
|
||||
});
|
||||
|
||||
run().then(() => {
|
||||
module.exports = {
|
||||
a: 1,
|
||||
};
|
||||
|
||||
console.log(
|
||||
module?.exports,
|
||||
require.cache[module.id].exports,
|
||||
module?.exports === require.cache[module.id],
|
||||
__dirname,
|
||||
Object.keys(require(module.id)),
|
||||
require(module.id),
|
||||
);
|
||||
|
||||
module.exports = function lol() {
|
||||
return 42;
|
||||
};
|
||||
|
||||
console.log(module.exports, module.exports());
|
||||
|
||||
queueMicrotask(() => {
|
||||
console.log(
|
||||
module?.exports,
|
||||
require.cache[module.id].exports,
|
||||
module?.exports === require.cache[module.id]?.exports,
|
||||
__dirname,
|
||||
Object.keys(require(module.id)),
|
||||
require(module.id),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"eventemitter3": "^5.0.0",
|
||||
"tiny-typed-emitter": "latest"
|
||||
},
|
||||
"prettier": "../../.prettierrc.cjs"
|
||||
}
|
||||
80
bench/snippets/private.mjs
Normal file
80
bench/snippets/private.mjs
Normal file
@@ -0,0 +1,80 @@
|
||||
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
|
||||
// This is a benchmark of the performance impact of using private properties.
|
||||
|
||||
bench("Polyfillprivate", () => {
|
||||
"use strict";
|
||||
var __classPrivateFieldGet =
|
||||
(this && this.__classPrivateFieldGet) ||
|
||||
function (receiver, state, kind, f) {
|
||||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
||||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||||
};
|
||||
var __classPrivateFieldSet =
|
||||
(this && this.__classPrivateFieldSet) ||
|
||||
function (receiver, state, value, kind, f) {
|
||||
if (kind === "m") throw new TypeError("Private method is not writable");
|
||||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
||||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||||
return kind === "a" ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value;
|
||||
};
|
||||
var _Foo_state, _Foo_inc;
|
||||
class Foo {
|
||||
constructor() {
|
||||
_Foo_state.set(this, 1);
|
||||
_Foo_inc.set(this, 13);
|
||||
}
|
||||
run() {
|
||||
let n = 1000000;
|
||||
while (n-- > 0) {
|
||||
__classPrivateFieldSet(
|
||||
this,
|
||||
_Foo_state,
|
||||
__classPrivateFieldGet(this, _Foo_state, "f") + __classPrivateFieldGet(this, _Foo_inc, "f"),
|
||||
"f",
|
||||
);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
(_Foo_state = new WeakMap()), (_Foo_inc = new WeakMap());
|
||||
new Foo().run();
|
||||
});
|
||||
|
||||
bench("NativePrivates", () => {
|
||||
class Foo {
|
||||
#state = 1;
|
||||
#inc = 13;
|
||||
|
||||
run() {
|
||||
let n = 1000000;
|
||||
while (n-- > 0) {
|
||||
this.#state += this.#inc;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
new Foo().run();
|
||||
});
|
||||
|
||||
bench("ConventionalPrivates", () => {
|
||||
class Foo {
|
||||
_state = 1;
|
||||
_inc = 13;
|
||||
|
||||
run() {
|
||||
let n = 1000000;
|
||||
while (n-- > 0) {
|
||||
this._state += this._inc;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
new Foo().run();
|
||||
});
|
||||
|
||||
await run();
|
||||
33
bench/snippets/process-info.mjs
Normal file
33
bench/snippets/process-info.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
import { performance } from "perf_hooks";
|
||||
|
||||
bench("process.memoryUsage()", () => {
|
||||
process.memoryUsage();
|
||||
});
|
||||
|
||||
bench("process.memoryUsage.rss()", () => {
|
||||
process.memoryUsage.rss();
|
||||
});
|
||||
|
||||
bench("process.cpuUsage()", () => {
|
||||
process.cpuUsage();
|
||||
});
|
||||
|
||||
const init = process.cpuUsage();
|
||||
bench("process.cpuUsage(delta)", () => {
|
||||
process.cpuUsage(init);
|
||||
});
|
||||
|
||||
bench("performance.now()", () => {
|
||||
performance.now();
|
||||
});
|
||||
|
||||
bench("process.hrtime()", () => {
|
||||
process.hrtime();
|
||||
});
|
||||
|
||||
bench("process.hrtime.bigint()", () => {
|
||||
process.hrtime.bigint();
|
||||
});
|
||||
|
||||
await run();
|
||||
17
bench/snippets/readfile-not-found.mjs
Normal file
17
bench/snippets/readfile-not-found.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
import { readFileSync, existsSync } from "node:fs";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
bench(`readFileSync(/tmp/404-not-found)`, () => {
|
||||
try {
|
||||
readFileSync("/tmp/404-not-found");
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
bench(`readFile(/tmp/404-not-found)`, async () => {
|
||||
try {
|
||||
await readFile("/tmp/404-not-found");
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,4 +1,10 @@
|
||||
import { realpathSync } from "node:fs";
|
||||
const count = parseInt(process.env.ITERATIONS || "1", 10) || 1;
|
||||
const arg = process.argv[process.argv.length - 1];
|
||||
for (let i = 0; i < count; i++) realpathSync(arg);
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
bench("realpathSync x " + count, () => {
|
||||
for (let i = 0; i < count; i++) realpathSync(arg, "utf-8");
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
15
bench/snippets/request-response-clone.mjs
Normal file
15
bench/snippets/request-response-clone.mjs
Normal file
@@ -0,0 +1,15 @@
|
||||
// This mostly exists to check for a memory leak in response.clone()
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
const req = new Request("http://localhost:3000/");
|
||||
const resp = await fetch("http://example.com");
|
||||
|
||||
bench("req.clone().url", () => {
|
||||
return req.clone().url;
|
||||
});
|
||||
|
||||
bench("resp.clone().url", () => {
|
||||
return resp.clone().url;
|
||||
});
|
||||
|
||||
await run();
|
||||
136
bench/snippets/response-arrayBuffer.mjs
Normal file
136
bench/snippets/response-arrayBuffer.mjs
Normal file
@@ -0,0 +1,136 @@
|
||||
// This snippet mostly exists to reproduce a memory leak
|
||||
//
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const obj = {
|
||||
"id": 1296269,
|
||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
||||
"name": "Hello-World",
|
||||
"full_name": "octocat/Hello-World",
|
||||
"owner": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false,
|
||||
},
|
||||
"private": false,
|
||||
"html_url": "https://github.com/octocat/Hello-World",
|
||||
"description": "This your first repo!",
|
||||
"fork": false,
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
||||
"archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
||||
"assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
||||
"collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
|
||||
"deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
|
||||
"downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
|
||||
"events_url": "https://api.github.com/repos/octocat/Hello-World/events",
|
||||
"forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
|
||||
"git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
||||
"issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
||||
"languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
|
||||
"merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
|
||||
"milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
||||
"notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
||||
"pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
||||
"releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
||||
"stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
|
||||
"tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
|
||||
"teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
|
||||
"trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
||||
"hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
|
||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
||||
"homepage": "https://github.com",
|
||||
"language": null,
|
||||
"forks_count": 9,
|
||||
"stargazers_count": 80,
|
||||
"watchers_count": 80,
|
||||
"size": 108,
|
||||
"default_branch": "master",
|
||||
"open_issues_count": 0,
|
||||
"is_template": false,
|
||||
"topics": ["octocat", "atom", "electron", "api"],
|
||||
"has_issues": true,
|
||||
"has_projects": true,
|
||||
"has_wiki": true,
|
||||
"has_pages": false,
|
||||
"has_downloads": true,
|
||||
"has_discussions": false,
|
||||
"archived": false,
|
||||
"disabled": false,
|
||||
"visibility": "public",
|
||||
"pushed_at": "2011-01-26T19:06:43Z",
|
||||
"created_at": "2011-01-26T19:01:12Z",
|
||||
"updated_at": "2011-01-26T19:14:43Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": true,
|
||||
},
|
||||
"security_and_analysis": {
|
||||
"advanced_security": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning_push_protection": {
|
||||
"status": "disabled",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Force the string to be 8bit
|
||||
const str = String.fromCharCode(
|
||||
...JSON.stringify(obj)
|
||||
.split("")
|
||||
.map(a => a.charCodeAt(0)),
|
||||
);
|
||||
var i = 0;
|
||||
|
||||
bench("new Response().arrayBuffer() (new string each call, latin1)", async () => {
|
||||
return await new Response(str + i++).arrayBuffer();
|
||||
});
|
||||
|
||||
bench("new Response().arrayBuffer() (new string each call, utf16)", async () => {
|
||||
return await new Response(str + i++ + "😊").arrayBuffer();
|
||||
});
|
||||
|
||||
bench("new Response().arrayBuffer() (existing string, latin1)", async () => {
|
||||
return await new Response(str).arrayBuffer();
|
||||
});
|
||||
|
||||
await run();
|
||||
123
bench/snippets/response-json.mjs
Normal file
123
bench/snippets/response-json.mjs
Normal file
@@ -0,0 +1,123 @@
|
||||
// This snippet mostly exists to reproduce a memory leak
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
const obj = {
|
||||
"id": 1296269,
|
||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
||||
"name": "Hello-World",
|
||||
"full_name": "octocat/Hello-World",
|
||||
"owner": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false,
|
||||
},
|
||||
"private": false,
|
||||
"html_url": "https://github.com/octocat/Hello-World",
|
||||
"description": "This your first repo!",
|
||||
"fork": false,
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
||||
"archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
||||
"assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
||||
"collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
|
||||
"deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
|
||||
"downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
|
||||
"events_url": "https://api.github.com/repos/octocat/Hello-World/events",
|
||||
"forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
|
||||
"git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
||||
"issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
||||
"languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
|
||||
"merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
|
||||
"milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
||||
"notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
||||
"pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
||||
"releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
||||
"stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
|
||||
"tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
|
||||
"teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
|
||||
"trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
||||
"hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
|
||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
||||
"homepage": "https://github.com",
|
||||
"language": null,
|
||||
"forks_count": 9,
|
||||
"stargazers_count": 80,
|
||||
"watchers_count": 80,
|
||||
"size": 108,
|
||||
"default_branch": "master",
|
||||
"open_issues_count": 0,
|
||||
"is_template": false,
|
||||
"topics": ["octocat", "atom", "electron", "api"],
|
||||
"has_issues": true,
|
||||
"has_projects": true,
|
||||
"has_wiki": true,
|
||||
"has_pages": false,
|
||||
"has_downloads": true,
|
||||
"has_discussions": false,
|
||||
"archived": false,
|
||||
"disabled": false,
|
||||
"visibility": "public",
|
||||
"pushed_at": "2011-01-26T19:06:43Z",
|
||||
"created_at": "2011-01-26T19:01:12Z",
|
||||
"updated_at": "2011-01-26T19:14:43Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": true,
|
||||
},
|
||||
"security_and_analysis": {
|
||||
"advanced_security": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning_push_protection": {
|
||||
"status": "disabled",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
bench("Response.json(obj)", async () => {
|
||||
return Response.json(obj);
|
||||
});
|
||||
|
||||
bench("Response.json(obj).json()", async () => {
|
||||
return await Response.json(obj).json();
|
||||
});
|
||||
|
||||
await run();
|
||||
1
bench/snippets/resposne-constructor.mjs
Normal file
1
bench/snippets/resposne-constructor.mjs
Normal file
@@ -0,0 +1 @@
|
||||
for (let i = 0; i < 9999999; i++) new Request("http://aaaaaaaaaaaaaaaaaaaaa");
|
||||
37
bench/snippets/rewriter.mjs
Normal file
37
bench/snippets/rewriter.mjs
Normal file
@@ -0,0 +1,37 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
const blob = new Blob(["<p id='foo'>Hello</p>"]);
|
||||
bench("prepend", async () => {
|
||||
await new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.prepend("Hello");
|
||||
},
|
||||
})
|
||||
.transform(new Response(blob))
|
||||
.text();
|
||||
});
|
||||
|
||||
bench("append", async () => {
|
||||
await new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.append("Hello");
|
||||
},
|
||||
})
|
||||
.transform(new Response(blob))
|
||||
.text();
|
||||
});
|
||||
|
||||
bench("getAttribute", async () => {
|
||||
await new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.getAttribute("id");
|
||||
},
|
||||
})
|
||||
.transform(new Response(blob))
|
||||
.text();
|
||||
});
|
||||
|
||||
await run();
|
||||
128
bench/snippets/serialize.mjs
Normal file
128
bench/snippets/serialize.mjs
Normal file
@@ -0,0 +1,128 @@
|
||||
import { serialize, deserialize } from "node:v8";
|
||||
import { bench, run } from "./runner.mjs";
|
||||
const obj = {
|
||||
"id": 1296269,
|
||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
||||
"name": "Hello-World",
|
||||
"full_name": "octocat/Hello-World",
|
||||
"owner": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false,
|
||||
},
|
||||
"private": false,
|
||||
"html_url": "https://github.com/octocat/Hello-World",
|
||||
"description": "This your first repo!",
|
||||
"fork": false,
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
||||
"archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
||||
"assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
||||
"collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
|
||||
"deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
|
||||
"downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
|
||||
"events_url": "https://api.github.com/repos/octocat/Hello-World/events",
|
||||
"forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
|
||||
"git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
||||
"issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
||||
"languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
|
||||
"merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
|
||||
"milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
||||
"notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
||||
"pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
||||
"releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
||||
"stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
|
||||
"tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
|
||||
"teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
|
||||
"trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
||||
"hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
|
||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
||||
"homepage": "https://github.com",
|
||||
"language": null,
|
||||
"forks_count": 9,
|
||||
"stargazers_count": 80,
|
||||
"watchers_count": 80,
|
||||
"size": 108,
|
||||
"default_branch": "master",
|
||||
"open_issues_count": 0,
|
||||
"is_template": false,
|
||||
"topics": ["octocat", "atom", "electron", "api"],
|
||||
"has_issues": true,
|
||||
"has_projects": true,
|
||||
"has_wiki": true,
|
||||
"has_pages": false,
|
||||
"has_downloads": true,
|
||||
"has_discussions": false,
|
||||
"archived": false,
|
||||
"disabled": false,
|
||||
"visibility": "public",
|
||||
"pushed_at": "2011-01-26T19:06:43Z",
|
||||
"created_at": "2011-01-26T19:01:12Z",
|
||||
"updated_at": "2011-01-26T19:14:43Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": true,
|
||||
},
|
||||
"security_and_analysis": {
|
||||
"advanced_security": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning": {
|
||||
"status": "enabled",
|
||||
},
|
||||
"secret_scanning_push_protection": {
|
||||
"status": "disabled",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
bench("serialize", () => {
|
||||
serialize(obj);
|
||||
});
|
||||
const serialized = serialize(obj);
|
||||
bench("deserialize", () => {
|
||||
deserialize(serialized);
|
||||
});
|
||||
|
||||
if (typeof Bun !== "undefined") {
|
||||
if (!Bun.deepEquals(obj, deserialize(serialized))) {
|
||||
throw new Error("not equal");
|
||||
}
|
||||
}
|
||||
|
||||
await run();
|
||||
39
bench/snippets/structuredClone.mjs
Normal file
39
bench/snippets/structuredClone.mjs
Normal file
@@ -0,0 +1,39 @@
|
||||
var testArray = [
|
||||
{
|
||||
description: "Random description.",
|
||||
testNumber: 123456789,
|
||||
testBoolean: true,
|
||||
testObject: {
|
||||
testString: "test string",
|
||||
testNumber: 12345,
|
||||
},
|
||||
testArray: [
|
||||
{
|
||||
myName: "test name",
|
||||
myNumber: 123245,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: "Random description.",
|
||||
testNumber: 123456789,
|
||||
testBoolean: true,
|
||||
testObject: {
|
||||
testString: "test string",
|
||||
testNumber: 12345,
|
||||
},
|
||||
testArray: [
|
||||
{
|
||||
myName: "test name",
|
||||
myNumber: 123245,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
bench("structuredClone(array)", () => structuredClone(testArray));
|
||||
bench("structuredClone(123)", () => structuredClone(123));
|
||||
bench("structuredClone({a: 123})", () => structuredClone({ a: 123 }));
|
||||
await run();
|
||||
60
bench/snippets/util-deprecate.mjs
Normal file
60
bench/snippets/util-deprecate.mjs
Normal file
@@ -0,0 +1,60 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
function deprecateUsingClosure(fn, msg, code) {
|
||||
if (process.noDeprecation === true) {
|
||||
return fn;
|
||||
}
|
||||
|
||||
var realFn = fn;
|
||||
var wrapper = () => {
|
||||
return fnToWrap.apply(this, arguments);
|
||||
};
|
||||
|
||||
var deprecater = () => {
|
||||
if (process.throwDeprecation) {
|
||||
var err = new Error(msg);
|
||||
if (code) err.code = code;
|
||||
throw err;
|
||||
} else if (process.traceDeprecation) {
|
||||
console.trace(msg);
|
||||
} else {
|
||||
console.error(msg);
|
||||
}
|
||||
|
||||
fnToWrap = realFn;
|
||||
return realFn.apply(this, arguments);
|
||||
};
|
||||
var fnToWrap = deprecater;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function deprecateOriginal(fn, msg) {
|
||||
var warned = false;
|
||||
function deprecated() {
|
||||
if (!warned) {
|
||||
if (process.throwDeprecation) {
|
||||
throw new Error(msg);
|
||||
} else if (process.traceDeprecation) {
|
||||
console.trace(msg);
|
||||
} else {
|
||||
console.error(msg);
|
||||
}
|
||||
warned = true;
|
||||
}
|
||||
return fn.apply(this, arguments);
|
||||
}
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
const deprecatedy = deprecateUsingClosure(() => {}, "This is deprecated", "DEP0001");
|
||||
const deprecatedy2 = deprecateOriginal(() => {}, "This is deprecated");
|
||||
|
||||
bench("deprecateUsingClosure", () => {
|
||||
deprecatedy(Math.random() + 1);
|
||||
});
|
||||
|
||||
bench("deprecateOriginal", () => {
|
||||
deprecatedy2(Math.random() + 1);
|
||||
});
|
||||
|
||||
await run();
|
||||
20
bench/snippets/webcrypto.mjs
Normal file
20
bench/snippets/webcrypto.mjs
Normal file
@@ -0,0 +1,20 @@
|
||||
import { group } from "mitata";
|
||||
import { bench, run } from "./runner.mjs";
|
||||
|
||||
const sizes = [
|
||||
["small (63 bytes)", 63],
|
||||
["medium (4096 bytes)", 4096],
|
||||
["large (64 MB)", 64 * 1024 * 1024],
|
||||
];
|
||||
for (let [name, size] of sizes) {
|
||||
group(name, () => {
|
||||
var buf = new Uint8Array(size);
|
||||
for (let algorithm of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) {
|
||||
bench(algorithm, async () => {
|
||||
await crypto.subtle.digest(algorithm, buf);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await run();
|
||||
BIN
bench/sqlite/bun.lockb
Executable file
BIN
bench/sqlite/bun.lockb
Executable file
Binary file not shown.
728
bench/sqlite/package-lock.json
generated
728
bench/sqlite/package-lock.json
generated
@@ -1,728 +0,0 @@
|
||||
{
|
||||
"name": "bench",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^8.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/better-sqlite3": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.0.1.tgz",
|
||||
"integrity": "sha512-JhTZjpyapA1icCEjIZB4TSSgkGdFgpWZA2Wszg7Cf4JwJwKQmbvuNnJBeR+EYG/Z29OXvR4G//Rbg31BW/Z7Yg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"prebuild-install": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"dependencies": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
|
||||
"integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-template": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"node_modules/github-from-package": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||
},
|
||||
"node_modules/napi-build-utils": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "3.22.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
|
||||
"integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
"integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
"github-from-package": "0.0.0",
|
||||
"minimist": "^1.2.3",
|
||||
"mkdirp-classic": "^0.5.3",
|
||||
"napi-build-utils": "^1.0.1",
|
||||
"node-abi": "^3.3.0",
|
||||
"pump": "^3.0.0",
|
||||
"rc": "^1.2.7",
|
||||
"simple-get": "^4.0.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"tunnel-agent": "^0.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"prebuild-install": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rc": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
||||
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
},
|
||||
"better-sqlite3": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.0.1.tgz",
|
||||
"integrity": "sha512-JhTZjpyapA1icCEjIZB4TSSgkGdFgpWZA2Wszg7Cf4JwJwKQmbvuNnJBeR+EYG/Z29OXvR4G//Rbg31BW/Z7Yg==",
|
||||
"requires": {
|
||||
"bindings": "^1.5.0",
|
||||
"prebuild-install": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"requires": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"requires": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
},
|
||||
"decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"requires": {
|
||||
"mimic-response": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||
},
|
||||
"detect-libc": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
|
||||
"integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"expand-template": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"github-from-package": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||
},
|
||||
"napi-build-utils": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
|
||||
},
|
||||
"node-abi": {
|
||||
"version": "3.22.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
|
||||
"integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
|
||||
"requires": {
|
||||
"semver": "^7.3.5"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
"integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
|
||||
"requires": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
"github-from-package": "0.0.0",
|
||||
"minimist": "^1.2.3",
|
||||
"mkdirp-classic": "^0.5.3",
|
||||
"napi-build-utils": "^1.0.1",
|
||||
"node-abi": "^3.3.0",
|
||||
"pump": "^3.0.0",
|
||||
"rc": "^1.2.7",
|
||||
"simple-get": "^4.0.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"tunnel-agent": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"requires": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
|
||||
},
|
||||
"simple-get": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
||||
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||
"requires": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="
|
||||
},
|
||||
"tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"requires": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^8.0.1"
|
||||
"better-sqlite3": "8.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
|
||||
1
bench/stream-file-upload-client/.gitignore
vendored
Normal file
1
bench/stream-file-upload-client/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
hello.txt
|
||||
35
bench/stream-file-upload-client/README.md
Normal file
35
bench/stream-file-upload-client/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# HTTP request file upload benchmark
|
||||
|
||||
This is a simple benchmark of uploading a file to a web server in different runtimes.
|
||||
|
||||
## Usage
|
||||
|
||||
Generate a file to upload (default is `hello.txt`):
|
||||
|
||||
```bash
|
||||
bun generate-file.js
|
||||
```
|
||||
|
||||
Run the server:
|
||||
|
||||
```bash
|
||||
node server-node.mjs
|
||||
```
|
||||
|
||||
Run the benchmark in bun:
|
||||
|
||||
```bash
|
||||
bun stream-file-bun.js
|
||||
```
|
||||
|
||||
Run the benchmark in node:
|
||||
|
||||
```bash
|
||||
node stream-file-node.mjs
|
||||
```
|
||||
|
||||
Run the benchmark in deno:
|
||||
|
||||
```bash
|
||||
deno run -A stream-file-deno.js
|
||||
```
|
||||
8
bench/stream-file-upload-client/generate-file.js
Normal file
8
bench/stream-file-upload-client/generate-file.js
Normal file
File diff suppressed because one or more lines are too long
15
bench/stream-file-upload-client/server-node.mjs
Normal file
15
bench/stream-file-upload-client/server-node.mjs
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createServer } from "node:http";
|
||||
const server = createServer((req, res) => {
|
||||
var chunkSize = 0;
|
||||
req.on("data", chunk => {
|
||||
chunkSize += chunk.byteLength;
|
||||
});
|
||||
|
||||
req.on("end", () => {
|
||||
console.log("Received", chunkSize, "bytes");
|
||||
res.end(`${chunkSize}`);
|
||||
});
|
||||
});
|
||||
server.listen(parseInt(process.env.PORT ?? "3000"), (err, port) => {
|
||||
console.log(`http://localhost:${server.address().port}`);
|
||||
});
|
||||
9
bench/stream-file-upload-client/stream-file-bun.js
Normal file
9
bench/stream-file-upload-client/stream-file-bun.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { file } from "bun";
|
||||
console.time("stream-file-bun");
|
||||
const response = await fetch(process.env.URL ?? "http://localhost:3000", {
|
||||
method: "POST",
|
||||
body: file(process.env.FILE ?? "hello.txt"),
|
||||
});
|
||||
console.timeEnd("stream-file-bun");
|
||||
|
||||
console.log("Sent", await response.text(), "bytes");
|
||||
12
bench/stream-file-upload-client/stream-file-deno.js
Normal file
12
bench/stream-file-upload-client/stream-file-deno.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const file = await Deno.open(Deno.env.get("FILE") ?? "hello.txt", {
|
||||
read: true,
|
||||
});
|
||||
|
||||
console.time("stream-file-deno");
|
||||
const response = await fetch(Deno.env.get("URL") ?? "http://localhost:3000", {
|
||||
method: "POST",
|
||||
body: file.readable,
|
||||
});
|
||||
console.timeEnd("stream-file-deno");
|
||||
|
||||
console.log("Sent", await response.text(), "bytes");
|
||||
19
bench/stream-file-upload-client/stream-file-node.mjs
Normal file
19
bench/stream-file-upload-client/stream-file-node.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createReadStream } from "node:fs";
|
||||
import http from "node:http";
|
||||
|
||||
console.time("stream-file-node");
|
||||
createReadStream(process.env.FILE ?? "hello.txt")
|
||||
.pipe(
|
||||
http
|
||||
.request(process.env.URL ?? "http://localhost:3000", {
|
||||
method: "POST",
|
||||
})
|
||||
.on("response", response => {
|
||||
response.on("data", data => {
|
||||
console.log("Sent", parseInt(data.toString(), 10), "bytes");
|
||||
});
|
||||
}),
|
||||
)
|
||||
.on("close", () => {
|
||||
console.timeEnd("stream-file-node");
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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.
|
||||
First, start the server. By default, it will wait for 32 clients which the client script will handle.
|
||||
|
||||
Run in Bun (`Bun.serve`):
|
||||
|
||||
@@ -19,10 +19,10 @@ node ./chat-server.node.mjs
|
||||
Run in Deno (`Deno.serve`):
|
||||
|
||||
```bash
|
||||
deno run -A --unstable ./chat-server.deno.mjs
|
||||
deno run -A ./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
|
||||
Then, run the client script. By default, it will connect 32 clients. This client script can run in Bun, Node, or Deno
|
||||
|
||||
```bash
|
||||
node ./chat-client.mjs
|
||||
@@ -34,6 +34,4 @@ For example, when the client sends `"foo"`, the server sends back `"John: foo"`
|
||||
|
||||
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.
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@ const env = "process" in globalThis ? process.env : "Deno" in globalThis ? Deno.
|
||||
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 CLIENTS_TO_WAIT_FOR = parseInt(env.CLIENTS_COUNT || "", 10) || 32;
|
||||
const DELAY = 64;
|
||||
const MESSAGES_TO_SEND = Array.from({ length: 32 }, () => [
|
||||
"Hello World!",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// See ./README.md for instructions on how to run this benchmark.
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 16;
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 32;
|
||||
var remainingClients = CLIENTS_TO_WAIT_FOR;
|
||||
const COMPRESS = process.env.COMPRESS === "1";
|
||||
const port = process.PORT || 4001;
|
||||
@@ -32,6 +32,7 @@ const server = Bun.serve({
|
||||
},
|
||||
|
||||
perMessageDeflate: false,
|
||||
publishToSelf: true,
|
||||
},
|
||||
|
||||
fetch(req, server) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// 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;
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(Deno.env.get("CLIENTS_COUNT") || "", 10) || 32;
|
||||
|
||||
var clients = [];
|
||||
async function reqHandler(req) {
|
||||
@@ -42,4 +42,4 @@ function sendReadyMessage() {
|
||||
|
||||
console.log(`Waiting for ${CLIENTS_TO_WAIT_FOR} clients to connect..`);
|
||||
|
||||
Deno.serve(reqHandler, { port });
|
||||
Deno.serve({ port }, reqHandler);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// 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;
|
||||
const CLIENTS_TO_WAIT_FOR = parseInt(process.env.CLIENTS_COUNT || "", 10) || 32;
|
||||
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.7",
|
||||
"utf-8-validate": "^5.0.10",
|
||||
"ws": "^8.9.0"
|
||||
"bufferutil": "4.0.7",
|
||||
"utf-8-validate": "6.0.3",
|
||||
"ws": "8.13.0"
|
||||
}
|
||||
}
|
||||
|
||||
76
build.zig
76
build.zig
@@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
const Wyhash = @import("./src/wyhash.zig").Wyhash;
|
||||
var is_debug_build = false;
|
||||
fn moduleSource(comptime out: []const u8) FileSource {
|
||||
if (comptime std.fs.path.dirname(@src().file)) |base| {
|
||||
const outpath = comptime base ++ std.fs.path.sep_str ++ out;
|
||||
@@ -8,27 +9,6 @@ fn moduleSource(comptime out: []const u8) FileSource {
|
||||
return FileSource.relative(out);
|
||||
}
|
||||
}
|
||||
pub fn addPicoHTTP(step: *CompileStep, comptime with_obj: bool) void {
|
||||
step.addIncludePath("src/deps");
|
||||
|
||||
if (with_obj) {
|
||||
step.addObjectFile("src/deps/picohttpparser.o");
|
||||
}
|
||||
|
||||
step.addIncludePath("src/deps");
|
||||
|
||||
if (with_obj) {
|
||||
step.addObjectFile(panicIfNotFound("src/deps/picohttpparser.o"));
|
||||
step.addObjectFile(panicIfNotFound("src/deps/libssl.a"));
|
||||
step.addObjectFile(panicIfNotFound("src/deps/libcrypto.a"));
|
||||
}
|
||||
|
||||
// step.add("/Users/jarred/Code/WebKit/WebKitBuild/Release/lib/libWTF.a");
|
||||
|
||||
// ./Tools/Scripts/build-jsc --jsc-only --cmakeargs="-DENABLE_STATIC_JSC=ON"
|
||||
// set -gx ICU_INCLUDE_DIRS "/usr/local/opt/icu4c/include"
|
||||
// homebrew-provided icu4c
|
||||
}
|
||||
|
||||
const color_map = std.ComptimeStringMap([]const u8, .{
|
||||
&.{ "black", "30m" },
|
||||
@@ -75,18 +55,31 @@ const BunBuildOptions = struct {
|
||||
fallback_html_version: u64 = 0,
|
||||
|
||||
pub fn updateRuntime(this: *BunBuildOptions) anyerror!void {
|
||||
var runtime_out_file = try std.fs.cwd().openFile("src/runtime.out.js", .{ .mode = .read_only });
|
||||
const runtime_hash = std.hash.Wyhash.hash(
|
||||
0,
|
||||
try runtime_out_file.readToEndAlloc(std.heap.page_allocator, try runtime_out_file.getEndPos()),
|
||||
);
|
||||
this.runtime_js_version = runtime_hash;
|
||||
var fallback_out_file = try std.fs.cwd().openFile("src/fallback.out.js", .{ .mode = .read_only });
|
||||
const fallback_hash = std.hash.Wyhash.hash(
|
||||
0,
|
||||
try fallback_out_file.readToEndAlloc(std.heap.page_allocator, try fallback_out_file.getEndPos()),
|
||||
);
|
||||
this.fallback_html_version = fallback_hash;
|
||||
if (std.fs.cwd().openFile("src/runtime.out.js", .{ .mode = .read_only })) |file| {
|
||||
defer file.close();
|
||||
const runtime_hash = Wyhash.hash(
|
||||
0,
|
||||
try file.readToEndAlloc(std.heap.page_allocator, try file.getEndPos()),
|
||||
);
|
||||
this.runtime_js_version = runtime_hash;
|
||||
} else |_| {
|
||||
if (!is_debug_build) {
|
||||
@panic("Runtime file was not read successfully. Please run `make setup`");
|
||||
}
|
||||
}
|
||||
|
||||
if (std.fs.cwd().openFile("src/fallback.out.js", .{ .mode = .read_only })) |file| {
|
||||
defer file.close();
|
||||
const fallback_hash = Wyhash.hash(
|
||||
0,
|
||||
try file.readToEndAlloc(std.heap.page_allocator, try file.getEndPos()),
|
||||
);
|
||||
this.fallback_html_version = fallback_hash;
|
||||
} else |_| {
|
||||
if (!is_debug_build) {
|
||||
@panic("Fallback file was not read successfully. Please run `make setup`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(this: BunBuildOptions, b: anytype) *std.build.OptionsStep {
|
||||
@@ -186,18 +179,19 @@ pub fn build(b: *Build) !void {
|
||||
}
|
||||
|
||||
std.fs.cwd().makePath(output_dir) catch {};
|
||||
is_debug_build = optimize == OptimizeMode.Debug;
|
||||
const bun_executable_name = if (optimize == std.builtin.OptimizeMode.Debug) "bun-debug" else "bun";
|
||||
const root_src = if (target.getOsTag() == std.Target.Os.Tag.freestanding)
|
||||
"src/main_wasm.zig"
|
||||
"root_wasm.zig"
|
||||
else
|
||||
"root.zig";
|
||||
|
||||
const min_version: std.builtin.Version = if (target.getOsTag() != .freestanding)
|
||||
const min_version: std.SemanticVersion = if (target.getOsTag() != .freestanding and !target.isWindows())
|
||||
target.getOsVersionMin().semver
|
||||
else
|
||||
.{ .major = 0, .minor = 0, .patch = 0 };
|
||||
|
||||
const max_version: std.builtin.Version = if (target.getOsTag() != .freestanding)
|
||||
const max_version: std.SemanticVersion = if (target.getOsTag() != .freestanding and !target.isWindows())
|
||||
target.getOsVersionMax().semver
|
||||
else
|
||||
.{ .major = 0, .minor = 0, .patch = 0 };
|
||||
@@ -224,7 +218,6 @@ pub fn build(b: *Build) !void {
|
||||
.argv = &.{
|
||||
"git",
|
||||
"rev-parse",
|
||||
"--short",
|
||||
"HEAD",
|
||||
},
|
||||
.cwd = b.pathFromRoot("."),
|
||||
@@ -246,7 +239,6 @@ pub fn build(b: *Build) !void {
|
||||
};
|
||||
|
||||
{
|
||||
addPicoHTTP(obj, false);
|
||||
obj.setMainPkgPath(b.pathFromRoot("."));
|
||||
|
||||
try addInternalPackages(
|
||||
@@ -329,7 +321,7 @@ pub fn build(b: *Build) !void {
|
||||
const wasm = b.step("bun-wasm", "Build WASM");
|
||||
var wasm_step = b.addStaticLibrary(.{
|
||||
.name = "bun-wasm",
|
||||
.root_source_file = FileSource.relative("src/main_wasm.zig"),
|
||||
.root_source_file = FileSource.relative("root_wasm.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
@@ -339,6 +331,8 @@ pub fn build(b: *Build) !void {
|
||||
// wasm_step.link_emit_relocs = true;
|
||||
// wasm_step.single_threaded = true;
|
||||
try configureObjectStep(b, wasm_step, @TypeOf(target), target, obj.main_pkg_path.?);
|
||||
var build_opts = default_build_options;
|
||||
wasm_step.addOptions("build_options", build_opts.step(b));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -467,8 +461,6 @@ pub fn configureObjectStep(b: *std.build.Builder, obj: *CompileStep, comptime Ta
|
||||
|
||||
// obj.setTarget(target);
|
||||
try addInternalPackages(b, obj, std.heap.page_allocator, b.zig_exe, target);
|
||||
if (target.getOsTag() != .freestanding)
|
||||
addPicoHTTP(obj, false);
|
||||
|
||||
obj.strip = false;
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ _bun_completions() {
|
||||
PACKAGE_OPTIONS[REMOVE_OPTIONS_LONG]="";
|
||||
PACKAGE_OPTIONS[REMOVE_OPTIONS_SHORT]="";
|
||||
|
||||
PACKAGE_OPTIONS[SHARED_OPTIONS_LONG]="--config --yarn --production --no-save --dry-run --lockfile --force --cache-dir --no-cache --silent --verbose --global --cwd --backend --link-native-bins --help";
|
||||
PACKAGE_OPTIONS[SHARED_OPTIONS_LONG]="--config --yarn --production --frozen-lockfile --no-save --dry-run --lockfile --force --cache-dir --no-cache --silent --verbose --global --cwd --backend --link-native-bins --help";
|
||||
PACKAGE_OPTIONS[SHARED_OPTIONS_SHORT]="-c -y -p -f -g";
|
||||
|
||||
PM_OPTIONS[LONG_OPTIONS]="--config --yarn --production --no-save --dry-run --lockfile --force --cache-dir --no-cache --silent --verbose --no-progress --no-summary --no-verify --ignore-scripts --global --cwd --backend --link-native-bins --help"
|
||||
PM_OPTIONS[LONG_OPTIONS]="--config --yarn --production --frozen-lockfile --no-save --dry-run --lockfile --force --cache-dir --no-cache --silent --verbose --no-progress --no-summary --no-verify --ignore-scripts --global --cwd --backend --link-native-bins --help"
|
||||
PM_OPTIONS[SHORT_OPTIONS]="-c -y -p -f -g"
|
||||
|
||||
local cur_word="${COMP_WORDS[${COMP_CWORD}]}";
|
||||
|
||||
@@ -47,8 +47,9 @@ _bun() {
|
||||
'-g[Add a package globally]' \
|
||||
'--global[Add a package globally]' \
|
||||
'--production[Don'"'"'t install devDependencies]' \
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--optional[Add dependency to optionalDependencies]' \
|
||||
'--development[Add dependency to devDependencies]' \
|
||||
'--dev[Add dependency to devDependencies]' \
|
||||
'-d[Add dependency to devDependencies]' \
|
||||
'-p[Don'"'"'t install devDependencies]' \
|
||||
'--no-save[]' \
|
||||
@@ -88,8 +89,9 @@ _bun() {
|
||||
'--yarn[Write a yarn.lock file (yarn v1)]' \
|
||||
'--global[Add a package globally]' \
|
||||
'--production[Don'"'"'t install devDependencies]' \
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--optional[Add dependency to optionalDependencies]' \
|
||||
'--development[Add dependency to devDependencies]' \
|
||||
'--dev[Add dependency to devDependencies]' \
|
||||
'-d[Add dependency to devDependencies]' \
|
||||
'-p[Don'"'"'t install devDependencies]' \
|
||||
'--no-save[]' \
|
||||
@@ -123,8 +125,9 @@ _bun() {
|
||||
'--yarn[Write a yarn.lock file (yarn v1)]' \
|
||||
'--global[Add a package globally]' \
|
||||
'--production[Don'"'"'t install devDependencies]' \
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--optional[Add dependency to optionalDependencies]' \
|
||||
'--development[Add dependency to devDependencies]' \
|
||||
'--dev[Add dependency to devDependencies]' \
|
||||
'-d[Add dependency to devDependencies]' \
|
||||
'-p[Don'"'"'t install devDependencies]' \
|
||||
'--no-save[]' \
|
||||
@@ -278,6 +281,7 @@ _bun() {
|
||||
'--yarn[Write a yarn.lock file (yarn v1)]'
|
||||
'-p[Do not install devDependencies]'
|
||||
'--production[Do not install devDependencies]'
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--no-save[Do not save a lockfile]'
|
||||
'--dry-run[Do not install anything]'
|
||||
'--lockfile[Store & load a lockfile at a specific filepath]'
|
||||
@@ -532,6 +536,7 @@ _bun() {
|
||||
'--yarn[Write a yarn.lock file (yarn v1)]' \
|
||||
'--production[Don'"'"'t install devDependencies]' \
|
||||
'-p[Don'"'"'t install devDependencies]' \
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--no-save[]' \
|
||||
'--dry-run[Don'"'"'t install anything]' \
|
||||
'--force[Always request the latest versions from the registry & reinstall all dependenices]' \
|
||||
@@ -565,6 +570,7 @@ _bun() {
|
||||
'--yarn[Write a yarn.lock file (yarn v1)]' \
|
||||
'--production[Don'"'"'t install devDependencies]' \
|
||||
'-p[Don'"'"'t install devDependencies]' \
|
||||
'--frozen-lockfile[Disallow changes to lockfile]' \
|
||||
'--no-save[]' \
|
||||
'--dry-run[Don'"'"'t install anything]' \
|
||||
'-g[Remove a package globally]' \
|
||||
|
||||
@@ -115,6 +115,7 @@ subcommands:
|
||||
- yarn -- "Write a yarn.lock file (yarn v1)"
|
||||
- production -- "Don't install devDependencies"
|
||||
- p -- "Don't install devDependencies"
|
||||
- frozen-lockfile -- "Disallow changes to lockfile"
|
||||
- no-save --
|
||||
- dry-run -- "Don't install anything"
|
||||
- force -- "Always request the latest versions from the registry & reinstall all dependenices"
|
||||
@@ -152,6 +153,7 @@ subcommands:
|
||||
- development -- "Add dependency to devDependencies"
|
||||
- d -- "Add dependency to devDependencies"
|
||||
- p -- "Don't install devDependencies"
|
||||
- frozen-lockfile -- "Disallow changes to lockfile"
|
||||
- no-save --
|
||||
- dry-run -- "Don't install anything"
|
||||
- force -- "Always request the latest versions from the registry & reinstall all dependenices"
|
||||
@@ -192,6 +194,7 @@ subcommands:
|
||||
- yarn -- "Write a yarn.lock file (yarn v1)"
|
||||
- production -- "Don't install devDependencies"
|
||||
- p -- "Don't install devDependencies"
|
||||
- frozen-lockfile -- "Disallow changes to lockfile"
|
||||
- no-save --
|
||||
- dry-run -- "Don't install anything"
|
||||
- force -- "Always request the latest versions from the registry & reinstall all dependenices"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
FROM debian:bullseye-slim AS build
|
||||
# Not officially supported (yet)
|
||||
|
||||
# https://github.com/oven-sh/bun/releases
|
||||
ARG BUN_VERSION=latest
|
||||
|
||||
988
docs/api/binary-data.md
Normal file
988
docs/api/binary-data.md
Normal file
@@ -0,0 +1,988 @@
|
||||
This page is intended as an introduction to working with binary data in JavaScript. Bun implements a number of data types and utilities for working with binary data, most of which are Web-standard. Any Bun-specific APIs will be noted as such.
|
||||
|
||||
Below is a quick "cheat sheet" that doubles as a table of contents. Click an item in the left column to jump to that section.
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- [`TypedArray`](#typedarray)
|
||||
- A family of classes that provide an `Array`-like interface for interacting with binary data. Includes `Uint8Array`, `Uint16Array`, `Int8Array`, and more.
|
||||
|
||||
---
|
||||
|
||||
- [`Buffer`](#buffer)
|
||||
- A subclass of `Uint8Array` that implements a wide range of convenience methods. Unlike the other elements in this table, this is a Node.js API (which Bun implements). It can't be used in the browser.
|
||||
|
||||
---
|
||||
|
||||
- [`DataView`](#dataview)
|
||||
- A class that provides a `get/set` API for writing some number of bytes to an `ArrayBuffer` at a particular byte offset. Often used reading or writing binary protocols.
|
||||
|
||||
---
|
||||
|
||||
- [`Blob`](#blob)
|
||||
- A readonly blob of binary data usually representing a file. Has a MIME `type`, a `size`, and methods for converting to `ArrayBuffer`, `ReadableStream`, and string.
|
||||
|
||||
---
|
||||
|
||||
<!-- - [`File`](#file)
|
||||
- _Browser only_. A subclass of `Blob` that represents a file. Has a `name` and `lastModified` timestamp. There is experimental support in Node.js v20; Bun does not support `File` yet; most of its functionality is provided by `BunFile`.
|
||||
|
||||
--- -->
|
||||
|
||||
- [`BunFile`](#bunfile)
|
||||
- _Bun only_. A subclass of `Blob` that represents a lazily-loaded file on disk. Created with `Bun.file(path)`.
|
||||
|
||||
{% /table %}
|
||||
|
||||
## `ArrayBuffer` and views
|
||||
|
||||
Until 2009, there was no language-native way to store and manipulate binary data in JavaScript. ECMAScript v5 introduced a range of new mechanisms for this. The most fundamental building block is `ArrayBuffer`, a simple data structure that represents a sequence of bytes in memory.
|
||||
|
||||
```ts
|
||||
// this buffer can store 8 bytes
|
||||
const buf = new ArrayBuffer(8);
|
||||
```
|
||||
|
||||
Despite the name, it isn't an array and supports none of the array methods and operators one might expect. In fact, there is no way to directly read or write values from an `ArrayBuffer`. There's very little you can do with one except check its size and create "slices" from it.
|
||||
|
||||
```ts
|
||||
const buf = new ArrayBuffer(8);
|
||||
|
||||
buf.byteLength; // => 8
|
||||
|
||||
const slice = buf.slice(0, 4); // returns new ArrayBuffer
|
||||
slice.byteLength; // => 4
|
||||
```
|
||||
|
||||
To do anything interesting we need a construct known as a "view". A view is a class that _wraps_ an `ArrayBuffer` instance and lets you read and manipulate the underlying data. There are two types of views: _typed arrays_ and `DataView`.
|
||||
|
||||
### `DataView`
|
||||
|
||||
The `DataView` class is a lower-level interface for reading and manipulating the data in an `ArrayBuffer`.
|
||||
|
||||
Below we create a new `DataView` and set the first byte to 5.
|
||||
|
||||
```ts
|
||||
const buf = new ArrayBuffer(4);
|
||||
// [0x0, 0x0, 0x0, 0x0]
|
||||
|
||||
const dv = new DataView(buf);
|
||||
dv.setUint8(0, 3); // write value 3 at byte offset 0
|
||||
dv.getUint8(0); // => 3
|
||||
// [0x11, 0x0, 0x0, 0x0]
|
||||
```
|
||||
|
||||
Now lets write a `Uint16` at byte offset `1`. This requires two bytes. We're using the value `513`, which is `2 * 256 + 1`; in bytes, that's `00000010 00000001`.
|
||||
|
||||
```ts
|
||||
dv.setUint16(1, 513);
|
||||
// [0x11, 0x10, 0x1, 0x0]
|
||||
|
||||
console.log(dv.getUint16(1)); // => 513
|
||||
```
|
||||
|
||||
We've now assigned a value to the first three bytes in our underlying `ArrayBuffer`. Even though the second and third bytes were created using `setUint16()`, we can still read each of its component bytes using `getUint8()`.
|
||||
|
||||
```ts
|
||||
console.log(dv.getUint8(1)); // => 2
|
||||
console.log(dv.getUint8(2)); // => 1
|
||||
```
|
||||
|
||||
Attempting to write a value that requires more space than is available in the underlying `ArrayBuffer` will cuase an error. Below we attempt to write a `Float64` (which requires 8 bytes) at byte offset `0`, but there are only four total bytes in the buffer.
|
||||
|
||||
```ts
|
||||
dv.setFloat64(0, 3.1415);
|
||||
// ^ RangeError: Out of bounds access
|
||||
```
|
||||
|
||||
The following methods are available on `DataView`:
|
||||
|
||||
{% table %}
|
||||
|
||||
- Getters
|
||||
- Setters
|
||||
|
||||
---
|
||||
|
||||
- [`getBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigInt64)
|
||||
- [`setBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigInt64)
|
||||
|
||||
---
|
||||
|
||||
- [`getBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigUint64)
|
||||
- [`setBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigUint64)
|
||||
|
||||
---
|
||||
|
||||
- [`getFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat32)
|
||||
- [`setFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat32)
|
||||
|
||||
---
|
||||
|
||||
- [`getFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat64)
|
||||
- [`setFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat64)
|
||||
|
||||
---
|
||||
|
||||
- [`getInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt16)
|
||||
- [`setInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt16)
|
||||
|
||||
---
|
||||
|
||||
- [`getInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt32)
|
||||
- [`setInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt32)
|
||||
|
||||
---
|
||||
|
||||
- [`getInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt8)
|
||||
- [`setInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt8)
|
||||
|
||||
---
|
||||
|
||||
- [`getUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint16)
|
||||
- [`setUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint16)
|
||||
|
||||
---
|
||||
|
||||
- [`getUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint32)
|
||||
- [`setUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint32)
|
||||
|
||||
---
|
||||
|
||||
- [`getUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint8)
|
||||
- [`setUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint8)
|
||||
|
||||
{% /table %}
|
||||
|
||||
### `TypedArray`
|
||||
|
||||
Typed arrays are a family of classes that provide an `Array`-like interface for interacting with data in an `ArrayBuffer`. Whereas a `DataView` lets you write numbers of varying size at a particular offset, a `TypedArray` interprets the underlying bytes as an array of numbers, each of a fixed size.
|
||||
|
||||
{% callout %}
|
||||
**Note** — It's common to refer to this family of classes collectively by their shared superclass `TypedArray`. This class as _internal_ to JavaScript; you can't directly create instances of it, and `TypedArray` is not defined in the global scope. Think of it as an `interface` or an abstract class.
|
||||
{% /callout %}
|
||||
|
||||
```ts
|
||||
const buffer = new ArrayBuffer(3);
|
||||
const arr = new Uint8Array(buffer);
|
||||
|
||||
// contents are initialized to zero
|
||||
console.log(arr); // Uint8Array(3) [0, 0, 0]
|
||||
|
||||
// assign values like an array
|
||||
arr[0] = 0;
|
||||
arr[1] = 10;
|
||||
arr[2] = 255;
|
||||
arr[3] = 255; // no-op, out of bounds
|
||||
```
|
||||
|
||||
While an `ArrayBuffer` is a generic sequence of bytes, these typed array classes interpret the bytes as an array of numbers of a given byte size.
|
||||
The top row contains the raw bytes, and the later rows contain how these bytes will be interpreted when _viewed_ using different typed array classes.
|
||||
|
||||
The following classes are typed arrays, along with a description of how they interpret the bytes in an `ArrayBuffer`:
|
||||
|
||||
{% table %}
|
||||
|
||||
- Class
|
||||
- Description
|
||||
|
||||
---
|
||||
|
||||
- [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
|
||||
- Every one (1) byte is interpreted as an unsigned 8-bit integer. Range 0 to 255.
|
||||
|
||||
---
|
||||
|
||||
- [`Uint16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array)
|
||||
- Every two (2) bytes are interpreted as an unsigned 16-bit integer. Range 0 to 65535.
|
||||
|
||||
---
|
||||
|
||||
- [`Uint32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)
|
||||
- Every four (4) bytes are interpreted as an unsigned 32-bit integer. Range 0 to 4294967295.
|
||||
|
||||
---
|
||||
|
||||
- [`Int8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array)
|
||||
- Every one (1) byte is interpreted as a signed 8-bit integer. Range -128 to 127.
|
||||
|
||||
---
|
||||
|
||||
- [`Int16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array)
|
||||
- Every two (2) bytes are interpreted as a signed 16-bit integer. Range -32768 to 32767.
|
||||
|
||||
---
|
||||
|
||||
- [`Int32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array)
|
||||
- Every four (4) bytes are interpreted as a signed 32-bit integer. Range -2147483648 to 2147483647.
|
||||
|
||||
---
|
||||
|
||||
- [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array)
|
||||
- Every four (4) bytes are interpreted as a 32-bit floating point number. Range -3.4e38 to 3.4e38.
|
||||
|
||||
---
|
||||
|
||||
- [`Float64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array)
|
||||
- Every eight (8) bytes are interpreted as a 64-bit floating point number. Range -1.7e308 to 1.7e308.
|
||||
|
||||
---
|
||||
|
||||
- [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)
|
||||
- Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers).
|
||||
|
||||
---
|
||||
|
||||
- [`BigUint64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array)
|
||||
- Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range 0 to 18446744073709551615 (though `BigInt` is capable of representing larger numbers).
|
||||
|
||||
---
|
||||
|
||||
- [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray)
|
||||
- Same as `Uint8Array`, but automatically "clamps" to the range 0-255 when assigning a value to an element.
|
||||
|
||||
{% /table %}
|
||||
|
||||
The table below demonstrates how the bytes in an `ArrayBuffer` are interpreted when viewed using different typed array classes.
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- `ArrayBuffer`
|
||||
- `00000000`
|
||||
- `00000001`
|
||||
- `00000010`
|
||||
- `00000011`
|
||||
- `00000100`
|
||||
- `00000101`
|
||||
- `00000110`
|
||||
- `00000111`
|
||||
|
||||
---
|
||||
|
||||
- `Uint8Array`
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
|
||||
---
|
||||
|
||||
- `Uint16Array`
|
||||
- 256 (`1 * 256 + 0`) {% colspan=2 %}
|
||||
- 770 (`3 * 256 + 2`) {% colspan=2 %}
|
||||
- 1284 (`5 * 256 + 4`) {% colspan=2 %}
|
||||
- 1798 (`7 * 256 + 6`) {% colspan=2 %}
|
||||
|
||||
---
|
||||
|
||||
- `Uint32Array`
|
||||
- 50462976 {% colspan=4 %}
|
||||
- 117835012 {% colspan=4 %}
|
||||
|
||||
---
|
||||
|
||||
- `BigUint64Array`
|
||||
- 506097522914230528n {% colspan=8 %}
|
||||
|
||||
{% /table %}
|
||||
|
||||
To create a typed array from a pre-defined `ArrayBuffer`:
|
||||
|
||||
```ts
|
||||
// create typed array from ArrayBuffer
|
||||
const buf = new ArrayBuffer(10);
|
||||
const arr = new Uint8Array(buf);
|
||||
|
||||
arr[0] = 30;
|
||||
arr[1] = 60;
|
||||
|
||||
// all elements are initialized to zero
|
||||
console.log(arr); // => Uint8Array(10) [ 30, 60, 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||
```
|
||||
|
||||
If we tried to instantiate a `Uint32Array` from this same `ArrayBuffer`, we'd get an error.
|
||||
|
||||
```ts
|
||||
const buf = new ArrayBuffer(10);
|
||||
const arr = new Uint32Array(buf);
|
||||
// ^ RangeError: ArrayBuffer length minus the byteOffset
|
||||
// is not a multiple of the element size
|
||||
```
|
||||
|
||||
A `Uint32` value requires four bytes (16 bits). Because the `ArrayBuffer` is 10 bytes long, there's no way to cleanly divide its contents into 4-byte chunks.
|
||||
|
||||
To fix this, we can create a typed array over a particular "slice" of an `ArrayBuffer`. The `Uint16Array` below only "views" the _first_ 8 bytes of the underlying `ArrayBuffer`. To achieve these, we specify a `byteOffset` of `0` and a `length` of `2`, which indicates the number of `Uint32` numbers we want our array to hold.
|
||||
|
||||
```ts
|
||||
// create typed array from ArrayBuffer slice
|
||||
const buf = new ArrayBuffer(10);
|
||||
const arr = new Uint32Array(buf, 0, 2);
|
||||
|
||||
/*
|
||||
buf _ _ _ _ _ _ _ _ _ _ 10 bytes
|
||||
arr [_______,_______] 2 4-byte elements
|
||||
*/
|
||||
|
||||
arr.byteOffset; // 0
|
||||
arr.length; // 2
|
||||
```
|
||||
|
||||
You don't need to explicitly create an `ArrayBuffer` instance; you can instead directly specify a length in the typed array constructor:
|
||||
|
||||
```ts
|
||||
const arr2 = new Uint8Array(5);
|
||||
|
||||
// all elements are initialized to zero
|
||||
// => Uint8Array(5) [0, 0, 0, 0, 0]
|
||||
```
|
||||
|
||||
Typed arrays can also be instantiated directly from an array of numbers, or another typed array:
|
||||
|
||||
```ts
|
||||
// from an array of numbers
|
||||
const arr1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
arr1[0]; // => 0;
|
||||
arr1[7]; // => 7;
|
||||
|
||||
// from another typed array
|
||||
const arr2 = new Uint8Array(arr);
|
||||
```
|
||||
|
||||
Broadly speaking, typed arrays provide the same methods as regular arrays, with a few exceptions. For example, `push` and `pop` are not available on typed arrays, because they would require resizing the underlying `ArrayBuffer`.
|
||||
|
||||
```ts
|
||||
const arr = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
|
||||
// supports common array methods
|
||||
arr.filter(n => n > 128); // Uint8Array(1) [255]
|
||||
arr.map(n => n * 2); // Uint8Array(8) [0, 2, 4, 6, 8, 10, 12, 14]
|
||||
arr.reduce((acc, n) => acc + n, 0); // 28
|
||||
arr.forEach(n => console.log(n)); // 0 1 2 3 4 5 6 7
|
||||
arr.every(n => n < 10); // true
|
||||
arr.find(n => n > 5); // 6
|
||||
arr.includes(5); // true
|
||||
arr.indexOf(5); // 5
|
||||
```
|
||||
|
||||
Refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) for more information on the properties and methods of typed arrays.
|
||||
|
||||
### `Uint8Array`
|
||||
|
||||
It's worth specifically highlighting `Uint8Array`, as it represents a classic "byte array"—a sequence of 8-bit unsigned integers between 0 and 255. This is the most common typed array you'll encounter in JavaScript.
|
||||
|
||||
It is the return value of [`TextEncoder#encode`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder), and the input type of [`TextDecoder#decode`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder), two utility classes designed to translate strings and various binary encodings, most notably `"utf-8"`.
|
||||
|
||||
```ts
|
||||
const encoder = new TextEncoder();
|
||||
const bytes = encoder.encode("hello world");
|
||||
// => Uint8Array(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ]
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
const text = decoder.decode(bytes);
|
||||
// => hello world
|
||||
```
|
||||
|
||||
### `Buffer`
|
||||
|
||||
Bun implements `Buffer`, a Node.js API for working with binary data that pre-dates the introduction of typed arrays in the JavaScript spec. It has since been re-implemented as a subclass of `Uint8Array`. It provides a wide range of methods, including several Array-like and `DataView`-like methods.
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello world");
|
||||
// => Buffer(16) [ 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103 ]
|
||||
|
||||
buf.length; // => 11
|
||||
buf[0]; // => 104, ascii for 'h'
|
||||
buf.writeUInt8(72, 0); // => ascii for 'H'
|
||||
|
||||
console.log(buf.toString());
|
||||
// => Hello world
|
||||
```
|
||||
|
||||
For complete documentation, refer to the [Node.js documentation](https://nodejs.org/api/buffer.html).
|
||||
|
||||
## `Blob`
|
||||
|
||||
`Blob` is a Web API commonly used for representing files. `Blob` was initially implemented in browsers (unlike `ArrayBuffer` which is part of JavaScript itself), but it is now supported in Node and Bun.
|
||||
|
||||
It isn't common to directly create `Blob` instances. More often, you'll recieve instances of `Blob` from an external source (like an `<input type="file">` element in the browser) or library. That said, it is possible to create a `Blob` from one or more string or binary "blob parts".
|
||||
|
||||
```ts
|
||||
const blob = new Blob(["<html>Hello</html>"], {
|
||||
type: "text/html",
|
||||
});
|
||||
|
||||
blob.type; // => text/html
|
||||
blob.size; // => 19
|
||||
```
|
||||
|
||||
These parts can be `string`, `ArrayBuffer`, `TypedArray`, `DataView`, or other `Blob` instances. The blob parts are concatenated together in the order they are provided.
|
||||
|
||||
```ts
|
||||
const blob = new Blob([
|
||||
"<html>",
|
||||
new Blob(["<body>"]),
|
||||
new Uint8Array([104, 101, 108, 108, 111]), // "hello" in binary
|
||||
"</body></html>",
|
||||
]);
|
||||
```
|
||||
|
||||
The contents of a `Blob` can be asynchronously read in various formats.
|
||||
|
||||
```ts
|
||||
await blob.text(); // => <html><body>hello</body></html>
|
||||
await blob.arrayBuffer(); // => ArrayBuffer (copies contents)
|
||||
await blob.stream(); // => ReadableStream
|
||||
```
|
||||
|
||||
### `BunFile`
|
||||
|
||||
`BunFile` is a subclass of `Blob` used to represent a lazily-loaded file on disk. Like `File`, it adds a `name` and `lastModified` property. Unlike `File`, it does not require the file to be loaded into memory.
|
||||
|
||||
```ts
|
||||
const file = Bun.file("index.txt");
|
||||
// => BunFile
|
||||
```
|
||||
|
||||
### `File`
|
||||
|
||||
{% callout %}
|
||||
Browser only. Experimental support in Node.js 20.
|
||||
{% /callout %}
|
||||
|
||||
[`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) is a subclass of `Blob` that adds a `name` and `lastModified` property. It's commonly used in the browser to represent files uploaded via a `<input type="file">` element. Node.js and Bun implement `File`.
|
||||
|
||||
```ts
|
||||
// on browser!
|
||||
// <input type="file" id="file" />
|
||||
|
||||
const files = document.getElementById("file").files;
|
||||
// => File[]
|
||||
```
|
||||
|
||||
```ts
|
||||
const file = new File(["<html>Hello</html>"], "index.html", {
|
||||
type: "text/html",
|
||||
});
|
||||
```
|
||||
|
||||
Refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Blob) for complete docs information.
|
||||
|
||||
## Streams
|
||||
|
||||
Streams are an important abstraction for working with binary data without loading it all into memory at once. They are commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data.
|
||||
|
||||
Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
||||
|
||||
{% callout %}
|
||||
Bun also implements the `node:stream` module, including [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams), [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams), and [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams). For complete documentation, refer to the Node.js docs.
|
||||
{% /callout %}
|
||||
|
||||
To create a simple readable stream:
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("hello");
|
||||
controller.enqueue("world");
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The contents of this stream can be read chunk-by-chunk with `for await` syntax.
|
||||
|
||||
```ts
|
||||
for await (const chunk of stream) {
|
||||
console.log(chunk);
|
||||
// => "hello"
|
||||
// => "world"
|
||||
}
|
||||
```
|
||||
|
||||
For a more complete discusson of streams in Bun, see [API > Streams](/docs/api/streams).
|
||||
|
||||
## Conversion
|
||||
|
||||
Converting from one binary format to another is a common task. This section is intended as a reference.
|
||||
|
||||
### From `ArrayBuffer`
|
||||
|
||||
Since `ArrayBuffer` stores the data that underlies other binary structures like `TypedArray`, the snippets below are not _converting_ from `ArrayBuffer` to another format. Instead, they are _creating_ a new instance using the data stored underlying data.
|
||||
|
||||
#### To `TypedArray`
|
||||
|
||||
```ts
|
||||
new Uint8Array(buf);
|
||||
```
|
||||
|
||||
#### To `DataView`
|
||||
|
||||
```ts
|
||||
new DataView(buf);
|
||||
```
|
||||
|
||||
#### To `Buffer`
|
||||
|
||||
```ts
|
||||
// create Buffer over entire ArrayBuffer
|
||||
Buffer.from(buf);
|
||||
|
||||
// create Buffer over a slice of the ArrayBuffer
|
||||
Buffer.from(buf, 0, 10);
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
new TextDecoder().decode(buf);
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
Array.from(new Uint8Array(buf));
|
||||
```
|
||||
|
||||
#### To `Blob`
|
||||
|
||||
```ts
|
||||
new Blob([buf], { type: "text/plain" });
|
||||
```
|
||||
|
||||
<!-- #### To `File`
|
||||
|
||||
```ts
|
||||
new File([buf], "filename.txt", { type: "text/plain", lastModified: Date.now() });
|
||||
``` -->
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
The following snippet creates a `ReadableStream` and enqueues the entire `ArrayBuffer` as a single chunk.
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(buf);
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="With chunking" %}
|
||||
To stream the `ArrayBuffer` in chunks, use a `Uint8Array` view and enqueue each chunk.
|
||||
|
||||
```ts
|
||||
const view = new Uint8Array(buf);
|
||||
const chunkSize = 1024;
|
||||
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
for (let i = 0; i < view.length; i += chunkSize) {
|
||||
controller.enqueue(view.slice(i, i + chunkSize));
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### From `TypedArray`
|
||||
|
||||
#### To `ArrayBuffer`
|
||||
|
||||
This retrieves the underlying `ArrayBuffer`. Note that a `TypedArray` can be a view of a _slice_ of the underlying buffer, so the sizes may differ.
|
||||
|
||||
```ts
|
||||
arr.buffer;
|
||||
```
|
||||
|
||||
#### To `DataView`
|
||||
|
||||
To creates a `DataView` over the same byte range as the TypedArray.
|
||||
|
||||
```ts
|
||||
new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
```
|
||||
|
||||
#### To `Buffer`
|
||||
|
||||
```ts
|
||||
Buffer.from(arr);
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
new TextDecoder().decode(arr);
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
Array.from(arr);
|
||||
```
|
||||
|
||||
#### To `Blob`
|
||||
|
||||
```ts
|
||||
new Blob([arr.buffer], { type: "text/plain" });
|
||||
```
|
||||
|
||||
<!-- #### To `File`
|
||||
|
||||
```ts
|
||||
new File([arr.buffer], "filename.txt", { type: "text/plain", lastModified: Date.now() });
|
||||
``` -->
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(arr);
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="With chunking" %}
|
||||
To stream the `ArrayBuffer` in chunks, split the `TypedArray` into chunks and enqueue each one individually.
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
for (let i = 0; i < arr.length; i += chunkSize) {
|
||||
controller.enqueue(arr.slice(i, i + chunkSize));
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### From `DataView`
|
||||
|
||||
#### To `ArrayBuffer`
|
||||
|
||||
```ts
|
||||
view.buffer;
|
||||
```
|
||||
|
||||
#### To `TypedArray`
|
||||
|
||||
Only works if the `byteLength` of the `DataView` is a multiple of the `BYTES_PER_ELEMENT` of the `TypedArray` subclass.
|
||||
|
||||
```ts
|
||||
new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
||||
new Uint16Array(view.buffer, view.byteOffset, view.byteLength / 2);
|
||||
new Uint32Array(view.buffer, view.byteOffset, view.byteLength / 4);
|
||||
// etc...
|
||||
```
|
||||
|
||||
#### To `Buffer`
|
||||
|
||||
```ts
|
||||
Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
new TextDecoder().decode(view);
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
Array.from(view);
|
||||
```
|
||||
|
||||
#### To `Blob`
|
||||
|
||||
```ts
|
||||
new Blob([view.buffer], { type: "text/plain" });
|
||||
```
|
||||
|
||||
<!-- #### To `File`
|
||||
|
||||
```ts
|
||||
new File([view.buffer], "filename.txt", { type: "text/plain", lastModified: Date.now() });
|
||||
``` -->
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(view.buffer);
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="With chunking" %}
|
||||
To stream the `ArrayBuffer` in chunks, split the `DataView` into chunks and enqueue each one individually.
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
for (let i = 0; i < view.byteLength; i += chunkSize) {
|
||||
controller.enqueue(view.buffer.slice(i, i + chunkSize));
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### From `Buffer`
|
||||
|
||||
#### To `ArrayBuffer`
|
||||
|
||||
```ts
|
||||
buf.buffer;
|
||||
```
|
||||
|
||||
#### To `TypedArray`
|
||||
|
||||
```ts
|
||||
new Uint8Array(buf);
|
||||
```
|
||||
|
||||
#### To `DataView`
|
||||
|
||||
```ts
|
||||
new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
buf.toString();
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
Array.from(buf);
|
||||
```
|
||||
|
||||
#### To `Blob`
|
||||
|
||||
```ts
|
||||
new Blob([buf], { type: "text/plain" });
|
||||
```
|
||||
|
||||
<!-- #### To `File`
|
||||
|
||||
```ts
|
||||
new File([buf], "filename.txt", { type: "text/plain", lastModified: Date.now() });
|
||||
``` -->
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(buf);
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="With chunking" %}
|
||||
To stream the `ArrayBuffer` in chunks, split the `Buffer` into chunks and enqueue each one individually.
|
||||
|
||||
```ts
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
for (let i = 0; i < buf.length; i += chunkSize) {
|
||||
controller.enqueue(buf.slice(i, i + chunkSize));
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### From `Blob`
|
||||
|
||||
#### To `ArrayBuffer`
|
||||
|
||||
The `Blob` class provides a convenience method for this purpose.
|
||||
|
||||
```ts
|
||||
await blob.arrayBuffer();
|
||||
```
|
||||
|
||||
#### To `TypedArray`
|
||||
|
||||
```ts
|
||||
new Uint8Array(await blob.arrayBuffer());
|
||||
```
|
||||
|
||||
#### To `DataView`
|
||||
|
||||
```ts
|
||||
new DataView(await blob.arrayBuffer());
|
||||
```
|
||||
|
||||
#### To `Buffer`
|
||||
|
||||
```ts
|
||||
Buffer.from(await blob.arrayBuffer());
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
await blob.text();
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
Array.from(new Uint8Array(await blob.arrayBuffer()));
|
||||
```
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
```ts
|
||||
blob.stream();
|
||||
```
|
||||
|
||||
<!-- ### From `File` -->
|
||||
|
||||
### From `ReadableStream`
|
||||
|
||||
It's common to use [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) as a convenient intermediate representation to make it easier to convert `ReadableStream` to other formats.
|
||||
|
||||
```ts
|
||||
stream; // ReadableStream
|
||||
|
||||
const buffer = new Response(stream).arrayBuffer();
|
||||
```
|
||||
|
||||
However this approach is verbose and adds overhead that slows down overall performance unnecessarily. Bun implements a set of optimized convenience functions for converting `ReadableStream` various binary formats.
|
||||
|
||||
#### To `ArrayBuffer`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
new Response(stream).arrayBuffer();
|
||||
|
||||
// with Bun function
|
||||
Bun.readableStreamToArrayBuffer(stream);
|
||||
```
|
||||
|
||||
#### To `TypedArray`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
const buf = await new Response(stream).arrayBuffer();
|
||||
new Uint8Array(buf);
|
||||
|
||||
// with Bun function
|
||||
new Uint8Array(Bun.readableStreamToArrayBuffer(stream));
|
||||
```
|
||||
|
||||
#### To `DataView`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
const buf = await new Response(stream).arrayBuffer();
|
||||
new DataView(buf);
|
||||
|
||||
// with Bun function
|
||||
new DataView(Bun.readableStreamToArrayBuffer(stream));
|
||||
```
|
||||
|
||||
#### To `Buffer`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
const buf = await new Response(stream).arrayBuffer();
|
||||
Buffer.from(buf);
|
||||
|
||||
// with Bun function
|
||||
Buffer.from(Bun.readableStreamToArrayBuffer(stream));
|
||||
```
|
||||
|
||||
#### To `string`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
new Response(stream).text();
|
||||
|
||||
// with Bun function
|
||||
await Bun.readableStreamToText(stream);
|
||||
```
|
||||
|
||||
#### To `number[]`
|
||||
|
||||
```ts
|
||||
// with Response
|
||||
const buf = await new Response(stream).arrayBuffer();
|
||||
Array.from(new Uint8Array(buf));
|
||||
|
||||
// with Bun function
|
||||
Array.from(new Uint8Array(Bun.readableStreamToArrayBuffer(stream)));
|
||||
```
|
||||
|
||||
Bun provides a utility for resolving a `ReadableStream` to an array of its chunks. Each chunk may be a string, typed array, or `ArrayBuffer`.
|
||||
|
||||
```ts
|
||||
// with Bun function
|
||||
Bun.readableStreamToArray(stream);
|
||||
```
|
||||
|
||||
#### To `Blob`
|
||||
|
||||
```ts
|
||||
new Response(stream).blob();
|
||||
```
|
||||
|
||||
<!-- #### To `File`
|
||||
|
||||
```ts
|
||||
new Response(stream)
|
||||
.blob()
|
||||
.then(blob => new File([blob], "filename.txt", { type: "text/plain", lastModified: Date.now() }));
|
||||
``` -->
|
||||
|
||||
#### To `ReadableStream`
|
||||
|
||||
To split a `ReadableStream` into two streams that can be consumed independently:
|
||||
|
||||
```ts
|
||||
const [a, b] = stream.tee();
|
||||
```
|
||||
|
||||
<!-- - Use Buffer
|
||||
- TextEncoder
|
||||
- `Bun.ArrayBufferSink`
|
||||
- ReadableStream
|
||||
- AsyncIterator
|
||||
- TypedArray vs ArrayBuffer vs DataView
|
||||
- Bun.indexOfLine
|
||||
- “direct” readablestream
|
||||
- readable stream has assumptions about
|
||||
- its very generic
|
||||
- all data is copies and queued
|
||||
- direct : no queueing
|
||||
- just a write function
|
||||
- you can write strings
|
||||
- more synchronous
|
||||
- corking works better -->
|
||||
@@ -1,8 +1,8 @@
|
||||
{% callout %}
|
||||
|
||||
<!-- **Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module. -->
|
||||
<!-- **Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module. -->
|
||||
|
||||
**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
|
||||
**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
@@ -202,6 +202,53 @@ const response = await fetch("https://bun.sh");
|
||||
await Bun.write("index.html", response);
|
||||
```
|
||||
|
||||
## Incremental writing with `FileSink`
|
||||
|
||||
Bun provides a native incremental file writing API called `FileSink`. To retrieve a `FileSink` instance from a `BunFile`:
|
||||
|
||||
```ts
|
||||
const file = Bun.file("output.txt");
|
||||
const writer = file.writer();
|
||||
```
|
||||
|
||||
To incrementally write to the file, call `.write()`.
|
||||
|
||||
```ts
|
||||
const file = Bun.file("output.txt");
|
||||
const writer = file.writer();
|
||||
|
||||
writer.write("it was the best of times\n");
|
||||
writer.write("it was the worst of times\n");
|
||||
```
|
||||
|
||||
These chunks will be buffered internally. To flush the buffer to disk, use `.flush()`. This returns the number of flushed bytes.
|
||||
|
||||
```ts
|
||||
writer.flush(); // write buffer to disk
|
||||
```
|
||||
|
||||
The buffer will also auto-flush when the `FileSink`'s _high water mark_ is reached; that is, when its internal buffer is full. This value can be configured.
|
||||
|
||||
```ts
|
||||
const file = Bun.file("output.txt");
|
||||
const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MB
|
||||
```
|
||||
|
||||
To flush the buffer and close the file:
|
||||
|
||||
```ts
|
||||
writer.end();
|
||||
```
|
||||
|
||||
Note that, by default, the `bun` process will stay alive until this `FileSink` is explicitly closed with `.end()`. To opt out of this behavior, you can "unref" the instance.
|
||||
|
||||
```ts
|
||||
writer.unref();
|
||||
|
||||
// to "re-ref" it later
|
||||
writer.ref();
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
The following is a 3-line implementation of the Linux `cat` command.
|
||||
@@ -238,7 +285,13 @@ interface Bun {
|
||||
|
||||
write(
|
||||
destination: string | number | BunFile | URL,
|
||||
input: string | Blob | ArrayBuffer | SharedArrayBuffer | TypedArray | Response,
|
||||
input:
|
||||
| string
|
||||
| Blob
|
||||
| ArrayBuffer
|
||||
| SharedArrayBuffer
|
||||
| TypedArray
|
||||
| Response,
|
||||
): Promise<number>;
|
||||
}
|
||||
|
||||
@@ -250,5 +303,17 @@ interface BunFile {
|
||||
stream(): Promise<ReadableStream>;
|
||||
arrayBuffer(): Promise<ArrayBuffer>;
|
||||
json(): Promise<any>;
|
||||
writer(params: { highWaterMark?: number }): FileSink;
|
||||
}
|
||||
|
||||
export interface FileSink {
|
||||
write(
|
||||
chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
): number;
|
||||
flush(): number | Promise<number>;
|
||||
end(error?: Error): number | Promise<number>;
|
||||
start(options?: { highWaterMark?: number }): void;
|
||||
ref(): void;
|
||||
unref(): void;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -34,7 +34,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer)
|
||||
- Node.js
|
||||
- See [Node.js > `Buffer`](/docs/runtime/nodejs-apis#node_buffer)
|
||||
- See [Node.js > `Buffer`](/docs/runtime/nodejs-apis#node-buffer)
|
||||
|
||||
---
|
||||
|
||||
@@ -172,7 +172,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`global`](https://nodejs.org/api/globals.html#global)
|
||||
- Node.js
|
||||
- See [Node.js > `global`](/docs/runtime/nodejs-apis#node_global).
|
||||
- See [Node.js > `global`](/docs/runtime/nodejs-apis#global).
|
||||
|
||||
---
|
||||
|
||||
@@ -220,7 +220,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`process`](https://nodejs.org/api/process.html)
|
||||
- Node.js
|
||||
- See [Node.js > `process`](/docs/runtime/nodejs-apis#node_process)
|
||||
- See [Node.js > `process`](/docs/runtime/nodejs-apis#node-process)
|
||||
|
||||
---
|
||||
|
||||
|
||||
205
docs/api/hashing.md
Normal file
205
docs/api/hashing.md
Normal file
@@ -0,0 +1,205 @@
|
||||
{% callout %}
|
||||
|
||||
Bun implements the `createHash` and `createHmac` functions from [`node:crypto`](https://nodejs.org/api/crypto.html) in addition to the Bun-native APIs documented below.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
## `Bun.password`
|
||||
|
||||
{% callout %}
|
||||
**Note** — Added in Bun 0.6.8.
|
||||
{% /callout %}
|
||||
|
||||
`Bun.password` is a collection of utility functions for hashing and verifying passwords with various cryptographically secure algorithms.
|
||||
|
||||
```ts
|
||||
const password = "super-secure-pa$$word";
|
||||
|
||||
const hash = await Bun.password.hash(password);
|
||||
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh6E8DQRhEXg/M/SqYCNu6gVdRRNs$GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4
|
||||
|
||||
const isMatch = await Bun.password.verify(password, hash);
|
||||
// => true
|
||||
```
|
||||
|
||||
The second argument to `Bun.password.hash` accepts a params object that lets you pick and configure the hashing algorithm.
|
||||
|
||||
```ts
|
||||
const password = "super-secure-pa$$word";
|
||||
|
||||
// use argon2 (default)
|
||||
const argonHash = await Bun.password.hash(password, {
|
||||
algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
|
||||
memoryCost: 4, // memory usage in kibibytes
|
||||
timeCost: 3, // the number of iterations
|
||||
});
|
||||
|
||||
// use bcrypt
|
||||
const bcryptHash = await Bun.password.hash(password, {
|
||||
algorithm: "bcrypt",
|
||||
cost: 4, // number between 4-31
|
||||
});
|
||||
```
|
||||
|
||||
The algorithm used to create the hash is stored in the hash itself. When using `bcrypt`, the returned hash is encoded in [Modular Crypt Format](https://passlib.readthedocs.io/en/stable/modular_crypt_format.html) for compatibility with most existing `bcrypt` implementations; with `argon2` the result is encoded in the newer [PHC format](https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md).
|
||||
|
||||
The `verify` function automatically detects the algorithm based on the input hash and use the correct verification method. It can correctly infer the algorithm from both PHC- or MCF-encoded hashes.
|
||||
|
||||
```ts
|
||||
const password = "super-secure-pa$$word";
|
||||
|
||||
const hash = await Bun.password.hash(password, {
|
||||
/* config */
|
||||
});
|
||||
|
||||
const isMatch = await Bun.password.verify(password, hash);
|
||||
// => true
|
||||
```
|
||||
|
||||
Synchronous versions of all functions are also available. Keep in mind that these functions are computationally expensive, so using a blocking API may degrade application performance.
|
||||
|
||||
```ts
|
||||
const password = "super-secure-pa$$word";
|
||||
|
||||
const hash = Bun.password.hashSync(password, {
|
||||
/* config */
|
||||
});
|
||||
|
||||
const isMatch = Bun.password.verifySync(password, hash);
|
||||
// => true
|
||||
```
|
||||
|
||||
## `Bun.hash`
|
||||
|
||||
`Bun.hash` is a collection of utilities for _non-cryptographic_ hashing. Non-cryptographic hashing algorithms are optimized for speed of computation over collision-resistance or security.
|
||||
|
||||
The standard `Bun.hash` functions uses [Wyhash](https://github.com/wangyi-fudan/wyhash) to generate a 64-bit hash from an input of arbitrary size.
|
||||
|
||||
```ts
|
||||
Bun.hash("some data here");
|
||||
// 11562320457524636935n
|
||||
```
|
||||
|
||||
The input can be a string, `TypedArray`, `DataView`, `ArrayBuffer`, or `SharedArrayBuffer`.
|
||||
|
||||
```ts
|
||||
const arr = new Uint8Array([1, 2, 3, 4]);
|
||||
|
||||
Bun.hash("some data here");
|
||||
Bun.hash(arr);
|
||||
Bun.hash(arr.buffer);
|
||||
Bun.hash(new DataView(arr.buffer));
|
||||
```
|
||||
|
||||
Optionally, an integer seed can be specified as the second parameter. For 64-bit hashes seeds above `Number.MAX_SAFE_INTEGER` should be given as BigInt to avoid loss of precision.
|
||||
|
||||
```ts
|
||||
Bun.hash("some data here", 1234);
|
||||
// 15724820720172937558n
|
||||
```
|
||||
|
||||
Additional hashing algorithms are available as properties on `Bun.hash`. The API is the same for each, only changing the return type from number for 32-bit hashes to bigint for 64-bit hashes.
|
||||
|
||||
```ts
|
||||
Bun.hash.wyhash("data", 1234); // equivalent to Bun.hash()
|
||||
Bun.hash.crc32("data", 1234);
|
||||
Bun.hash.adler32("data", 1234);
|
||||
Bun.hash.cityHash32("data", 1234);
|
||||
Bun.hash.cityHash64("data", 1234);
|
||||
Bun.hash.murmur32v3("data", 1234);
|
||||
Bun.hash.murmur32v2("data", 1234);
|
||||
Bun.hash.murmur64v2("data", 1234);
|
||||
```
|
||||
|
||||
## `Bun.CryptoHasher`
|
||||
|
||||
`Bun.CryptoHasher` is a general-purpose utility class that lets you incrementally compute a hash of string or binary data using a range of cryptographic hash algorithms. The following algorithms are supported:
|
||||
|
||||
- `"blake2b256"`
|
||||
- `"md4"`
|
||||
- `"md5"`
|
||||
- `"ripemd160"`
|
||||
- `"sha1"`
|
||||
- `"sha224"`
|
||||
- `"sha256"`
|
||||
- `"sha384"`
|
||||
- `"sha512"`
|
||||
- `"sha512-256"`
|
||||
|
||||
```ts
|
||||
const hasher = new Bun.CryptoHasher("sha256");
|
||||
hasher.update("hello world");
|
||||
hasher.digest();
|
||||
// Uint8Array(32) [ <byte>, <byte>, ... ]
|
||||
```
|
||||
|
||||
Once initialized, data can be incrementally fed to to the hasher using `.update()`. This method accepts `string`, `TypedArray`, and `ArrayBuffer`.
|
||||
|
||||
```ts
|
||||
const hasher = new Bun.CryptoHasher();
|
||||
|
||||
hasher.update("hello world");
|
||||
hasher.update(new Uint8Array([1, 2, 3]));
|
||||
hasher.update(new ArrayBuffer(10));
|
||||
```
|
||||
|
||||
If a `string` is passed, an optional second parameter can be used to specify the encoding (default `'utf-8'`). The following encodings are supported:
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- Binary encodings
|
||||
- `"base64"` `"base64url"` `"hex"` `"binary"`
|
||||
|
||||
---
|
||||
|
||||
- Character encodings
|
||||
- `"utf8"` `"utf-8"` `"utf16le"` `"latin1"`
|
||||
|
||||
---
|
||||
|
||||
- Legacy character encodings
|
||||
- `"ascii"` `"binary"` `"ucs2"` `"ucs-2"`
|
||||
|
||||
{% /table %}
|
||||
|
||||
```ts
|
||||
hasher.update("hello world"); // defaults to utf8
|
||||
hasher.update("hello world", "hex");
|
||||
hasher.update("hello world", "base64");
|
||||
hasher.update("hello world", "latin1");
|
||||
```
|
||||
|
||||
After the data has been feed into the hasher, a final hash can be computed using `.digest()`. By default, this method returns a `Uint8Array` containing the hash.
|
||||
|
||||
```ts
|
||||
const hasher = new Bun.CryptoHasher();
|
||||
hasher.update("hello world");
|
||||
|
||||
hasher.digest();
|
||||
// => Uint8Array(32) [ 185, 77, 39, 185, 147, ... ]
|
||||
```
|
||||
|
||||
The `.digest()` method can optionally return the hash as a string. To do so, specify an encoding:
|
||||
|
||||
```ts
|
||||
hasher.digest("base64");
|
||||
// => "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="
|
||||
|
||||
hasher.digest("hex");
|
||||
// => "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
||||
```
|
||||
|
||||
Alternatively, the method can write the hash into a pre-existing `TypedArray` instance. This may be desirable in some performance-sensitive applications.
|
||||
|
||||
```ts
|
||||
const arr = new Uint8Array(32);
|
||||
|
||||
hasher.digest(arr);
|
||||
|
||||
console.log(arr);
|
||||
// => Uint8Array(32) [ 185, 77, 39, 185, 147, ... ]
|
||||
```
|
||||
|
||||
<!-- Bun.sha; -->
|
||||
133
docs/api/http.md
133
docs/api/http.md
@@ -1,19 +1,12 @@
|
||||
The page primarily documents the Bun-native `Bun.serve` API. Bun also implements [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) and the Node.js [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html) modules.
|
||||
|
||||
{% callout %}
|
||||
**Note** — This page documents the `Bun.serve` API. This API is heavily optimized and represents the recommended way to build HTTP servers in Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_http) implementation of the Node.js [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html) modules.
|
||||
These modules have been re-implemented to use Bun's fast internal HTTP infrastructure. Feel free to use these modules directly; frameworks like [Express](https://expressjs.com/) that depend on these modules should work out of the box. For granular compatibility information, see [Runtime > Node.js APIs](/docs/runtime/nodejs-apis).
|
||||
{% /callout %}
|
||||
|
||||
## Send a request (`fetch()`)
|
||||
To start a high-performance HTTP server with a clean API, the recommended approach is [`Bun.serve`](#start-a-server-bun-serve).
|
||||
|
||||
Bun implements the Web `fetch` API for making HTTP requests. The `fetch` function is available in the global scope.
|
||||
|
||||
```ts
|
||||
const response = await fetch("https://bun.sh/manifest.json");
|
||||
const result = (await response.json()) as any;
|
||||
console.log(result.icons[0].src);
|
||||
// => "/logo-square.jpg"
|
||||
```
|
||||
|
||||
## Start a server (`Bun.serve()`)
|
||||
## `Bun.serve()`
|
||||
|
||||
Start an HTTP server in Bun with `Bun.serve`.
|
||||
|
||||
@@ -50,7 +43,7 @@ Bun.serve({
|
||||
});
|
||||
```
|
||||
|
||||
### Error handling
|
||||
## Error handling
|
||||
|
||||
To activate development mode, set `development: true`. By default, development mode is _enabled_ unless `NODE_ENV` is `production`.
|
||||
|
||||
@@ -74,7 +67,7 @@ Bun.serve({
|
||||
fetch(req) {
|
||||
throw new Error("woops!");
|
||||
},
|
||||
error(error: Error) {
|
||||
error(error) {
|
||||
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
|
||||
headers: {
|
||||
"Content-Type": "text/html",
|
||||
@@ -100,36 +93,92 @@ const server = Bun.serve({
|
||||
server.stop();
|
||||
```
|
||||
|
||||
### TLS
|
||||
## TLS
|
||||
|
||||
Bun supports TLS out of the box, powered by [OpenSSL](https://www.openssl.org/). Enable TLS by passing in a value for `keyFile` and `certFile`; both are required to enable TLS. If needed, supply a `passphrase` to decrypt the `keyFile`.
|
||||
Bun supports TLS out of the box, powered by [BoringSSL](https://boringssl.googlesource.com/boringssl). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS.
|
||||
|
||||
```ts-diff
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
},
|
||||
|
||||
+ tls: {
|
||||
+ key: Bun.file("./key.pem"),
|
||||
+ cert: Bun.file("./cert.pem"),
|
||||
+ }
|
||||
});
|
||||
```
|
||||
|
||||
The `key` and `cert` fields expect the _contents_ of your TLS key and certificate, _not a path to it_. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
fetch() {},
|
||||
|
||||
tls: {
|
||||
// BunFile
|
||||
key: Bun.file("./key.pem"),
|
||||
// Buffer
|
||||
key: fs.readFileSync("./key.pem"),
|
||||
// string
|
||||
key: fs.readFileSync("./key.pem", "utf8"),
|
||||
// array of above
|
||||
key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
|
||||
},
|
||||
keyFile: "./key.pem", // path to TLS key
|
||||
certFile: "./cert.pem", // path to TLS cert
|
||||
passphrase: "super-secret", // optional passphrase
|
||||
});
|
||||
```
|
||||
|
||||
The root CA and Diffie-Helman parameters can be configured as well.
|
||||
{% callout %}
|
||||
|
||||
**Note** — Earlier versions of Bun supported passing a file path as `keyFile` and `certFile`; this has been deprecated as of `v0.6.3`.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
If your private key is encrypted with a passphrase, provide a value for `passphrase` to decrypt it.
|
||||
|
||||
```ts-diff
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
},
|
||||
|
||||
tls: {
|
||||
key: Bun.file("./key.pem"),
|
||||
cert: Bun.file("./cert.pem"),
|
||||
+ passphrase: "my-secret-passphrase",
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Optionally, you can override the trusted CA certificates by passing a value for `ca`. By default, the server will trust the list of well-known CAs curated by Mozilla. When `ca` is specified, the Mozilla list is overwritten.
|
||||
|
||||
```ts-diff
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
},
|
||||
tls: {
|
||||
key: Bun.file("./key.pem"), // path to TLS key
|
||||
cert: Bun.file("./cert.pem"), // path to TLS cert
|
||||
+ ca: Bun.file("./ca.pem"), // path to root CA certificate
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
To override Diffie-Helman parameters:
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!!!");
|
||||
// ...
|
||||
tls: {
|
||||
// other config
|
||||
dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Helman parameters
|
||||
},
|
||||
keyFile: "./key.pem", // path to TLS key
|
||||
certFile: "./cert.pem", // path to TLS cert
|
||||
caFile: "./ca.pem", // path to root CA certificate
|
||||
dhParamsFile: "./dhparams.pem", // Diffie Helman parameters
|
||||
});
|
||||
```
|
||||
|
||||
### Hot reloading
|
||||
## Hot reloading
|
||||
|
||||
Thus far, the examples on this page have used the explicit `Bun.serve` API. Bun also supports an alternate syntax.
|
||||
|
||||
@@ -153,7 +202,7 @@ $ bun --hot server.ts
|
||||
|
||||
It's possible to configure hot reloading while using the explicit `Bun.serve` API; for details refer to [Runtime > Hot reloading](/docs/runtime/hot).
|
||||
|
||||
### Streaming files
|
||||
## Streaming files
|
||||
|
||||
To stream a file, return a `Response` object with a `BunFile` object as the body.
|
||||
|
||||
@@ -191,7 +240,7 @@ Bun.serve({
|
||||
});
|
||||
```
|
||||
|
||||
### Benchmarks
|
||||
## Benchmarks
|
||||
|
||||
Below are Bun and Node.js implementations of a simple HTTP server that responds `Bun!` to each incoming `Request`.
|
||||
|
||||
@@ -234,7 +283,7 @@ The `Bun.serve` server can handle roughly 2.5x more requests per second than Nod
|
||||
|
||||
{% image width="499" alt="image" src="https://user-images.githubusercontent.com/709451/162389032-fc302444-9d03-46be-ba87-c12bd8ce89a0.png" /%}
|
||||
|
||||
### Reference
|
||||
## Reference
|
||||
|
||||
{% details summary="See TypeScript definitions" %}
|
||||
|
||||
@@ -246,11 +295,21 @@ interface Bun {
|
||||
port?: number;
|
||||
development?: boolean;
|
||||
error?: (error: Error) => Response | Promise<Response>;
|
||||
keyFile?: string;
|
||||
certFile?: string;
|
||||
caFile?: string;
|
||||
dhParamsFile?: string;
|
||||
passphrase?: string;
|
||||
tls?: {
|
||||
key?:
|
||||
| string
|
||||
| TypedArray
|
||||
| BunFile
|
||||
| Array<string | TypedArray | BunFile>;
|
||||
cert?:
|
||||
| string
|
||||
| TypedArray
|
||||
| BunFile
|
||||
| Array<string | TypedArray | BunFile>;
|
||||
ca?: string | TypedArray | BunFile | Array<string | TypedArray | BunFile>;
|
||||
passphrase?: string;
|
||||
dhParamsFile?: string;
|
||||
};
|
||||
maxRequestBodySize?: number;
|
||||
lowMemoryMode?: boolean;
|
||||
}): Server;
|
||||
|
||||
52
docs/api/import-meta.md
Normal file
52
docs/api/import-meta.md
Normal file
@@ -0,0 +1,52 @@
|
||||
The `import.meta` object is a way for a module to access information about itself. It's part of the JavaScript language, but its contents are not standardized. Each "host" (browser, runtime, etc) is free to implement any properties it wishes on the `import.meta` object.
|
||||
|
||||
Bun implements the following properties.
|
||||
|
||||
```ts#/path/to/project/file.ts
|
||||
import.meta.dir; // => "/path/to/project"
|
||||
import.meta.file; // => "file.ts"
|
||||
import.meta.path; // => "/path/to/project/file.ts"
|
||||
|
||||
import.meta.main; // `true` if this file is directly executed by `bun run`
|
||||
// `false` otherwise
|
||||
|
||||
import.meta.resolveSync("zod")
|
||||
// resolve an import specifier relative to the directory
|
||||
```
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- `import.meta.dir`
|
||||
- Absolute path to the directory containing the current file, e.g. `/path/to/project`. Equivalent to `__dirname` in CommonJS modules (and Node.js)
|
||||
|
||||
---
|
||||
|
||||
- `import.meta.file`
|
||||
- The name of the current file, e.g. `index.tsx`
|
||||
|
||||
---
|
||||
|
||||
- `import.meta.path`
|
||||
- Absolute path to the current file, e.g. `/path/to/project/index.tx`. Equivalent to `__filename` in CommonJS modules (and Node.js)
|
||||
|
||||
---
|
||||
|
||||
- `import.meta.main`
|
||||
- `boolean` Indicates whether the current file is the entrypoint to the current `bun` process. Is the file being directly executed by `bun run` or is it being imported?
|
||||
|
||||
---
|
||||
|
||||
- `import.meta.resolve{Sync}`
|
||||
- Resolve a module specifier (e.g. `"zod"` or `"./file.tsx`) to an absolute path. While file would be imported if the specifier were imported from this file?
|
||||
|
||||
```ts
|
||||
import.meta.resolveSync("zod");
|
||||
// => "/path/to/project/node_modules/zod/index.ts"
|
||||
|
||||
import.meta.resolveSync("./file.tsx");
|
||||
// => "/path/to/project/file.tsx"
|
||||
```
|
||||
|
||||
{% /table %}
|
||||
@@ -12,7 +12,7 @@ The second argument to `Bun.spawn` is a parameters object that can be used to co
|
||||
|
||||
```ts
|
||||
const proc = Bun.spawn(["echo", "hello"], {
|
||||
cwd: "./path/to/subdir", // specify a working direcory
|
||||
cwd: "./path/to/subdir", // specify a working directory
|
||||
env: { ...process.env, FOO: "bar" }, // specify environment variables
|
||||
onExit(proc, exitCode, signalCode, error) {
|
||||
// exit handler
|
||||
|
||||
@@ -74,8 +74,8 @@ Note: `close()` is called automatically when the database is garbage collected.
|
||||
|
||||
```ts
|
||||
const olddb = new Database("mydb.sqlite");
|
||||
const contents = db.serialize(); // => Uint8Array
|
||||
const newdb = new Database(contents);
|
||||
const contents = olddb.serialize(); // => Uint8Array
|
||||
const newdb = Database.deserialize(contents);
|
||||
```
|
||||
|
||||
Internally, `.serialize()` calls [`sqlite3_serialize`](https://www.sqlite.org/c3ref/serialize.html).
|
||||
@@ -250,7 +250,7 @@ Transactions are a mechanism for executing multiple queries in an _atomic_ way;
|
||||
|
||||
```ts
|
||||
const insertCat = db.prepare("INSERT INTO cats (name) VALUES ($name)");
|
||||
const insertCats = db.transaction((cats) => {
|
||||
const insertCats = db.transaction(cats => {
|
||||
for (const cat of cats) insertCat.run(cat);
|
||||
});
|
||||
```
|
||||
@@ -261,7 +261,7 @@ To execute the transaction, call this function. All arguments will be passed thr
|
||||
|
||||
```ts
|
||||
const insert = db.prepare("INSERT INTO cats (name) VALUES ($name)");
|
||||
const insertCats = db.transaction((cats) => {
|
||||
const insertCats = db.transaction(cats => {
|
||||
for (const cat of cats) insert.run(cat);
|
||||
return cats.length;
|
||||
});
|
||||
@@ -296,11 +296,11 @@ const insertExpense = db.prepare(
|
||||
"INSERT INTO expenses (note, dollars) VALUES (?, ?)",
|
||||
);
|
||||
const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)");
|
||||
const insertCats = db.transaction((cats) => {
|
||||
const insertCats = db.transaction(cats => {
|
||||
for (const cat of cats) insert.run(cat);
|
||||
});
|
||||
|
||||
const adopt = db.transaction((cats) => {
|
||||
const adopt = db.transaction(cats => {
|
||||
insertExpense.run("adoption fees", 20);
|
||||
insertCats(cats); // nested transaction
|
||||
});
|
||||
|
||||
172
docs/api/streams.md
Normal file
172
docs/api/streams.md
Normal file
@@ -0,0 +1,172 @@
|
||||
Streams are an important abstraction for working with binary data without loading it all into memory at once. They are commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data.
|
||||
|
||||
Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream).
|
||||
|
||||
{% callout %}
|
||||
Bun also implements the `node:stream` module, including [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams), [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams), and [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams). For complete documentation, refer to the [Node.js docs](https://nodejs.org/api/stream.html).
|
||||
{% /callout %}
|
||||
|
||||
To create a simple `ReadableStream`:
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("hello");
|
||||
controller.enqueue("world");
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The contents of a `ReadableStream` can be read chunk-by-chunk with `for await` syntax.
|
||||
|
||||
```ts
|
||||
for await (const chunk of stream) {
|
||||
console.log(chunk);
|
||||
// => "hello"
|
||||
// => "world"
|
||||
}
|
||||
```
|
||||
|
||||
## Direct `ReadableStream`
|
||||
|
||||
Bun implements an optimized version of `ReadableStream` that avoid unnecessary data copying & queue management logic. With a traditional `ReadableStream`, chunks of data are _enqueued_. Each chunk is copied into a queue, where it sits until the stream is ready to send more data.
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("hello");
|
||||
controller.enqueue("world");
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
With a direct `ReadableStream`, chunks of data are written directly to the stream. No queueing happens, and there's no need to clone the chunk data into memory. The `controller` API is updated to reflect this; instead of `.enqueue()` you call `.write`.
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
type: "direct",
|
||||
pull(controller) {
|
||||
controller.write("hello");
|
||||
controller.write("world");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When using a direct `ReadableStream`, all chunk queueing is handled by the destination. The consumer of the stream receives exactly what is passed to `controller.write()`, without any encoding or modification.
|
||||
|
||||
## `Bun.ArrayBufferSink`
|
||||
|
||||
The `Bun.ArrayBufferSink` class is a fast incremental writer for constructing an `ArrayBuffer` of unknown size.
|
||||
|
||||
```ts
|
||||
const sink = new Bun.ArrayBufferSink();
|
||||
|
||||
sink.write("h");
|
||||
sink.write("e");
|
||||
sink.write("l");
|
||||
sink.write("l");
|
||||
sink.write("o");
|
||||
|
||||
sink.end();
|
||||
// ArrayBuffer(5) [ 104, 101, 108, 108, 111 ]
|
||||
```
|
||||
|
||||
To instead retrieve the data as a `Uint8Array`, pass the `asUint8Array` option to the constructor.
|
||||
|
||||
```ts-diff
|
||||
const sink = new Bun.ArrayBufferSink({
|
||||
+ asUint8Array: true
|
||||
});
|
||||
|
||||
sink.write("h");
|
||||
sink.write("e");
|
||||
sink.write("l");
|
||||
sink.write("l");
|
||||
sink.write("o");
|
||||
|
||||
sink.end();
|
||||
// Uint8Array(5) [ 104, 101, 108, 108, 111 ]
|
||||
```
|
||||
|
||||
The `.write()` method supports strings, typed arrays, `ArrayBuffer`, and `SharedArrayBuffer`.
|
||||
|
||||
```ts
|
||||
sink.write("h");
|
||||
sink.write(new Uint8Array([101, 108]));
|
||||
sink.write(Buffer.from("lo").buffer);
|
||||
|
||||
sink.end();
|
||||
```
|
||||
|
||||
Once `.end()` is called, no more data can be written to the `ArrayBufferSink`. However, in the context of buffering a stream, it's useful to continuously write data and periodically `.flush()` the contents (say, into a `WriteableStream`). To support this, pass `stream: true` to the constructor.
|
||||
|
||||
```ts
|
||||
const sink = new Bun.ArrayBufferSink({
|
||||
stream: true,
|
||||
});
|
||||
|
||||
sink.write("h");
|
||||
sink.write("e");
|
||||
sink.write("l");
|
||||
sink.flush();
|
||||
// ArrayBuffer(5) [ 104, 101, 108 ]
|
||||
|
||||
sink.write("l");
|
||||
sink.write("o");
|
||||
sink.flush();
|
||||
// ArrayBuffer(5) [ 108, 111 ]
|
||||
```
|
||||
|
||||
The `.flush()` method returns the buffered data as an `ArrayBuffer` (or `Uint8Array` if `asUint8Array: true`) and clears internal buffer.
|
||||
|
||||
To manually set the size of the internal buffer in bytes, pass a value for `highWaterMark`:
|
||||
|
||||
```ts
|
||||
const sink = new Bun.ArrayBufferSink({
|
||||
highWaterMark: 1024 * 1024, // 1 MB
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="Reference" %}
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Fast incremental writer that becomes an `ArrayBuffer` on end().
|
||||
*/
|
||||
export class ArrayBufferSink {
|
||||
constructor();
|
||||
|
||||
start(options?: {
|
||||
asUint8Array?: boolean;
|
||||
/**
|
||||
* Preallocate an internal buffer of this size
|
||||
* This can significantly improve performance when the chunk size is small
|
||||
*/
|
||||
highWaterMark?: number;
|
||||
/**
|
||||
* On {@link ArrayBufferSink.flush}, return the written data as a `Uint8Array`.
|
||||
* Writes will restart from the beginning of the buffer.
|
||||
*/
|
||||
stream?: boolean;
|
||||
}): void;
|
||||
|
||||
write(
|
||||
chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
): number;
|
||||
/**
|
||||
* Flush the internal buffer
|
||||
*
|
||||
* If {@link ArrayBufferSink.start} was passed a `stream` option, this will return a `ArrayBuffer`
|
||||
* If {@link ArrayBufferSink.start} was passed a `stream` option and `asUint8Array`, this will return a `Uint8Array`
|
||||
* Otherwise, this will return the number of bytes written since the last flush
|
||||
*
|
||||
* This API might change later to separate Uint8ArraySink and ArrayBufferSink
|
||||
*/
|
||||
flush(): number | Uint8Array | ArrayBuffer;
|
||||
end(): ArrayBuffer | Uint8Array;
|
||||
}
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
@@ -59,7 +59,7 @@ Bun.listen<SocketData>({
|
||||
});
|
||||
```
|
||||
|
||||
To enable TLS, pass a `tls` object containing `keyFile` and `certFile` properties.
|
||||
To enable TLS, pass a `tls` object containing `key` and `cert` fields.
|
||||
|
||||
```ts
|
||||
Bun.listen({
|
||||
@@ -69,13 +69,38 @@ Bun.listen({
|
||||
data(socket, data) {},
|
||||
},
|
||||
tls: {
|
||||
certFile: "cert.pem",
|
||||
keyFile: "key.pem",
|
||||
// can be string, BunFile, TypedArray, Buffer, or array thereof
|
||||
key: Bun.file("./key.pem"),
|
||||
cert: Bun.file("./cert.pem"),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The result of `Bun.listen` is a server that conforms to the `TCPSocket` instance.
|
||||
{% callout %}
|
||||
|
||||
**Note** — Earlier versions of Bun supported passing a file path as `keyFile` and `certFile`; this has been deprecated as of `v0.6.3`.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
The `key` and `cert` fields expect the _contents_ of your TLS key and certificate. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
|
||||
|
||||
```ts
|
||||
Bun.listen({
|
||||
// ...
|
||||
tls: {
|
||||
// BunFile
|
||||
key: Bun.file("./key.pem"),
|
||||
// Buffer
|
||||
key: fs.readFileSync("./key.pem"),
|
||||
// string
|
||||
key: fs.readFileSync("./key.pem", "utf8"),
|
||||
// array of above
|
||||
key: [Bun.file('./key1.pem'), Bun.file('./key2.pem']
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The result of `Bun.listen` is a server that conforms to the `TCPSocket` interface.
|
||||
|
||||
```ts
|
||||
const server = Bun.listen({
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
## `Bun.sleep`
|
||||
## `Bun.version`
|
||||
|
||||
A `string` containing the version of the `bun` CLI that is currently running.
|
||||
|
||||
```ts
|
||||
Bun.version;
|
||||
// => "0.6.4"
|
||||
```
|
||||
|
||||
## `Bun.revision`
|
||||
|
||||
The git commit of [Bun](https://github.com/oven-sh/bun) that was compiled to create the current `bun` CLI.
|
||||
|
||||
```ts
|
||||
Bun.revision;
|
||||
// => "f02561530fda1ee9396f51c8bc99b38716e38296"
|
||||
```
|
||||
|
||||
## `Bun.env`
|
||||
|
||||
An alias for `process.env`.
|
||||
|
||||
## `Bun.main`
|
||||
|
||||
An absolute path to the entrypoint of the current program (the file that was executed with `bun run`).
|
||||
|
||||
```ts#script.ts
|
||||
Bun.main;
|
||||
// /path/to/script.ts
|
||||
```
|
||||
|
||||
This is particular useful for determining whether a script is being directly executed, as opposed to being imported by another script.
|
||||
|
||||
```ts
|
||||
if (import.meta.path === Bun.main) {
|
||||
// this script is being directly executed
|
||||
} else {
|
||||
// this file is being imported from another script
|
||||
}
|
||||
```
|
||||
|
||||
This is analogous to the [`require.main = module` trick](https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line) in Node.js.
|
||||
|
||||
## `Bun.sleep()`
|
||||
|
||||
`Bun.sleep(ms: number)` (added in Bun v0.5.6)
|
||||
|
||||
@@ -20,11 +63,23 @@ await Bun.sleep(oneSecondInFuture);
|
||||
console.log("hello one second later!");
|
||||
```
|
||||
|
||||
## `Bun.which`
|
||||
## `Bun.sleepSync()`
|
||||
|
||||
`Bun.sleepSync(ms: number)` (added in Bun v0.5.6)
|
||||
|
||||
A blocking synchronous version of `Bun.sleep`.
|
||||
|
||||
```ts
|
||||
console.log("hello");
|
||||
Bun.sleepSync(1000); // blocks thread for one second
|
||||
console.log("hello one second later!");
|
||||
```
|
||||
|
||||
## `Bun.which()`
|
||||
|
||||
`Bun.which(bin: string)`
|
||||
|
||||
Find the path to an executable, similar to typing `which` in your terminal.
|
||||
Returns the path to an executable, similar to typing `which` in your terminal.
|
||||
|
||||
```ts
|
||||
const ls = Bun.which("ls");
|
||||
@@ -51,11 +106,11 @@ const ls = Bun.which("ls", {
|
||||
console.log(ls); // null
|
||||
```
|
||||
|
||||
## `Bun.peek`
|
||||
## `Bun.peek()`
|
||||
|
||||
`Bun.peek(prom: Promise)` (added in Bun v0.2.2)
|
||||
|
||||
`Bun.peek` is a utility function that lets you read a promise's result without `await` or `.then`, but only if the promise has already fulfilled or rejected.
|
||||
Reads a promise's result without `await` or `.then`, but only if the promise has already fulfilled or rejected.
|
||||
|
||||
```ts
|
||||
import { peek } from "bun";
|
||||
@@ -94,7 +149,9 @@ test("peek", () => {
|
||||
// If we peek a rejected promise, it:
|
||||
// - returns the error
|
||||
// - does not mark the promise as handled
|
||||
const rejected = Promise.reject(new Error("Successfully tested promise rejection"));
|
||||
const rejected = Promise.reject(
|
||||
new Error("Successfully tested promise rejection"),
|
||||
);
|
||||
expect(peek(rejected).message).toBe("Successfully tested promise rejection");
|
||||
});
|
||||
```
|
||||
@@ -117,9 +174,9 @@ test("peek.status", () => {
|
||||
});
|
||||
```
|
||||
|
||||
## `Bun.openInEditor`
|
||||
## `Bun.openInEditor()`
|
||||
|
||||
Open a file in your default editor. Bun auto-detects your editor via the `$VISUAL` or `$EDITOR` environment variables.
|
||||
Opens a file in your default editor. Bun auto-detects your editor via the `$VISUAL` or `$EDITOR` environment variables.
|
||||
|
||||
```ts
|
||||
const currentFile = import.meta.url;
|
||||
@@ -142,3 +199,310 @@ Bun.openInEditor(import.meta.url, {
|
||||
column: 5,
|
||||
});
|
||||
```
|
||||
|
||||
Bun.ArrayBufferSink;
|
||||
|
||||
## `Bun.deepEquals()`
|
||||
|
||||
Nestedly checks if two objects are equivalent. This is used internally by `expect().toEqual()` in `bun:test`.
|
||||
|
||||
```ts
|
||||
const foo = { a: 1, b: 2, c: { d: 3 } };
|
||||
|
||||
// true
|
||||
Bun.deepEquals(foo, { a: 1, b: 2, c: { d: 3 } });
|
||||
|
||||
// false
|
||||
Bun.deepEquals(foo, { a: 1, b: 2, c: { d: 4 } });
|
||||
```
|
||||
|
||||
A third boolean parameter can be used to enable "strict" mode. This is used by `expect().toStrictEqual()` in the test runner.
|
||||
|
||||
```ts
|
||||
const a = { entries: [1, 2] };
|
||||
const b = { entries: [1, 2], extra: undefined };
|
||||
|
||||
Bun.deepEquals(a, b); // => true
|
||||
Bun.deepEquals(a, b, true); // => false
|
||||
```
|
||||
|
||||
In strict mode, the following are considered unequal:
|
||||
|
||||
```ts
|
||||
// undefined values
|
||||
Bun.deepEquals({}, { a: undefined }, true); // false
|
||||
|
||||
// undefined in arrays
|
||||
Bun.deepEquals(["asdf"], ["asdf", undefined], true); // false
|
||||
|
||||
// sparse arrays
|
||||
Bun.deepEquals([, 1], [undefined, 1], true); // false
|
||||
|
||||
// object literals vs instances w/ same properties
|
||||
class Foo {
|
||||
a = 1;
|
||||
}
|
||||
Bun.deepEquals(new Foo(), { a: 1 }, true); // false
|
||||
```
|
||||
|
||||
## `Bun.escapeHTML()`
|
||||
|
||||
`Bun.escapeHTML(value: string | object | number | boolean): string`
|
||||
|
||||
Escapes the following characters from an input string:
|
||||
|
||||
- `"` becomes `"""`
|
||||
- `&` becomes `"&"`
|
||||
- `'` becomes `"'"`
|
||||
- `<` becomes `"<"`
|
||||
- `>` becomes `">"`
|
||||
|
||||
This function is optimized for large input. On an M1X, it processes 480 MB/s -
|
||||
20 GB/s, depending on how much data is being escaped and whether there is non-ascii
|
||||
text. Non-string types will be converted to a string before escaping.
|
||||
|
||||
<!-- ## `Bun.enableANSIColors()` -->
|
||||
|
||||
## `Bun.fileURLToPath()`
|
||||
|
||||
Converts a `file://` URL to an absolute path.
|
||||
|
||||
```ts
|
||||
const path = Bun.fileURLToPath(new URL("file:///foo/bar.txt"));
|
||||
console.log(path); // "/foo/bar.txt"
|
||||
```
|
||||
|
||||
## `Bun.pathToFileURL()`
|
||||
|
||||
Converts an absolute path to a `file://` URL.
|
||||
|
||||
```ts
|
||||
const url = Bun.pathToFileURL("/foo/bar.txt");
|
||||
console.log(url); // "file:///foo/bar.txt"
|
||||
```
|
||||
|
||||
<!-- Bun.hash; -->
|
||||
|
||||
## `Bun.gzipSync()`
|
||||
|
||||
Compresses a `Uint8Array` using zlib's GZIP algorithm.
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello".repeat(100)); // Buffer extends Uint8Array
|
||||
const compressed = Bun.gzipSync(buf);
|
||||
|
||||
buf; // => Uint8Array(500)
|
||||
compressed; // => Uint8Array(30)
|
||||
```
|
||||
|
||||
Optionally, pass a parameters object as the second argument:
|
||||
|
||||
{% details summary="zlib compression options"%}
|
||||
|
||||
```ts
|
||||
export type ZlibCompressionOptions = {
|
||||
/**
|
||||
* The compression level to use. Must be between `-1` and `9`.
|
||||
* - A value of `-1` uses the default compression level (Currently `6`)
|
||||
* - A value of `0` gives no compression
|
||||
* - A value of `1` gives least compression, fastest speed
|
||||
* - A value of `9` gives best compression, slowest speed
|
||||
*/
|
||||
level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
||||
/**
|
||||
* How much memory should be allocated for the internal compression state.
|
||||
*
|
||||
* A value of `1` uses minimum memory but is slow and reduces compression ratio.
|
||||
*
|
||||
* A value of `9` uses maximum memory for optimal speed. The default is `8`.
|
||||
*/
|
||||
memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
||||
/**
|
||||
* The base 2 logarithm of the window size (the size of the history buffer).
|
||||
*
|
||||
* Larger values of this parameter result in better compression at the expense of memory usage.
|
||||
*
|
||||
* The following value ranges are supported:
|
||||
* - `9..15`: The output will have a zlib header and footer (Deflate)
|
||||
* - `-9..-15`: The output will **not** have a zlib header or footer (Raw Deflate)
|
||||
* - `25..31` (16+`9..15`): The output will have a gzip header and footer (gzip)
|
||||
*
|
||||
* The gzip header will have no file name, no extra data, no comment, no modification time (set to zero) and no header CRC.
|
||||
*/
|
||||
windowBits?:
|
||||
| -9
|
||||
| -10
|
||||
| -11
|
||||
| -12
|
||||
| -13
|
||||
| -14
|
||||
| -15
|
||||
| 9
|
||||
| 10
|
||||
| 11
|
||||
| 12
|
||||
| 13
|
||||
| 14
|
||||
| 15
|
||||
| 25
|
||||
| 26
|
||||
| 27
|
||||
| 28
|
||||
| 29
|
||||
| 30
|
||||
| 31;
|
||||
/**
|
||||
* Tunes the compression algorithm.
|
||||
*
|
||||
* - `Z_DEFAULT_STRATEGY`: For normal data **(Default)**
|
||||
* - `Z_FILTERED`: For data produced by a filter or predictor
|
||||
* - `Z_HUFFMAN_ONLY`: Force Huffman encoding only (no string match)
|
||||
* - `Z_RLE`: Limit match distances to one (run-length encoding)
|
||||
* - `Z_FIXED` prevents the use of dynamic Huffman codes
|
||||
*
|
||||
* `Z_RLE` is designed to be almost as fast as `Z_HUFFMAN_ONLY`, but give better compression for PNG image data.
|
||||
*
|
||||
* `Z_FILTERED` forces more Huffman coding and less string matching, it is
|
||||
* somewhat intermediate between `Z_DEFAULT_STRATEGY` and `Z_HUFFMAN_ONLY`.
|
||||
* Filtered data consists mostly of small values with a somewhat random distribution.
|
||||
*/
|
||||
strategy?: number;
|
||||
};
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## `Bun.gunzipSync()`
|
||||
|
||||
Decompresses a `Uint8Array` using zlib's GUNZIP algorithm.
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello".repeat(100)); // Buffer extends Uint8Array
|
||||
const compressed = Bun.gunzipSync(buf);
|
||||
|
||||
const dec = new TextDecoder();
|
||||
const uncompressed = Bun.inflateSync(compressed);
|
||||
dec.decode(uncompressed);
|
||||
// => "hellohellohello..."
|
||||
```
|
||||
|
||||
## `Bun.deflateSync()`
|
||||
|
||||
Compresses a `Uint8Array` using zlib's DEFLATE algorithm.
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello".repeat(100));
|
||||
const compressed = Bun.deflateSync(buf);
|
||||
|
||||
buf; // => Uint8Array(25)
|
||||
compressed; // => Uint8Array(10)
|
||||
```
|
||||
|
||||
The second argument supports the same set of configuration options as [`Bun.gzipSync`](#bun.gzipSync).
|
||||
|
||||
## `Bun.inflateSync()`
|
||||
|
||||
Decompresses a `Uint8Array` using zlib's INFLATE algorithm.
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello".repeat(100));
|
||||
const compressed = Bun.deflateSync(buf);
|
||||
|
||||
const dec = new TextDecoder();
|
||||
const decompressed = Bun.inflateSync(compressed);
|
||||
dec.decode(decompressed);
|
||||
// => "hellohellohello..."
|
||||
```
|
||||
|
||||
## `Bun.inspect()`
|
||||
|
||||
Serializes an object to a `string` exactly as it would be printed by `console.log`.
|
||||
|
||||
```ts
|
||||
const obj = { foo: "bar" };
|
||||
const str = Bun.inspect(obj);
|
||||
// => '{\nfoo: "bar" \n}'
|
||||
|
||||
const arr = new Uint8Array([1, 2, 3]);
|
||||
const str = Bun.inspect(arr);
|
||||
// => "Uint8Array(3) [ 1, 2, 3 ]"
|
||||
```
|
||||
|
||||
## `Bun.nanoseconds()`
|
||||
|
||||
Returns the number of nanoseconds since the current `bun` process started, as a `number`. Useful for high-precision timing and benchmarking.
|
||||
|
||||
```ts
|
||||
Bun.nanoseconds();
|
||||
// => 7288958
|
||||
```
|
||||
|
||||
## `Bun.readableStreamTo*()`
|
||||
|
||||
Bun implements a set of convenience functions for asynchronously consuming the body of a `ReadableStream` and converting it to various binary formats.
|
||||
|
||||
```ts
|
||||
const stream = (await fetch("https://bun.sh")).body;
|
||||
stream; // => ReadableStream
|
||||
|
||||
await Bun.readableStreamToArrayBuffer(stream);
|
||||
// => ArrayBuffer
|
||||
|
||||
await Bun.readableStreamToBlob(stream);
|
||||
// => Blob
|
||||
|
||||
await Bun.readableStreamToJSON(stream);
|
||||
// => object
|
||||
|
||||
await Bun.readableStreamToText(stream);
|
||||
// => string
|
||||
|
||||
// returns all chunks as an array
|
||||
await Bun.readableStreamToArray(stream);
|
||||
// => unknown[]
|
||||
|
||||
// returns all chunks as a FormData object (encoded as x-www-form-urlencoded)
|
||||
await Bun.readableStreamToFormData(stream);
|
||||
|
||||
// returns all chunks as a FormData object (encoded as multipart/form-data)
|
||||
await Bun.readableStreamToFormData(stream, multipartFormBoundary);
|
||||
```
|
||||
|
||||
## `Bun.resolveSync()`
|
||||
|
||||
Resolves a file path or module specifier using Bun's internal module resolution algorithm. The first argument is the path to resolve, and the second argument is the "root". If no match is found, an `Error` is thrown.
|
||||
|
||||
```ts
|
||||
Bun.resolveSync("./foo.ts", "/path/to/project");
|
||||
// => "/path/to/project/foo.ts"
|
||||
|
||||
Bun.resolveSync("zod", "/path/to/project");
|
||||
// => "/path/to/project/node_modules/zod/index.ts"
|
||||
```
|
||||
|
||||
To resolve relative to the current working directory, pass `process.cwd` or `"."` as the root.
|
||||
|
||||
```ts
|
||||
Bun.resolveSync("./foo.ts", process.cwd());
|
||||
Bun.resolveSync("./foo.ts", "/path/to/project");
|
||||
```
|
||||
|
||||
To resolve relative to the directory containing the current file, pass `import.meta.dir`.
|
||||
|
||||
```ts
|
||||
Bun.resolveSync("./foo.ts", import.meta.dir);
|
||||
```
|
||||
|
||||
## `serialize` & `deserialize` in `bun:jsc`
|
||||
|
||||
To save a JavaScript value into an ArrayBuffer & back, use `serialize` and `deserialize` from the `"bun:jsc"` module.
|
||||
|
||||
```js
|
||||
import { serialize, deserialize } from "bun:jsc";
|
||||
|
||||
const buf = serialize({ foo: "bar" });
|
||||
const obj = deserialize(buf);
|
||||
console.log(obj); // => { foo: "bar" }
|
||||
```
|
||||
|
||||
Internally, [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) and [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) serialize and deserialize the same way. This exposes the underlying [HTML Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) to JavaScript as an ArrayBuffer.
|
||||
|
||||
@@ -12,41 +12,7 @@
|
||||
Internally Bun's WebSocket implementation is built on [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
||||
{% /callout %}
|
||||
|
||||
## Connect to a WebSocket server
|
||||
|
||||
To connect to an external socket server, create an instance of `WebSocket` with the constructor.
|
||||
|
||||
```ts
|
||||
const socket = new WebSocket("ws://localhost:3000");
|
||||
```
|
||||
|
||||
Bun supports setting custom headers. This is a Bun-specific extension of the `WebSocket` standard.
|
||||
|
||||
```ts
|
||||
const socket = new WebSocket("ws://localhost:3000", {
|
||||
headers: {
|
||||
// custom headers
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
To add event listeners to the socket:
|
||||
|
||||
```ts
|
||||
// message is received
|
||||
socket.addEventListener("message", event => {});
|
||||
|
||||
// socket opened
|
||||
socket.addEventListener("open", event => {});
|
||||
|
||||
// socket closed
|
||||
socket.addEventListener("close", event => {});
|
||||
|
||||
// error handler
|
||||
socket.addEventListener("error", event => {});
|
||||
```
|
||||
|
||||
## Create a WebSocket server
|
||||
## Start a WebSocket server
|
||||
|
||||
Below is a simple WebSocket server built with `Bun.serve`, in which all incoming requests are [upgraded](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) to WebSocket connections in the `fetch` handler. The socket handlers are declared in the `websocket` parameter.
|
||||
|
||||
@@ -109,7 +75,7 @@ Bun.serve({
|
||||
});
|
||||
```
|
||||
|
||||
## Sending messages
|
||||
### Sending messages
|
||||
|
||||
Each `ServerWebSocket` instance has a `.send()` method for sending messages to the client. It supports a range of input types.
|
||||
|
||||
@@ -119,7 +85,7 @@ ws.send(response.arrayBuffer()); // ArrayBuffer
|
||||
ws.send(new Uint8Array([1, 2, 3])); // TypedArray | DataView
|
||||
```
|
||||
|
||||
## Headers
|
||||
### Headers
|
||||
|
||||
Once the upgrade succeeds, Bun will send a `101 Switching Protocols` response per the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism). Additional `headers` can be attched to this `Response` in the call to `server.upgrade()`.
|
||||
|
||||
@@ -137,7 +103,7 @@ Bun.serve({
|
||||
});
|
||||
```
|
||||
|
||||
## Contextual data
|
||||
### Contextual data
|
||||
|
||||
Contextual `data` can be attached to a new WebSocket in the `.upgrade()` call. This data is made available on the `ws.data` property inside the WebSocket handlers.
|
||||
|
||||
@@ -145,16 +111,20 @@ Contextual `data` can be attached to a new WebSocket in the `.upgrade()` call. T
|
||||
type WebSocketData = {
|
||||
createdAt: number;
|
||||
channelId: string;
|
||||
authToken: string;
|
||||
};
|
||||
|
||||
// TypeScript: specify the type of `data`
|
||||
Bun.serve<WebSocketData>({
|
||||
fetch(req, server) {
|
||||
// use a library to parse cookies
|
||||
const cookies = parseCookies(req.headers.get("Cookie"));
|
||||
server.upgrade(req, {
|
||||
// TS: this object must conform to WebSocketData
|
||||
// this object must conform to WebSocketData
|
||||
data: {
|
||||
createdAt: Date.now(),
|
||||
channelId: new URL(req.url).searchParams.get("channelId"),
|
||||
authToken: cookies["X-Token"],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -163,53 +133,76 @@ Bun.serve<WebSocketData>({
|
||||
websocket: {
|
||||
// handler called when a message is received
|
||||
async message(ws, message) {
|
||||
ws.data; // WebSocketData
|
||||
const user = getUserFromToken(ws.data.authToken);
|
||||
|
||||
await saveMessageToDatabase({
|
||||
channel: ws.data.channelId,
|
||||
message: String(message),
|
||||
userId: user.id,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Pub/Sub
|
||||
To connect to this server from the browser, create a new `WebSocket`.
|
||||
|
||||
```ts#browser.js
|
||||
const socket = new WebSocket("ws://localhost:3000/chat");
|
||||
|
||||
socket.addEventListener("message", event => {
|
||||
console.log(event.data);
|
||||
})
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Identifying users** — The cookies that are currently set on the page will be sent with the WebSocket upgrade request and available on `req.headers` in the `fetch` handler. Parse these cookies to determine the identity of the connecting user and set the value of `data` accordingly.
|
||||
{% /callout %}
|
||||
|
||||
### Pub/Sub
|
||||
|
||||
Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic. This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
|
||||
|
||||
```ts
|
||||
const pubsubserver = Bun.serve<{username: string}>({
|
||||
const server = Bun.serve<{ username: string }>({
|
||||
fetch(req, server) {
|
||||
if (req.url === '/chat') {
|
||||
const cookies = getCookieFromRequest(req);
|
||||
const success = server.upgrade(req, {
|
||||
data: {username: cookies.username},
|
||||
});
|
||||
const url = new URL(req.url);
|
||||
if (url.pathname === "/chat") {
|
||||
console.log(`upgrade!`);
|
||||
const username = getUsernameFromReq(req);
|
||||
const success = server.upgrade(req, { data: { username } });
|
||||
return success
|
||||
? undefined
|
||||
: new Response('WebSocket upgrade error', {status: 400});
|
||||
: new Response("WebSocket upgrade error", { status: 400 });
|
||||
}
|
||||
|
||||
return new Response('Hello world');
|
||||
return new Response("Hello world");
|
||||
},
|
||||
websocket: {
|
||||
open(ws) {
|
||||
ws.subscribe('the-group-chat');
|
||||
ws.publish('the-group-chat', `${ws.data.username} has entered the chat`);
|
||||
const msg = `${ws.data.username} has entered the chat`;
|
||||
ws.subscribe("the-group-chat");
|
||||
ws.publish("the-group-chat", msg);
|
||||
},
|
||||
message(ws, message) {
|
||||
// this is a group chat
|
||||
// so the server re-broadcasts incoming message to everyone
|
||||
ws.publish('the-group-chat', `${ws.data.username}: ${message}`);
|
||||
ws.publish("the-group-chat", `${ws.data.username}: ${message}`);
|
||||
},
|
||||
close(ws) {
|
||||
ws.unsubscribe('the-group-chat');
|
||||
ws.publish('the-group-chat', `${ws.data.username} has left the chat`);
|
||||
const msg = `${ws.data.username} has left the chat`;
|
||||
ws.unsubscribe("the-group-chat");
|
||||
ws.publish("the-group-chat", msg);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Listening on ${server.hostname}:${server.port}`);
|
||||
```
|
||||
|
||||
## Compression
|
||||
Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`.
|
||||
|
||||
### Compression
|
||||
|
||||
Per-message [compression](https://websockets.readthedocs.io/en/stable/topics/compression.html) can be enabled with the `perMessageDeflate` parameter.
|
||||
|
||||
@@ -231,7 +224,7 @@ ws.send("Hello world", true);
|
||||
|
||||
For fine-grained control over compression characteristics, refer to the [Reference](#reference).
|
||||
|
||||
## Backpressure
|
||||
### Backpressure
|
||||
|
||||
The `.send(message)` method of `ServerWebSocket` returns a `number` indicating the result of the operation.
|
||||
|
||||
@@ -241,6 +234,42 @@ The `.send(message)` method of `ServerWebSocket` returns a `number` indicating t
|
||||
|
||||
This gives you better control over backpressure in your server.
|
||||
|
||||
## Connect to a `Websocket` server
|
||||
|
||||
To connect to an external socket server, either from a browser or from Bun, create an instance of `WebSocket` with the constructor.
|
||||
|
||||
```ts
|
||||
const socket = new WebSocket("ws://localhost:3000");
|
||||
```
|
||||
|
||||
In browsers, the cookies that are currently set on the page will be sent with the WebSocket upgrade request. This is a standard feature of the `WebSocket` API.
|
||||
|
||||
For convenience, Bun lets you setting custom headers directly in the constructor. This is a Bun-specific extension of the `WebSocket` standard. _This will not work in browsers._
|
||||
|
||||
```ts
|
||||
const socket = new WebSocket("ws://localhost:3000", {
|
||||
headers: {
|
||||
// custom headers
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
To add event listeners to the socket:
|
||||
|
||||
```ts
|
||||
// message is received
|
||||
socket.addEventListener("message", event => {});
|
||||
|
||||
// socket opened
|
||||
socket.addEventListener("open", event => {});
|
||||
|
||||
// socket closed
|
||||
socket.addEventListener("close", event => {});
|
||||
|
||||
// error handler
|
||||
socket.addEventListener("error", event => {});
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
@@ -248,7 +277,10 @@ namespace Bun {
|
||||
export function serve(params: {
|
||||
fetch: (req: Request, server: Server) => Response | Promise<Response>;
|
||||
websocket?: {
|
||||
message: (ws: ServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
||||
message: (
|
||||
ws: ServerWebSocket,
|
||||
message: string | ArrayBuffer | Uint8Array,
|
||||
) => void;
|
||||
open?: (ws: ServerWebSocket) => void;
|
||||
close?: (ws: ServerWebSocket) => void;
|
||||
error?: (ws: ServerWebSocket, error: Error) => void;
|
||||
@@ -278,7 +310,11 @@ type Compressor =
|
||||
|
||||
interface Server {
|
||||
pendingWebsockets: number;
|
||||
publish(topic: string, data: string | ArrayBufferView | ArrayBuffer, compress?: boolean): number;
|
||||
publish(
|
||||
topic: string,
|
||||
data: string | ArrayBufferView | ArrayBuffer,
|
||||
compress?: boolean,
|
||||
): number;
|
||||
upgrade(
|
||||
req: Request,
|
||||
options?: {
|
||||
|
||||
168
docs/api/workers.md
Normal file
168
docs/api/workers.md
Normal file
@@ -0,0 +1,168 @@
|
||||
{% callout %}
|
||||
`Worker` support was added in Bun v0.7.0.
|
||||
{% /callout %}
|
||||
|
||||
[`Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Worker) lets you start and communicate with a new JavaScript instance running on a separate thread while sharing I/O resources with the main thread.
|
||||
|
||||
Bun implements a minimal version of the [Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) with extensions that make it work better for server-side use cases. Like the rest of Bun, `Worker` in Bun support CommonJS, ES Modules, TypeScript, JSX, TSX and more out of the box. No extra build steps are necessary.
|
||||
|
||||
## Creating a `Worker`
|
||||
|
||||
Like in browsers, [`Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Worker) is a global. Use it to create a new worker thread.
|
||||
|
||||
From the main thread:
|
||||
|
||||
```js#Main_thread
|
||||
const workerURL = new URL("worker.ts", import.meta.url).href;
|
||||
const worker = new Worker(workerURL);
|
||||
|
||||
worker.postMessage("hello");
|
||||
worker.onmessage = event => {
|
||||
console.log(event.data);
|
||||
};
|
||||
```
|
||||
|
||||
Worker thread:
|
||||
|
||||
```ts#worker.ts_(Worker_thread)
|
||||
self.onmessage = (event: MessageEvent) => {
|
||||
console.log(event.data);
|
||||
postMessage("world");
|
||||
};
|
||||
```
|
||||
|
||||
You can use `import`/`export` syntax in your worker code. Unlike in browsers, there's no need to specify `{type: "module"}` to use ES Modules.
|
||||
|
||||
To simplify error handling, the initial script to load is resolved at the time `new Worker(url)` is called.
|
||||
|
||||
```js
|
||||
const worker = new Worker("/not-found.js");
|
||||
// throws an error immediately
|
||||
```
|
||||
|
||||
The specifier passed to `Worker` is resolved relative to the project root (like typing `bun ./path/to/file.js`).
|
||||
|
||||
### `"open"`
|
||||
|
||||
The `"open"` event is emitted when a worker is created and ready to receive messages. This can be used to send an initial message to a worker once it's ready. (This event does not exist in browsers.)
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
|
||||
|
||||
worker.addEventListener("open", () => {
|
||||
console.log("worker is ready");
|
||||
});
|
||||
```
|
||||
|
||||
Messages are automatically enqueued until the worker is ready, so there is no need to wait for the `"open"` event to send messages.
|
||||
|
||||
## Messages with `postMessage`
|
||||
|
||||
To send messages, use [`worker.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage) and [`self.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). This leverages the [HTML Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).
|
||||
|
||||
```js
|
||||
// On the worker thread, `postMessage` is automatically "routed" to the parent thread.
|
||||
postMessage({ hello: "world" });
|
||||
|
||||
// On the main thread
|
||||
worker.postMessage({ hello: "world" });
|
||||
```
|
||||
|
||||
To receive messages, use the [`message` event handler](https://developer.mozilla.org/en-US/docs/Web/API/Worker/message_event) on the worker and main thread.
|
||||
|
||||
```js
|
||||
// Worker thread:
|
||||
self.addEventListener("message", event => {
|
||||
console.log(event.data);
|
||||
});
|
||||
// or use the setter:
|
||||
// self.onmessage = fn
|
||||
|
||||
// if on the main thread
|
||||
worker.addEventListener("message", event => {
|
||||
console.log(event.data);
|
||||
});
|
||||
// or use the setter:
|
||||
// worker.onmessage = fn
|
||||
```
|
||||
|
||||
## Terminating a worker
|
||||
|
||||
A `Worker` instance terminates automatically once it's event loop has no work left to do. Attaching a `"message"` listener on the global or any `MessagePort`s will keep the event loop alive. To forcefully terminate a `Worker`, call `worker.terminate()`.
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
|
||||
|
||||
// ...some time later
|
||||
worker.terminate();
|
||||
```
|
||||
|
||||
This will cause the worker's to exit as soon as possible.
|
||||
|
||||
### `process.exit()`
|
||||
|
||||
A worker can terminate itself with `process.exit()`. This does not terminate the main process. Like in Node.js, `process.on('beforeExit', callback)` and `process.on('exit', callback)` are emitted on the worker thread (and not on the main thread), and the exit code is passed to the `"close"` event.
|
||||
|
||||
### `"close"`
|
||||
|
||||
The `"close"` event is emitted when a worker has been terminated. It can take some time for the worker to actually terminate, so this event is emitted when the worker has been marked as terminated. The `CloseEvent` will contain the exit code passed to `process.exit()`, or 0 if closed for other reasons.
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
|
||||
|
||||
worker.addEventListener("close", event => {
|
||||
console.log("worker is being closed");
|
||||
});
|
||||
```
|
||||
|
||||
This event does not exist in browsers.
|
||||
|
||||
## Managing lifetime
|
||||
|
||||
By default, an active `Worker` will keep the main (spawning) process alive, so async tasks like `setTimeout` and promises will keep the process alive. Attaching `message` listeners will also keep the `Worker` alive.
|
||||
|
||||
### `worker.unref()`
|
||||
|
||||
To stop a running worker from keeping the process alive, call `worker.unref()`. This decouples the lifetime of the worker to the lifetime of the main process, and is equivlent to what Node.js' `worker_threads` does.
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
|
||||
worker.unref();
|
||||
```
|
||||
|
||||
Note: `worker.unref()` is not available in browers.
|
||||
|
||||
### `worker.ref()`
|
||||
|
||||
To keep the process alive until the `Worker` terminates, call `worker.ref()`. A ref'd worker is the default behavior, and still needs something going on in the event loop (such as a `"message"` listener) for the worker to continue running.
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
|
||||
worker.unref();
|
||||
// later...
|
||||
worker.ref();
|
||||
```
|
||||
|
||||
Alternatively, you can also pass an `options` object to `Worker`:
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("worker.ts", import.meta.url).href, {
|
||||
ref: false,
|
||||
});
|
||||
```
|
||||
|
||||
Note: `worker.ref()` is not available in browers.
|
||||
|
||||
## Memory usage with `smol`
|
||||
|
||||
JavaScript instances can use a lot of memory. Bun's `Worker` supports a `smol` mode that reduces memory usage, at a cost of performance. To enable `smol` mode, pass `smol: true` to the `options` object in the `Worker` constructor.
|
||||
|
||||
```js
|
||||
const worker = new Worker("./i-am-smol.ts", {
|
||||
smol: true,
|
||||
});
|
||||
```
|
||||
|
||||
{% details summary="What does `smol` mode actually do?" %}
|
||||
Setting `smol: true` sets `JSC::HeapSize` to be `Small` instead of the default `Large`.
|
||||
{% /details %}
|
||||
@@ -307,7 +307,7 @@ Depending on the target, Bun will apply different module resolution rules and op
|
||||
---
|
||||
|
||||
- `browser`
|
||||
- _Default._ For generating bundles that are intended for execution by a browser. Prioritizes the `"browser"` export condition when resolving imports. An error will be thrown if any Node.js or Bun built-ins are imported or used, e.g. `node:fs` or `Bun.serve`.
|
||||
- _Default._ For generating bundles that are intended for execution by a browser. Prioritizes the `"browser"` export condition when resolving imports. Importing any built-in modules, like `node:events` or `node:path` will work, but calling some functions, like `fs.readFile` will not work.
|
||||
|
||||
---
|
||||
|
||||
@@ -482,7 +482,7 @@ n/a
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Bun implements a univeral plugin system for both Bun's runtime and bundler. Refer to the [plugin documentation](/docs/bundler/plugins) for complete documentation.
|
||||
Bun implements a universal plugin system for both Bun's runtime and bundler. Refer to the [plugin documentation](/docs/bundler/plugins) for complete documentation.
|
||||
|
||||
<!-- ### `manifest`
|
||||
|
||||
@@ -1272,7 +1272,17 @@ interface BuildArtifact extends Blob {
|
||||
sourcemap?: BuildArtifact;
|
||||
}
|
||||
|
||||
type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "file" | "napi" | "wasm" | "text";
|
||||
type Loader =
|
||||
| "js"
|
||||
| "jsx"
|
||||
| "ts"
|
||||
| "tsx"
|
||||
| "json"
|
||||
| "toml"
|
||||
| "file"
|
||||
| "napi"
|
||||
| "wasm"
|
||||
| "text";
|
||||
|
||||
interface BuildOutput {
|
||||
outputs: BuildArtifact[];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user