mirror of
https://github.com/oven-sh/bun
synced 2026-02-05 08:28:55 +00:00
Compare commits
116 Commits
dylan/gith
...
jarred/mod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82b1d3fb65 | ||
|
|
6265ac2307 | ||
|
|
af131cfe77 | ||
|
|
15d268f8da | ||
|
|
2bd296bc90 | ||
|
|
39ce95c0d0 | ||
|
|
3a0d7fc3f0 | ||
|
|
b05adf1e35 | ||
|
|
1496681297 | ||
|
|
3906d17165 | ||
|
|
f297b95436 | ||
|
|
fafd9368f5 | ||
|
|
1836ecd2ed | ||
|
|
4cdaabd433 | ||
|
|
4a74a46780 | ||
|
|
b62c010e95 | ||
|
|
074534b292 | ||
|
|
b0393fba62 | ||
|
|
7166fe10b5 | ||
|
|
2890ad53c4 | ||
|
|
01e3474600 | ||
|
|
756eee087a | ||
|
|
4b2cdc4fc1 | ||
|
|
184528e4eb | ||
|
|
8cf7d6157a | ||
|
|
68324daf78 | ||
|
|
66debb1ce4 | ||
|
|
d5d9fc4684 | ||
|
|
f6b694ee2c | ||
|
|
bb623196a3 | ||
|
|
e9948f1291 | ||
|
|
378385ba60 | ||
|
|
ef5930e8bc | ||
|
|
0173571b19 | ||
|
|
35259c0c1d | ||
|
|
e7cba822e4 | ||
|
|
0d34e7a141 | ||
|
|
aedc8c0ead | ||
|
|
9c0cd5c030 | ||
|
|
2f10398c74 | ||
|
|
49ef5bccec | ||
|
|
dcbcf9803a | ||
|
|
e731eff382 | ||
|
|
a57d7ecb5b | ||
|
|
d187563d36 | ||
|
|
e91436e524 | ||
|
|
bbc2e96090 | ||
|
|
f53eb7cd59 | ||
|
|
98d19fa624 | ||
|
|
a3958190e8 | ||
|
|
6504bfef74 | ||
|
|
220cb0eb94 | ||
|
|
01e04e3341 | ||
|
|
0853e19f53 | ||
|
|
a9b8e3ecc8 | ||
|
|
bec6161dce | ||
|
|
8c580e6764 | ||
|
|
c5354951ba | ||
|
|
f1658e2e58 | ||
|
|
90d7f33522 | ||
|
|
d9c0273421 | ||
|
|
d65b1fd80b | ||
|
|
7becb5ec74 | ||
|
|
c3f5baa091 | ||
|
|
800ad150ff | ||
|
|
5608e59270 | ||
|
|
e31ed84b1b | ||
|
|
548b1d02f2 | ||
|
|
f63955a01f | ||
|
|
2996ef7156 | ||
|
|
2b1f3438e6 | ||
|
|
2a8f3a3b4e | ||
|
|
a87aa2fafe | ||
|
|
9b5e66453b | ||
|
|
46f978838d | ||
|
|
21576589c6 | ||
|
|
d7062eb367 | ||
|
|
851dc9aadc | ||
|
|
d08e112d41 | ||
|
|
77d7e47019 | ||
|
|
1bad64bc5e | ||
|
|
0794767291 | ||
|
|
d7c8a58453 | ||
|
|
4fab8fee21 | ||
|
|
3f2df4526e | ||
|
|
d6d4ead438 | ||
|
|
4e67862753 | ||
|
|
584e6dd1c2 | ||
|
|
4bb753295d | ||
|
|
892593c73b | ||
|
|
691cf338c2 | ||
|
|
beb746e5ea | ||
|
|
89faee2522 | ||
|
|
969da088f5 | ||
|
|
c50be68790 | ||
|
|
2fbb95142a | ||
|
|
755e16d962 | ||
|
|
b1063edf3e | ||
|
|
edb4cbac2b | ||
|
|
a59a69e21b | ||
|
|
4c9e009971 | ||
|
|
4531cf18c2 | ||
|
|
31bda68f24 | ||
|
|
1bf28e0d77 | ||
|
|
6a17ebe669 | ||
|
|
39446ebdb8 | ||
|
|
c2c3b0d4a9 | ||
|
|
9a90d90966 | ||
|
|
05781dd91e | ||
|
|
a6a474a83f | ||
|
|
44dd744f0a | ||
|
|
df4ec8aaad | ||
|
|
0348b169d6 | ||
|
|
54dbf3ba21 | ||
|
|
5f09a4dd0a | ||
|
|
e58e85cd5c |
3
.github/workflows/bun-linux-aarch64.yml
vendored
3
.github/workflows/bun-linux-aarch64.yml
vendored
@@ -16,6 +16,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -37,7 +38,7 @@ jobs:
|
||||
arch: aarch64
|
||||
build_arch: arm64
|
||||
runner: linux-arm64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-arm64-lto"
|
||||
build_machine_arch: aarch64
|
||||
|
||||
|
||||
6
.github/workflows/bun-linux-build.yml
vendored
6
.github/workflows/bun-linux-build.yml
vendored
@@ -16,6 +16,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -25,6 +26,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -47,7 +49,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
- cpu: nehalem
|
||||
@@ -55,7 +57,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
|
||||
|
||||
18
.github/workflows/bun-mac-aarch64.yml
vendored
18
.github/workflows/bun-mac-aarch64.yml
vendored
@@ -15,6 +15,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -23,6 +24,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -117,7 +119,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -126,7 +128,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -135,7 +137,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -144,7 +146,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: native
|
||||
@@ -152,7 +154,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/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
dependencies: true
|
||||
compile_obj: true
|
||||
@@ -258,7 +260,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -266,14 +268,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/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/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
18
.github/workflows/bun-mac-x64-baseline.yml
vendored
18
.github/workflows/bun-mac-x64-baseline.yml
vendored
@@ -15,6 +15,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -23,6 +24,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -117,7 +119,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -126,7 +128,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: nehalem
|
||||
@@ -135,7 +137,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -144,7 +146,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -152,7 +154,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/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -259,7 +261,7 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -267,14 +269,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/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/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
18
.github/workflows/bun-mac-x64.yml
vendored
18
.github/workflows/bun-mac-x64.yml
vendored
@@ -15,6 +15,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -23,6 +24,7 @@ on:
|
||||
paths:
|
||||
- "src/**/*"
|
||||
- "test/**/*"
|
||||
- "packages/bun-usockets/src/**/*"
|
||||
- "build.zig"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
@@ -117,7 +119,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: haswell
|
||||
@@ -126,7 +128,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -135,7 +137,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: haswell
|
||||
@@ -144,7 +146,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -152,7 +154,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/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -261,7 +263,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-12
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: haswell
|
||||
arch: x86_64
|
||||
tag: bun-darwin-x64
|
||||
@@ -269,14 +271,14 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-12
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/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/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-3/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
2
.github/workflows/bun-release.yml
vendored
2
.github/workflows/bun-release.yml
vendored
@@ -2,7 +2,7 @@ name: bun-release
|
||||
concurrency: release
|
||||
env:
|
||||
BUN_VERSION: ${{ github.event.inputs.tag || github.event.release.tag_name || 'canary' }}
|
||||
BUN_LATEST: ${{ github.event.inputs.is-latest || github.event.release.prerelease == 'false' }}
|
||||
BUN_LATEST: ${{ (github.event.inputs.is-latest || github.event.release.tag_name) && 'true' || 'false' }}
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
|
||||
2
.github/workflows/zig-fmt.yml
vendored
2
.github/workflows/zig-fmt.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: zig-fmt
|
||||
|
||||
env:
|
||||
ZIG_VERSION: 0.12.0-dev.163+6780a6bbf
|
||||
ZIG_VERSION: 0.12.0-dev.899+027aabf49
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
set -euxo pipefail
|
||||
|
||||
# if bun-webkit node_modules directory exists
|
||||
if [ -d ./node_modules/bun-webkit ]; then
|
||||
if [ -d ./node_modules/bun-webkit ] || [ -d ./node_modules/bun-webkit-debug ]; then
|
||||
rm -f bun-webkit
|
||||
# get the first matching bun-webkit-* directory name
|
||||
ln -s ./node_modules/$(ls ./node_modules | grep bun-webkit- | head -n 1) ./bun-webkit
|
||||
ln -s ./node_modules/$(ls ./node_modules | grep bun-webkit- | grep -v bun-webkit-debug | head -n 1) ./bun-webkit
|
||||
fi
|
||||
|
||||
# sets up vscode C++ intellisense
|
||||
|
||||
85
.vscode/c_cpp_properties.json
vendored
85
.vscode/c_cpp_properties.json
vendored
@@ -6,11 +6,11 @@
|
||||
"includePath": [
|
||||
"${workspaceFolder}/../webkit-build/include/",
|
||||
"${workspaceFolder}/bun-webkit/include/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/bmalloc/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/bmalloc/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcore/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
|
||||
@@ -28,11 +28,11 @@
|
||||
"path": [
|
||||
"${workspaceFolder}/../webkit-build/include/",
|
||||
"${workspaceFolder}/bun-webkit/include/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/JavaScriptCore/PrivateHeaders/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/bmalloc/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/bmalloc/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/bindings/*",
|
||||
"${workspaceFolder}/src/bun.js/bindings/*",
|
||||
"${workspaceFolder}/src/napi/*",
|
||||
@@ -59,7 +59,70 @@
|
||||
"ENABLE_INSPECTOR_ALTERNATE_DISPATCHERS=0",
|
||||
"BUILDING_JSCONLY__",
|
||||
"USE_FOUNDATION=1",
|
||||
"ASSERT_ENABLED=0",
|
||||
"ASSERT_ENABLED=1",
|
||||
"DU_DISABLE_RENAMING=1"
|
||||
],
|
||||
"macFrameworkPath": [],
|
||||
"compilerPath": "${workspaceFolder}/.vscode/clang++",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20"
|
||||
},
|
||||
{
|
||||
"name": "BunWithJSCDebug",
|
||||
"forcedInclude": ["${workspaceFolder}/src/bun.js/bindings/root.h"],
|
||||
"includePath": [
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/bmalloc/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcore/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
|
||||
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
|
||||
"${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}/packages/bun-usockets/src",
|
||||
"${workspaceFolder}/packages/"
|
||||
],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers/**",
|
||||
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/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/js/builtins/*",
|
||||
"${workspaceFolder}/src/js/out/*",
|
||||
"${workspaceFolder}/src/bun.js/modules/*",
|
||||
"${workspaceFolder}/src/deps",
|
||||
"${workspaceFolder}/src/deps/boringssl/include/",
|
||||
"${workspaceFolder}/packages/bun-usockets/",
|
||||
"${workspaceFolder}/packages/bun-uws/",
|
||||
"${workspaceFolder}/src/napi"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ".vscode/cppdb_debug"
|
||||
},
|
||||
"defines": [
|
||||
"STATICALLY_LINKED_WITH_JavaScriptCore=1",
|
||||
"STATICALLY_LINKED_WITH_WTF=1",
|
||||
"BUILDING_WITH_CMAKE=1",
|
||||
"NOMINMAX",
|
||||
"ENABLE_INSPECTOR_ALTERNATE_DISPATCHERS=0",
|
||||
"BUILDING_JSCONLY__",
|
||||
"USE_FOUNDATION=1",
|
||||
"ASSERT_ENABLED=1",
|
||||
"DU_DISABLE_RENAMING=1"
|
||||
],
|
||||
"macFrameworkPath": [],
|
||||
|
||||
7
.vscode/launch.json
generated
vendored
7
.vscode/launch.json
generated
vendored
@@ -82,7 +82,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun test [*]",
|
||||
"program": "bun-debug",
|
||||
"args": ["test"],
|
||||
"args": ["test", "js/node"],
|
||||
"cwd": "${workspaceFolder}/test",
|
||||
"env": {
|
||||
"FORCE_COLOR": "1",
|
||||
@@ -96,7 +96,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun test [*] (fast)",
|
||||
"program": "bun-debug",
|
||||
"args": ["test"],
|
||||
"args": ["test", "js"],
|
||||
// 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": {
|
||||
@@ -310,10 +310,9 @@
|
||||
"cwd": "${fileDirname}",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"BUN_DEBUG_QUIET_LOGS": "1"
|
||||
"BUN_DEBUG_ALL": "1"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -7,8 +7,7 @@
|
||||
"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.formattingProvider": "zls",
|
||||
"zig.buildArgs": ["obj", "-Dfor-editor"],
|
||||
"zig.buildOption": "build",
|
||||
"zig.buildFilePath": "${workspaceFolder}/build.zig",
|
||||
@@ -223,7 +222,6 @@
|
||||
"valarray": "cpp",
|
||||
"codecvt": "cpp"
|
||||
},
|
||||
"cmake.configureOnOpen": false,
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"eslint.workingDirectories": ["packages/bun-types"],
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
|
||||
@@ -10,7 +10,7 @@ Today (February 2023), Bun's codebase has five distinct parts:
|
||||
|
||||
- JavaScript, JSX, & TypeScript transpiler, module resolver, and related code
|
||||
- JavaScript runtime ([`src/bun.js/`](src/bun.js/))
|
||||
- JavaScript runtime bindings ([`src/bun.zig/bindings/**/*.cpp`](src/bun.zig/bindings/))
|
||||
- JavaScript runtime bindings ([`src/bun.js/bindings/**/*.cpp`](src/bun.js/bindings/))
|
||||
- Package manager ([`src/install/`](src/install/))
|
||||
- Shared utilities ([`src/string_immutable.zig`](src/string_immutable.zig))
|
||||
|
||||
|
||||
@@ -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=2023-oct3
|
||||
ARG WEBKIT_TAG=2023-oct3-3
|
||||
ARG ZIG_TAG=jul1
|
||||
ARG ZIG_VERSION="0.12.0-dev.163+6780a6bbf"
|
||||
ARG ZIG_VERSION="0.12.0-dev.899+027aabf49"
|
||||
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
|
||||
|
||||
ARG ZIG_FOLDERNAME=zig-linux-${BUILD_MACHINE_ARCH}-${ZIG_VERSION}
|
||||
|
||||
4
Makefile
4
Makefile
@@ -1954,5 +1954,5 @@ setup: vendor-dev identifier-cache clean-bindings
|
||||
|
||||
.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)
|
||||
@echo "For detailed build instructions, see https://bun.sh/docs/project/contributing"
|
||||
@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)
|
||||
@@ -93,8 +93,8 @@ bun upgrade --canary
|
||||
- [`bun run`](https://bun.sh/docs/cli/run)
|
||||
- [`bun install`](https://bun.sh/docs/cli/install)
|
||||
- [`bun test`](https://bun.sh/docs/cli/test)
|
||||
- [`bun init`](https://bun.sh/docs/templates#bun-init)
|
||||
- [`bun create`](https://bun.sh/docs/templates#bun-create)
|
||||
- [`bun init`](https://bun.sh/docs/cli/init)
|
||||
- [`bun create`](https://bun.sh/docs/cli/bun-create)
|
||||
- [`bunx`](https://bun.sh/docs/cli/bunx)
|
||||
- Runtime
|
||||
- [Runtime](https://bun.sh/docs/runtime/index)
|
||||
|
||||
25
bench/snippets/require-builtins.mjs
Normal file
25
bench/snippets/require-builtins.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
import { bench, run } from "./runner.mjs";
|
||||
import { builtinModules } from "node:module";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { spawnSync } from "child_process";
|
||||
|
||||
for (let builtin of builtinModules) {
|
||||
const path = `/tmp/require.${builtin.replaceAll("/", "_")}.cjs`;
|
||||
await writeFile(
|
||||
path,
|
||||
`
|
||||
const builtin = ${JSON.stringify(builtin)};
|
||||
const now = require("perf_hooks").performance.now();
|
||||
require(builtin);
|
||||
const end = require("perf_hooks").performance.now();
|
||||
process.stdout.write(JSON.stringify({builtin, time: end - now}) + "\\n");
|
||||
`,
|
||||
);
|
||||
const result = spawnSync(typeof Bun !== "undefined" ? "bun" : "node", [path], {
|
||||
stdio: ["inherit", "inherit", "inherit"],
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_NO_WARNINGS: "1",
|
||||
},
|
||||
});
|
||||
}
|
||||
38
build.zig
38
build.zig
@@ -1,3 +1,5 @@
|
||||
const required_zig_version = "0.12.0-dev.899+027aabf49";
|
||||
|
||||
const std = @import("std");
|
||||
const pathRel = std.fs.path.relative;
|
||||
const Wyhash = @import("./src/wyhash.zig").Wyhash;
|
||||
@@ -146,6 +148,20 @@ pub fn build(b: *Build) !void {
|
||||
}
|
||||
|
||||
pub fn build_(b: *Build) !void {
|
||||
if (!std.mem.eql(u8, @import("builtin").zig_version_string, required_zig_version)) {
|
||||
const colors = std.io.getStdErr().supportsAnsiEscapeCodes();
|
||||
std.debug.print(
|
||||
"{s}WARNING:\nBun requires zig version '{s}', but found '{s}', build may fail...\nMake sure you installed the right version as per https://bun.sh/docs/project/development#install-zig\n{s}You can update to the right version using 'zigup {s}'\n\n",
|
||||
.{
|
||||
if (colors) "\x1b[1;33m" else "",
|
||||
required_zig_version,
|
||||
@import("builtin").zig_version_string,
|
||||
if (colors) "\x1b[0m" else "",
|
||||
required_zig_version,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
@@ -217,7 +233,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative(root_src),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = .{ .cwd_relative = b.pathFromRoot(".") },
|
||||
.main_mod_path = .{ .cwd_relative = b.pathFromRoot(".") },
|
||||
});
|
||||
|
||||
b.reference_trace = 16;
|
||||
@@ -331,7 +347,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("src/bindgen.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -348,7 +364,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("root_wasm.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer wasm_step.dependOn(&wasm.step);
|
||||
wasm.strip = false;
|
||||
@@ -367,7 +383,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("misctools/http_bench.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -381,7 +397,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("misctools/machbench.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -395,7 +411,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("misctools/fetch.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -409,7 +425,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("src/bench/string-handling.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -423,7 +439,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("src/sha.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -437,7 +453,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("src/sourcemap/vlq_bench.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -451,7 +467,7 @@ pub fn build_(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative("misctools/tgz.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
defer headers_step.dependOn(&headers_obj.step);
|
||||
try configureObjectStep(b, headers_obj, headers_step, @TypeOf(target), target);
|
||||
@@ -468,7 +484,7 @@ pub fn build_(b: *Build) !void {
|
||||
var headers_obj: *CompileStep = b.addTest(.{
|
||||
.root_source_file = FileSource.relative(test_file orelse "src/main.zig"),
|
||||
.target = target,
|
||||
.main_pkg_path = obj.main_pkg_path,
|
||||
.main_mod_path = obj.main_mod_path,
|
||||
});
|
||||
headers_obj.filter = test_filter;
|
||||
if (test_bin_) |test_bin| {
|
||||
|
||||
@@ -26,10 +26,10 @@ Below is a quick "cheat sheet" that doubles as a table of contents. Click an ite
|
||||
|
||||
---
|
||||
|
||||
<!-- - [`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`.
|
||||
- [`File`](#file)
|
||||
- A subclass of `Blob` that represents a file. Has a `name` and `lastModified` timestamp. There is experimental support in Node.js v20.
|
||||
|
||||
--- -->
|
||||
---
|
||||
|
||||
- [`BunFile`](#bunfile)
|
||||
- _Bun only_. A subclass of `Blob` that represents a lazily-loaded file on disk. Created with `Bun.file(path)`.
|
||||
|
||||
@@ -183,6 +183,60 @@ const proc = Bun.spawn(["echo", "hello"]);
|
||||
proc.unref();
|
||||
```
|
||||
|
||||
## Inter-process communication (IPC)
|
||||
|
||||
Bun supports direct inter-process communication channel between two `bun` processes. To receive messages from a spawned Bun subprocess, specify an `ipc` handler.
|
||||
{%callout%}
|
||||
**Note** — This API is only compatible with other `bun` processes. Use `process.execPath` to get a path to the currently running `bun` executable.
|
||||
{%/callout%}
|
||||
|
||||
```ts#parent.ts
|
||||
const child = Bun.spawn(["bun", "child.ts"], {
|
||||
ipc(message) {
|
||||
/**
|
||||
* The message received from the sub process
|
||||
**/
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The parent process can send messages to the subprocess using the `.send()` method on the returned `Subprocess` instance. A reference to the sending subprocess is also available as the second argument in the `ipc` handler.
|
||||
|
||||
```ts#parent.ts
|
||||
const childProc = Bun.spawn(["bun", "child.ts"], {
|
||||
ipc(message, childProc) {
|
||||
/**
|
||||
* The message received from the sub process
|
||||
**/
|
||||
childProc.send("Respond to child")
|
||||
},
|
||||
});
|
||||
|
||||
childProc.send("I am your father"); // The parent can send messages to the child as well
|
||||
```
|
||||
|
||||
Meanwhile the child process can send messages to its parent using with `process.send()` and receive messages with `process.on("message")`. This is the same API used for `child_process.fork()` in Node.js.
|
||||
|
||||
```ts#child.ts
|
||||
process.send("Hello from child as string");
|
||||
process.send({ message: "Hello from child as object" });
|
||||
|
||||
process.on("message", (message) => {
|
||||
// print message from parent
|
||||
console.log(message);
|
||||
});
|
||||
```
|
||||
|
||||
All messages are serialized using the JSC `serialize` API, which allows for the same set of [transferrable types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) supported by `postMessage` and `structuredClone`, including strings, typed arrays, streams, and objects.
|
||||
|
||||
```ts#child.ts
|
||||
// send a string
|
||||
process.send("Hello from child as string");
|
||||
|
||||
// send an object
|
||||
process.send({ message: "Hello from child as object" });
|
||||
```
|
||||
|
||||
## Blocking API (`Bun.spawnSync()`)
|
||||
|
||||
Bun provides a synchronous equivalent of `Bun.spawn` called `Bun.spawnSync`. This is a blocking API that supports the same inputs and parameters as `Bun.spawn`. It returns a `SyncSubprocess` object, which differs from `Subprocess` in a few ways.
|
||||
|
||||
@@ -192,7 +192,7 @@ const server = Bun.serve<{ username: string }>({
|
||||
close(ws) {
|
||||
const msg = `${ws.data.username} has left the chat`;
|
||||
ws.unsubscribe("the-group-chat");
|
||||
server.publish("the-group-chat", msg);
|
||||
ws.publish("the-group-chat", msg);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -328,7 +328,7 @@ Depending on the target, Bun will apply different module resolution rules and op
|
||||
|
||||
All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which indicates to the Bun runtime that there's no need to re-transpile the file before execution.
|
||||
|
||||
If any entrypoints contains a Bun shebang (`#!/usr/bin/env bun`) the bundler will default to `target: "bun"` instead of `"browser`.
|
||||
If any entrypoints contains a Bun shebang (`#!/usr/bin/env bun`) the bundler will default to `target: "bun"` instead of `"browser"`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
155
docs/cli/add.md
Normal file
155
docs/cli/add.md
Normal file
@@ -0,0 +1,155 @@
|
||||
To add a particular package:
|
||||
|
||||
```bash
|
||||
$ bun add preact
|
||||
```
|
||||
|
||||
To specify a version, version range, or tag:
|
||||
|
||||
```bash
|
||||
$ bun add zod@3.20.0
|
||||
$ bun add zod@^3.0.0
|
||||
$ bun add zod@latest
|
||||
```
|
||||
|
||||
## `--dev`
|
||||
|
||||
{% callout %}
|
||||
**Alias** — `--development`, `-d`, `-D`
|
||||
{% /callout %}
|
||||
|
||||
To add a package as a dev dependency (`"devDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --dev @types/react
|
||||
$ bun add -d @types/react
|
||||
```
|
||||
|
||||
## `--optional`
|
||||
|
||||
To add a package as an optional dependency (`"optionalDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --optional lodash
|
||||
```
|
||||
|
||||
## `--exact`
|
||||
|
||||
To add a package and pin to the resolved version, use `--exact`. This will resolve the version of the package and add it to your `package.json` with an exact version number instead of a version range.
|
||||
|
||||
```bash
|
||||
$ bun add react --exact
|
||||
$ bun add react -E
|
||||
```
|
||||
|
||||
This will add the following to your `package.json`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"dependencies": {
|
||||
// without --exact
|
||||
"react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0
|
||||
|
||||
// with --exact
|
||||
"react": "18.2.0" // this matches only 18.2.0 exactly
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To view a complete list of options for this command:
|
||||
|
||||
```bash
|
||||
$ bun add --help
|
||||
```
|
||||
|
||||
## `--global`
|
||||
|
||||
{% callout %}
|
||||
**Note** — This would not modify package.json of your current project folder.
|
||||
**Alias** - `bun add --global`, `bun add -g`, `bun install --global` and `bun install -g`
|
||||
{% /callout %}
|
||||
|
||||
To install a package globally, use the `-g`/`--global` flag. This will not modify the `package.json` of your current project. Typically this is used for installing command-line tools.
|
||||
|
||||
```bash
|
||||
$ bun add --global cowsay # or `bun add -g cowsay`
|
||||
$ cowsay "Bun!"
|
||||
______
|
||||
< Bun! >
|
||||
------
|
||||
\ ^__^
|
||||
\ (oo)\_______
|
||||
(__)\ )\/\
|
||||
||----w |
|
||||
|| ||
|
||||
```
|
||||
|
||||
{% details summary="Configuring global installation behavior" %}
|
||||
|
||||
```toml
|
||||
[install]
|
||||
# where `bun add --global` installs packages
|
||||
globalDir = "~/.bun/install/global"
|
||||
|
||||
# where globally-installed package bins are linked
|
||||
globalBinDir = "~/.bun/bin"
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Trusted dependencies
|
||||
|
||||
Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall`. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
|
||||
|
||||
To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
+ "trustedDependencies": ["my-trusted-package"]
|
||||
}
|
||||
```
|
||||
|
||||
Bun reads this field and will run lifecycle scripts for `my-trusted-package`.
|
||||
|
||||
<!-- Bun maintains an allow-list of popular packages containing `postinstall` scripts that are known to be safe. To run lifecycle scripts for packages that aren't on this list, add the package to `trustedDependencies` in your package.json. -->
|
||||
|
||||
## Git dependencies
|
||||
|
||||
To add a dependency from a git repository:
|
||||
|
||||
```bash
|
||||
$ bun add git@github.com:moment/moment.git
|
||||
```
|
||||
|
||||
Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"dayjs": "git+https://github.com/iamkun/dayjs.git",
|
||||
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
|
||||
"moment": "git@github.com:moment/moment.git",
|
||||
"zod": "github:colinhacks/zod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tarball dependencies
|
||||
|
||||
A package name can correspond to a publicly hosted `.tgz` file. During installation, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
|
||||
|
||||
```sh
|
||||
$ bun add zod@https://registry.npmjs.org/zod/-/zod-3.21.4.tgz
|
||||
```
|
||||
|
||||
This will add the following line to your `package.json`:
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,36 +1,12 @@
|
||||
## `bun init`
|
||||
|
||||
Scaffold an empty project with the interactive `bun init` command.
|
||||
|
||||
```bash
|
||||
$ bun init
|
||||
bun init helps you get started with a minimal project and tries to
|
||||
guess sensible defaults. Press ^C anytime to quit.
|
||||
|
||||
package name (quickstart):
|
||||
entry point (index.ts):
|
||||
|
||||
Done! A package.json file was saved in the current directory.
|
||||
+ index.ts
|
||||
+ .gitignore
|
||||
+ tsconfig.json (for editor auto-complete)
|
||||
+ README.md
|
||||
|
||||
To get started, run:
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
|
||||
|
||||
## `bun create`
|
||||
|
||||
{% callout %}
|
||||
**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
|
||||
{% /callout %}
|
||||
|
||||
Template a new Bun project with `bun create`. This is a flexible command that can be used to create a new project with a `create-<template>` npm package, a GitHub repo, or a local template.
|
||||
|
||||
### From `npm`
|
||||
If you're looking to create a brand new empty project, use [`bun init`](/docs/cli/init).
|
||||
|
||||
## From `npm`
|
||||
|
||||
```sh
|
||||
$ bun create <template> [<destination>]
|
||||
@@ -45,7 +21,7 @@ $ bunx create-remix
|
||||
|
||||
Refer to the documentation of the associated `create-<template>` package for complete documentation and usage instructions.
|
||||
|
||||
### From GitHub
|
||||
## From GitHub
|
||||
|
||||
This will download the contents of the GitHub repo to disk.
|
||||
|
||||
@@ -115,7 +91,7 @@ $ bun create https://github.com/ahfarmer/calculator ./myapp
|
||||
|
||||
Bun installs the files as they currently exist current default branch (usually `main` or `master`). Unlike `git clone` it doesn't download the commit history or configure a remote. -->
|
||||
|
||||
### From a local template
|
||||
## From a local template
|
||||
|
||||
{% callout %}
|
||||
**⚠️ Warning** — Unlike remote templates, running `bun create` with a local template will delete the entire destination folder if it already exists! Be careful.
|
||||
@@ -59,8 +59,8 @@ optional = true
|
||||
# Install local devDependencies (default: true)
|
||||
dev = true
|
||||
|
||||
# Install peerDependencies (default: false)
|
||||
peer = false
|
||||
# Install peerDependencies (default: true)
|
||||
peer = true
|
||||
|
||||
# When using `bun install -g`, install packages here
|
||||
globalDir = "~/.bun/install/global"
|
||||
@@ -170,7 +170,7 @@ bun stores normalized `cpu` and `os` values from npm in the lockfile, along with
|
||||
|
||||
## Peer dependencies?
|
||||
|
||||
Peer dependencies are handled similarly to yarn. `bun install` does not automatically install peer dependencies and will try to choose an existing dependency.
|
||||
Peer dependencies are handled similarly to yarn. `bun install` will automatically install peer dependencies. If the dependency is marked optional in `peerDependenciesMeta`, an existing dependency will be chosen if possible.
|
||||
|
||||
## Lockfile
|
||||
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
## `bun init`
|
||||
|
||||
Scaffold an empty project with `bun init`. It's an interactive tool.
|
||||
|
||||
```bash
|
||||
$ bun init
|
||||
bun init helps you get started with a minimal project and tries to
|
||||
guess sensible defaults. Press ^C anytime to quit.
|
||||
|
||||
package name (quickstart):
|
||||
entry point (index.ts):
|
||||
|
||||
Done! A package.json file was saved in the current directory.
|
||||
+ index.ts
|
||||
+ .gitignore
|
||||
+ tsconfig.json (for editor auto-complete)
|
||||
+ README.md
|
||||
|
||||
To get started, run:
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
|
||||
|
||||
## `bun create`
|
||||
|
||||
Template a new Bun project with `bun create`.
|
||||
|
||||
```bash
|
||||
$ bun create <template> <destination>
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
|
||||
{% /callout %}
|
||||
|
||||
A template can take a number of forms:
|
||||
|
||||
```bash
|
||||
$ bun create <template> # an official template (remote)
|
||||
$ bun create <username>/<repo> # a GitHub repo (remote)
|
||||
$ bun create <local-template> # a custom template (local)
|
||||
```
|
||||
|
||||
Running `bun create` performs the following steps:
|
||||
|
||||
- Download the template (remote templates only)
|
||||
- Copy all template files into the destination folder. By default Bun will _not overwrite_ any existing files. Use the `--force` flag to overwrite existing files.
|
||||
- Install dependencies with `bun install`.
|
||||
- Initialize a fresh Git repo. Opt out with the `--no-git` flag.
|
||||
- Run the template's configured `start` script, if defined.
|
||||
|
||||
<!-- ## Official templates
|
||||
|
||||
The following official templates are available.
|
||||
|
||||
```bash
|
||||
bun create next ./myapp
|
||||
bun create react ./myapp
|
||||
bun create svelte-kit ./myapp
|
||||
bun create elysia ./myapp
|
||||
bun create hono ./myapp
|
||||
bun create kingworld ./myapp
|
||||
```
|
||||
|
||||
Each of these corresponds to a directory in the [bun-community/create-templates](https://github.com/bun-community/create-templates) repo. If you think a major framework is missing, please open a PR there. This list will change over time as additional examples are added. To see an up-to-date list, run `bun create` with no arguments.
|
||||
|
||||
```bash
|
||||
$ bun create
|
||||
Welcome to bun! Create a new project by pasting any of the following:
|
||||
<list of templates>
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
⚡️ **Speed** — At the time of writing, `bun create react app` runs ~11x faster on a M1 Macbook Pro than `yarn create react-app app`.
|
||||
{% /callout %} -->
|
||||
|
||||
## GitHub repos
|
||||
|
||||
A template of the form `<username>/<repo>` will be downloaded from GitHub.
|
||||
|
||||
```bash
|
||||
$ bun create ahfarmer/calculator ./myapp
|
||||
```
|
||||
|
||||
Complete GitHub URLs will also work:
|
||||
|
||||
```bash
|
||||
$ bun create github.com/ahfarmer/calculator ./myapp
|
||||
$ bun create https://github.com/ahfarmer/calculator ./myapp
|
||||
```
|
||||
|
||||
Bun installs the files as they currently exist current default branch (usually `main`). Unlike `git clone` it doesn't download the commit history or configure a remote.
|
||||
|
||||
## Local templates
|
||||
|
||||
{% callout %}
|
||||
**⚠️ Warning** — Unlike remote templates, running `bun create` with a local template will delete the entire destination folder if it already exists! Be careful.
|
||||
{% /callout %}
|
||||
Bun's templater can be extended to support custom templates defined on your local file system. These templates should live in one of the following directories:
|
||||
|
||||
- `$HOME/.bun-create/<name>`: global templates
|
||||
- `<project root>/.bun-create/<name>`: project-specific templates
|
||||
|
||||
{% callout %}
|
||||
**Note** — You can customize the global template path by setting the `BUN_CREATE_DIR` environment variable.
|
||||
{% /callout %}
|
||||
|
||||
To create a local template, navigate to `$HOME/.bun-create` and create a new directory with the desired name of your template.
|
||||
|
||||
```bash
|
||||
$ cd $HOME/.bun-create
|
||||
$ mkdir foo
|
||||
$ cd foo
|
||||
```
|
||||
|
||||
Then, create a `package.json` file in that directory with the following contents:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
You can run `bun create foo` elsewhere on your file system to verify that Bun is correctly finding your local template.
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- `postinstall`
|
||||
- runs after installing dependencies
|
||||
|
||||
---
|
||||
|
||||
- `preinstall`
|
||||
- runs before installing dependencies
|
||||
|
||||
<!-- ---
|
||||
|
||||
- `start`
|
||||
- a command to auto-start the application -->
|
||||
|
||||
{% /table %}
|
||||
|
||||
Each of these can correspond to a string or array of strings. An array of commands will be executed in order. Here is an example:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@bun-examples/simplereact",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"bun-create": {
|
||||
"preinstall": "echo 'Installing...'", // a single command
|
||||
"postinstall": ["echo 'Done!'"], // an array of commands
|
||||
"start": "bun run echo 'Hello world!'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When cloning a template, `bun create` will automatically remove the `"bun-create"` section from `package.json` before writing it to the destination folder.
|
||||
|
||||
## Reference
|
||||
|
||||
### CLI flags
|
||||
|
||||
{% table %}
|
||||
|
||||
- Flag
|
||||
- Description
|
||||
|
||||
---
|
||||
|
||||
- `--force`
|
||||
- Overwrite existing files
|
||||
|
||||
---
|
||||
|
||||
- `--no-install`
|
||||
- Skip installing `node_modules` & tasks
|
||||
|
||||
---
|
||||
|
||||
- `--no-git`
|
||||
- Don’t initialize a git repository
|
||||
|
||||
---
|
||||
|
||||
- `--open`
|
||||
- Start & open in-browser after finish
|
||||
|
||||
{% /table %}
|
||||
|
||||
### Environment variables
|
||||
|
||||
{% table %}
|
||||
|
||||
- Name
|
||||
- Description
|
||||
|
||||
---
|
||||
|
||||
- `GITHUB_API_DOMAIN`
|
||||
- If you’re using a GitHub enterprise or a proxy, you can customize the GitHub domain Bun pings for downloads
|
||||
|
||||
---
|
||||
|
||||
- `GITHUB_API_TOKEN`
|
||||
- This lets `bun create` work with private repositories or if you get rate-limited
|
||||
|
||||
{% /table %}
|
||||
|
||||
{% details summary="How `bun create` works" %}
|
||||
|
||||
When you run `bun create ${template} ${destination}`, here’s what happens:
|
||||
|
||||
IF remote template
|
||||
|
||||
1. GET `registry.npmjs.org/@bun-examples/${template}/latest` and parse it
|
||||
2. GET `registry.npmjs.org/@bun-examples/${template}/-/${template}-${latestVersion}.tgz`
|
||||
3. Decompress & extract `${template}-${latestVersion}.tgz` into `${destination}`
|
||||
|
||||
- If there are files that would overwrite, warn and exit unless `--force` is passed
|
||||
|
||||
IF GitHub repo
|
||||
|
||||
1. Download the tarball from GitHub’s API
|
||||
2. Decompress & extract into `${destination}`
|
||||
|
||||
- If there are files that would overwrite, warn and exit unless `--force` is passed
|
||||
|
||||
ELSE IF local template
|
||||
|
||||
1. Open local template folder
|
||||
2. Delete destination directory recursively
|
||||
3. Copy files recursively using the fastest system calls available (on macOS `fcopyfile` and Linux, `copy_file_range`). Do not copy or traverse into `node_modules` folder if exists (this alone makes it faster than `cp`)
|
||||
|
||||
4. Parse the `package.json` (again!), update `name` to be `${basename(destination)}`, remove the `bun-create` section from the `package.json` and save the updated `package.json` to disk.
|
||||
- IF Next.js is detected, add `bun-framework-next` to the list of dependencies
|
||||
- IF Create React App is detected, add the entry point in /src/index.{js,jsx,ts,tsx} to `public/index.html`
|
||||
- IF Relay is detected, add `bun-macro-relay` so that Relay works
|
||||
5. Auto-detect the npm client, preferring `pnpm`, `yarn` (v1), and lastly `npm`
|
||||
6. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
|
||||
7. Run `${npmClient} install` unless `--no-install` is passed OR no dependencies are in package.json
|
||||
8. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
|
||||
9. Run `git init; git add -A .; git commit -am "Initial Commit";`
|
||||
|
||||
- Rename `gitignore` to `.gitignore`. NPM automatically removes `.gitignore` files from appearing in packages.
|
||||
- If there are dependencies, this runs in a separate thread concurrently while node_modules are being installed
|
||||
- Using libgit2 if available was tested and performed 3x slower in microbenchmarks
|
||||
|
||||
{% /details %}
|
||||
@@ -1,3 +1,27 @@
|
||||
Scaffold an empty Bun project with the interactive `bun init` command.
|
||||
|
||||
```bash
|
||||
$ bun init
|
||||
bun init helps you get started with a minimal project and tries to
|
||||
guess sensible defaults. Press ^C anytime to quit.
|
||||
|
||||
package name (quickstart):
|
||||
entry point (index.ts):
|
||||
|
||||
Done! A package.json file was saved in the current directory.
|
||||
+ index.ts
|
||||
+ .gitignore
|
||||
+ tsconfig.json (for editor auto-complete)
|
||||
+ README.md
|
||||
|
||||
To get started, run:
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
|
||||
|
||||
{% details summary="How `bun init` works" %}
|
||||
|
||||
`bun init` is a quick way to start a blank project with Bun. It guesses with sane defaults and is non-destructive when run multiple times.
|
||||
|
||||

|
||||
@@ -13,6 +37,4 @@ If you pass `-y` or `--yes`, it will assume you want to continue without asking
|
||||
|
||||
At the end, it runs `bun install` to install `bun-types`.
|
||||
|
||||
#### How is `bun init` different than `bun create`?
|
||||
|
||||
`bun init` is for blank projects. `bun create` applies templates.
|
||||
{% /details %}
|
||||
@@ -9,7 +9,7 @@ The `bun` CLI contains a Node.js-compatible package manager designed to be a dra
|
||||
{% /callout %}
|
||||
|
||||
{% details summary="For Linux users" %}
|
||||
The minimum Linux Kernel version is 5.1. If you're on Linux kernel 5.1 - 5.5, `bun install` should still work, but HTTP requests will be slow due to a lack of support for io_uring's `connect()` operation.
|
||||
The recommended minimum Linux Kernel version is 5.6. If you're on Linux kernel 5.1 - 5.5, `bun install` will work, but HTTP requests will be slow due to a lack of support for io_uring's `connect()` operation.
|
||||
|
||||
If you're using Ubuntu 20.04, here's how to install a [newer kernel](https://wiki.ubuntu.com/Kernel/LTSEnablementStack):
|
||||
|
||||
@@ -23,41 +23,19 @@ sudo apt install --install-recommends linux-generic-hwe-20.04
|
||||
|
||||
{% /details %}
|
||||
|
||||
## `bun install`
|
||||
|
||||
To install all dependencies of a project:
|
||||
|
||||
```bash
|
||||
$ bun install
|
||||
```
|
||||
|
||||
On Linux, `bun install` tends to install packages 20-100x faster than `npm install`. On macOS, it's more like 4-80x.
|
||||
|
||||

|
||||
|
||||
Running `bun install` will:
|
||||
|
||||
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun does not install `peerDependencies` by default.
|
||||
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun will install `peerDependencies` by default.
|
||||
- **Run** your project's `{pre|post}install` and `{pre|post}prepare` scripts at the appropriate time. For security reasons Bun _does not execute_ lifecycle scripts of installed dependencies.
|
||||
- **Write** a `bun.lockb` lockfile to the project root.
|
||||
|
||||
To install in production mode (i.e. without `devDependencies` or `optionalDependencies`):
|
||||
|
||||
```bash
|
||||
$ bun install --production
|
||||
```
|
||||
|
||||
To install with reproducible dependencies, use `--frozen-lockfile`. If your `package.json` disagrees with `bun.lockb`, Bun will exit with an error. This is useful for production builds and CI environments.
|
||||
|
||||
```bash
|
||||
$ bun install --frozen-lockfile
|
||||
```
|
||||
|
||||
To perform a dry run (i.e. don't actually install anything):
|
||||
|
||||
```bash
|
||||
$ bun install --dry-run
|
||||
```
|
||||
## Logging
|
||||
|
||||
To modify logging verbosity:
|
||||
|
||||
@@ -66,86 +44,59 @@ $ bun install --verbose # debug logging
|
||||
$ bun install --silent # no logging
|
||||
```
|
||||
|
||||
{% details summary="Configuring behavior" %}
|
||||
The default behavior of `bun install` can be configured in `bunfig.toml`:
|
||||
## Lifecycle scripts
|
||||
|
||||
```toml
|
||||
[install]
|
||||
Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts like `postinstall` for installed dependencies. Executing arbitrary scripts represents a potential security risk.
|
||||
|
||||
# whether to install optionalDependencies
|
||||
optional = true
|
||||
To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
|
||||
|
||||
# whether to install devDependencies
|
||||
dev = true
|
||||
|
||||
# whether to install peerDependencies
|
||||
peer = false
|
||||
|
||||
# equivalent to `--production` flag
|
||||
production = false
|
||||
|
||||
# equivalent to `--frozen-lockfile` flag
|
||||
frozenLockfile = false
|
||||
|
||||
# equivalent to `--dry-run` flag
|
||||
dryRun = false
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
+ "trustedDependencies": ["my-trusted-package"]
|
||||
}
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
Then re-install the package. Bun will read this field and run lifecycle scripts for `my-trusted-package`.
|
||||
|
||||
## `bun add`
|
||||
## Workspaces
|
||||
|
||||
To add a particular package:
|
||||
Bun supports `"workspaces"` in package.json. For complete documentation refer to [Package manager > Workspaces](/docs/install/workspaces).
|
||||
|
||||
```bash
|
||||
$ bun add preact
|
||||
```
|
||||
|
||||
To specify a version, version range, or tag:
|
||||
|
||||
```bash
|
||||
$ bun add zod@3.20.0
|
||||
$ bun add zod@^3.0.0
|
||||
$ bun add zod@latest
|
||||
```
|
||||
|
||||
To add a package as a dev dependency (`"devDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --dev @types/react
|
||||
$ bun add -d @types/react
|
||||
```
|
||||
|
||||
To add a package as an optional dependency (`"optionalDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --optional lodash
|
||||
```
|
||||
|
||||
To add a package and pin to the resolved version, use `--exact`. This will resolve the version of the package and add it to your `package.json` with an exact version number instead of a version range.
|
||||
|
||||
```bash
|
||||
$ bun add react --exact
|
||||
```
|
||||
|
||||
This will add the following to your `package.json`:
|
||||
|
||||
```jsonc
|
||||
```json#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"workspaces": ["packages/*"],
|
||||
"dependencies": {
|
||||
// without --exact
|
||||
"react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0
|
||||
|
||||
// with --exact
|
||||
"react": "18.2.0" // this matches only 18.2.0 exactly
|
||||
"preact": "^10.5.13"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To install a package globally:
|
||||
## Overrides and resolutions
|
||||
|
||||
Bun supports npm's `"overrides"` and Yarn's `"resolutions"` in `package.json`. These are mechanisms for specifying a version range for _metadependencies_—the dependencies of your dependencies. Refer to [Package manager > Overrides and resolutions](/docs/install/overrides) for complete documentation.
|
||||
|
||||
```json-diff#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"foo": "^2.0.0"
|
||||
},
|
||||
+ "overrides": {
|
||||
+ "bar": "~4.4.0"
|
||||
+ }
|
||||
}
|
||||
```
|
||||
|
||||
## Global packages
|
||||
|
||||
To install a package globally, use the `-g`/`--global` flag. Typically this is used for installing command-line tools.
|
||||
|
||||
```bash
|
||||
$ bun add --global cowsay # or `bun add -g cowsay`
|
||||
$ bun install --global cowsay # or `bun install -g cowsay`
|
||||
$ cowsay "Bun!"
|
||||
______
|
||||
< Bun! >
|
||||
@@ -157,159 +108,75 @@ $ cowsay "Bun!"
|
||||
|| ||
|
||||
```
|
||||
|
||||
{% details summary="Configuring global installation behavior" %}
|
||||
## Production mode
|
||||
|
||||
```toml
|
||||
[install]
|
||||
# where `bun install --global` installs packages
|
||||
globalDir = "~/.bun/install/global"
|
||||
|
||||
# where globally-installed package bins are linked
|
||||
globalBinDir = "~/.bun/bin"
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
To view a complete list of options for a given command:
|
||||
To install in production mode (i.e. without `devDependencies` or `optionalDependencies`):
|
||||
|
||||
```bash
|
||||
$ bun add --help
|
||||
$ bun install --production
|
||||
```
|
||||
|
||||
## `bun remove`
|
||||
|
||||
To remove a dependency:
|
||||
For reproducible installs, use `--frozen-lockfile`. This will install the exact versions of each package specified in the lockfile. If your `package.json` disagrees with `bun.lockb`, Bun will exit with an error. The lockfile will not be updated.
|
||||
|
||||
```bash
|
||||
$ bun remove preact
|
||||
$ bun install --frozen-lockfile
|
||||
```
|
||||
|
||||
## `bun update`
|
||||
For more information on Bun's binary lockfile `bun.lockb`, refer to [Package manager > Lockfile](/docs/install/lockfile).
|
||||
|
||||
To update all dependencies to the latest version _that's compatible with the version range specified in your `package.json`_:
|
||||
## Dry run
|
||||
|
||||
```sh
|
||||
$ bun update
|
||||
```
|
||||
|
||||
This will not edit your `package.json`. There's currently no command to force-update all dependencies to the latest version regardless version ranges.
|
||||
|
||||
## `bun link`
|
||||
|
||||
Use `bun link` in a local directory to register the current package as a "linkable" package.
|
||||
To perform a dry run (i.e. don't actually install anything):
|
||||
|
||||
```bash
|
||||
$ cd /path/to/cool-pkg
|
||||
$ cat package.json
|
||||
{
|
||||
"name": "cool-pkg",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
$ bun link
|
||||
bun link v1.x (7416672e)
|
||||
Success! Registered "cool-pkg"
|
||||
|
||||
To use cool-pkg in a project, run:
|
||||
bun link cool-pkg
|
||||
|
||||
Or add it in dependencies in your package.json file:
|
||||
"cool-pkg": "link:cool-pkg"
|
||||
$ bun install --dry-run
|
||||
```
|
||||
|
||||
This package can now be "linked" into other projects using `bun link cool-pkg`. This will create a symlink in the `node_modules` directory of the target project, pointing to the local directory.
|
||||
## Non-npm dependencies
|
||||
|
||||
```bash
|
||||
$ cd /path/to/my-app
|
||||
$ bun link cool-pkg
|
||||
```
|
||||
Bun supports installing dependencies from Git, GitHub, and local or remotely-hosted tarballs. For complete documentation refer to [Package manager > Git, GitHub, and tarball dependencies](/docs/cli/add).
|
||||
|
||||
In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencies` field of your app's package.json with a special version specifier that tells Bun to load from the registered local directory instead of installing from `npm`:
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
+ "cool-pkg": "link:cool-pkg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Trusted dependencies
|
||||
|
||||
Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall`. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
|
||||
|
||||
<!-- Bun maintains an allow-list of popular packages containing `postinstall` scripts that are known to be safe. To run lifecycle scripts for packages that aren't on this list, add the package to `trustedDependencies` in your package.json. -->
|
||||
|
||||
To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
|
||||
|
||||
<!-- ```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
+ "trustedDependencies": {
|
||||
+ "my-trusted-package": "*"
|
||||
+ }
|
||||
}
|
||||
``` -->
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
+ "trustedDependencies": ["my-trusted-package"]
|
||||
}
|
||||
```
|
||||
|
||||
Bun reads this field and will run lifecycle scripts for `my-trusted-package`.
|
||||
|
||||
<!-- If you specify a version range, Bun will only execute lifecycle scripts if the resolved package version matches the range. -->
|
||||
<!--
|
||||
```json
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"trustedDependencies": {
|
||||
"my-trusted-package": "^1.0.0"
|
||||
}
|
||||
}
|
||||
``` -->
|
||||
|
||||
## Git dependencies
|
||||
|
||||
To add a dependency from a git repository:
|
||||
|
||||
```bash
|
||||
$ bun install git@github.com:moment/moment.git
|
||||
```
|
||||
|
||||
Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
|
||||
|
||||
```json
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"dayjs": "git+https://github.com/iamkun/dayjs.git",
|
||||
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
|
||||
"moment": "git@github.com:moment/moment.git",
|
||||
"zod": "github:colinhacks/zod"
|
||||
"zod": "github:colinhacks/zod",
|
||||
"react": "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tarball dependencies
|
||||
## Configuration
|
||||
|
||||
A package name can correspond to a publicly hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
|
||||
The default behavior of `bun install` can be configured in `bunfig.toml`. The default values are shown below.
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
|
||||
}
|
||||
}
|
||||
```toml
|
||||
[install]
|
||||
|
||||
# whether to install optionalDependencies
|
||||
optional = true
|
||||
|
||||
# whether to install devDependencies
|
||||
dev = true
|
||||
|
||||
# whether to install peerDependencies
|
||||
peer = true
|
||||
|
||||
# equivalent to `--production` flag
|
||||
production = false
|
||||
|
||||
# equivalent to `--frozen-lockfile` flag
|
||||
frozenLockfile = false
|
||||
|
||||
# equivalent to `--dry-run` flag
|
||||
dryRun = false
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
Looking to speed up your CI? Use the official `oven-sh/setup-bun` action to install `bun` in a GitHub Actions pipeline.
|
||||
Looking to speed up your CI? Use the official [`oven-sh/setup-bun`](https://github.com/oven-sh/setup-bun) action to install `bun` in a GitHub Actions pipeline.
|
||||
|
||||
```yaml#.github/workflows/release.yml
|
||||
name: bun-types
|
||||
|
||||
46
docs/cli/link.md
Normal file
46
docs/cli/link.md
Normal file
@@ -0,0 +1,46 @@
|
||||
Use `bun link` in a local directory to register the current package as a "linkable" package.
|
||||
|
||||
```bash
|
||||
$ cd /path/to/cool-pkg
|
||||
$ cat package.json
|
||||
{
|
||||
"name": "cool-pkg",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
$ bun link
|
||||
bun link v1.x (7416672e)
|
||||
Success! Registered "cool-pkg"
|
||||
|
||||
To use cool-pkg in a project, run:
|
||||
bun link cool-pkg
|
||||
|
||||
Or add it in dependencies in your package.json file:
|
||||
"cool-pkg": "link:cool-pkg"
|
||||
```
|
||||
|
||||
This package can now be "linked" into other projects using `bun link cool-pkg`. This will create a symlink in the `node_modules` directory of the target project, pointing to the local directory.
|
||||
|
||||
```bash
|
||||
$ cd /path/to/my-app
|
||||
$ bun link cool-pkg
|
||||
```
|
||||
|
||||
In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencies` field of your app's package.json with a special version specifier that tells Bun to load from the registered local directory instead of installing from `npm`:
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
+ "cool-pkg": "link:cool-pkg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To _unregister_ a local package, navigate to the package's root directory and run `bun unlink`.
|
||||
|
||||
```bash
|
||||
$ cd /path/to/cool-pkg
|
||||
$ bun unlink
|
||||
bun unlink v1.x (7416672e)
|
||||
```
|
||||
5
docs/cli/remove.md
Normal file
5
docs/cli/remove.md
Normal file
@@ -0,0 +1,5 @@
|
||||
To remove a dependency:
|
||||
|
||||
```bash
|
||||
$ bun remove ts-node
|
||||
```
|
||||
7
docs/cli/update.md
Normal file
7
docs/cli/update.md
Normal file
@@ -0,0 +1,7 @@
|
||||
To update all dependencies to the latest version _that's compatible with the version range specified in your `package.json`_:
|
||||
|
||||
```sh
|
||||
$ bun update
|
||||
```
|
||||
|
||||
This will not edit your `package.json`. There's currently no command to force-update all dependencies to the latest version regardless version ranges.
|
||||
140
docs/guides/ecosystem/docker.md
Normal file
140
docs/guides/ecosystem/docker.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
name: Containerize a Bun application with Docker
|
||||
---
|
||||
|
||||
{% callout %}
|
||||
This guide assumes you already have [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed.
|
||||
{% /callout %}
|
||||
|
||||
[Docker](https://www.docker.com) is a platform for packaging and running an application as a lightweight, portable _container_ that encapsulates all the necessary dependencies.
|
||||
|
||||
---
|
||||
|
||||
To _containerize_ our application, we define a `Dockerfile`. This file contains a list of instructions to initialize the container, copy our local project files into it, install dependencies, and starts the application.
|
||||
|
||||
```docker#Dockerfile
|
||||
# use the official Bun image
|
||||
# see all versions at https://hub.docker.com/r/oven/bun/tags
|
||||
FROM oven/bun:1 as base
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# install dependencies into temp directory
|
||||
# this will cache them and speed up future builds
|
||||
FROM base AS install
|
||||
RUN mkdir -p /temp/dev
|
||||
COPY package.json bun.lockb /temp/dev/
|
||||
RUN cd /temp/dev && bun install --frozen-lockfile
|
||||
|
||||
# install with --production (exclude devDependencies)
|
||||
RUN mkdir -p /temp/prod
|
||||
COPY package.json bun.lockb /temp/prod/
|
||||
RUN cd /temp/prod && bun install --frozen-lockfile --production
|
||||
|
||||
# copy node_modules from temp directory
|
||||
# then copy all (non-ignored) project files into the image
|
||||
FROM install AS prerelease
|
||||
COPY --from=install /temp/dev/node_modules node_modules
|
||||
COPY . .
|
||||
|
||||
# [optional] tests & build
|
||||
ENV NODE_ENV=production
|
||||
RUN bun test
|
||||
RUN bun run build
|
||||
|
||||
# copy production dependencies and source code into final image
|
||||
FROM base AS release
|
||||
COPY --from=install /temp/prod/node_modules node_modules
|
||||
COPY --from=prerelease /usr/src/app/index.ts .
|
||||
COPY --from=prerelease /usr/src/app/package.json .
|
||||
|
||||
# run the app
|
||||
USER bun
|
||||
EXPOSE 3000/tcp
|
||||
ENTRYPOINT [ "bun", "run", "index.ts" ]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Now that you have your docker image, let's look at `.dockerignore` which has the same syntax as `.gitignore`, here you need to specify the files/directories that must not go in any stage of the docker build. An example for a ignore file is
|
||||
|
||||
```txt#.dockerignore
|
||||
node_modules
|
||||
Dockerfile*
|
||||
docker-compose*
|
||||
.dockerignore
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
LICENSE
|
||||
.vscode
|
||||
Makefile
|
||||
helm-charts
|
||||
.env
|
||||
.editorconfig
|
||||
.idea
|
||||
coverage*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
We'll now use `docker build` to convert this `Dockerfile` into a _Docker image_, is a self-contained template containing all the dependencies and configuration required to run the application.
|
||||
|
||||
The `-t` flag lets us specify a name for the image, and `--pull` tells Docker to automatically download the latest version of the base image (`oven/bun`). The initial build will take longer, as Docker will download all the base images and dependencies.
|
||||
|
||||
```bash
|
||||
$ docker build --pull -t bun-hello-world .
|
||||
[+] Building 0.9s (21/21) FINISHED
|
||||
=> [internal] load build definition from Dockerfile 0.0s
|
||||
=> => transferring dockerfile: 37B 0.0s
|
||||
=> [internal] load .dockerignore 0.0s
|
||||
=> => transferring context: 35B 0.0s
|
||||
=> [internal] load metadata for docker.io/oven/bun:1 0.8s
|
||||
=> [auth] oven/bun:pull token for registry-1.docker.io 0.0s
|
||||
=> [base 1/2] FROM docker.io/oven/bun:1@sha256:373265748d3cd3624cb3f3ee6004f45b1fc3edbd07a622aeeec17566d2756997 0.0s
|
||||
=> [internal] load build context 0.0s
|
||||
=> => transferring context: 155B 0.0s
|
||||
# ...lots of commands...
|
||||
=> exporting to image 0.0s
|
||||
=> => exporting layers 0.0s
|
||||
=> => writing image sha256:360663f7fdcd6f11e8e94761d5592e2e4dfc8d167f034f15cd5a863d5dc093c4 0.0s
|
||||
=> => naming to docker.io/library/bun-hello-world 0.0s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
We've built a new _Docker image_. Now let's use that image to spin up an actual, running _container_.
|
||||
|
||||
We'll use `docker run` to start a new container using the `bun-hello-world` image. It will be run in _detached_ mode (`-d`) and we'll map the container's port 3000 to our local machine's port 3000 (`-p 3000:3000`).
|
||||
|
||||
The `run` command prints a string representing the _container ID_.
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 3000:3000 bun-hello-world
|
||||
7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The container is now running in the background. Visit [localhost:3000](http://localhost:3000). You should see a `Hello, World!` message.
|
||||
|
||||
---
|
||||
|
||||
To stop the container, we'll use `docker stop <container-id>`.
|
||||
|
||||
```sh
|
||||
$ docker stop 7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If you can't find the container ID, you can use `docker ps` to list all running containers.
|
||||
|
||||
```sh
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7f03e212a15e bun-hello-world "bun run index.ts" 2 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp flamboyant_cerf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
That's it! Refer to the [Docker documentation](https://docs.docker.com/) for more advanced usage.
|
||||
54
docs/guides/ecosystem/pm2.md
Normal file
54
docs/guides/ecosystem/pm2.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: Run Bun as a daemon with PM2
|
||||
---
|
||||
|
||||
[PM2](https://pm2.keymetrics.io/) is a popular process manager that manages and runs your applications as daemons (background processes).
|
||||
|
||||
It offers features like process monitoring, automatic restarts, and easy scaling. Using a process manager is common when deploying a Bun application on a cloud-hosted virtual private server (VPS), as it:
|
||||
|
||||
- Keeps your Node.js application running continuously.
|
||||
- Ensure high availability and reliability of your application.
|
||||
- Monitor and manage multiple processes with ease.
|
||||
- Simplify the deployment process.
|
||||
|
||||
---
|
||||
|
||||
You can use PM2 with Bun in two ways: as a CLI option or in a configuration file.
|
||||
|
||||
### With `--interpreter`
|
||||
|
||||
---
|
||||
|
||||
To start your application with PM2 and Bun as the interpreter, open your terminal and run the following command:
|
||||
|
||||
```bash
|
||||
pm2 start --interpreter ~/.bun/bin/bun index.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### With a configuration file
|
||||
|
||||
---
|
||||
|
||||
Alternatively, you can create a PM2 configuration file. Create a file named `pm2.config.js` in your project directory and add the following content.
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
name: "app", // Name of your application
|
||||
script: "index.ts", // Entry point of your application
|
||||
interpreter: "~/.bun/bin/bun", // Path to the Bun interpreter
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
After saving the file, you can start your application with PM2
|
||||
|
||||
```bash
|
||||
pm2 start pm2.config.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
That’s it! Your JavaScript/TypeScript web server is now running as a daemon with PM2 using Bun as the interpreter.
|
||||
@@ -4,7 +4,7 @@ name: Use React and JSX
|
||||
|
||||
React just works with Bun. Bun supports `.jsx` and `.tsx` files out of the box.
|
||||
|
||||
Remember that JSX is just a special syntax for including HTML-like syntax in JavaScript files. It's commonReact uses JSX syntax, as do other React alternatives like [Preact](https://preactjs.com/) and [Solid](https://www.solidjs.com/). Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
|
||||
Remember that JSX is just a special syntax for including HTML-like syntax in JavaScript files. React uses JSX syntax, as do alternatives like [Preact](https://preactjs.com/) and [Solid](https://www.solidjs.com/). Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
|
||||
|
||||
---
|
||||
|
||||
@@ -27,7 +27,7 @@ const element = jsx("h1", { children: "Hello, world!" });
|
||||
|
||||
---
|
||||
|
||||
This code requires `react` to run, so make sure you you've installed React.
|
||||
This code requires `react` to run, so make sure you've installed React.
|
||||
|
||||
```bash
|
||||
$ bun install react
|
||||
|
||||
113
docs/guides/ecosystem/systemd.md
Normal file
113
docs/guides/ecosystem/systemd.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
name: Run Bun as a daemon with systemd
|
||||
---
|
||||
|
||||
[systemd](https://systemd.io) is an init system and service manager for Linux operating systems that manages the startup and control of system processes and services.
|
||||
|
||||
<!-- systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, maintains mount and auto mount points, and implements an elaborate transactional dependency-based service control logic. systemd supports SysV and LSB init scripts and works as a replacement for sysvinit. -->
|
||||
|
||||
<!-- Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution. -->
|
||||
|
||||
---
|
||||
|
||||
To run a Bun application as a daemon using **systemd** you'll need to create a _service file_ in `/lib/systemd/system/`.
|
||||
|
||||
```sh
|
||||
$ cd /lib/systemd/system
|
||||
$ touch my-app.service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Here is a typical service file that runs an application on system start. You can use this as a template for your own service. Replace `YOUR_USER` with the name of the user you want to run the application as. To run as `root`, replace `YOUR_USER` with `root`, though this is generally not recommended for security reasons.
|
||||
|
||||
Refer to the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.service.html) for more information on each setting.
|
||||
|
||||
```ini#my-app.service
|
||||
[Unit]
|
||||
# describe the app
|
||||
Description=My App
|
||||
# start the app after the network is available
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# usually you'll use 'simple'
|
||||
# one of https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
|
||||
Type=simple
|
||||
# which user to use when starting the app
|
||||
User=YOUR_USER
|
||||
# path to your application's root directory
|
||||
WorkingDirectory=/home/YOUR_USER/path/to/my-app
|
||||
# the command to start the app
|
||||
# requires absolute paths
|
||||
ExecStart=/home/YOUR_USER/.bun/bin/bun run index.ts
|
||||
# restart policy
|
||||
# one of {no|on-success|on-failure|on-abnormal|on-watchdog|on-abort|always}
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
# start the app automatically
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If your application starts a webserver, note that non-`root` users are not able to listen on ports 80 or 443 by default. To permanently allow Bun to listen on these ports when executed by a non-`root` user, use the following command. This step isn't necessary when running as `root`.
|
||||
|
||||
```bash
|
||||
$ sudo setcap CAP_NET_BIND_SERVICE=+eip ~/.bun/bin/bun
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
With the service file configured, you can now _enable_ the service. Once enabled, it will start automatically on reboot. This requires `sudo` permissions.
|
||||
|
||||
```bash
|
||||
$ sudo systemctl enable my-app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To start the service without rebooting, you can manually _start_ it.
|
||||
|
||||
```bash
|
||||
$ sudo systemctl start my-app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Check the status of your application with `systemctl status`. If you've started your app successfully, you should see something like this:
|
||||
|
||||
```bash
|
||||
$ sudo systemctl status my-app
|
||||
● my-app.service - My App
|
||||
Loaded: loaded (/lib/systemd/system/my-app.service; enabled; preset: enabled)
|
||||
Active: active (running) since Thu 2023-10-12 11:34:08 UTC; 1h 8min ago
|
||||
Main PID: 309641 (bun)
|
||||
Tasks: 3 (limit: 503)
|
||||
Memory: 40.9M
|
||||
CPU: 1.093s
|
||||
CGroup: /system.slice/my-app.service
|
||||
└─309641 /home/YOUR_USER/.bun/bin/bun run /home/YOUR_USER/application/index.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To update the service, edit the contents of the service file, then reload the daemon.
|
||||
|
||||
```bash
|
||||
$ sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
For a complete guide on the service unit configuration, you can check [this page](https://www.freedesktop.org/software/systemd/man/systemd.service.html). Or refer to this cheatsheet of common commands:
|
||||
|
||||
```bash
|
||||
$ sudo systemctl daemon-reload # tell systemd that some files got changed
|
||||
$ sudo systemctl enable my-app # enable the app (to allow auto-start)
|
||||
$ sudo systemctl disable my-app # disable the app (turns off auto-start)
|
||||
$ sudo systemctl start my-app # start the app if is stopped
|
||||
$ sudo systemctl stop my-app # stop the app
|
||||
$ sudo systemctl restart my-app # restart the app
|
||||
```
|
||||
@@ -30,8 +30,7 @@ bun install
|
||||
|
||||
Start the development server with the `vite` CLI using `bunx`.
|
||||
|
||||
The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>). After Bun 1.0 this flag will no longer be necessary.
|
||||
|
||||
The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>).
|
||||
```bash
|
||||
bunx --bun vite
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name: Add a peer dependency
|
||||
---
|
||||
|
||||
To add an npm package as a peer dependency, directly modify the `peerDependencies` object in your package.json. Running `bun install` will not install peer dependencies.
|
||||
To add an npm package as a peer dependency, directly modify the `peerDependencies` object in your package.json. Running `bun install` will install peer dependencies by default, unless marked optional in `peerDependenciesMeta`.
|
||||
|
||||
```json-diff
|
||||
{
|
||||
|
||||
@@ -47,4 +47,4 @@ Note that this only allows lifecycle scripts for the specific package listed in
|
||||
|
||||
---
|
||||
|
||||
See [Docs > Package manager > Trusted dependencies](/docs/cli/install#trusted-dependencies) for complete documentation of trusted dependencies.
|
||||
See [Docs > Package manager > Trusted dependencies](/docs/install/lifecycle) for complete documentation of trusted dependencies.
|
||||
|
||||
66
docs/guides/process/ipc.md
Normal file
66
docs/guides/process/ipc.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: Spawn a child process and communicate using IPC
|
||||
---
|
||||
|
||||
Use [`Bun.spawn()`](/docs/api/spawn) to spawn a child process. When spawning a second `bun` process, you can open a direct inter-process communication (IPC) channel between the two processes.
|
||||
|
||||
{%callout%}
|
||||
**Note** — This API is only compatible with other `bun` processes. Use `process.execPath` to get a path to the currently running `bun` executable.
|
||||
{%/callout%}
|
||||
|
||||
```ts#parent.ts
|
||||
const child = Bun.spawn(["bun", "child.ts"], {
|
||||
ipc(message) {
|
||||
/**
|
||||
* The message received from the sub process
|
||||
**/
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The parent process can send messages to the subprocess using the `.send()` method on the returned `Subprocess` instance. A reference to the sending subprocess is also available as the second argument in the `ipc` handler.
|
||||
|
||||
```ts#parent.ts
|
||||
const childProc = Bun.spawn(["bun", "child.ts"], {
|
||||
ipc(message, childProc) {
|
||||
/**
|
||||
* The message received from the sub process
|
||||
**/
|
||||
childProc.send("Respond to child")
|
||||
},
|
||||
});
|
||||
|
||||
childProc.send("I am your father"); // The parent can send messages to the child as well
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Meanwhile the child process can send messages to its parent using with `process.send()` and receive messages with `process.on("message")`. This is the same API used for `child_process.fork()` in Node.js.
|
||||
|
||||
```ts#child.ts
|
||||
process.send("Hello from child as string");
|
||||
process.send({ message: "Hello from child as object" });
|
||||
|
||||
process.on("message", (message) => {
|
||||
// print message from parent
|
||||
console.log(message);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
All messages are serialized using the JSC `serialize` API, which allows for the same set of [transferrable types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) supported by `postMessage` and `structuredClone`, including strings, typed arrays, streams, and objects.
|
||||
|
||||
```ts#child.ts
|
||||
// send a string
|
||||
process.send("Hello from child as string");
|
||||
|
||||
// send an object
|
||||
process.send({ message: "Hello from child as object" });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See [Docs > API > Child processes](/docs/api/spawn) for complete documentation.
|
||||
52
docs/guides/write-file/append.md
Normal file
52
docs/guides/write-file/append.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: Append content to a file
|
||||
---
|
||||
|
||||
Bun implements the `node:fs` module, which includes the `fs.appendFile` and `fs.appendFileSync` functions for appending content to files.
|
||||
|
||||
---
|
||||
|
||||
You can use `fs.appendFile` to asynchronously append data to a file, creating the file if it does not yet exist. The content can be a string or a `Buffer`.
|
||||
|
||||
```ts
|
||||
import { appendFile } from "node:fs/promises";
|
||||
|
||||
await appendFile("message.txt", "data to append");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To use the non-`Promise` API:
|
||||
|
||||
```ts
|
||||
import { appendFile } from "node:fs";
|
||||
|
||||
appendFile("message.txt", "data to append", err => {
|
||||
if (err) throw err;
|
||||
console.log('The "data to append" was appended to file!');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To specify the encoding of the content:
|
||||
|
||||
```js
|
||||
import { appendFile } from "node:fs";
|
||||
|
||||
appendFile("message.txt", "data to append", "utf8", callback);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To append the data synchronously, use `fs.appendFileSync`:
|
||||
|
||||
```ts
|
||||
import { appendFileSync } from "node:fs";
|
||||
|
||||
appendFileSync("message.txt", "data to append", "utf8");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See the [Node.js documentation](https://nodejs.org/api/fs.html#fspromisesappendfilepath-data-options) for more information.
|
||||
@@ -26,7 +26,7 @@ Get started with one of the quick links below, or read on to learn more about Bu
|
||||
{% arrowbutton href="/docs/installation" text="Install Bun" /%}
|
||||
{% arrowbutton href="/docs/quickstart" text="Do the quickstart" /%}
|
||||
{% arrowbutton href="/docs/cli/install" text="Install a package" /%}
|
||||
{% arrowbutton href="/docs/templates" text="Use a project template" /%}
|
||||
{% arrowbutton href="/docs/cli/bun-create" text="Use a project template" /%}
|
||||
{% arrowbutton href="/docs/bundler" text="Bundle code for production" /%}
|
||||
{% arrowbutton href="/docs/api/http" text="Build an HTTP server" /%}
|
||||
{% arrowbutton href="/docs/api/websockets" text="Build a Websocket server" /%}
|
||||
@@ -37,11 +37,14 @@ Get started with one of the quick links below, or read on to learn more about Bu
|
||||
|
||||
## What is a runtime?
|
||||
|
||||
JavaScript (or, more formally, ECMAScript) is just a _specification_ for a programming language. Anyone can write a JavaScript _engine_ that ingests a valid JavaScript program and executes it. The two most popular engines in use today are V8 (developed by Google) and JavaScriptCore (developed by Apple). Both are open source.
|
||||
JavaScript (or, more formally, ECMAScript) is just a _specification_ for a programming language. Anyone can write a JavaScript _engine_ that ingests a valid JavaScript program and executes it. The two most popular engines in use today are V8 (developed by Google)
|
||||
and JavaScriptCore (developed by Apple). Both are open source.
|
||||
|
||||
But most JavaScript programs don't run in a vacuum. They need a way to access the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute.
|
||||
|
||||
### Browsers
|
||||
|
||||
But most JavaScript programs don't run in a vacuum. They need a way to access the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute. Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
|
||||
Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
|
||||
|
||||
<!-- JavaScript runtime that exposes JavaScript engines are designed to run "vanilla" JavaScript programs, but it's often JavaScript _runtimes_ use an engine internally to execute the code and implement additional APIs that are then made available to executed programs.
|
||||
JavaScript was [initially designed](https://en.wikipedia.org/wiki/JavaScript) as a language to run in web browsers to implement interactivity and dynamic behavior in web pages. Browsers are the first JavaScript runtimes. JavaScript programs that are executed in browsers have access to a set of Web-specific global APIs on the `window` object. -->
|
||||
|
||||
@@ -39,7 +39,7 @@ On Linux, `bun install` tends to install packages 20-100x faster than `npm insta
|
||||
|
||||
Running `bun install` will:
|
||||
|
||||
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun does not install `peerDependencies` by default.
|
||||
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun will install `peerDependencies` by default.
|
||||
- **Run** your project's `{pre|post}install` scripts at the appropriate time. For security reasons Bun _does not execute_ lifecycle scripts of installed dependencies.
|
||||
- **Write** a `bun.lockb` lockfile to the project root.
|
||||
|
||||
@@ -81,7 +81,7 @@ optional = true
|
||||
dev = true
|
||||
|
||||
# whether to install peerDependencies
|
||||
peer = false
|
||||
peer = true
|
||||
|
||||
# equivalent to `--production` flag
|
||||
production = false
|
||||
|
||||
44
docs/install/lifecycle.md
Normal file
44
docs/install/lifecycle.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Packages on `npm` can define _lifecycle scripts_ in their `package.json`. Some of the most common are below, but there are [many others](https://docs.npmjs.com/cli/v10/using-npm/scripts).
|
||||
|
||||
- `preinstall`: Runs before the package is installed
|
||||
- `postinstall`: Runs after the package is installed
|
||||
- `preuninstall`: Runs before the package is uninstalled
|
||||
- `prepublishOnly`: Runs before the package is published
|
||||
|
||||
These scripts are arbitrary shell commands that the package manager is expected to read and execute at the appropriate time. But executing arbitrary scripts represents a potential security risk, so—unlike other `npm` clients—Bun does not execute arbitrary lifecycle scripts by default.
|
||||
|
||||
## `postinstall`
|
||||
|
||||
The `postinstall` script is particularly important. It's widely used to build or install platform-specific binaries for packages that are implemented as [native Node.js add-ons](https://nodejs.org/api/addons.html). For example, `node-sass` is a popular package that uses `postinstall` to build a native binary for Sass.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"node-sass": "^6.0.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `trustedDependencies`
|
||||
|
||||
Instead of executing arbitrary scripts, Bun uses a "default-secure" approach. You can add certain packages to an allow list, and Bun will execute lifecycle scripts for those packages. To tell Bun to allow lifecycle scripts for a particular package, add the package name to `trustedDependencies` array in your `package.json`.
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
+ "trustedDependencies": ["node-sass"]
|
||||
}
|
||||
```
|
||||
|
||||
Once added to `trustedDependencies`, install/re-install the package. Bun will read this field and run lifecycle scripts for `my-trusted-package`.
|
||||
|
||||
## `--ignore-scripts`
|
||||
|
||||
To disable lifecycle scripts for all packages, use the `--ignore-scripts` flag.
|
||||
|
||||
```bash
|
||||
$ bun install --ignore-scripts
|
||||
```
|
||||
73
docs/install/overrides.md
Normal file
73
docs/install/overrides.md
Normal file
@@ -0,0 +1,73 @@
|
||||
Bun supports npm's `"overrides"` and Yarn's `"resolutions"` in `package.json`. These are mechanisms for specifying a version range for _metadependencies_—the dependencies of your dependencies. Refer to [Package manager > Overrides and resolutions](/docs/install/overrides) for complete documentation.
|
||||
|
||||
```json-diff#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"foo": "^2.0.0"
|
||||
},
|
||||
+ "overrides": {
|
||||
+ "bar": "~4.4.0"
|
||||
+ }
|
||||
}
|
||||
```
|
||||
|
||||
By default, Bun will install the latest version of all dependencies and metadependencies, according to the ranges specified in each package's `package.json`. Let's say you have a project with one dependency, `foo`, which in turn has a dependency on `bar`. This means `bar` is a _metadependency_ of our project.
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"foo": "^2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When you run `bun install`, Bun will install the latest versions of each package.
|
||||
|
||||
```
|
||||
# tree layout of node_modules
|
||||
node_modules
|
||||
├── foo@1.2.3
|
||||
└── bar@4.5.6
|
||||
```
|
||||
|
||||
But what if a security vulnerability was introduced in `bar@4.5.6`? We may want a way to pin `bar` to an older version that doesn't have the vulerability. This is where `"overrides"`/`"resolutions"` come in.
|
||||
|
||||
## `"overrides"`
|
||||
|
||||
Add `bar` to the `"overrides"` field in `package.json`. Bun will defer to the specified version range when determining which version of `bar` to install, whether it's a dependency or a metadependency.
|
||||
|
||||
{% callout %}
|
||||
**Note** — Bun currently only supports top-level `"overrides"`. [Nested overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides) are not supported.
|
||||
{% /callout %}
|
||||
|
||||
```json-diff#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"foo": "^2.0.0"
|
||||
},
|
||||
+ "overrides": {
|
||||
+ "bar": "~4.4.0"
|
||||
+ }
|
||||
}
|
||||
```
|
||||
|
||||
## `"resolutions"`
|
||||
|
||||
The syntax is similar for `"resolutions"`, which is Yarn's alternative to `"overrides"`. Bun supports this feature to make migration from Yarn easier.
|
||||
|
||||
As with `"overrides"`, _nested resolutions_ are not currently supported.
|
||||
|
||||
```json-diff#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"foo": "^2.0.0"
|
||||
},
|
||||
+ "resolutions": {
|
||||
+ "bar": "~4.4.0"
|
||||
+ }
|
||||
}
|
||||
```
|
||||
@@ -24,7 +24,7 @@ tree
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
In the root `package.json`, the `"workspaces"` key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It conventional to place all the workspace in a directory called `packages`.
|
||||
In the root `package.json`, the `"workspaces"` key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It's conventional to place all the workspace in a directory called `packages`.
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Bun ships as a single executable that can be installed a few different ways.
|
||||
|
||||
## macOS and Linux
|
||||
## Installing
|
||||
|
||||
### macOS and Linux
|
||||
|
||||
{% callout %}
|
||||
**Linux users** — The `unzip` package is required to install Bun. Use `sudo apt install unzip` to install `unzip` package.
|
||||
@@ -35,7 +37,7 @@ $ proto install bun
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
## Windows
|
||||
### Windows
|
||||
|
||||
Bun provides a _limited, experimental_ native build for Windows. At the moment, only the Bun runtime is supported.
|
||||
|
||||
@@ -67,6 +69,59 @@ $ docker pull oven/bun:alpine
|
||||
$ docker pull oven/bun:distroless
|
||||
```
|
||||
|
||||
## Checking installation
|
||||
|
||||
To check that Bun was installed successfully, open a new terminal window and run `bun --version`.
|
||||
|
||||
```sh
|
||||
$ bun --version
|
||||
1.x.y
|
||||
```
|
||||
|
||||
To see the precise commit of [oven-sh/bun](https://github.com/oven-sh/bun) that you're using, run `bun --revision`.
|
||||
|
||||
```sh
|
||||
$ bun --revision
|
||||
1.x.y+b7982ac1318937560f38e0f8eb18f45eaa43480f
|
||||
```
|
||||
|
||||
If you've installed Bun but are seeing a `command not found` error, you may have to manually add the installation directory (`~/.bun/bin`) to your `PATH`.
|
||||
|
||||
{% details summary="How to add to your `PATH`" %}
|
||||
First, determine what shell you're using:
|
||||
|
||||
```sh
|
||||
$ echo $SHELL
|
||||
/bin/zsh # or /bin/bash or /bin/fish
|
||||
```
|
||||
|
||||
Then add these lines below to bottom of your shell's configuration file.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#~/.zshrc
|
||||
# add to ~/.zshrc
|
||||
export BUN_INSTALL="$HOME/.bun"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
```
|
||||
|
||||
```bash#~/.bashrc
|
||||
# add to ~/.bashrc
|
||||
export BUN_INSTALL="$HOME/.bun"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
```
|
||||
|
||||
```sh#~/.config/fish/config.fish
|
||||
# add to ~/.config/fish/config.fish
|
||||
export BUN_INSTALL="$HOME/.bun"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
Save the file. You'll need to open a new shell/terminal window for the changes to take effect.
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Upgrading
|
||||
|
||||
Once installed, the binary can upgrade itself.
|
||||
|
||||
39
docs/nav.ts
39
docs/nav.ts
@@ -38,12 +38,13 @@ export default {
|
||||
page("typescript", "TypeScript", {
|
||||
description: "Install and configure type declarations for Bun's APIs",
|
||||
}),
|
||||
page("templates", "Templates", {
|
||||
description: "Hit the ground running with one of Bun's official templates, or download a template from GitHub.",
|
||||
|
||||
divider("Templating"),
|
||||
page("cli/init", "`bun init`", {
|
||||
description: "Scaffold an empty Bun project.",
|
||||
}),
|
||||
page("guides", "Guides", {
|
||||
description: "A set of walkthrough guides and code snippets for performing common tasks with Bun",
|
||||
href: "/guides",
|
||||
page("cli/bun-create", "`bun create`", {
|
||||
description: "Scaffold a new Bun project from an official template or GitHub repo.",
|
||||
}),
|
||||
|
||||
// page("typescript", "TypeScript"),
|
||||
@@ -81,7 +82,6 @@ export default {
|
||||
// page("bundev", "Dev server"),
|
||||
// page("benchmarks", "Benchmarks"),
|
||||
|
||||
// divider("Runtime"),
|
||||
divider("Runtime"),
|
||||
page("cli/run", "`bun run`", {
|
||||
description: "Use `bun run` to execute JavaScript/TypeScript files and package.json scripts.",
|
||||
@@ -152,6 +152,21 @@ export default {
|
||||
description:
|
||||
"Install all dependencies with `bun install`, or manage dependencies with `bun add` and `bun remove`.",
|
||||
}),
|
||||
page("cli/add", "`bun add`", {
|
||||
description: "Add dependencies to your project.",
|
||||
}),
|
||||
page("cli/remove", "`bun remove`", {
|
||||
description: "Remove dependencies from your project.",
|
||||
}),
|
||||
page("cli/update", "`bun update`", {
|
||||
description: "Update your project's dependencies.",
|
||||
}),
|
||||
page("cli/link", "`bun link`", {
|
||||
description: "Install local packages as dependencies in your project.",
|
||||
}),
|
||||
page("cli/pm", "`bun pm`", {
|
||||
description: "Utilities relating to package management with Bun.",
|
||||
}),
|
||||
page("install/cache", "Global cache", {
|
||||
description:
|
||||
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
|
||||
@@ -159,6 +174,9 @@ export default {
|
||||
page("install/workspaces", "Workspaces", {
|
||||
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
|
||||
}),
|
||||
page("install/lifecycle", "Lifecycle scripts", {
|
||||
description: "How Bun handles package lifecycle scripts with trustedDependencies",
|
||||
}),
|
||||
page("install/lockfile", "Lockfile", {
|
||||
description:
|
||||
"Bun's binary lockfile `bun.lockb` tracks your resolved dependency tree, making future installs fast and repeatable.",
|
||||
@@ -166,9 +184,12 @@ export default {
|
||||
page("install/registries", "Scopes and registries", {
|
||||
description: "How to configure private scopes and custom package registries.",
|
||||
}),
|
||||
page("install/utilities", "Utilities", {
|
||||
description: "Use `bun pm` to introspect your global module cache or project dependency tree.",
|
||||
page("install/overrides", "Overrides and resolutions", {
|
||||
description: "Specify version ranges for nested dependencies",
|
||||
}),
|
||||
// page("install/utilities", "Utilities", {
|
||||
// description: "Use `bun pm` to introspect your global module cache or project dependency tree.",
|
||||
// }),
|
||||
|
||||
divider("Bundler"),
|
||||
page("bundler", "`Bun.build`", {
|
||||
@@ -334,7 +355,7 @@ export default {
|
||||
page("project/benchmarking", "Benchmarking", {
|
||||
description: `Bun is designed for performance. Learn how to benchmark Bun yourself.`,
|
||||
}),
|
||||
page("project/development", "Development", {
|
||||
page("project/contributing", "Contributing", {
|
||||
description: "Learn how to contribute to Bun and get your local development environment up and running.",
|
||||
}),
|
||||
page("project/licensing", "License", {
|
||||
|
||||
@@ -130,11 +130,11 @@ Zig can be installed either with our npm package [`@oven/zig`](https://www.npmjs
|
||||
|
||||
```bash
|
||||
$ bun install -g @oven/zig
|
||||
$ zigup 0.12.0-dev.163+6780a6bbf
|
||||
$ zigup 0.12.0-dev.899+027aabf49
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
We last updated Zig on **July 18th, 2023**
|
||||
We last updated Zig on **October 12th, 2023**
|
||||
{% /callout %}
|
||||
|
||||
## First Build
|
||||
@@ -392,6 +392,26 @@ $ bun install
|
||||
$ make cpp
|
||||
```
|
||||
|
||||
## Building WebKit locally + Debug mode of JSC
|
||||
|
||||
WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:
|
||||
|
||||
```bash
|
||||
# once you run this, `make submodule` can be used to automatically
|
||||
# update WebKit and the other submodules
|
||||
$ git submodule update --init --depth 1 --checkout src/bun.js/WebKit
|
||||
# to make a jsc release build
|
||||
$ make jsc
|
||||
# JSC debug build does not work perfectly with Bun yet, this is actively being
|
||||
# worked on and will eventually become the default.
|
||||
$ make jsc-build-linux-compile-debug cpp
|
||||
$ make jsc-build-mac-compile-debug cpp
|
||||
```
|
||||
|
||||
Note that the WebKit folder, including build artifacts, is 8GB+ in size.
|
||||
|
||||
If you are using a JSC debug build and using VScode, make sure to run the `C/C++: Select a Configuration` command to configure intellisense to find the debug headers.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### 'span' file not found on Ubuntu
|
||||
@@ -42,7 +42,10 @@ const server = Bun.serve({
|
||||
console.log(`Listening on http://localhost:${server.port} ...`);
|
||||
```
|
||||
|
||||
If you're using TypeScript, you may see a type error on the `Bun` global. To fix this, install `bun-types`.
|
||||
{% details summary="Seeing TypeScript errors on `Bun`?" %}
|
||||
If you used `bun init`, Bun will have automatically installed Bun's TypeScript declarations and configured your `tsconfig.json`. If you're trying out Bun in an existing project, you may see a type error on the `Bun` global.
|
||||
|
||||
To fix this, first install `bun-types` as a dev dependency.
|
||||
|
||||
```sh
|
||||
$ bun add -d bun-types
|
||||
@@ -58,6 +61,8 @@ Then add the following line to your `compilerOptions` in `tsconfig.json`.
|
||||
}
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
Run the file from your shell.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -209,11 +209,11 @@ dev = true
|
||||
|
||||
### `install.peer`
|
||||
|
||||
Whether to install peer dependencies. Default `false`.
|
||||
Whether to install peer dependencies. Default `true`.
|
||||
|
||||
```toml
|
||||
[install]
|
||||
peer = false
|
||||
peer = true
|
||||
```
|
||||
|
||||
### `install.production`
|
||||
|
||||
@@ -30,7 +30,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
||||
|
||||
### [`node:crypto`](https://nodejs.org/api/crypto.html)
|
||||
|
||||
🟡 Missing `Certificate` `ECDH` `KeyObject` `X509Certificate` `checkPrime` `checkPrimeSync` `createPrivateKey` `createPublicKey` `createSecretKey` `diffieHellman` `generateKey` `generateKeyPair` `generateKeyPairSync` `generateKeySync` `generatePrime` `generatePrimeSync` `getCipherInfo` `getFips` `hkdf` `hkdfSync` `secureHeapUsed` `setEngine` `setFips` `sign` `verify`
|
||||
🟡 Missing `Certificate` `ECDH` `X509Certificate` `checkPrime` `checkPrimeSync` `diffieHellman` `generatePrime` `generatePrimeSync` `getCipherInfo` `getFips` `hkdf` `hkdfSync` `secureHeapUsed` `setEngine` `setFips`
|
||||
|
||||
Some methods are not optimized yet.
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ for (let key of Object.keys(json).sort()) {
|
||||
}
|
||||
|
||||
const withExtensions = [
|
||||
...new Set([
|
||||
...Object.keys(json)
|
||||
...new Set(
|
||||
Object.keys(json)
|
||||
.filter(key => {
|
||||
return !!json[key]?.extensions?.length;
|
||||
})
|
||||
@@ -26,7 +26,7 @@ const withExtensions = [
|
||||
});
|
||||
})
|
||||
.sort(),
|
||||
]),
|
||||
),
|
||||
];
|
||||
|
||||
all += "\n";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"name": "bun",
|
||||
"dependencies": {
|
||||
"@vscode/debugadapter": "^1.61.0",
|
||||
"esbuild": "^0.17.15",
|
||||
@@ -26,7 +27,7 @@
|
||||
"@types/react": "^18.0.25",
|
||||
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
||||
"@typescript-eslint/parser": "^5.31.0",
|
||||
"bun-webkit": "0.0.1-2c4d07c9499a65f36f554dc4cd4e9e0640632b8c"
|
||||
"bun-webkit": "0.0.1-b3eb3541118a997adc959e138155f5f4736892da"
|
||||
},
|
||||
"version": "0.0.0",
|
||||
"prettier": "./.prettierrc.cjs"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { spawnSync } from "node:child_process";
|
||||
run().catch(console.error);
|
||||
|
||||
async function run() {
|
||||
const cwd = new URL("../protocol/", import.meta.url);
|
||||
const cwd = new URL("../src/protocol/", import.meta.url);
|
||||
const runner = "Bun" in globalThis ? "bunx" : "npx";
|
||||
const write = (name: string, data: string) => {
|
||||
const path = new URL(name, cwd);
|
||||
|
||||
@@ -638,7 +638,7 @@ export namespace DAP {
|
||||
*/
|
||||
export type BreakpointLocationsRequest = {
|
||||
/**
|
||||
* The source location of the breakpoints; either `source.path` or `source.reference` must be specified.
|
||||
* The source location of the breakpoints; either `source.path` or `source.sourceReference` must be specified.
|
||||
*/
|
||||
source: Source;
|
||||
/**
|
||||
@@ -1139,6 +1139,12 @@ export namespace DAP {
|
||||
* The value should be less than or equal to 2147483647 (2^31-1).
|
||||
*/
|
||||
indexedVariables?: number;
|
||||
/**
|
||||
* A memory reference to a location appropriate for this result.
|
||||
* For pointer type eval results, this is generally a reference to the memory address contained in the pointer.
|
||||
* This attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true.
|
||||
*/
|
||||
memoryReference?: string;
|
||||
};
|
||||
/**
|
||||
* Arguments for `source` request.
|
||||
@@ -1286,7 +1292,7 @@ export namespace DAP {
|
||||
/**
|
||||
* A memory reference to a location appropriate for this result.
|
||||
* For pointer type eval results, this is generally a reference to the memory address contained in the pointer.
|
||||
* This attribute should be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true.
|
||||
* This attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true.
|
||||
*/
|
||||
memoryReference?: string;
|
||||
};
|
||||
@@ -1344,6 +1350,12 @@ export namespace DAP {
|
||||
* The value should be less than or equal to 2147483647 (2^31-1).
|
||||
*/
|
||||
indexedVariables?: number;
|
||||
/**
|
||||
* A memory reference to a location appropriate for this result.
|
||||
* For pointer type eval results, this is generally a reference to the memory address contained in the pointer.
|
||||
* This attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true.
|
||||
*/
|
||||
memoryReference?: string;
|
||||
};
|
||||
/**
|
||||
* Arguments for `stepInTargets` request.
|
||||
@@ -2064,8 +2076,10 @@ export namespace DAP {
|
||||
*/
|
||||
indexedVariables?: number;
|
||||
/**
|
||||
* The memory reference for the variable if the variable represents executable code, such as a function pointer.
|
||||
* This attribute is only required if the corresponding capability `supportsMemoryReferences` is true.
|
||||
* A memory reference associated with this variable.
|
||||
* For pointer type variables, this is generally a reference to the memory address contained in the pointer.
|
||||
* For executable data, this reference may later be used in a `disassemble` request.
|
||||
* This attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true.
|
||||
*/
|
||||
memoryReference?: string;
|
||||
};
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
{ "$ref": "#/definitions/Request" },
|
||||
{
|
||||
"type": "object",
|
||||
"description": "The `cancel` request is used by the client in two situations:\n- to indicate that it is no longer interested in the result produced by a specific request issued earlier\n- to cancel a progress sequence. Clients should only call this request if the corresponding capability `supportsCancelRequest` is true.\nThis request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' in honoring this request but there are no guarantees.\nThe `cancel` request may return an error if it could not cancel an operation but a client should refrain from presenting this error to end users.\nThe request that got cancelled still needs to send a response back. This can either be a normal result (`success` attribute true) or an error response (`success` attribute false and the `message` set to `cancelled`).\nReturning partial results from a cancelled request is possible but please note that a client has no generic way for detecting that a response is partial or not.\nThe progress that got cancelled still needs to send a `progressEnd` event back.\n A client should not assume that progress just got cancelled after sending the `cancel` request.",
|
||||
"description": "The `cancel` request is used by the client in two situations:\n- to indicate that it is no longer interested in the result produced by a specific request issued earlier\n- to cancel a progress sequence.\nClients should only call this request if the corresponding capability `supportsCancelRequest` is true.\nThis request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' in honoring this request but there are no guarantees.\nThe `cancel` request may return an error if it could not cancel an operation but a client should refrain from presenting this error to end users.\nThe request that got cancelled still needs to send a response back. This can either be a normal result (`success` attribute true) or an error response (`success` attribute false and the `message` set to `cancelled`).\nReturning partial results from a cancelled request is possible but please note that a client has no generic way for detecting that a response is partial or not.\nThe progress that got cancelled still needs to send a `progressEnd` event back.\n A client should not assume that progress just got cancelled after sending the `cancel` request.",
|
||||
"properties": {
|
||||
"command": { "type": "string", "enum": ["cancel"] },
|
||||
"arguments": { "$ref": "#/definitions/CancelArguments" }
|
||||
@@ -1074,7 +1074,7 @@
|
||||
"properties": {
|
||||
"source": {
|
||||
"$ref": "#/definitions/Source",
|
||||
"description": "The source location of the breakpoints; either `source.path` or `source.reference` must be specified."
|
||||
"description": "The source location of the breakpoints; either `source.path` or `source.sourceReference` must be specified."
|
||||
},
|
||||
"line": {
|
||||
"type": "integer",
|
||||
@@ -2035,6 +2035,10 @@
|
||||
"indexedVariables": {
|
||||
"type": "integer",
|
||||
"description": "The number of indexed child variables.\nThe client can use this information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)."
|
||||
},
|
||||
"memoryReference": {
|
||||
"type": "string",
|
||||
"description": "A memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true."
|
||||
}
|
||||
},
|
||||
"required": ["value"]
|
||||
@@ -2326,7 +2330,7 @@
|
||||
},
|
||||
"memoryReference": {
|
||||
"type": "string",
|
||||
"description": "A memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute should be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true."
|
||||
"description": "A memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true."
|
||||
}
|
||||
},
|
||||
"required": ["result", "variablesReference"]
|
||||
@@ -2397,6 +2401,10 @@
|
||||
"indexedVariables": {
|
||||
"type": "integer",
|
||||
"description": "The number of indexed child variables.\nThe client can use this information to present the variables in a paged UI and fetch them in chunks.\nThe value should be less than or equal to 2147483647 (2^31-1)."
|
||||
},
|
||||
"memoryReference": {
|
||||
"type": "string",
|
||||
"description": "A memory reference to a location appropriate for this result.\nFor pointer type eval results, this is generally a reference to the memory address contained in the pointer.\nThis attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true."
|
||||
}
|
||||
},
|
||||
"required": ["value"]
|
||||
@@ -3240,7 +3248,7 @@
|
||||
},
|
||||
"memoryReference": {
|
||||
"type": "string",
|
||||
"description": "The memory reference for the variable if the variable represents executable code, such as a function pointer.\nThis attribute is only required if the corresponding capability `supportsMemoryReferences` is true."
|
||||
"description": "A memory reference associated with this variable.\nFor pointer type variables, this is generally a reference to the memory address contained in the pointer.\nFor executable data, this reference may later be used in a `disassemble` request.\nThis attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true."
|
||||
}
|
||||
},
|
||||
"required": ["name", "value", "variablesReference"]
|
||||
@@ -3299,8 +3307,8 @@
|
||||
"Indicates that the object is a constant.",
|
||||
"Indicates that the object is read only.",
|
||||
"Indicates that the object is a raw string.",
|
||||
"Indicates that the object can have an Object ID created for it.",
|
||||
"Indicates that the object has an Object ID associated with it.",
|
||||
"Indicates that the object can have an Object ID created for it. This is a vestigial attribute that is used by some clients; 'Object ID's are not specified in the protocol.",
|
||||
"Indicates that the object has an Object ID associated with it. This is a vestigial attribute that is used by some clients; 'Object ID's are not specified in the protocol.",
|
||||
"Indicates that the evaluation had side effects.",
|
||||
"Indicates that the object has its value tracked by a data breakpoint."
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@ import { spawnSync } from "node:child_process";
|
||||
run().catch(console.error);
|
||||
|
||||
async function run() {
|
||||
const cwd = new URL("../protocol/", import.meta.url);
|
||||
const cwd = new URL("../src/protocol/", import.meta.url);
|
||||
const runner = "Bun" in globalThis ? "bunx" : "npx";
|
||||
const write = (name: string, data: string) => {
|
||||
const path = new URL(name, cwd);
|
||||
|
||||
@@ -1136,7 +1136,8 @@ export namespace V8 {
|
||||
| "Canceled"
|
||||
| "RpPageNotVisible"
|
||||
| "SilentMediationFailure"
|
||||
| "ThirdPartyCookiesBlocked";
|
||||
| "ThirdPartyCookiesBlocked"
|
||||
| "NotSignedInWithIdp";
|
||||
export type FederatedAuthUserInfoRequestIssueDetails = {
|
||||
federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason;
|
||||
};
|
||||
@@ -1192,6 +1193,25 @@ export namespace V8 {
|
||||
*/
|
||||
failedRequestInfo?: FailedRequestInfo | undefined;
|
||||
};
|
||||
export type PropertyRuleIssueReason = "InvalidSyntax" | "InvalidInitialValue" | "InvalidInherits" | "InvalidName";
|
||||
/**
|
||||
* This issue warns about errors in property rules that lead to property
|
||||
* registrations being ignored.
|
||||
*/
|
||||
export type PropertyRuleIssueDetails = {
|
||||
/**
|
||||
* Source code position of the property rule.
|
||||
*/
|
||||
sourceCodeLocation: SourceCodeLocation;
|
||||
/**
|
||||
* Reason why the property rule was discarded.
|
||||
*/
|
||||
propertyRuleIssueReason: PropertyRuleIssueReason;
|
||||
/**
|
||||
* The value of the property rule property that failed to parse
|
||||
*/
|
||||
propertyValue?: string | undefined;
|
||||
};
|
||||
/**
|
||||
* A unique identifier for the type of issue. Each type may use one of the
|
||||
* optional fields in InspectorIssueDetails to convey more specific
|
||||
@@ -1215,7 +1235,8 @@ export namespace V8 {
|
||||
| "FederatedAuthRequestIssue"
|
||||
| "BounceTrackingIssue"
|
||||
| "StylesheetLoadingIssue"
|
||||
| "FederatedAuthUserInfoRequestIssue";
|
||||
| "FederatedAuthUserInfoRequestIssue"
|
||||
| "PropertyRuleIssue";
|
||||
/**
|
||||
* This struct holds a list of optional fields with additional information
|
||||
* specific to the kind of issue. When adding a new issue code, please also
|
||||
@@ -1239,6 +1260,7 @@ export namespace V8 {
|
||||
federatedAuthRequestIssueDetails?: FederatedAuthRequestIssueDetails | undefined;
|
||||
bounceTrackingIssueDetails?: BounceTrackingIssueDetails | undefined;
|
||||
stylesheetLoadingIssueDetails?: StylesheetLoadingIssueDetails | undefined;
|
||||
propertyRuleIssueDetails?: PropertyRuleIssueDetails | undefined;
|
||||
federatedAuthUserInfoRequestIssueDetails?: FederatedAuthUserInfoRequestIssueDetails | undefined;
|
||||
};
|
||||
/**
|
||||
@@ -1390,16 +1412,82 @@ export namespace V8 {
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* address field name, for example Jon Doe.
|
||||
* address field value, for example Jon Doe.
|
||||
*/
|
||||
value: string;
|
||||
};
|
||||
/**
|
||||
* A list of address fields.
|
||||
*/
|
||||
export type AddressFields = {
|
||||
fields: AddressField[];
|
||||
};
|
||||
export type Address = {
|
||||
/**
|
||||
* fields and values defining a test address.
|
||||
* fields and values defining an address.
|
||||
*/
|
||||
fields: AddressField[];
|
||||
};
|
||||
/**
|
||||
* Defines how an address can be displayed like in chrome://settings/addresses.
|
||||
* Address UI is a two dimensional array, each inner array is an "address information line", and when rendered in a UI surface should be displayed as such.
|
||||
* The following address UI for instance:
|
||||
* [[{name: "GIVE_NAME", value: "Jon"}, {name: "FAMILY_NAME", value: "Doe"}], [{name: "CITY", value: "Munich"}, {name: "ZIP", value: "81456"}]]
|
||||
* should allow the receiver to render:
|
||||
* Jon Doe
|
||||
* Munich 81456
|
||||
*/
|
||||
export type AddressUI = {
|
||||
/**
|
||||
* A two dimension array containing the repesentation of values from an address profile.
|
||||
*/
|
||||
addressFields: AddressFields[];
|
||||
};
|
||||
/**
|
||||
* Specified whether a filled field was done so by using the html autocomplete attribute or autofill heuristics.
|
||||
*/
|
||||
export type FillingStrategy = "autocompleteAttribute" | "autofillInferred";
|
||||
export type FilledField = {
|
||||
/**
|
||||
* The type of the field, e.g text, password etc.
|
||||
*/
|
||||
htmlType: string;
|
||||
/**
|
||||
* the html id
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* the html name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* the field value
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* The actual field type, e.g FAMILY_NAME
|
||||
*/
|
||||
autofillType: string;
|
||||
/**
|
||||
* The filling strategy
|
||||
*/
|
||||
fillingStrategy: FillingStrategy;
|
||||
};
|
||||
/**
|
||||
* Emitted when an address form is filled.
|
||||
* @event `Autofill.addressFormFilled`
|
||||
*/
|
||||
export type AddressFormFilledEvent = {
|
||||
/**
|
||||
* Information about the fields that were filled
|
||||
*/
|
||||
filledFields: FilledField[];
|
||||
/**
|
||||
* An UI representation of the address used to fill the form.
|
||||
* Consists of a 2D array where each child represents an address/profile line.
|
||||
*/
|
||||
addressUi: AddressUI;
|
||||
};
|
||||
/**
|
||||
* Trigger autofill on a form identified by the fieldId.
|
||||
* If the field and related form cannot be autofilled, returns an error.
|
||||
@@ -1437,6 +1525,26 @@ export namespace V8 {
|
||||
* @response `Autofill.setAddresses`
|
||||
*/
|
||||
export type SetAddressesResponse = {};
|
||||
/**
|
||||
* Disables autofill domain notifications.
|
||||
* @request `Autofill.disable`
|
||||
*/
|
||||
export type DisableRequest = {};
|
||||
/**
|
||||
* Disables autofill domain notifications.
|
||||
* @response `Autofill.disable`
|
||||
*/
|
||||
export type DisableResponse = {};
|
||||
/**
|
||||
* Enables autofill domain notifications.
|
||||
* @request `Autofill.enable`
|
||||
*/
|
||||
export type EnableRequest = {};
|
||||
/**
|
||||
* Enables autofill domain notifications.
|
||||
* @response `Autofill.enable`
|
||||
*/
|
||||
export type EnableResponse = {};
|
||||
}
|
||||
export namespace BackgroundService {
|
||||
/**
|
||||
@@ -3573,6 +3681,25 @@ export namespace V8 {
|
||||
* @response `CSS.setEffectivePropertyValueForNode`
|
||||
*/
|
||||
export type SetEffectivePropertyValueForNodeResponse = {};
|
||||
/**
|
||||
* Modifies the property rule property name.
|
||||
* @request `CSS.setPropertyRulePropertyName`
|
||||
*/
|
||||
export type SetPropertyRulePropertyNameRequest = {
|
||||
styleSheetId: StyleSheetId;
|
||||
range: SourceRange;
|
||||
propertyName: string;
|
||||
};
|
||||
/**
|
||||
* Modifies the property rule property name.
|
||||
* @response `CSS.setPropertyRulePropertyName`
|
||||
*/
|
||||
export type SetPropertyRulePropertyNameResponse = {
|
||||
/**
|
||||
* The resulting key text after modification.
|
||||
*/
|
||||
propertyName: Value;
|
||||
};
|
||||
/**
|
||||
* Modifies the keyframe rule key text.
|
||||
* @request `CSS.setKeyframeKey`
|
||||
@@ -7168,6 +7295,16 @@ export namespace V8 {
|
||||
* @response `EventBreakpoints.removeInstrumentationBreakpoint`
|
||||
*/
|
||||
export type RemoveInstrumentationBreakpointResponse = {};
|
||||
/**
|
||||
* Removes all breakpoints
|
||||
* @request `EventBreakpoints.disable`
|
||||
*/
|
||||
export type DisableRequest = {};
|
||||
/**
|
||||
* Removes all breakpoints
|
||||
* @response `EventBreakpoints.disable`
|
||||
*/
|
||||
export type DisableResponse = {};
|
||||
}
|
||||
export namespace FedCm {
|
||||
/**
|
||||
@@ -7178,7 +7315,7 @@ export namespace V8 {
|
||||
/**
|
||||
* Whether the dialog shown is an account chooser or an auto re-authentication dialog.
|
||||
*/
|
||||
export type DialogType = "AccountChooser" | "AutoReauthn" | "ConfirmIdpSignin";
|
||||
export type DialogType = "AccountChooser" | "AutoReauthn" | "ConfirmIdpLogin";
|
||||
/**
|
||||
* Corresponds to IdentityRequestAccount
|
||||
*/
|
||||
@@ -7189,7 +7326,7 @@ export namespace V8 {
|
||||
givenName: string;
|
||||
pictureUrl: string;
|
||||
idpConfigUrl: string;
|
||||
idpSigninUrl: string;
|
||||
idpLoginUrl: string;
|
||||
loginState: LoginState;
|
||||
/**
|
||||
* These two are only set if the loginState is signUp
|
||||
@@ -7252,6 +7389,20 @@ export namespace V8 {
|
||||
* @response `FedCm.selectAccount`
|
||||
*/
|
||||
export type SelectAccountResponse = {};
|
||||
/**
|
||||
* Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had
|
||||
* clicked the continue button.
|
||||
* @request `FedCm.confirmIdpLogin`
|
||||
*/
|
||||
export type ConfirmIdpLoginRequest = {
|
||||
dialogId: string;
|
||||
};
|
||||
/**
|
||||
* Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had
|
||||
* clicked the continue button.
|
||||
* @response `FedCm.confirmIdpLogin`
|
||||
*/
|
||||
export type ConfirmIdpLoginResponse = {};
|
||||
/**
|
||||
* undefined
|
||||
* @request `FedCm.dismissDialog`
|
||||
@@ -10477,6 +10628,7 @@ export namespace V8 {
|
||||
| "ch-ect"
|
||||
| "ch-prefers-color-scheme"
|
||||
| "ch-prefers-reduced-motion"
|
||||
| "ch-prefers-reduced-transparency"
|
||||
| "ch-rtt"
|
||||
| "ch-save-data"
|
||||
| "ch-ua"
|
||||
@@ -13109,7 +13261,6 @@ export namespace V8 {
|
||||
| "LowEndDevice"
|
||||
| "InvalidSchemeRedirect"
|
||||
| "InvalidSchemeNavigation"
|
||||
| "InProgressNavigation"
|
||||
| "NavigationRequestBlockedByCsp"
|
||||
| "MainFrameNavigation"
|
||||
| "MojoBinderPolicy"
|
||||
@@ -13121,7 +13272,6 @@ export namespace V8 {
|
||||
| "NavigationBadHttpStatus"
|
||||
| "ClientCertRequested"
|
||||
| "NavigationRequestNetworkError"
|
||||
| "MaxNumOfRunningPrerendersExceeded"
|
||||
| "CancelAllHostsForTesting"
|
||||
| "DidFailLoad"
|
||||
| "Stop"
|
||||
@@ -13133,9 +13283,8 @@ export namespace V8 {
|
||||
| "MixedContent"
|
||||
| "TriggerBackgrounded"
|
||||
| "MemoryLimitExceeded"
|
||||
| "FailToGetMemoryUsage"
|
||||
| "DataSaverEnabled"
|
||||
| "HasEffectiveUrl"
|
||||
| "TriggerUrlHasEffectiveUrl"
|
||||
| "ActivatedBeforeStarted"
|
||||
| "InactivePageRestriction"
|
||||
| "StartFailed"
|
||||
@@ -13166,7 +13315,13 @@ export namespace V8 {
|
||||
| "PrerenderingDisabledByDevTools"
|
||||
| "ResourceLoadBlockedByClient"
|
||||
| "SpeculationRuleRemoved"
|
||||
| "ActivatedWithAuxiliaryBrowsingContexts";
|
||||
| "ActivatedWithAuxiliaryBrowsingContexts"
|
||||
| "MaxNumOfRunningEagerPrerendersExceeded"
|
||||
| "MaxNumOfRunningNonEagerPrerendersExceeded"
|
||||
| "MaxNumOfRunningEmbedderPrerendersExceeded"
|
||||
| "PrerenderingUrlHasEffectiveUrl"
|
||||
| "RedirectedPrerenderingUrlHasEffectiveUrl"
|
||||
| "ActivationUrlHasEffectiveUrl";
|
||||
/**
|
||||
* Preloading status values, see also PreloadingTriggeringOutcome. This
|
||||
* status is shared by prefetchStatusUpdated and prerenderStatusUpdated.
|
||||
@@ -13221,24 +13376,6 @@ export namespace V8 {
|
||||
export type RuleSetRemovedEvent = {
|
||||
id: RuleSetId;
|
||||
};
|
||||
/**
|
||||
* Fired when a prerender attempt is completed.
|
||||
* @event `Preload.prerenderAttemptCompleted`
|
||||
*/
|
||||
export type PrerenderAttemptCompletedEvent = {
|
||||
key: PreloadingAttemptKey;
|
||||
/**
|
||||
* The frame id of the frame initiating prerendering.
|
||||
*/
|
||||
initiatingFrameId: Page.FrameId;
|
||||
prerenderingUrl: string;
|
||||
finalStatus: PrerenderFinalStatus;
|
||||
/**
|
||||
* This is used to give users more information about the name of the API call
|
||||
* that is incompatible with prerender and has caused the cancellation of the attempt
|
||||
*/
|
||||
disallowedApiMethod?: string | undefined;
|
||||
};
|
||||
/**
|
||||
* Fired when a preload enabled state is updated.
|
||||
* @event `Preload.preloadEnabledStateUpdated`
|
||||
@@ -13935,12 +14072,21 @@ export namespace V8 {
|
||||
/**
|
||||
* Enum of interest group access types.
|
||||
*/
|
||||
export type InterestGroupAccessType = "join" | "leave" | "update" | "loaded" | "bid" | "win";
|
||||
export type InterestGroupAccessType =
|
||||
| "join"
|
||||
| "leave"
|
||||
| "update"
|
||||
| "loaded"
|
||||
| "bid"
|
||||
| "win"
|
||||
| "additionalBid"
|
||||
| "additionalBidWin"
|
||||
| "clear";
|
||||
/**
|
||||
* Ad advertising element inside an interest group.
|
||||
*/
|
||||
export type InterestGroupAd = {
|
||||
renderUrl: string;
|
||||
renderURL: string;
|
||||
metadata?: string | undefined;
|
||||
};
|
||||
/**
|
||||
@@ -13951,10 +14097,10 @@ export namespace V8 {
|
||||
name: string;
|
||||
expirationTime: Network.TimeSinceEpoch;
|
||||
joiningOrigin: string;
|
||||
biddingUrl?: string | undefined;
|
||||
biddingWasmHelperUrl?: string | undefined;
|
||||
updateUrl?: string | undefined;
|
||||
trustedBiddingSignalsUrl?: string | undefined;
|
||||
biddingLogicURL?: string | undefined;
|
||||
biddingWasmHelperURL?: string | undefined;
|
||||
updateURL?: string | undefined;
|
||||
trustedBiddingSignalsURL?: string | undefined;
|
||||
trustedBiddingSignalsKeys: string[];
|
||||
userBiddingSignals?: string | undefined;
|
||||
ads: InterestGroupAd[];
|
||||
@@ -14099,20 +14245,27 @@ export namespace V8 {
|
||||
key: string;
|
||||
value: UnsignedInt128AsBase16;
|
||||
};
|
||||
export type AttributionReportingEventReportWindows = {
|
||||
/**
|
||||
* duration in seconds
|
||||
*/
|
||||
start: number;
|
||||
/**
|
||||
* duration in seconds
|
||||
*/
|
||||
ends: number[];
|
||||
};
|
||||
export type AttributionReportingSourceRegistration = {
|
||||
time: Network.TimeSinceEpoch;
|
||||
/**
|
||||
* duration in seconds
|
||||
*/
|
||||
expiry?: number | undefined;
|
||||
expiry: number;
|
||||
eventReportWindows: AttributionReportingEventReportWindows;
|
||||
/**
|
||||
* duration in seconds
|
||||
*/
|
||||
eventReportWindow?: number | undefined;
|
||||
/**
|
||||
* duration in seconds
|
||||
*/
|
||||
aggregatableReportWindow?: number | undefined;
|
||||
aggregatableReportWindow: number;
|
||||
type: AttributionReportingSourceType;
|
||||
sourceOrigin: string;
|
||||
reportingOrigin: string;
|
||||
@@ -16381,6 +16534,7 @@ export namespace V8 {
|
||||
"Animation.animationCreated": Animation.AnimationCreatedEvent;
|
||||
"Animation.animationStarted": Animation.AnimationStartedEvent;
|
||||
"Audits.issueAdded": Audits.IssueAddedEvent;
|
||||
"Autofill.addressFormFilled": Autofill.AddressFormFilledEvent;
|
||||
"BackgroundService.recordingStateChanged": BackgroundService.RecordingStateChangedEvent;
|
||||
"BackgroundService.backgroundServiceEventReceived": BackgroundService.BackgroundServiceEventReceivedEvent;
|
||||
"Browser.downloadWillBegin": Browser.DownloadWillBeginEvent;
|
||||
@@ -16460,7 +16614,6 @@ export namespace V8 {
|
||||
"PerformanceTimeline.timelineEventAdded": PerformanceTimeline.TimelineEventAddedEvent;
|
||||
"Preload.ruleSetUpdated": Preload.RuleSetUpdatedEvent;
|
||||
"Preload.ruleSetRemoved": Preload.RuleSetRemovedEvent;
|
||||
"Preload.prerenderAttemptCompleted": Preload.PrerenderAttemptCompletedEvent;
|
||||
"Preload.preloadEnabledStateUpdated": Preload.PreloadEnabledStateUpdatedEvent;
|
||||
"Preload.prefetchStatusUpdated": Preload.PrefetchStatusUpdatedEvent;
|
||||
"Preload.prerenderStatusUpdated": Preload.PrerenderStatusUpdatedEvent;
|
||||
@@ -16533,6 +16686,8 @@ export namespace V8 {
|
||||
"Audits.checkFormsIssues": Audits.CheckFormsIssuesRequest;
|
||||
"Autofill.trigger": Autofill.TriggerRequest;
|
||||
"Autofill.setAddresses": Autofill.SetAddressesRequest;
|
||||
"Autofill.disable": Autofill.DisableRequest;
|
||||
"Autofill.enable": Autofill.EnableRequest;
|
||||
"BackgroundService.startObserving": BackgroundService.StartObservingRequest;
|
||||
"BackgroundService.stopObserving": BackgroundService.StopObservingRequest;
|
||||
"BackgroundService.setRecording": BackgroundService.SetRecordingRequest;
|
||||
@@ -16583,6 +16738,7 @@ export namespace V8 {
|
||||
"CSS.trackComputedStyleUpdates": CSS.TrackComputedStyleUpdatesRequest;
|
||||
"CSS.takeComputedStyleUpdates": CSS.TakeComputedStyleUpdatesRequest;
|
||||
"CSS.setEffectivePropertyValueForNode": CSS.SetEffectivePropertyValueForNodeRequest;
|
||||
"CSS.setPropertyRulePropertyName": CSS.SetPropertyRulePropertyNameRequest;
|
||||
"CSS.setKeyframeKey": CSS.SetKeyframeKeyRequest;
|
||||
"CSS.setMediaText": CSS.SetMediaTextRequest;
|
||||
"CSS.setContainerQueryText": CSS.SetContainerQueryTextRequest;
|
||||
@@ -16705,9 +16861,11 @@ export namespace V8 {
|
||||
"Emulation.setAutomationOverride": Emulation.SetAutomationOverrideRequest;
|
||||
"EventBreakpoints.setInstrumentationBreakpoint": EventBreakpoints.SetInstrumentationBreakpointRequest;
|
||||
"EventBreakpoints.removeInstrumentationBreakpoint": EventBreakpoints.RemoveInstrumentationBreakpointRequest;
|
||||
"EventBreakpoints.disable": EventBreakpoints.DisableRequest;
|
||||
"FedCm.enable": FedCm.EnableRequest;
|
||||
"FedCm.disable": FedCm.DisableRequest;
|
||||
"FedCm.selectAccount": FedCm.SelectAccountRequest;
|
||||
"FedCm.confirmIdpLogin": FedCm.ConfirmIdpLoginRequest;
|
||||
"FedCm.dismissDialog": FedCm.DismissDialogRequest;
|
||||
"FedCm.resetCooldown": FedCm.ResetCooldownRequest;
|
||||
"Fetch.disable": Fetch.DisableRequest;
|
||||
@@ -16979,6 +17137,8 @@ export namespace V8 {
|
||||
"Audits.checkFormsIssues": Audits.CheckFormsIssuesResponse;
|
||||
"Autofill.trigger": Autofill.TriggerResponse;
|
||||
"Autofill.setAddresses": Autofill.SetAddressesResponse;
|
||||
"Autofill.disable": Autofill.DisableResponse;
|
||||
"Autofill.enable": Autofill.EnableResponse;
|
||||
"BackgroundService.startObserving": BackgroundService.StartObservingResponse;
|
||||
"BackgroundService.stopObserving": BackgroundService.StopObservingResponse;
|
||||
"BackgroundService.setRecording": BackgroundService.SetRecordingResponse;
|
||||
@@ -17029,6 +17189,7 @@ export namespace V8 {
|
||||
"CSS.trackComputedStyleUpdates": CSS.TrackComputedStyleUpdatesResponse;
|
||||
"CSS.takeComputedStyleUpdates": CSS.TakeComputedStyleUpdatesResponse;
|
||||
"CSS.setEffectivePropertyValueForNode": CSS.SetEffectivePropertyValueForNodeResponse;
|
||||
"CSS.setPropertyRulePropertyName": CSS.SetPropertyRulePropertyNameResponse;
|
||||
"CSS.setKeyframeKey": CSS.SetKeyframeKeyResponse;
|
||||
"CSS.setMediaText": CSS.SetMediaTextResponse;
|
||||
"CSS.setContainerQueryText": CSS.SetContainerQueryTextResponse;
|
||||
@@ -17151,9 +17312,11 @@ export namespace V8 {
|
||||
"Emulation.setAutomationOverride": Emulation.SetAutomationOverrideResponse;
|
||||
"EventBreakpoints.setInstrumentationBreakpoint": EventBreakpoints.SetInstrumentationBreakpointResponse;
|
||||
"EventBreakpoints.removeInstrumentationBreakpoint": EventBreakpoints.RemoveInstrumentationBreakpointResponse;
|
||||
"EventBreakpoints.disable": EventBreakpoints.DisableResponse;
|
||||
"FedCm.enable": FedCm.EnableResponse;
|
||||
"FedCm.disable": FedCm.DisableResponse;
|
||||
"FedCm.selectAccount": FedCm.SelectAccountResponse;
|
||||
"FedCm.confirmIdpLogin": FedCm.ConfirmIdpLoginResponse;
|
||||
"FedCm.dismissDialog": FedCm.DismissDialogResponse;
|
||||
"FedCm.resetCooldown": FedCm.ResetCooldownResponse;
|
||||
"Fetch.disable": Fetch.DisableResponse;
|
||||
|
||||
@@ -1091,7 +1091,8 @@
|
||||
"Canceled",
|
||||
"RpPageNotVisible",
|
||||
"SilentMediationFailure",
|
||||
"ThirdPartyCookiesBlocked"
|
||||
"ThirdPartyCookiesBlocked",
|
||||
"NotSignedInWithIdp"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1163,6 +1164,34 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PropertyRuleIssueReason",
|
||||
"type": "string",
|
||||
"enum": ["InvalidSyntax", "InvalidInitialValue", "InvalidInherits", "InvalidName"]
|
||||
},
|
||||
{
|
||||
"id": "PropertyRuleIssueDetails",
|
||||
"description": "This issue warns about errors in property rules that lead to property\nregistrations being ignored.",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{
|
||||
"name": "sourceCodeLocation",
|
||||
"description": "Source code position of the property rule.",
|
||||
"$ref": "SourceCodeLocation"
|
||||
},
|
||||
{
|
||||
"name": "propertyRuleIssueReason",
|
||||
"description": "Reason why the property rule was discarded.",
|
||||
"$ref": "PropertyRuleIssueReason"
|
||||
},
|
||||
{
|
||||
"name": "propertyValue",
|
||||
"description": "The value of the property rule property that failed to parse",
|
||||
"optional": true,
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "InspectorIssueCode",
|
||||
"description": "A unique identifier for the type of issue. Each type may use one of the\noptional fields in InspectorIssueDetails to convey more specific\ninformation about the kind of issue.",
|
||||
@@ -1185,7 +1214,8 @@
|
||||
"FederatedAuthRequestIssue",
|
||||
"BounceTrackingIssue",
|
||||
"StylesheetLoadingIssue",
|
||||
"FederatedAuthUserInfoRequestIssue"
|
||||
"FederatedAuthUserInfoRequestIssue",
|
||||
"PropertyRuleIssue"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1227,6 +1257,7 @@
|
||||
},
|
||||
{ "name": "bounceTrackingIssueDetails", "optional": true, "$ref": "BounceTrackingIssueDetails" },
|
||||
{ "name": "stylesheetLoadingIssueDetails", "optional": true, "$ref": "StylesheetLoadingIssueDetails" },
|
||||
{ "name": "propertyRuleIssueDetails", "optional": true, "$ref": "PropertyRuleIssueDetails" },
|
||||
{
|
||||
"name": "federatedAuthUserInfoRequestIssueDetails",
|
||||
"optional": true,
|
||||
@@ -1344,20 +1375,76 @@
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "name", "description": "address field name, for example GIVEN_NAME.", "type": "string" },
|
||||
{ "name": "value", "description": "address field name, for example Jon Doe.", "type": "string" }
|
||||
{ "name": "value", "description": "address field value, for example Jon Doe.", "type": "string" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "AddressFields",
|
||||
"description": "A list of address fields.",
|
||||
"type": "object",
|
||||
"properties": [{ "name": "fields", "type": "array", "items": { "$ref": "AddressField" } }]
|
||||
},
|
||||
{
|
||||
"id": "Address",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{
|
||||
"name": "fields",
|
||||
"description": "fields and values defining a test address.",
|
||||
"description": "fields and values defining an address.",
|
||||
"type": "array",
|
||||
"items": { "$ref": "AddressField" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "AddressUI",
|
||||
"description": "Defines how an address can be displayed like in chrome://settings/addresses.\nAddress UI is a two dimensional array, each inner array is an \"address information line\", and when rendered in a UI surface should be displayed as such.\nThe following address UI for instance:\n[[{name: \"GIVE_NAME\", value: \"Jon\"}, {name: \"FAMILY_NAME\", value: \"Doe\"}], [{name: \"CITY\", value: \"Munich\"}, {name: \"ZIP\", value: \"81456\"}]]\nshould allow the receiver to render:\nJon Doe\nMunich 81456",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{
|
||||
"name": "addressFields",
|
||||
"description": "A two dimension array containing the repesentation of values from an address profile.",
|
||||
"type": "array",
|
||||
"items": { "$ref": "AddressFields" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "FillingStrategy",
|
||||
"description": "Specified whether a filled field was done so by using the html autocomplete attribute or autofill heuristics.",
|
||||
"type": "string",
|
||||
"enum": ["autocompleteAttribute", "autofillInferred"]
|
||||
},
|
||||
{
|
||||
"id": "FilledField",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "htmlType", "description": "The type of the field, e.g text, password etc.", "type": "string" },
|
||||
{ "name": "id", "description": "the html id", "type": "string" },
|
||||
{ "name": "name", "description": "the html name", "type": "string" },
|
||||
{ "name": "value", "description": "the field value", "type": "string" },
|
||||
{ "name": "autofillType", "description": "The actual field type, e.g FAMILY_NAME", "type": "string" },
|
||||
{ "name": "fillingStrategy", "description": "The filling strategy", "$ref": "FillingStrategy" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "addressFormFilled",
|
||||
"description": "Emitted when an address form is filled.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "filledFields",
|
||||
"description": "Information about the fields that were filled",
|
||||
"type": "array",
|
||||
"items": { "$ref": "FilledField" }
|
||||
},
|
||||
{
|
||||
"name": "addressUi",
|
||||
"description": "An UI representation of the address used to fill the form.\nConsists of a 2D array where each child represents an address/profile line.",
|
||||
"$ref": "AddressUI"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
@@ -1387,7 +1474,9 @@
|
||||
"name": "setAddresses",
|
||||
"description": "Set addresses so that developers can verify their forms implementation.",
|
||||
"parameters": [{ "name": "addresses", "type": "array", "items": { "$ref": "Address" } }]
|
||||
}
|
||||
},
|
||||
{ "name": "disable", "description": "Disables autofill domain notifications." },
|
||||
{ "name": "enable", "description": "Enables autofill domain notifications." }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -3211,6 +3300,18 @@
|
||||
{ "name": "value", "type": "string" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setPropertyRulePropertyName",
|
||||
"description": "Modifies the property rule property name.",
|
||||
"parameters": [
|
||||
{ "name": "styleSheetId", "$ref": "StyleSheetId" },
|
||||
{ "name": "range", "$ref": "SourceRange" },
|
||||
{ "name": "propertyName", "type": "string" }
|
||||
],
|
||||
"returns": [
|
||||
{ "name": "propertyName", "description": "The resulting key text after modification.", "$ref": "Value" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setKeyframeKey",
|
||||
"description": "Modifies the keyframe rule key text.",
|
||||
@@ -4628,7 +4729,7 @@
|
||||
{
|
||||
"domain": "DOMDebugger",
|
||||
"description": "DOM debugging allows setting breakpoints on particular DOM operations and events. JavaScript\nexecution will stop on these operations as if there was a regular breakpoint set.",
|
||||
"dependencies": ["DOM", "Debugger", "Runtime"],
|
||||
"dependencies": ["DOM", "Runtime"],
|
||||
"types": [
|
||||
{
|
||||
"id": "DOMBreakpointType",
|
||||
@@ -4738,6 +4839,8 @@
|
||||
"name": "removeInstrumentationBreakpoint",
|
||||
"description": "Removes breakpoint on particular native event.",
|
||||
"experimental": true,
|
||||
"deprecated": true,
|
||||
"redirect": "EventBreakpoints",
|
||||
"parameters": [{ "name": "eventName", "description": "Instrumentation name to stop on.", "type": "string" }]
|
||||
},
|
||||
{
|
||||
@@ -4788,6 +4891,8 @@
|
||||
"name": "setInstrumentationBreakpoint",
|
||||
"description": "Sets breakpoint on particular native event.",
|
||||
"experimental": true,
|
||||
"deprecated": true,
|
||||
"redirect": "EventBreakpoints",
|
||||
"parameters": [{ "name": "eventName", "description": "Instrumentation name to stop on.", "type": "string" }]
|
||||
},
|
||||
{
|
||||
@@ -6069,7 +6174,7 @@
|
||||
},
|
||||
{
|
||||
"domain": "EventBreakpoints",
|
||||
"description": "EventBreakpoints permits setting breakpoints on particular operations and\nevents in targets that run JavaScript but do not have a DOM.\nJavaScript execution will stop on these operations as if there was a regular\nbreakpoint set.",
|
||||
"description": "EventBreakpoints permits setting JavaScript breakpoints on operations and events\noccurring in native code invoked from JavaScript. Once breakpoint is hit, it is\nreported through Debugger domain, similarly to regular breakpoints being hit.",
|
||||
"experimental": true,
|
||||
"commands": [
|
||||
{
|
||||
@@ -6081,7 +6186,8 @@
|
||||
"name": "removeInstrumentationBreakpoint",
|
||||
"description": "Removes breakpoint on particular native event.",
|
||||
"parameters": [{ "name": "eventName", "description": "Instrumentation name to stop on.", "type": "string" }]
|
||||
}
|
||||
},
|
||||
{ "name": "disable", "description": "Removes all breakpoints" }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -6099,7 +6205,7 @@
|
||||
"id": "DialogType",
|
||||
"description": "Whether the dialog shown is an account chooser or an auto re-authentication dialog.",
|
||||
"type": "string",
|
||||
"enum": ["AccountChooser", "AutoReauthn", "ConfirmIdpSignin"]
|
||||
"enum": ["AccountChooser", "AutoReauthn", "ConfirmIdpLogin"]
|
||||
},
|
||||
{
|
||||
"id": "Account",
|
||||
@@ -6112,7 +6218,7 @@
|
||||
{ "name": "givenName", "type": "string" },
|
||||
{ "name": "pictureUrl", "type": "string" },
|
||||
{ "name": "idpConfigUrl", "type": "string" },
|
||||
{ "name": "idpSigninUrl", "type": "string" },
|
||||
{ "name": "idpLoginUrl", "type": "string" },
|
||||
{ "name": "loginState", "$ref": "LoginState" },
|
||||
{
|
||||
"name": "termsOfServiceUrl",
|
||||
@@ -6160,6 +6266,11 @@
|
||||
{ "name": "accountIndex", "type": "integer" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "confirmIdpLogin",
|
||||
"description": "Only valid if the dialog type is ConfirmIdpLogin. Acts as if the user had\nclicked the continue button.",
|
||||
"parameters": [{ "name": "dialogId", "type": "string" }]
|
||||
},
|
||||
{
|
||||
"name": "dismissDialog",
|
||||
"parameters": [
|
||||
@@ -6987,16 +7098,14 @@
|
||||
{
|
||||
"name": "tiltX",
|
||||
"description": "The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0)",
|
||||
"experimental": true,
|
||||
"optional": true,
|
||||
"type": "integer"
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"name": "tiltY",
|
||||
"description": "The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0).",
|
||||
"experimental": true,
|
||||
"optional": true,
|
||||
"type": "integer"
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"name": "twist",
|
||||
@@ -7280,16 +7389,14 @@
|
||||
{
|
||||
"name": "tiltX",
|
||||
"description": "The plane angle between the Y-Z plane and the plane containing both the stylus axis and the Y axis, in degrees of the range [-90,90], a positive tiltX is to the right (default: 0).",
|
||||
"experimental": true,
|
||||
"optional": true,
|
||||
"type": "integer"
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"name": "tiltY",
|
||||
"description": "The plane angle between the X-Z plane and the plane containing both the stylus axis and the X axis, in degrees of the range [-90,90], a positive tiltY is towards the user (default: 0).",
|
||||
"experimental": true,
|
||||
"optional": true,
|
||||
"type": "integer"
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"name": "twist",
|
||||
@@ -9158,6 +9265,7 @@
|
||||
"ch-ect",
|
||||
"ch-prefers-color-scheme",
|
||||
"ch-prefers-reduced-motion",
|
||||
"ch-prefers-reduced-transparency",
|
||||
"ch-rtt",
|
||||
"ch-save-data",
|
||||
"ch-ua",
|
||||
@@ -11403,7 +11511,6 @@
|
||||
"LowEndDevice",
|
||||
"InvalidSchemeRedirect",
|
||||
"InvalidSchemeNavigation",
|
||||
"InProgressNavigation",
|
||||
"NavigationRequestBlockedByCsp",
|
||||
"MainFrameNavigation",
|
||||
"MojoBinderPolicy",
|
||||
@@ -11415,7 +11522,6 @@
|
||||
"NavigationBadHttpStatus",
|
||||
"ClientCertRequested",
|
||||
"NavigationRequestNetworkError",
|
||||
"MaxNumOfRunningPrerendersExceeded",
|
||||
"CancelAllHostsForTesting",
|
||||
"DidFailLoad",
|
||||
"Stop",
|
||||
@@ -11427,9 +11533,8 @@
|
||||
"MixedContent",
|
||||
"TriggerBackgrounded",
|
||||
"MemoryLimitExceeded",
|
||||
"FailToGetMemoryUsage",
|
||||
"DataSaverEnabled",
|
||||
"HasEffectiveUrl",
|
||||
"TriggerUrlHasEffectiveUrl",
|
||||
"ActivatedBeforeStarted",
|
||||
"InactivePageRestriction",
|
||||
"StartFailed",
|
||||
@@ -11460,7 +11565,13 @@
|
||||
"PrerenderingDisabledByDevTools",
|
||||
"ResourceLoadBlockedByClient",
|
||||
"SpeculationRuleRemoved",
|
||||
"ActivatedWithAuxiliaryBrowsingContexts"
|
||||
"ActivatedWithAuxiliaryBrowsingContexts",
|
||||
"MaxNumOfRunningEagerPrerendersExceeded",
|
||||
"MaxNumOfRunningNonEagerPrerendersExceeded",
|
||||
"MaxNumOfRunningEmbedderPrerendersExceeded",
|
||||
"PrerenderingUrlHasEffectiveUrl",
|
||||
"RedirectedPrerenderingUrlHasEffectiveUrl",
|
||||
"ActivationUrlHasEffectiveUrl"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -11515,26 +11626,6 @@
|
||||
"parameters": [{ "name": "ruleSet", "$ref": "RuleSet" }]
|
||||
},
|
||||
{ "name": "ruleSetRemoved", "parameters": [{ "name": "id", "$ref": "RuleSetId" }] },
|
||||
{
|
||||
"name": "prerenderAttemptCompleted",
|
||||
"description": "Fired when a prerender attempt is completed.",
|
||||
"parameters": [
|
||||
{ "name": "key", "$ref": "PreloadingAttemptKey" },
|
||||
{
|
||||
"name": "initiatingFrameId",
|
||||
"description": "The frame id of the frame initiating prerendering.",
|
||||
"$ref": "Page.FrameId"
|
||||
},
|
||||
{ "name": "prerenderingUrl", "type": "string" },
|
||||
{ "name": "finalStatus", "$ref": "PrerenderFinalStatus" },
|
||||
{
|
||||
"name": "disallowedApiMethod",
|
||||
"description": "This is used to give users more information about the name of the API call\nthat is incompatible with prerender and has caused the cancellation of the attempt",
|
||||
"optional": true,
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "preloadEnabledStateUpdated",
|
||||
"description": "Fired when a preload enabled state is updated.",
|
||||
@@ -12077,14 +12168,14 @@
|
||||
"id": "InterestGroupAccessType",
|
||||
"description": "Enum of interest group access types.",
|
||||
"type": "string",
|
||||
"enum": ["join", "leave", "update", "loaded", "bid", "win"]
|
||||
"enum": ["join", "leave", "update", "loaded", "bid", "win", "additionalBid", "additionalBidWin", "clear"]
|
||||
},
|
||||
{
|
||||
"id": "InterestGroupAd",
|
||||
"description": "Ad advertising element inside an interest group.",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "renderUrl", "type": "string" },
|
||||
{ "name": "renderURL", "type": "string" },
|
||||
{ "name": "metadata", "optional": true, "type": "string" }
|
||||
]
|
||||
},
|
||||
@@ -12097,10 +12188,10 @@
|
||||
{ "name": "name", "type": "string" },
|
||||
{ "name": "expirationTime", "$ref": "Network.TimeSinceEpoch" },
|
||||
{ "name": "joiningOrigin", "type": "string" },
|
||||
{ "name": "biddingUrl", "optional": true, "type": "string" },
|
||||
{ "name": "biddingWasmHelperUrl", "optional": true, "type": "string" },
|
||||
{ "name": "updateUrl", "optional": true, "type": "string" },
|
||||
{ "name": "trustedBiddingSignalsUrl", "optional": true, "type": "string" },
|
||||
{ "name": "biddingLogicURL", "optional": true, "type": "string" },
|
||||
{ "name": "biddingWasmHelperURL", "optional": true, "type": "string" },
|
||||
{ "name": "updateURL", "optional": true, "type": "string" },
|
||||
{ "name": "trustedBiddingSignalsURL", "optional": true, "type": "string" },
|
||||
{ "name": "trustedBiddingSignalsKeys", "type": "array", "items": { "type": "string" } },
|
||||
{ "name": "userBiddingSignals", "optional": true, "type": "string" },
|
||||
{ "name": "ads", "type": "array", "items": { "$ref": "InterestGroupAd" } },
|
||||
@@ -12275,20 +12366,24 @@
|
||||
{ "name": "value", "$ref": "UnsignedInt128AsBase16" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "AttributionReportingEventReportWindows",
|
||||
"experimental": true,
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "start", "description": "duration in seconds", "type": "integer" },
|
||||
{ "name": "ends", "description": "duration in seconds", "type": "array", "items": { "type": "integer" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "AttributionReportingSourceRegistration",
|
||||
"experimental": true,
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "time", "$ref": "Network.TimeSinceEpoch" },
|
||||
{ "name": "expiry", "description": "duration in seconds", "optional": true, "type": "integer" },
|
||||
{ "name": "eventReportWindow", "description": "duration in seconds", "optional": true, "type": "integer" },
|
||||
{
|
||||
"name": "aggregatableReportWindow",
|
||||
"description": "duration in seconds",
|
||||
"optional": true,
|
||||
"type": "integer"
|
||||
},
|
||||
{ "name": "expiry", "description": "duration in seconds", "type": "integer" },
|
||||
{ "name": "eventReportWindows", "$ref": "AttributionReportingEventReportWindows" },
|
||||
{ "name": "aggregatableReportWindow", "description": "duration in seconds", "type": "integer" },
|
||||
{ "name": "type", "$ref": "AttributionReportingSourceType" },
|
||||
{ "name": "sourceOrigin", "type": "string" },
|
||||
{ "name": "reportingOrigin", "type": "string" },
|
||||
|
||||
@@ -279,7 +279,7 @@ async function sendResponse(response: unknown): Promise<void> {
|
||||
}
|
||||
await fetch(`runtime/invocation/${requestId}/response`, {
|
||||
method: "POST",
|
||||
body: response === null ? null : JSON.stringify(response),
|
||||
body: response === null ? null : (typeof response === 'string' ? response : JSON.stringify(response)),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
48
packages/bun-types/buffer.d.ts
vendored
48
packages/bun-types/buffer.d.ts
vendored
@@ -2084,31 +2084,31 @@ declare module "buffer" {
|
||||
values(): IterableIterator<number>;
|
||||
}
|
||||
var Buffer: BufferConstructor;
|
||||
|
||||
/**
|
||||
* This function returns `true` if `input` contains only valid UTF-8-encoded data,
|
||||
* including the case in which `input` is empty.
|
||||
*
|
||||
* Throws if the `input` is a detached array buffer.
|
||||
* @since Bun v0.6.13
|
||||
* @param input The input to validate.
|
||||
*/
|
||||
export function isUtf8(
|
||||
input: TypedArray | ArrayBufferLike | DataView,
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* This function returns `true` if `input` contains only valid ASCII-encoded data,
|
||||
* including the case in which `input` is empty.
|
||||
*
|
||||
* Throws if the `input` is a detached array buffer.
|
||||
* @since Bun v0.6.13
|
||||
* @param input The input to validate.
|
||||
*/
|
||||
export function isAscii(
|
||||
input: TypedArray | ArrayBufferLike | DataView,
|
||||
): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns `true` if `input` contains only valid UTF-8-encoded data,
|
||||
* including the case in which `input` is empty.
|
||||
*
|
||||
* Throws if the `input` is a detached array buffer.
|
||||
* @since Bun v0.6.13
|
||||
* @param input The input to validate.
|
||||
*/
|
||||
export function isUtf8(
|
||||
input: TypedArray | ArrayBufferLike | DataView,
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* This function returns `true` if `input` contains only valid ASCII-encoded data,
|
||||
* including the case in which `input` is empty.
|
||||
*
|
||||
* Throws if the `input` is a detached array buffer.
|
||||
* @since Bun v0.6.13
|
||||
* @param input The input to validate.
|
||||
*/
|
||||
export function isAscii(
|
||||
input: TypedArray | ArrayBufferLike | DataView,
|
||||
): boolean;
|
||||
}
|
||||
declare module "node:buffer" {
|
||||
export * from "buffer";
|
||||
|
||||
48
packages/bun-types/bun-test.d.ts
vendored
48
packages/bun-types/bun-test.d.ts
vendored
@@ -27,6 +27,38 @@ declare module "bun:test" {
|
||||
|
||||
export const mock: {
|
||||
<T extends AnyFunction>(Function: T): Mock<T>;
|
||||
|
||||
/**
|
||||
* Replace the module `id` with the return value of `factory`.
|
||||
*
|
||||
* This is useful for mocking modules.
|
||||
*
|
||||
* @param id module ID to mock
|
||||
* @param factory a function returning an object that will be used as the exports of the mocked module
|
||||
*
|
||||
* @example
|
||||
* ## Example
|
||||
* ```ts
|
||||
* import { mock } from "bun:test";
|
||||
*
|
||||
* mock.module("fs/promises", () => {
|
||||
* return {
|
||||
* readFile: () => Promise.resolve("hello world"),
|
||||
* };
|
||||
* });
|
||||
*
|
||||
* import { readFile } from "fs/promises";
|
||||
*
|
||||
* console.log(await readFile("hello.txt", "utf8")); // hello world
|
||||
* ```
|
||||
*
|
||||
* ## More notes
|
||||
*
|
||||
* If the module is already loaded, exports are overwritten with the return
|
||||
* value of `factory`. If the export didn't exist before, it will not be
|
||||
* added to existing import statements. This is due to how ESM works.
|
||||
*/
|
||||
module(id: string, factory: () => any): void | Promise<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -479,13 +511,13 @@ declare module "bun:test" {
|
||||
* @param actual the actual value
|
||||
*/
|
||||
export const expect: {
|
||||
(actual?: unknown): Expect;
|
||||
<T = unknown>(actual?: T): Expect<T>;
|
||||
any: (
|
||||
constructor: ((..._: any[]) => any) | { new (..._: any[]): any },
|
||||
) => Expect;
|
||||
anything: () => Expect;
|
||||
stringContaining: (str: string) => Expect;
|
||||
stringMatching: (regex: RegExp | string) => Expect;
|
||||
stringContaining: (str: string) => Expect<string>;
|
||||
stringMatching: <T extends RegExp | string>(regex: T) => Expect<T>;
|
||||
};
|
||||
/**
|
||||
* Asserts that a value matches some criteria.
|
||||
@@ -982,6 +1014,16 @@ declare module "bun:test" {
|
||||
* @param end the end number (exclusive)
|
||||
*/
|
||||
toBeWithin(start: number, end: number): void;
|
||||
/**
|
||||
* Asserts that a value is equal to the expected string, ignoring any whitespace.
|
||||
*
|
||||
* @example
|
||||
* expect(" foo ").toEqualIgnoringWhitespace("foo");
|
||||
* expect("bar").toEqualIgnoringWhitespace(" bar ");
|
||||
*
|
||||
* @param expected the expected string
|
||||
*/
|
||||
toEqualIgnoringWhitespace(expected: string): void;
|
||||
/**
|
||||
* Asserts that a value is a `symbol`.
|
||||
*
|
||||
|
||||
9
packages/bun-types/bun.d.ts
vendored
9
packages/bun-types/bun.d.ts
vendored
@@ -1870,6 +1870,15 @@ declare module "bun" {
|
||||
*/
|
||||
port?: string | number;
|
||||
|
||||
/**
|
||||
* If the `SO_REUSEPORT` flag should be set.
|
||||
*
|
||||
* This allows multiple processes to bind to the same port, which is useful for load balancing.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
reusePort?: boolean;
|
||||
|
||||
/**
|
||||
* What hostname should the server listen on?
|
||||
*
|
||||
|
||||
8
packages/bun-types/globals.d.ts
vendored
8
packages/bun-types/globals.d.ts
vendored
@@ -546,6 +546,12 @@ interface Worker extends EventTarget, AbstractWorker {
|
||||
*/
|
||||
unref(): void;
|
||||
|
||||
/**
|
||||
* An integer identifier for the referenced thread. Inside the worker thread,
|
||||
* it is available as `require('node:worker_threads').threadId`.
|
||||
* This value is unique for each `Worker` instance inside a single process.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
threadId: number;
|
||||
}
|
||||
|
||||
@@ -733,6 +739,8 @@ interface Process {
|
||||
* On other operating systems, this returns `undefined`.
|
||||
*/
|
||||
constrainedMemory(): number | undefined;
|
||||
|
||||
send(data: any): void;
|
||||
}
|
||||
|
||||
interface MemoryUsageObject {
|
||||
|
||||
@@ -23,7 +23,7 @@ try {
|
||||
|
||||
const header = await file(join(import.meta.dir, "..", "header.txt")).text();
|
||||
const filesToCat = (await getDotTsFiles("./")).filter(
|
||||
f => !["./index.d.ts"].some(tf => f === tf),
|
||||
f => f !== "./index.d.ts",
|
||||
);
|
||||
|
||||
const fileContents: string[] = [];
|
||||
|
||||
@@ -45,6 +45,7 @@ describe("bun:test", () => {
|
||||
test("expect()", () => {
|
||||
expect(1).toBe(1);
|
||||
expect(1).not.toBe(2);
|
||||
// @ts-expect-error
|
||||
expect({ a: 1 }).toEqual({ a: 1, b: undefined });
|
||||
expect({ a: 1 }).toStrictEqual({ a: 1 });
|
||||
expect(new Set()).toHaveProperty("size");
|
||||
|
||||
4
packages/bun-types/ws.d.ts
vendored
4
packages/bun-types/ws.d.ts
vendored
@@ -74,6 +74,8 @@ declare module "ws" {
|
||||
WebSocket?: U | undefined;
|
||||
}
|
||||
|
||||
interface ServerOption extends WebSocketServerOptions {}
|
||||
|
||||
interface AddressInfo {
|
||||
address: string;
|
||||
family: string;
|
||||
@@ -219,4 +221,6 @@ declare module "ws" {
|
||||
listener: (...args: any[]) => void,
|
||||
): this;
|
||||
}
|
||||
|
||||
var Server: typeof WebSocketServer;
|
||||
}
|
||||
|
||||
@@ -397,6 +397,32 @@ int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
|
||||
return recv(fd, buf, length, flags);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/uio.h>
|
||||
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
struct iovec chunks[2];
|
||||
|
||||
chunks[0].iov_base = (char *)header;
|
||||
chunks[0].iov_len = header_length;
|
||||
chunks[1].iov_base = (char *)payload;
|
||||
chunks[1].iov_len = payload_length;
|
||||
|
||||
return writev(fd, chunks, 2);
|
||||
}
|
||||
#else
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
int written = bsd_send(fd, header, header_length, 0);
|
||||
if (written == header_length) {
|
||||
int second_write = bsd_send(fd, payload, payload_length, 0);
|
||||
if (second_write > 0) {
|
||||
written += second_write;
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
#endif
|
||||
|
||||
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
|
||||
|
||||
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
|
||||
@@ -427,43 +453,12 @@ int bsd_would_block() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
|
||||
// listen both on ipv6 and ipv4
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options) {
|
||||
struct addrinfo hints, *result;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
char port_string[16];
|
||||
snprintf(port_string, 16, "%d", port);
|
||||
|
||||
if (getaddrinfo(host, port_string, &hints, &result)) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
|
||||
struct addrinfo *listenAddr;
|
||||
for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET6) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
|
||||
listenAddr = a;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct addrinfo *a = result; a && listenFd == LIBUS_SOCKET_ERROR; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
|
||||
listenAddr = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
freeaddrinfo(result);
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
inline LIBUS_SOCKET_DESCRIPTOR bsd_bind_listen_fd(
|
||||
LIBUS_SOCKET_DESCRIPTOR listenFd,
|
||||
struct addrinfo *listenAddr,
|
||||
int port,
|
||||
int options
|
||||
) {
|
||||
|
||||
if (port != 0) {
|
||||
/* Otherwise, always enable SO_REUSEPORT and SO_REUSEADDR _unless_ options specify otherwise */
|
||||
@@ -487,22 +482,76 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
int disabled = 0;
|
||||
setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
|
||||
#endif
|
||||
|
||||
if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen) || listen(listenFd, 512)) {
|
||||
bsd_close_socket(listenFd);
|
||||
freeaddrinfo(result);
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return listenFd;
|
||||
}
|
||||
|
||||
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
|
||||
// listen both on ipv6 and ipv4
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options) {
|
||||
struct addrinfo hints, *result;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
char port_string[16];
|
||||
snprintf(port_string, 16, "%d", port);
|
||||
|
||||
if (getaddrinfo(host, port_string, &hints, &result)) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
|
||||
struct addrinfo *listenAddr;
|
||||
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET6) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
listenAddr = a;
|
||||
if (bsd_bind_listen_fd(listenFd, listenAddr, port, options) != LIBUS_SOCKET_ERROR) {
|
||||
freeaddrinfo(result);
|
||||
return listenFd;
|
||||
}
|
||||
|
||||
bsd_close_socket(listenFd);
|
||||
}
|
||||
}
|
||||
|
||||
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
|
||||
if (a->ai_family == AF_INET) {
|
||||
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol);
|
||||
if (listenFd == LIBUS_SOCKET_ERROR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
listenAddr = a;
|
||||
if (bsd_bind_listen_fd(listenFd, listenAddr, port, options) != LIBUS_SOCKET_ERROR) {
|
||||
freeaddrinfo(result);
|
||||
return listenFd;
|
||||
}
|
||||
|
||||
bsd_close_socket(listenFd);
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/un.h>
|
||||
#else
|
||||
@@ -768,4 +817,4 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path,
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd
|
||||
|
||||
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
|
||||
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
|
||||
int bsd_would_block();
|
||||
|
||||
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
|
||||
|
||||
@@ -344,6 +344,9 @@ void *us_socket_get_native_handle(int ssl, struct us_socket_t *s);
|
||||
* Set hint msg_more if you have more immediate data to write. */
|
||||
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more);
|
||||
|
||||
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
|
||||
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length);
|
||||
|
||||
/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
|
||||
* at any given point in time. Will remove any such pre set timer */
|
||||
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds);
|
||||
@@ -382,6 +385,7 @@ int us_socket_local_port(int ssl, struct us_socket_t *s);
|
||||
|
||||
/* Copy remote (IP) address of socket, or fail with zero length. */
|
||||
void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *length);
|
||||
void us_socket_local_address(int ssl, struct us_socket_t *s, char *buf, int *length);
|
||||
|
||||
/* Bun extras */
|
||||
struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds);
|
||||
|
||||
@@ -48,6 +48,16 @@ void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *le
|
||||
}
|
||||
}
|
||||
|
||||
void us_socket_local_address(int ssl, struct us_socket_t *s, char *buf, int *length) {
|
||||
struct bsd_addr_t addr;
|
||||
if (bsd_local_addr(us_poll_fd(&s->p), &addr) || *length < bsd_addr_get_ip_length(&addr)) {
|
||||
*length = 0;
|
||||
} else {
|
||||
*length = bsd_addr_get_ip_length(&addr);
|
||||
memcpy(buf, bsd_addr_get_ip(&addr), *length);
|
||||
}
|
||||
}
|
||||
|
||||
struct us_socket_context_t *us_socket_context(int ssl, struct us_socket_t *s) {
|
||||
return s->context;
|
||||
}
|
||||
@@ -151,6 +161,20 @@ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_e
|
||||
return us_socket_from_fd(ctx, socket_ext_size, fds[0]);
|
||||
}
|
||||
|
||||
/* This is not available for SSL sockets as it makes no sense. */
|
||||
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
|
||||
if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
|
||||
if (written != header_length + payload_length) {
|
||||
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
}
|
||||
|
||||
return written < 0 ? 0 : written;
|
||||
}
|
||||
|
||||
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd) {
|
||||
#ifdef LIBUS_USE_LIBUV
|
||||
@@ -301,4 +325,4 @@ unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const
|
||||
*port = bsd_addr_get_port(&addr);
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,12 @@ public:
|
||||
getLoopData()->corkedSocketIsSSL = SSL;
|
||||
}
|
||||
|
||||
void uncorkWithoutSending() {
|
||||
if (isCorked()) {
|
||||
getLoopData()->corkedSocket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cork this socket. Only one socket may ever be corked per-loop at any given time */
|
||||
void cork() {
|
||||
/* Extra check for invalid corking of others */
|
||||
|
||||
@@ -77,12 +77,12 @@ public:
|
||||
writeHeader("Date", std::string_view(((LoopData *) us_loop_ext(us_socket_context_loop(SSL, (us_socket_context(SSL, (us_socket_t *) this)))))->date, 29));
|
||||
|
||||
/* You can disable this altogether */
|
||||
#ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
|
||||
if (!Super::getLoopData()->noMark) {
|
||||
/* We only expose major version */
|
||||
writeHeader("uWebSockets", "20");
|
||||
}
|
||||
#endif
|
||||
// #ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
|
||||
// if (!Super::getLoopData()->noMark) {
|
||||
// /* We only expose major version */
|
||||
// writeHeader("uWebSockets", "20");
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
|
||||
/* Returns true on success, indicating that it might be feasible to write more data.
|
||||
|
||||
@@ -245,9 +245,14 @@ struct InflationStream {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save off the bytes we're about to overwrite */
|
||||
char* tailLocation = (char*)compressed.data() + compressed.length();
|
||||
char preTailBytes[4];
|
||||
memcpy(preTailBytes, tailLocation, 4);
|
||||
|
||||
/* Append tail to chunk */
|
||||
unsigned char tail[4] = {0x00, 0x00, 0xff, 0xff};
|
||||
memcpy((char *)compressed.data() + compressed.length(), tail, 4);
|
||||
memcpy(tailLocation, tail, 4);
|
||||
compressed = {compressed.data(), compressed.length() + 4};
|
||||
|
||||
/* We clear this one here, could be done better */
|
||||
@@ -275,6 +280,9 @@ struct InflationStream {
|
||||
inflateReset(&inflationStream);
|
||||
}
|
||||
|
||||
/* Restore the bytes we used for the tail */
|
||||
memcpy(tailLocation, preTailBytes, 4);
|
||||
|
||||
if ((err != Z_BUF_ERROR && err != Z_OK) || zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -105,48 +105,73 @@ public:
|
||||
|
||||
/* If we are subscribers and have messages to drain we need to drain them here to stay synced */
|
||||
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
|
||||
if (webSocketData->subscriber) {
|
||||
/* This will call back into us, send. */
|
||||
webSocketContextData->topicTree->drain(webSocketData->subscriber);
|
||||
}
|
||||
|
||||
/* Transform the message to compressed domain if requested */
|
||||
if (compress) {
|
||||
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
|
||||
|
||||
/* Check and correct the compress hint. It is never valid to compress 0 bytes */
|
||||
if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
|
||||
LoopData *loopData = Super::getLoopData();
|
||||
/* Compress using either shared or dedicated deflationStream */
|
||||
if (webSocketData->deflationStream) {
|
||||
message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false);
|
||||
/* Special path for long sends of non-compressed, non-SSL messages */
|
||||
if (message.length() >= 16 * 1024 && !compress && !SSL && !webSocketData->subscriber && getBufferedAmount() == 0 && Super::getLoopData()->corkOffset == 0) {
|
||||
char header[10];
|
||||
int header_length = (int) protocol::formatMessage<isServer>(header, nullptr, 0, opCode, message.length(), compress, fin);
|
||||
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length());
|
||||
|
||||
if (written != header_length + (int) message.length()) {
|
||||
/* Buffer up backpressure */
|
||||
if (written > header_length) {
|
||||
webSocketData->buffer.append(message.data() + written - header_length, message.length() - (size_t) (written - header_length));
|
||||
} else {
|
||||
message = loopData->deflationStream->deflate(loopData->zlibContext, message, true);
|
||||
webSocketData->buffer.append(header + written, (size_t) header_length - (size_t) written);
|
||||
webSocketData->buffer.append(message.data(), message.length());
|
||||
}
|
||||
} else {
|
||||
compress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get size, allocate size, write if needed */
|
||||
size_t messageFrameSize = protocol::messageFrameSize(message.length());
|
||||
auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize);
|
||||
protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress, fin);
|
||||
|
||||
/* Depending on size of message we have different paths */
|
||||
if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) {
|
||||
/* This is a drain */
|
||||
auto[written, failed] = Super::write(nullptr, 0);
|
||||
if (failed) {
|
||||
/* Return false for failure, skipping to reset the timeout below */
|
||||
/* We cannot still be corked if we have backpressure.
|
||||
* We also cannot uncork normally since it will re-write the already buffered
|
||||
* up backpressure again. */
|
||||
Super::uncorkWithoutSending();
|
||||
return BACKPRESSURE;
|
||||
}
|
||||
} else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) {
|
||||
/* Uncork if we came here uncorked */
|
||||
auto [written, failed] = Super::uncork();
|
||||
if (failed) {
|
||||
return BACKPRESSURE;
|
||||
} else {
|
||||
|
||||
if (webSocketData->subscriber) {
|
||||
/* This will call back into us, send. */
|
||||
webSocketContextData->topicTree->drain(webSocketData->subscriber);
|
||||
}
|
||||
|
||||
/* Transform the message to compressed domain if requested */
|
||||
if (compress) {
|
||||
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
|
||||
|
||||
/* Check and correct the compress hint. It is never valid to compress 0 bytes */
|
||||
if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
|
||||
LoopData *loopData = Super::getLoopData();
|
||||
/* Compress using either shared or dedicated deflationStream */
|
||||
if (webSocketData->deflationStream) {
|
||||
message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false);
|
||||
} else {
|
||||
message = loopData->deflationStream->deflate(loopData->zlibContext, message, true);
|
||||
}
|
||||
} else {
|
||||
compress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get size, allocate size, write if needed */
|
||||
size_t messageFrameSize = protocol::messageFrameSize(message.length());
|
||||
auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize);
|
||||
protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress, fin);
|
||||
|
||||
/* Depending on size of message we have different paths */
|
||||
if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) {
|
||||
/* This is a drain */
|
||||
auto[written, failed] = Super::write(nullptr, 0);
|
||||
if (failed) {
|
||||
/* Return false for failure, skipping to reset the timeout below */
|
||||
return BACKPRESSURE;
|
||||
}
|
||||
} else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) {
|
||||
/* Uncork if we came here uncorked */
|
||||
auto [written, failed] = Super::uncork();
|
||||
if (failed) {
|
||||
return BACKPRESSURE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Every successful send resets the timeout */
|
||||
@@ -221,6 +246,8 @@ public:
|
||||
/* There is no timeout when failing to uncork for WebSockets,
|
||||
* as that is handled by idleTimeout */
|
||||
auto [written, failed] = Super::uncork();
|
||||
(void)written;
|
||||
(void)failed;
|
||||
} else {
|
||||
/* We are already corked, or can't cork so let's just call the handler */
|
||||
handler();
|
||||
@@ -349,4 +376,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_WEBSOCKET_H
|
||||
#endif // UWS_WEBSOCKET_H
|
||||
@@ -1,11 +0,0 @@
|
||||
# Upcoming release
|
||||
|
||||
- [Bun.js] Enable `SharedArrayBuffer` and Atomics
|
||||
|
||||
# 0.41.0
|
||||
|
||||
- [bun run] `bun run ./file.js` now supports running JavaScript, TS, TSX, and JSX files with Bun.js. Before, it would say `"error: Missing script"`. If there is a `#!` shebang at the start of the file, the file will not be run with Bun.js. You can still use Node & Deno with `bun run`, that works the same as before.
|
||||
- [Bun.js] Top-level await
|
||||
- [Bun.js] `performance.now()` is implemented
|
||||
- [Bun.js] `fetch()` is fixed
|
||||
- [.env loader] Pass through process environment variable values verbatim instead of treating them similarly to .env files. `.env` needs special parsing because quotes are optional, values are potentially nested, and it's whitespace sensitive. This probably also improves the performance of loading process environment variables, but that was already pretty quick so it probably doesn't matter.
|
||||
@@ -279,5 +279,13 @@ pub fn BabyList(comptime Type: type) type {
|
||||
|
||||
return this.len - initial;
|
||||
}
|
||||
|
||||
pub fn writeTypeAsBytesAssumeCapacity(this: *@This(), comptime Int: type, int: Int) void {
|
||||
if (comptime Type != u8)
|
||||
@compileError("Unsupported for type " ++ @typeName(Type));
|
||||
std.debug.assert(this.cap >= this.len + @sizeOf(Int));
|
||||
@as([*]align(1) Int, @ptrCast(this.ptr[this.len .. this.len + @sizeOf(Int)]))[0] = int;
|
||||
this.len += @sizeOf(Int);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
5
|
||||
7
|
||||
Submodule src/bun.js/WebKit updated: e1aa0a58e2...1a49a1f94b
@@ -102,11 +102,12 @@ const LibInfo = struct {
|
||||
) catch unreachable;
|
||||
const promise_value = request.head.promise.value();
|
||||
|
||||
const hints = query.options.toLibC();
|
||||
const errno = getaddrinfo_async_start_(
|
||||
&request.backend.libinfo.machport,
|
||||
name_z.ptr,
|
||||
null,
|
||||
null,
|
||||
if (hints != null) &hints.? else null,
|
||||
GetAddrInfoRequest.getAddrInfoAsyncCallback,
|
||||
request,
|
||||
);
|
||||
@@ -860,7 +861,7 @@ pub const CAresNameInfo = struct {
|
||||
return;
|
||||
}
|
||||
var name_info = result.?;
|
||||
const array = name_info.toJSReponse(this.globalThis.allocator(), this.globalThis);
|
||||
const array = name_info.toJSResponse(this.globalThis.allocator(), this.globalThis);
|
||||
this.onComplete(array);
|
||||
return;
|
||||
}
|
||||
@@ -1250,7 +1251,7 @@ pub const CAresReverse = struct {
|
||||
return;
|
||||
}
|
||||
var node = result.?;
|
||||
const array = node.toJSReponse(this.globalThis.allocator(), this.globalThis, "");
|
||||
const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, "");
|
||||
this.onComplete(array);
|
||||
return;
|
||||
}
|
||||
@@ -1321,7 +1322,7 @@ pub fn CAresLookup(comptime cares_type: type, comptime type_name: []const u8) ty
|
||||
return;
|
||||
}
|
||||
var node = result.?;
|
||||
const array = node.toJSReponse(this.globalThis.allocator(), this.globalThis, type_name);
|
||||
const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, type_name);
|
||||
this.onComplete(array);
|
||||
return;
|
||||
}
|
||||
@@ -1536,7 +1537,7 @@ pub const DNSResolver = struct {
|
||||
|
||||
var pending: ?*CAresLookup(cares_type, lookup_name) = key.lookup.head.next;
|
||||
var prev_global = key.lookup.head.globalThis;
|
||||
var array = addr.toJSReponse(this.vm.allocator, prev_global, lookup_name);
|
||||
var array = addr.toJSResponse(this.vm.allocator, prev_global, lookup_name);
|
||||
defer addr.deinit();
|
||||
array.ensureStillAlive();
|
||||
key.lookup.head.onComplete(array);
|
||||
@@ -1547,7 +1548,7 @@ pub const DNSResolver = struct {
|
||||
while (pending) |value| {
|
||||
var new_global = value.globalThis;
|
||||
if (prev_global != new_global) {
|
||||
array = addr.toJSReponse(this.vm.allocator, new_global, lookup_name);
|
||||
array = addr.toJSResponse(this.vm.allocator, new_global, lookup_name);
|
||||
prev_global = new_global;
|
||||
}
|
||||
pending = value.next;
|
||||
@@ -1666,7 +1667,7 @@ pub const DNSResolver = struct {
|
||||
// The callback need not and should not attempt to free the memory
|
||||
// pointed to by hostent; the ares library will free it when the
|
||||
// callback returns.
|
||||
var array = addr.toJSReponse(this.vm.allocator, prev_global, "");
|
||||
var array = addr.toJSResponse(this.vm.allocator, prev_global, "");
|
||||
array.ensureStillAlive();
|
||||
key.lookup.head.onComplete(array);
|
||||
bun.default_allocator.destroy(key.lookup);
|
||||
@@ -1676,7 +1677,7 @@ pub const DNSResolver = struct {
|
||||
while (pending) |value| {
|
||||
var new_global = value.globalThis;
|
||||
if (prev_global != new_global) {
|
||||
array = addr.toJSReponse(this.vm.allocator, new_global, "");
|
||||
array = addr.toJSResponse(this.vm.allocator, new_global, "");
|
||||
prev_global = new_global;
|
||||
}
|
||||
pending = value.next;
|
||||
@@ -1707,7 +1708,7 @@ pub const DNSResolver = struct {
|
||||
var pending: ?*CAresNameInfo = key.lookup.head.next;
|
||||
var prev_global = key.lookup.head.globalThis;
|
||||
|
||||
var array = name_info.toJSReponse(this.vm.allocator, prev_global);
|
||||
var array = name_info.toJSResponse(this.vm.allocator, prev_global);
|
||||
array.ensureStillAlive();
|
||||
key.lookup.head.onComplete(array);
|
||||
bun.default_allocator.destroy(key.lookup);
|
||||
@@ -1717,7 +1718,7 @@ pub const DNSResolver = struct {
|
||||
while (pending) |value| {
|
||||
var new_global = value.globalThis;
|
||||
if (prev_global != new_global) {
|
||||
array = name_info.toJSReponse(this.vm.allocator, new_global);
|
||||
array = name_info.toJSResponse(this.vm.allocator, new_global);
|
||||
prev_global = new_global;
|
||||
}
|
||||
pending = value.next;
|
||||
@@ -2475,7 +2476,7 @@ pub const DNSResolver = struct {
|
||||
return dns_lookup.promise.value();
|
||||
}
|
||||
|
||||
// var hints_buf = &[_]c_ares.AddrInfo_hints{query.toCAres()};
|
||||
var hints_buf = &[_]c_ares.AddrInfo_hints{query.toCAres()};
|
||||
var request = GetAddrInfoRequest.init(
|
||||
cache,
|
||||
.{
|
||||
@@ -2491,7 +2492,7 @@ pub const DNSResolver = struct {
|
||||
channel.getAddrInfo(
|
||||
query.name,
|
||||
query.port,
|
||||
&.{},
|
||||
hints_buf,
|
||||
GetAddrInfoRequest,
|
||||
request,
|
||||
GetAddrInfoRequest.onCaresComplete,
|
||||
|
||||
@@ -1929,7 +1929,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
|
||||
pub fn finalize(this: *This) callconv(.C) void {
|
||||
log("finalize()", .{});
|
||||
log("finalize() {d}", .{@intFromPtr(this)});
|
||||
if (!this.detached) {
|
||||
this.detached = true;
|
||||
if (!this.socket.isClosed()) {
|
||||
|
||||
@@ -62,11 +62,9 @@ pub const Subprocess = struct {
|
||||
is_sync: bool = false,
|
||||
this_jsvalue: JSC.JSValue = .zero,
|
||||
|
||||
ipc: IPCMode,
|
||||
// this is only ever accessed when `ipc` is not `none`
|
||||
ipc_socket: IPC.Socket = undefined,
|
||||
ipc_mode: IPCMode,
|
||||
ipc_callback: JSC.Strong = .{},
|
||||
ipc_buffer: bun.ByteList,
|
||||
ipc: IPC.IPCData,
|
||||
|
||||
has_pending_unref: bool = false,
|
||||
pub const SignalCode = bun.SignalCode;
|
||||
@@ -83,7 +81,7 @@ pub const Subprocess = struct {
|
||||
|
||||
pub fn updateHasPendingActivityFlag(this: *Subprocess) void {
|
||||
@fence(.SeqCst);
|
||||
this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null and this.ipc == .none and this.has_pending_unref, .SeqCst);
|
||||
this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null and this.ipc_mode == .none and this.has_pending_unref, .SeqCst);
|
||||
}
|
||||
|
||||
pub fn hasPendingActivity(this: *Subprocess) callconv(.C) bool {
|
||||
@@ -93,7 +91,7 @@ pub const Subprocess = struct {
|
||||
|
||||
pub fn updateHasPendingActivity(this: *Subprocess) void {
|
||||
@fence(.Release);
|
||||
this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null and this.ipc == .none and this.has_pending_unref, .Release);
|
||||
this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null and this.ipc_mode == .none and this.has_pending_unref, .Release);
|
||||
}
|
||||
|
||||
pub fn ref(this: *Subprocess) void {
|
||||
@@ -428,7 +426,7 @@ pub const Subprocess = struct {
|
||||
}
|
||||
|
||||
pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue {
|
||||
if (this.ipc == .none) {
|
||||
if (this.ipc_mode == .none) {
|
||||
global.throw("Subprocess.send() can only be used if an IPC channel is open.", .{});
|
||||
return .zero;
|
||||
}
|
||||
@@ -440,20 +438,16 @@ pub const Subprocess = struct {
|
||||
|
||||
const value = callFrame.argument(0);
|
||||
|
||||
const success = IPC.serializeJSValueForSubprocess(
|
||||
global,
|
||||
value,
|
||||
this.ipc_socket.fd(),
|
||||
);
|
||||
const success = this.ipc.serializeAndSend(global, value);
|
||||
if (!success) return .zero;
|
||||
|
||||
return JSC.JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
pub fn disconnect(this: *Subprocess) void {
|
||||
if (this.ipc == .none) return;
|
||||
this.ipc_socket.close(0, null);
|
||||
this.ipc = .none;
|
||||
if (this.ipc_mode == .none) return;
|
||||
this.ipc.socket.close(0, null);
|
||||
this.ipc_mode = .none;
|
||||
}
|
||||
|
||||
pub fn getPid(
|
||||
@@ -1541,15 +1535,15 @@ pub const Subprocess = struct {
|
||||
.stderr = Readable.init(stdio[bun.STDERR_FD], stderr_pipe[0], jsc_vm.allocator, default_max_buffer_size),
|
||||
.on_exit_callback = if (on_exit_callback != .zero) JSC.Strong.create(on_exit_callback, globalThis) else .{},
|
||||
.is_sync = is_sync,
|
||||
.ipc = ipc_mode,
|
||||
.ipc_mode = ipc_mode,
|
||||
// will be assigned in the block below
|
||||
.ipc_socket = socket,
|
||||
.ipc_buffer = bun.ByteList{},
|
||||
.ipc = .{ .socket = socket },
|
||||
.ipc_callback = if (ipc_callback != .zero) JSC.Strong.create(ipc_callback, globalThis) else undefined,
|
||||
};
|
||||
if (ipc_mode != .none) {
|
||||
var ptr = socket.ext(*Subprocess);
|
||||
ptr.?.* = subprocess;
|
||||
subprocess.ipc.writeVersionPacket();
|
||||
}
|
||||
|
||||
if (subprocess.stdin == .pipe) {
|
||||
@@ -2060,7 +2054,7 @@ pub const Subprocess = struct {
|
||||
const result = cb.callWithThis(
|
||||
this.globalThis,
|
||||
this.this_jsvalue,
|
||||
&[_]JSValue{data},
|
||||
&[_]JSValue{ data, this.this_jsvalue },
|
||||
);
|
||||
data.ensureStillAlive();
|
||||
if (result.isAnyError()) {
|
||||
@@ -2073,7 +2067,7 @@ pub const Subprocess = struct {
|
||||
|
||||
pub fn handleIPCClose(this: *Subprocess, _: IPC.Socket) void {
|
||||
// uSocket is already freed so calling .close() on the socket can segfault
|
||||
this.ipc = .none;
|
||||
this.ipc_mode = .none;
|
||||
this.updateHasPendingActivity();
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,8 @@ fn x509PrintGeneralName(out: *BoringSSL.BIO, name: *BoringSSL.GENERAL_NAME) bool
|
||||
// instead always print its numeric representation.
|
||||
var oline: [256]u8 = undefined;
|
||||
_ = BoringSSL.OBJ_obj2txt(&oline, @sizeOf(@TypeOf(oline)), name.d.rid, 1);
|
||||
_ = BoringSSL.BIO_printf(out, "Registered ID:%s", &oline);
|
||||
// Workaround for https://github.com/ziglang/zig/issues/16197
|
||||
_ = BoringSSL.BIO_printf(out, "Registered ID:%s", @as([*]const u8, &oline));
|
||||
} else if (name.name_type == .GEN_X400) {
|
||||
_ = BoringSSL.BIO_printf(out, "X400Name:<unsupported>");
|
||||
} else if (name.name_type == .GEN_EDIPARTY) {
|
||||
@@ -301,7 +302,8 @@ fn x509InfoAccessPrint(out: *BoringSSL.BIO, ext: *BoringSSL.X509_EXTENSION) bool
|
||||
}
|
||||
var tmp: [80]u8 = undefined;
|
||||
_ = BoringSSL.i2t_ASN1_OBJECT(&tmp, @sizeOf(@TypeOf(tmp)), desc.method);
|
||||
_ = BoringSSL.BIO_printf(out, "%s - ", &tmp);
|
||||
// Workaround for https://github.com/ziglang/zig/issues/16197
|
||||
_ = BoringSSL.BIO_printf(out, "%s - ", @as([*]const u8, &tmp));
|
||||
|
||||
if (!x509PrintGeneralName(out, desc.location)) {
|
||||
return false;
|
||||
|
||||
@@ -384,10 +384,10 @@ pub const HTMLRewriter = struct {
|
||||
|
||||
result.* = Response{
|
||||
.allocator = bun.default_allocator,
|
||||
.init = .{
|
||||
.status_code = 200,
|
||||
},
|
||||
.body = .{
|
||||
.init = .{
|
||||
.status_code = 200,
|
||||
},
|
||||
.value = .{
|
||||
.Locked = .{
|
||||
.global = global,
|
||||
@@ -397,16 +397,16 @@ pub const HTMLRewriter = struct {
|
||||
},
|
||||
};
|
||||
|
||||
result.body.init.method = original.body.init.method;
|
||||
result.body.init.status_code = original.body.init.status_code;
|
||||
result.init.method = original.init.method;
|
||||
result.init.status_code = original.init.status_code;
|
||||
result.init.status_text = original.init.status_text.clone();
|
||||
|
||||
// https://github.com/oven-sh/bun/issues/3334
|
||||
if (original.body.init.headers) |headers| {
|
||||
result.body.init.headers = headers.cloneThis(global);
|
||||
if (original.init.headers) |headers| {
|
||||
result.init.headers = headers.cloneThis(global);
|
||||
}
|
||||
|
||||
result.url = original.url.clone();
|
||||
result.status_text = original.status_text.clone();
|
||||
var value = original.getBodyValue();
|
||||
sink.bodyValueBufferer = JSC.WebCore.BodyValueBufferer.init(sink, onFinishedBuffering, sink.global, bun.default_allocator);
|
||||
sink.bodyValueBufferer.?.run(value) catch |buffering_error| {
|
||||
@@ -606,10 +606,10 @@ pub const HTMLRewriter = struct {
|
||||
|
||||
// result.* = Response{
|
||||
// .allocator = bun.default_allocator,
|
||||
// .init = .{
|
||||
// .status_code = 200,
|
||||
// },
|
||||
// .body = .{
|
||||
// .init = .{
|
||||
// .status_code = 200,
|
||||
// },
|
||||
// .value = .{
|
||||
// .Locked = .{
|
||||
// .global = global,
|
||||
@@ -619,9 +619,9 @@ pub const HTMLRewriter = struct {
|
||||
// },
|
||||
// };
|
||||
|
||||
// result.body.init.headers = original.body.init.headers;
|
||||
// result.body.init.method = original.body.init.method;
|
||||
// result.body.init.status_code = original.body.init.status_code;
|
||||
// result.init.headers = original.init.headers;
|
||||
// result.init.method = original.init.method;
|
||||
// result.init.status_code = original.init.status_code;
|
||||
|
||||
// result.url = bun.default_allocator.dupe(u8, original.url) catch unreachable;
|
||||
// result.status_text = bun.default_allocator.dupe(u8, original.status_text) catch unreachable;
|
||||
|
||||
@@ -45,6 +45,10 @@ function generate(name) {
|
||||
getter: "getHostname",
|
||||
cache: true,
|
||||
},
|
||||
address: {
|
||||
getter: "getAddress",
|
||||
cache: true,
|
||||
},
|
||||
protocol: {
|
||||
getter: "getProtocol",
|
||||
},
|
||||
|
||||
@@ -2988,7 +2988,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
var needs_content_type = true;
|
||||
const content_type: MimeType = brk: {
|
||||
if (response.body.init.headers) |headers_| {
|
||||
if (response.init.headers) |headers_| {
|
||||
if (headers_.fastGet(.ContentType)) |content| {
|
||||
needs_content_type = false;
|
||||
break :brk MimeType.byName(content.slice());
|
||||
@@ -3008,7 +3008,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
};
|
||||
|
||||
var has_content_disposition = false;
|
||||
if (response.body.init.headers) |headers_| {
|
||||
if (response.init.headers) |headers_| {
|
||||
has_content_disposition = headers_.fastHas(.ContentDisposition);
|
||||
needs_content_range = needs_content_range and headers_.fastHas(.ContentRange);
|
||||
if (needs_content_range) {
|
||||
@@ -3018,7 +3018,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
this.writeStatus(status);
|
||||
this.writeHeaders(headers_);
|
||||
|
||||
response.body.init.headers = null;
|
||||
response.init.headers = null;
|
||||
headers_.deref();
|
||||
} else if (needs_content_range) {
|
||||
status = 206;
|
||||
@@ -5297,6 +5297,37 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
return JSC.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.activeSocketsCount())))));
|
||||
}
|
||||
|
||||
pub fn getAddress(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue {
|
||||
switch (this.config.address) {
|
||||
.unix => |unix| {
|
||||
var value = bun.String.create(bun.sliceTo(@constCast(unix), 0));
|
||||
defer value.deref();
|
||||
return value.toJS(globalThis);
|
||||
},
|
||||
.tcp => {
|
||||
var port: u16 = this.config.address.tcp.port;
|
||||
|
||||
if (this.listener) |listener| {
|
||||
port = @intCast(listener.getLocalPort());
|
||||
|
||||
var buf: [64]u8 = [_]u8{0} ** 64;
|
||||
var is_ipv6: bool = false;
|
||||
|
||||
if (listener.socket().localAddressText(&buf, &is_ipv6)) |slice| {
|
||||
var ip = bun.String.create(slice);
|
||||
return JSSocketAddress__create(
|
||||
this.globalThis,
|
||||
ip.toJS(this.globalThis),
|
||||
port,
|
||||
is_ipv6,
|
||||
);
|
||||
}
|
||||
}
|
||||
return JSValue.jsNull();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getHostname(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue {
|
||||
if (this.cached_hostname.isEmpty()) {
|
||||
if (this.listener) |listener| {
|
||||
|
||||
@@ -1178,8 +1178,7 @@ pub fn DOMCall(
|
||||
\\ thisObject->putDirect(
|
||||
\\ globalObject->vm(),
|
||||
\\ Identifier::fromString(globalObject->vm(), "{[name]s}"_s),
|
||||
\\ function,
|
||||
\\ JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0
|
||||
\\ function
|
||||
\\ );
|
||||
\\}}
|
||||
;
|
||||
|
||||
@@ -22,7 +22,7 @@ AsyncContextFrame* AsyncContextFrame::create(VM& vm, JSC::Structure* structure,
|
||||
AsyncContextFrame* AsyncContextFrame::create(JSGlobalObject* global, JSValue callback, JSValue context)
|
||||
{
|
||||
auto& vm = global->vm();
|
||||
AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, static_cast<Zig::GlobalObject*>(global)->AsyncContextFrameStructure());
|
||||
AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, jsCast<Zig::GlobalObject*>(global)->AsyncContextFrameStructure());
|
||||
asyncContextData->finishCreation(vm);
|
||||
asyncContextData->callback.set(vm, asyncContextData, callback);
|
||||
asyncContextData->context.set(vm, asyncContextData, context);
|
||||
@@ -47,7 +47,7 @@ JSValue AsyncContextFrame::withAsyncContextIfNeeded(JSGlobalObject* globalObject
|
||||
auto& vm = globalObject->vm();
|
||||
return AsyncContextFrame::create(
|
||||
vm,
|
||||
static_cast<Zig::GlobalObject*>(globalObject)->AsyncContextFrameStructure(),
|
||||
jsCast<Zig::GlobalObject*>(globalObject)->AsyncContextFrameStructure(),
|
||||
callback,
|
||||
context);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ static JSValue constructPluginObject(VM& vm, JSObject* bunObject)
|
||||
auto* globalObject = bunObject->globalObject();
|
||||
JSFunction* pluginFunction = JSFunction::create(vm, globalObject, 1, String("plugin"_s), jsFunctionBunPlugin, ImplementationVisibility::Public, NoIntrinsic);
|
||||
pluginFunction->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "clearAll"_s), 1, jsFunctionBunPluginClear, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
return pluginFunction;
|
||||
}
|
||||
@@ -222,33 +222,33 @@ static JSValue constructDNSObject(VM& vm, JSObject* bunObject)
|
||||
JSGlobalObject* globalObject = bunObject->globalObject();
|
||||
JSC::JSObject* dnsObject = JSC::constructEmptyObject(globalObject);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "lookup"_s), 2, Bun__DNSResolver__lookup, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolve"_s), 2, Bun__DNSResolver__resolve, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveSrv"_s), 2, Bun__DNSResolver__resolveSrv, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveTxt"_s), 2, Bun__DNSResolver__resolveTxt, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveSoa"_s), 2, Bun__DNSResolver__resolveSoa, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveNaptr"_s), 2, Bun__DNSResolver__resolveNaptr, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveMx"_s), 2, Bun__DNSResolver__resolveMx, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveCaa"_s), 2, Bun__DNSResolver__resolveCaa, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveNs"_s), 2, Bun__DNSResolver__resolveNs, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolvePtr"_s), 2, Bun__DNSResolver__resolvePtr, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveCname"_s), 2, Bun__DNSResolver__resolveCname, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "getServers"_s), 2, Bun__DNSResolver__getServers, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "reverse"_s), 2, Bun__DNSResolver__reverse, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "lookupService"_s), 2, Bun__DNSResolver__lookupService, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
JSC::PropertyAttribute::DontDelete | 0);
|
||||
return dnsObject;
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ static JSValue constructBunPeekObject(VM& vm, JSObject* bunObject)
|
||||
JSC::Identifier identifier = JSC::Identifier::fromString(vm, "peek"_s);
|
||||
JSFunction* peekFunction = JSFunction::create(vm, globalObject, 2, WTF::String("peek"_s), functionBunPeek, ImplementationVisibility::Public, NoIntrinsic);
|
||||
JSFunction* peekStatus = JSFunction::create(vm, globalObject, 1, WTF::String("status"_s), functionBunPeekStatus, ImplementationVisibility::Public, NoIntrinsic);
|
||||
peekFunction->putDirect(vm, PropertyName(JSC::Identifier::fromString(vm, "status"_s)), peekStatus, JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
|
||||
peekFunction->putDirect(vm, PropertyName(JSC::Identifier::fromString(vm, "status"_s)), peekStatus, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
return peekFunction;
|
||||
}
|
||||
@@ -663,6 +663,7 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBunObject, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
@@ -673,15 +674,14 @@ public:
|
||||
void finishCreation(JSC::VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
}
|
||||
|
||||
static JSBunObject* create(JSC::VM& vm, JSGlobalObject* globalObject)
|
||||
{
|
||||
auto* object = new (NotNull, JSC::allocateCell<JSBunObject>(vm)) JSBunObject(vm, createStructure(vm, globalObject, globalObject->objectPrototype()));
|
||||
auto structure = createStructure(vm, globalObject, globalObject->objectPrototype());
|
||||
auto* object = new (NotNull, JSC::allocateCell<JSBunObject>(vm)) JSBunObject(vm, structure);
|
||||
object->finishCreation(vm);
|
||||
|
||||
return object;
|
||||
}
|
||||
};
|
||||
@@ -702,11 +702,11 @@ public:
|
||||
#undef bunObjectReadableStreamToJSONCodeGenerator
|
||||
#undef bunObjectReadableStreamToTextCodeGenerator
|
||||
|
||||
const JSC::ClassInfo JSBunObject::s_info = { "Bun"_s, &JSNonFinalObject::s_info, &bunObjectTable, nullptr, CREATE_METHOD_TABLE(JSBunObject) };
|
||||
const JSC::ClassInfo JSBunObject::s_info = { "Bun"_s, &Base::s_info, &bunObjectTable, nullptr, CREATE_METHOD_TABLE(JSBunObject) };
|
||||
|
||||
JSC::JSObject* createBunObject(VM& vm, JSObject* globalObject)
|
||||
{
|
||||
return JSBunObject::create(vm, static_cast<Zig::GlobalObject*>(globalObject));
|
||||
return JSBunObject::create(vm, jsCast<Zig::GlobalObject*>(globalObject));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "JavaScriptCore/JSObjectInlines.h"
|
||||
#include "wtf/text/WTFString.h"
|
||||
#include "JavaScriptCore/JSCInlines.h"
|
||||
#include "JavaScriptCore/StrongInlines.h"
|
||||
|
||||
#include "JavaScriptCore/ObjectConstructor.h"
|
||||
#include "JavaScriptCore/SubspaceInlines.h"
|
||||
@@ -21,6 +22,11 @@
|
||||
#include "JavaScriptCore/RegularExpression.h"
|
||||
#include "JavaScriptCore/JSMap.h"
|
||||
#include "JavaScriptCore/JSMapInlines.h"
|
||||
#include "JavaScriptCore/JSModuleRecord.h"
|
||||
#include "JavaScriptCore/JSModuleNamespaceObject.h"
|
||||
#include "JavaScriptCore/SourceOrigin.h"
|
||||
#include "JavaScriptCore/JSModuleLoader.h"
|
||||
#include "CommonJSModuleRecord.h"
|
||||
|
||||
namespace Zig {
|
||||
|
||||
@@ -402,6 +408,277 @@ JSFunction* BunPlugin::Group::find(JSC::JSGlobalObject* globalObject, String& pa
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BunPlugin::OnLoad::addModuleMock(JSC::VM& vm, const String& path, JSC::JSObject* mockObject)
|
||||
{
|
||||
Zig::GlobalObject* globalObject = Zig::jsCast<Zig::GlobalObject*>(mockObject->globalObject());
|
||||
|
||||
if (globalObject->onLoadPlugins.virtualModules == nullptr) {
|
||||
globalObject->onLoadPlugins.virtualModules = new BunPlugin::VirtualModuleMap;
|
||||
}
|
||||
auto* virtualModules = globalObject->onLoadPlugins.virtualModules;
|
||||
|
||||
virtualModules->set(path, JSC::Strong<JSC::JSObject> { vm, mockObject });
|
||||
}
|
||||
|
||||
class JSModuleMock final : public JSC::JSNonFinalObject {
|
||||
public:
|
||||
using Base = JSC::JSNonFinalObject;
|
||||
|
||||
mutable WriteBarrier<JSObject> callbackFunctionOrCachedResult;
|
||||
bool hasCalledModuleMock = false;
|
||||
|
||||
static JSModuleMock* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* callback);
|
||||
static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype);
|
||||
|
||||
DECLARE_INFO;
|
||||
DECLARE_VISIT_CHILDREN;
|
||||
|
||||
JSObject* executeOnce(JSC::JSGlobalObject* lexicalGlobalObject);
|
||||
|
||||
template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
|
||||
return nullptr;
|
||||
return WebCore::subspaceForImpl<JSModuleMock, WebCore::UseCustomHeapCellType::No>(
|
||||
vm,
|
||||
[](auto& spaces) { return spaces.m_clientSubspaceForJSModuleMock.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSModuleMock = std::forward<decltype(space)>(space); },
|
||||
[](auto& spaces) { return spaces.m_subspaceForJSModuleMock.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_subspaceForJSModuleMock = std::forward<decltype(space)>(space); });
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM&, JSC::JSObject* callback);
|
||||
|
||||
private:
|
||||
JSModuleMock(JSC::VM&, JSC::Structure*);
|
||||
};
|
||||
|
||||
const JSC::ClassInfo JSModuleMock::s_info = { "ModuleMock"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSModuleMock) };
|
||||
|
||||
JSModuleMock* JSModuleMock::create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* callback)
|
||||
{
|
||||
JSModuleMock* ptr = new (NotNull, JSC::allocateCell<JSModuleMock>(vm)) JSModuleMock(vm, structure);
|
||||
ptr->finishCreation(vm, callback);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void JSModuleMock::finishCreation(JSC::VM& vm, JSObject* callback)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
callbackFunctionOrCachedResult.set(vm, this, callback);
|
||||
}
|
||||
|
||||
JSModuleMock::JSModuleMock(JSC::VM& vm, JSC::Structure* structure)
|
||||
: Base(vm, structure)
|
||||
{
|
||||
}
|
||||
|
||||
Structure* JSModuleMock::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
{
|
||||
return Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
|
||||
}
|
||||
|
||||
JSObject* JSModuleMock::executeOnce(JSC::JSGlobalObject* lexicalGlobalObject)
|
||||
{
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
if (hasCalledModuleMock) {
|
||||
return callbackFunctionOrCachedResult.get();
|
||||
}
|
||||
|
||||
hasCalledModuleMock = true;
|
||||
|
||||
if (!callbackFunctionOrCachedResult) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "Cannot call mock without a callback"_s));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSC::JSValue callbackValue = callbackFunctionOrCachedResult.get();
|
||||
if (!callbackValue.isCell() || !callbackValue.isCallable()) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a function"_s));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* callback = callbackValue.getObject();
|
||||
JSC::JSValue result = JSC::call(lexicalGlobalObject, callback, JSC::getCallData(callback), JSC::jsUndefined(), ArgList());
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!result.isObject()) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a function that returns an object"_s));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* object = result.getObject();
|
||||
this->callbackFunctionOrCachedResult.set(vm, this, object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
extern "C" EncodedJSValue JSMock__jsModuleMock(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe)
|
||||
{
|
||||
JSC::VM& vm = lexicalGlobalObject->vm();
|
||||
Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject);
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
if (UNLIKELY(!globalObject)) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "Cannot run mock from a different global context"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
if (callframe->argumentCount() < 1) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a module and function"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::JSString* specifierString = callframe->argument(0).toString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
WTF::String specifier = specifierString->value(globalObject);
|
||||
|
||||
if (specifier.isEmpty()) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a module and function"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
if (specifier.startsWith("./"_s) || specifier.startsWith("../"_s) || specifier == "."_s) {
|
||||
JSC::SourceOrigin sourceOrigin = callframe->callerSourceOrigin(vm);
|
||||
const URL& url = sourceOrigin.url();
|
||||
if (url.protocolIsFile()) {
|
||||
URL joinedURL = URL(url, specifier);
|
||||
specifier = joinedURL.fileSystemPath();
|
||||
specifierString = jsString(vm, specifier);
|
||||
} else {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) cannot mock relative paths in non-files"_s));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
JSC::JSValue callbackValue = callframe->argument(1);
|
||||
if (!callbackValue.isCell() || !callbackValue.isCallable()) {
|
||||
scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "mock(module, fn) requires a function"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::JSObject* callback = callbackValue.getObject();
|
||||
|
||||
JSModuleMock* mock = JSModuleMock::create(vm, globalObject->mockModule.mockModuleStructure.getInitializedOnMainThread(globalObject), callback);
|
||||
|
||||
auto* esm = globalObject->esmRegistryMap();
|
||||
|
||||
auto getJSValue = [&]() -> JSValue {
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
JSValue result = mock->executeOnce(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, JSValue());
|
||||
|
||||
if (result && result.isObject()) {
|
||||
while (JSC::JSPromise* promise = jsDynamicCast<JSC::JSPromise*>(result)) {
|
||||
switch (promise->status(vm)) {
|
||||
case JSC::JSPromise::Status::Rejected: {
|
||||
result = promise->result(vm);
|
||||
scope.throwException(globalObject, result);
|
||||
return {};
|
||||
break;
|
||||
}
|
||||
case JSC::JSPromise::Status::Fulfilled: {
|
||||
result = promise->result(vm);
|
||||
break;
|
||||
}
|
||||
// TODO: blocking wait for promise
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
bool removeFromESM = false;
|
||||
bool removeFromCJS = false;
|
||||
|
||||
if (JSValue entryValue = esm->get(globalObject, specifierString)) {
|
||||
removeFromESM = true;
|
||||
|
||||
if (entryValue.isObject()) {
|
||||
JSObject* entry = entryValue.getObject();
|
||||
if (JSValue moduleValue = entry->getIfPropertyExists(globalObject, Identifier::fromString(vm, String("module"_s)))) {
|
||||
if (auto* mod = jsDynamicCast<JSC::AbstractModuleRecord*>(moduleValue)) {
|
||||
JSC::JSModuleNamespaceObject* moduleNamespaceObject = mod->getModuleNamespace(globalObject);
|
||||
JSValue exportsValue = getJSValue();
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
removeFromESM = false;
|
||||
|
||||
if (exportsValue.isObject()) {
|
||||
// TODO: use fast path for property iteration
|
||||
auto* object = exportsValue.getObject();
|
||||
JSC::PropertyNameArray names(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
|
||||
JSObject::getOwnPropertyNames(object, globalObject, names, DontEnumPropertiesMode::Exclude);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
for (auto& name : names) {
|
||||
// consistent with regular esm handling code
|
||||
auto catchScope = DECLARE_CATCH_SCOPE(vm);
|
||||
JSValue value = object->get(globalObject, name);
|
||||
if (scope.exception()) {
|
||||
scope.clearException();
|
||||
value = jsUndefined();
|
||||
}
|
||||
moduleNamespaceObject->overrideExportValue(globalObject, name, value);
|
||||
}
|
||||
|
||||
} else {
|
||||
// if it's not an object, I guess we just set the default export?
|
||||
moduleNamespaceObject->overrideExportValue(globalObject, vm.propertyNames->defaultKeyword, exportsValue);
|
||||
}
|
||||
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
// TODO: do we need to handle intermediate loading state here?
|
||||
// entry->putDirect(vm, Identifier::fromString(vm, String("evaluated"_s)), jsBoolean(true), 0);
|
||||
// entry->putDirect(vm, Identifier::fromString(vm, String("state"_s)), jsNumber(JSC::JSModuleLoader::Status::Ready), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto entryValue = globalObject->requireMap()->get(globalObject, specifierString)) {
|
||||
removeFromCJS = true;
|
||||
if (auto* moduleObject = jsDynamicCast<Bun::JSCommonJSModule*>(entryValue)) {
|
||||
JSValue exportsValue = getJSValue();
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
moduleObject->putDirect(vm, Bun::builtinNames(vm).exportsPublicName(), exportsValue, 0);
|
||||
moduleObject->hasEvaluated = true;
|
||||
removeFromCJS = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeFromESM) {
|
||||
esm->remove(globalObject, specifierString);
|
||||
}
|
||||
|
||||
if (removeFromCJS) {
|
||||
globalObject->requireMap()->remove(globalObject, specifierString);
|
||||
}
|
||||
|
||||
globalObject->onLoadPlugins.addModuleMock(vm, specifier, mock);
|
||||
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void JSModuleMock::visitChildrenImpl(JSCell* cell, Visitor& visitor)
|
||||
{
|
||||
JSModuleMock* mock = jsCast<JSModuleMock*>(cell);
|
||||
ASSERT_GC_OBJECT_INHERITS(mock, info());
|
||||
Base::visitChildren(mock, visitor);
|
||||
|
||||
visitor.append(mock->callbackFunctionOrCachedResult);
|
||||
}
|
||||
|
||||
DEFINE_VISIT_CHILDREN(JSModuleMock);
|
||||
|
||||
EncodedJSValue BunPlugin::OnLoad::run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path)
|
||||
{
|
||||
Group* groupPtr = this->group(namespaceString ? Bun::toWTFString(*namespaceString) : String());
|
||||
@@ -558,7 +835,13 @@ extern "C" JSC::EncodedJSValue Bun__runOnLoadPlugins(Zig::GlobalObject* globalOb
|
||||
}
|
||||
|
||||
namespace Bun {
|
||||
JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specifier)
|
||||
|
||||
Structure* createModuleMockStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
{
|
||||
return Zig::JSModuleMock::createStructure(vm, globalObject, prototype);
|
||||
}
|
||||
|
||||
JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specifier, bool& wasModuleMock)
|
||||
{
|
||||
auto fallback = [&]() -> JSC::JSValue {
|
||||
return JSValue::decode(Bun__runVirtualModule(globalObject, specifier));
|
||||
@@ -569,16 +852,27 @@ JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specif
|
||||
}
|
||||
auto& virtualModules = *globalObject->onLoadPlugins.virtualModules;
|
||||
WTF::String specifierString = Bun::toWTFString(*specifier);
|
||||
|
||||
if (auto virtualModuleFn = virtualModules.get(specifierString)) {
|
||||
auto& vm = globalObject->vm();
|
||||
JSC::JSObject* function = virtualModuleFn.get();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
JSC::MarkedArgumentBuffer arguments;
|
||||
JSC::CallData callData = JSC::getCallData(function);
|
||||
RELEASE_ASSERT(callData.type != JSC::CallData::Type::None);
|
||||
JSValue result;
|
||||
|
||||
if (Zig::JSModuleMock* moduleMock = jsDynamicCast<Zig::JSModuleMock*>(function)) {
|
||||
wasModuleMock = true;
|
||||
// module mock
|
||||
result = moduleMock->executeOnce(globalObject);
|
||||
} else {
|
||||
// regular function
|
||||
JSC::MarkedArgumentBuffer arguments;
|
||||
JSC::CallData callData = JSC::getCallData(function);
|
||||
RELEASE_ASSERT(callData.type != JSC::CallData::Type::None);
|
||||
|
||||
result = call(globalObject, function, callData, JSC::jsUndefined(), arguments);
|
||||
}
|
||||
|
||||
auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments);
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
|
||||
|
||||
if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) {
|
||||
|
||||
@@ -72,6 +72,8 @@ public:
|
||||
VirtualModuleMap* virtualModules = nullptr;
|
||||
JSC::EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path);
|
||||
|
||||
void addModuleMock(JSC::VM& vm, const String& path, JSC::JSObject* mock);
|
||||
|
||||
~OnLoad()
|
||||
{
|
||||
if (virtualModules) {
|
||||
@@ -97,5 +99,6 @@ class GlobalObject;
|
||||
} // namespace Zig
|
||||
|
||||
namespace Bun {
|
||||
JSC::JSValue runVirtualModule(Zig::GlobalObject*, BunString* specifier);
|
||||
JSC::JSValue runVirtualModule(Zig::GlobalObject*, BunString* specifier, bool& wasModuleMock);
|
||||
JSC::Structure* createModuleMockStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "JavaScriptCore/JSCJSValueInlines.h"
|
||||
#include "helpers.h"
|
||||
#include "simdutf.h"
|
||||
#include "wtf/text/ExternalStringImpl.h"
|
||||
#include "wtf/Seconds.h"
|
||||
#include "GCDefferalContext.h"
|
||||
#include <JavaScriptCore/JSONObject.h>
|
||||
#include <wtf/text/AtomString.h>
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(CallSitePrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
|
||||
@@ -196,11 +196,25 @@ static const HashTableValue RequireFunctionPrototypeValues[] = {
|
||||
{ "cache"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsRequireCacheGetter, jsRequireCacheSetter } },
|
||||
};
|
||||
|
||||
Structure* RequireFunctionPrototype::createStructure(
|
||||
JSC::VM& vm,
|
||||
JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
return Structure::create(vm, globalObject, globalObject->functionPrototype(), TypeInfo(JSFunctionType, StructureFlags), info());
|
||||
}
|
||||
|
||||
Structure* RequireResolveFunctionPrototype::createStructure(
|
||||
JSC::VM& vm,
|
||||
JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
return Structure::create(vm, globalObject, globalObject->functionPrototype(), TypeInfo(JSFunctionType, StructureFlags), info());
|
||||
}
|
||||
|
||||
RequireResolveFunctionPrototype* RequireResolveFunctionPrototype::create(JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
|
||||
auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject, globalObject->functionPrototype());
|
||||
auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject);
|
||||
RequireResolveFunctionPrototype* prototype = new (NotNull, JSC::allocateCell<RequireResolveFunctionPrototype>(vm)) RequireResolveFunctionPrototype(vm, structure);
|
||||
prototype->finishCreation(vm);
|
||||
return prototype;
|
||||
@@ -211,11 +225,11 @@ RequireFunctionPrototype* RequireFunctionPrototype::create(
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
|
||||
auto* structure = RequireFunctionPrototype::createStructure(vm, globalObject, globalObject->functionPrototype());
|
||||
auto* structure = RequireFunctionPrototype::createStructure(vm, globalObject);
|
||||
RequireFunctionPrototype* prototype = new (NotNull, JSC::allocateCell<RequireFunctionPrototype>(vm)) RequireFunctionPrototype(vm, structure);
|
||||
prototype->finishCreation(vm);
|
||||
|
||||
prototype->putDirect(vm, JSC::Identifier::fromString(vm, "resolve"_s), static_cast<Zig::GlobalObject*>(globalObject)->requireResolveFunctionUnbound(), PropertyAttribute::Function | 0);
|
||||
prototype->putDirect(vm, JSC::Identifier::fromString(vm, "resolve"_s), jsCast<Zig::GlobalObject*>(globalObject)->requireResolveFunctionUnbound(), 0);
|
||||
|
||||
return prototype;
|
||||
}
|
||||
@@ -223,7 +237,7 @@ RequireFunctionPrototype* RequireFunctionPrototype::create(
|
||||
void RequireFunctionPrototype::finishCreation(JSC::VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(vm, info()));
|
||||
ASSERT(inherits(info()));
|
||||
|
||||
reifyStaticProperties(vm, info(), RequireFunctionPrototypeValues, *this);
|
||||
JSC::JSFunction* requireDotMainFunction = JSFunction::create(
|
||||
@@ -231,11 +245,11 @@ void RequireFunctionPrototype::finishCreation(JSC::VM& vm)
|
||||
moduleMainCodeGenerator(vm),
|
||||
globalObject()->globalScope());
|
||||
|
||||
this->putDirect(
|
||||
vm,
|
||||
this->putDirectAccessor(
|
||||
globalObject(),
|
||||
JSC::Identifier::fromString(vm, "main"_s),
|
||||
JSC::GetterSetter::create(vm, globalObject(), requireDotMainFunction, JSValue()),
|
||||
PropertyAttribute::Builtin | PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0);
|
||||
JSC::GetterSetter::create(vm, globalObject(), requireDotMainFunction, requireDotMainFunction),
|
||||
PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0);
|
||||
|
||||
auto extensions = constructEmptyObject(globalObject());
|
||||
extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".js"_s), jsBoolean(true), 0);
|
||||
@@ -325,6 +339,16 @@ JSC_DEFINE_CUSTOM_GETTER(getterPaths, (JSC::JSGlobalObject * globalObject, JSC::
|
||||
return JSValue::encode(thisObject->m_paths.get());
|
||||
}
|
||||
|
||||
JSC_DEFINE_CUSTOM_GETTER(getterLoaded, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
|
||||
{
|
||||
JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue));
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
return JSValue::encode(jsBoolean(thisObject->hasEvaluated));
|
||||
}
|
||||
|
||||
JSC_DEFINE_CUSTOM_SETTER(setterPaths,
|
||||
(JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
|
||||
JSC::EncodedJSValue value, JSC::PropertyName propertyName))
|
||||
@@ -372,12 +396,19 @@ JSC_DEFINE_CUSTOM_SETTER(setterParent,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSValue createLoaded(VM& vm, JSObject* object)
|
||||
JSC_DEFINE_CUSTOM_SETTER(setterLoaded,
|
||||
(JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
|
||||
JSC::EncodedJSValue value, JSC::PropertyName propertyName))
|
||||
{
|
||||
JSCommonJSModule* cjs = jsCast<JSCommonJSModule*>(object);
|
||||
return jsBoolean(cjs->hasEvaluated);
|
||||
JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue));
|
||||
if (!thisObject)
|
||||
return false;
|
||||
|
||||
thisObject->hasEvaluated = JSValue::decode(value).toBoolean(globalObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSValue createChildren(VM& vm, JSObject* object)
|
||||
{
|
||||
return constructEmptyArray(object->globalObject(), nullptr, 0);
|
||||
@@ -445,7 +476,7 @@ static const struct HashTableValue JSCommonJSModulePrototypeTableValues[] = {
|
||||
{ "children"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, createChildren } },
|
||||
{ "filename"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterFilename, setterFilename } },
|
||||
{ "id"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterId, setterId } },
|
||||
{ "loaded"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, createLoaded } },
|
||||
{ "loaded"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterLoaded, setterLoaded } },
|
||||
{ "parent"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor | PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, getterParent, setterParent } },
|
||||
{ "path"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPath, setterPath } },
|
||||
{ "paths"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPaths, setterPaths } },
|
||||
@@ -464,6 +495,14 @@ public:
|
||||
return prototype;
|
||||
}
|
||||
|
||||
static JSC::Structure* createStructure(
|
||||
JSC::VM& vm,
|
||||
JSC::JSGlobalObject* globalObject,
|
||||
JSC::JSValue prototype)
|
||||
{
|
||||
return JSC::Structure::create(vm, globalObject, prototype, TypeInfo(JSC::ObjectType, StructureFlags), info());
|
||||
}
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
JSCommonJSModulePrototype(
|
||||
@@ -476,14 +515,15 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCommonJSModulePrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(vm, info()));
|
||||
reifyStaticProperties(vm, JSCommonJSModule::info(), JSCommonJSModulePrototypeTableValues, *this);
|
||||
ASSERT(inherits(info()));
|
||||
reifyStaticProperties(vm, info(), JSCommonJSModulePrototypeTableValues, *this);
|
||||
|
||||
this->putDirectNativeFunction(
|
||||
vm,
|
||||
@@ -494,16 +534,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
const JSC::ClassInfo JSCommonJSModulePrototype::s_info = { "Module"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModulePrototype) };
|
||||
const JSC::ClassInfo JSCommonJSModulePrototype::s_info = { "ModulePrototype"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModulePrototype) };
|
||||
|
||||
void JSCommonJSModule::finishCreation(JSC::VM& vm, JSC::JSString* id, JSValue filename, JSC::JSString* dirname, JSC::JSSourceCode* sourceCode)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(vm, info()));
|
||||
ASSERT(inherits(info()));
|
||||
m_id.set(vm, this, id);
|
||||
m_filename.set(vm, this, filename);
|
||||
m_dirname.set(vm, this, dirname);
|
||||
this->sourceCode.set(vm, this, sourceCode);
|
||||
if (sourceCode)
|
||||
this->sourceCode.set(vm, this, sourceCode);
|
||||
}
|
||||
|
||||
JSC::Structure* JSCommonJSModule::createStructure(
|
||||
@@ -569,7 +610,7 @@ JSCommonJSModule* JSCommonJSModule::create(
|
||||
vm,
|
||||
WebCore::clientData(vm)->builtinNames().exportsPublicName(),
|
||||
exportsObject,
|
||||
exportsObject.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0);
|
||||
0);
|
||||
out->hasEvaluated = hasEvaluated;
|
||||
out->m_parent.set(vm, out, parent);
|
||||
|
||||
@@ -604,14 +645,15 @@ bool JSCommonJSModule::evaluate(
|
||||
RELEASE_AND_RETURN(throwScope, true);
|
||||
}
|
||||
|
||||
void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
|
||||
JSC::Identifier moduleKey,
|
||||
void populateESMExports(
|
||||
JSC::JSGlobalObject* globalObject,
|
||||
JSValue result,
|
||||
Vector<JSC::Identifier, 4>& exportNames,
|
||||
JSC::MarkedArgumentBuffer& exportValues)
|
||||
JSC::MarkedArgumentBuffer& exportValues,
|
||||
bool ignoreESModuleAnnotation)
|
||||
{
|
||||
auto result = this->exportsObject();
|
||||
|
||||
auto& vm = globalObject->vm();
|
||||
Identifier esModuleMarker = builtinNames(vm).__esModulePublicName();
|
||||
|
||||
// Bun's intepretation of the "__esModule" annotation:
|
||||
//
|
||||
@@ -644,7 +686,8 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
|
||||
bool needsToAssignDefault = true;
|
||||
|
||||
if (result.isObject()) {
|
||||
auto* exports = asObject(result);
|
||||
auto* exports = result.getObject();
|
||||
bool hasESModuleMarker = !ignoreESModuleAnnotation && exports->hasProperty(globalObject, esModuleMarker);
|
||||
|
||||
auto* structure = exports->structure();
|
||||
uint32_t size = structure->inlineSize() + structure->outOfLineSize();
|
||||
@@ -653,8 +696,6 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
|
||||
|
||||
auto catchScope = DECLARE_CATCH_SCOPE(vm);
|
||||
|
||||
Identifier esModuleMarker = builtinNames(vm).__esModulePublicName();
|
||||
bool hasESModuleMarker = !this->ignoreESModuleAnnotation && exports->hasProperty(globalObject, esModuleMarker);
|
||||
if (catchScope.exception()) {
|
||||
catchScope.clearException();
|
||||
}
|
||||
@@ -764,6 +805,18 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
|
||||
}
|
||||
}
|
||||
|
||||
void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
|
||||
JSC::Identifier moduleKey,
|
||||
Vector<JSC::Identifier, 4>& exportNames,
|
||||
JSC::MarkedArgumentBuffer& exportValues)
|
||||
{
|
||||
auto result = this->exportsObject();
|
||||
|
||||
auto& vm = globalObject->vm();
|
||||
Identifier esModuleMarker = builtinNames(vm).__esModulePublicName();
|
||||
populateESMExports(globalObject, result, exportNames, exportValues, this->ignoreESModuleAnnotation);
|
||||
}
|
||||
|
||||
JSValue JSCommonJSModule::exportsObject()
|
||||
{
|
||||
return this->get(globalObject(), JSC::PropertyName(clientData(vm())->builtinNames().exportsPublicName()));
|
||||
@@ -774,18 +827,6 @@ JSValue JSCommonJSModule::id()
|
||||
return m_id.get();
|
||||
}
|
||||
|
||||
template<typename, SubspaceAccess mode> JSC::GCClient::IsoSubspace* JSCommonJSModule::subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
|
||||
return nullptr;
|
||||
return WebCore::subspaceForImpl<JSCommonJSModule, WebCore::UseCustomHeapCellType::No>(
|
||||
vm,
|
||||
[](auto& spaces) { return spaces.m_clientSubspaceForCommonJSModuleRecord.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); },
|
||||
[](auto& spaces) { return spaces.m_subspaceForCommonJSModuleRecord.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_subspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); });
|
||||
}
|
||||
|
||||
Structure* createCommonJSModuleStructure(
|
||||
Zig::GlobalObject* globalObject)
|
||||
{
|
||||
@@ -849,9 +890,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo
|
||||
void RequireResolveFunctionPrototype::finishCreation(JSC::VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(vm, info()));
|
||||
ASSERT(inherits(info()));
|
||||
|
||||
reifyStaticProperties(vm, RequireResolveFunctionPrototype::info(), RequireResolveFunctionPrototypeValues, *this);
|
||||
reifyStaticProperties(vm, info(), RequireResolveFunctionPrototypeValues, *this);
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
}
|
||||
|
||||
@@ -995,8 +1036,6 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l
|
||||
globalObject->CommonJSModuleObjectStructure(),
|
||||
filename, filename, dirname, nullptr);
|
||||
|
||||
auto& builtinNames = WebCore::builtinNames(vm);
|
||||
|
||||
JSFunction* requireFunction = JSC::JSBoundFunction::create(vm,
|
||||
globalObject,
|
||||
globalObject->requireFunctionUnbound(),
|
||||
@@ -1009,7 +1048,7 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l
|
||||
moduleObject,
|
||||
ArgList(), 1, jsString(vm, String("resolve"_s)));
|
||||
|
||||
requireFunction->putDirect(vm, builtinNames.resolvePublicName(), resolveFunction, PropertyAttribute::Function | 0);
|
||||
requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0);
|
||||
|
||||
return requireFunction;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,13 @@ namespace Bun {
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunctionCreateCommonJSModule);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunctionLoadModule);
|
||||
|
||||
void populateESMExports(
|
||||
JSC::JSGlobalObject* globalObject,
|
||||
JSC::JSValue result,
|
||||
WTF::Vector<JSC::Identifier, 4>& exportNames,
|
||||
JSC::MarkedArgumentBuffer& exportValues,
|
||||
bool ignoreESModuleAnnotation);
|
||||
|
||||
class JSCommonJSModule final : public JSC::JSDestructibleObject {
|
||||
public:
|
||||
using Base = JSC::JSDestructibleObject;
|
||||
@@ -72,11 +79,21 @@ public:
|
||||
JSValue exportsObject();
|
||||
JSValue id();
|
||||
|
||||
DECLARE_INFO;
|
||||
DECLARE_VISIT_CHILDREN;
|
||||
|
||||
DECLARE_INFO;
|
||||
template<typename, SubspaceAccess mode>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm);
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
|
||||
return nullptr;
|
||||
return WebCore::subspaceForImpl<JSCommonJSModule, WebCore::UseCustomHeapCellType::No>(
|
||||
vm,
|
||||
[](auto& spaces) { return spaces.m_clientSubspaceForCommonJSModuleRecord.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); },
|
||||
[](auto& spaces) { return spaces.m_subspaceForCommonJSModuleRecord.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_subspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); });
|
||||
}
|
||||
|
||||
bool hasEvaluated = false;
|
||||
|
||||
@@ -110,7 +127,9 @@ inline std::optional<JSC::SourceCode> createCommonJSModule(
|
||||
class RequireResolveFunctionPrototype final : public JSC::JSNonFinalObject {
|
||||
public:
|
||||
using Base = JSC::JSNonFinalObject;
|
||||
|
||||
static RequireResolveFunctionPrototype* create(JSC::JSGlobalObject* globalObject);
|
||||
static Structure* createStructure(VM& vm, JSC::JSGlobalObject* globalObject);
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
@@ -124,6 +143,7 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(RequireResolveFunctionPrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
@@ -133,7 +153,11 @@ public:
|
||||
class RequireFunctionPrototype final : public JSC::JSNonFinalObject {
|
||||
public:
|
||||
using Base = JSC::JSNonFinalObject;
|
||||
|
||||
static RequireFunctionPrototype* create(JSC::JSGlobalObject* globalObject);
|
||||
static Structure* createStructure(VM& vm, JSC::JSGlobalObject* globalObject);
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
RequireFunctionPrototype(
|
||||
JSC::VM& vm,
|
||||
@@ -145,12 +169,11 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(RequireFunctionPrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
DECLARE_INFO;
|
||||
|
||||
void finishCreation(JSC::VM& vm);
|
||||
void finishCreation(JSC::VM&);
|
||||
};
|
||||
|
||||
} // namespace Bun
|
||||
|
||||
@@ -266,7 +266,7 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb
|
||||
if (LIKELY(global)) {
|
||||
auto overrideHandler = global->m_nodeModuleOverriddenResolveFilename.get();
|
||||
if (UNLIKELY(overrideHandler)) {
|
||||
ASSERT(overrideHandler.isCallable(globalObject));
|
||||
ASSERT(overrideHandler->isCallable());
|
||||
MarkedArgumentBuffer args;
|
||||
args.append(moduleName);
|
||||
args.append(from);
|
||||
@@ -434,6 +434,7 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ImportMetaObjectPrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
|
||||
@@ -447,11 +448,13 @@ public:
|
||||
reifyStaticProperties(vm, ImportMetaObject::info(), ImportMetaObjectPrototypeValues, *this);
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
|
||||
this->putDirect(
|
||||
vm,
|
||||
auto mainGetter = JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject);
|
||||
|
||||
this->putDirectAccessor(
|
||||
this->globalObject(),
|
||||
builtinNames.mainPublicName(),
|
||||
GetterSetter::create(vm, globalObject, JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject), nullptr),
|
||||
JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin | 0);
|
||||
GetterSetter::create(vm, globalObject, mainGetter, mainGetter),
|
||||
JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | 0);
|
||||
}
|
||||
|
||||
ImportMetaObjectPrototype(JSC::VM& vm, JSC::Structure* structure)
|
||||
@@ -463,7 +466,7 @@ public:
|
||||
const ClassInfo ImportMetaObjectPrototype::s_info = {
|
||||
"ImportMeta"_s,
|
||||
|
||||
Base::info(), nullptr, nullptr, CREATE_METHOD_TABLE(ImportMetaObjectPrototype)
|
||||
&Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImportMetaObjectPrototype)
|
||||
};
|
||||
|
||||
JSC::Structure* ImportMetaObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
|
||||
|
||||
@@ -120,16 +120,23 @@ DEFINE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE, InternalModuleRegistry);
|
||||
InternalModuleRegistry* InternalModuleRegistry::create(VM& vm, Structure* structure)
|
||||
{
|
||||
InternalModuleRegistry* registry = new (NotNull, allocateCell<InternalModuleRegistry>(vm)) InternalModuleRegistry(vm, structure);
|
||||
for (uint8_t i = 0; i < BUN_INTERNAL_MODULE_COUNT; i++) {
|
||||
registry->internalField(static_cast<Field>(i))
|
||||
.set(vm, registry, jsUndefined());
|
||||
}
|
||||
registry->finishCreation(vm);
|
||||
return registry;
|
||||
}
|
||||
|
||||
void InternalModuleRegistry::finishCreation(VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
ASSERT(inherits(info()));
|
||||
|
||||
for (uint8_t i = 0; i < BUN_INTERNAL_MODULE_COUNT; i++) {
|
||||
this->internalField(static_cast<Field>(i)).set(vm, this, jsUndefined());
|
||||
}
|
||||
}
|
||||
|
||||
Structure* InternalModuleRegistry::createStructure(VM& vm, JSGlobalObject* globalObject)
|
||||
{
|
||||
return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 48);
|
||||
return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 0);
|
||||
}
|
||||
|
||||
JSValue InternalModuleRegistry::requireId(JSGlobalObject* globalObject, VM& vm, Field id)
|
||||
@@ -152,7 +159,7 @@ JSC_DEFINE_HOST_FUNCTION(InternalModuleRegistry::jsCreateInternalModuleById, (JS
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
auto id = callframe->argument(0).toUInt32(lexicalGlobalObject);
|
||||
|
||||
auto registry = static_cast<Zig::GlobalObject*>(lexicalGlobalObject)->internalModuleRegistry();
|
||||
auto registry = jsCast<Zig::GlobalObject*>(lexicalGlobalObject)->internalModuleRegistry();
|
||||
auto mod = registry->createInternalModuleById(lexicalGlobalObject, vm, static_cast<Field>(id));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
registry->internalField(static_cast<Field>(id)).set(vm, registry, mod);
|
||||
|
||||
@@ -16,19 +16,21 @@ using namespace JSC;
|
||||
// - some are written in JS (src/js, there is a readme file that explain those files more.
|
||||
// - others are native code (src/bun.js/modules), see _NativeModule.h in there.
|
||||
class InternalModuleRegistry : public JSInternalFieldObjectImpl<BUN_INTERNAL_MODULE_COUNT> {
|
||||
protected:
|
||||
JS_EXPORT_PRIVATE InternalModuleRegistry(VM&, Structure*);
|
||||
DECLARE_DEFAULT_FINISH_CREATION;
|
||||
DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE);
|
||||
|
||||
public:
|
||||
using Base = JSInternalFieldObjectImpl<BUN_INTERNAL_MODULE_COUNT>;
|
||||
|
||||
DECLARE_EXPORT_INFO;
|
||||
|
||||
static size_t allocationSize(Checked<size_t> inlineCapacity)
|
||||
{
|
||||
ASSERT_UNUSED(inlineCapacity, inlineCapacity == 0U);
|
||||
return sizeof(InternalModuleRegistry);
|
||||
}
|
||||
|
||||
enum Field : uint8_t {
|
||||
#include "../../../src/js/out/InternalModuleRegistry+enum.h"
|
||||
};
|
||||
|
||||
const WriteBarrier<Unknown>& internalField(Field field) const { return Base::internalField(static_cast<uint32_t>(field)); }
|
||||
WriteBarrier<Unknown>& internalField(Field field) { return Base::internalField(static_cast<uint32_t>(field)); }
|
||||
|
||||
@@ -52,8 +54,11 @@ public:
|
||||
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsCreateInternalModuleById);
|
||||
|
||||
protected:
|
||||
private:
|
||||
JS_EXPORT_PRIVATE InternalModuleRegistry(VM&, Structure*);
|
||||
DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE);
|
||||
JSValue createInternalModuleById(JSGlobalObject* globalObject, VM& vm, Field id);
|
||||
void finishCreation(VM&);
|
||||
};
|
||||
|
||||
} // namespace Bun
|
||||
|
||||
@@ -742,10 +742,16 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS
|
||||
byteLength += typedArray->length();
|
||||
}
|
||||
|
||||
if (callFrame->argumentCount() > 1) {
|
||||
auto byteLengthValue = callFrame->uncheckedArgument(1);
|
||||
byteLength = std::min(byteLength, byteLengthValue.toTypedArrayIndex(lexicalGlobalObject, "totalLength must be a valid number"_s));
|
||||
JSValue totalLengthValue = callFrame->argument(1);
|
||||
if (!totalLengthValue.isUndefined()) {
|
||||
if (UNLIKELY(!totalLengthValue.isNumber())) {
|
||||
throwTypeError(lexicalGlobalObject, throwScope, "totalLength must be a valid number"_s);
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
auto totalLength = totalLengthValue.toTypedArrayIndex(lexicalGlobalObject, "totalLength must be a valid number"_s);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
byteLength = totalLength;
|
||||
}
|
||||
|
||||
if (byteLength == 0) {
|
||||
@@ -819,6 +825,7 @@ public:
|
||||
template<typename CellType, JSC::SubspaceAccess>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBufferPrototype, Base);
|
||||
return &vm.plainObjectSpace();
|
||||
}
|
||||
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
|
||||
@@ -1825,8 +1832,8 @@ static const HashTableValue JSBufferPrototypeTableValues[]
|
||||
{ "lastIndexOf"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_lastIndexOf, 3 } },
|
||||
{ "latin1Slice"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeLatin1SliceCodeGenerator, 2 } },
|
||||
{ "latin1Write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeLatin1WriteCodeGenerator, 1 } },
|
||||
{ "offset"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeOffsetCodeGenerator, 0 } },
|
||||
{ "parent"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeParentCodeGenerator, 0 } },
|
||||
{ "offset"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, jsBufferPrototypeOffsetCodeGenerator, 0 } },
|
||||
{ "parent"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, jsBufferPrototypeParentCodeGenerator, 0 } },
|
||||
{ "readBigInt64"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64LECodeGenerator, 1 } },
|
||||
{ "readBigInt64BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64BECodeGenerator, 1 } },
|
||||
{ "readBigInt64LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64LECodeGenerator, 1 } },
|
||||
@@ -1934,8 +1941,7 @@ const ClassInfo JSBufferPrototype::s_info = {
|
||||
// We must use the same naming convention to match Node
|
||||
// Some packages (like MongoDB's official Node.js client) rely on this behavior.
|
||||
"Uint8Array"_s,
|
||||
|
||||
nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferPrototype)
|
||||
&Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferPrototype)
|
||||
};
|
||||
|
||||
static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAlloc(jsBufferConstructorAllocWithoutTypeChecks,
|
||||
@@ -1968,7 +1974,7 @@ static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAllocUnsaf
|
||||
*/
|
||||
#include "JSBuffer.lut.h"
|
||||
|
||||
const ClassInfo JSBufferConstructor::s_info = { "Buffer"_s, nullptr, &jsBufferConstructorTable, nullptr, CREATE_METHOD_TABLE(JSBufferConstructor) };
|
||||
const ClassInfo JSBufferConstructor::s_info = { "Buffer"_s, &Base::s_info, &jsBufferConstructorTable, nullptr, CREATE_METHOD_TABLE(JSBufferConstructor) };
|
||||
|
||||
void JSBufferConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, JSC::JSObject* prototype)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user