diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000000000..39b4a6eacaa2a8
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,62 @@
+### What does this PR do?
+
+
+
+
+
+- [ ] Documentation or TypeScript types (it's okay to leave the rest blank in this case)
+- [ ] Code changes
+
+### How did you verify your code works?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/workflows/bun-linux-aarch64.yml b/.github/workflows/bun-linux-aarch64.yml
index aaeda6c4e16215..d29fa0b7bcfedd 100644
--- a/.github/workflows/bun-linux-aarch64.yml
+++ b/.github/workflows/bun-linux-aarch64.yml
@@ -36,7 +36,7 @@ jobs:
arch: aarch64
build_arch: arm64
runner: linux-arm64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-linux-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-linux-arm64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-arm64-lto"
build_machine_arch: aarch64
diff --git a/.github/workflows/bun-linux-build.yml b/.github/workflows/bun-linux-build.yml
index 9ad92e6b19e6cd..f4b288d8efc0c4 100644
--- a/.github/workflows/bun-linux-build.yml
+++ b/.github/workflows/bun-linux-build.yml
@@ -46,7 +46,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-linux-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
- cpu: nehalem
@@ -54,7 +54,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-linux-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
diff --git a/.github/workflows/bun-mac-aarch64.yml b/.github/workflows/bun-mac-aarch64.yml
index 7fa73017c0f866..52258374e4cdc1 100644
--- a/.github/workflows/bun-mac-aarch64.yml
+++ b/.github/workflows/bun-mac-aarch64.yml
@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: native
@@ -152,7 +152,7 @@ jobs:
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
artifact: bun-obj-darwin-aarch64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
dependencies: true
compile_obj: true
@@ -257,7 +257,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -265,14 +265,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/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-july23/bun-webkit-macos-arm64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml
index bd75ec20212e42..049a966918a35d 100644
--- a/.github/workflows/bun-mac-x64-baseline.yml
+++ b/.github/workflows/bun-mac-x64-baseline.yml
@@ -117,7 +117,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -258,7 +258,7 @@ jobs:
package: bun-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64-baseline
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -266,14 +266,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/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-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml
index 371486effedf8d..4289c578f31cfa 100644
--- a/.github/workflows/bun-mac-x64.yml
+++ b/.github/workflows/bun-mac-x64.yml
@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: haswell
@@ -126,7 +126,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: haswell
@@ -144,7 +144,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-arm64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -260,7 +260,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-11
# artifact: bun-obj-darwin-x64-baseline
- # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
@@ -268,14 +268,14 @@ jobs:
package: bun-darwin-x64
runner: macos-11
artifact: bun-obj-darwin-x64
- webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-july23/bun-webkit-macos-amd64-lto.tar.gz"
+ webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/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-july23/bun-webkit-macos-arm64-lto.tar.gz"
+ # webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-aug3-2/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
diff --git a/.gitignore b/.gitignore
index eb970e815ce903..f5823c7885d350 100644
--- a/.gitignore
+++ b/.gitignore
@@ -122,6 +122,9 @@ cold-jsc-start.d
/test.ts
-src/js/out/modules_dev
+src/js/out/modules*
+src/js/out/functions*
+src/js/out/tmp
+src/js/out/DebugPath.h
make-dev-stats.csv
diff --git a/Dockerfile b/Dockerfile
index 304bf680d961cc..9042ea80211c23 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ ARG ARCH=x86_64
ARG BUILD_MACHINE_ARCH=x86_64
ARG TRIPLET=${ARCH}-linux-gnu
ARG BUILDARCH=amd64
-ARG WEBKIT_TAG=2023-july23
+ARG WEBKIT_TAG=2023-aug3-2
ARG ZIG_TAG=jul1
ARG ZIG_VERSION="0.11.0-dev.4006+bf827d0b5"
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
diff --git a/Makefile b/Makefile
index 3de9de27695d08..070d03ec46e5c8 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,6 @@ BUN_AUTO_UPDATER_REPO = Jarred-Sumner/bun-releases-for-updater
CMAKE_CXX_COMPILER_LAUNCHER_FLAG :=
-
-
# 'make' command will trigger the help target
.DEFAULT_GOAL := help
@@ -20,7 +18,7 @@ CPU_TARGET ?= native
MARCH_NATIVE = -mtune=$(CPU_TARGET)
NATIVE_OR_OLD_MARCH =
-MMD_IF_LOCAL =
+MMD_IF_LOCAL =
DEFAULT_MIN_MACOS_VERSION=
ARCH_NAME :=
DOCKER_BUILDARCH =
@@ -556,22 +554,13 @@ tinycc:
PYTHON=$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null)
-.PHONY: builtins
-builtins:
- NODE_ENV=production bun src/js/builtins/codegen/index.ts --minify
-
.PHONY: esm
-esm:
- NODE_ENV=production bun src/js/build-esm.ts
+js:
+ NODE_ENV=production bun src/js/_codegen/index.ts
esm-debug:
BUN_DEBUG_QUIET_LOGS=1 NODE_ENV=production bun-debug src/js/build-esm.ts
-.PHONY: generate-builtins
-generate-builtins: builtins
-
-
-
BUN_TYPES_REPO_PATH ?= $(realpath packages/bun-types)
ifeq ($(DEBUG),true)
@@ -714,44 +703,44 @@ dev-build-obj-wasm:
.PHONY: dev-wasm
dev-wasm: dev-build-obj-wasm
- emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
- -g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
+ emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
+ -g2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
- packages/debug-bun-freestanding-wasm32/bun-wasm.o $(OPTIMIZATION_LEVEL) --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
+ packages/debug-bun-freestanding-wasm32/bun-wasm.o --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
-o packages/debug-bun-freestanding-wasm32/bun-wasm.wasm
- cp packages/debug-bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
+ cp packages/debug-bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
.PHONY: build-obj-wasm
build-obj-wasm:
$(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding
- emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
- -g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
+ emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
+ -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
packages/bun-freestanding-wasm32/bun-wasm.o $(OPTIMIZATION_LEVEL) --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
-o packages/bun-freestanding-wasm32/bun-wasm.wasm
- cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
+ cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
.PHONY: build-obj-wasm-small
build-obj-wasm-small:
- $(ZIG) build bun-wasm -Doptimize=ReleaseSmall -Dtarget=wasm32-freestanding
- emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
- -g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
+ $(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding
+ emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \
+ -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
$(BUN_DEPS_DIR)/libmimalloc.a.wasm \
packages/bun-freestanding-wasm32/bun-wasm.o -Oz --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
-o packages/bun-freestanding-wasm32/bun-wasm.wasm
- cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
+ cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
.PHONY: wasm
-wasm: api build-obj-wasm-small
+wasm: api mimalloc-wasm build-obj-wasm-small
@rm -rf packages/bun-wasm/*.{d.ts,js,wasm,cjs,mjs,tsbuildinfo}
@cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm
@cp src/api/schema.d.ts packages/bun-wasm/schema.d.ts
@cp src/api/schema.js packages/bun-wasm/schema.js
@cd packages/bun-wasm && $(NPM_CLIENT) run tsc -- -p .
- @$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=esm --minify 2> /dev/null
+ @bun build --sourcemap=external --external=fs --outdir=packages/bun-wasm --target=browser --minify ./packages/bun-wasm/index.ts
@mv packages/bun-wasm/index.js packages/bun-wasm/index.mjs
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.mjs.map
- @$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
+ @$(ESBUILD) --sourcemap=external --external:fs --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
@mv packages/bun-wasm/index.js packages/bun-wasm/index.cjs
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.cjs.map
@rm -rf packages/bun-wasm/*.tsbuildinfo
@@ -1118,7 +1107,7 @@ dev-obj-linux:
$(ZIG) build obj -Dtarget=x86_64-linux-gnu -Dcpu="$(CPU_TARGET)"
.PHONY: dev
-dev: mkdir-dev esm dev-obj link ## compile zig changes + link bun
+dev: mkdir-dev dev-obj link ## compile zig changes + link bun
mkdir-dev:
mkdir -p $(DEBUG_PACKAGE_DIR)
@@ -1203,6 +1192,7 @@ jsc-build-mac-compile:
-DPORT="JSCOnly" \
-DENABLE_STATIC_JSC=ON \
-DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON \
+ -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_THIN_ARCHIVES=OFF \
-DBUN_FAST_TLS=ON \
@@ -1225,6 +1215,7 @@ jsc-build-mac-compile-lto:
-DPORT="JSCOnly" \
-DENABLE_STATIC_JSC=ON \
-DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON \
+ -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_THIN_ARCHIVES=OFF \
-DBUN_FAST_TLS=ON \
@@ -1252,6 +1243,7 @@ jsc-build-mac-compile-debug:
-DUSE_THIN_ARCHIVES=OFF \
-DENABLE_FTL_JIT=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
+ -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
-G Ninja \
$(CMAKE_FLAGS_WITHOUT_RELEASE) \
-DPTHREAD_JIT_PERMISSIONS_API=1 \
@@ -1275,6 +1267,7 @@ jsc-build-linux-compile-config:
-DENABLE_FTL_JIT=ON \
-DENABLE_REMOTE_INSPECTOR=ON \
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
+ -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
-USE_VISIBILITY_ATTRIBUTE=1 \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-G Ninja \
@@ -1386,7 +1379,8 @@ mimalloc:
mimalloc-wasm:
- cd $(BUN_DEPS_DIR)/mimalloc; emcmake cmake -DMI_BUILD_SHARED=OFF -DMI_BUILD_STATIC=ON -DMI_BUILD_TESTS=OFF -DMI_BUILD_OBJECT=ON ${MIMALLOC_OVERRIDE_FLAG} -DMI_USE_CXX=ON .; emmake make;
+ rm -rf $(BUN_DEPS_DIR)/mimalloc/CMakeCache* $(BUN_DEPS_DIR)/mimalloc/CMakeFiles
+ cd $(BUN_DEPS_DIR)/mimalloc; emcmake cmake -DMI_BUILD_SHARED=OFF -DMI_BUILD_STATIC=ON -DMI_BUILD_TESTS=OFF -GNinja -DMI_BUILD_OBJECT=ON ${MIMALLOC_OVERRIDE_FLAG} -DMI_USE_CXX=OFF .; emmake cmake --build .;
cp $(BUN_DEPS_DIR)/mimalloc/$(MIMALLOC_INPUT_PATH) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE).wasm
# alias for link, incase anyone still types that
@@ -1914,11 +1908,11 @@ bun: vendor identifier-cache build-obj bun-link-lld-release bun-codesign-release
.PHONY: regenerate-bindings
regenerate-bindings: ## compile src/js/builtins + all c++ code, does not link
- @make clean-bindings builtins
+ @make clean-bindings js
@make bindings -j$(CPU_COUNT)
.PHONY: setup
-setup: vendor-dev identifier-cache clean-bindings
+setup: vendor-dev identifier-cache clean-bindings js
make jsc-check
make bindings -j$(CPU_COUNT)
@echo ""
diff --git a/bench/hot-module-reloading/css-stress-test/tsconfig.json b/bench/hot-module-reloading/css-stress-test/tsconfig.json
index 289c8f710e3991..718c2366c42bde 100644
--- a/bench/hot-module-reloading/css-stress-test/tsconfig.json
+++ b/bench/hot-module-reloading/css-stress-test/tsconfig.json
@@ -5,4 +5,4 @@
"jsx": "react-jsx",
"paths": {}
}
-}
\ No newline at end of file
+}
diff --git a/bench/snippets/private.mjs b/bench/snippets/private.mjs
new file mode 100644
index 00000000000000..ca75c6e07aabe4
--- /dev/null
+++ b/bench/snippets/private.mjs
@@ -0,0 +1,80 @@
+import { bench, run } from "../node_modules/mitata/src/cli.mjs";
+// This is a benchmark of the performance impact of using private properties.
+
+bench("Polyfillprivate", () => {
+ "use strict";
+ var __classPrivateFieldGet =
+ (this && this.__classPrivateFieldGet) ||
+ function (receiver, state, kind, f) {
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
+ throw new TypeError("Cannot read private member from an object whose class did not declare it");
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
+ };
+ var __classPrivateFieldSet =
+ (this && this.__classPrivateFieldSet) ||
+ function (receiver, state, value, kind, f) {
+ if (kind === "m") throw new TypeError("Private method is not writable");
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
+ throw new TypeError("Cannot write private member to an object whose class did not declare it");
+ return kind === "a" ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value;
+ };
+ var _Foo_state, _Foo_inc;
+ class Foo {
+ constructor() {
+ _Foo_state.set(this, 1);
+ _Foo_inc.set(this, 13);
+ }
+ run() {
+ let n = 1000000;
+ while (n-- > 0) {
+ __classPrivateFieldSet(
+ this,
+ _Foo_state,
+ __classPrivateFieldGet(this, _Foo_state, "f") + __classPrivateFieldGet(this, _Foo_inc, "f"),
+ "f",
+ );
+ }
+ return n;
+ }
+ }
+ (_Foo_state = new WeakMap()), (_Foo_inc = new WeakMap());
+ new Foo().run();
+});
+
+bench("NativePrivates", () => {
+ class Foo {
+ #state = 1;
+ #inc = 13;
+
+ run() {
+ let n = 1000000;
+ while (n-- > 0) {
+ this.#state += this.#inc;
+ }
+ return n;
+ }
+ }
+
+ new Foo().run();
+});
+
+bench("ConventionalPrivates", () => {
+ class Foo {
+ _state = 1;
+ _inc = 13;
+
+ run() {
+ let n = 1000000;
+ while (n-- > 0) {
+ this._state += this._inc;
+ }
+ return n;
+ }
+ }
+
+ new Foo().run();
+});
+
+await run();
diff --git a/bench/snippets/request-response-clone.mjs b/bench/snippets/request-response-clone.mjs
new file mode 100644
index 00000000000000..05a98065602ab7
--- /dev/null
+++ b/bench/snippets/request-response-clone.mjs
@@ -0,0 +1,15 @@
+// This mostly exists to check for a memory leak in response.clone()
+import { bench, run } from "./runner.mjs";
+
+const req = new Request("http://localhost:3000/");
+const resp = await fetch("http://example.com");
+
+bench("req.clone().url", () => {
+ return req.clone().url;
+});
+
+bench("resp.clone().url", () => {
+ return resp.clone().url;
+});
+
+await run();
diff --git a/bench/snippets/resposne-constructor.mjs b/bench/snippets/resposne-constructor.mjs
new file mode 100644
index 00000000000000..a15892804c463b
--- /dev/null
+++ b/bench/snippets/resposne-constructor.mjs
@@ -0,0 +1 @@
+for (let i = 0; i < 9999999; i++) new Request("http://aaaaaaaaaaaaaaaaaaaaa");
diff --git a/bench/snippets/webcrypto.mjs b/bench/snippets/webcrypto.mjs
new file mode 100644
index 00000000000000..2d1256cf8fd28a
--- /dev/null
+++ b/bench/snippets/webcrypto.mjs
@@ -0,0 +1,20 @@
+import { group } from "mitata";
+import { bench, run } from "./runner.mjs";
+
+const sizes = [
+ ["small (63 bytes)", 63],
+ ["medium (4096 bytes)", 4096],
+ ["large (64 MB)", 64 * 1024 * 1024],
+];
+for (let [name, size] of sizes) {
+ group(name, () => {
+ var buf = new Uint8Array(size);
+ for (let algorithm of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) {
+ bench(algorithm, async () => {
+ await crypto.subtle.digest(algorithm, buf);
+ });
+ }
+ });
+}
+
+await run();
diff --git a/bench/websocket-server/README.md b/bench/websocket-server/README.md
index 2578c8d51ba5b6..c583e54bab5aeb 100644
--- a/bench/websocket-server/README.md
+++ b/bench/websocket-server/README.md
@@ -2,7 +2,7 @@
This benchmarks a websocket server intended as a simple but very active chat room.
-First, start the server. By default, it will wait for 16 clients which the client script will handle.
+First, start the server. By default, it will wait for 32 clients which the client script will handle.
Run in Bun (`Bun.serve`):
@@ -19,10 +19,10 @@ node ./chat-server.node.mjs
Run in Deno (`Deno.serve`):
```bash
-deno run -A --unstable ./chat-server.deno.mjs
+deno run -A ./chat-server.deno.mjs
```
-Then, run the client script. By default, it will connect 16 clients. This client script can run in Bun, Node, or Deno
+Then, run the client script. By default, it will connect 32 clients. This client script can run in Bun, Node, or Deno
```bash
node ./chat-client.mjs
diff --git a/build.zig b/build.zig
index 569a6bdd2a0bdb..4a20d8481d02d5 100644
--- a/build.zig
+++ b/build.zig
@@ -182,7 +182,7 @@ pub fn build(b: *Build) !void {
is_debug_build = optimize == OptimizeMode.Debug;
const bun_executable_name = if (optimize == std.builtin.OptimizeMode.Debug) "bun-debug" else "bun";
const root_src = if (target.getOsTag() == std.Target.Os.Tag.freestanding)
- "src/main_wasm.zig"
+ "root_wasm.zig"
else
"root.zig";
@@ -322,7 +322,7 @@ pub fn build(b: *Build) !void {
const wasm = b.step("bun-wasm", "Build WASM");
var wasm_step = b.addStaticLibrary(.{
.name = "bun-wasm",
- .root_source_file = FileSource.relative("src/main_wasm.zig"),
+ .root_source_file = FileSource.relative("root_wasm.zig"),
.target = target,
.optimize = optimize,
});
@@ -332,6 +332,8 @@ pub fn build(b: *Build) !void {
// wasm_step.link_emit_relocs = true;
// wasm_step.single_threaded = true;
try configureObjectStep(b, wasm_step, @TypeOf(target), target, obj.main_pkg_path.?);
+ var build_opts = default_build_options;
+ wasm_step.addOptions("build_options", build_opts.step(b));
}
{
diff --git a/bun.lockb b/bun.lockb
index ac7b5dac53b062..76f7802823d59a 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/completions/bun.zsh b/completions/bun.zsh
index a8f66b4fa30613..59df1db47b045f 100644
--- a/completions/bun.zsh
+++ b/completions/bun.zsh
@@ -49,7 +49,7 @@ _bun() {
'--production[Don'"'"'t install devDependencies]' \
'--frozen-lockfile[Disallow changes to lockfile]' \
'--optional[Add dependency to optionalDependencies]' \
- '--development[Add dependency to devDependencies]' \
+ '--dev[Add dependency to devDependencies]' \
'-d[Add dependency to devDependencies]' \
'-p[Don'"'"'t install devDependencies]' \
'--no-save[]' \
@@ -91,7 +91,7 @@ _bun() {
'--production[Don'"'"'t install devDependencies]' \
'--frozen-lockfile[Disallow changes to lockfile]' \
'--optional[Add dependency to optionalDependencies]' \
- '--development[Add dependency to devDependencies]' \
+ '--dev[Add dependency to devDependencies]' \
'-d[Add dependency to devDependencies]' \
'-p[Don'"'"'t install devDependencies]' \
'--no-save[]' \
@@ -127,7 +127,7 @@ _bun() {
'--production[Don'"'"'t install devDependencies]' \
'--frozen-lockfile[Disallow changes to lockfile]' \
'--optional[Add dependency to optionalDependencies]' \
- '--development[Add dependency to devDependencies]' \
+ '--dev[Add dependency to devDependencies]' \
'-d[Add dependency to devDependencies]' \
'-p[Don'"'"'t install devDependencies]' \
'--no-save[]' \
diff --git a/docs/api/binary-data.md b/docs/api/binary-data.md
index 71b02338ff9962..77a54a7620a833 100644
--- a/docs/api/binary-data.md
+++ b/docs/api/binary-data.md
@@ -927,7 +927,7 @@ Buffer.from(Bun.readableStreamToArrayBuffer(stream));
new Response(stream).text();
// with Bun function
-await Bun.readableStreamToString(stream);
+await Bun.readableStreamToText(stream);
```
#### To `number[]`
diff --git a/docs/api/file-io.md b/docs/api/file-io.md
index be9cf0991caecd..e141c8b1718910 100644
--- a/docs/api/file-io.md
+++ b/docs/api/file-io.md
@@ -1,8 +1,8 @@
{% callout %}
-
+
-**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
+**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
{% /callout %}
diff --git a/docs/api/globals.md b/docs/api/globals.md
index 370dd3800927d9..fe7cd60c64ae21 100644
--- a/docs/api/globals.md
+++ b/docs/api/globals.md
@@ -34,7 +34,7 @@ Bun implements the following globals.
- [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer)
- Node.js
-- See [Node.js > `Buffer`](/docs/runtime/nodejs-apis#node_buffer)
+- See [Node.js > `Buffer`](/docs/runtime/nodejs-apis#node-buffer)
---
@@ -172,7 +172,7 @@ Bun implements the following globals.
- [`global`](https://nodejs.org/api/globals.html#global)
- Node.js
-- See [Node.js > `global`](/docs/runtime/nodejs-apis#node_global).
+- See [Node.js > `global`](/docs/runtime/nodejs-apis#global).
---
@@ -220,7 +220,7 @@ Bun implements the following globals.
- [`process`](https://nodejs.org/api/process.html)
- Node.js
-- See [Node.js > `process`](/docs/runtime/nodejs-apis#node_process)
+- See [Node.js > `process`](/docs/runtime/nodejs-apis#node-process)
---
diff --git a/docs/api/hashing.md b/docs/api/hashing.md
index 3c15e1346f44fe..13a285693fe9c8 100644
--- a/docs/api/hashing.md
+++ b/docs/api/hashing.md
@@ -77,7 +77,7 @@ The standard `Bun.hash` functions uses [Wyhash](https://github.com/wangyi-fudan/
```ts
Bun.hash("some data here");
-// 976213160445840
+// 11562320457524636935n
```
The input can be a string, `TypedArray`, `DataView`, `ArrayBuffer`, or `SharedArrayBuffer`.
@@ -91,14 +91,14 @@ Bun.hash(arr.buffer);
Bun.hash(new DataView(arr.buffer));
```
-Optionally, an integer seed can be specified as the second parameter.
+Optionally, an integer seed can be specified as the second parameter. For 64-bit hashes seeds above `Number.MAX_SAFE_INTEGER` should be given as BigInt to avoid loss of precision.
```ts
Bun.hash("some data here", 1234);
-// 1173484059023252
+// 15724820720172937558n
```
-Additional hashing algorithms are available as properties on `Bun.hash`. The API is the same for each.
+Additional hashing algorithms are available as properties on `Bun.hash`. The API is the same for each, only changing the return type from number for 32-bit hashes to bigint for 64-bit hashes.
```ts
Bun.hash.wyhash("data", 1234); // equivalent to Bun.hash()
@@ -107,6 +107,7 @@ Bun.hash.adler32("data", 1234);
Bun.hash.cityHash32("data", 1234);
Bun.hash.cityHash64("data", 1234);
Bun.hash.murmur32v3("data", 1234);
+Bun.hash.murmur32v2("data", 1234);
Bun.hash.murmur64v2("data", 1234);
```
diff --git a/docs/api/import-meta.md b/docs/api/import-meta.md
index 8e148fffaacc6f..3c22308ce4b312 100644
--- a/docs/api/import-meta.md
+++ b/docs/api/import-meta.md
@@ -19,17 +19,17 @@ import.meta.resolveSync("zod")
---
- `import.meta.dir`
-- Absolute path to the directory containing the current fil, e.g. `/path/to/project`. Equivalent to `__dirname` in Node.js.
+- Absolute path to the directory containing the current file, e.g. `/path/to/project`. Equivalent to `__dirname` in CommonJS modules (and Node.js)
---
- `import.meta.file`
-- The name of the current file, e.g. `index.tsx`. Equivalent to `__filename` in Node.js.
+- The name of the current file, e.g. `index.tsx`
---
- `import.meta.path`
-- Absolute path to the current file, e.g. `/path/to/project/index.tx`.
+- Absolute path to the current file, e.g. `/path/to/project/index.tx`. Equivalent to `__filename` in CommonJS modules (and Node.js)
---
diff --git a/docs/api/spawn.md b/docs/api/spawn.md
index 1ef81f1b7ec875..b040272b5dc6cb 100644
--- a/docs/api/spawn.md
+++ b/docs/api/spawn.md
@@ -12,7 +12,7 @@ The second argument to `Bun.spawn` is a parameters object that can be used to co
```ts
const proc = Bun.spawn(["echo", "hello"], {
- cwd: "./path/to/subdir", // specify a working direcory
+ cwd: "./path/to/subdir", // specify a working directory
env: { ...process.env, FOO: "bar" }, // specify environment variables
onExit(proc, exitCode, signalCode, error) {
// exit handler
diff --git a/docs/api/streams.md b/docs/api/streams.md
index 210090927b1ca9..f0fa75f29dbdc4 100644
--- a/docs/api/streams.md
+++ b/docs/api/streams.md
@@ -1,6 +1,6 @@
Streams are an important abstraction for working with binary data without loading it all into memory at once. They are commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data.
-Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
+Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream).
{% callout %}
Bun also implements the `node:stream` module, including [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams), [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams), and [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams). For complete documentation, refer to the [Node.js docs](https://nodejs.org/api/stream.html).
diff --git a/docs/bundler/index.md b/docs/bundler/index.md
index da1c3ecaeea339..bfbed2077c9667 100644
--- a/docs/bundler/index.md
+++ b/docs/bundler/index.md
@@ -482,7 +482,7 @@ n/a
{% /codetabs %}
-Bun implements a univeral plugin system for both Bun's runtime and bundler. Refer to the [plugin documentation](/docs/bundler/plugins) for complete documentation.
+Bun implements a universal plugin system for both Bun's runtime and bundler. Refer to the [plugin documentation](/docs/bundler/plugins) for complete documentation.
-
-## `--preload`
-
-To consume this plugin, add this file to the `preload` option in your [`bunfig.toml`](/docs/runtime/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
-
-```toml
-preload = ["./yamlPlugin.ts"]
-```
-
-To preload files during `bun test`:
-
-```toml
-[test]
-preload = ["./loader.ts"]
-```
-
-{% details summary="Usage without preload" %}
-
-Alternatively, you can import this file manually at the top of your project's entrypoint, before any application code is imported.
-
-```ts#app.ts
-import "./yamlPlugin.ts";
-import { config } from "./config.yml";
-
-console.log(config);
-```
-
-{% /details %}
-
-## Third-party plugins
-
-By convention, third-party plugins intended for consumption should export a factory function that accepts some configuration and returns a plugin object.
-
-```ts
-import { plugin } from "bun";
-import fooPlugin from "bun-plugin-foo";
-
-plugin(
- fooPlugin({
- // configuration
- }),
-);
-
-// application code
-```
-
-Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
-
-```jsx
-import { plugin } from "bun";
-import mdx from "@mdx-js/esbuild";
-
-plugin(mdx());
-
-import { renderToStaticMarkup } from "react-dom/server";
-import Foo from "./bar.mdx";
-console.log(renderToStaticMarkup());
-```
-
-## Loaders
-
-
-
-
-
-
-
-
-
-Plugins are primarily used to extend Bun with loaders for additional file types. Let's look at a simple plugin that implements a loader for `.yaml` files.
-
-```ts#yamlPlugin.ts
-import { plugin } from "bun";
-
-plugin({
- name: "YAML",
- async setup(build) {
- const { load } = await import("js-yaml");
- const { readFileSync } = await import("fs");
-
- // when a .yaml file is imported...
- build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
-
- // read and parse the file
- const text = readFileSync(args.path, "utf8");
- const exports = load(text) as Record;
-
- // and returns it as a module
- return {
- exports,
- loader: "object", // special loader for JS objects
- };
- });
- },
-});
-```
-
-With this plugin, data can be directly imported from `.yaml` files.
-
-{% codetabs %}
-
-```ts#index.ts
-import "./yamlPlugin.ts"
-import {name, releaseYear} from "./data.yml"
-
-console.log(name, releaseYear);
-```
-
-```yaml#data.yml
-name: Fast X
-releaseYear: 2023
-```
-
-{% /codetabs %}
-
-Note that the returned object has a `loader` property. This tells Bun which of its internal loaders should be used to handle the result. Even though we're implementing a loader for `.yaml`, the result must still be understandable by one of Bun's built-in loaders. It's loaders all the way down.
-
-In this case we're using `"object"`—a built-in loader (intended for use by plugins) that converts a plain JavaScript object to an equivalent ES module. Any of Bun's built-in loaders are supported; these same loaders are used by Bun internally for handling files of various kinds. The table below is a quick reference; refer to [Bundler > Loaders](/docs/bundler/loaders) for complete documentation.
-
-{% table %}
-
-- Loader
-- Extensions
-- Output
-
----
-
-- `js`
-- `.mjs` `.cjs`
-- Transpile to JavaScript files
-
----
-
-- `jsx`
-- `.js` `.jsx`
-- Transform JSX then transpile
-
----
-
-- `ts`
-- `.ts` `.mts` `cts`
-- Transform TypeScript then transpile
-
----
-
-- `tsx`
-- `.tsx`
-- Transform TypeScript, JSX, then transpile
-
----
-
-- `toml`
-- `.toml`
-- Parse using Bun's built-in TOML parser
-
----
-
-- `json`
-- `.json`
-- Parse using Bun's built-in JSON parser
-
----
-
-- `napi`
-- `.node`
-- Import a native Node.js addon
-
----
-
-- `wasm`
-- `.wasm`
-- Import a native Node.js addon
-
----
-
-- `object`
-- _none_
-- A special loader intended for plugins that converts a plain JavaScript object to an equivalent ES module. Each key in the object corresponds to a named export.
-
-{% /callout %}
-
-Loading a YAML file is useful, but plugins support more than just data loading. Let's look at a plugin that lets Bun import `*.svelte` files.
-
-```ts#sveltePlugin.ts
-import { plugin } from "bun";
-
-await plugin({
- name: "svelte loader",
- async setup(build) {
- const { compile } = await import("svelte/compiler");
- const { readFileSync } = await import("fs");
-
- // when a .svelte file is imported...
- build.onLoad({ filter: /\.svelte$/ }, ({ path }) => {
-
- // read and compile it with the Svelte compiler
- const file = readFileSync(path, "utf8");
- const contents = compile(file, {
- filename: path,
- generate: "ssr",
- }).js.code;
-
- // and return the compiled source code as "js"
- return {
- contents,
- loader: "js",
- };
- });
- },
-});
-```
-
-> Note: in a production implementation, you'd want to cache the compiled output and include additional error handling.
-
-The object returned from `build.onLoad` contains the compiled source code in `contents` and specifies `"js"` as its loader. That tells Bun to consider the returned `contents` to be a JavaScript module and transpile it using Bun's built-in `js` loader.
-
-With this plugin, Svelte components can now be directly imported and consumed.
-
-```js
-import "./sveltePlugin.ts";
-import MySvelteComponent from "./component.svelte";
-
-console.log(mySvelteComponent.render());
-```
-
-## Reading `Bun.build`'s config
-
-Plugins can read and write to the [build config](/docs/bundler#api) with `build.config`.
-
-```ts
-Bun.build({
- entrypoints: ["./app.ts"],
- outdir: "./dist",
- sourcemap: "external",
- plugins: [
- {
- name: "demo",
- setup(build) {
- console.log(build.config.sourcemap); // "external"
-
- build.config.minify = true; // enable minification
-
- // `plugins` is readonly
- console.log(`Number of plugins: ${build.config.plugins.length}`);
- },
- },
- ],
-});
-```
-
-## Reference
-
-```ts
-namespace Bun {
- function plugin(plugin: { name: string; setup: (build: PluginBuilder) => void }): void;
-}
-
-type PluginBuilder = {
- onResolve: (
- args: { filter: RegExp; namespace?: string },
- callback: (args: { path: string; importer: string }) => {
- path: string;
- namespace?: string;
- } | void,
- ) => void;
- onLoad: (
- args: { filter: RegExp; namespace?: string },
- callback: (args: { path: string }) => {
- loader?: Loader;
- contents?: string;
- exports?: Record;
- },
- ) => void;
- config: BuildConfig;
-};
-
-type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "object";
-```
-
-The `onLoad` method optionally accepts a `namespace` in addition to the `filter` regex. This namespace will be be used to prefix the import in transpiled code; for instance, a loader with a `filter: /\.yaml$/` and `namespace: "yaml:"` will transform an import from `./myfile.yaml` into `yaml:./myfile.yaml`.
diff --git a/docs/bundler/vs-esbuild.md b/docs/bundler/vs-esbuild.md
index 5ccde1a1f7f75b..463fcc13aa9723 100644
--- a/docs/bundler/vs-esbuild.md
+++ b/docs/bundler/vs-esbuild.md
@@ -897,7 +897,7 @@ const myPlugin: BunPlugin = {
};
```
-The `builder` object provides some methods for hooking into parts of the bundling process. Bun implements `onResolve` and `onLoad`; it does not yet implement the esbuild hooks `onStart`, `onEnd`, and `onDispose`, and `resolve` utilities. `initialOptions` is partially implemented, being read-only and only having a subset of esbuild's options; use [`config`](/docs/bundler/plugins#reading-bunbuilds-config) (same thing but with Bun's `BuildConfig` format) instead.
+The `builder` object provides some methods for hooking into parts of the bundling process. Bun implements `onResolve` and `onLoad`; it does not yet implement the esbuild hooks `onStart`, `onEnd`, and `onDispose`, and `resolve` utilities. `initialOptions` is partially implemented, being read-only and only having a subset of esbuild's options; use [`config`](/docs/bundler/plugins#reading-the-config) (same thing but with Bun's `BuildConfig` format) instead.
```ts
import type { BunPlugin } from "bun";
diff --git a/docs/cli/install.md b/docs/cli/install.md
index 584350a42fa694..9b323a8aa82bd7 100644
--- a/docs/cli/install.md
+++ b/docs/cli/install.md
@@ -40,7 +40,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.
-- **Run** your project's `{pre|post}install` scripts at the appropriate time. For security reasons Bun _does not execute_ lifecycle scripts of installed dependencies.
+- **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`):
@@ -114,7 +114,7 @@ $ bun add zod@latest
To add a package as a dev dependency (`"devDependencies"`):
```bash
-$ bun add --development @types/react
+$ bun add --dev @types/react
$ bun add -d @types/react
```
diff --git a/docs/cli/run.md b/docs/cli/run.md
index 60061ee5c2493a..3680573b06a10f 100644
--- a/docs/cli/run.md
+++ b/docs/cli/run.md
@@ -126,4 +126,4 @@ Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/
{% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%}
-
+
diff --git a/docs/ecosystem/elysia.md b/docs/ecosystem/elysia.md
index b5225e6ce02bba..60dafe98125ce0 100644
--- a/docs/ecosystem/elysia.md
+++ b/docs/ecosystem/elysia.md
@@ -1,7 +1,7 @@
[Elysia](https://elysiajs.com) is a Bun-first performance focused web framework that takes full advantage of Bun's HTTP, file system, and hot reloading APIs.
Designed with TypeScript in mind, you don't need to understand TypeScript to gain the benefit of TypeScript with Elysia. The library understands what you want and automatically infers the type from your code.
-:zap: Elysia is [one of the fastest Bun web frameworks](https://github.com/SaltyAom/bun-http-framework-benchmark)
+⚡️ Elysia is [one of the fastest Bun web frameworks](https://github.com/SaltyAom/bun-http-framework-benchmark)
```ts#server.ts
import { Elysia } from 'elysia'
@@ -9,7 +9,7 @@ import { Elysia } from 'elysia'
const app = new Elysia()
.get('/', () => 'Hello Elysia')
.listen(8080)
-
+
console.log(`🦊 Elysia is running at on port ${app.server.port}...`)
```
diff --git a/docs/ecosystem/express.md b/docs/ecosystem/express.md
index bbca048abf170e..8f1fccae105dbf 100644
--- a/docs/ecosystem/express.md
+++ b/docs/ecosystem/express.md
@@ -22,7 +22,7 @@ app.listen(port, () => {
Bun implements the [`node:http`](https://nodejs.org/api/http.html) and [`node:https`](https://nodejs.org/api/https.html) modules that these libraries rely on. These modules can also be used directly, though [`Bun.serve`](/docs/api/http) is recommended for most use cases.
{% callout %}
-**Note** — Refer to the [Runtime > Node.js APIs](/docs/runtime/nodejs-apis#node_http) page for more detailed compatibility information.
+**Note** — Refer to the [Runtime > Node.js APIs](/docs/runtime/nodejs-apis#node-http) page for more detailed compatibility information.
{% /callout %}
```ts
diff --git a/docs/ecosystem/hono.md b/docs/ecosystem/hono.md
index c89dce9f7f89d4..e96fbc5c910f25 100644
--- a/docs/ecosystem/hono.md
+++ b/docs/ecosystem/hono.md
@@ -1,15 +1,16 @@
[Hono](https://github.com/honojs/hono) is a lightweight ultrafast web framework designed for the edge.
```ts
-import { Hono } from 'hono'
-const app = new Hono()
+import { Hono } from "hono";
+const app = new Hono();
-app.get('/', (c) => c.text('Hono!'))
+app.get("/", c => c.text("Hono!"));
-export default app
+export default app;
```
Get started with `bun create` or follow Hono's [Bun quickstart](https://hono.dev/getting-started/bun).
+
```bash
$ bun create hono ./myapp
$ cd myapp
diff --git a/docs/guides/binary/arraybuffer-to-array.md b/docs/guides/binary/arraybuffer-to-array.md
new file mode 100644
index 00000000000000..688030b0a0d15d
--- /dev/null
+++ b/docs/guides/binary/arraybuffer-to-array.md
@@ -0,0 +1,27 @@
+---
+name: Convert an ArrayBuffer to an array of numbers
+---
+
+To retrieve the contents of an `ArrayBuffer` as an array of numbers, create a [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) over of the buffer. and use the [`Array.from()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) method to convert it to an array.
+
+```ts
+const buf = new ArrayBuffer(64);
+const arr = new Uint8Array(buf);
+arr.length; // 64
+arr[0]; // 0 (instantiated with all zeros)
+```
+
+---
+
+The `Uint8Array` class supports array indexing and iteration. However if you wish to convert the instance to a regular `Array`, use `Array.from()`. (This will likely be slower than using the `Uint8Array` directly.)
+
+```ts
+const buf = new ArrayBuffer(64);
+const uintArr = new Uint8Array(buf);
+const regularArr = Array.from(uintArr);
+// number[]
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/arraybuffer-to-blob.md b/docs/guides/binary/arraybuffer-to-blob.md
new file mode 100644
index 00000000000000..53795282e6613b
--- /dev/null
+++ b/docs/guides/binary/arraybuffer-to-blob.md
@@ -0,0 +1,24 @@
+---
+name: Convert an ArrayBuffer to a Blob
+---
+
+A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) can be constructed from an array of "chunks", where each chunk is a string, binary data structure, or another `Blob`.
+
+```ts
+const buf = new ArrayBuffer(64);
+const blob = new Blob([buf]);
+```
+
+---
+
+By default the `type` of the resulting `Blob` will be unset. This can be set manually.
+
+```ts
+const buf = new ArrayBuffer(64);
+const blob = new Blob([buf], { type: "application/octet-stream" });
+blob.type; // => "application/octet-stream"
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/arraybuffer-to-buffer.md b/docs/guides/binary/arraybuffer-to-buffer.md
new file mode 100644
index 00000000000000..4aeb54e697acad
--- /dev/null
+++ b/docs/guides/binary/arraybuffer-to-buffer.md
@@ -0,0 +1,25 @@
+---
+name: Convert an ArrayBuffer to a Buffer
+---
+
+The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) API predates the introduction of `ArrayBuffer` into the JavaScript language. Bun implements both.
+
+Use the static `Buffer.from()` method to create a `Buffer` from an `ArrayBuffer`.
+
+```ts
+const arrBuffer = new ArrayBuffer(64);
+const nodeBuffer = Buffer.from(arrBuffer);
+```
+
+---
+
+To create a `Buffer` that only views a portion of the underlying buffer, pass the offset and length to the constructor.
+
+```ts
+const arrBuffer = new ArrayBuffer(64);
+const nodeBuffer = Buffer.from(arrBuffer, 0, 16); // view first 16 bytes
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/arraybuffer-to-string.md b/docs/guides/binary/arraybuffer-to-string.md
new file mode 100644
index 00000000000000..13bb83122b2fe1
--- /dev/null
+++ b/docs/guides/binary/arraybuffer-to-string.md
@@ -0,0 +1,15 @@
+---
+name: Convert an ArrayBuffer to a string
+---
+
+Bun implements the Web-standard [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) class for converting between binary data types and strings.
+
+```ts
+const buf = new ArrayBuffer(64);
+const decoder = new TextDecoder();
+const str = decoder.decode(buf);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/arraybuffer-to-typedarray.md b/docs/guides/binary/arraybuffer-to-typedarray.md
new file mode 100644
index 00000000000000..a4e823d8f7e77b
--- /dev/null
+++ b/docs/guides/binary/arraybuffer-to-typedarray.md
@@ -0,0 +1,39 @@
+---
+name: Convert an ArrayBuffer to a Uint8Array
+---
+
+A `Uint8Array` is a _typed array_, meaning it is a mechanism for viewing the data in an underlying `ArrayBuffer`.
+
+```ts
+const buffer = new ArrayBuffer(64);
+const arr = new Uint8Array(buffer);
+```
+
+---
+
+Instances of other typed arrays can be created similarly.
+
+```ts
+const buffer = new ArrayBuffer(64);
+
+const arr1 = new Uint8Array(buffer);
+const arr2 = new Uint16Array(buffer);
+const arr3 = new Uint32Array(buffer);
+const arr4 = new Float32Array(buffer);
+const arr5 = new Float64Array(buffer);
+const arr6 = new BigInt64Array(buffer);
+const arr7 = new BigUint64Array(buffer);
+```
+
+---
+
+To create a typed array that only views a portion of the underlying buffer, pass the offset and length to the constructor.
+
+```ts
+const buffer = new ArrayBuffer(64);
+const arr = new Uint8Array(buffer, 0, 16); // view first 16 bytes
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/binary/blob-to-arraybuffer.md b/docs/guides/binary/blob-to-arraybuffer.md
new file mode 100644
index 00000000000000..18e3f1235da7d8
--- /dev/null
+++ b/docs/guides/binary/blob-to-arraybuffer.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Blob to an ArrayBuffer
+---
+
+The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, including `.arrayBuffer()`.
+
+```ts
+const blob = new Blob(["hello world"]);
+const buf = await blob.arrayBuffer();
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/blob-to-dataview.md b/docs/guides/binary/blob-to-dataview.md
new file mode 100644
index 00000000000000..7d874c1f6e0a77
--- /dev/null
+++ b/docs/guides/binary/blob-to-dataview.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Blob to a DataView
+---
+
+The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats. This snippets reads the contents to an `ArrayBuffer`, then creates a `DataView` from the buffer.
+
+```ts
+const blob = new Blob(["hello world"]);
+const arr = new DataView(await blob.arrayBuffer());
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/blob-to-stream.md b/docs/guides/binary/blob-to-stream.md
new file mode 100644
index 00000000000000..37a916ab38479e
--- /dev/null
+++ b/docs/guides/binary/blob-to-stream.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Blob to a ReadableStream
+---
+
+The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, inluding `.stream()`. This returns `Promise`.
+
+```ts
+const blob = new Blob(["hello world"]);
+const stream = await blob.stream();
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/blob-to-string.md b/docs/guides/binary/blob-to-string.md
new file mode 100644
index 00000000000000..05692c32e8419e
--- /dev/null
+++ b/docs/guides/binary/blob-to-string.md
@@ -0,0 +1,15 @@
+---
+name: Convert a Blob to a string
+---
+
+The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, inluding `.text()`.
+
+```ts
+const blob = new Blob(["hello world"]);
+const str = await blob.text();
+// => "hello world"
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/blob-to-typedarray.md b/docs/guides/binary/blob-to-typedarray.md
new file mode 100644
index 00000000000000..efedad02fcb41d
--- /dev/null
+++ b/docs/guides/binary/blob-to-typedarray.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Blob to a Uint8Array
+---
+
+The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats. This snippets reads the contents to an `ArrayBuffer`, then creates a `Uint8Array` from the buffer.
+
+```ts
+const blob = new Blob(["hello world"]);
+const arr = new Uint8Array(await blob.arrayBuffer());
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/buffer-to-arraybuffer.md b/docs/guides/binary/buffer-to-arraybuffer.md
new file mode 100644
index 00000000000000..56ba78a00a832f
--- /dev/null
+++ b/docs/guides/binary/buffer-to-arraybuffer.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Buffer to an ArrayBuffer
+---
+
+The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) class provides a way to view and manipulate data in an underlying `ArrayBuffer`, which is available via the `buffer` property.
+
+```ts
+const nodeBuf = Buffer.alloc(64);
+const arrBuf = nodeBuf.buffer;
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/buffer-to-blob.md b/docs/guides/binary/buffer-to-blob.md
new file mode 100644
index 00000000000000..9f59c9f687a076
--- /dev/null
+++ b/docs/guides/binary/buffer-to-blob.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Buffer to a blob
+---
+
+A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) can be constructed from an array of "chunks", where each chunk is a string, binary data structure (including `Buffer`), or another `Blob`.
+
+```ts
+const buf = Buffer.from("hello");
+const blob = new Blob([buf]);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/buffer-to-readablestream.md b/docs/guides/binary/buffer-to-readablestream.md
new file mode 100644
index 00000000000000..fbb03df5079323
--- /dev/null
+++ b/docs/guides/binary/buffer-to-readablestream.md
@@ -0,0 +1,41 @@
+---
+name: Convert a Buffer to a ReadableStream
+---
+
+The naive approach to creating a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) from a [`Buffer`](https://nodejs.org/api/buffer.html) is to use the `ReadableStream` constructor and enqueue the entire array as a single chunk. For a large buffer, this may be undesirable as this approach does not "streaming" the data in smaller chunks.
+
+```ts
+const buf = Buffer.from("hello world");
+const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(buf);
+ controller.close();
+ },
+});
+```
+
+---
+
+To stream the data in smaller chunks, first create a `Blob` instance from the `Buffer`. Then use the [`Blob.stream()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream) method to create a `ReadableStream` that streams the data in chunks of a specified size.
+
+```ts
+const buf = Buffer.from("hello world");
+const blob = new Blob([buf]);
+const stream = blob.stream();
+```
+
+---
+
+The chunk size can be set by passing a number to the `.stream()` method.
+
+```ts
+const buf = Buffer.from("hello world");
+const blob = new Blob([buf]);
+
+// set chunk size of 1024 bytes
+const stream = blob.stream(1024);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/buffer-to-string.md b/docs/guides/binary/buffer-to-string.md
new file mode 100644
index 00000000000000..f900cd6a3b0860
--- /dev/null
+++ b/docs/guides/binary/buffer-to-string.md
@@ -0,0 +1,25 @@
+---
+name: Convert a Buffer to a string
+---
+
+The [`Buffer`](https://nodejs.org/api/buffer.html) class provides a built-in `.toString()` method that converts a `Buffer` to a string.
+
+```ts
+const buf = Buffer.from("hello");
+const str = buf.toString();
+// => "hello"
+```
+
+---
+
+You can optionally specify an encoding and byte range.
+
+```ts
+const buf = Buffer.from("hello world!");
+const str = buf.toString("utf8", 0, 5);
+// => "hello"
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/buffer-to-typedarray.md b/docs/guides/binary/buffer-to-typedarray.md
new file mode 100644
index 00000000000000..c59d77218ac465
--- /dev/null
+++ b/docs/guides/binary/buffer-to-typedarray.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Buffer to a Uint8Array
+---
+
+The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) class extends [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), so no conversion is needed. All properties and methods on `Uint8Array` are available on `Buffer`.
+
+```ts
+const buf = Buffer.alloc(64);
+buf instanceof Uint8Array; // => true
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/dataview-to-string.md b/docs/guides/binary/dataview-to-string.md
new file mode 100644
index 00000000000000..0151eaa58d3d64
--- /dev/null
+++ b/docs/guides/binary/dataview-to-string.md
@@ -0,0 +1,15 @@
+---
+name: Convert a Uint8Array to a string
+---
+
+If a [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) contains ASCII-encoded text, you can convert it to a string using the [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) class.
+
+```ts
+const dv: DataView = ...;
+const decoder = new TextDecoder();
+const str = decoder.decode(dv);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/index.json b/docs/guides/binary/index.json
new file mode 100644
index 00000000000000..0ddf3da4959e7e
--- /dev/null
+++ b/docs/guides/binary/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Binary data",
+ "description": "A collection of guides for converting between binary data formats with Bun"
+}
diff --git a/docs/guides/binary/typedarray-to-arraybuffer.md b/docs/guides/binary/typedarray-to-arraybuffer.md
new file mode 100644
index 00000000000000..2458b21c0ddb60
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-arraybuffer.md
@@ -0,0 +1,25 @@
+---
+name: Convert a Uint8Array to an ArrayBuffer
+---
+
+A [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) is a _typed array_ class, meaning it is a mechanism for viewing data in an underlying `ArrayBuffer`. The underlying `ArrayBuffer` is accessible via the `buffer` property.
+
+```ts
+const arr = new Uint8Array(64);
+arr.buffer; // => ArrayBuffer(64)
+```
+
+---
+
+The `Uint8Array` may be a view over a _subset_ of the data in the underlying `ArrayBuffer`. In this case, the `buffer` property will return the entire buffer, and the `byteOffset` and `byteLength` properties will indicate the subset.
+
+```ts
+const arr = new Uint8Array(64, 16, 32);
+arr.buffer; // => ArrayBuffer(64)
+arr.byteOffset; // => 16
+arr.byteLength; // => 32
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/typedarray-to-blob.md b/docs/guides/binary/typedarray-to-blob.md
new file mode 100644
index 00000000000000..e2ca301b8bca80
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-blob.md
@@ -0,0 +1,16 @@
+---
+name: Convert a Uint8Array to a Blob
+---
+
+A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) can be constructed from an array of "chunks", where each chunk is a string, binary data structure (including `Uint8Array`), or another `Blob`.
+
+```ts
+const arr = new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]);
+const blob = new Blob([arr]);
+console.log(await blob.text());
+// => "hello"
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/typedarray-to-buffer.md b/docs/guides/binary/typedarray-to-buffer.md
new file mode 100644
index 00000000000000..e4013644aae1e8
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-buffer.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Uint8Array to a Buffer
+---
+
+The [`Buffer`](https://nodejs.org/api/buffer.html) class extends [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) with a number of additional methods. Use `Buffer.from()` to create a `Buffer` instance from a `Uint8Array`.
+
+```ts
+const arr: Uint8Array = ...
+const buf = Buffer.from(arr);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/typedarray-to-dataview.md b/docs/guides/binary/typedarray-to-dataview.md
new file mode 100644
index 00000000000000..dfef2166bde9d4
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-dataview.md
@@ -0,0 +1,14 @@
+---
+name: Convert a Uint8Array to a DataView
+---
+
+A [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) is a _typed array_ class, meaning it is a mechanism for viewing data in an underlying `ArrayBuffer`. The following snippet creates a [`DataView`] instance over the same range of data as the `Uint8Array`.
+
+```ts
+const arr: Uint8Array = ...
+const dv = new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/typedarray-to-readablestream.md b/docs/guides/binary/typedarray-to-readablestream.md
new file mode 100644
index 00000000000000..3be9e29d524bf9
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-readablestream.md
@@ -0,0 +1,41 @@
+---
+name: Convert a Uint8Array to a ReadableStream
+---
+
+The naive approach to creating a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) from a [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) is to use the [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) constructor and enqueue the entire array as a single chunk. For larger chunks, this may be undesirable as it isn't actually "streaming" the data.
+
+```ts
+const arr = new Uint8Array(64);
+const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(arr);
+ controller.close();
+ },
+});
+```
+
+---
+
+To stream the data in smaller chunks, first create a `Blob` instance from the `Uint8Array`. Then use the [`Blob.stream()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream) method to create a `ReadableStream` that streams the data in chunks of a specified size.
+
+```ts
+const arr = new Uint8Array(64);
+const blob = new Blob([arr]);
+const stream = blob.stream();
+```
+
+---
+
+The chunk size can be set by passing a number to the `.stream()` method.
+
+```ts
+const arr = new Uint8Array(64);
+const blob = new Blob([arr]);
+
+// set chunk size of 1024 bytes
+const stream = blob.stream(1024);
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/binary/typedarray-to-string.md b/docs/guides/binary/typedarray-to-string.md
new file mode 100644
index 00000000000000..9c5703420c05da
--- /dev/null
+++ b/docs/guides/binary/typedarray-to-string.md
@@ -0,0 +1,16 @@
+---
+name: Convert a Uint8Array to a string
+---
+
+Bun implements the Web-standard [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) class for converting from binary data types like `Uint8Array` and strings.
+
+```ts
+const arr = new Uint8Array([104, 101, 108, 108, 111]);
+const decoder = new TextDecoder();
+const str = decoder.decode(buf);
+// => "hello"
+```
+
+---
+
+See [Docs > API > Binary Data](/docs/api/binary-data#conversion) for complete documentation on manipulating binary data with Bun.
diff --git a/docs/guides/ecosystem/discordjs.md b/docs/guides/ecosystem/discordjs.md
new file mode 100644
index 00000000000000..7d9541861150fc
--- /dev/null
+++ b/docs/guides/ecosystem/discordjs.md
@@ -0,0 +1,77 @@
+---
+name: Create a Discord bot
+---
+
+Discord.js works [out of the box](https://bun.sh/blog/bun-v0.6.7) with Bun. Let's write a simple bot. First create a directory and initialize it with `bun init`.
+
+```bash
+mkdir my-bot
+cd my-bot
+bun init
+```
+
+---
+
+Now install Discord.js.
+
+```bash
+bun add discord.js
+```
+
+---
+
+Before we go further, we need to go to the [Discord developer portal](https://discord.com/developers/applications), login/signup, create a new _Application_, then create a new _Bot_ within that application. Follow the [official guide](https://discordjs.guide/preparations/setting-up-a-bot-application.html#creating-your-bot) for step-by-step instructions.
+
+---
+
+Once complete, you'll be presented with your bot's _private key_. Let's add this to a file called `.env.local`. Bun automatically reads this file and loads it into `process.env`.
+
+{% callout %}
+This is an example token that has already been invalidated.
+{% /callout %}
+
+```txt#.env.local
+DISCORD_TOKEN=NzkyNzE1NDU0MTk2MDg4ODQy.X-hvzA.Ovy4MCQywSkoMRRclStW4xAYK7I
+```
+
+---
+
+Be sure to add `.env.local` to your `.gitignore`! It is dangerous to check your bot's private key into version control.
+
+```txt#.gitignore
+node_modules
+.env.local
+```
+
+---
+
+Now let's actually write our bot in a new file called `bot.ts`.
+
+```ts#bot.ts
+// import discord.js
+import {Client, Events, GatewayIntentBits} from 'discord.js';
+
+// create a new Client instance
+const client = new Client({intents: [GatewayIntentBits.Guilds]});
+
+// listen for the client to be ready
+client.once(Events.ClientReady, (c) => {
+ console.log(`Ready! Logged in as ${c.user.tag}`);
+});
+
+// login with the token from .env.local
+client.login(process.env.DISCORD_TOKEN);
+```
+
+---
+
+Now we can run our bot with `bun run`. It may take a several seconds for the client to initialize the first time you run the file.
+
+```bash
+$ bun run bot.ts
+Ready! Logged in as my-bot#1234
+```
+
+---
+
+You're up and running with a bare-bones Discord.js bot! This is a basic guide to setting up your bot with Bun; we recommend the [official Discord docs](https://discordjs.guide/) for complete information on the `discord.js` API.
diff --git a/docs/guides/ecosystem/elysia.md b/docs/guides/ecosystem/elysia.md
new file mode 100644
index 00000000000000..ae1a8e37b92ba0
--- /dev/null
+++ b/docs/guides/ecosystem/elysia.md
@@ -0,0 +1,31 @@
+---
+name: Build an HTTP server using Elysia and Bun
+---
+
+[Elysia](https://elysiajs.com) is a Bun-first performance focused web framework that takes full advantage of Bun's HTTP, file system, and hot reloading APIs. Get started with `bun create`.
+
+```bash
+$ bun create elysia myapp
+$ cd myapp
+$ bun run dev
+```
+
+---
+
+To define a simple HTTP route and start a server with Elysia:
+
+```ts#server.ts
+import { Elysia } from 'elysia'
+
+const app = new Elysia()
+ .get('/', () => 'Hello Elysia')
+ .listen(8080)
+
+console.log(`🦊 Elysia is running at on port ${app.server.port}...`)
+```
+
+---
+
+Elysia is a full-featured server framework with Express-like syntax, type inference, middleware, file uploads, and plugins for JWT authentication, tRPC, and more. It's also is one of the [fastest Bun web frameworks](https://github.com/SaltyAom/bun-http-framework-benchmark).
+
+Refer to the Elysia [documentation](https://elysiajs.com/quick-start.html) for more information.
diff --git a/docs/guides/ecosystem/express.md b/docs/guides/ecosystem/express.md
new file mode 100644
index 00000000000000..6042b17e4412cf
--- /dev/null
+++ b/docs/guides/ecosystem/express.md
@@ -0,0 +1,40 @@
+---
+name: Build an HTTP server using Express and Bun
+---
+
+Express and other major Node.js HTTP libraries should work out of the box. Bun implements the [`node:http`](https://nodejs.org/api/http.html) and [`node:https`](https://nodejs.org/api/https.html) modules that these libraries rely on.
+
+{% callout %}
+Refer to the [Runtime > Node.js APIs](/docs/runtime/nodejs-apis#node-http) page for more detailed compatibility information.
+{% /callout %}
+
+```sh
+$ bun add express
+```
+
+---
+
+To define a simple HTTP route and start a server with Express:
+
+```ts#server.ts
+import express from "express";
+
+const app = express();
+const port = 8080;
+
+app.get("/", (req, res) => {
+ res.send("Hello World!");
+});
+
+app.listen(port, () => {
+ console.log(`Listening on port ${port}...`);
+});
+```
+
+---
+
+To start the server on `localhost`:
+
+```sh
+$ bun server.ts
+```
diff --git a/docs/guides/ecosystem/hono.md b/docs/guides/ecosystem/hono.md
new file mode 100644
index 00000000000000..6d928a655db255
--- /dev/null
+++ b/docs/guides/ecosystem/hono.md
@@ -0,0 +1,39 @@
+---
+name: Build an HTTP server using Hono and Bun
+---
+
+[Hono](https://github.com/honojs/hono) is a lightweight ultrafast web framework designed for the edge.
+
+```ts
+import { Hono } from "hono";
+const app = new Hono();
+
+app.get("/", c => c.text("Hono!"));
+
+export default app;
+```
+
+---
+
+Use `create-hono` to get started with one of Hono's project templates. Select `bun` when prompted for a template.
+
+```bash
+$ bunx create-hono myapp
+✔ Which template do you want to use? › bun
+cloned honojs/starter#main to /path/to/myapp
+✔ Copied project files
+$ cd myapp
+$ bun install
+```
+
+---
+
+Then start the dev server and visit [localhost:3000](http://localhost:3000).
+
+```bash
+$ bun run dev
+```
+
+---
+
+Refer to Hono's guide on [getting started with Bun](https://hono.dev/getting-started/bun) for more information.
diff --git a/docs/guides/ecosystem/index.json b/docs/guides/ecosystem/index.json
new file mode 100644
index 00000000000000..4099acec339582
--- /dev/null
+++ b/docs/guides/ecosystem/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Ecosystem",
+ "description": "A collection of guides for using various tools and frameworks with Bun"
+}
diff --git a/docs/guides/ecosystem/mongoose.md b/docs/guides/ecosystem/mongoose.md
new file mode 100644
index 00000000000000..bfcb957cc8709c
--- /dev/null
+++ b/docs/guides/ecosystem/mongoose.md
@@ -0,0 +1,80 @@
+---
+name: Read and write data to MongoDB using Mongoose and Bun
+---
+
+MongoDB and Mongoose work out of the box with Bun. This guide assumes you've already installed MongoDB and are running it as background process/service on your development machine. Follow [this guide](https://www.mongodb.com/docs/manual/installation/) for details.
+
+---
+
+Once MongoDB is running, create a directory and initialize it with `bun init`.
+
+```bash
+mkdir mongoose-app
+cd mongoose-app
+bun init
+```
+
+---
+
+Then add Mongoose as a dependency.
+
+```bash
+bun add mongoose
+```
+
+---
+
+In `schema.ts` we'll declare and export a simple `Animal` model.
+
+```ts#schema.ts
+import * as mongoose from 'mongoose';
+
+const animalSchema = new mongoose.Schema(
+ {
+ name: {type: String, required: true},
+ sound: {type: String, required: true},
+ }
+);
+
+export type Animal = mongoose.InferSchemaType;
+export const Animal = mongoose.model('Kitten', animalSchema);
+```
+
+---
+
+Now from `index.ts` we can import `Animal`, connect to MongoDB, and add some data to our database.
+
+```ts#index.ts
+import * as mongoose from 'mongoose';
+import {Animal} from './schema';
+
+// connect to database
+await mongoose.connect('mongodb://127.0.0.1:27017/mongoose-app');
+
+// create new Animal
+const cow = new Animal({
+ name: 'Cow',
+ sound: 'Moo',
+});
+await cow.save(); // saves to the database
+
+// read all Animals
+const animals = await Animal.find();
+animals[0].speak(); // logs "Moo!"
+
+// disconect
+await mongoose.disconnect();
+```
+
+---
+
+Lets run this with `bun run`.
+
+```bash
+$ bun run index.ts
+Moo!
+```
+
+---
+
+This is a simple introduction to using Mongoose with TypeScript and Bun. As you build your application, refer to the official [MongoDB](https://docs.mongodb.com/) and [Mongoose](https://mongoosejs.com/docs/) sites for complete documentation.
diff --git a/docs/guides/ecosystem/nextjs.md b/docs/guides/ecosystem/nextjs.md
new file mode 100644
index 00000000000000..b8b45ca594b856
--- /dev/null
+++ b/docs/guides/ecosystem/nextjs.md
@@ -0,0 +1,31 @@
+---
+name: Build an app with Next.js and Bun
+---
+
+{% callout %}
+Next.js currently relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
+{% /callout %}
+
+---
+
+Initialize a Next.js app with `create-next-app`. This automatically installs dependencies using `npm`.
+
+```sh
+$ bunx create-next-app
+✔ What is your project named? … my-app
+✔ Would you like to use TypeScript with this project? … No / Yes
+✔ Would you like to use ESLint with this project? … No / Yes
+✔ Would you like to use `src/` directory with this project? … No / Yes
+✔ Would you like to use experimental `app/` directory with this project? … No / Yes
+✔ What import alias would you like configured? … @/*
+Creating a new Next.js app in /path/to/my-app.
+```
+
+---
+
+To start the dev server, run `bun run dev` from the project root.
+
+```sh
+$ cd my-app
+$ bun run dev
+```
diff --git a/docs/guides/ecosystem/prisma.md b/docs/guides/ecosystem/prisma.md
new file mode 100644
index 00000000000000..e697e2133ae4b6
--- /dev/null
+++ b/docs/guides/ecosystem/prisma.md
@@ -0,0 +1,110 @@
+---
+name: Get started using Prisma
+---
+
+Prisma works out of the box with Bun. First, create a directory and initialize it with `bun init`.
+
+```bash
+mkdir prisma-app
+cd prisma-app
+bun init
+```
+
+---
+
+Then add Prisma as a dependency.
+
+```bash
+bun add prisma
+```
+
+---
+
+We'll use the Prisma CLI with `bunx` to initialize our schema and migration directory. For simplicity we'll be using an in-memory SQLite database.
+
+```bash
+bunx prisma init --datasource-provider sqlite
+```
+
+---
+
+Open `prisma/schema.prisma` and add a simple `User` model.
+
+```prisma-diff#prisma/schema.prisma
+ generator client {
+ provider = "prisma-client-js"
+ }
+
+ datasource db {
+ provider = "sqlite"
+ url = env("DATABASE_URL")
+ }
+
++ model User {
++ id Int @id @default(autoincrement())
++ email String @unique
++ name String?
++ }
+```
+
+---
+
+Then generate and run initial migration.
+
+This will generate a `.sql` migration file in `prisma/migrations`, create a new SQLite instance, and execute the migration against the new instance.
+
+```bash
+bunx prisma migrate dev --name init
+```
+
+---
+
+Prisma automatically generates our _Prisma client_ whenever we execute a new migration. The client provides a fully typed API for reading and writing from our database.
+
+It can be imported from `@prisma/client`.
+
+```ts#src/index.ts
+import {PrismaClient} from "@prisma/client";
+```
+
+---
+
+Let's write a simple script to create a new user, then count the number of users in the database.
+
+```ts#index.ts
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+// create a new user
+await prisma.user.create({
+ data: {
+ name: "John Dough",
+ email: `john-${Math.random()}@example.com`,
+ },
+});
+
+// count the number of users
+const count = await prisma.user.count();
+console.log(`There are ${count} users in the database.`);
+```
+
+---
+
+Let's run this script with `bun run`. Each time we run it, a new user is created.
+
+```bash
+$ bun run index.ts
+Created john-0.12802932895402364@example.com
+There are 1 users in the database.
+$ bun run index.ts
+Created john-0.8671308799782803@example.com
+There are 2 users in the database.
+$ bun run index.ts
+Created john-0.4465968383115295@example.com
+There are 3 users in the database.
+```
+
+---
+
+That's it! Now that you've set up Prisma using Bun, we recommend referring to the [official Prisma docs](https://www.prisma.io/docs/concepts/components/prisma-client) as you continue to develop your application.
diff --git a/docs/guides/ecosystem/react.md b/docs/guides/ecosystem/react.md
new file mode 100644
index 00000000000000..b712e210e36b97
--- /dev/null
+++ b/docs/guides/ecosystem/react.md
@@ -0,0 +1,30 @@
+---
+name: Use React and JSX
+---
+
+React just works with Bun. Bun supports `.jsx` and `.tsx` files out of the box. Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
+
+```tsx#react.tsx
+function Component(props: {message: string}) {
+ return (
+
+ {props.message}
+
+ );
+}
+
+console.log();
+```
+
+---
+
+Bun implements special logging for JSX to make debugging easier.
+
+```bash
+$ bun run react.tsx
+
+```
+
+---
+
+Refer to [Runtime > JSX](/docs/runtime/jsx) for complete documentation on configuring JSX.
diff --git a/docs/guides/ecosystem/ssr-react.md b/docs/guides/ecosystem/ssr-react.md
new file mode 100644
index 00000000000000..59d37db46d35e3
--- /dev/null
+++ b/docs/guides/ecosystem/ssr-react.md
@@ -0,0 +1,42 @@
+---
+name: Server-side render (SSR) a React component
+---
+
+To render a React component to an HTML stream server-side (SSR):
+
+```tsx
+import { renderToReadableStream } from "react-dom/server";
+
+function Component(props: { message: string }) {
+ return (
+
+ {props.message}
+
+ );
+}
+
+const stream = await renderToReadableStream(
+ ,
+);
+```
+
+---
+
+Combining this with `Bun.serve()`, we get a simple SSR HTTP server:
+
+```tsx
+Bun.serve({
+ async fetch() {
+ const stream = await renderToReadableStream(
+ ,
+ );
+ return new Response(stream, {
+ headers: { "Content-Type": "text/html" },
+ });
+ },
+});
+```
+
+---
+
+React `18.3` and later includes an [SSR optimization](https://github.com/facebook/react/pull/25597) that takes advantage of Bun's "direct" `ReadableStream` implementation.
diff --git a/docs/guides/ecosystem/stric.md b/docs/guides/ecosystem/stric.md
new file mode 100644
index 00000000000000..15ef72cc6e034b
--- /dev/null
+++ b/docs/guides/ecosystem/stric.md
@@ -0,0 +1,53 @@
+---
+name: Build an HTTP server using StricJS and Bun
+---
+
+[StricJS](https://github.com/bunsvr) is a Bun framework for building high-performance web applications and APIs.
+
+- **Fast** — Stric is one of the fastest Bun frameworks. See [benchmark](https://github.com/bunsvr/benchmark) for more details.
+- **Minimal** — The basic components like `@stricjs/router` and `@stricjs/utils` are under 50kB and require no external dependencies.
+- **Extensible** — Stric includes with a plugin system, dependency injection, and optional optimizations for handling requests.
+
+---
+
+Use `bun init` to create an empty project.
+
+```bash
+$ mkdir myapp
+$ cd myapp
+$ bun init
+$ bun add @stricjs/router
+```
+
+---
+
+To implement a simple HTTP server with StricJS:
+
+```ts#index.ts
+import { Router } from '@stricjs/router';
+
+export default new Router()
+ .get('/', () => new Response('Hi'));
+```
+
+---
+
+To serve static files from `/public/*`:
+
+```ts#index.ts
+export default new Router()
+ .get('/', () => new Response('Hi'))
+ .get('/public/*', stream('.'));
+```
+
+---
+
+Run the file in watch mode to start the development server.
+
+```bash
+$ bun --watch run index.ts
+```
+
+---
+
+For more info, see Stric's [documentation](https://stricjs.gitbook.io/docs).
diff --git a/docs/guides/ecosystem/vite.md b/docs/guides/ecosystem/vite.md
new file mode 100644
index 00000000000000..857e11aae65d10
--- /dev/null
+++ b/docs/guides/ecosystem/vite.md
@@ -0,0 +1,71 @@
+---
+name: Build a frontend using Vite and Bun
+---
+
+{% callout %}
+While Vite currently works with Bun, it has not been heavily optimized, nor has Vite been adapted to use Bun's bundler, module resolver, or transpiler.
+{% /callout %}
+
+---
+
+Vite works out of the box with Bun (v0.7 and later). Get started with one of Vite's templates.
+
+```bash
+$ bunx create-vite my-app
+✔ Select a framework: › React
+✔ Select a variant: › TypeScript + SWC
+Scaffolding project in /path/to/my-app...
+```
+
+---
+
+Then `cd` into the project directory and install dependencies.
+
+```bash
+cd my-app
+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](). After Bun 1.0 this flag will no longer be necessary.
+
+```bash
+bunx --bun vite
+```
+
+---
+
+To simplify this command, update the `"dev"` script in `package.json` to the following.
+
+```json-diff#package.json
+ "scripts": {
+- "dev": "vite",
++ "dev": "bunx --bun vite",
+ "build": "vite build",
+ "serve": "vite preview"
+ },
+ // ...
+```
+
+---
+
+Now you can start the development server with `bun run dev`.
+
+```bash
+bun run dev
+```
+
+---
+
+The following command will build your app for production.
+
+```sh
+$ bunx --bun vite build
+```
+
+---
+
+This is a stripped down guide to get you started with Vite + Bun. For more information, see the [Vite documentation](https://vitejs.dev/guide/).
diff --git a/docs/guides/http/fetch.md b/docs/guides/http/fetch.md
new file mode 100644
index 00000000000000..7b1c0fb8df6287
--- /dev/null
+++ b/docs/guides/http/fetch.md
@@ -0,0 +1,24 @@
+---
+name: Send an HTTP request using fetch
+---
+
+Bun implements the Web-standard [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API for sending HTTP requests. To send a simple `GET` request to a URL:
+
+```ts
+const response = await fetch("https://bun.sh");
+const html = await response.text(); // HTML string
+```
+
+---
+
+To send a `POST` request to an API endpoint.
+
+```ts
+const response = await fetch("https://bun.sh/api", {
+ method: "POST",
+ body: JSON.stringify({ message: "Hello from Bun!" }),
+ headers: { "Content-Type": "application/json" },
+});
+
+const body = await response.json();
+```
diff --git a/docs/guides/http/file-uploads.md b/docs/guides/http/file-uploads.md
new file mode 100644
index 00000000000000..a708a238a77e45
--- /dev/null
+++ b/docs/guides/http/file-uploads.md
@@ -0,0 +1,94 @@
+---
+name: Upload files via HTTP using FormData
+---
+
+To upload files via HTTP with Bun, use the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API. Let's start with a HTTP server that serves a simple HTML web form.
+
+```ts#index.ts
+const server = Bun.serve({
+ port: 4000,
+ async fetch(req) {
+ const url = new URL(req.url);
+
+ // return index.html for root path
+ if (url.pathname === "/")
+ return new Response(Bun.file("index.html"), {
+ headers: {
+ "Content-Type": "text/html",
+ },
+ });
+
+ return new Response("Not Found", { status: 404 });
+ },
+});
+
+console.log(`Listening on http://localhost:${server.port}`);
+```
+
+---
+
+We can define our HTML form in another file, `index.html`.
+
+```html#index.html
+
+
+
+
+ Form
+
+
+
+
+
+```
+
+---
+
+At this point, we can run the server and visit [`localhost:4000`](http://localhost:4000) to see our form.
+
+```bash
+$ bun run index.ts
+Listening on http://localhost:4000
+```
+
+---
+
+Our form will send a `POST` request to the `/action` endpoint with the form data. Let's handle that request in our server.
+
+First we use the [`.formData()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/formData) method on the incoming `Request` to asynchonously parse its contents to a `FormData` instance. Then we can use the [`.get()`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/get) method to extract the value of the `name` and `profilePicture` fields. Here `name` corresponds to a `string` and `profilePicture` is a `Blob`.
+
+Finally, we write the `Blob` to disk using [`Bun.write()`](/docs/api/file-io#writing-files-bun-write).
+
+```ts-diff#index.ts
+const server = Bun.serve({
+ port: 4000,
+ async fetch(req) {
+ const url = new URL(req.url);
+
+ // return index.html for root path
+ if (url.pathname === "/")
+ return new Response(Bun.file("index.html"), {
+ headers: {
+ "Content-Type": "text/html",
+ },
+ });
+
++ // parse formdata at /action
++ if (url.pathname === '/action') {
++ const formdata = await req.formData();
++ const name = formdata.get('name');
++ const profilePicture = formdata.get('profilePicture');+
++ if (!profilePicture) throw new Error('Must upload a profile picture.');
++ // write profilePicture to disk
++ await Bun.write('profilePicture.png', profilePicture);
++ return new Response("Success");
++ }
+
+ return new Response("Not Found", { status: 404 });
+ },
+});
+```
diff --git a/docs/guides/http/hot.md b/docs/guides/http/hot.md
new file mode 100644
index 00000000000000..c033e5be5c7b90
--- /dev/null
+++ b/docs/guides/http/hot.md
@@ -0,0 +1,55 @@
+---
+name: Hot reload an HTTP server
+---
+
+Bun supports the [`--hot`](/docs/runtime/hot#hot-mode) flag to run a file with hot reloading enabled. When any module or file changes, Bun re-runs the file.
+
+```sh
+bun --hot run index.ts
+```
+
+---
+
+To avoid re-running `Bun.serve()` during `--hot` reloads, you should assign the `Server` instance as a property of `globalThis`. The `globalThis` object survives hot reloads.
+
+```ts
+import { type Serve, type Server } from "bun";
+
+// make TypeScript happy
+declare global {
+ var server: Server;
+}
+
+// define server parameters
+const serveOptions: Serve = {
+ port: 3000,
+ fetch(req) {
+ return new Response(`Hello world`);
+ },
+};
+
+if (!globalThis.server) {
+ globalThis.server = Bun.serve(serveOptions);
+} else {
+ globalThis.server.reload(serveOptions);
+}
+```
+
+---
+
+To avoid manually calling `server.reload()`, you can use start a server with Bun's [object syntax](/docs/runtime/hot#http-servers). If you `export default` a plain object with a `fetch` handler defined, then run this file with Bun, Bun will start an HTTP server as if you'd passed this object into `Bun.serve()`.
+
+With this approach, Bun automatically reloads the server when reloads happen.
+
+See [HTTP > Hot Reloading](<[/docs/api/http](https://bun.sh/docs/api/http#hot-reloading)>) for full docs.
+
+```ts
+import { type Serve } from "bun";
+
+export default {
+ port: 3000,
+ fetch(req) {
+ return new Response(`Hello world`);
+ },
+} satisfies Serve;
+```
diff --git a/docs/guides/http/index.json b/docs/guides/http/index.json
new file mode 100644
index 00000000000000..d018e1bdd3ede9
--- /dev/null
+++ b/docs/guides/http/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "HTTP",
+ "description": "A collection of guides for building HTTP servers with Bun"
+}
diff --git a/docs/guides/http/simple.md b/docs/guides/http/simple.md
new file mode 100644
index 00000000000000..be5147541def6d
--- /dev/null
+++ b/docs/guides/http/simple.md
@@ -0,0 +1,18 @@
+---
+name: Write a simple HTTP server
+---
+
+This starts an HTTP server listening on port `3000`. It responds to all requests with a `Response` with status `200` and body `"Welcome to Bun!"`.
+
+See [`Bun.serve`](/docs/api/http) for details.
+
+```ts
+const server = Bun.serve({
+ port: 3000,
+ fetch(request) {
+ return new Response("Welcome to Bun!");
+ },
+});
+
+console.log(`Listening on localhost:\${server.port}`);
+```
diff --git a/docs/guides/http/stream-file.md b/docs/guides/http/stream-file.md
new file mode 100644
index 00000000000000..ab16acf4257a5a
--- /dev/null
+++ b/docs/guides/http/stream-file.md
@@ -0,0 +1,48 @@
+---
+name: Stream a file as an HTTP Response
+---
+
+This snippet reads a file from disk using [`Bun.file()`](/docs/api/file-io#reading-files-bun-file). This returns a `BunFile` instance, which can be passed directly into the `new Response` constructor.
+
+```ts
+const path = "/path/to/file.txt";
+const file = Bun.file(path);
+const resp = new Response(file);
+```
+
+---
+
+The `Content-Type` is read from the file and automatically set on the `Response`.
+
+```ts
+new Response(Bun.file("./package.json")).headers.get("Content-Type");
+// => application/json;charset=utf-8
+
+new Response(Bun.file("./test.txt")).headers.get("Content-Type");
+// => text/plain;charset=utf-8
+
+new Response(Bun.file("./index.tsx")).headers.get("Content-Type");
+// => text/javascript;charset=utf-8
+
+new Response(Bun.file("./img.png")).headers.get("Content-Type");
+// => image/png
+```
+
+---
+
+Putting it all together with [`Bun.serve()`](/docs/api/http#bun-serve).
+
+```ts
+// static file server
+Bun.serve({
+ async fetch(req) {
+ const path = new URL(req.url).pathname;
+ const file = Bun.file(path);
+ return new Response(file);
+ },
+});
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/http/tls.md b/docs/guides/http/tls.md
new file mode 100644
index 00000000000000..a7e59dfea90b0c
--- /dev/null
+++ b/docs/guides/http/tls.md
@@ -0,0 +1,30 @@
+---
+name: Configure TLS on an HTTP server
+---
+
+Set the `tls` key to configure TLS. Both `key` and `cert` are required. The `key` should be the contents of your private key; `cert` should be the contents of your issued certificate. Use [`Bun.file()`](/docs/api/file-io#reading-files-bun-file) to read the contents.
+
+```ts
+const server = Bun.serve({
+ fetch: (request) => new Response("Welcome to Bun!"),
+ tls: {
+ cert: Bun.file("cert.pem"),
+ key: Bun.file("key.pem"),
+ },
+});
+```
+
+---
+
+By default Bun trusts the default Mozilla-curated list of well-known root CAs. To override this list, pass an array of certificates as `ca`.
+
+```ts
+const server = Bun.serve({
+ fetch: (request) => new Response("Welcome to Bun!"),
+ tls: {
+ cert: Bun.file("cert.pem"),
+ key: Bun.file("key.pem"),
+ ca: [Bun.file("ca1.pem"), Bun.file("ca2.pem")],
+ },
+});
+```
diff --git a/docs/guides/install/add-dev.md b/docs/guides/install/add-dev.md
new file mode 100644
index 00000000000000..3f7b74f9c73bd9
--- /dev/null
+++ b/docs/guides/install/add-dev.md
@@ -0,0 +1,26 @@
+---
+name: Add a development dependency
+---
+
+To add an npm package as a development dependency, use `bun add --development`.
+
+```sh
+$ bun add zod --dev
+$ bun add zod -d # shorthand
+```
+
+---
+
+This will add the package to `devDependencies` in `package.json`.
+
+```json-diff
+{
+ "devDependencies": {
++ "zod": "^3.0.0"
+ }
+}
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/add-git.md b/docs/guides/install/add-git.md
new file mode 100644
index 00000000000000..c98bc29a854ce8
--- /dev/null
+++ b/docs/guides/install/add-git.md
@@ -0,0 +1,36 @@
+---
+name: Add a Git dependency
+---
+
+Bun supports directly adding GitHub repositories as dependencies of your project.
+
+```sh
+$ bun add github:lodash/lodash
+```
+
+---
+
+This will add the following line to your `package.json`:
+
+```json-diff#package.json
+{
+ "dependencies": {
++ "lodash": "github:lodash/lodash"
+ }
+}
+```
+
+---
+
+Bun supports a number of protocols for specifying Git dependencies.
+
+```sh
+$ bun add git+https://github.com/lodash/lodash.git
+$ bun add git+ssh://github.com/lodash/lodash.git#4.17.21
+$ bun add git@github.com:lodash/lodash.git
+$ bun add github:colinhacks/zod
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/add-optional.md b/docs/guides/install/add-optional.md
new file mode 100644
index 00000000000000..6d02c23e20708a
--- /dev/null
+++ b/docs/guides/install/add-optional.md
@@ -0,0 +1,25 @@
+---
+name: Add an optional dependency
+---
+
+To add an npm package as a peer dependency, use the `--optional` flag.
+
+```sh
+$ bun add zod --optional
+```
+
+---
+
+This will add the package to `optionalDependencies` in `package.json`.
+
+```json-diff
+{
+ "optionalDependencies": {
++ "zod": "^3.0.0"
+ }
+}
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/add-peer.md b/docs/guides/install/add-peer.md
new file mode 100644
index 00000000000000..78d5c86b358503
--- /dev/null
+++ b/docs/guides/install/add-peer.md
@@ -0,0 +1,17 @@
+---
+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.
+
+```json-diff
+{
+ "peerDependencies": {
++ "zod": "^3.0.0"
+ }
+}
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/add-tarball.md b/docs/guides/install/add-tarball.md
new file mode 100644
index 00000000000000..f09dbbbfa50d72
--- /dev/null
+++ b/docs/guides/install/add-tarball.md
@@ -0,0 +1,33 @@
+---
+name: Add a tarball dependency
+---
+
+Bun's package manager can install any publicly available tarball URL as a dependency of your project.
+
+```sh
+$ bun add zod@https://registry.npmjs.org/zod/-/zod-3.21.4.tgz
+```
+
+---
+
+Running this command will download, extract, and install the tarball to your project's `node_modules` directory. It will also add the following line to your `package.json`:
+
+```json-diff#package.json
+{
+ "dependencies": {
++ "zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
+ }
+}
+```
+
+---
+
+The package `"zod"` can now be imported as usual.
+
+```ts
+import { z } from "zod";
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/add.md b/docs/guides/install/add.md
new file mode 100644
index 00000000000000..dfb88e5e46b43a
--- /dev/null
+++ b/docs/guides/install/add.md
@@ -0,0 +1,42 @@
+---
+name: Add a dependency
+---
+
+To add an npm package as a dependency, use `bun add`.
+
+```sh
+$ bun add zod
+```
+
+---
+
+This will add the package to `dependencies` in `package.json`. By default, the `^` range specifier will be used, to indicate that any future minor or patch versions are acceptable.
+
+```json-diff
+{
+ "dependencies": {
++ "zod": "^3.0.0"
+ }
+}
+```
+
+---
+
+To "pin" to the `latest` version of the package, use `--exact`. This will add the package to `dependencies` without the `^`, pinning your project to the exact version you installed.
+
+```sh
+$ bun add zod --exact
+```
+
+---
+
+To specify an exact version or a tag:
+
+```sh
+$ bun add zod@3.0.0
+$ bun add zod@next
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/cicd.md b/docs/guides/install/cicd.md
new file mode 100644
index 00000000000000..4be29925d41ecb
--- /dev/null
+++ b/docs/guides/install/cicd.md
@@ -0,0 +1,41 @@
+---
+name: Install dependencies with Bun in GitHub Actions
+---
+
+Use the official [`setup-bun`](https://github.com/oven-sh/setup-bun) GitHub Action to install `bun` in your GitHub Actions runner.
+
+```yaml-diff#workflow.yml
+name: my-workflow
+jobs:
+ my-job:
+ name: my-job
+ runs-on: ubuntu-latest
+ steps:
+ # ...
+ - uses: actions/checkout@v3
++ - uses: oven-sh/setup-bun@v1
+
+ # run any `bun` or `bunx` command
++ - run: bun install
+```
+
+---
+
+To specify a version of Bun to install:
+
+```yaml-diff#workflow.yml
+name: my-workflow
+jobs:
+ my-job:
+ name: my-job
+ runs-on: ubuntu-latest
+ steps:
+ # ...
+ - uses: oven-sh/setup-bun@v1
++ with:
++ version: 0.7.0 # or "canary"
+```
+
+---
+
+Refer to the [README.md](https://github.com/oven-sh/setup-bun) for complete documentation of the `setup-bun` GitHub Action.
diff --git a/docs/guides/install/custom-registry.md b/docs/guides/install/custom-registry.md
new file mode 100644
index 00000000000000..64b3cf76b6c9a9
--- /dev/null
+++ b/docs/guides/install/custom-registry.md
@@ -0,0 +1,30 @@
+---
+name: Override the default npm registry for bun install
+---
+
+The default registry is `registry.npmjs.org`. This can be globally configured in `bunfig.toml`.
+
+```toml#bunfig.toml
+[install]
+# set default registry as a string
+registry = "https://registry.npmjs.org"
+
+# if needed, set a token
+registry = { url = "https://registry.npmjs.org", token = "123456" }
+
+# if needed, set a username/password
+registry = "https://username:password@registry.npmjs.org"
+```
+
+---
+
+Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/cli/run#environment-variables) for more information.
+
+```toml#bunfig.toml
+[install]
+registry = { url = "https://registry.npmjs.org", token = "$npm_token" }
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/index.json b/docs/guides/install/index.json
new file mode 100644
index 00000000000000..017ef2845d76bc
--- /dev/null
+++ b/docs/guides/install/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Package manager",
+ "description": "A collection of guides for managing dependencies with Bun's package manager"
+}
diff --git a/docs/guides/install/npm-alias.md b/docs/guides/install/npm-alias.md
new file mode 100644
index 00000000000000..0b38d8c71605e7
--- /dev/null
+++ b/docs/guides/install/npm-alias.md
@@ -0,0 +1,23 @@
+---
+name: Install a package under a different name
+---
+
+To install an npm package under an alias:
+
+```sh
+$ bun add my-custom-name@npm:zod
+```
+
+---
+
+The `zod` package can now be imported as `my-custom-name`.
+
+```ts
+import { z } from "my-custom-name";
+
+z.string();
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/registry-scope.md b/docs/guides/install/registry-scope.md
new file mode 100644
index 00000000000000..48f7dee79a1695
--- /dev/null
+++ b/docs/guides/install/registry-scope.md
@@ -0,0 +1,32 @@
+---
+name: Configure a private registry for an organization scope with bun install
+---
+
+Bun does not read `.npmrc` files; instead private registries are configured via `bunfig.toml`. To configure a registry for a particular npm scope:
+
+```toml#bunfig.toml
+[install.scopes]
+# as a string
+"@myorg1" = "https://username:password@registry.myorg.com/"
+
+# as an object with username/password
+# you can reference environment variables
+"@myorg2" = { username = "myusername", password = "$npm_pass", url = "https://registry.myorg.com/" }
+
+# as an object with token
+"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
+
+```
+
+---
+
+Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/cli/run#environment-variables) for more information.
+
+```toml#bunfig.toml
+[install.scopes]
+"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/workspaces.md b/docs/guides/install/workspaces.md
new file mode 100644
index 00000000000000..7c359b28554470
--- /dev/null
+++ b/docs/guides/install/workspaces.md
@@ -0,0 +1,68 @@
+---
+name: Configuring a monorepo using workspaces
+---
+
+Bun's package manager supports npm `"workspaces"`. This allows you to split a codebase into multiple distinct "packages" that live in the same repository, can depend on each other, and (when possible) share a `node_modules` directory.
+
+---
+
+The root `package.json` should not contain any `"dependencies"`, `"devDependencies"`, etc. Each individual package should be self-contained and declare its own dependencies. Similarly, it's conventional to declare `"private": true` to avoid accidentally publishing the root package to `npm`.
+
+```json#package.json
+{
+ "name": "my-monorepo",
+ "private": true,
+ "workspaces": [
+ "packages/*"
+ ]
+}
+```
+
+---
+
+It's common to place all packages in a `packages` directory. The `"workspaces"` field in package.json supports glob patterns, so you can use `packages/*` to indicate that each subdirectory of `packages` should be considered separate _package_ (also known as a workspace).
+
+```txt
+.
+├── package.json
+├── node_modules
+└── packages
+ ├── stuff-a
+ │ └── package.json
+ └── stuff-b
+ └── package.json
+```
+
+---
+
+To add one workspace as a dependency of another, modify its `package.json`. Here were adding `stuff-a` as a dependency of `stuff-b`.
+
+```json#packages/stuff-b/package.json
+{
+ "name": "stuff-b",
+ "dependencies": {
++ "stuff-a": "*"
+ }
+}
+```
+
+---
+
+Once added, run `bun install` from the project root to install dependencies for all workspaces.
+
+```sh
+$ bun install
+```
+
+---
+
+To add npm dependencies to a particular workspace, just `cd` to the appropriate directory and run `bun add` commands as you would normally. Bun will detect that you are in a workspace and hoist the dependency as needed.
+
+```sh
+$ cd packages/stuff-a
+$ bun add zod
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/install/yarnlock.md b/docs/guides/install/yarnlock.md
new file mode 100644
index 00000000000000..898df634d87b5b
--- /dev/null
+++ b/docs/guides/install/yarnlock.md
@@ -0,0 +1,42 @@
+---
+name: Generate a human-readable lockfile
+---
+
+By default Bun generates a binary `bun.lockb` file when you run `bun install`. In some cases, it's preferable to generate a human-readable lockfile instead.
+
+---
+
+Use the `--yarn` flag to generate a Yarn-compatible `yarn.lock` file (in addition to `bun.lockb`).
+
+```sh
+$ bun install --yarn
+```
+
+---
+
+To set this as the default behavior, add the following to your `bunfig.toml` file.
+
+```toml#bunfig.toml
+[install]
+print = "yarn"
+```
+
+---
+
+To print a Yarn lockfile to your console without writing it to disk, just "run" your `bun.lockb` with `bun`.
+
+```sh
+$ bun bun.lockb
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+# bun ./bun.lockb --hash: 9BFBF11D86084AAB-9418b03ff880c569-390CE6459EACEC9A...
+
+abab@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz"
+ integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvH...
+```
+
+---
+
+See [Docs > Package manager](/docs/cli/install) for complete documentation of Bun's package manager.
diff --git a/docs/guides/process/argv.md b/docs/guides/process/argv.md
new file mode 100644
index 00000000000000..f9f3c77e4865a1
--- /dev/null
+++ b/docs/guides/process/argv.md
@@ -0,0 +1,22 @@
+---
+name: Parse command-line arguments
+---
+
+The _argument vector_ is the list of arguments passed to the program when it is run. It is available as `Bun.argv`.
+
+```ts#cli.ts
+console.log(Bun.argv);
+```
+
+---
+
+Running this file with arguments results in the following:
+
+```sh
+$ bun run cli.tsx --flag1 --flag2 value
+[ '/path/to/bun', '/path/to/cli.ts', '--flag1', '--flag2', 'value' ]
+```
+
+---
+
+To parse `argv` into a more useful format, consider using [minimist](https://github.com/minimistjs/minimist) or [commander](https://github.com/tj/commander.js).
diff --git a/docs/guides/process/ctrl-c.md b/docs/guides/process/ctrl-c.md
new file mode 100644
index 00000000000000..b880cf62c03c04
--- /dev/null
+++ b/docs/guides/process/ctrl-c.md
@@ -0,0 +1,16 @@
+---
+name: Listen for CTRL+C
+---
+
+The `ctrl+c` shortcut sends an _interrupt signal_ to the running process. This signal can be intercepted by listening for the `SIGINT` event. If you want to close the process, you must explicitly call `process.exit()`.
+
+```ts
+process.on("SIGINT", () => {
+ console.log("Ctrl-C was pressed");
+ process.exit();
+});
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/process/index.json b/docs/guides/process/index.json
new file mode 100644
index 00000000000000..df0384544b2864
--- /dev/null
+++ b/docs/guides/process/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Processes",
+ "description": "A collection of guides for inspecting the current process and creating child processes with Bun"
+}
diff --git a/docs/guides/process/nanoseconds.md b/docs/guides/process/nanoseconds.md
new file mode 100644
index 00000000000000..b8aee81235d6a2
--- /dev/null
+++ b/docs/guides/process/nanoseconds.md
@@ -0,0 +1,13 @@
+---
+name: Get the process uptime in nanoseconds
+---
+
+Use `Bun.nanoseconds()` to get the total number of nanoseconds the `bun` process has been alive.
+
+```ts
+Bun.nanoseconds();
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/process/os-signals.md b/docs/guides/process/os-signals.md
new file mode 100644
index 00000000000000..ae7b9896fc109a
--- /dev/null
+++ b/docs/guides/process/os-signals.md
@@ -0,0 +1,39 @@
+---
+name: Listen to OS signals
+---
+
+Bun supports the Node.js `process` global, including the `process.on()` method for listening to OS signals.
+
+```ts
+process.on("SIGINT", () => {
+ console.log("Received SIGINT");
+});
+```
+
+---
+
+If you don't know which signal to listen for, you listen to the umbrella `"exit"` event.
+
+```ts
+process.on("exit", (code) => {
+ console.log(`Process exited with code ${code}`);
+});
+```
+
+---
+
+If you don't know which signal to listen for, you listen to the [`"beforeExit"`](https://nodejs.org/api/process.html#event-beforeexit) and [`"exit"`](https://nodejs.org/api/process.html#event-exit) events.
+
+```ts
+process.on("beforeExit", (code) => {
+ console.log(`Event loop is empty!`);
+});
+
+process.on("exit", (code) => {
+ console.log(`Process is exiting with code ${code}`);
+});
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/process/spawn-stderr.md b/docs/guides/process/spawn-stderr.md
new file mode 100644
index 00000000000000..9e9e8da99be30e
--- /dev/null
+++ b/docs/guides/process/spawn-stderr.md
@@ -0,0 +1,31 @@
+---
+name: Read stderr from a child process
+---
+
+When using [`Bun.spawn()`](/docs/api/spawn), the child process inherits the `stderr` of the spawning process. If instead you'd prefer to read and handle `stderr`, set the `stderr` option to `"pipe"`.
+
+```ts
+const proc = Bun.spawn(["echo", "hello"], {
+ stderr: "pipe",
+});
+proc.stderr; // => ReadableStream
+```
+
+---
+
+To read `stderr` until the child process exits, use the [`Bun.readableStreamToText()`](/docs/api/utils#bun-readablestreamto) convenience function.
+
+```ts
+const proc = Bun.spawn(["echo", "hello"], {
+ stderr: "pipe",
+});
+
+const errors: string = await Bun.readableStreamToText(proc.stderr);
+if (errors) {
+ // handle errors
+}
+```
+
+---
+
+See [Docs > API > Child processes](/docs/api/spawn) for complete documentation.
diff --git a/docs/guides/process/spawn-stdout.md b/docs/guides/process/spawn-stdout.md
new file mode 100644
index 00000000000000..e73fe59a0eb6ad
--- /dev/null
+++ b/docs/guides/process/spawn-stdout.md
@@ -0,0 +1,26 @@
+---
+name: Read stdout from a child process
+---
+
+When using [`Bun.spawn()`](/docs/api/spawn), the `stdout` of the child process can be consumed as a `ReadableStream` via `proc.stdout`.
+
+```ts
+const proc = Bun.spawn(["echo", "hello"]);
+
+const output = await new Response(proc.stdout).text();
+output; // => "hello"
+```
+
+---
+
+To instead pipe the `stdout` of the child process to `stdout` of the parent process, set "inherit".
+
+```ts
+const proc = Bun.spawn(["echo", "hello"], {
+ stdout: "inherit",
+});
+```
+
+---
+
+See [Docs > API > Child processes](/docs/api/spawn) for complete documentation.
diff --git a/docs/guides/process/spawn.md b/docs/guides/process/spawn.md
new file mode 100644
index 00000000000000..f0fca8e8abe3e5
--- /dev/null
+++ b/docs/guides/process/spawn.md
@@ -0,0 +1,41 @@
+---
+name: Spawn a child process
+---
+
+Use [`Bun.spawn()`](/docs/api/spawn) to spawn a child process.
+
+```ts
+const proc = Bun.spawn(["echo", "hello"]);
+
+// await completion
+await proc.exited;
+```
+
+---
+
+The second argument accepts a configuration object.
+
+```ts
+const proc = Bun.spawn("echo", ["Hello, world!"], {
+ cwd: "/tmp",
+ env: { FOO: "bar" },
+ onExit(proc, exitCode, signalCode, error) {
+ // exit handler
+ },
+});
+```
+
+---
+
+By default, the `stdout` of the child process can be consumed as a `ReadableStream` using `proc.stdout`.
+
+```ts
+const proc = Bun.spawn(["echo", "hello"]);
+
+const output = await new Response(proc.stdout).text();
+output; // => "hello"
+```
+
+---
+
+See [Docs > API > Child processes](/docs/api/spawn) for complete documentation.
diff --git a/docs/guides/process/stdin.md b/docs/guides/process/stdin.md
new file mode 100644
index 00000000000000..c19c9e1065390a
--- /dev/null
+++ b/docs/guides/process/stdin.md
@@ -0,0 +1,54 @@
+---
+name: Read from stdin
+---
+
+For CLI tools, it's often useful to read from `stdin`. In Bun, the `console` object is an `AsyncIterable` that yields lines from `stdin`.
+
+```ts#index.ts
+const prompt = "Type something: ";
+process.stdout.write(prompt);
+for await (const line of console) {
+ console.log(`You typed: ${line}`);
+ process.stdout.write(prompt);
+}
+```
+
+---
+
+Running this file results in a never-ending interactive prompt that echoes whatever the user types.
+
+```sh
+$ bun run index.tsx
+Type something: hello
+You typed: hello
+Type something: hello again
+You typed: hello again
+```
+
+---
+
+Bun also exposes stdin as a `BunFile` via `Bun.stdin`. This is useful for incrementally reading large inputs that are piped into the `bun` process.
+
+There is no guarantee that the chunks will be split line-by-line.
+
+```ts#stdin.ts
+for await (const chunk of Bun.stdin.stream()) {
+ // chunk is Uint8Array
+ // this converts it to text (assumes ASCII encoding)
+ const chunkText = Buffer.from(chunk).toString();
+ console.log(`Chunk: ${chunkText}`);
+}
+```
+
+---
+
+This will print the input that is piped into the `bun` process.
+
+```sh
+$ echo "hello" | bun run stdin.ts
+Chunk: hello
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/read-file/arraybuffer.md b/docs/guides/read-file/arraybuffer.md
new file mode 100644
index 00000000000000..149b08d8eb0a30
--- /dev/null
+++ b/docs/guides/read-file/arraybuffer.md
@@ -0,0 +1,28 @@
+---
+name: Read a file to an ArrayBuffer
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. Use `.arrayBuffer()` to read the file as an `ArrayBuffer`.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+const buffer = await file.arrayBuffer();
+```
+
+---
+
+The binary content in the `ArrayBuffer` can then be read as a typed array, such as `Uint8Array`.
+
+```ts
+const buffer = await file.arrayBuffer();
+const bytes = new Uint8Array(buffer);
+
+bytes[0];
+bytes.length;
+```
+
+---
+
+Refer to the [Typed arrays](/docs/api/binary-data#typedarray) docs for more information on working with typed arrays in Bun.
diff --git a/docs/guides/read-file/buffer.md b/docs/guides/read-file/buffer.md
new file mode 100644
index 00000000000000..d27fa14894d7eb
--- /dev/null
+++ b/docs/guides/read-file/buffer.md
@@ -0,0 +1,19 @@
+---
+name: Read a file to a Buffer
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats.
+
+To read the file into a `Buffer` instance, first use `.arrayBuffer()` to consume the file as an `ArrayBuffer`, then use `Buffer.from()` to create a `Buffer` from the `ArrayBuffer`.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+const arrbuf = await file.arrayBuffer();
+const buffer = Buffer.from(arrbuf);
+```
+
+---
+
+Refer to [Binary data > Buffer](/docs/api/binary-data#buffer) for more information on working with `Buffer` and other binary data formats in Bun.
diff --git a/docs/guides/read-file/exists.md b/docs/guides/read-file/exists.md
new file mode 100644
index 00000000000000..fd6cbbf9a418d8
--- /dev/null
+++ b/docs/guides/read-file/exists.md
@@ -0,0 +1,16 @@
+---
+name: Check if a file exists
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. Use the `.exists()` method to check if a file exists at the given path.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+file.exists(); // boolean;
+```
+
+---
+
+Refer to [API > File I/O](/docs/api/file-io) for more information on working with `BunFile`.
diff --git a/docs/guides/read-file/index.json b/docs/guides/read-file/index.json
new file mode 100644
index 00000000000000..321fd96e29c024
--- /dev/null
+++ b/docs/guides/read-file/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Reading files",
+ "description": "A collection of guides for reading files with Bun"
+}
diff --git a/docs/guides/read-file/json.md b/docs/guides/read-file/json.md
new file mode 100644
index 00000000000000..e14fd560af3d0e
--- /dev/null
+++ b/docs/guides/read-file/json.md
@@ -0,0 +1,17 @@
+---
+name: Read a JSON file
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. Use `.json()` to read and parse the contents of a `.json` file as a plain object.
+
+The MIME type of the `BunFile` will be set accordingly.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+const contents = await file.json();
+// { name: "my-package" }
+
+file.type; // => "application/json;charset=utf-8";
+```
diff --git a/docs/guides/read-file/mime.md b/docs/guides/read-file/mime.md
new file mode 100644
index 00000000000000..44a8e686072bb2
--- /dev/null
+++ b/docs/guides/read-file/mime.md
@@ -0,0 +1,20 @@
+---
+name: Get the MIME type of a file
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob`, so use the `.type` property to read the MIME type.
+
+```ts
+const file = Bun.file("./package.json");
+file.type; // application/json
+
+const file = Bun.file("./index.html");
+file.type; // text/html
+
+const file = Bun.file("./image.png");
+file.type; // image/png
+```
+
+---
+
+Refer to [API > File I/O](/docs/api/file-io) for more information on working with `BunFile`.
diff --git a/docs/guides/read-file/stream.md b/docs/guides/read-file/stream.md
new file mode 100644
index 00000000000000..ac4bd9e2f12c0e
--- /dev/null
+++ b/docs/guides/read-file/stream.md
@@ -0,0 +1,26 @@
+---
+name: Read a file as a ReadableStream
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. Use `.stream()` to consume the file incrementally as a `ReadableStream`.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+const stream = await file.stream();
+```
+
+---
+
+The chunks of the stream can be consumed as an [async iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols) using `for await`.
+
+```ts
+for await (const chunk of stream) {
+ chunk; // => Uint8Array
+}
+```
+
+---
+
+Refer to the [Streams](/docs/api/streams) documentation for more information on working with streams in Bun.
diff --git a/docs/guides/read-file/string.md b/docs/guides/read-file/string.md
new file mode 100644
index 00000000000000..08cdfd95228ee0
--- /dev/null
+++ b/docs/guides/read-file/string.md
@@ -0,0 +1,22 @@
+---
+name: Read a file as a string
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. Use `.text()` to read the contents as a string.
+
+```ts
+const path = "/path/to/file.txt";
+const file = Bun.file(path);
+
+const text = await file.text();
+// string
+```
+
+---
+
+Any relative paths will be resolved relative to the project root (the nearest directory containing a `package.json` file).
+
+```ts
+const path = "./file.txt";
+const file = Bun.file(path);
+```
diff --git a/docs/guides/read-file/uint8array.md b/docs/guides/read-file/uint8array.md
new file mode 100644
index 00000000000000..1afcaa79711f98
--- /dev/null
+++ b/docs/guides/read-file/uint8array.md
@@ -0,0 +1,22 @@
+---
+name: Read a file to a Uint8Array
+---
+
+The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats.
+
+To read the file into a `Uint8Array` instance, retrieve the contents of the `BunFile` as an `ArrayBuffer` with `.arrayBuffer()`, then pass it into the `Uint8Array` constructor.
+
+```ts
+const path = "/path/to/package.json";
+const file = Bun.file(path);
+
+const arrBuffer = await file.arrayBuffer();
+const byteArray = new Uint8Array(arrBuffer);
+
+byteArray[0]; // first byteArray
+byteArray.length; // length of byteArray
+```
+
+---
+
+Refer to [API > Binary data > Typed arrays](/docs/api/binary-data#typedarray) for more information on working with `Uint8Array` and other binary data formats in Bun.
diff --git a/docs/guides/read-file/watch.md b/docs/guides/read-file/watch.md
new file mode 100644
index 00000000000000..0c38a0ecef09db
--- /dev/null
+++ b/docs/guides/read-file/watch.md
@@ -0,0 +1,68 @@
+---
+name: Watch a directory for changes
+---
+
+Bun implements the `node:fs` module, including the `fs.watch` function for listening for file system changes.
+
+This code block listens for changes to files in the current directory. By default this operation is _shallow_, meaning that changes to files in subdirectories will not be detected.
+
+```ts
+import { watch } from "fs";
+
+const watcher = watch(import.meta.dir, (event, filename) => {
+ console.log(`Detected ${event} in ${filename}`);
+});
+```
+
+---
+
+To listen to changes in subdirectories, pass the `recursive: true` option to `fs.watch`.
+
+```ts
+import { watch } from "fs";
+
+const watcher = watch(
+ import.meta.dir,
+ { recursive: true },
+ (event, filename) => {
+ console.log(`Detected ${event} in ${filename}`);
+ },
+);
+```
+
+---
+
+Using the `node:fs/promises` module, you can listen for changes using `for await...of` instead of a callback.
+
+```ts
+import { watch } from "fs/promises";
+
+const watcher = watch(import.meta.dir);
+for await (const event of watcher) {
+ console.log(`Detected ${event.eventType} in ${event.filename}`);
+}
+```
+
+---
+
+To stop listening for changes, call `watcher.close()`. It's common to do this when the process receives a `SIGINT` signal, such as when the user presses Ctrl-C.
+
+```ts
+import { watch } from "fs";
+
+const watcher = watch(import.meta.dir, (event, filename) => {
+ console.log(`Detected ${event} in ${filename}`);
+});
+
+process.on("SIGINT", () => {
+ // close watcher when Ctrl-C is pressed
+ console.log("Closing watcher...");
+ watcher.close();
+
+ process.exit(0);
+});
+```
+
+---
+
+Refer to [API > Binary data > Typed arrays](/docs/api/binary-data#typedarray) for more information on working with `Uint8Array` and other binary data formats in Bun.
diff --git a/docs/guides/runtime/cicd.md b/docs/guides/runtime/cicd.md
new file mode 100644
index 00000000000000..6dfef2ddd8ef99
--- /dev/null
+++ b/docs/guides/runtime/cicd.md
@@ -0,0 +1,43 @@
+---
+name: Install and run Bun in GitHub Actions
+---
+
+Use the official [`setup-bun`](https://github.com/oven-sh/setup-bun) GitHub Action to install `bun` in your GitHub Actions runner.
+
+```yaml-diff#workflow.yml
+name: my-workflow
+jobs:
+ my-job:
+ name: my-job
+ runs-on: ubuntu-latest
+ steps:
+ # ...
+ - uses: actions/checkout@v3
++ - uses: oven-sh/setup-bun@v1
+
+ # run any `bun` or `bunx` command
++ - run: bun install
++ - run: bun index.ts
++ - run: bun run build
+```
+
+---
+
+To specify a version of Bun to install:
+
+```yaml-diff#workflow.yml
+name: my-workflow
+jobs:
+ my-job:
+ name: my-job
+ runs-on: ubuntu-latest
+ steps:
+ # ...
+ - uses: oven-sh/setup-bun@v1
++ with:
++ version: 0.7.0 # or "canary"
+```
+
+---
+
+Refer to the [README.md](https://github.com/oven-sh/setup-bun) for complete documentation of the `setup-bun` GitHub Action.
diff --git a/docs/guides/runtime/import-json.md b/docs/guides/runtime/import-json.md
new file mode 100644
index 00000000000000..3db2daaea1c331
--- /dev/null
+++ b/docs/guides/runtime/import-json.md
@@ -0,0 +1,32 @@
+---
+name: Import a JSON file
+---
+
+Bun natively supports `.json` imports.
+
+```json#package.json
+{
+ "name": "bun",
+ "version": "1.0.0",
+ "author": {
+ "name": "John Dough",
+ "email": "john@dough.com"
+ }
+}
+```
+
+---
+
+Import the file like any other source file.
+
+```ts
+import data from "./package.json";
+
+data.name; // => "bun"
+data.version; // => "1.0.0"
+data.author.name; // => "John Dough"
+```
+
+---
+
+See [Docs > Runtime > TypeScript](/docs/runtime/typescript) for more information on using TypeScript with Bun.
diff --git a/docs/guides/runtime/import-toml.md b/docs/guides/runtime/import-toml.md
new file mode 100644
index 00000000000000..2a2e47aa49cc3c
--- /dev/null
+++ b/docs/guides/runtime/import-toml.md
@@ -0,0 +1,30 @@
+---
+name: Import a TOML file
+---
+
+Bun natively supports importing `.toml` files.
+
+```toml#data.toml
+name = "bun"
+version = "1.0.0"
+
+[author]
+name = "John Dough"
+email = "john@dough.com"
+```
+
+---
+
+Import the file like any other source file.
+
+```ts
+import data from "./data.toml";
+
+data.name; // => "bun"
+data.version; // => "1.0.0"
+data.author.name; // => "John Dough"
+```
+
+---
+
+See [Docs > Runtime > TypeScript](/docs/runtime/typescript) for more information on using TypeScript with Bun.
diff --git a/docs/guides/runtime/index.json b/docs/guides/runtime/index.json
new file mode 100644
index 00000000000000..fad27c69def455
--- /dev/null
+++ b/docs/guides/runtime/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Runtime",
+ "description": "A collection of guides for executing code with the Bun runtime"
+}
diff --git a/docs/guides/runtime/read-env.md b/docs/guides/runtime/read-env.md
new file mode 100644
index 00000000000000..512f731dda5415
--- /dev/null
+++ b/docs/guides/runtime/read-env.md
@@ -0,0 +1,32 @@
+---
+name: Read environment variables
+---
+
+The current environment variables can be accessed via `process.env`.
+
+```ts
+process.env.API_TOKEN; // => "secret"
+```
+
+---
+
+Bun also exposes these variables via `Bun.env`, which is a simple alias of `process.env`.
+
+```ts
+Bun.env.API_TOKEN; // => "secret"
+```
+
+---
+
+To print all currently-set environment variables to the command line, run `bun run env`. This is useful for debugging.
+
+```sh
+$ bun run env
+BAZ=stuff
+FOOBAR=aaaaaa
+
+```
+
+---
+
+See [Docs > Runtime > Environment variables](/docs/cli/run#environment-variables) for more information on using environment variables with Bun.
diff --git a/docs/guides/runtime/set-env.md b/docs/guides/runtime/set-env.md
new file mode 100644
index 00000000000000..97cac348848143
--- /dev/null
+++ b/docs/guides/runtime/set-env.md
@@ -0,0 +1,37 @@
+---
+name: Set environment variables
+---
+
+The current environment variables can be accessed via `process.env` or `Bun.env`.
+
+```ts
+Bun.env.API_TOKEN; // => "secret"
+process.env.API_TOKEN; // => "secret"
+```
+
+---
+
+Set these variables in a `.env` file.
+
+Bun reads the following files automatically (listed in order of increasing precedence).
+
+- `.env`
+- `.env.production` or `.env.development` (depending on value of `NODE_ENV`)
+- `.env.local`
+
+```txt#.env
+FOO=hello
+BAR=world
+```
+
+---
+
+Variables can also be set via the command line.
+
+```sh
+$ FOO=helloworld bun run dev
+```
+
+---
+
+See [Docs > Runtime > Environment variables](/docs/cli/run#environment-variables) for more information on using environment variables with Bun.
diff --git a/docs/guides/runtime/tsconfig-paths.md b/docs/guides/runtime/tsconfig-paths.md
new file mode 100644
index 00000000000000..5c3f591f594a84
--- /dev/null
+++ b/docs/guides/runtime/tsconfig-paths.md
@@ -0,0 +1,29 @@
+---
+name: Re-map import paths
+---
+
+Bun reads the `paths` field in your `tsconfig.json` to re-write import paths. This is useful for aliasing package names or avoiding long relative paths.
+
+```json
+{
+ "compilerOptions": {
+ "paths": {
+ "my-custom-name": "zod",
+ "@components/*": "./src/components/*"
+ }
+ }
+}
+```
+
+---
+
+With the above `tsconfig.json`, the following imports will be re-written:
+
+```ts
+import { z } from "my-custom-name"; // imports from "zod"
+import { Button } from "@components/Button"; // imports from "./src/components/Button"
+```
+
+---
+
+See [Docs > Runtime > TypeScript](/docs/runtime/typescript) for more information on using TypeScript with Bun.
diff --git a/docs/guides/streams/index.json b/docs/guides/streams/index.json
new file mode 100644
index 00000000000000..da6ff26297814f
--- /dev/null
+++ b/docs/guides/streams/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Streams",
+ "description": "A collection of guides for manipulating streams with Bun"
+}
diff --git a/docs/guides/streams/to-array.md b/docs/guides/streams/to-array.md
new file mode 100644
index 00000000000000..bca40cf12ad427
--- /dev/null
+++ b/docs/guides/streams/to-array.md
@@ -0,0 +1,14 @@
+---
+name: Convert a ReadableStream to an array of chunks
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats. The `Bun.readableStreamToArray` function reads the contents of a `ReadableStream` to an array of chunks.
+
+```ts
+const stream = new ReadableStream();
+const str = await Bun.readableStreamToArray(stream);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-arraybuffer.md b/docs/guides/streams/to-arraybuffer.md
new file mode 100644
index 00000000000000..b20d96a04c4efc
--- /dev/null
+++ b/docs/guides/streams/to-arraybuffer.md
@@ -0,0 +1,14 @@
+---
+name: Convert a ReadableStream to an ArrayBuffer
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats.
+
+```ts
+const stream = new ReadableStream();
+const buf = await Bun.readableStreamToArrayBuffer(stream);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-blob.md b/docs/guides/streams/to-blob.md
new file mode 100644
index 00000000000000..3380dca3842e78
--- /dev/null
+++ b/docs/guides/streams/to-blob.md
@@ -0,0 +1,14 @@
+---
+name: Convert a ReadableStream to a Blob
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats.
+
+```ts
+const stream = new ReadableStream();
+const blob = await Bun.readableStreamToBlob(stream);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-buffer.md b/docs/guides/streams/to-buffer.md
new file mode 100644
index 00000000000000..d6450d644e49b7
--- /dev/null
+++ b/docs/guides/streams/to-buffer.md
@@ -0,0 +1,15 @@
+---
+name: Convert a ReadableStream to a Buffer
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats. This snippet reads the contents of a `ReadableStream` to an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), then creates a [`Buffer`](https://nodejs.org/api/buffer.html) that points to it.
+
+```ts
+const stream = new ReadableStream();
+const arrBuf = await Bun.readableStreamToArrayBuffer(stream);
+const nodeBuf = Buffer.from(arrBuf);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-json.md b/docs/guides/streams/to-json.md
new file mode 100644
index 00000000000000..cf9e7c71ee76b9
--- /dev/null
+++ b/docs/guides/streams/to-json.md
@@ -0,0 +1,14 @@
+---
+name: Convert a ReadableStream to a JSON
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats.
+
+```ts
+const stream = new ReadableStream();
+const json = await Bun.readableStreamToJSON(stream);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-string.md b/docs/guides/streams/to-string.md
new file mode 100644
index 00000000000000..309f45c52d7a0c
--- /dev/null
+++ b/docs/guides/streams/to-string.md
@@ -0,0 +1,14 @@
+---
+name: Convert a ReadableStream to a string
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats.
+
+```ts
+const stream = new ReadableStream();
+const str = await Bun.readableStreamToText(stream);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/streams/to-typedarray.md b/docs/guides/streams/to-typedarray.md
new file mode 100644
index 00000000000000..faa18e4ad2ddc8
--- /dev/null
+++ b/docs/guides/streams/to-typedarray.md
@@ -0,0 +1,15 @@
+---
+name: Convert a ReadableStream to a Uint8Array
+---
+
+Bun provides a number of convenience functions for reading the contents of a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) into different formats. This snippet reads the contents of a `ReadableStream` to an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), then creates a [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) that points to the buffer.
+
+```ts
+const stream = new ReadableStream();
+const buf = await Bun.readableStreamToArrayBuffer(stream);
+const uint8 = new Uint8Array(buf);
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils#bun-readablestreamto) for documentation on Bun's other `ReadableStream` conversion functions.
diff --git a/docs/guides/util/base64.md b/docs/guides/util/base64.md
new file mode 100644
index 00000000000000..bbc8f090639646
--- /dev/null
+++ b/docs/guides/util/base64.md
@@ -0,0 +1,15 @@
+---
+name: Encode and decode base64 strings
+---
+
+Bun implements the Web-standard [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/atob) and [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa) functions for encoding and decoding base64 strings.
+
+```ts
+const data = "hello world";
+const encoded = btoa(data); // => "aGVsbG8gd29ybGQ="
+const decoded = atob(encoded); // => "hello world"
+```
+
+---
+
+See [Docs > Web APIs](/docs/runtime/web-apis) for a complete breakdown of the Web APIs implemented in Bun.
diff --git a/docs/guides/util/deep-equals.md b/docs/guides/util/deep-equals.md
new file mode 100644
index 00000000000000..9d8dc74d4ef362
--- /dev/null
+++ b/docs/guides/util/deep-equals.md
@@ -0,0 +1,39 @@
+---
+name: Check if two objects are deeply equal
+---
+
+Check if two objects are deeply equal. This is used internally by `expect().toEqual()` in Bun's [test runner](/docs/test/writing).
+
+```ts#index.ts
+const a = { a: 1, b: 2, c: { d: 3 } };
+const b = { a: 1, b: 2, c: { d: 3 } };
+
+Bun.deepEquals(a, b); // true
+```
+
+---
+
+Pass `true` as a third argument to enable strict mode. This is used internally by `expect().toStrictEqual()` in Bun's [test runner](/docs/test/writing).
+
+The following examples would return `true` in non-strict mode but `false` in strict mode.
+
+```ts
+// undefined values
+Bun.deepEquals({}, { a: undefined }, true); // false
+
+// undefined in arrays
+Bun.deepEquals(["asdf"], ["asdf", undefined], true); // false
+
+// sparse arrays
+Bun.deepEquals([, 1], [undefined, 1], true); // false
+
+// object literals vs instances w/ same properties
+class Foo {
+ a = 1;
+}
+Bun.deepEquals(new Foo(), { a: 1 }, true); // false
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/deflate.md b/docs/guides/util/deflate.md
new file mode 100644
index 00000000000000..91dd8925ab8612
--- /dev/null
+++ b/docs/guides/util/deflate.md
@@ -0,0 +1,18 @@
+---
+name: Compress and decompress data with DEFLATE
+---
+
+Use `Bun.deflateSync()` to compress a `Uint8Array` with DEFLATE.
+
+```ts
+const data = Buffer.from("Hello, world!");
+const compressed = Bun.deflateSync("Hello, world!");
+// => Uint8Array
+
+const decompressed = Bun.inflateSync(compressed);
+// => Uint8Array
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/entrypoint.md b/docs/guides/util/entrypoint.md
new file mode 100644
index 00000000000000..e53d4c9a13572d
--- /dev/null
+++ b/docs/guides/util/entrypoint.md
@@ -0,0 +1,17 @@
+---
+name: Check if the current file is the entrypoint
+---
+
+Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.main` to check if the current file is the entrypoint of the current process.
+
+```ts#index.ts
+if(import.meta.main){
+ // this file is directly executed with `bun run`
+}else{
+ // this file is being imported by another file
+}
+```
+
+---
+
+See [Docs > API > import.meta](/docs/api/import-meta) for complete documentation.
diff --git a/docs/guides/util/escape-html.md b/docs/guides/util/escape-html.md
new file mode 100644
index 00000000000000..4d88fb85766f2c
--- /dev/null
+++ b/docs/guides/util/escape-html.md
@@ -0,0 +1,22 @@
+---
+name: Escape an HTML string
+---
+
+The `Bun.escapeHTML()` utility can be used to escape HTML characters in a string. The following replacements are made.
+
+- `"` becomes `"""`
+- `&` becomes `"&"`
+- `'` becomes `"'"`
+- `<` becomes `"<"`
+- `>` becomes `">"`
+
+This function is optimized for large input. Non-string types will be converted to a string before escaping.
+
+```ts
+Bun.escapeHTML("");
+// <script>alert('Hello World!')</script>
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/file-url-to-path.md b/docs/guides/util/file-url-to-path.md
new file mode 100644
index 00000000000000..0464504a69e3bd
--- /dev/null
+++ b/docs/guides/util/file-url-to-path.md
@@ -0,0 +1,14 @@
+---
+name: Convert a file URL to an absolute path
+---
+
+Use `Bun.fileURLToPath()` to convert a `file://` URL to an absolute path.
+
+```ts
+Bun.fileURLToPath("file:///path/to/file.txt");
+// => "/path/to/file.txt"
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/gzip.md b/docs/guides/util/gzip.md
new file mode 100644
index 00000000000000..c755b7c8bd43fb
--- /dev/null
+++ b/docs/guides/util/gzip.md
@@ -0,0 +1,18 @@
+---
+name: Compress and decompress data with gzip
+---
+
+Use `Bun.gzipSync()` to compress a `Uint8Array` with gzip.
+
+```ts
+const data = Buffer.from("Hello, world!");
+const compressed = Bun.gzipSync("Hello, world!");
+// => Uint8Array
+
+const decompressed = Bun.gunzipSync(compressed);
+// => Uint8Array
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/hash-a-password.md b/docs/guides/util/hash-a-password.md
new file mode 100644
index 00000000000000..6941bfcfee0092
--- /dev/null
+++ b/docs/guides/util/hash-a-password.md
@@ -0,0 +1,54 @@
+---
+name: Hash a password
+---
+
+The `Bun.password.hash()` function provides a fast, built-in mechanism for securely hashing passwords in Bun. No third-party dependencies are required.
+
+```ts
+const password = "super-secure-pa$$word";
+
+const hash = await Bun.password.hash(password);
+// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh6E8DQRhEXg/M/SqYCNu6gVdRRNs$GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4
+```
+
+---
+
+By default this uses the [Argon2id](https://en.wikipedia.org/wiki/Argon2) algorithm. Pass a second argument to `Bun.hash.password()` to use a different algorithm or configure the hashing parameters.
+
+```ts
+const password = "super-secure-pa$$word";
+
+// use argon2 (default)
+const argonHash = await Bun.password.hash(password, {
+ memoryCost: 4, // memory usage in kibibytes
+ timeCost: 3, // the number of iterations
+});
+```
+
+---
+
+Bun also implements the [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) algorithm. Specify `algorithm: "bcrypt"` to use it.
+
+```ts
+// use bcrypt
+const bcryptHash = await Bun.password.hash(password, {
+ algorithm: "bcrypt",
+ cost: 4, // number between 4-31
+});
+```
+
+---
+
+To verify a password, use `Bun.password.verify()`. The algorithm and its parameters are stored in the hash itself, so there's no need to re-specify any configuration.
+
+```ts
+const password = "super-secure-pa$$word";
+const hash = await Bun.password.hash(password);
+
+const isMatch = await Bun.password.verify(password, hash);
+// => true
+```
+
+---
+
+See [Docs > API > Hashing](/docs/api/hashing#bun-password) for complete documentation.
diff --git a/docs/guides/util/import-meta-dir.md b/docs/guides/util/import-meta-dir.md
new file mode 100644
index 00000000000000..edfa023724f1e1
--- /dev/null
+++ b/docs/guides/util/import-meta-dir.md
@@ -0,0 +1,13 @@
+---
+name: Get the directory of the current file
+---
+
+Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object.
+
+```ts#/a/b/c.ts
+import.meta.dir; // => "/a/b"
+```
+
+---
+
+See [Docs > API > import.meta](/docs/api/import-meta) for complete documentation.
diff --git a/docs/guides/util/import-meta-file.md b/docs/guides/util/import-meta-file.md
new file mode 100644
index 00000000000000..8edf262b25c2e9
--- /dev/null
+++ b/docs/guides/util/import-meta-file.md
@@ -0,0 +1,13 @@
+---
+name: Get the file name of the current file
+---
+
+Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.file` to retreive the name of the current file.
+
+```ts#/a/b/c.ts
+import.meta.file; // => "c.ts"
+```
+
+---
+
+See [Docs > API > import.meta](/docs/api/import-meta) for complete documentation.
diff --git a/docs/guides/util/import-meta-path.md b/docs/guides/util/import-meta-path.md
new file mode 100644
index 00000000000000..b93670a387054b
--- /dev/null
+++ b/docs/guides/util/import-meta-path.md
@@ -0,0 +1,13 @@
+---
+name: Get the absolute path of the current file
+---
+
+Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.path` to retreive the absolute path of the current file.
+
+```ts#/a/b/c.ts
+import.meta.path; // => "/a/b/c.ts"
+```
+
+---
+
+See [Docs > API > import.meta](/docs/api/import-meta) for complete documentation.
diff --git a/docs/guides/util/index.json b/docs/guides/util/index.json
new file mode 100644
index 00000000000000..7e988ae252d368
--- /dev/null
+++ b/docs/guides/util/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Utilities",
+ "description": "A collection of guides relating to Bun's array of built-in utility functions"
+}
diff --git a/docs/guides/util/main.md b/docs/guides/util/main.md
new file mode 100644
index 00000000000000..e34fcd8f7b0e30
--- /dev/null
+++ b/docs/guides/util/main.md
@@ -0,0 +1,32 @@
+---
+name: Get the absolute path to the current entrypoint
+---
+
+The `Bun.main` property contains the absolute path to the current entrypoint.
+
+{% codetabs %}
+
+```ts#foo.ts
+console.log(Bun.main);
+```
+
+```ts#index.ts
+import "./foo.ts";
+```
+
+{% /codetabs %}
+
+---
+
+The printed path corresponds to the file that is executed with `bun run`.
+
+```sh
+$ bun run index.ts
+/path/to/index.ts
+$ bun run foo.ts
+/path/to/foo.ts
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/path-to-file-url.md b/docs/guides/util/path-to-file-url.md
new file mode 100644
index 00000000000000..202be61eb032bd
--- /dev/null
+++ b/docs/guides/util/path-to-file-url.md
@@ -0,0 +1,14 @@
+---
+name: Convert an absolute path to a file URL
+---
+
+Use `Bun.pathToFileURL()` to convert an absolute path to a `file://` URL.
+
+```ts
+Bun.pathToFileURL("/path/to/file.txt");
+// => "file:///path/to/file.txt"
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/sleep.md b/docs/guides/util/sleep.md
new file mode 100644
index 00000000000000..dbc39c05715b04
--- /dev/null
+++ b/docs/guides/util/sleep.md
@@ -0,0 +1,22 @@
+---
+name: Sleep for a fixed number of milliseconds
+---
+
+The `Bun.sleep` method provides a convenient way to create a void `Promise` that resolves in a fixed number of milliseconds.
+
+```ts
+// sleep for 1 second
+await Bun.sleep(1000);
+```
+
+---
+
+Internally, this is equivalent to the following snippet that uses [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout).
+
+```ts
+await new Promise((resolve) => setTimeout(resolve, ms));
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/util/version.md b/docs/guides/util/version.md
new file mode 100644
index 00000000000000..c1f5b8bfaafdeb
--- /dev/null
+++ b/docs/guides/util/version.md
@@ -0,0 +1,21 @@
+---
+name: Get the current Bun version
+---
+
+Get the current version of Bun in a semver format.
+
+```ts#index.ts
+Bun.version; // => "0.6.15"
+```
+
+---
+
+Get the exact `git` commit of [`oven-sh/bun`](https://github.com/oven-sh/bun) that was compiled to produce this Bun binary.
+
+```ts#index.ts
+Bun.revision; // => "49231b2cb9aa48497ab966fc0bb6b742dacc4994"
+```
+
+---
+
+See [Docs > API > Utils](/docs/api/utils) for more useful utilities.
diff --git a/docs/guides/websocket/compression.md b/docs/guides/websocket/compression.md
new file mode 100644
index 00000000000000..e98d8f0c983f88
--- /dev/null
+++ b/docs/guides/websocket/compression.md
@@ -0,0 +1,31 @@
+---
+name: Enable compression for WebSocket messages
+---
+
+Per-message compression can be enabled with the `perMessageDeflate` parameter. When set, all messages will be compressed using the [permessage-deflate](https://tools.ietf.org/html/rfc7692) WebSocket extension.
+
+```ts
+Bun.serve({
+ // ...
+ websocket: {
+ // enable compression
+ perMessageDeflate: true,
+ },
+});
+```
+
+---
+
+To enable compression for individual messages, pass `true` as the second parameter to `ws.send()`.
+
+```ts
+Bun.serve({
+ // ...
+ websocket: {
+ async message(ws, message) {
+ // send a compressed message
+ ws.send("Hello world!", true);
+ },
+ },
+});
+```
diff --git a/docs/guides/websocket/context.md b/docs/guides/websocket/context.md
new file mode 100644
index 00000000000000..9e387d685b8c3a
--- /dev/null
+++ b/docs/guides/websocket/context.md
@@ -0,0 +1,72 @@
+---
+name: Set per-socket contextual data on a WebSocket
+---
+
+When building a WebSocket server, it's typically necessary to store some identifying information or context associated with each connected client.
+
+With [Bun.serve()](/docs/api/websockets#contextual-data), this "contextual data" is set when the connection is initially upgraded by passing a `data` parameter in the `server.upgrade()` call.
+
+```ts
+Bun.serve<{ socketId: number }>({
+ fetch(req, server) {
+ const success = server.upgrade(req, {
+ data: {
+ socketId: Math.random(),
+ },
+ });
+ if (success) return undefined;
+
+ // handle HTTP request normally
+ // ...
+ },
+ websocket: {
+ // define websocket handlers
+ async message(ws, message) {
+ // the contextual dta is available as the `data` property
+ // on the WebSocket instance
+ console.log(`Received ${message} from ${ws.data.socketId}}`);
+ },
+ },
+});
+```
+
+---
+
+It's common to read cookies/headers from the incoming request to identify the connecting client.
+
+```ts
+type WebSocketData = {
+ createdAt: number;
+ token: string;
+ userId: string;
+};
+
+// TypeScript: specify the type of `data`
+Bun.serve({
+ async fetch(req, server) {
+ // use a library to parse cookies
+ const cookies = parseCookies(req.headers.get("Cookie"));
+ const token = cookies["X-Token"];
+ const user = await getUserFromToken(ws.data.authToken);
+
+ const upgraded = server.upgrade(req, {
+ data: {
+ createdAt: Date.now(),
+ token: cookies["X-Token"],
+ userId: user.id,
+ },
+ });
+
+ if (upgraded) return undefined;
+ },
+ websocket: {
+ async message(ws, message) {
+ // save the message to a database
+ await saveMessageToDatabase({
+ message: String(message),
+ userId: ws.data.userId,
+ });
+ },
+ },
+});
+```
diff --git a/docs/guides/websocket/index.json b/docs/guides/websocket/index.json
new file mode 100644
index 00000000000000..cb4d71b1ad1e8c
--- /dev/null
+++ b/docs/guides/websocket/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "WebSocket",
+ "description": "A collection of guides relating to building WebSocket servers with Bun"
+}
diff --git a/docs/guides/websocket/pubsub.md b/docs/guides/websocket/pubsub.md
new file mode 100644
index 00000000000000..7403d4d2f5e7cb
--- /dev/null
+++ b/docs/guides/websocket/pubsub.md
@@ -0,0 +1,38 @@
+---
+name: Build a publish-subscribe WebSocket server
+---
+
+Bun's server-side `WebSocket` API provides a native pub-sub API. Sockets can be subscribed to a set of named channels using `socket.subscribe()`; messages can be published to a channel using `socket.publish(, )`.
+
+This code snippet implements a simple single-channel chat server.
+
+```ts
+const server = Bun.serve<{ username: string }>({
+ fetch(req, server) {
+ const cookies = req.headers.get("cookie");
+ const username = getUsernameFromCookies(cookies);
+ const success = server.upgrade(req, { data: { username } });
+ if (success) return undefined;
+
+ return new Response("Hello world");
+ },
+ websocket: {
+ open(ws) {
+ const msg = `${ws.data.username} has entered the chat`;
+ ws.subscribe("the-group-chat");
+ ws.publish("the-group-chat", msg);
+ },
+ message(ws, message) {
+ // the server re-broadcasts incoming messages to everyone
+ ws.publish("the-group-chat", `${ws.data.username}: ${message}`);
+ },
+ close(ws) {
+ const msg = `${ws.data.username} has left the chat`;
+ ws.publish("the-group-chat", msg);
+ ws.unsubscribe("the-group-chat");
+ },
+ },
+});
+
+console.log(`Listening on ${server.hostname}:${server.port}`);
+```
diff --git a/docs/guides/websocket/simple.md b/docs/guides/websocket/simple.md
new file mode 100644
index 00000000000000..5aabf2fdf40db9
--- /dev/null
+++ b/docs/guides/websocket/simple.md
@@ -0,0 +1,33 @@
+---
+name: Build a simple WebSocket server
+---
+
+Start a simple WebSocket server using [`Bun.serve`](/docs/api/http).
+
+Inside `fetch`, we attempt to upgrade incoming `ws:` or `wss:` requests to WebSocket connections.
+
+```ts
+const server = Bun.serve<{ authToken: string }>({
+ fetch(req, server) {
+ const success = server.upgrade(req);
+ if (success) {
+ // Bun automatically returns a 101 Switching Protocols
+ // if the upgrade succeeds
+ return undefined;
+ }
+
+ // handle HTTP request normally
+ return new Response("Hello world!");
+ },
+ websocket: {
+ // this is called when a message is received
+ async message(ws, message) {
+ console.log(`Received ${message}`);
+ // send back a message
+ ws.send(`You said: ${message}`);
+ },
+ },
+});
+
+console.log(`Listening on localhost:\${server.port}`);
+```
diff --git a/docs/guides/websocket/upgrade.md b/docs/guides/websocket/upgrade.md
new file mode 100644
index 00000000000000..cec8c38025eb2a
--- /dev/null
+++ b/docs/guides/websocket/upgrade.md
@@ -0,0 +1,28 @@
+---
+name: Upgrade an HTTP request to a WebSocket connection
+---
+
+Inside `fetch`, use the `server.upgrade()` function to upgrade an incoming `Request` to a WebSocket connection. Bun automatically returns a 101 Switching Protocols response if the upgrade succeeds.
+
+Refer to the [WebSocket docs](/docs/api/websockets) for more information on building WebSocket servers.
+
+```ts
+const server = Bun.serve<{ authToken: string }>({
+ fetch(req, server) {
+ const success = server.upgrade(req);
+ if (success) {
+ // Bun automatically returns a 101 Switching Protocols
+ // if the upgrade succeeds
+ return undefined;
+ }
+
+ // handle HTTP request normally
+ return new Response("Hello world!");
+ },
+ websocket: {
+ // define websocket handlers
+ },
+});
+
+console.log(`Listening on localhost:\${server.port}`);
+```
diff --git a/docs/guides/write-file/basic.md b/docs/guides/write-file/basic.md
new file mode 100644
index 00000000000000..66f180a40be6c8
--- /dev/null
+++ b/docs/guides/write-file/basic.md
@@ -0,0 +1,44 @@
+---
+name: Write a string to a file
+---
+
+This code snippet writes a string to disk at a particular _absolute path_.
+
+It uses the fast [`Bun.write()`](/docs/api/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a _destination_; the second is the _data_ to write.
+
+```ts
+const path = "/path/to/file.txt";
+await Bun.write(path, "Lorem ipsum");
+```
+
+---
+
+Any relative paths will be resolved relative to the project root (the nearest directory containing a `package.json` file).
+
+```ts
+const path = "./file.txt";
+await Bun.write(path, "Lorem ipsum");
+```
+
+---
+
+You can pass a `BunFile` as the destination. `Bun.write()` will write the data to its associated path.
+
+```ts
+const path = Bun.file("./file.txt");
+await Bun.write(path, "Lorem ipsum");
+```
+
+---
+
+`Bun.write()` returns the number of bytes written to disk.
+
+```ts
+const path = "./file.txt";
+const bytes = await Bun.write(path, "Lorem ipsum");
+// => 11
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/blob.md b/docs/guides/write-file/blob.md
new file mode 100644
index 00000000000000..a923190bfa3ce5
--- /dev/null
+++ b/docs/guides/write-file/blob.md
@@ -0,0 +1,28 @@
+---
+name: Write a Blob to a file
+---
+
+This code snippet writes a `Blob` to disk at a particular path.
+
+It uses the fast [`Bun.write()`](/docs/api/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a _destination_, like an absolute path or `BunFile` instance. The second argument is the _data_ to write.
+
+```ts
+const path = "/path/to/file.txt";
+await Bun.write(path, "Lorem ipsum");
+```
+
+---
+
+The `BunFile` class extends `Blob`, so you can pass a `BunFile` directly into `Bun.write()` as well.
+
+```ts
+const path = "./out.txt";
+const data = Bun.file("./in.txt");
+
+// write the contents of ./in.txt to ./out.txt
+await Bun.write(path, data);
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/cat.md b/docs/guides/write-file/cat.md
new file mode 100644
index 00000000000000..a9f9a0ba68418e
--- /dev/null
+++ b/docs/guides/write-file/cat.md
@@ -0,0 +1,17 @@
+---
+name: Write a file to stdout
+---
+
+Bun exposes `stdout` as a `BunFile` with the `Bun.stdout` property. This can be used as a destination for [`Bun.write()`](/docs/api/file-io#writing-files-bun-write).
+
+This code writes a file to `stdout` similar to the `cat` command in Unix.
+
+```ts#cat.ts
+const path = "/path/to/file.txt";
+const file = Bun.file(path);
+await Bun.write(Bun.stdout, file);
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/file-cp.md b/docs/guides/write-file/file-cp.md
new file mode 100644
index 00000000000000..b8910e269a4422
--- /dev/null
+++ b/docs/guides/write-file/file-cp.md
@@ -0,0 +1,16 @@
+---
+name: Copy a file to another location
+---
+
+This code snippet copies a file to another location on disk.
+
+It uses the fast [`Bun.write()`](/docs/api/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a _destination_, like an absolute path or `BunFile` instance. The second argument is the _data_ to write.
+
+```ts
+const file = Bun.file("/path/to/original.txt");
+await Bun.write("/path/to/copy.txt", file);
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/filesink.md b/docs/guides/write-file/filesink.md
new file mode 100644
index 00000000000000..10ea792ee69daf
--- /dev/null
+++ b/docs/guides/write-file/filesink.md
@@ -0,0 +1,52 @@
+---
+name: Write a file incrementally
+---
+
+Bun provides an API for incrementally writing to a file. This is useful for writing large files, or for writing to a file over a long period of time.
+
+Call `.writer()` on a `BunFile` to retrieve a `FileSink` instance. This instance can be used to efficiently buffer data and periodically "flush" it to disk. You can write & flush many times.
+
+```ts
+const file = Bun.file("/path/to/file.txt");
+const writer = file.writer();
+
+writer.write("lorem");
+writer.write("ipsum");
+writer.write("dolor");
+
+writer.flush();
+
+// continue writing & flushing
+```
+
+---
+
+The `.write()` method can accept strings or binary data.
+
+```ts
+w.write("hello");
+w.write(Buffer.from("there"));
+w.write(new Uint8Array([0, 255, 128]));
+writer.flush();
+```
+
+---
+
+The `FileSink` will also auto-flush when its internal buffer is full. You can configure the buffer size with the `highWaterMark` option.
+
+```ts
+const file = Bun.file("/path/to/file.txt");
+const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MB
+```
+
+---
+
+When you're done writing to the file, call `.end()` to auto-flush the buffer and close the file.
+
+```ts
+writer.end();
+```
+
+---
+
+Full documentation: [FileSink](/docs/api/file-io#incremental-writing-with-filesink).
diff --git a/docs/guides/write-file/index.json b/docs/guides/write-file/index.json
new file mode 100644
index 00000000000000..dea48e215f358b
--- /dev/null
+++ b/docs/guides/write-file/index.json
@@ -0,0 +1,4 @@
+{
+ "name": "Writing files",
+ "description": "A collection of guides for writing files with Bun"
+}
diff --git a/docs/guides/write-file/response.md b/docs/guides/write-file/response.md
new file mode 100644
index 00000000000000..fb2bd79eba573f
--- /dev/null
+++ b/docs/guides/write-file/response.md
@@ -0,0 +1,17 @@
+---
+name: Write a Response to a file
+---
+
+This code snippet writes a `Response` to disk at a particular path. Bun will consume the `Response` body according to its `Content-Type` header.
+
+It uses the fast [`Bun.write()`](/docs/api/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a _destination_, like an absolute path or `BunFile` instance. The second argument is the _data_ to write.
+
+```ts
+const result = await fetch("https://bun.sh");
+const path = "./file.txt";
+await Bun.write(path, result);
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/stdout.md b/docs/guides/write-file/stdout.md
new file mode 100644
index 00000000000000..00fa11a6073333
--- /dev/null
+++ b/docs/guides/write-file/stdout.md
@@ -0,0 +1,21 @@
+---
+name: Write to stdout
+---
+
+The `console.log` function writes to `stdout`. It will automatically append a line break at the end of the printed data.
+
+```ts
+console.log("Lorem ipsum");
+```
+
+---
+
+For more advanced use cases, Bun exposes `stdout` as a `BunFile` via the `Bun.stdout` property. This can be used as a destination for [`Bun.write()`](/docs/api/file-io#writing-files-bun-write).
+
+```ts
+await Bun.write(Bun.stdout, "Lorem ipsum");
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/stream.md b/docs/guides/write-file/stream.md
new file mode 100644
index 00000000000000..efb7efd8a5d24b
--- /dev/null
+++ b/docs/guides/write-file/stream.md
@@ -0,0 +1,17 @@
+---
+name: Write a ReadableStream to a file
+---
+
+To write a `ReadableStream` to disk, first create a `Response` instance from the stream. This `Response` can then be written to disk using [`Bun.write()`](/docs/api/file-io#writing-files-bun-write).
+
+```ts
+const stream: ReadableStream = ...;
+const path = "./file.txt";
+const response = new Response(stream);
+
+await Bun.write(path, response);
+```
+
+---
+
+See [Docs > API > File I/O](/docs/api/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`.
diff --git a/docs/guides/write-file/unlink.md b/docs/guides/write-file/unlink.md
new file mode 100644
index 00000000000000..ba0cbe8b1d3611
--- /dev/null
+++ b/docs/guides/write-file/unlink.md
@@ -0,0 +1,23 @@
+---
+name: Delete a file
+---
+
+To synchronously delete a file with Bun, use the `unlinkSync` function from the [`node:fs`](https://nodejs.org/api/fs.html#fs_fs_unlink_path_callback) module. (Currently, there is no `Bun` API for deleting files.)
+
+```ts
+import { unlinkSync } from "node:fs";
+
+const path = "/path/to/file.txt";
+unlinkSync(path);
+```
+
+---
+
+To remove a file asynchronously, use the `unlink` function from the [`node:fs/promises`](https://nodejs.org/api/fs.html#fs_fspromises_unlink_path) module.
+
+```ts
+import { unlink } from "node:fs/promises";
+
+const path = "/path/to/file.txt";
+await unlink(path);
+```
diff --git a/docs/install/cache.md b/docs/install/cache.md
index 6bd13d04ad7109..bb22e545d88a8c 100644
--- a/docs/install/cache.md
+++ b/docs/install/cache.md
@@ -19,7 +19,7 @@ disableManifest = false
## Minimizing re-downloads
-Bun strives to avoid re-downloading packages mutiple times. When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun will use the cached package instead of downloading it again.
+Bun strives to avoid re-downloading packages multiple times. When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun will use the cached package instead of downloading it again.
{% details summary="Installation details" %}
If the semver version has pre-release suffix (`1.0.0-beta.0`) or a build suffix (`1.0.0+20220101`), it is replaced with a hash of that value instead, to reduce the chances of errors associated with long file paths.
diff --git a/docs/install/index.md b/docs/install/index.md
index 162a4abacf1f77..540ade9f032dd5 100644
--- a/docs/install/index.md
+++ b/docs/install/index.md
@@ -114,7 +114,7 @@ $ bun add zod@latest
To add a package as a dev dependency (`"devDependencies"`):
```bash
-$ bun add --development @types/react
+$ bun add --dev @types/react
$ bun add -d @types/react
```
diff --git a/docs/nav.ts b/docs/nav.ts
index 13af7b20ec8734..4b3a67ec0a36f1 100644
--- a/docs/nav.ts
+++ b/docs/nav.ts
@@ -38,6 +38,11 @@ export default {
page("templates", "Templates", {
description: "Hit the ground running with one of Bun's official templates, or download a template from GitHub.",
}),
+ page("guides", "Guides", {
+ description: "A set of walkthrough guides and code snippets for performing common tasks with Bun",
+ href: "/guides",
+ }),
+
// page("typescript", "TypeScript"),
// divider("CLI"),
@@ -105,6 +110,9 @@ export default {
page("runtime/nodejs-apis", "Node.js compatibility", {
description: `Bun aims for full Node.js compatibility. This page tracks the current compatibility status.`,
}),
+ page("runtime/plugins", "Plugins", {
+ description: `Implement custom loaders and module resolution logic with Bun's plugin system.`,
+ }),
// page("runtime/nodejs", "Node.js compatibility", {
// description: `Track the status of Bun's API compatibility with Node.js.`,
@@ -202,6 +210,9 @@ export default {
page("test/dom", "DOM testing", {
description: "Write headless tests for UI and React/Vue/Svelte/Lit components with happy-dom",
}),
+ page("test/coverage", "Code coverage", {
+ description: "Generate code coverage reports with `bun test --coverage`",
+ }),
divider("Package runner"),
page("cli/bunx", "`bunx`", {
@@ -210,30 +221,29 @@ export default {
// page("runtime/nodejs", "Node.js APIs"),
- divider("Ecosystem"),
+ // divider("Ecosystem"),
// page("ecosystem/react", "React", {
// description: `The Bun runtime supports JSX syntax out of the box and optimizes server-side rendering.`,
// }),
- page("ecosystem/express", "Express", {
- description: `Servers built with Express and other major Node.js HTTP libraries work out of the box.`,
- }),
- page("ecosystem/elysia", "Elysia", {
- description: `Get started with Elysia, a Bun-native framework designed for the edge.`,
- }),
- page("ecosystem/hono", "Hono", {
- description: `Hono is an ultra-fast, Bun-friendly web framework designed for edge environments.`,
- }),
+ // page("ecosystem/express", "Express", {
+ // description: `Servers built with Express and other major Node.js HTTP libraries work out of the box.`,
+ // }),
+ // page("ecosystem/elysia", "Elysia", {
+ // description: `Get started with Elysia, a Bun-native framework designed for the edge.`,
+ // }),
+ // page("ecosystem/hono", "Hono", {
+ // description: `Hono is an ultra-fast, Bun-friendly web framework designed for edge environments.`,
+ // }),
// page("ecosystem/buchta", "Buchta", {
// description: `Buchta is a Bun-native fullstack framework for Svelte and Preact apps.`,
// }),
- page("ecosystem/stric", "Stric", {
- description: `Stric is a minimalist, fast web framework for Bun.`,
- }),
-
- page("ecosystem/awesome", "Awesome", {
- href: "https://github.com/apvarun/awesome-bun",
- description: ``,
- }),
+ // page("ecosystem/stric", "Stric", {
+ // description: `Stric is a minimalist, fast web framework for Bun.`,
+ // }),
+ // page("ecosystem/awesome", "Awesome", {
+ // href: "https://github.com/apvarun/awesome-bun",
+ // description: ``,
+ // }),
divider("API"),
page("api/http", "HTTP server", {
diff --git a/docs/runtime/autoimport.md b/docs/runtime/autoimport.md
index 70af18e1f737ff..d1472302496679 100644
--- a/docs/runtime/autoimport.md
+++ b/docs/runtime/autoimport.md
@@ -4,7 +4,7 @@
If no `node_modules` directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the **Bun module resolution algorithm**.
-Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/docs/cli/install#global-cache) during execution (the same cache used by [`bun install`](/docs/cli/install)).
+Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/docs/install/cache) during execution (the same cache used by [`bun install`](/docs/cli/install)).
```ts
import { foo } from "foo"; // install `latest` version
diff --git a/docs/runtime/bun-apis.md b/docs/runtime/bun-apis.md
index c4cd534e75ff2c..6907e802dc599b 100644
--- a/docs/runtime/bun-apis.md
+++ b/docs/runtime/bun-apis.md
@@ -95,6 +95,6 @@ Click the link in the right column to jump to the associated documentation.
---
- Utilities
-- [`Bun.version`](/docs/api/utils#bun-version) [`Bun.revision`](/docs/api/utils#bun-revision) [`Bun.env`](/docs/api/utils#bun-env) [`Bun.main`](/docs/api/utils#bun-main) [`Bun.sleep()`](/docs/api/utils#bun-sleep) [`Bun.sleepSync()`](/docs/api/utils#bun-sleepsync) [`Bun.which()`](/docs/api/utils#bun-which) [`Bun.peek()`](/docs/api/utils#bun-peek) [`Bun.openInEditor()`](/docs/api/utils#bun-openineditor) [`Bun.deepEquals()`](/docs/api/utils#bun-deepequals) [`Bun.escapeHTML()`](/docs/api/utils#bun-escapehtlm) [`Bun.enableANSIColors()`](/docs/api/utils#bun-enableansicolors) [`Bun.fileURLToPath()`](/docs/api/utils#bun-fileurltopath) [`Bun.pathToFileURL()`](/docs/api/utils#bun-pathtofileurl) [`Bun.gzipSync()`](/docs/api/utils#bun-gzipsync) [`Bun.gunzipSync()`](/docs/api/utils#bun-gunzipsync) [`Bun.deflateSync()`](/docs/api/utils#bun-deflatesync) [`Bun.inflateSync()`](/docs/api/utils#bun-inflatesync) [`Bun.inspect()`](/docs/api/utils#bun-inspect) [`Bun.nanoseconds()`](/docs/api/utils#bun-nanoseconds) [`Bun.readableStreamTo*()`](/docs/api/utils#bun-readablestreamto) [`Bun.resolveSync()`](/docs/api/utils#bun-resolvesync)
+- [`Bun.version`](/docs/api/utils#bun-version) [`Bun.revision`](/docs/api/utils#bun-revision) [`Bun.env`](/docs/api/utils#bun-env) [`Bun.main`](/docs/api/utils#bun-main) [`Bun.sleep()`](/docs/api/utils#bun-sleep) [`Bun.sleepSync()`](/docs/api/utils#bun-sleepsync) [`Bun.which()`](/docs/api/utils#bun-which) [`Bun.peek()`](/docs/api/utils#bun-peek) [`Bun.openInEditor()`](/docs/api/utils#bun-openineditor) [`Bun.deepEquals()`](/docs/api/utils#bun-deepequals) [`Bun.escapeHTML()`](/docs/api/utils#bun-escapehtml) [`Bun.fileURLToPath()`](/docs/api/utils#bun-fileurltopath) [`Bun.pathToFileURL()`](/docs/api/utils#bun-pathtofileurl) [`Bun.gzipSync()`](/docs/api/utils#bun-gzipsync) [`Bun.gunzipSync()`](/docs/api/utils#bun-gunzipsync) [`Bun.deflateSync()`](/docs/api/utils#bun-deflatesync) [`Bun.inflateSync()`](/docs/api/utils#bun-inflatesync) [`Bun.inspect()`](/docs/api/utils#bun-inspect) [`Bun.nanoseconds()`](/docs/api/utils#bun-nanoseconds) [`Bun.readableStreamTo*()`](/docs/api/utils#bun-readablestreamto) [`Bun.resolveSync()`](/docs/api/utils#bun-resolvesync)
{% /table %}
diff --git a/docs/runtime/index.md b/docs/runtime/index.md
index 90d2000066a483..a10ac0cff7bd2a 100644
--- a/docs/runtime/index.md
+++ b/docs/runtime/index.md
@@ -6,7 +6,7 @@ Bun is designed to start fast and run fast. It's transpiler and runtime are writ
{% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%}
-
+
Performance sensitive APIs like `Buffer`, `fetch`, and `Response` are heavily profiled and optimized. Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. It starts and runs faster than V8, the engine used by Node.js and Chromium-based browsers.
diff --git a/docs/runtime/jsx.md b/docs/runtime/jsx.md
index ecf250c8274a4f..053c8b01c102a8 100644
--- a/docs/runtime/jsx.md
+++ b/docs/runtime/jsx.md
@@ -77,7 +77,7 @@ How JSX constructs are transformed into vanilla JavaScript internally. The table
);
```
- The `jsxDEV` variable name is a convention used by React. The `DEV` suffix is a visible way to indicate that the code is intended for use in development. The development version of React is slowers and includes additional validity checks & debugging tools.
+ The `jsxDEV` variable name is a convention used by React. The `DEV` suffix is a visible way to indicate that the code is intended for use in development. The development version of React is slower and includes additional validity checks & debugging tools.
---
diff --git a/docs/runtime/modules.md b/docs/runtime/modules.md
index 42f2a08e6a69fb..207315804339c9 100644
--- a/docs/runtime/modules.md
+++ b/docs/runtime/modules.md
@@ -98,22 +98,24 @@ import { stuff } from "foo";
The full specification of this algorithm are officially documented in the [Node.js documentation](https://nodejs.org/api/modules.html); we won't rehash it here. Briefly: if you import `from "foo"`, Bun scans up the file system for a `node_modules` directory containing the package `foo`.
-Once it finds the `foo` package, Bun reads the `package.json` to determine how the package should be imported. Unless `"type": "module"` is specified, Bun assumes the package is using CommonJS and transpiles into a synchronous ES module internally. To determine the package's entrypoint, Bun first reads the `exports` field in and checks the following conditions in order:
+Once it finds the `foo` package, Bun reads the `package.json` to determine how the package should be imported. To determine the package's entrypoint, Bun first reads the `exports` field and checks for the following conditions.
```jsonc#package.json
{
"name": "foo",
"exports": {
- "bun": "./index.js", // highest priority
+ "bun": "./index.js",
"worker": "./index.js",
- "module": "./index.js",
"node": "./index.js",
+ "require": "./index.js", # if importer is CommonJS
+ "import": "./index.mjs", # if importer is ES module
"default": "./index.js",
- "browser": "./index.js" // lowest priority
}
}
```
+Whichever one of these conditions occurs _first_ in the `package.json` is used to determine the package's entrypoint.
+
Bun respects subpath [`"exports"`](https://nodejs.org/api/packages.html#subpath-exports) and [`"imports"`](https://nodejs.org/api/packages.html#imports). Specifying any subpath in the `"exports"` map will prevent other subpaths from being importable.
```jsonc#package.json
diff --git a/docs/runtime/nodejs-apis.md b/docs/runtime/nodejs-apis.md
index dad8489c075321..67a6bf4987f889 100644
--- a/docs/runtime/nodejs-apis.md
+++ b/docs/runtime/nodejs-apis.md
@@ -4,7 +4,171 @@ This page is updated regularly to reflect compatibility status of the latest ver
## Built-in modules
-{% block className="ScrollFrame" %}
+### [`node:assert`](https://nodejs.org/api/assert.html)
+
+🟢 Fully implemented.
+
+### [`node:async_hooks`](https://nodejs.org/api/async_hooks.html)
+
+🔴 Not implemented.
+
+### [`node:buffer`](https://nodejs.org/api/buffer.html)
+
+🟢 Fully implemented.
+
+### [`node:child_process`](https://nodejs.org/api/child_process.html)
+
+🟡 Missing IPC, `Stream` stdio, `proc.gid`, `proc.uid`, advanced serialization.
+
+### [`node:cluster`](https://nodejs.org/api/cluster.html)
+
+🔴 Not implemented.
+
+### [`node:console`](https://nodejs.org/api/console.html)
+
+🟢 Recommended to use `console` global instead
+
+### [`node:crypto`](https://nodejs.org/api/crypto.html)
+
+🟡 Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`. Some methods are not optimized yet.
+
+### [`node:dgram`](https://nodejs.org/api/dgram.html)
+
+🔴 Not implemented.
+
+### [`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html)
+
+🟢 Fully implemented.
+
+### [`node:dns`](https://nodejs.org/api/dns.html)
+
+🟢 Fully implemented.
+
+### [`node:domain`](https://nodejs.org/api/domain.html)
+
+🟢 Fully implemented.
+
+### [`node:events`](https://nodejs.org/api/events.html)
+
+🟡 Missing `EventEmitterAsyncResource` `events.on`.
+
+### [`node:fs`](https://nodejs.org/api/fs.html)
+
+🟡 Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.{watchFile|unwatchFile}` `fs.{cp|cpSync}`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
+
+### [`node:http`](https://nodejs.org/api/http.html)
+
+🟢 Fully implemented.
+
+### [`node:http2`](https://nodejs.org/api/http2.html)
+
+🔴 Not implemented.
+
+### [`node:https`](https://nodejs.org/api/https.html)
+
+🟢 Fully implemented.
+
+### [`node:inspector`](https://nodejs.org/api/inspector.html)
+
+🔴 Not implemented.
+
+### [`node:module`](https://nodejs.org/api/module.html)
+
+🟢 Fully implemented.
+
+### [`node:net`](https://nodejs.org/api/net.html)
+
+🟡 Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
+
+### [`node:os`](https://nodejs.org/api/os.html)
+
+🟢 Fully implemented.
+
+### [`node:path`](https://nodejs.org/api/path.html)
+
+🟢 Fully implemented.
+
+### [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html)
+
+🟡 Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
+
+### [`node:process`](https://nodejs.org/api/process.html)
+
+🟡 See `Globals > process`.
+
+### [`node:punycode`](https://nodejs.org/api/punycode.html)
+
+🟢 Fully implemented. _Deprecated by Node.js._
+
+### [`node:querystring`](https://nodejs.org/api/querystring.html)
+
+🟢 Fully implemented.
+
+### [`node:readline`](https://nodejs.org/api/readline.html)
+
+🟢 Fully implemented.
+
+### [`node:repl`](https://nodejs.org/api/repl.html)
+
+🔴 Not implemented.
+
+### [`node:stream`](https://nodejs.org/api/stream.html)
+
+🟢 Fully implemented.
+
+### [`node:string_decoder`](https://nodejs.org/api/string_decoder.html)
+
+🟢 Fully implemented.
+
+### [`node:sys`](https://nodejs.org/api/util.html)
+
+🟡 See `node:util`.
+
+### [`node:timers`](https://nodejs.org/api/timers.html)
+
+🟢 Recommended to use global `setTimeout`, et. al. instead.
+
+### [`node:tls`](https://nodejs.org/api/tls.html)
+
+🟡 Missing `tls.createSecurePair`
+
+### [`node:trace_events`](https://nodejs.org/api/tracing.html)
+
+🔴 Not implemented.
+
+### [`node:tty`](https://nodejs.org/api/tty.html)
+
+🟡 Missing `tty.ReadStream` and `tty.WriteStream`.
+
+### [`node:url`](https://nodejs.org/api/url.html)
+
+🟡 Missing `url.domainTo{ASCII|Unicode}`. Recommended to use `URL` and `URLSearchParams` globals instead.
+
+### [`node:util`](https://nodejs.org/api/util.html)
+
+🟡 Missing `util.MIMEParams` `util.MIMEType` `util.formatWithOptions()` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
+
+### [`node:v8`](https://nodejs.org/api/v8.html)
+
+🔴 `serialize` and `deserialize` use JavaScriptCore's wire format instead of V8's. Otherwise, not implemented. For profiling, use [`bun:jsc`](/docs/project/benchmarking#bunjsc) instead.
+
+### [`node:vm`](https://nodejs.org/api/vm.html)
+
+🟡 Core functionality works, but VM modules are not implemented. `ShadowRealm` can be used.
+
+### [`node:wasi`](https://nodejs.org/api/wasi.html)
+
+🟡 Partially implemented.
+
+### [`node:worker_threads`](https://nodejs.org/api/worker_threads.html)
+
+🟢 Fully implemented.
+
+### [`node:zlib`](https://nodejs.org/api/zlib.html)
+
+🟡 Missing `zlib.brotli*`
+
+
## Globals
The table below lists all globals implemented by Node.js and Bun's current compatibility status.
-{% table %}
+### [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
+
+🟢 Fully implemented.
+
+### [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
+
+🟢 Fully implemented.
+
+### [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+
+🟢 Fully implemented.
+
+### [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer)
+
+🟡 Incomplete implementation of `base64` and `base64url` encodings.
+
+### [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy)
+
+🟢 Fully implemented.
+
+### [`__dirname`](https://nodejs.org/api/globals.html#__dirname)
+
+🟢 Fully implemented.
+
+### [`__filename`](https://nodejs.org/api/globals.html#__filename)
+
+🟢 Fully implemented.
+
+### [`atob()`](https://developer.mozilla.org/en-US/docs/Web/API/atob)
+
+🟢 Fully implemented.
+
+### [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel)
+
+🟢 Fully implemented.
+
+### [`btoa()`](https://developer.mozilla.org/en-US/docs/Web/API/btoa)
+
+🟢 Fully implemented.
+
+### [`clearImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearImmediate)
+
+🟢 Fully implemented.
+
+### [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval)
+
+🟢 Fully implemented.
+
+### [`clearTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout)
+
+🟢 Fully implemented.
+
+### [`CompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)
+
+🔴 Not implemented.
+
+### [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
+
+🟢 Fully implemented.
+
+### [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy)
+
+🟢 Fully implemented.
+
+### [`Crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto)
+
+🟢 Fully implemented.
+
+### [`SubtleCrypto (crypto)`](https://developer.mozilla.org/en-US/docs/Web/API/crypto)
+
+🟢 Fully implemented.
+
+### [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
+
+🟢 Fully implemented.
+
+### [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)
+
+🟢 Fully implemented.
+
+### [`DecompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream)
+
+🔴 Not implemented.
+
+### [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event)
+
+🟢 Fully implemented.
+
+### [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
+
+🟢 Fully implemented.
+
+### [`exports`](https://nodejs.org/api/globals.html#exports)
+
+🟢 Fully implemented.
+
+### [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch)
+
+🟢 Fully implemented.
+
+### [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
+
+🟢 Fully implemented. Added in Bun 0.5.7.
+
+### [`global`](https://nodejs.org/api/globals.html#global)
+
+🟢 Implemented. This is an object containing all objects in the global namespace. It's rarely referenced directly, as its contents are available without an additional prefix, e.g. `__dirname` instead of `global.__dirname`.
+
+### [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis)
+
+🟢 Aliases to `global`.
+
+### [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
+
+🟢 Fully implemented.
+
+### [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel)
+
+🟢 Fully implemented.
+
+### [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
+
+🟢 Fully implemented.
+
+### [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort)
+
+🟢 Fully implemented.
+
+### [`module`](https://nodejs.org/api/globals.html#module)
+
+🟢 Fully implemented.
+
+### [`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry)
+
+🔴 Not implemented.
+
+### [`PerformanceMark`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark)
+
+🔴 Not implemented.
+
+### [`PerformanceMeasure`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure)
+
+🔴 Not implemented.
+
+### [`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver)
+
+🔴 Not implemented.
+
+### [`PerformanceObserverEntryList`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserverEntryList)
+
+🔴 Not implemented.
+
+### [`PerformanceResourceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming)
+
+🔴 Not implemented.
+
+### [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/performance)
+
+🟢 Fully implemented.
+
+### [`process`](https://nodejs.org/api/process.html)
+
+🟡 Missing `process.allowedNodeEnvironmentFlags` `process.channel()` `process.connected` `process.constrainedMemory()` `process.disconnect()` `process.getActiveResourcesInfo/setActiveResourcesInfo()` `process.setuid/setgid/setegid/seteuid/setgroups()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.report` `process.resourceUsage()` `process.send()`.
+
+### [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
+
+🟢 Fully implemented.
+
+### [`ReadableByteStreamController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableByteStreamController)
+
+🟢 Fully implemented.
+
+### [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
+
+🟢 Fully implemented.
+
+### [`ReadableStreamBYOBReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader)
+
+🔴 Not implemented.
+
+### [`ReadableStreamBYOBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBRequest)
+
+🔴 Not implemented.
+
+### [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController)
+
+🟢 Fully implemented.
+
+### [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader)
+
+🟢 Fully implemented.
+
+### [`require()`](https://nodejs.org/api/globals.html#require)
+
+🟢 Fully implemented, as well as [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), and [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
+
+### [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
+
+🟢 Fully implemented.
+
+### [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
+
+🟢 Fully implemented.
+
+### [`setImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate)
+
+🟢 Fully implemented.
+
+### [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval)
+
+🟢 Fully implemented.
+
+### [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout)
+
+🟢 Fully implemented.
+
+### [`structuredClone()`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)
+
+🟢 Fully implemented.
+
+### [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
+
+🟢 Fully implemented.
+
+### [`DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException)
+
+🟢 Fully implemented.
+
+### [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
+
+🟢 Fully implemented.
+
+### [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream)
+
+🔴 Not implemented.
+
+### [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder)
+
+🟢 Fully implemented.
+
+### [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream)
+
+🔴 Not implemented.
+
+### [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream)
+
+🟢 Fully implemented.
+
+### [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController)
+
+🟢 Fully implemented.
+
+### [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
+
+🟢 Fully implemented.
+
+### [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+
+🟢 Fully implemented.
+
+### [`WebAssembly`](https://nodejs.org/api/globals.html#webassembly)
+
+🟢 Fully implemented.
+
+### [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream)
+
+🟢 Fully implemented.
+
+### [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController)
+
+🟢 Fully implemented.
+
+### [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)
+
+🟢 Fully implemented.
+
+
diff --git a/docs/runtime/plugins.md b/docs/runtime/plugins.md
new file mode 100644
index 00000000000000..39eea327866e3a
--- /dev/null
+++ b/docs/runtime/plugins.md
@@ -0,0 +1,276 @@
+{% callout %}
+**Note** — Introduced in Bun v0.1.11.
+{% /callout %}
+
+Bun provides a universal plugin API that can be used to extend both the _runtime_ and [_bundler_](/docs/bundler).
+
+Plugins intercept imports and perform custom loading logic: reading files, transpiling code, etc. They can be used to add support for additional file types, like `.scss` or `.yaml`. In the context of Bun's bundler, plugins can be used to implement framework-level features like CSS extraction, macros, and client-server code co-location.
+
+## Usage
+
+A plugin is defined as simple JavaScript object containing a `name` property and a `setup` function. Register a plugin with Bun using the `plugin` function.
+
+```tsx#myPlugin.ts
+import { plugin, type BunPlugin } from "bun";
+
+const myPlugin: BunPlugin = {
+ name: "Custom loader",
+ setup(build) {
+ // implementation
+ },
+};
+```
+
+Plugins have to be registered before any other code runs! To achieve this, use the `preload` option in your [`bunfig.toml`](/docs/runtime/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
+
+```toml
+preload = ["./myPlugin.ts"]
+```
+
+To preload files before `bun test`:
+
+```toml
+[test]
+preload = ["./myPlugin.ts"]
+```
+
+## Third-party plugins
+
+By convention, third-party plugins intended for consumption should export a factory function that accepts some configuration and returns a plugin object.
+
+```ts
+import { plugin } from "bun";
+import fooPlugin from "bun-plugin-foo";
+
+plugin(
+ fooPlugin({
+ // configuration
+ }),
+);
+```
+
+Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
+
+```jsx
+import { plugin } from "bun";
+import mdx from "@mdx-js/esbuild";
+
+plugin(mdx());
+```
+
+## Loaders
+
+Plugins are primarily used to extend Bun with loaders for additional file types. Let's look at a simple plugin that implements a loader for `.yaml` files.
+
+```ts#yamlPlugin.ts
+import { plugin } from "bun";
+
+plugin({
+ name: "YAML",
+ async setup(build) {
+ const { load } = await import("js-yaml");
+ const { readFileSync } = await import("fs");
+
+ // when a .yaml file is imported...
+ build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
+
+ // read and parse the file
+ const text = readFileSync(args.path, "utf8");
+ const exports = load(text) as Record;
+
+ // and returns it as a module
+ return {
+ exports,
+ loader: "object", // special loader for JS objects
+ };
+ });
+ },
+});
+```
+
+With this plugin, data can be directly imported from `.yaml` files.
+
+{% codetabs %}
+
+```ts#index.ts
+import "./yamlPlugin.ts"
+import {name, releaseYear} from "./data.yml"
+
+console.log(name, releaseYear);
+```
+
+```yaml#data.yml
+name: Fast X
+releaseYear: 2023
+```
+
+{% /codetabs %}
+
+Note that the returned object has a `loader` property. This tells Bun which of its internal loaders should be used to handle the result. Even though we're implementing a loader for `.yaml`, the result must still be understandable by one of Bun's built-in loaders. It's loaders all the way down.
+
+In this case we're using `"object"`—a built-in loader (intended for use by plugins) that converts a plain JavaScript object to an equivalent ES module. Any of Bun's built-in loaders are supported; these same loaders are used by Bun internally for handling files of various kinds. The table below is a quick reference; refer to [Bundler > Loaders](/docs/bundler/loaders) for complete documentation.
+
+{% table %}
+
+- Loader
+- Extensions
+- Output
+
+---
+
+- `js`
+- `.mjs` `.cjs`
+- Transpile to JavaScript files
+
+---
+
+- `jsx`
+- `.js` `.jsx`
+- Transform JSX then transpile
+
+---
+
+- `ts`
+- `.ts` `.mts` `cts`
+- Transform TypeScript then transpile
+
+---
+
+- `tsx`
+- `.tsx`
+- Transform TypeScript, JSX, then transpile
+
+---
+
+- `toml`
+- `.toml`
+- Parse using Bun's built-in TOML parser
+
+---
+
+- `json`
+- `.json`
+- Parse using Bun's built-in JSON parser
+
+---
+
+- `napi`
+- `.node`
+- Import a native Node.js addon
+
+---
+
+- `wasm`
+- `.wasm`
+- Import a native Node.js addon
+
+---
+
+- `object`
+- _none_
+- A special loader intended for plugins that converts a plain JavaScript object to an equivalent ES module. Each key in the object corresponds to a named export.
+
+{% /callout %}
+
+Loading a YAML file is useful, but plugins support more than just data loading. Let's look at a plugin that lets Bun import `*.svelte` files.
+
+```ts#sveltePlugin.ts
+import { plugin } from "bun";
+
+await plugin({
+ name: "svelte loader",
+ async setup(build) {
+ const { compile } = await import("svelte/compiler");
+ const { readFileSync } = await import("fs");
+
+ // when a .svelte file is imported...
+ build.onLoad({ filter: /\.svelte$/ }, ({ path }) => {
+
+ // read and compile it with the Svelte compiler
+ const file = readFileSync(path, "utf8");
+ const contents = compile(file, {
+ filename: path,
+ generate: "ssr",
+ }).js.code;
+
+ // and return the compiled source code as "js"
+ return {
+ contents,
+ loader: "js",
+ };
+ });
+ },
+});
+```
+
+> Note: in a production implementation, you'd want to cache the compiled output and include additional error handling.
+
+The object returned from `build.onLoad` contains the compiled source code in `contents` and specifies `"js"` as its loader. That tells Bun to consider the returned `contents` to be a JavaScript module and transpile it using Bun's built-in `js` loader.
+
+With this plugin, Svelte components can now be directly imported and consumed.
+
+```js
+import "./sveltePlugin.ts";
+import MySvelteComponent from "./component.svelte";
+
+console.log(mySvelteComponent.render());
+```
+
+## Reading the config
+
+Plugins can read and write to the [build config](/docs/bundler#api) with `build.config`.
+
+```ts
+Bun.build({
+ entrypoints: ["./app.ts"],
+ outdir: "./dist",
+ sourcemap: "external",
+ plugins: [
+ {
+ name: "demo",
+ setup(build) {
+ console.log(build.config.sourcemap); // "external"
+
+ build.config.minify = true; // enable minification
+
+ // `plugins` is readonly
+ console.log(`Number of plugins: ${build.config.plugins.length}`);
+ },
+ },
+ ],
+});
+```
+
+## Reference
+
+```ts
+namespace Bun {
+ function plugin(plugin: {
+ name: string;
+ setup: (build: PluginBuilder) => void;
+ }): void;
+}
+
+type PluginBuilder = {
+ onResolve: (
+ args: { filter: RegExp; namespace?: string },
+ callback: (args: { path: string; importer: string }) => {
+ path: string;
+ namespace?: string;
+ } | void,
+ ) => void;
+ onLoad: (
+ args: { filter: RegExp; namespace?: string },
+ callback: (args: { path: string }) => {
+ loader?: Loader;
+ contents?: string;
+ exports?: Record;
+ },
+ ) => void;
+ config: BuildConfig;
+};
+
+type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "object";
+```
+
+The `onLoad` method optionally accepts a `namespace` in addition to the `filter` regex. This namespace will be be used to prefix the import in transpiled code; for instance, a loader with a `filter: /\.yaml$/` and `namespace: "yaml:"` will transform an import from `./myfile.yaml` into `yaml:./myfile.yaml`.
diff --git a/docs/runtime/web-apis.md b/docs/runtime/web-apis.md
index 366fa7819944e6..98c822274fdb42 100644
--- a/docs/runtime/web-apis.md
+++ b/docs/runtime/web-apis.md
@@ -17,7 +17,7 @@ The following Web APIs are partially or completely supported.
---
- Web Workers
-- [`Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Worker) [`self.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/postMessage) [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone). Missing `MessagePort`, `MessageChannel`, `BroadcastChannel`.
+- [`Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Worker) [`self.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope/postMessage) [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel), [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel).
---
diff --git a/docs/test/coverage.md b/docs/test/coverage.md
new file mode 100644
index 00000000000000..229da41f2c45e1
--- /dev/null
+++ b/docs/test/coverage.md
@@ -0,0 +1,57 @@
+`bun:test` supports seeing which lines of code are covered by tests. To use this feature, pass `--coverage` to the CLI:
+
+```sh
+bun test --coverage
+```
+
+It will print out a coverage report to the console:
+
+```js
+-------------|---------|---------|-------------------
+File | % Funcs | % Lines | Uncovered Line #s
+-------------|---------|---------|-------------------
+All files | 38.89 | 42.11 |
+ index-0.ts | 33.33 | 36.84 | 10-15,19-24
+ index-1.ts | 33.33 | 36.84 | 10-15,19-24
+ index-10.ts | 33.33 | 36.84 | 10-15,19-24
+ index-2.ts | 33.33 | 36.84 | 10-15,19-24
+ index-3.ts | 33.33 | 36.84 | 10-15,19-24
+ index-4.ts | 33.33 | 36.84 | 10-15,19-24
+ index-5.ts | 33.33 | 36.84 | 10-15,19-24
+ index-6.ts | 33.33 | 36.84 | 10-15,19-24
+ index-7.ts | 33.33 | 36.84 | 10-15,19-24
+ index-8.ts | 33.33 | 36.84 | 10-15,19-24
+ index-9.ts | 33.33 | 36.84 | 10-15,19-24
+ index.ts | 100.00 | 100.00 |
+-------------|---------|---------|-------------------
+```
+
+If coverage is below a threshold, `bun:test` will exit with a non-zero exit code to indicate the failure.
+
+### Configuring coverage
+
+`bunfig.toml` supports configuring coverage:
+
+```toml
+[test]
+
+# Always enable coverage
+coverage = true
+
+# Anything less than 90% coverage will fail the test
+# coverageThreshold = 0.9
+coverageThreshold = { line = 0.9, function = 0.9 }
+
+
+# Don't include .test.* files in coverage reports
+coverageSkipTestFiles = true
+
+# Disable sourcemap support in coverage reports
+# By default, coverage reports will automatically use Bun's internal sourcemap.
+# You probably don't want to configure this
+# coverageIgnoreSourcemaps = false
+```
+
+`coverageThreshold` can be either a number or an object with `line` and `function` keys. When a number, it is treated as both the line and function threshold.
+
+Coverage support was added in Bun v0.7.3.
diff --git a/docs/test/writing.md b/docs/test/writing.md
index e5e3fe1b0e6169..a99af8b90c5555 100644
--- a/docs/test/writing.md
+++ b/docs/test/writing.md
@@ -101,7 +101,7 @@ test.todo("fix this", () => {
});
```
-To exlusively run tests marked as _todo_, use `bun test --todo`.
+To exclusively run tests marked as _todo_, use `bun test --todo`.
```sh
$ bun test --todo
diff --git a/examples/hashing.js b/examples/hashing.js
index cf4772ffe33905..3f23d1312314d6 100644
--- a/examples/hashing.js
+++ b/examples/hashing.js
@@ -1,18 +1,19 @@
-// Accepts a string, TypedArray, or Blob (file blob supported is not implemented but planned)
+// Accepts a string, TypedArray, or Blob (file blob support is not implemented but planned)
const input = "hello world".repeat(400);
// Bun.hash() defaults to Wyhash because it's fast
console.log(Bun.hash(input));
console.log(Bun.hash.wyhash(input));
-// and returns a number
-// all of these hashing functions return numbers, not typed arrays.
-console.log(Bun.hash.adler32(input));
-console.log(Bun.hash.crc32(input));
-console.log(Bun.hash.cityHash32(input));
-console.log(Bun.hash.cityHash64(input));
-console.log(Bun.hash.murmur32v3(input));
-console.log(Bun.hash.murmur64v2(input));
+// and returns a bigint
+// all of these hashing functions return number if 32-bit or bigint if 64-bit, not typed arrays.
+console.log(Bun.hash.adler32(input)); // number
+console.log(Bun.hash.crc32(input)); // number
+console.log(Bun.hash.cityHash32(input)); // number
+console.log(Bun.hash.cityHash64(input)); // bigint
+console.log(Bun.hash.murmur32v3(input)); // number
+console.log(Bun.hash.murmur32v2(input)); // number
+console.log(Bun.hash.murmur64v2(input)); // bigint
// Second argument accepts a seed where relevant
console.log(Bun.hash(input, 12345));
diff --git a/examples/macros/matchInFile.tsx b/examples/macros/matchInFile.tsx
index e434d1decce2ce..4793661d99addf 100644
--- a/examples/macros/matchInFile.tsx
+++ b/examples/macros/matchInFile.tsx
@@ -1,12 +1,12 @@
// macro code
-export function matchInFile(callExpression: BunAST.CallExpression) {
+export async function matchInFile(callExpression: BunAST.CallExpression) {
const [filePathNode, matcherNode] = callExpression.arguments;
let filePath: string;
filePath = filePathNode.get();
let matcher: RegExp;
matcher = matcherNode.get();
- const file: string = Bun.readFile(Bun.cwd + filePath);
+ const file: string = await Bun.file(Bun.cwd + filePath).text();
return (
diff --git a/package.json b/package.json
index 9da688e5fccba4..4697689f9c46b0 100644
--- a/package.json
+++ b/package.json
@@ -22,10 +22,9 @@
},
"devDependencies": {
"@types/react": "^18.0.25",
- "@types/ws": "^8.5.5",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
- "bun-webkit": "0.0.1-3a53c6af693c5f387de752b0c793ac1ab5f0a164"
+ "bun-webkit": "0.0.1-74609640b2a7c5a1588b824f870d1b0ff91bfd8e"
},
"version": "0.0.0",
"prettier": "./.prettierrc.cjs"
diff --git a/packages/bun-types/async_hooks.d.ts b/packages/bun-types/async_hooks.d.ts
index e69de29bb2d1d6..43de681caf8834 100644
--- a/packages/bun-types/async_hooks.d.ts
+++ b/packages/bun-types/async_hooks.d.ts
@@ -0,0 +1,554 @@
+/**
+ * We strongly discourage the use of the `async_hooks` API.
+ * Other APIs that can cover most of its use cases include:
+ *
+ * * `AsyncLocalStorage` tracks async context
+ * * `process.getActiveResourcesInfo()` tracks active resources
+ *
+ * The `node:async_hooks` module provides an API to track asynchronous resources.
+ * It can be accessed using:
+ *
+ * ```js
+ * import async_hooks from 'node:async_hooks';
+ * ```
+ * @experimental
+ * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/async_hooks.js)
+ */
+declare module "async_hooks" {
+ /**
+ * ```js
+ * import { executionAsyncId } from 'node:async_hooks';
+ * import fs from 'node:fs';
+ *
+ * console.log(executionAsyncId()); // 1 - bootstrap
+ * fs.open(path, 'r', (err, fd) => {
+ * console.log(executionAsyncId()); // 6 - open()
+ * });
+ * ```
+ *
+ * The ID returned from `executionAsyncId()` is related to execution timing, not
+ * causality (which is covered by `triggerAsyncId()`):
+ *
+ * ```js
+ * const server = net.createServer((conn) => {
+ * // Returns the ID of the server, not of the new connection, because the
+ * // callback runs in the execution scope of the server's MakeCallback().
+ * async_hooks.executionAsyncId();
+ *
+ * }).listen(port, () => {
+ * // Returns the ID of a TickObject (process.nextTick()) because all
+ * // callbacks passed to .listen() are wrapped in a nextTick().
+ * async_hooks.executionAsyncId();
+ * });
+ * ```
+ *
+ * Promise contexts may not get precise `executionAsyncIds` by default.
+ * See the section on `promise execution tracking`.
+ * @since v0.7.0
+ * @return The `asyncId` of the current execution context. Useful to track when something calls.
+ */
+ function executionAsyncId(): number;
+ /**
+ * Resource objects returned by `executionAsyncResource()` are most often internal
+ * Node.js handle objects with undocumented APIs. Using any functions or properties
+ * on the object is likely to crash your application and should be avoided.
+ *
+ * Using `executionAsyncResource()` in the top-level execution context will
+ * return an empty object as there is no handle or request object to use,
+ * but having an object representing the top-level can be helpful.
+ *
+ * ```js
+ * import { open } from 'node:fs';
+ * import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';
+ *
+ * console.log(executionAsyncId(), executionAsyncResource()); // 1 {}
+ * open(new URL(import.meta.url), 'r', (err, fd) => {
+ * console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap
+ * });
+ * ```
+ *
+ * This can be used to implement continuation local storage without the
+ * use of a tracking `Map` to store the metadata:
+ *
+ * ```js
+ * import { createServer } from 'node:http';
+ * import {
+ * executionAsyncId,
+ * executionAsyncResource,
+ * createHook,
+ * } from 'async_hooks';
+ * const sym = Symbol('state'); // Private symbol to avoid pollution
+ *
+ * createHook({
+ * init(asyncId, type, triggerAsyncId, resource) {
+ * const cr = executionAsyncResource();
+ * if (cr) {
+ * resource[sym] = cr[sym];
+ * }
+ * },
+ * }).enable();
+ *
+ * const server = createServer((req, res) => {
+ * executionAsyncResource()[sym] = { state: req.url };
+ * setTimeout(function() {
+ * res.end(JSON.stringify(executionAsyncResource()[sym]));
+ * }, 100);
+ * }).listen(3000);
+ * ```
+ * @since v0.7.0
+ * @return The resource representing the current execution. Useful to store data within the resource.
+ */
+ function executionAsyncResource(): object;
+ /**
+ * ```js
+ * const server = net.createServer((conn) => {
+ * // The resource that caused (or triggered) this callback to be called
+ * // was that of the new connection. Thus the return value of triggerAsyncId()
+ * // is the asyncId of "conn".
+ * async_hooks.triggerAsyncId();
+ *
+ * }).listen(port, () => {
+ * // Even though all callbacks passed to .listen() are wrapped in a nextTick()
+ * // the callback itself exists because the call to the server's .listen()
+ * // was made. So the return value would be the ID of the server.
+ * async_hooks.triggerAsyncId();
+ * });
+ * ```
+ *
+ * Promise contexts may not get valid `triggerAsyncId`s by default. See
+ * the section on `promise execution tracking`.
+ * @return The ID of the resource responsible for calling the callback that is currently being executed.
+ */
+ function triggerAsyncId(): number;
+ interface HookCallbacks {
+ /**
+ * Called when a class is constructed that has the possibility to emit an asynchronous event.
+ * @param asyncId a unique ID for the async resource
+ * @param type the type of the async resource
+ * @param triggerAsyncId the unique ID of the async resource in whose execution context this async resource was created
+ * @param resource reference to the resource representing the async operation, needs to be released during destroy
+ */
+ init?(
+ asyncId: number,
+ type: string,
+ triggerAsyncId: number,
+ resource: object,
+ ): void;
+ /**
+ * When an asynchronous operation is initiated or completes a callback is called to notify the user.
+ * The before callback is called just before said callback is executed.
+ * @param asyncId the unique identifier assigned to the resource about to execute the callback.
+ */
+ before?(asyncId: number): void;
+ /**
+ * Called immediately after the callback specified in before is completed.
+ * @param asyncId the unique identifier assigned to the resource which has executed the callback.
+ */
+ after?(asyncId: number): void;
+ /**
+ * Called when a promise has resolve() called. This may not be in the same execution id
+ * as the promise itself.
+ * @param asyncId the unique id for the promise that was resolve()d.
+ */
+ promiseResolve?(asyncId: number): void;
+ /**
+ * Called after the resource corresponding to asyncId is destroyed
+ * @param asyncId a unique ID for the async resource
+ */
+ destroy?(asyncId: number): void;
+ }
+ interface AsyncHook {
+ /**
+ * Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
+ */
+ enable(): this;
+ /**
+ * Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
+ */
+ disable(): this;
+ }
+ /**
+ * Registers functions to be called for different lifetime events of each async
+ * operation.
+ *
+ * The callbacks `init()`/`before()`/`after()`/`destroy()` are called for the
+ * respective asynchronous event during a resource's lifetime.
+ *
+ * All callbacks are optional. For example, if only resource cleanup needs to
+ * be tracked, then only the `destroy` callback needs to be passed. The
+ * specifics of all functions that can be passed to `callbacks` is in the `Hook Callbacks` section.
+ *
+ * ```js
+ * import { createHook } from 'node:async_hooks';
+ *
+ * const asyncHook = createHook({
+ * init(asyncId, type, triggerAsyncId, resource) { },
+ * destroy(asyncId) { },
+ * });
+ * ```
+ *
+ * The callbacks will be inherited via the prototype chain:
+ *
+ * ```js
+ * class MyAsyncCallbacks {
+ * init(asyncId, type, triggerAsyncId, resource) { }
+ * destroy(asyncId) {}
+ * }
+ *
+ * class MyAddedCallbacks extends MyAsyncCallbacks {
+ * before(asyncId) { }
+ * after(asyncId) { }
+ * }
+ *
+ * const asyncHook = async_hooks.createHook(new MyAddedCallbacks());
+ * ```
+ *
+ * Because promises are asynchronous resources whose lifecycle is tracked
+ * via the async hooks mechanism, the `init()`, `before()`, `after()`, and`destroy()` callbacks _must not_ be async functions that return promises.
+ * @since v0.7.0
+ * @param callbacks The `Hook Callbacks` to register
+ * @return Instance used for disabling and enabling hooks
+ */
+ function createHook(callbacks: HookCallbacks): AsyncHook;
+ interface AsyncResourceOptions {
+ /**
+ * The ID of the execution context that created this async event.
+ * @default executionAsyncId()
+ */
+ triggerAsyncId?: number | undefined;
+ /**
+ * Disables automatic `emitDestroy` when the object is garbage collected.
+ * This usually does not need to be set (even if `emitDestroy` is called
+ * manually), unless the resource's `asyncId` is retrieved and the
+ * sensitive API's `emitDestroy` is called with it.
+ * @default false
+ */
+ requireManualDestroy?: boolean | undefined;
+ }
+ /**
+ * The class `AsyncResource` is designed to be extended by the embedder's async
+ * resources. Using this, users can easily trigger the lifetime events of their
+ * own resources.
+ *
+ * The `init` hook will trigger when an `AsyncResource` is instantiated.
+ *
+ * The following is an overview of the `AsyncResource` API.
+ *
+ * ```js
+ * import { AsyncResource, executionAsyncId } from 'node:async_hooks';
+ *
+ * // AsyncResource() is meant to be extended. Instantiating a
+ * // new AsyncResource() also triggers init. If triggerAsyncId is omitted then
+ * // async_hook.executionAsyncId() is used.
+ * const asyncResource = new AsyncResource(
+ * type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false },
+ * );
+ *
+ * // Run a function in the execution context of the resource. This will
+ * // * establish the context of the resource
+ * // * trigger the AsyncHooks before callbacks
+ * // * call the provided function `fn` with the supplied arguments
+ * // * trigger the AsyncHooks after callbacks
+ * // * restore the original execution context
+ * asyncResource.runInAsyncScope(fn, thisArg, ...args);
+ *
+ * // Call AsyncHooks destroy callbacks.
+ * asyncResource.emitDestroy();
+ *
+ * // Return the unique ID assigned to the AsyncResource instance.
+ * asyncResource.asyncId();
+ *
+ * // Return the trigger ID for the AsyncResource instance.
+ * asyncResource.triggerAsyncId();
+ * ```
+ */
+ class AsyncResource {
+ /**
+ * AsyncResource() is meant to be extended. Instantiating a
+ * new AsyncResource() also triggers init. If triggerAsyncId is omitted then
+ * async_hook.executionAsyncId() is used.
+ * @param type The type of async event.
+ * @param triggerAsyncId The ID of the execution context that created
+ * this async event (default: `executionAsyncId()`), or an
+ * AsyncResourceOptions object (since v9.3.0)
+ */
+ constructor(type: string, triggerAsyncId?: number | AsyncResourceOptions);
+ /**
+ * Binds the given function to the current execution context.
+ * @since v0.7.0
+ * @param fn The function to bind to the current execution context.
+ * @param type An optional name to associate with the underlying `AsyncResource`.
+ */
+ static bind any, ThisArg>(
+ fn: Func,
+ type?: string,
+ thisArg?: ThisArg,
+ ): Func;
+ /**
+ * Binds the given function to execute to this `AsyncResource`'s scope.
+ * @since v0.7.0
+ * @param fn The function to bind to the current `AsyncResource`.
+ */
+ bind any>(fn: Func): Func;
+ /**
+ * Call the provided function with the provided arguments in the execution context
+ * of the async resource. This will establish the context, trigger the AsyncHooks
+ * before callbacks, call the function, trigger the AsyncHooks after callbacks, and
+ * then restore the original execution context.
+ * @since v0.7.0
+ * @param fn The function to call in the execution context of this async resource.
+ * @param thisArg The receiver to be used for the function call.
+ * @param args Optional arguments to pass to the function.
+ */
+ runInAsyncScope(
+ fn: (this: This, ...args: any[]) => Result,
+ thisArg?: This,
+ ...args: any[]
+ ): Result;
+ /**
+ * Call all `destroy` hooks. This should only ever be called once. An error will
+ * be thrown if it is called more than once. This **must** be manually called. If
+ * the resource is left to be collected by the GC then the `destroy` hooks will
+ * never be called.
+ * @return A reference to `asyncResource`.
+ */
+ emitDestroy(): this;
+ /**
+ * @return The unique `asyncId` assigned to the resource.
+ */
+ asyncId(): number;
+ /**
+ *
+ * @return The same `triggerAsyncId` that is passed to the `AsyncResource` constructor.
+ */
+ triggerAsyncId(): number;
+ }
+ /**
+ * This class creates stores that stay coherent through asynchronous operations.
+ *
+ * While you can create your own implementation on top of the `node:async_hooks`module, `AsyncLocalStorage` should be preferred as it is a performant and memory
+ * safe implementation that involves significant optimizations that are non-obvious
+ * to implement.
+ *
+ * The following example uses `AsyncLocalStorage` to build a simple logger
+ * that assigns IDs to incoming HTTP requests and includes them in messages
+ * logged within each request.
+ *
+ * ```js
+ * import http from 'node:http';
+ * import { AsyncLocalStorage } from 'node:async_hooks';
+ *
+ * const asyncLocalStorage = new AsyncLocalStorage();
+ *
+ * function logWithId(msg) {
+ * const id = asyncLocalStorage.getStore();
+ * console.log(`${id !== undefined ? id : '-'}:`, msg);
+ * }
+ *
+ * let idSeq = 0;
+ * http.createServer((req, res) => {
+ * asyncLocalStorage.run(idSeq++, () => {
+ * logWithId('start');
+ * // Imagine any chain of async operations here
+ * setImmediate(() => {
+ * logWithId('finish');
+ * res.end();
+ * });
+ * });
+ * }).listen(8080);
+ *
+ * http.get('http://localhost:8080');
+ * http.get('http://localhost:8080');
+ * // Prints:
+ * // 0: start
+ * // 1: start
+ * // 0: finish
+ * // 1: finish
+ * ```
+ *
+ * Each instance of `AsyncLocalStorage` maintains an independent storage context.
+ * Multiple instances can safely exist simultaneously without risk of interfering
+ * with each other's data.
+ * @since v0.7.0
+ */
+ class AsyncLocalStorage {
+ /**
+ * Binds the given function to the current execution context.
+ * @since v0.7.0
+ * @experimental
+ * @param fn The function to bind to the current execution context.
+ * @return A new function that calls `fn` within the captured execution context.
+ */
+ static bind any>(fn: Func): Func;
+ /**
+ * Captures the current execution context and returns a function that accepts a
+ * function as an argument. Whenever the returned function is called, it
+ * calls the function passed to it within the captured context.
+ *
+ * ```js
+ * const asyncLocalStorage = new AsyncLocalStorage();
+ * const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot());
+ * const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore()));
+ * console.log(result); // returns 123
+ * ```
+ *
+ * AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple
+ * async context tracking purposes, for example:
+ *
+ * ```js
+ * class Foo {
+ * #runInAsyncScope = AsyncLocalStorage.snapshot();
+ *
+ * get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); }
+ * }
+ *
+ * const foo = asyncLocalStorage.run(123, () => new Foo());
+ * console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123
+ * ```
+ * @since v0.7.0
+ * @experimental
+ * @return A new function with the signature `(fn: (...args) : R, ...args) : R`.
+ */
+ static snapshot(): (
+ fn: (...args: TArgs) => R,
+ ...args: TArgs
+ ) => R;
+ /**
+ * Disables the instance of `AsyncLocalStorage`. All subsequent calls
+ * to `asyncLocalStorage.getStore()` will return `undefined` until`asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()` is called again.
+ *
+ * When calling `asyncLocalStorage.disable()`, all current contexts linked to the
+ * instance will be exited.
+ *
+ * Calling `asyncLocalStorage.disable()` is required before the`asyncLocalStorage` can be garbage collected. This does not apply to stores
+ * provided by the `asyncLocalStorage`, as those objects are garbage collected
+ * along with the corresponding async resources.
+ *
+ * Use this method when the `asyncLocalStorage` is not in use anymore
+ * in the current process.
+ * @since v0.7.0
+ * @experimental
+ */
+ disable(): void;
+ /**
+ * Returns the current store.
+ * If called outside of an asynchronous context initialized by
+ * calling `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()`, it
+ * returns `undefined`.
+ * @since v0.7.0
+ */
+ getStore(): T | undefined;
+ /**
+ * Runs a function synchronously within a context and returns its
+ * return value. The store is not accessible outside of the callback function.
+ * The store is accessible to any asynchronous operations created within the
+ * callback.
+ *
+ * The optional `args` are passed to the callback function.
+ *
+ * If the callback function throws an error, the error is thrown by `run()` too.
+ * The stacktrace is not impacted by this call and the context is exited.
+ *
+ * Example:
+ *
+ * ```js
+ * const store = { id: 2 };
+ * try {
+ * asyncLocalStorage.run(store, () => {
+ * asyncLocalStorage.getStore(); // Returns the store object
+ * setTimeout(() => {
+ * asyncLocalStorage.getStore(); // Returns the store object
+ * }, 200);
+ * throw new Error();
+ * });
+ * } catch (e) {
+ * asyncLocalStorage.getStore(); // Returns undefined
+ * // The error will be caught here
+ * }
+ * ```
+ * @since v0.7.0
+ */
+ run(
+ store: T,
+ callback: (...args: TArgs) => R,
+ ...args: TArgs
+ ): R;
+ /**
+ * Runs a function synchronously outside of a context and returns its
+ * return value. The store is not accessible within the callback function or
+ * the asynchronous operations created within the callback. Any `getStore()`call done within the callback function will always return `undefined`.
+ *
+ * The optional `args` are passed to the callback function.
+ *
+ * If the callback function throws an error, the error is thrown by `exit()` too.
+ * The stacktrace is not impacted by this call and the context is re-entered.
+ *
+ * Example:
+ *
+ * ```js
+ * // Within a call to run
+ * try {
+ * asyncLocalStorage.getStore(); // Returns the store object or value
+ * asyncLocalStorage.exit(() => {
+ * asyncLocalStorage.getStore(); // Returns undefined
+ * throw new Error();
+ * });
+ * } catch (e) {
+ * asyncLocalStorage.getStore(); // Returns the same object or value
+ * // The error will be caught here
+ * }
+ * ```
+ * @since v0.7.0
+ * @experimental
+ */
+ exit(
+ callback: (...args: TArgs) => R,
+ ...args: TArgs
+ ): R;
+ /**
+ * Transitions into the context for the remainder of the current
+ * synchronous execution and then persists the store through any following
+ * asynchronous calls.
+ *
+ * Example:
+ *
+ * ```js
+ * const store = { id: 1 };
+ * // Replaces previous store with the given store object
+ * asyncLocalStorage.enterWith(store);
+ * asyncLocalStorage.getStore(); // Returns the store object
+ * someAsyncOperation(() => {
+ * asyncLocalStorage.getStore(); // Returns the same object
+ * });
+ * ```
+ *
+ * This transition will continue for the _entire_ synchronous execution.
+ * This means that if, for example, the context is entered within an event
+ * handler subsequent event handlers will also run within that context unless
+ * specifically bound to another context with an `AsyncResource`. That is why`run()` should be preferred over `enterWith()` unless there are strong reasons
+ * to use the latter method.
+ *
+ * ```js
+ * const store = { id: 1 };
+ *
+ * emitter.on('my-event', () => {
+ * asyncLocalStorage.enterWith(store);
+ * });
+ * emitter.on('my-event', () => {
+ * asyncLocalStorage.getStore(); // Returns the same object
+ * });
+ *
+ * asyncLocalStorage.getStore(); // Returns undefined
+ * emitter.emit('my-event');
+ * asyncLocalStorage.getStore(); // Returns the same object
+ * ```
+ * @since v0.7.0
+ * @experimental
+ */
+ enterWith(store: T): void;
+ }
+}
+
+declare module "node:async_hooks" {
+ export * from "async_hooks";
+}
diff --git a/packages/bun-types/bun-test.d.ts b/packages/bun-types/bun-test.d.ts
index 5182f7e93986b7..790d8bfea53080 100644
--- a/packages/bun-types/bun-test.d.ts
+++ b/packages/bun-types/bun-test.d.ts
@@ -169,6 +169,25 @@ declare module "bun:test" {
* @param condition if these tests should be skipped
*/
skipIf(condition: boolean): (label: string, fn: () => void) => void;
+ /**
+ * Returns a function that runs for each item in `table`.
+ *
+ * @param table Array of Arrays with the arguments that are passed into the test fn for each row.
+ */
+ each>(
+ table: ReadonlyArray,
+ ): (
+ label: string,
+ fn: (...args: T) => void | Promise,
+ options?: number | TestOptions,
+ ) => void;
+ each(
+ table: ReadonlyArray,
+ ): (
+ label: string,
+ fn: (arg: T) => void | Promise,
+ options?: number | TestOptions,
+ ) => void;
};
/**
* Describes a group of related tests.
@@ -395,6 +414,25 @@ declare module "bun:test" {
| ((done: (err?: unknown) => void) => void),
options?: number | TestOptions,
) => void;
+ /**
+ * Returns a function that runs for each item in `table`.
+ *
+ * @param table Array of Arrays with the arguments that are passed into the test fn for each row.
+ */
+ each>(
+ table: ReadonlyArray,
+ ): (
+ label: string,
+ fn: (...args: T) => void | Promise,
+ options?: number | TestOptions,
+ ) => void;
+ each(
+ table: ReadonlyArray,
+ ): (
+ label: string,
+ fn: (arg: T, done: (err?: unknown) => void) => void | Promise,
+ options?: number | TestOptions,
+ ) => void;
};
/**
* Runs a test.
@@ -426,7 +464,7 @@ declare module "bun:test" {
* @param actual the actual value
*/
export const expect: {
- (actual: unknown): Expect;
+ (actual?: unknown): Expect;
any: (
constructor: ((..._: any[]) => any) | { new (..._: any[]): any },
) => Expect;
@@ -468,6 +506,30 @@ declare module "bun:test" {
* expect(Promise.reject("error")).rejects.toBe("error");
*/
rejects: Expect;
+ /**
+ * Assertion which passes.
+ *
+ * @link https://jest-extended.jestcommunity.dev/docs/matchers/pass
+ * @example
+ * expect().pass();
+ * expect().pass("message is optional");
+ * expect().not.pass();
+ * expect().not.pass("hi");
+ *
+ * @param message the message to display if the test fails (optional)
+ */
+ pass: (message?: string) => void;
+ /**
+ * Assertion which fails.
+ *
+ * @link https://jest-extended.jestcommunity.dev/docs/matchers/fail
+ * @example
+ * expect().fail();
+ * expect().fail("message is optional");
+ * expect().not.fail();
+ * expect().not.fail("hi");
+ */
+ fail: (message?: string) => void;
/**
* Asserts that a value equals what is expected.
*
@@ -957,6 +1019,23 @@ declare module "bun:test" {
* @param expected the expected substring
*/
toInclude(expected: string): void;
+ /**
+ * Asserts that a value includes a `string` {times} times.
+ * @param expected the expected substring
+ * @param times the number of times the substring should occur
+ */
+ toIncludeRepeated(expected: string, times: number): void;
+ /**
+ * Checks whether a value satisfies a custom condition.
+ * @param {Function} predicate - The custom condition to be satisfied. It should be a function that takes a value as an argument (in this case the value from expect) and returns a boolean.
+ * @example
+ * expect(1).toSatisfy((val) => val > 0);
+ * expect("foo").toSatisfy((val) => val === "foo");
+ * expect("bar").not.toSatisfy((val) => val === "bun");
+ * @link https://vitest.dev/api/expect.html#tosatisfy
+ * @link https://jest-extended.jestcommunity.dev/docs/matchers/toSatisfy
+ */
+ toSatisfy(predicate: (value: T) => boolean): void;
/**
* Asserts that a value starts with a `string`.
*
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index efd8a91b685235..20f247d91c84e9 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -3179,6 +3179,11 @@ declare module "bun" {
const plugin: BunRegisterPlugin;
+ /**
+ * Is the current global scope the main thread?
+ */
+ const isMainThread: boolean;
+
interface Socket {
/**
* Write `data` to the socket
diff --git a/packages/bun-types/diagnostics_channel.d.ts b/packages/bun-types/diagnostics_channel.d.ts
new file mode 100644
index 00000000000000..afc63c922b3cf3
--- /dev/null
+++ b/packages/bun-types/diagnostics_channel.d.ts
@@ -0,0 +1,254 @@
+/**
+ * The `node:diagnostics_channel` module provides an API to create named channels
+ * to report arbitrary message data for diagnostics purposes.
+ *
+ * It can be accessed using:
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ * ```
+ *
+ * It is intended that a module writer wanting to report diagnostics messages
+ * will create one or many top-level channels to report messages through.
+ * Channels may also be acquired at runtime but it is not encouraged
+ * due to the additional overhead of doing so. Channels may be exported for
+ * convenience, but as long as the name is known it can be acquired anywhere.
+ *
+ * If you intend for your module to produce diagnostics data for others to
+ * consume it is recommended that you include documentation of what named
+ * channels are used along with the shape of the message data. Channel names
+ * should generally include the module name to avoid collisions with data from
+ * other modules.
+ * @since Bun v0.7.2
+ * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/diagnostics_channel.js)
+ */
+declare module "diagnostics_channel" {
+ import { AsyncLocalStorage } from "async_hooks";
+ // type AsyncLocalStorage = import("async_hooks").AsyncLocalStorage;
+ type ChannelListener = (message: unknown, name: string | symbol) => void;
+ /**
+ * Check if there are active subscribers to the named channel. This is helpful if
+ * the message you want to send might be expensive to prepare.
+ *
+ * This API is optional but helpful when trying to publish messages from very
+ * performance-sensitive code.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * if (diagnostics_channel.hasSubscribers('my-channel')) {
+ * // There are subscribers, prepare and publish message
+ * }
+ * ```
+ * @since Bun v0.7.2
+ * @param name The channel name
+ * @return If there are active subscribers
+ */
+ function hasSubscribers(name: string | symbol): boolean;
+ /**
+ * This is the primary entry-point for anyone wanting to publish to a named
+ * channel. It produces a channel object which is optimized to reduce overhead at
+ * publish time as much as possible.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * const channel = diagnostics_channel.channel('my-channel');
+ * ```
+ * @since Bun v0.7.2
+ * @param name The channel name
+ * @return The named channel object
+ */
+ function channel(name: string | symbol): Channel;
+ /**
+ * Register a message handler to subscribe to this channel. This message handler
+ * will be run synchronously whenever a message is published to the channel. Any
+ * errors thrown in the message handler will trigger an `'uncaughtException'`.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * diagnostics_channel.subscribe('my-channel', (message, name) => {
+ * // Received data
+ * });
+ * ```
+ * @since Bun v0.7.2
+ * @param name The channel name
+ * @param onMessage The handler to receive channel messages
+ */
+ function subscribe(name: string | symbol, onMessage: ChannelListener): void;
+ /**
+ * Remove a message handler previously registered to this channel with {@link subscribe}.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * function onMessage(message, name) {
+ * // Received data
+ * }
+ *
+ * diagnostics_channel.subscribe('my-channel', onMessage);
+ *
+ * diagnostics_channel.unsubscribe('my-channel', onMessage);
+ * ```
+ * @since Bun v0.7.2
+ * @param name The channel name
+ * @param onMessage The previous subscribed handler to remove
+ * @return `true` if the handler was found, `false` otherwise.
+ */
+ function unsubscribe(
+ name: string | symbol,
+ onMessage: ChannelListener,
+ ): boolean;
+ /**
+ * The class `Channel` represents an individual named channel within the data
+ * pipeline. It is used to track subscribers and to publish messages when there
+ * are subscribers present. It exists as a separate object to avoid channel
+ * lookups at publish time, enabling very fast publish speeds and allowing
+ * for heavy use while incurring very minimal cost. Channels are created with {@link channel}, constructing a channel directly
+ * with `new Channel(name)` is not supported.
+ * @since Bun v0.7.2
+ */
+ class Channel {
+ readonly name: string | symbol;
+ /**
+ * Check if there are active subscribers to this channel. This is helpful if
+ * the message you want to send might be expensive to prepare.
+ *
+ * This API is optional but helpful when trying to publish messages from very
+ * performance-sensitive code.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * const channel = diagnostics_channel.channel('my-channel');
+ *
+ * if (channel.hasSubscribers) {
+ * // There are subscribers, prepare and publish message
+ * }
+ * ```
+ * @since Bun v0.7.2
+ */
+ readonly hasSubscribers: boolean;
+ private constructor(name: string | symbol);
+ /**
+ * Publish a message to any subscribers to the channel. This will trigger
+ * message handlers synchronously so they will execute within the same context.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * const channel = diagnostics_channel.channel('my-channel');
+ *
+ * channel.publish({
+ * some: 'message',
+ * });
+ * ```
+ * @since Bun v0.7.2
+ * @param message The message to send to the channel subscribers
+ */
+ publish(message: unknown): void;
+ /**
+ * Register a message handler to subscribe to this channel. This message handler
+ * will be run synchronously whenever a message is published to the channel. Any
+ * errors thrown in the message handler will trigger an `'uncaughtException'`.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * const channel = diagnostics_channel.channel('my-channel');
+ *
+ * channel.subscribe((message, name) => {
+ * // Received data
+ * });
+ * ```
+ * @since Bun v0.7.2
+ * @deprecated Use {@link subscribe(name, onMessage)}
+ * @param onMessage The handler to receive channel messages
+ */
+ subscribe(onMessage: ChannelListener): void;
+ /**
+ * Remove a message handler previously registered to this channel with `channel.subscribe(onMessage)`.
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ *
+ * const channel = diagnostics_channel.channel('my-channel');
+ *
+ * function onMessage(message, name) {
+ * // Received data
+ * }
+ *
+ * channel.subscribe(onMessage);
+ *
+ * channel.unsubscribe(onMessage);
+ * ```
+ * @since Bun v0.7.2
+ * @deprecated Use {@link unsubscribe(name, onMessage)}
+ * @param onMessage The previous subscribed handler to remove
+ * @return `true` if the handler was found, `false` otherwise.
+ */
+ unsubscribe(onMessage: ChannelListener): void;
+ bindStore(
+ store: AsyncLocalStorage,
+ transform?: TransformCallback,
+ ): void;
+ unbindStore(store: AsyncLocalStorage): void;
+ runStores(
+ context: unknown,
+ fn: (...args: unknown[]) => unknown,
+ receiver?: unknown,
+ ...args: unknown[]
+ ): any;
+ }
+ type TransformCallback = (value: T) => unknown;
+ type TracingChannelSubscribers = {
+ start?: ChannelListener;
+ end?: ChannelListener;
+ asyncStart?: ChannelListener;
+ asyncEnd?: ChannelListener;
+ error?: ChannelListener;
+ };
+ type TracingChannels = {
+ start: Channel;
+ end: Channel;
+ asyncStart: Channel;
+ asyncEnd: Channel;
+ error: Channel;
+ };
+ class TracingChannel implements TracingChannels {
+ readonly start: Channel;
+ readonly end: Channel;
+ readonly asyncStart: Channel;
+ readonly asyncEnd: Channel;
+ readonly error: Channel;
+ subscribe(subscribers: TracingChannelSubscribers): void;
+ unsubscribe(subscribers: TracingChannelSubscribers): boolean;
+ traceSync(
+ fn: (...values: any[]) => T,
+ context?: any,
+ thisArg?: any,
+ ...args: any[]
+ ): any;
+ tracePromise(
+ fn: (...values: any[]) => Promise,
+ context?: any,
+ thisArg?: any,
+ ...args: any[]
+ ): Promise;
+ traceCallback(
+ fn: (...values: any[]) => T,
+ position?: number,
+ context?: any,
+ thisArg?: any,
+ ...args: any[]
+ ): any;
+ }
+ function tracingChannel(
+ nameOrChannels: string | TracingChannels,
+ ): TracingChannel;
+}
+
+declare module "node:diagnostics_channel" {
+ export * from "diagnostics_channel";
+}
diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts
index 885294b0d7541f..71403eb805e71f 100644
--- a/packages/bun-types/globals.d.ts
+++ b/packages/bun-types/globals.d.ts
@@ -2,7 +2,7 @@
* "blob" is not supported yet
*/
type BinaryType = "nodebuffer" | "arraybuffer" | "blob";
-type Transferable = ArrayBuffer;
+type Transferable = ArrayBuffer | MessagePort;
type MessageEventSource = undefined;
type Encoding = "utf-8" | "windows-1252" | "utf-16";
type Platform =
@@ -366,6 +366,179 @@ declare function structuredClone(
options?: StructuredSerializeOptions,
): T;
+declare var MessagePort: typeof import("worker_threads").MessagePort;
+declare type MessagePort = import("worker_threads").MessagePort;
+declare var MessageChannel: typeof import("worker_threads").MessageChannel;
+declare type MessageChannel = import("worker_threads").MessageChannel;
+declare var BroadcastChannel: typeof import("worker_threads").BroadcastChannel;
+declare type BroadcastChannel = import("worker_threads").BroadcastChannel;
+
+interface AbstractWorkerEventMap {
+ error: ErrorEvent;
+}
+
+interface WorkerEventMap extends AbstractWorkerEventMap {
+ message: MessageEvent;
+ messageerror: MessageEvent;
+ close: CloseEvent;
+ open: Event;
+}
+
+interface AbstractWorker {
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ServiceWorker/error_event) */
+ onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
+ addEventListener(
+ type: K,
+ listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ addEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: K,
+ listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any,
+ options?: boolean | EventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | EventListenerOptions,
+ ): void;
+}
+
+/**
+ * Bun's Web Worker constructor supports some extra options on top of the API browsers have.
+ */
+interface WorkerOptions {
+ /**
+ * A string specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of
+ * the worker, which is mainly useful for debugging purposes.
+ */
+ name?: string;
+
+ /**
+ * Use less memory, but make the worker slower.
+ *
+ * Internally, this sets the heap size configuration in JavaScriptCore to be
+ * the small heap instead of the large heap.
+ */
+ smol?: boolean;
+
+ /**
+ * When `true`, the worker will keep the parent thread alive until the worker is terminated or `unref`'d.
+ * When `false`, the worker will not keep the parent thread alive.
+ *
+ * By default, this is `false`.
+ */
+ ref?: boolean;
+
+ /**
+ * In Bun, this does nothing.
+ */
+ type?: string;
+
+ /**
+ * List of arguments which would be stringified and appended to
+ * `Bun.argv` / `process.argv` in the worker. This is mostly similar to the `data`
+ * but the values will be available on the global `Bun.argv` as if they
+ * were passed as CLI options to the script.
+ */
+ // argv?: any[] | undefined;
+
+ /** If `true` and the first argument is a string, interpret the first argument to the constructor as a script that is executed once the worker is online. */
+ // eval?: boolean | undefined;
+
+ /**
+ * If set, specifies the initial value of process.env inside the Worker thread. As a special value, worker.SHARE_ENV may be used to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread's process.env object affect the other thread as well. Default: process.env.
+ */
+ env?:
+ | Record
+ | typeof import("node:worker_threads")["SHARE_ENV"]
+ | undefined;
+
+ /**
+ * In Bun, this does nothing.
+ */
+ credentials?: string;
+
+ /**
+ * @default true
+ */
+ // trackUnmanagedFds?: boolean;
+
+ // resourceLimits?: import("worker_threads").ResourceLimits;
+}
+
+interface Worker extends EventTarget, AbstractWorker {
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/message_event) */
+ onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/messageerror_event) */
+ onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
+ /**
+ * Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/postMessage)
+ */
+ postMessage(message: any, transfer: Transferable[]): void;
+ postMessage(message: any, options?: StructuredSerializeOptions): void;
+ /**
+ * Aborts worker's associated global environment.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/terminate)
+ */
+ terminate(): void;
+ addEventListener(
+ type: K,
+ listener: (this: Worker, ev: WorkerEventMap[K]) => any,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ addEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: K,
+ listener: (this: Worker, ev: WorkerEventMap[K]) => any,
+ options?: boolean | EventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | EventListenerOptions,
+ ): void;
+
+ /**
+ * Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default
+ * behavior). If the worker is `ref()`ed, calling `ref()` again has
+ * no effect.
+ * @since v10.5.0
+ */
+ ref(): void;
+ /**
+ * Calling `unref()` on a worker allows the thread to exit if this is the only
+ * active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect.
+ * @since v10.5.0
+ */
+ unref(): void;
+
+ threadId: number;
+}
+
+declare var Worker: {
+ prototype: Worker;
+ new (scriptURL: string | URL, options?: WorkerOptions): Worker;
+ /**
+ * This is the cloned value of the `data` property passed to `new Worker()`
+ *
+ * This is Bun's equivalent of `workerData` in Node.js.
+ */
+ data: any;
+};
+
interface EncodeIntoResult {
/**
* The read Unicode code units of input.
@@ -560,7 +733,7 @@ declare module "node:process" {
interface BlobInterface {
text(): Promise;
arrayBuffer(): Promise;
- json(): Promise;
+ json(): Promise;
formData(): Promise;
}
@@ -699,14 +872,7 @@ declare var FormData: {
new (): FormData;
};
-declare class Blob implements BlobInterface {
- /**
- * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
- *
- * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects
- * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
- */
- constructor(parts?: BlobPart[], options?: BlobPropertyBag);
+declare interface Blob {
/**
* Create a new view **without 🚫 copying** the underlying data.
*
@@ -763,7 +929,7 @@ declare class Blob implements BlobInterface {
* This first decodes the data from UTF-8, then parses it as JSON.
*
*/
- json(): Promise;
+ json(): Promise;
/**
* Read the data from the blob as a {@link FormData} object.
@@ -782,6 +948,16 @@ declare class Blob implements BlobInterface {
type: string;
readonly size: number;
}
+declare var Blob: {
+ prototype: Blob;
+ /**
+ * Create a new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+ *
+ * @param `parts` - An array of strings, numbers, BufferSource, or [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects
+ * @param `options` - An object containing properties to be added to the [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+ */
+ new (parts?: BlobPart[], options?: BlobPropertyBag): Blob;
+};
interface ResponseInit {
headers?: HeadersInit;
@@ -920,7 +1096,7 @@ declare class Response implements BlobInterface {
* This first decodes the data from UTF-8, then parses it as JSON.
*
*/
- json(): Promise;
+ json(): Promise;
/**
* Read the data from the Response as a Blob.
@@ -1181,7 +1357,7 @@ declare class Request implements BlobInterface {
* This first decodes the data from UTF-8, then parses it as JSON.
*
*/
- json(): Promise;
+ json(): Promise;
/**
* Consume the [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) body as a `Blob`.
@@ -1468,24 +1644,6 @@ declare class ShadowRealm {
evaluate(sourceText: string): any;
}
-interface Blob {
- /**
- * Read the contents of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) as a JSON object
- * @warn in browsers, this function is only available for `Response` and `Request`
- */
- json(): Promise;
- /**
- * Read the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) as a UTF-8 string
- * @link https://developer.mozilla.org/en-US/docs/Web/API/Blob/text
- */
- text(): Promise;
- /**
- * Read the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) as an ArrayBuffer object
- * @link https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
- */
- arrayBuffer(): Promise;
-}
-
declare var performance: {
/**
* Milliseconds since Bun.js started
@@ -1891,6 +2049,8 @@ interface MessageEvent extends Event {
readonly lastEventId: string;
/** Returns the origin of the message, for server-sent events and cross-document messaging. */
readonly origin: string;
+ /** Returns the MessagePort array sent with the message, for cross-document messaging and channel messaging. */
+ readonly ports: ReadonlyArray;
readonly source: MessageEventSource;
/** @deprecated */
initMessageEvent(
@@ -3494,43 +3654,17 @@ declare module "*.txt" {
export = text;
}
+declare module "*.toml" {
+ var contents: unknown;
+ export = contents;
+}
+
interface EventSourceEventMap {
error: Event;
message: MessageEvent;
open: Event;
}
-interface Worker extends EventTarget {
- onerror: ((this: Worker, ev: ErrorEvent) => any) | null;
- onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
- onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
-
- addEventListener(
- type: K,
- listener: (this: Worker, ev: WorkerEventMap[K]) => any,
- options?: boolean | AddEventListenerOptions,
- ): void;
-
- removeEventListener(
- type: K,
- listener: (this: Worker, ev: WorkerEventMap[K]) => any,
- options?: boolean | EventListenerOptions,
- ): void;
-
- terminate(): void;
-
- postMessage(message: any, transfer?: Transferable[]): void;
-
- /**
- * Keep the process alive until the worker is terminated or `unref`'d
- */
- ref(): void;
- /**
- * Undo a previous `ref()`
- */
- unref(): void;
-}
-
/**
* Post a message to the parent thread.
*
@@ -3538,44 +3672,6 @@ interface Worker extends EventTarget {
*/
declare function postMessage(message: any, transfer?: Transferable[]): void;
-declare var Worker: {
- prototype: Worker;
- new (stringUrl: string | URL, options?: WorkerOptions): Worker;
-};
-
-interface WorkerOptions {
- name?: string;
-
- /**
- * Use less memory, but make the worker slower.
- *
- * Internally, this sets the heap size configuration in JavaScriptCore to be
- * the small heap instead of the large heap.
- */
- smol?: boolean;
-
- /**
- * When `true`, the worker will keep the parent thread alive until the worker is terminated or `unref`'d.
- * When `false`, the worker will not keep the parent thread alive.
- *
- * By default, this is `false`.
- */
- ref?: boolean;
-
- /**
- * Does nothing in Bun
- */
- type?: string
-}
-
-interface WorkerEventMap {
- message: MessageEvent;
- messageerror: MessageEvent;
- error: ErrorEvent;
- open: Event;
- close: Event;
-}
-
interface EventSource extends EventTarget {
onerror: ((this: EventSource, ev: ErrorEvent) => any) | null;
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null;
@@ -3648,3 +3744,31 @@ declare var EventSource: {
readonly CONNECTING: number;
readonly OPEN: number;
};
+
+interface PromiseConstructor {
+ /**
+ * Create a deferred promise, with exposed `resolve` and `reject` methods which can be called
+ * separately.
+ *
+ * This is useful when you want to return a Promise and have code outside the Promise
+ * resolve or reject it.
+ *
+ * ## Example
+ * ```ts
+ * const { promise, resolve, reject } = Promise.withResolvers();
+ *
+ * setTimeout(() => {
+ * resolve("Hello world!");
+ * }, 1000);
+ *
+ * await promise; // "Hello world!"
+ * ```
+ *
+ * `Promise.withResolvers()` is a [stage3 proposal](https://github.com/tc39/proposal-promise-with-resolvers).
+ */
+ withResolvers(): {
+ promise: Promise;
+ resolve: (value?: T | PromiseLike) => void;
+ reject: (reason?: any) => void;
+ };
+}
diff --git a/packages/bun-types/index.d.ts b/packages/bun-types/index.d.ts
index 981a4dbc72eb6a..e5f866c2102fde 100644
--- a/packages/bun-types/index.d.ts
+++ b/packages/bun-types/index.d.ts
@@ -6,6 +6,7 @@
///
///
///
+///
///
///
///
@@ -13,6 +14,7 @@
///
///
///
+///
///
///
///
@@ -42,4 +44,7 @@
///
///
///
+///
+///
+///
///
diff --git a/packages/bun-types/perf_hooks.d.ts b/packages/bun-types/perf_hooks.d.ts
index 792223e6b1f550..587602a2652b35 100644
--- a/packages/bun-types/perf_hooks.d.ts
+++ b/packages/bun-types/perf_hooks.d.ts
@@ -145,16 +145,19 @@ declare module "perf_hooks" {
// */
// readonly v8Start: number;
// }
- // interface EventLoopUtilization {
- // idle: number;
- // active: number;
- // utilization: number;
- // }
+ interface EventLoopUtilization {
+ idle: number;
+ active: number;
+ utilization: number;
+ }
// /**
// * @param util1 The result of a previous call to eventLoopUtilization()
// * @param util2 The result of a previous call to eventLoopUtilization() prior to util1
// */
- // type EventLoopUtilityFunction = (util1?: EventLoopUtilization, util2?: EventLoopUtilization) => EventLoopUtilization;
+ type EventLoopUtilityFunction = (
+ util1?: EventLoopUtilization,
+ util2?: EventLoopUtilization,
+ ) => EventLoopUtilization;
// interface MarkOptions {
// /**
// * Additional optional detail to include with the mark.
diff --git a/packages/bun-types/tests/broadcast.test-d.ts b/packages/bun-types/tests/broadcast.test-d.ts
new file mode 100644
index 00000000000000..ea5f8cb054eec0
--- /dev/null
+++ b/packages/bun-types/tests/broadcast.test-d.ts
@@ -0,0 +1,11 @@
+const channel = new BroadcastChannel("my-channel");
+const message = { hello: "world" };
+
+channel.onmessage = event => {
+ console.log(event.data); // { hello: "world" }
+};
+channel.postMessage(message);
+
+const error = new Error("hello world");
+const clone = structuredClone(error);
+console.log(clone.message); // "hello world"
diff --git a/packages/bun-types/tests/diag.test-d.ts b/packages/bun-types/tests/diag.test-d.ts
new file mode 100644
index 00000000000000..35f41ce050664d
--- /dev/null
+++ b/packages/bun-types/tests/diag.test-d.ts
@@ -0,0 +1,12 @@
+import diagnostics_channel from "diagnostics_channel";
+
+// Create a channel object
+const channel = diagnostics_channel.channel("my-channel");
+
+// Subscribe to the channel
+channel.subscribe((message, name) => {
+ console.log("Received message:", message);
+});
+
+// Publish a message to the channel
+channel.publish({ some: "data" });
diff --git a/packages/bun-types/tests/fs.test-d.ts b/packages/bun-types/tests/fs.test-d.ts
index 3acfafa76b616a..a752889df82024 100644
--- a/packages/bun-types/tests/fs.test-d.ts
+++ b/packages/bun-types/tests/fs.test-d.ts
@@ -13,3 +13,5 @@ watch(".", (eventType, filename) => {
console.log(`filename = ${filename}`);
}
});
+
+Bun.file("sdf").exists();
diff --git a/packages/bun-types/tests/globals.test-d.ts b/packages/bun-types/tests/globals.test-d.ts
index 64b37be139716f..a5441f20120e09 100644
--- a/packages/bun-types/tests/globals.test-d.ts
+++ b/packages/bun-types/tests/globals.test-d.ts
@@ -93,3 +93,6 @@ new Request("", { method: "POST" });
Bun.sleepSync(1); // sleep for 1 ms (not recommended)
await Bun.sleep(1); // sleep for 1 ms (recommended)
+
+Blob;
+WebSocket;
diff --git a/packages/bun-types/tests/toml.test-d.ts b/packages/bun-types/tests/toml.test-d.ts
new file mode 100644
index 00000000000000..eaf20e7829b80b
--- /dev/null
+++ b/packages/bun-types/tests/toml.test-d.ts
@@ -0,0 +1,4 @@
+import { expectType } from "tsd";
+import data from "../../../bunfig.toml";
+
+expectType(data);
diff --git a/packages/bun-types/tests/worker.test-d.ts b/packages/bun-types/tests/worker.test-d.ts
index 604e0a501c782d..dc457ccaa225de 100644
--- a/packages/bun-types/tests/worker.test-d.ts
+++ b/packages/bun-types/tests/worker.test-d.ts
@@ -1,14 +1,29 @@
-const worker = new Worker("./worker.ts");
-worker.addEventListener("message", (event: MessageEvent) => {
- console.log("Message from worker:", event.data);
+import { Worker as NodeWorker } from "node:worker_threads";
+import * as tsd from "tsd";
+
+const webWorker = new Worker("./worker.js");
+
+webWorker.addEventListener("message", event => {
+ tsd.expectType(event);
+});
+webWorker.addEventListener("error", event => {
+ tsd.expectType(event);
+});
+webWorker.addEventListener("messageerror", event => {
+ tsd.expectType(event);
+});
+
+const nodeWorker = new NodeWorker("./worker.ts");
+nodeWorker.on("message", event => {
+ console.log("Message from worker:", event);
});
-worker.postMessage("Hello from main thread!");
+nodeWorker.postMessage("Hello from main thread!");
const workerURL = new URL("worker.ts", import.meta.url).href;
const _worker2 = new Worker(workerURL);
-worker.postMessage("hello");
-worker.onmessage = event => {
+nodeWorker.postMessage("hello");
+webWorker.onmessage = event => {
console.log(event.data);
};
@@ -16,15 +31,20 @@ worker.onmessage = event => {
postMessage({ hello: "world" });
// On the main thread
-worker.postMessage({ hello: "world" });
+nodeWorker.postMessage({ hello: "world" });
// ...some time later
-worker.terminate();
+nodeWorker.terminate();
// Bun.pathToFileURL
const _worker3 = new Worker(new URL("worker.ts", import.meta.url).href, {
ref: true,
smol: true,
+ credentials: "",
+ name: "a name",
+ env: {
+ envValue: "hello",
+ },
});
-export { worker, _worker2, _worker3 };
+export { nodeWorker as worker, _worker2, _worker3 };
diff --git a/packages/bun-types/tests/ws.test-d.ts b/packages/bun-types/tests/ws.test-d.ts
new file mode 100644
index 00000000000000..fdc4072af2403f
--- /dev/null
+++ b/packages/bun-types/tests/ws.test-d.ts
@@ -0,0 +1,11 @@
+import { WebSocket, WebSocketServer } from "ws";
+
+const ws = new WebSocket("ws://www.host.com/path");
+
+ws.send("asdf");
+
+const wss = new WebSocketServer({
+ port: 8080,
+ perMessageDeflate: false,
+});
+wss;
diff --git a/packages/bun-types/tsconfig.json b/packages/bun-types/tsconfig.json
index e346b31b43a3ab..ad946c2e0a0ec9 100644
--- a/packages/bun-types/tsconfig.json
+++ b/packages/bun-types/tsconfig.json
@@ -1,8 +1,6 @@
{
"compilerOptions": {
- "lib": [
- "ESNext"
- ],
+ "lib": ["ESNext"],
"skipLibCheck": false,
"strict": true,
"target": "esnext",
@@ -10,7 +8,8 @@
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"disableSolutionSearching": true,
- "noUnusedLocals": true
+ "noUnusedLocals": true,
+ "outDir": "build"
},
"exclude": [
"dist",
diff --git a/packages/bun-types/node-vm.d.ts b/packages/bun-types/vm.d.ts
similarity index 100%
rename from packages/bun-types/node-vm.d.ts
rename to packages/bun-types/vm.d.ts
diff --git a/packages/bun-types/worker_threads.d.ts b/packages/bun-types/worker_threads.d.ts
new file mode 100644
index 00000000000000..ddc59fec54f208
--- /dev/null
+++ b/packages/bun-types/worker_threads.d.ts
@@ -0,0 +1,748 @@
+/**
+ * The `worker_threads` module enables the use of threads that execute JavaScript
+ * in parallel. To access it:
+ *
+ * ```js
+ * const worker = require('worker_threads');
+ * ```
+ *
+ * Workers (threads) are useful for performing CPU-intensive JavaScript operations.
+ * They do not help much with I/O-intensive work. The Node.js built-in
+ * asynchronous I/O operations are more efficient than Workers can be.
+ *
+ * Unlike `child_process` or `cluster`, `worker_threads` can share memory. They do
+ * so by transferring `ArrayBuffer` instances or sharing `SharedArrayBuffer`instances.
+ *
+ * ```js
+ * const {
+ * Worker, isMainThread, parentPort, workerData
+ * } = require('worker_threads');
+ *
+ * if (isMainThread) {
+ * module.exports = function parseJSAsync(script) {
+ * return new Promise((resolve, reject) => {
+ * const worker = new Worker(__filename, {
+ * workerData: script
+ * });
+ * worker.on('message', resolve);
+ * worker.on('error', reject);
+ * worker.on('exit', (code) => {
+ * if (code !== 0)
+ * reject(new Error(`Worker stopped with exit code ${code}`));
+ * });
+ * });
+ * };
+ * } else {
+ * const { parse } = require('some-js-parsing-library');
+ * const script = workerData;
+ * parentPort.postMessage(parse(script));
+ * }
+ * ```
+ *
+ * The above example spawns a Worker thread for each `parseJSAsync()` call. In
+ * practice, use a pool of Workers for these kinds of tasks. Otherwise, the
+ * overhead of creating Workers would likely exceed their benefit.
+ *
+ * When implementing a worker pool, use the `AsyncResource` API to inform
+ * diagnostic tools (e.g. to provide asynchronous stack traces) about the
+ * correlation between tasks and their outcomes. See `"Using AsyncResource for a Worker thread pool"` in the `async_hooks` documentation for an example implementation.
+ *
+ * Worker threads inherit non-process-specific options by default. Refer to `Worker constructor options` to know how to customize worker thread options,
+ * specifically `argv` and `execArgv` options.
+ * @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/worker_threads.js)
+ */
+declare module "worker_threads" {
+ // import { Blob } from "node:buffer";
+ import { Readable, Writable } from "node:stream";
+ import { Context } from "node:vm";
+ import { EventEmitter } from "node:events";
+ import { EventLoopUtilityFunction } from "node:perf_hooks";
+ // import { FileHandle } from "node:fs/promises";
+ // import { Readable, Writable } from "node:stream";
+ import { URL } from "node:url";
+ // import { X509Certificate } from "node:crypto";
+ const isMainThread: boolean;
+ const parentPort: null | MessagePort;
+ const resourceLimits: ResourceLimits;
+ const SHARE_ENV: unique symbol;
+ const threadId: number;
+ const workerData: any;
+
+ interface WorkerPerformance {
+ eventLoopUtilization: EventLoopUtilityFunction;
+ }
+ type TransferListItem =
+ | ArrayBuffer
+ | MessagePort
+ // | FileHandle
+ // | X509Certificate
+ | Blob;
+ /**
+ * Instances of the `worker.MessagePort` class represent one end of an
+ * asynchronous, two-way communications channel. It can be used to transfer
+ * structured data, memory regions and other `MessagePort`s between different `Worker` s.
+ *
+ * This implementation matches [browser `MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) s.
+ * @since v10.5.0
+ */
+ class MessagePort extends EventEmitter {
+ /**
+ * Disables further sending of messages on either side of the connection.
+ * This method can be called when no further communication will happen over this`MessagePort`.
+ *
+ * The `'close' event` is emitted on both `MessagePort` instances that
+ * are part of the channel.
+ * @since v10.5.0
+ */
+ close(): void;
+ /**
+ * Sends a JavaScript value to the receiving side of this channel.`value` is transferred in a way which is compatible with
+ * the [HTML structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).
+ *
+ * In particular, the significant differences to `JSON` are:
+ *
+ * * `value` may contain circular references.
+ * * `value` may contain instances of builtin JS types such as `RegExp`s,`BigInt`s, `Map`s, `Set`s, etc.
+ * * `value` may contain typed arrays, both using `ArrayBuffer`s
+ * and `SharedArrayBuffer`s.
+ * * `value` may contain [`WebAssembly.Module`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) instances.
+ * * `value` may not contain native (C++-backed) objects other than:
+ *
+ * ```js
+ * const { MessageChannel } = require('worker_threads');
+ * const { port1, port2 } = new MessageChannel();
+ *
+ * port1.on('message', (message) => console.log(message));
+ *
+ * const circularData = {};
+ * circularData.foo = circularData;
+ * // Prints: { foo: [Circular] }
+ * port2.postMessage(circularData);
+ * ```
+ *
+ * `transferList` may be a list of [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), `MessagePort` and `FileHandle` objects.
+ * After transferring, they are not usable on the sending side of the channel
+ * anymore (even if they are not contained in `value`). Unlike with `child processes`, transferring handles such as network sockets is currently
+ * not supported.
+ *
+ * If `value` contains [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) instances, those are accessible
+ * from either thread. They cannot be listed in `transferList`.
+ *
+ * `value` may still contain `ArrayBuffer` instances that are not in`transferList`; in that case, the underlying memory is copied rather than moved.
+ *
+ * ```js
+ * const { MessageChannel } = require('worker_threads');
+ * const { port1, port2 } = new MessageChannel();
+ *
+ * port1.on('message', (message) => console.log(message));
+ *
+ * const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
+ * // This posts a copy of `uint8Array`:
+ * port2.postMessage(uint8Array);
+ * // This does not copy data, but renders `uint8Array` unusable:
+ * port2.postMessage(uint8Array, [ uint8Array.buffer ]);
+ *
+ * // The memory for the `sharedUint8Array` is accessible from both the
+ * // original and the copy received by `.on('message')`:
+ * const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
+ * port2.postMessage(sharedUint8Array);
+ *
+ * // This transfers a freshly created message port to the receiver.
+ * // This can be used, for example, to create communication channels between
+ * // multiple `Worker` threads that are children of the same parent thread.
+ * const otherChannel = new MessageChannel();
+ * port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);
+ * ```
+ *
+ * The message object is cloned immediately, and can be modified after
+ * posting without having side effects.
+ *
+ * For more information on the serialization and deserialization mechanisms
+ * behind this API, see the `serialization API of the v8 module`.
+ * @since v10.5.0
+ */
+ postMessage(
+ value: any,
+ transferList?: ReadonlyArray,
+ ): void;
+ /**
+ * Opposite of `unref()`. Calling `ref()` on a previously `unref()`ed port does _not_ let the program exit if it's the only active handle left (the default
+ * behavior). If the port is `ref()`ed, calling `ref()` again has no effect.
+ *
+ * If listeners are attached or removed using `.on('message')`, the port
+ * is `ref()`ed and `unref()`ed automatically depending on whether
+ * listeners for the event exist.
+ * @since v10.5.0
+ */
+ ref(): void;
+ /**
+ * Calling `unref()` on a port allows the thread to exit if this is the only
+ * active handle in the event system. If the port is already `unref()`ed calling`unref()` again has no effect.
+ *
+ * If listeners are attached or removed using `.on('message')`, the port is`ref()`ed and `unref()`ed automatically depending on whether
+ * listeners for the event exist.
+ * @since v10.5.0
+ */
+ unref(): void;
+ /**
+ * Starts receiving messages on this `MessagePort`. When using this port
+ * as an event emitter, this is called automatically once `'message'`listeners are attached.
+ *
+ * This method exists for parity with the Web `MessagePort` API. In Node.js,
+ * it is only useful for ignoring messages when no event listener is present.
+ * Node.js also diverges in its handling of `.onmessage`. Setting it
+ * automatically calls `.start()`, but unsetting it lets messages queue up
+ * until a new handler is set or the port is discarded.
+ * @since v10.5.0
+ */
+ start(): void;
+ addListener(event: "close", listener: () => void): this;
+ addListener(event: "message", listener: (value: any) => void): this;
+ addListener(event: "messageerror", listener: (error: Error) => void): this;
+ addListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ emit(event: "close"): boolean;
+ emit(event: "message", value: any): boolean;
+ emit(event: "messageerror", error: Error): boolean;
+ emit(event: string | symbol, ...args: any[]): boolean;
+ on(event: "close", listener: () => void): this;
+ on(event: "message", listener: (value: any) => void): this;
+ on(event: "messageerror", listener: (error: Error) => void): this;
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
+ once(event: "close", listener: () => void): this;
+ once(event: "message", listener: (value: any) => void): this;
+ once(event: "messageerror", listener: (error: Error) => void): this;
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
+ prependListener(event: "close", listener: () => void): this;
+ prependListener(event: "message", listener: (value: any) => void): this;
+ prependListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ prependListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ prependOnceListener(event: "close", listener: () => void): this;
+ prependOnceListener(event: "message", listener: (value: any) => void): this;
+ prependOnceListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ prependOnceListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ removeListener(event: "close", listener: () => void): this;
+ removeListener(event: "message", listener: (value: any) => void): this;
+ removeListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ removeListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ off(event: "close", listener: () => void): this;
+ off(event: "message", listener: (value: any) => void): this;
+ off(event: "messageerror", listener: (error: Error) => void): this;
+ off(event: string | symbol, listener: (...args: any[]) => void): this;
+ }
+ interface WorkerOptions {
+ /**
+ * A string specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of
+ * the worker, which is mainly useful for debugging purposes.
+ */
+ name?: string;
+
+ /**
+ * Use less memory, but make the worker slower.
+ *
+ * Internally, this sets the heap size configuration in JavaScriptCore to be
+ * the small heap instead of the large heap.
+ */
+ smol?: boolean;
+
+ /**
+ * When `true`, the worker will keep the parent thread alive until the worker is terminated or `unref`'d.
+ * When `false`, the worker will not keep the parent thread alive.
+ *
+ * By default, this is `false`.
+ */
+ ref?: boolean;
+
+ /**
+ * In Bun, this does nothing.
+ */
+ type?: string;
+
+ /**
+ * List of arguments which would be stringified and appended to
+ * `Bun.argv` / `process.argv` in the worker. This is mostly similar to the `data`
+ * but the values will be available on the global `Bun.argv` as if they
+ * were passed as CLI options to the script.
+ */
+ // argv?: any[] | undefined;
+
+ /** If `true` and the first argument is a string, interpret the first argument to the constructor as a script that is executed once the worker is online. */
+ // eval?: boolean | undefined;
+
+ /**
+ * If set, specifies the initial value of process.env inside the Worker thread. As a special value, worker.SHARE_ENV may be used to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread's process.env object affect the other thread as well. Default: process.env.
+ */
+ env?:
+ | Record
+ | typeof import("node:worker_threads")["SHARE_ENV"]
+ | undefined;
+
+ /**
+ * In Bun, this does nothing.
+ */
+ credentials?: string;
+
+ /**
+ * @default true
+ */
+ // trackUnmanagedFds?: boolean;
+
+ workerData?: any;
+
+ /**
+ * An array of objects that are transferred rather than cloned when being passed between threads.
+ */
+ transferList?: import("worker_threads").TransferListItem[];
+
+ // resourceLimits?: import("worker_threads").ResourceLimits;
+ // stdin?: boolean | undefined;
+ // stdout?: boolean | undefined;
+ // stderr?: boolean | undefined;
+ // execArgv?: string[] | undefined;
+ }
+ interface ResourceLimits {
+ /**
+ * The maximum size of a heap space for recently created objects.
+ */
+ maxYoungGenerationSizeMb?: number | undefined;
+ /**
+ * The maximum size of the main heap in MB.
+ */
+ maxOldGenerationSizeMb?: number | undefined;
+ /**
+ * The size of a pre-allocated memory range used for generated code.
+ */
+ codeRangeSizeMb?: number | undefined;
+ /**
+ * The default maximum stack size for the thread. Small values may lead to unusable Worker instances.
+ * @default 4
+ */
+ stackSizeMb?: number | undefined;
+ }
+ /**
+ * The `Worker` class represents an independent JavaScript execution thread.
+ * Most Node.js APIs are available inside of it.
+ *
+ * Notable differences inside a Worker environment are:
+ *
+ * * The `process.stdin`, `process.stdout` and `process.stderr` may be redirected by the parent thread.
+ * * The `require('worker_threads').isMainThread` property is set to `false`.
+ * * The `require('worker_threads').parentPort` message port is available.
+ * * `process.exit()` does not stop the whole program, just the single thread,
+ * and `process.abort()` is not available.
+ * * `process.chdir()` and `process` methods that set group or user ids
+ * are not available.
+ * * `process.env` is a copy of the parent thread's environment variables,
+ * unless otherwise specified. Changes to one copy are not visible in other
+ * threads, and are not visible to native add-ons (unless `worker.SHARE_ENV` is passed as the `env` option to the `Worker` constructor).
+ * * `process.title` cannot be modified.
+ * * Signals are not delivered through `process.on('...')`.
+ * * Execution may stop at any point as a result of `worker.terminate()` being invoked.
+ * * IPC channels from parent processes are not accessible.
+ * * The `trace_events` module is not supported.
+ * * Native add-ons can only be loaded from multiple threads if they fulfill `certain conditions`.
+ *
+ * Creating `Worker` instances inside of other `Worker`s is possible.
+ *
+ * Like [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) and the `cluster module`, two-way communication can be
+ * achieved through inter-thread message passing. Internally, a `Worker` has a
+ * built-in pair of `MessagePort` s that are already associated with each other
+ * when the `Worker` is created. While the `MessagePort` object on the parent side
+ * is not directly exposed, its functionalities are exposed through `worker.postMessage()` and the `worker.on('message')` event
+ * on the `Worker` object for the parent thread.
+ *
+ * To create custom messaging channels (which is encouraged over using the default
+ * global channel because it facilitates separation of concerns), users can create
+ * a `MessageChannel` object on either thread and pass one of the`MessagePort`s on that `MessageChannel` to the other thread through a
+ * pre-existing channel, such as the global one.
+ *
+ * See `port.postMessage()` for more information on how messages are passed,
+ * and what kind of JavaScript values can be successfully transported through
+ * the thread barrier.
+ *
+ * ```js
+ * const assert = require('assert');
+ * const {
+ * Worker, MessageChannel, MessagePort, isMainThread, parentPort
+ * } = require('worker_threads');
+ * if (isMainThread) {
+ * const worker = new Worker(__filename);
+ * const subChannel = new MessageChannel();
+ * worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
+ * subChannel.port2.on('message', (value) => {
+ * console.log('received:', value);
+ * });
+ * } else {
+ * parentPort.once('message', (value) => {
+ * assert(value.hereIsYourPort instanceof MessagePort);
+ * value.hereIsYourPort.postMessage('the worker is sending this');
+ * value.hereIsYourPort.close();
+ * });
+ * }
+ * ```
+ * @since v10.5.0
+ */
+ class Worker extends EventEmitter {
+ /**
+ * If `stdin: true` was passed to the `Worker` constructor, this is a
+ * writable stream. The data written to this stream will be made available in
+ * the worker thread as `process.stdin`.
+ * @since v10.5.0
+ */
+ readonly stdin: Writable | null;
+ /**
+ * This is a readable stream which contains data written to `process.stdout` inside the worker thread. If `stdout: true` was not passed to the `Worker` constructor, then data is piped to the
+ * parent thread's `process.stdout` stream.
+ * @since v10.5.0
+ */
+ readonly stdout: Readable;
+ /**
+ * This is a readable stream which contains data written to `process.stderr` inside the worker thread. If `stderr: true` was not passed to the `Worker` constructor, then data is piped to the
+ * parent thread's `process.stderr` stream.
+ * @since v10.5.0
+ */
+ readonly stderr: Readable;
+ /**
+ * 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
+ */
+ readonly threadId: number;
+ /**
+ * Provides the set of JS engine resource constraints for this Worker thread.
+ * If the `resourceLimits` option was passed to the `Worker` constructor,
+ * this matches its values.
+ *
+ * If the worker has stopped, the return value is an empty object.
+ * @since v13.2.0, v12.16.0
+ */
+ readonly resourceLimits?: ResourceLimits | undefined;
+ /**
+ * An object that can be used to query performance information from a worker
+ * instance. Similar to `perf_hooks.performance`.
+ * @since v15.1.0, v14.17.0, v12.22.0
+ */
+ readonly performance: WorkerPerformance;
+ /**
+ * @param filename The path to the Worker’s main script or module.
+ * Must be either an absolute path or a relative path (i.e. relative to the current working directory) starting with ./ or ../,
+ * or a WHATWG URL object using file: protocol. If options.eval is true, this is a string containing JavaScript code rather than a path.
+ */
+ constructor(filename: string | URL, options?: WorkerOptions);
+ /**
+ * Send a message to the worker that is received via `require('node:worker_threads').parentPort.on('message')`.
+ * See `port.postMessage()` for more details.
+ * @since v10.5.0
+ */
+ postMessage(
+ value: any,
+ transferList?: ReadonlyArray,
+ ): void;
+ /**
+ * Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default
+ * behavior). If the worker is `ref()`ed, calling `ref()` again has
+ * no effect.
+ * @since v10.5.0
+ */
+ ref(): void;
+ /**
+ * Calling `unref()` on a worker allows the thread to exit if this is the only
+ * active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect.
+ * @since v10.5.0
+ */
+ unref(): void;
+ /**
+ * Stop all JavaScript execution in the worker thread as soon as possible.
+ * Returns a Promise for the exit code that is fulfilled when the `'exit' event` is emitted.
+ * @since v10.5.0
+ */
+ terminate(): Promise;
+ /**
+ * Returns a readable stream for a V8 snapshot of the current state of the Worker.
+ * See `v8.getHeapSnapshot()` for more details.
+ *
+ * If the Worker thread is no longer running, which may occur before the `'exit' event` is emitted, the returned `Promise` is rejected
+ * immediately with an `ERR_WORKER_NOT_RUNNING` error.
+ * @since v13.9.0, v12.17.0
+ * @return A promise for a Readable Stream containing a V8 heap snapshot
+ */
+ getHeapSnapshot(): Promise;
+ addListener(event: "error", listener: (err: Error) => void): this;
+ addListener(event: "exit", listener: (exitCode: number) => void): this;
+ addListener(event: "message", listener: (value: any) => void): this;
+ addListener(event: "messageerror", listener: (error: Error) => void): this;
+ addListener(event: "online", listener: () => void): this;
+ addListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ emit(event: "error", err: Error): boolean;
+ emit(event: "exit", exitCode: number): boolean;
+ emit(event: "message", value: any): boolean;
+ emit(event: "messageerror", error: Error): boolean;
+ emit(event: "online"): boolean;
+ emit(event: string | symbol, ...args: any[]): boolean;
+ on(event: "error", listener: (err: Error) => void): this;
+ on(event: "exit", listener: (exitCode: number) => void): this;
+ on(event: "message", listener: (value: any) => void): this;
+ on(event: "messageerror", listener: (error: Error) => void): this;
+ on(event: "online", listener: () => void): this;
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
+ once(event: "error", listener: (err: Error) => void): this;
+ once(event: "exit", listener: (exitCode: number) => void): this;
+ once(event: "message", listener: (value: any) => void): this;
+ once(event: "messageerror", listener: (error: Error) => void): this;
+ once(event: "online", listener: () => void): this;
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
+ prependListener(event: "error", listener: (err: Error) => void): this;
+ prependListener(event: "exit", listener: (exitCode: number) => void): this;
+ prependListener(event: "message", listener: (value: any) => void): this;
+ prependListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ prependListener(event: "online", listener: () => void): this;
+ prependListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ prependOnceListener(event: "error", listener: (err: Error) => void): this;
+ prependOnceListener(
+ event: "exit",
+ listener: (exitCode: number) => void,
+ ): this;
+ prependOnceListener(event: "message", listener: (value: any) => void): this;
+ prependOnceListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ prependOnceListener(event: "online", listener: () => void): this;
+ prependOnceListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ removeListener(event: "error", listener: (err: Error) => void): this;
+ removeListener(event: "exit", listener: (exitCode: number) => void): this;
+ removeListener(event: "message", listener: (value: any) => void): this;
+ removeListener(
+ event: "messageerror",
+ listener: (error: Error) => void,
+ ): this;
+ removeListener(event: "online", listener: () => void): this;
+ removeListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ off(event: "error", listener: (err: Error) => void): this;
+ off(event: "exit", listener: (exitCode: number) => void): this;
+ off(event: "message", listener: (value: any) => void): this;
+ off(event: "messageerror", listener: (error: Error) => void): this;
+ off(event: "online", listener: () => void): this;
+ off(event: string | symbol, listener: (...args: any[]) => void): this;
+ }
+
+ interface BroadcastChannelEventMap {
+ message: MessageEvent;
+ messageerror: MessageEvent;
+ }
+
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel) */
+ interface BroadcastChannel extends EventTarget {
+ /**
+ * Returns the channel name (as passed to the constructor).
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel/name)
+ */
+ readonly name: string;
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel/message_event) */
+ onmessage: ((this: BroadcastChannel, ev: MessageEvent) => any) | null;
+ /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel/messageerror_event) */
+ onmessageerror: ((this: BroadcastChannel, ev: MessageEvent) => any) | null;
+ /**
+ * Closes the BroadcastChannel object, opening it up to garbage collection.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel/close)
+ */
+ close(): void;
+ /**
+ * Sends the given message to other BroadcastChannel objects set up for this channel. Messages can be structured objects, e.g. nested objects and arrays.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/BroadcastChannel/postMessage)
+ */
+ postMessage(message: any): void;
+ addEventListener(
+ type: K,
+ listener: (
+ this: BroadcastChannel,
+ ev: BroadcastChannelEventMap[K],
+ ) => any,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ addEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | AddEventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: K,
+ listener: (
+ this: BroadcastChannel,
+ ev: BroadcastChannelEventMap[K],
+ ) => any,
+ options?: boolean | EventListenerOptions,
+ ): void;
+ removeEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | EventListenerOptions,
+ ): void;
+
+ /**
+ * Keep the process alive until the BroadcastChannel is closed or `unref`'d.
+ * BroadcastChannel is `ref`'d by default.
+ */
+ ref(): void;
+ /**
+ * Undo a previous `ref()`
+ */
+ unref(): void;
+ }
+
+ var BroadcastChannel: {
+ prototype: BroadcastChannel;
+ new (name: string): BroadcastChannel;
+ };
+
+ function markAsUntransferable(object: object): void;
+ /**
+ * Transfer a `MessagePort` to a different `vm` Context. The original `port`object is rendered unusable, and the returned `MessagePort` instance
+ * takes its place.
+ *
+ * The returned `MessagePort` is an object in the target context and
+ * inherits from its global `Object` class. Objects passed to the [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) listener are also created in the
+ * target context
+ * and inherit from its global `Object` class.
+ *
+ * However, the created `MessagePort` no longer inherits from [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), and only
+ * [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) can be used to receive
+ * events using it.
+ * @since v11.13.0
+ * @param port The message port to transfer.
+ * @param contextifiedSandbox A `contextified` object as returned by the `vm.createContext()` method.
+ */
+ function moveMessagePortToContext(
+ port: MessagePort,
+ contextifiedSandbox: Context,
+ ): MessagePort;
+ /**
+ * Receive a single message from a given `MessagePort`. If no message is available,`undefined` is returned, otherwise an object with a single `message` property
+ * that contains the message payload, corresponding to the oldest message in the`MessagePort`’s queue.
+ *
+ * ```js
+ * const { MessageChannel, receiveMessageOnPort } = require('worker_threads');
+ * const { port1, port2 } = new MessageChannel();
+ * port1.postMessage({ hello: 'world' });
+ *
+ * console.log(receiveMessageOnPort(port2));
+ * // Prints: { message: { hello: 'world' } }
+ * console.log(receiveMessageOnPort(port2));
+ * // Prints: undefined
+ * ```
+ *
+ * When this function is used, no `'message'` event is emitted and the`onmessage` listener is not invoked.
+ * @since v12.3.0
+ */
+ function receiveMessageOnPort(port: MessagePort):
+ | {
+ message: any;
+ }
+ | undefined;
+ type Serializable = string | object | number | boolean | bigint;
+ /**
+ * Within a worker thread, `worker.getEnvironmentData()` returns a clone
+ * of data passed to the spawning thread's `worker.setEnvironmentData()`.
+ * Every new `Worker` receives its own copy of the environment data
+ * automatically.
+ *
+ * ```js
+ * const {
+ * Worker,
+ * isMainThread,
+ * setEnvironmentData,
+ * getEnvironmentData,
+ * } = require('worker_threads');
+ *
+ * if (isMainThread) {
+ * setEnvironmentData('Hello', 'World!');
+ * const worker = new Worker(__filename);
+ * } else {
+ * console.log(getEnvironmentData('Hello')); // Prints 'World!'.
+ * }
+ * ```
+ * @since v15.12.0, v14.18.0
+ * @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key.
+ */
+ function getEnvironmentData(key: Serializable): Serializable;
+ /**
+ * The `worker.setEnvironmentData()` API sets the content of`worker.getEnvironmentData()` in the current thread and all new `Worker`instances spawned from the current context.
+ * @since v15.12.0, v14.18.0
+ * @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key.
+ * @param value Any arbitrary, cloneable JavaScript value that will be cloned and passed automatically to all new `Worker` instances. If `value` is passed as `undefined`, any previously set value
+ * for the `key` will be deleted.
+ */
+ function setEnvironmentData(key: Serializable, value: Serializable): void;
+
+ /**
+ * This Channel Messaging API interface allows us to create a new message channel and send data through it via its two MessagePort properties.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageChannel)
+ */
+ interface MessageChannel {
+ /**
+ * Returns the first MessagePort object.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageChannel/port1)
+ */
+ readonly port1: MessagePort;
+ /**
+ * Returns the second MessagePort object.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageChannel/port2)
+ */
+ readonly port2: MessagePort;
+ }
+
+ var MessageChannel: {
+ prototype: MessageChannel;
+ new (): MessageChannel;
+ };
+
+ interface MessagePortEventMap {
+ message: MessageEvent;
+ messageerror: MessageEvent;
+ }
+}
+declare module "node:worker_threads" {
+ export * from "worker_threads";
+}
diff --git a/packages/bun-types/ws.d.ts b/packages/bun-types/ws.d.ts
new file mode 100644
index 00000000000000..a14f87edd6e16d
--- /dev/null
+++ b/packages/bun-types/ws.d.ts
@@ -0,0 +1,222 @@
+/**
+ * The `node:diagnostics_channel` module provides an API to create named channels
+ * to report arbitrary message data for diagnostics purposes.
+ *
+ * It can be accessed using:
+ *
+ * ```js
+ * import diagnostics_channel from 'node:diagnostics_channel';
+ * ```
+ *
+ * It is intended that a module writer wanting to report diagnostics messages
+ * will create one or many top-level channels to report messages through.
+ * Channels may also be acquired at runtime but it is not encouraged
+ * due to the additional overhead of doing so. Channels may be exported for
+ * convenience, but as long as the name is known it can be acquired anywhere.
+ *
+ * If you intend for your module to produce diagnostics data for others to
+ * consume it is recommended that you include documentation of what named
+ * channels are used along with the shape of the message data. Channel names
+ * should generally include the module name to avoid collisions with data from
+ * other modules.
+ * @since Bun v0.7.2
+ * @see [source](https://github.com/nodejs/node/blob/v20.2.0/lib/diagnostics_channel.js)
+ */
+declare module "ws" {
+ import {
+ IncomingMessage,
+ OutgoingHttpHeaders,
+ Server as HTTPServer,
+ } from "http";
+ import { Duplex, EventEmitter } from "stream";
+ // import {Server as HTTPServer} from "http";
+ import { Server as HTTPSServer } from "https";
+ var WebSocket: typeof global.WebSocket;
+ interface WebSocket extends globalThis.WebSocket {}
+
+ type VerifyClientCallbackSync<
+ Request extends IncomingMessage = IncomingMessage,
+ > = (info: { origin: string; secure: boolean; req: Request }) => boolean;
+ type VerifyClientCallbackAsync<
+ Request extends IncomingMessage = IncomingMessage,
+ > = (
+ info: { origin: string; secure: boolean; req: Request },
+ callback: (
+ res: boolean,
+ code?: number,
+ message?: string,
+ headers?: OutgoingHttpHeaders,
+ ) => void,
+ ) => void;
+
+ interface WebSocketServerOptions<
+ U extends typeof WebSocket = typeof WebSocket,
+ V extends typeof IncomingMessage = typeof IncomingMessage,
+ > {
+ host?: string | undefined;
+ port?: number | undefined;
+ backlog?: number | undefined;
+ server?: HTTPServer | HTTPSServer | undefined;
+ verifyClient?:
+ | VerifyClientCallbackAsync>
+ | VerifyClientCallbackSync>
+ | undefined;
+ handleProtocols?: (
+ protocols: Set,
+ request: InstanceType,
+ ) => string | false;
+ path?: string | undefined;
+ noServer?: boolean | undefined;
+ clientTracking?: boolean | undefined;
+ perMessageDeflate?: boolean; // | PerMessageDeflateOptions | undefined;
+ // maxPayload?: number | undefined;
+ // skipUTF8Validation?: boolean | undefined;
+ WebSocket?: U | undefined;
+ }
+
+ interface AddressInfo {
+ address: string;
+ family: string;
+ port: number;
+ }
+
+ // WebSocket Server
+ class WebSocketServer<
+ T extends typeof WebSocket = typeof WebSocket,
+ U extends typeof IncomingMessage = typeof IncomingMessage,
+ > extends EventEmitter {
+ options: WebSocketServerOptions;
+ path: string;
+ clients: Set>;
+
+ constructor(options?: WebSocketServerOptions, callback?: () => void);
+
+ address(): AddressInfo | string;
+ close(cb?: (err?: Error) => void): void;
+ handleUpgrade(
+ request: InstanceType,
+ socket: Duplex,
+ upgradeHead: Buffer,
+ callback: (client: InstanceType, request: InstanceType) => void,
+ ): void;
+ shouldHandle(request: InstanceType): boolean | Promise;
+
+ // Events
+ on(
+ event: "connection",
+ cb: (
+ this: WebSocketServer,
+ socket: InstanceType,
+ request: InstanceType,
+ ) => void,
+ ): this;
+ on(
+ event: "error",
+ cb: (this: WebSocketServer, error: Error) => void,
+ ): this;
+ on(
+ event: "headers",
+ cb: (
+ this: WebSocketServer,
+ headers: string[],
+ request: InstanceType,
+ ) => void,
+ ): this;
+ on(
+ event: "close" | "listening",
+ cb: (this: WebSocketServer) => void,
+ ): this;
+ on(
+ event: string | symbol,
+ listener: (this: WebSocketServer, ...args: any[]) => void,
+ ): this;
+
+ once(
+ event: "connection",
+ cb: (
+ this: WebSocketServer,
+ socket: InstanceType,
+ request: InstanceType,
+ ) => void,
+ ): this;
+ once(
+ event: "error",
+ cb: (this: WebSocketServer, error: Error) => void,
+ ): this;
+ once(
+ event: "headers",
+ cb: (
+ this: WebSocketServer,
+ headers: string[],
+ request: InstanceType,
+ ) => void,
+ ): this;
+ once(
+ event: "close" | "listening",
+ cb: (this: WebSocketServer) => void,
+ ): this;
+ once(
+ event: string | symbol,
+ listener: (this: WebSocketServer, ...args: any[]) => void,
+ ): this;
+
+ off(
+ event: "connection",
+ cb: (
+ this: WebSocketServer,
+ socket: InstanceType,
+ request: InstanceType,
+ ) => void,
+ ): this;
+ off(
+ event: "error",
+ cb: (this: WebSocketServer, error: Error) => void,
+ ): this;
+ off(
+ event: "headers",
+ cb: (
+ this: WebSocketServer,
+ headers: string[],
+ request: InstanceType,
+ ) => void,
+ ): this;
+ off(
+ event: "close" | "listening",
+ cb: (this: WebSocketServer) => void,
+ ): this;
+ off(
+ event: string | symbol,
+ listener: (this: WebSocketServer, ...args: any[]) => void,
+ ): this;
+
+ addListener(
+ event: "connection",
+ cb: (client: InstanceType, request: InstanceType) => void,
+ ): this;
+ addListener(event: "error", cb: (err: Error) => void): this;
+ addListener(
+ event: "headers",
+ cb: (headers: string[], request: InstanceType) => void,
+ ): this;
+ addListener(event: "close" | "listening", cb: () => void): this;
+ addListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+
+ removeListener(
+ event: "connection",
+ cb: (client: InstanceType, request: InstanceType) => void,
+ ): this;
+ removeListener(event: "error", cb: (err: Error) => void): this;
+ removeListener(
+ event: "headers",
+ cb: (headers: string[], request: InstanceType) => void,
+ ): this;
+ removeListener(event: "close" | "listening", cb: () => void): this;
+ removeListener(
+ event: string | symbol,
+ listener: (...args: any[]) => void,
+ ): this;
+ }
+}
diff --git a/packages/bun-wasm/index.ts b/packages/bun-wasm/index.ts
index b72400661a9f6e..10a7b3aa4047d9 100644
--- a/packages/bun-wasm/index.ts
+++ b/packages/bun-wasm/index.ts
@@ -1,11 +1,14 @@
// @ts-nocheck
import { ByteBuffer } from "peechy/bb";
import {
+ Loader as BunLoader,
+ TestKind,
+ decodeGetTestsResponse,
decodeScanResult,
decodeTransformResponse,
+ encodeGetTestsRequest,
encodeScan,
encodeTransform,
- Loader as BunLoader,
type ScanResult,
type TransformResponse,
} from "./schema";
@@ -15,9 +18,13 @@ export enum Loader {
tsx = BunLoader.tsx,
ts = BunLoader.ts,
}
-
+const testKindMap = {
+ [TestKind.describe_fn]: "describe",
+ [TestKind.test_fn]: "test",
+};
+const capturedErrors = [];
+let captureErrors = false;
export type { ScanResult, TransformResponse };
-
function normalizeLoader(file_name: string, loader?: Loader): BunLoader {
return (
(loader
@@ -82,12 +89,22 @@ var scratch2: Uint8Array;
const env = {
console_log(slice: number) {
+ const text = Bun._wasmPtrLenToString(slice);
+ if (captureErrors) {
+ capturedErrors.push(text);
+ return;
+ }
//@ts-ignore
- console.log(Bun._wasmPtrLenToString(slice));
+ console.log(text);
},
console_error(slice: number) {
//@ts-ignore
- console.error(Bun._wasmPtrLenToString(slice));
+ const text = Bun._wasmPtrLenToString(slice);
+ if (captureErrors) {
+ capturedErrors.push(text);
+ return;
+ }
+ console.error(text);
},
console_warn(slice: number) {
//@ts-ignore
@@ -148,7 +165,6 @@ const env = {
},
emscripten_notify_memory_growth() {},
};
-
export class Bun {
private static has_initialized = false;
// @ts-ignore-line
@@ -179,63 +195,115 @@ export class Bun {
return Bun._decoder.decode(region);
}
- static async init(url, fetch = globalThis.fetch) {
- // globalThis.sucraseTransform = sucraseTransform;
+ static async init(url, heapSize = 64_000_000, fetch = globalThis.fetch) {
scratch = new Uint8Array(8096);
if (Bun.has_initialized) {
return;
}
-
- if (globalThis?.WebAssembly?.instantiateStreaming) {
- Bun.wasm_source = await globalThis.WebAssembly.instantiateStreaming(
- fetch(url),
- { env: env, wasi_snapshot_preview1: Wasi },
- );
- } else if (typeof window !== "undefined") {
- const resp = await fetch(url);
- Bun.wasm_source = await globalThis.WebAssembly.instantiate(
- await resp.arrayBuffer(),
- {
+ if (typeof process === "undefined") {
+ if (globalThis?.WebAssembly?.instantiateStreaming) {
+ Bun.wasm_source = await globalThis.WebAssembly.instantiateStreaming(fetch(url), {
env: env,
wasi_snapshot_preview1: Wasi,
- },
- );
- // is it node?
+ });
+ } else if (typeof window !== "undefined") {
+ const resp = await fetch(url);
+ Bun.wasm_source = await globalThis.WebAssembly.instantiate(await resp.arrayBuffer(), {
+ env: env,
+ wasi_snapshot_preview1: Wasi,
+ });
+ // is it node?
+ }
} else {
//@ts-ignore
const fs = await import("fs");
- Bun.wasm_source = await globalThis.WebAssembly.instantiate(
- fs.readFileSync(url),
- {
- env: env,
- wasi_snapshot_preview1: Wasi,
- },
- );
+ Bun.wasm_source = await globalThis.WebAssembly.instantiate(fs.readFileSync(url), {
+ env: env,
+ wasi_snapshot_preview1: Wasi,
+ });
}
- const res = Bun.wasm_exports.init();
+ const res = Bun.wasm_exports.init(heapSize);
+
if (res < 0) {
- throw `[Bun] Failed to initialize WASM module: code ${res}`;
+ throw new Error(`[Bun] Failed to initialize WASM module: code ${res}`);
}
Bun.has_initialized = true;
}
- static transformSync(
- content: Uint8Array | string,
- file_name: string,
- loader?: Loader,
- ): TransformResponse {
- if (!Bun.has_initialized) {
- throw "Please run await Bun.init(wasm_url) before using this.";
+ static getTests(content: Uint8Array | string, filename = "my.test.tsx") {
+ const bb = new ByteBuffer(scratch);
+ bb.length = 0;
+ bb.index = 0;
+ const contents_buffer = content;
+
+ encodeGetTestsRequest(
+ {
+ contents: contents_buffer,
+ path: filename,
+ },
+ bb,
+ );
+
+ const data = bb.toUint8Array();
+
+ const input_ptr = Bun.wasm_exports.bun_malloc(data.length);
+ var buffer = Bun._wasmPtrToSlice(input_ptr);
+ buffer.set(data);
+ captureErrors = true;
+ try {
+ var resp_ptr = Bun.wasm_exports.getTests(input_ptr);
+ } catch (e) {
+ throw e;
+ } finally {
+ captureErrors = false;
+ Bun.wasm_exports.bun_free(input_ptr);
+ }
+
+ if (Number(resp_ptr) === 0) {
+ if (capturedErrors.length) {
+ const err = capturedErrors.slice();
+ capturedErrors.length = 0;
+ throw new Error(err.join("\n").trim());
+ }
+
+ throw new Error("Failed to parse");
+ }
+
+ if (capturedErrors.length) {
+ Bun.wasm_exports.bun_free(resp_ptr);
+ const err = capturedErrors.slice();
+ capturedErrors.length = 0;
+ throw new Error(err.join("\n").trim());
+ }
+
+ var _bb = new ByteBuffer(Bun._wasmPtrToSlice(resp_ptr));
+
+ const response = decodeGetTestsResponse(_bb);
+ var tests = new Array(response.tests.length);
+
+ for (var i = 0; i < response.tests.length; i++) {
+ tests[i] = {
+ name: new TextDecoder().decode(
+ response.contents.subarray(
+ response.tests[i].label.offset,
+ response.tests[i].label.offset + response.tests[i].label.length,
+ ),
+ ),
+ byteOffset: response.tests[i].byteOffset,
+ kind: testKindMap[response.tests[i].kind],
+ };
}
- // if (process.env.NODE_ENV === "development") {
- // console.time("[Bun] Transform " + file_name);
- // }
+ Bun.wasm_exports.bun_free(resp_ptr);
+
+ return tests;
+ }
+ static transformSync(content: Uint8Array | string, file_name: string, loader?: Loader): TransformResponse {
const bb = new ByteBuffer(scratch);
bb.length = 0;
bb.index = 0;
@@ -274,28 +342,14 @@ export class Bun {
buffer.set(data);
const resp_ptr = Bun.wasm_exports.transform(input_ptr);
-
var _bb = new ByteBuffer(Bun._wasmPtrToSlice(resp_ptr));
-
const response = decodeTransformResponse(_bb);
Bun.wasm_exports.bun_free(input_ptr);
scratch = bb.data;
return response;
}
- static scan(
- content: Uint8Array | string,
- file_name: string,
- loader?: Loader,
- ): ScanResult {
- if (!Bun.has_initialized) {
- throw "Please run await Bun.init(wasm_url) before using this.";
- }
-
- // if (process.env.NODE_ENV === "development") {
- // console.time("[Bun] Transform " + file_name);
- // }
- scratch.fill(0);
+ static scan(content: Uint8Array | string, file_name: string, loader?: Loader): ScanResult {
const bb = new ByteBuffer(scratch);
bb.length = 0;
bb.index = 0;
@@ -337,15 +391,5 @@ export class Bun {
export const transformSync = Bun.transformSync;
export const scan = Bun.scan;
export const init = Bun.init;
+export const getTests = Bun.getTests;
export default Bun;
-
-if ("window" in globalThis && !("Bun" in globalThis)) {
- // @ts-ignore-line
- globalThis.Bun = Bun;
-}
-
-//@ts-ignore
-if (process.env.NODE_ENV === "development") {
- //@ts-ignore
- Bun.env = env;
-}
diff --git a/packages/bun-wasm/test/node.mjs b/packages/bun-wasm/test/node.mjs
index 7890a5c6e12110..2699a1dad7af3a 100644
--- a/packages/bun-wasm/test/node.mjs
+++ b/packages/bun-wasm/test/node.mjs
@@ -1,28 +1,7 @@
-// This is not released yet because there are some memory bugs with the WASM build
-// It causes syntax errors which don't make any sense
-// Most likely, this is an issue with some code expecting 64 bit pointers
-// That's also why this test just prints instead of using a test runner
-import * as Bun from "../index.mjs";
+import { readFileSync } from "fs";
+import { init, getTests } from "../index.mjs";
-await Bun.init(new URL("../bun.wasm", import.meta.url));
+const buf = (process.argv.length > 2 ? readFileSync(process.argv.at(-1)) : "") || readFileSync(import.meta.url);
+await init(new URL("../bun.wasm", import.meta.url));
-const buf =
- (process.argv.length > 2 ? process.argv.at(-1) : "") ||
- new TextEncoder().encode(`
-
-export function hi() {
- return Hey
;
-}
-
-`);
-const result = Bun.transformSync(buf, "hi.jsx", "jsx");
-if (result.errors?.length) {
- console.log(JSON.stringify(result.errors, null, 2));
- throw new Error("Failed");
-}
-
-if (!result.files.length) {
- throw new Error("unexpectedly empty");
-}
-
-process.stdout.write(result.files[0].data);
+console.log(getTests(buf));
diff --git a/root.zig b/root.zig
index 0d00409ebf85a9..0fc0d3987a9938 100644
--- a/root.zig
+++ b/root.zig
@@ -17,3 +17,6 @@ pub const completions = struct {
pub const zsh = @embedFile("./completions/bun.zsh");
pub const fish = @embedFile("./completions/bun.fish");
};
+
+pub const JavaScriptCore = @import("./src/jsc.zig");
+pub const C = @import("./src/c.zig");
diff --git a/root_wasm.zig b/root_wasm.zig
new file mode 100644
index 00000000000000..f04ceb015c9327
--- /dev/null
+++ b/root_wasm.zig
@@ -0,0 +1,26 @@
+pub usingnamespace @import("src/main_wasm.zig");
+
+pub const bun = @import("src/bun.zig");
+
+pub const content = struct {
+ pub const error_js_path = "packages/bun-error/dist/index.js";
+ pub const error_js = @embedFile(error_js_path);
+
+ pub const error_css_path = "packages/bun-error/dist/bun-error.css";
+ pub const error_css_path_dev = "packages/bun-error/bun-error.css";
+
+ pub const error_css = @embedFile(error_css_path);
+};
+
+pub const completions = struct {};
+pub const is_bindgen = true;
+pub const JavaScriptCore = struct {
+ pub fn markBinding(_: @import("std").builtin.SourceLocation) void {
+ unreachable;
+ }
+
+ pub const ZigString = struct {};
+};
+
+pub const C = struct {};
+pub const build_options = @import("build_options");
diff --git a/src/ArenaAllocator.zig b/src/ArenaAllocator.zig
index 2ccb08d19aea53..c2d8718fd4d3a7 100644
--- a/src/ArenaAllocator.zig
+++ b/src/ArenaAllocator.zig
@@ -1,4 +1,3 @@
-/// TODO: delete this once we've upgraded Zig and https://github.com/ziglang/zig/pull/15985 is merged.
const std = @import("std");
const assert = std.debug.assert;
const mem = std.mem;
@@ -152,7 +151,7 @@ pub const ArenaAllocator = struct {
return false;
};
self.child_allocator.rawFree(first_alloc_buf, align_bits, @returnAddress());
- const node = @as(*BufNode, @ptrCast(@alignCast(new_ptr)));
+ const node: *BufNode = @ptrCast(@alignCast(new_ptr));
node.* = .{ .data = total_size };
self.state.buffer_list.first = node;
}
@@ -167,7 +166,7 @@ pub const ArenaAllocator = struct {
const log2_align = comptime std.math.log2_int(usize, @alignOf(BufNode));
const ptr = self.child_allocator.rawAlloc(len, log2_align, @returnAddress()) orelse
return null;
- const buf_node = @as(*BufNode, @ptrCast(@alignCast(ptr)));
+ const buf_node: *BufNode = @ptrCast(@alignCast(ptr));
buf_node.* = .{ .data = len };
self.state.buffer_list.prepend(buf_node);
self.state.end_index = 0;
@@ -175,7 +174,7 @@ pub const ArenaAllocator = struct {
}
fn alloc(ctx: *anyopaque, n: usize, log2_ptr_align: u8, ra: usize) ?[*]u8 {
- const self = @as(*ArenaAllocator, @ptrCast(@alignCast(ctx)));
+ const self: *ArenaAllocator = @ptrCast(@alignCast(ctx));
_ = ra;
const ptr_align = @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_ptr_align));
@@ -209,7 +208,7 @@ pub const ArenaAllocator = struct {
}
fn resize(ctx: *anyopaque, buf: []u8, log2_buf_align: u8, new_len: usize, ret_addr: usize) bool {
- const self = @as(*ArenaAllocator, @ptrCast(@alignCast(ctx)));
+ const self: *ArenaAllocator = @ptrCast(@alignCast(ctx));
_ = log2_buf_align;
_ = ret_addr;
@@ -236,7 +235,7 @@ pub const ArenaAllocator = struct {
_ = log2_buf_align;
_ = ret_addr;
- const self = @as(*ArenaAllocator, @ptrCast(@alignCast(ctx)));
+ const self: *ArenaAllocator = @ptrCast(@alignCast(ctx));
const cur_node = self.state.buffer_list.first orelse return;
const cur_buf = @as([*]u8, @ptrCast(cur_node))[@sizeOf(BufNode)..cur_node.data];
diff --git a/src/__global.zig b/src/__global.zig
index 7bcdaeeda44b31..9a33fff37b4b32 100644
--- a/src/__global.zig
+++ b/src/__global.zig
@@ -7,20 +7,26 @@ const StringTypes = @import("./string_types.zig");
const Mimalloc = @import("root").bun.Mimalloc;
const bun = @import("root").bun;
-const BASE_VERSION = "0.7";
-
pub const build_id = std.fmt.parseInt(u64, std.mem.trim(u8, @embedFile("./build-id"), "\n \r\t"), 10) catch unreachable;
+pub const version: @import("./install/semver.zig").Version = .{
+ .major = 0,
+ .minor = 7,
+ .patch = build_id,
+};
+
+const version_string = std.fmt.comptimePrint("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
+
pub const package_json_version = if (Environment.isDebug)
- std.fmt.comptimePrint(BASE_VERSION ++ ".{d}_debug", .{build_id})
+ version_string ++ "_debug"
else
- std.fmt.comptimePrint(BASE_VERSION ++ ".{d}", .{build_id});
+ version_string;
pub const package_json_version_with_sha = if (Environment.git_sha.len == 0)
package_json_version
else if (Environment.isDebug)
- std.fmt.comptimePrint(BASE_VERSION ++ ".{d}_debug ({s})", .{ build_id, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] })
+ std.fmt.comptimePrint("{s}_debug ({s})", .{ version_string, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] })
else
- std.fmt.comptimePrint(BASE_VERSION ++ ".{d} ({s})", .{ build_id, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] });
+ std.fmt.comptimePrint("{s} ({s})", .{ version_string, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] });
pub const os_name = if (Environment.isWindows)
"win32"
@@ -47,12 +53,6 @@ pub inline fn getStartTime() i128 {
return @import("root").bun.start_time;
}
-pub const version: @import("./install/semver.zig").Version = .{
- .major = 0,
- .minor = 6,
- .patch = build_id,
-};
-
pub fn setThreadName(name: StringTypes.stringZ) void {
if (Environment.isLinux) {
_ = std.os.prctl(.SET_NAME, .{@intFromPtr(name.ptr)}) catch 0;
diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts
index 2a86340ad66b95..a982b910d712f0 100644
--- a/src/api/schema.d.ts
+++ b/src/api/schema.d.ts
@@ -331,6 +331,16 @@ export const WebsocketCommandKindKeys: {
3: "build_with_file_path";
build_with_file_path: "build_with_file_path";
};
+export const enum TestKind {
+ test_fn = 1,
+ describe_fn = 2,
+}
+export const TestKindKeys: {
+ 1: "test_fn";
+ test_fn: "test_fn";
+ 2: "describe_fn";
+ describe_fn: "describe_fn";
+};
export interface StackFrame {
function_name: string;
file: string;
@@ -729,6 +739,22 @@ export interface ClientServerModuleManifest {
contents: Uint8Array;
}
+export interface GetTestsRequest {
+ path: string;
+ contents: Uint8Array;
+}
+
+export interface TestResponseItem {
+ byteOffset: int32;
+ label: StringPointer;
+ kind: TestKind;
+}
+
+export interface GetTestsResponse {
+ tests: TestResponseItem[];
+ contents: Uint8Array;
+}
+
export declare function encodeStackFrame(message: StackFrame, bb: ByteBuffer): void;
export declare function decodeStackFrame(buffer: ByteBuffer): StackFrame;
export declare function encodeStackFramePosition(message: StackFramePosition, bb: ByteBuffer): void;
@@ -847,3 +873,9 @@ export declare function encodeClientServerModule(message: ClientServerModule, bb
export declare function decodeClientServerModule(buffer: ByteBuffer): ClientServerModule;
export declare function encodeClientServerModuleManifest(message: ClientServerModuleManifest, bb: ByteBuffer): void;
export declare function decodeClientServerModuleManifest(buffer: ByteBuffer): ClientServerModuleManifest;
+export declare function encodeGetTestsRequest(message: GetTestsRequest, bb: ByteBuffer): void;
+export declare function decodeGetTestsRequest(buffer: ByteBuffer): GetTestsRequest;
+export declare function encodeTestResponseItem(message: TestResponseItem, bb: ByteBuffer): void;
+export declare function decodeTestResponseItem(buffer: ByteBuffer): TestResponseItem;
+export declare function encodeGetTestsResponse(message: GetTestsResponse, bb: ByteBuffer): void;
+export declare function decodeGetTestsResponse(buffer: ByteBuffer): GetTestsResponse;
diff --git a/src/api/schema.js b/src/api/schema.js
index f1e68031ec85bc..b28c5669c2e3ab 100644
--- a/src/api/schema.js
+++ b/src/api/schema.js
@@ -3315,6 +3315,108 @@ function encodeClientServerModuleManifest(message, bb) {
}
}
+function decodeGetTestsRequest(bb) {
+ var result = {};
+
+ result["path"] = bb.readString();
+ result["contents"] = bb.readByteArray();
+ return result;
+}
+
+function encodeGetTestsRequest(message, bb) {
+ var value = message["path"];
+ if (value != null) {
+ bb.writeString(value);
+ } else {
+ throw new Error('Missing required field "path"');
+ }
+
+ var value = message["contents"];
+ if (value != null) {
+ bb.writeByteArray(value);
+ } else {
+ throw new Error('Missing required field "contents"');
+ }
+}
+const TestKind = {
+ "1": 1,
+ "2": 2,
+ "test_fn": 1,
+ "describe_fn": 2,
+};
+const TestKindKeys = {
+ "1": "test_fn",
+ "2": "describe_fn",
+ "test_fn": "test_fn",
+ "describe_fn": "describe_fn",
+};
+
+function decodeTestResponseItem(bb) {
+ var result = {};
+
+ result["byteOffset"] = bb.readInt32();
+ result["label"] = decodeStringPointer(bb);
+ result["kind"] = TestKind[bb.readByte()];
+ return result;
+}
+
+function encodeTestResponseItem(message, bb) {
+ var value = message["byteOffset"];
+ if (value != null) {
+ bb.writeInt32(value);
+ } else {
+ throw new Error('Missing required field "byteOffset"');
+ }
+
+ var value = message["label"];
+ if (value != null) {
+ encodeStringPointer(value, bb);
+ } else {
+ throw new Error('Missing required field "label"');
+ }
+
+ var value = message["kind"];
+ if (value != null) {
+ var encoded = TestKind[value];
+ if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + ' for enum "TestKind"');
+ bb.writeByte(encoded);
+ } else {
+ throw new Error('Missing required field "kind"');
+ }
+}
+
+function decodeGetTestsResponse(bb) {
+ var result = {};
+
+ var length = bb.readVarUint();
+ var values = (result["tests"] = Array(length));
+ for (var i = 0; i < length; i++) values[i] = decodeTestResponseItem(bb);
+ result["contents"] = bb.readByteArray();
+ return result;
+}
+
+function encodeGetTestsResponse(message, bb) {
+ var value = message["tests"];
+ if (value != null) {
+ var values = value,
+ n = values.length;
+ bb.writeVarUint(n);
+ for (var i = 0; i < n; i++) {
+ value = values[i];
+ encodeTestResponseItem(value, bb);
+ }
+ } else {
+ throw new Error('Missing required field "tests"');
+ }
+
+ var value = message["contents"];
+ if (value != null) {
+ bb.writeByteArray(value);
+ } else {
+ throw new Error('Missing required field "contents"');
+ }
+}
+
export { Loader };
export { LoaderKeys };
export { FrameworkEntryPointType };
@@ -3461,3 +3563,11 @@ export { decodeClientServerModule };
export { encodeClientServerModule };
export { decodeClientServerModuleManifest };
export { encodeClientServerModuleManifest };
+export { decodeGetTestsRequest };
+export { encodeGetTestsRequest };
+export { TestKind };
+export { TestKindKeys };
+export { decodeTestResponseItem };
+export { encodeTestResponseItem };
+export { decodeGetTestsResponse };
+export { encodeGetTestsResponse };
diff --git a/src/api/schema.peechy b/src/api/schema.peechy
index a172606f7b2cce..53800e4f318b6e 100644
--- a/src/api/schema.peechy
+++ b/src/api/schema.peechy
@@ -609,3 +609,25 @@ struct ClientServerModuleManifest {
StringPointer[] exportNames;
byte[] contents;
}
+
+
+struct GetTestsRequest {
+ string path;
+ byte[] contents;
+}
+
+smol TestKind {
+ test_fn = 1;
+ describe_fn = 2;
+}
+
+struct TestResponseItem {
+ int32 byteOffset;
+ StringPointer label;
+ TestKind kind;
+}
+
+struct GetTestsResponse {
+ TestResponseItem[] tests;
+ byte[] contents;
+}
\ No newline at end of file
diff --git a/src/api/schema.zig b/src/api/schema.zig
index 94f2d22df4e52c..de46a813b1fe49 100644
--- a/src/api/schema.zig
+++ b/src/api/schema.zig
@@ -3140,4 +3140,87 @@ pub const Api = struct {
try writer.writeArray(u8, this.contents);
}
};
+
+ pub const GetTestsRequest = struct {
+ /// path
+ path: []const u8,
+
+ /// contents
+ contents: []const u8,
+
+ pub fn decode(reader: anytype) anyerror!GetTestsRequest {
+ var this = std.mem.zeroes(GetTestsRequest);
+
+ this.path = try reader.readValue([]const u8);
+ this.contents = try reader.readArray(u8);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeValue(@TypeOf(this.path), this.path);
+ try writer.writeArray(u8, this.contents);
+ }
+ };
+
+ pub const TestKind = enum(u8) {
+ _none,
+ /// test_fn
+ test_fn,
+
+ /// describe_fn
+ describe_fn,
+
+ _,
+
+ pub fn jsonStringify(self: *const @This(), opts: anytype, o: anytype) !void {
+ return try std.json.stringify(@tagName(self), opts, o);
+ }
+ };
+
+ pub const TestResponseItem = struct {
+ /// byteOffset
+ byte_offset: i32 = 0,
+
+ /// label
+ label: StringPointer,
+
+ /// kind
+ kind: TestKind,
+
+ pub fn decode(reader: anytype) anyerror!TestResponseItem {
+ var this = std.mem.zeroes(TestResponseItem);
+
+ this.byte_offset = try reader.readValue(i32);
+ this.label = try reader.readValue(StringPointer);
+ this.kind = try reader.readValue(TestKind);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeInt(this.byte_offset);
+ try writer.writeValue(@TypeOf(this.label), this.label);
+ try writer.writeEnum(this.kind);
+ }
+ };
+
+ pub const GetTestsResponse = struct {
+ /// tests
+ tests: []const TestResponseItem,
+
+ /// contents
+ contents: []const u8,
+
+ pub fn decode(reader: anytype) anyerror!GetTestsResponse {
+ var this = std.mem.zeroes(GetTestsResponse);
+
+ this.tests = try reader.readArray(TestResponseItem);
+ this.contents = try reader.readArray(u8);
+ return this;
+ }
+
+ pub fn encode(this: *const @This(), writer: anytype) anyerror!void {
+ try writer.writeArray(TestResponseItem, this.tests);
+ try writer.writeArray(u8, this.contents);
+ }
+ };
};
diff --git a/src/build-id b/src/build-id
index d00491fd7e5bb6..b8626c4cff2849 100644
--- a/src/build-id
+++ b/src/build-id
@@ -1 +1 @@
-1
+4
diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig
index b9b2d7b06914b0..457a8ec4f9657a 100644
--- a/src/bun.js/ResolveMessage.zig
+++ b/src/bun.js/ResolveMessage.zig
@@ -35,6 +35,9 @@ pub const ResolveMessage = struct {
return try std.fmt.allocPrint(allocator, "Cannot find module \"{s}\" from \"{s}\"", .{ specifier, referrer });
}
},
+ error.InvalidDataURL => {
+ return try std.fmt.allocPrint(allocator, "Cannot resolve invalid data URL \"{s}\" from \"{s}\"", .{ specifier, referrer });
+ },
else => {
if (Resolver.isPackagePath(specifier)) {
return try std.fmt.allocPrint(allocator, "{s} while resolving package \"{s}\" from \"{s}\"", .{ @errorName(err), specifier, referrer });
diff --git a/src/bun.js/Strong.zig b/src/bun.js/Strong.zig
new file mode 100644
index 00000000000000..d2ed3afbd3b379
--- /dev/null
+++ b/src/bun.js/Strong.zig
@@ -0,0 +1,114 @@
+const bun = @import("root").bun;
+const JSC = bun.JSC;
+
+const StrongImpl = opaque {
+ pub fn init(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) *StrongImpl {
+ JSC.markBinding(@src());
+ return Bun__StrongRef__new(globalThis, value);
+ }
+
+ pub fn get(this: *StrongImpl) JSC.JSValue {
+ JSC.markBinding(@src());
+ return Bun__StrongRef__get(this);
+ }
+
+ pub fn set(this: *StrongImpl, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ Bun__StrongRef__set(this, globalThis, value);
+ }
+
+ pub fn clear(this: *StrongImpl) void {
+ JSC.markBinding(@src());
+ Bun__StrongRef__clear(this);
+ }
+
+ pub fn deinit(
+ this: *StrongImpl,
+ ) void {
+ JSC.markBinding(@src());
+ Bun__StrongRef__delete(this);
+ }
+
+ extern fn Bun__StrongRef__delete(this: *StrongImpl) void;
+ extern fn Bun__StrongRef__new(*JSC.JSGlobalObject, JSC.JSValue) *StrongImpl;
+ extern fn Bun__StrongRef__get(this: *StrongImpl) JSC.JSValue;
+ extern fn Bun__StrongRef__set(this: *StrongImpl, *JSC.JSGlobalObject, JSC.JSValue) void;
+ extern fn Bun__StrongRef__clear(this: *StrongImpl) void;
+};
+
+pub const Strong = struct {
+ ref: ?*StrongImpl = null,
+ globalThis: ?*JSC.JSGlobalObject = null,
+
+ pub fn init() Strong {
+ return .{};
+ }
+
+ pub fn create(
+ value: JSC.JSValue,
+ globalThis: *JSC.JSGlobalObject,
+ ) Strong {
+ if (value != .zero) {
+ return .{ .ref = StrongImpl.init(globalThis, value), .globalThis = globalThis };
+ }
+
+ return .{ .globalThis = globalThis };
+ }
+
+ pub fn get(this: *Strong) ?JSC.JSValue {
+ var ref = this.ref orelse return null;
+ const result = ref.get();
+ if (result == .zero) {
+ return null;
+ }
+
+ return result;
+ }
+
+ pub fn swap(this: *Strong) JSC.JSValue {
+ var ref = this.ref orelse return .zero;
+ const result = ref.get();
+ if (result == .zero) {
+ return .zero;
+ }
+
+ ref.clear();
+ return result;
+ }
+
+ pub fn has(this: *Strong) bool {
+ var ref = this.ref orelse return false;
+ return ref.get() != .zero;
+ }
+
+ pub fn trySwap(this: *Strong) ?JSC.JSValue {
+ const result = this.swap();
+ if (result == .zero) {
+ return null;
+ }
+
+ return result;
+ }
+
+ pub fn set(this: *Strong, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ var ref: *StrongImpl = this.ref orelse {
+ if (value == .zero) return;
+ this.ref = StrongImpl.init(globalThis, value);
+ this.globalThis = globalThis;
+ return;
+ };
+ this.globalThis = globalThis;
+ ref.set(globalThis, value);
+ }
+
+ pub fn clear(this: *Strong) void {
+ var ref: *StrongImpl = this.ref orelse return;
+ ref.clear();
+ }
+
+ pub fn deinit(this: *Strong) void {
+ var ref: *StrongImpl = this.ref orelse return;
+ this.ref = null;
+ ref.deinit();
+ }
+};
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
index 284095ff91529d..74609640b2a7c5 160000
--- a/src/bun.js/WebKit
+++ b/src/bun.js/WebKit
@@ -1 +1 @@
-Subproject commit 284095ff91529df883cf5ab30d66048a3207bade
+Subproject commit 74609640b2a7c5a1588b824f870d1b0ff91bfd8e
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 85d2e7f8325730..fe0aafc25d0823 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -582,88 +582,6 @@ pub fn newPath(
return Node.Path.create(ctx.ptr(), is_windows).asObjectRef();
}
-pub fn readFileAsStringCallback(
- ctx: js.JSContextRef,
- buf_z: [:0]const u8,
- exception: js.ExceptionRef,
-) js.JSValueRef {
- const path = buf_z.ptr[0..buf_z.len];
- var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
- JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- defer file.close();
-
- const stat = file.stat() catch |err| {
- JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- if (stat.kind != .file) {
- JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- var contents_buf = VirtualMachine.get().allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
- defer VirtualMachine.get().allocator.free(contents_buf);
- const contents_len = file.readAll(contents_buf) catch |err| {
- JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- contents_buf[contents_len] = 0;
-
- // Very slow to do it this way. We're copying the string twice.
- // But it's important that this string is garbage collected instead of manually managed.
- // We can't really recycle this one.
- // TODO: use external string
- return js.JSValueMakeString(ctx, js.JSStringCreateWithUTF8CString(contents_buf.ptr));
-}
-
-pub fn readFileAsBytesCallback(
- ctx: js.JSContextRef,
- buf_z: [:0]const u8,
- exception: js.ExceptionRef,
-) js.JSValueRef {
- const path = buf_z.ptr[0..buf_z.len];
- const allocator = VirtualMachine.get().allocator;
-
- var file = std.fs.cwd().openFileZ(buf_z, .{ .mode = .read_only }) catch |err| {
- JSError(allocator, "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- defer file.close();
-
- const stat = file.stat() catch |err| {
- JSError(allocator, "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- if (stat.kind != .file) {
- JSError(allocator, "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- }
-
- var contents_buf = allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
- const contents_len = file.readAll(contents_buf) catch |err| {
- JSError(allocator, "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
- return js.JSValueMakeUndefined(ctx);
- };
-
- contents_buf[contents_len] = 0;
-
- var marked_array_buffer = allocator.create(MarkedArrayBuffer) catch unreachable;
- marked_array_buffer.* = MarkedArrayBuffer.fromBytes(
- contents_buf[0..contents_len],
- allocator,
- .Uint8Array,
- );
-
- return marked_array_buffer.toJSObjectRef(ctx, exception);
-}
-
pub fn getRouteFiles(
_: void,
ctx: js.JSContextRef,
@@ -783,40 +701,6 @@ pub fn openInEditor(
return JSC.JSValue.jsUndefined().asObjectRef();
}
-pub fn readFileAsBytes(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
-) js.JSValueRef {
- var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
- buf[path.len] = 0;
-
- const buf_z: [:0]const u8 = buf[0..path.len :0];
- const result = readFileAsBytesCallback(ctx, buf_z, exception);
- return result;
-}
-
-pub fn readFileAsString(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- arguments: []const js.JSValueRef,
- exception: js.ExceptionRef,
-) js.JSValueRef {
- var buf: [bun.MAX_PATH_BYTES]u8 = undefined;
- const path = getFilePath(ctx, arguments, &buf, exception) orelse return null;
- buf[path.len] = 0;
-
- const buf_z: [:0]const u8 = buf[0..path.len :0];
- const result = readFileAsStringCallback(ctx, buf_z, exception);
- return result;
-}
-
pub fn getPublicPath(to: string, origin: URL, comptime Writer: type, writer: Writer) void {
return getPublicPathWithAssetPrefix(to, VirtualMachine.get().bundler.fs.top_level_dir, origin, VirtualMachine.get().bundler.options.routes.asset_prefix_path, comptime Writer, writer);
}
@@ -1108,27 +992,6 @@ comptime {
}
}
-pub fn readAllStdinSync(
- _: void,
- ctx: js.JSContextRef,
- _: js.JSObjectRef,
- _: js.JSObjectRef,
- _: []const js.JSValueRef,
- exception: js.ExceptionRef,
-) js.JSValueRef {
- var stack = std.heap.stackFallback(2048, getAllocator(ctx));
- var allocator = stack.get();
-
- var stdin = std.io.getStdIn();
- var result = stdin.readToEndAlloc(allocator, std.math.maxInt(u32)) catch |err| {
- JSError(undefined, "{s} reading stdin", .{@errorName(err)}, ctx, exception);
- return null;
- };
- var out = ZigString.init(result);
- out.detectEncoding();
- return out.toValueGC(ctx.ptr()).asObjectRef();
-}
-
var public_path_temp_str: [bun.MAX_PATH_BYTES]u8 = undefined;
pub fn getPublicPathJS(
@@ -1158,35 +1021,60 @@ pub const Class = NewClass(
.read_only = true,
},
.{
- .match = .{
- .rfn = &Router.deprecatedBunGlobalMatch,
+ // Private
+ // TODO: We should remove _Os, _Path, and make registerMacro and fs be private builtins
+ .DO_NOT_USE_OR_YOU_WILL_BE_FIRED_mimalloc_dump = .{
+ .rfn = &dump_mimalloc,
+ .enumerable = false,
},
- .sleepSync = .{
- .rfn = &sleepSync,
+ ._Os = .{
+ .rfn = &Bun.newOs,
+ .enumerable = false,
},
- // .fetch = .{
- // .rfn = &Fetch.call,
- // },
+ ._Path = .{
+ .rfn = &Bun.newPath,
+ .enumerable = false,
+ },
+ .registerMacro = .{
+ .rfn = &Bun.registerMacro,
+ .enumerable = false,
+ },
+ .fs = .{
+ .rfn = &Bun.createNodeFS,
+ .enumerable = false,
+ },
+ .jest = .{
+ .rfn = &@import("../test/jest.zig").Jest.call,
+ .enumerable = false,
+ },
+
+ // TODO: remove these deprecated methods before 1.0
.getImportedStyles = .{
.rfn = &Bun.getImportedStyles,
- },
- .inspect = .{
- .rfn = &Bun.inspect,
+ .enumerable = false,
},
.getRouteFiles = .{
.rfn = &Bun.getRouteFiles,
+ .enumerable = false,
},
- ._Os = .{
- .rfn = &Bun.newOs,
- },
- ._Path = .{
- .rfn = &Bun.newPath,
+ .match = .{
+ .rfn = &Router.deprecatedBunGlobalMatch,
+ .enumerable = false,
},
.getRouteNames = .{
.rfn = &Bun.getRouteNames,
+ .enumerable = false,
+ },
+
+ // Public API
+ .sleepSync = .{
+ .rfn = &sleepSync,
},
- .readFile = .{
- .rfn = &Bun.readFileAsString,
+ // .fetch = .{
+ // .rfn = &Fetch.call,
+ // },
+ .inspect = .{
+ .rfn = &Bun.inspect,
},
.resolveSync = .{
.rfn = &Bun.resolveSync,
@@ -1194,24 +1082,9 @@ pub const Class = NewClass(
.resolve = .{
.rfn = &Bun.resolve,
},
- .readFileBytes = .{
- .rfn = &Bun.readFileAsBytes,
- },
.getPublicPath = .{
.rfn = &Bun.getPublicPathJS,
},
- .registerMacro = .{
- .rfn = &Bun.registerMacro,
- .enumerable = false,
- },
- .fs = .{
- .rfn = &Bun.createNodeFS,
- .enumerable = false,
- },
- .jest = .{
- .rfn = &@import("../test/jest.zig").Jest.call,
- .enumerable = false,
- },
.indexOfLine = .{
.rfn = &Bun.indexOfLine,
},
@@ -1233,9 +1106,6 @@ pub const Class = NewClass(
.openInEditor = .{
.rfn = &Bun.openInEditor,
},
- .readAllStdinSync = .{
- .rfn = &Bun.readAllStdinSync,
- },
.serve = .{
.rfn = &Bun.serve,
},
@@ -1251,9 +1121,6 @@ pub const Class = NewClass(
.nanoseconds = .{
.rfn = &nanoseconds,
},
- .DO_NOT_USE_OR_YOU_WILL_BE_FIRED_mimalloc_dump = .{
- .rfn = &dump_mimalloc,
- },
.gzipSync = .{
.rfn = &JSC.wrapWithHasContainer(JSZlib, "gzipSync", false, false, true),
},
@@ -1266,7 +1133,6 @@ pub const Class = NewClass(
.inflateSync = .{
.rfn = &JSC.wrapWithHasContainer(JSZlib, "inflateSync", false, false, true),
},
-
.which = .{
.rfn = &which,
},
@@ -1279,11 +1145,9 @@ pub const Class = NewClass(
.build = .{
.rfn = &Bun.JSBundler.buildFn,
},
-
.listen = .{
.rfn = &JSC.wrapWithHasContainer(JSC.API.Listener, "listen", false, false, false),
},
-
.connect = .{
.rfn = &JSC.wrapWithHasContainer(JSC.API.Listener, "connect", false, false, false),
},
@@ -1292,8 +1156,10 @@ pub const Class = NewClass(
.main = .{
.get = getMain,
},
+ // TODO: decide what we want to do
.cwd = .{
.get = getCWD,
+ .enumerable = false,
},
.origin = .{
.get = getOrigin,
@@ -1307,11 +1173,15 @@ pub const Class = NewClass(
.stderr = .{
.get = getStderr,
},
+ // TODO: remove this before 1.0
.routesDir = .{
.get = getRoutesDir,
+ .enumerable = false,
},
+ // TODO: remove this before 1.0
.assetPrefix = .{
.get = getAssetPrefix,
+ .enumerable = false,
},
.argv = .{
.get = getArgv,
@@ -3322,24 +3192,24 @@ pub const Hash = struct {
} else {
var seed: u64 = 0;
if (args.nextEat()) |arg| {
- if (arg.isNumber()) {
- seed = arg.toU32();
+ if (arg.isNumber() or arg.isBigInt()) {
+ seed = arg.toUInt64NoTruncate();
}
}
if (comptime std.meta.trait.isNumber(@TypeOf(function_args[0]))) {
- function_args[0] = @as(@TypeOf(function_args[0]), @intCast(seed));
+ function_args[0] = @as(@TypeOf(function_args[0]), @truncate(seed));
function_args[1] = input;
} else {
- function_args[1] = @as(@TypeOf(function_args[1]), @intCast(seed));
function_args[0] = input;
+ function_args[1] = @as(@TypeOf(function_args[1]), @truncate(seed));
}
const value = @call(.auto, Function, function_args);
if (@TypeOf(value) == u32) {
- return JSC.JSValue.jsNumber(@as(i32, @bitCast(value))).asObjectRef();
+ return JSC.JSValue.jsNumber(@as(u32, @bitCast(value))).asObjectRef();
}
- return JSC.JSValue.jsNumber(value).asObjectRef();
+ return JSC.JSValue.fromUInt64NoTruncate(ctx.ptr(), value).asObjectRef();
}
}
};
diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig
index 4d961b54c332c1..ed76dc777bf5c9 100644
--- a/src/bun.js/api/bun/dns_resolver.zig
+++ b/src/bun.js/api/bun/dns_resolver.zig
@@ -16,6 +16,8 @@ const JSGlobalObject = JSC.JSGlobalObject;
const c_ares = bun.c_ares;
const GetAddrInfoAsyncCallback = fn (i32, ?*std.c.addrinfo, ?*anyopaque) callconv(.C) void;
+const INET6_ADDRSTRLEN = if (bun.Environment.isWindows) 65 else 46;
+const IANA_DNS_PORT = 53;
const LibInfo = struct {
// static int32_t (*getaddrinfo_async_start)(mach_port_t*,
@@ -2015,6 +2017,89 @@ pub const DNSResolver = struct {
return promise;
}
+ pub fn getServers(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ _ = callframe;
+
+ var vm = globalThis.bunVM();
+ var resolver = vm.rareData().globalDNSResolver(vm);
+ var channel: *c_ares.Channel = switch (resolver.getChannel()) {
+ .result => |res| res,
+ .err => |err| {
+ const system_error = JSC.SystemError{
+ .errno = -1,
+ .code = bun.String.static(err.code()),
+ .message = bun.String.static(err.label()),
+ };
+
+ globalThis.throwValue(system_error.toErrorInstance(globalThis));
+ return .zero;
+ },
+ };
+
+ var servers: [*c]c_ares.struct_ares_addr_port_node = undefined;
+ const r = c_ares.ares_get_servers_ports(channel, &servers);
+ if (r != c_ares.ARES_SUCCESS) {
+ const err = c_ares.Error.get(r).?;
+ globalThis.throwValue(globalThis.createErrorInstance("ares_get_servers_ports error: {s}", .{err.label()}));
+ return .zero;
+ }
+ defer c_ares.ares_free_data(servers);
+
+ const values = JSC.JSValue.createEmptyArray(globalThis, 0);
+
+ var i: u32 = 0;
+ var cur = servers;
+ while (cur != null) : ({
+ i += 1;
+ cur = cur.*.next;
+ }) {
+ // Formatting reference: https://nodejs.org/api/dns.html#dnsgetservers
+ // Brackets '[' and ']' consume 2 bytes, used for IPv6 format (e.g., '[2001:4860:4860::8888]:1053').
+ // Port range is 6 bytes (e.g., ':65535').
+ // Null terminator '\0' uses 1 byte.
+ var buf: [INET6_ADDRSTRLEN + 2 + 6 + 1]u8 = undefined;
+ const family = cur.*.family;
+
+ const ip = if (family == std.os.AF.INET6) blk: {
+ break :blk c_ares.ares_inet_ntop(family, &cur.*.addr.addr6, buf[1..], @sizeOf(@TypeOf(buf)) - 1);
+ } else blk: {
+ break :blk c_ares.ares_inet_ntop(family, &cur.*.addr.addr4, buf[1..], @sizeOf(@TypeOf(buf)) - 1);
+ };
+ if (ip == null) {
+ globalThis.throwValue(globalThis.createErrorInstance(
+ "ares_inet_ntop error: no more space to convert a network format address",
+ .{},
+ ));
+ return .zero;
+ }
+
+ var port = cur.*.tcp_port;
+ if (port == 0) {
+ port = cur.*.udp_port;
+ }
+ if (port == 0) {
+ port = IANA_DNS_PORT;
+ }
+
+ const size = bun.len(bun.cast([*:0]u8, &buf));
+ if (port == IANA_DNS_PORT) {
+ values.putIndex(globalThis, i, JSC.ZigString.init(buf[1..size]).withEncoding().toValueGC(globalThis));
+ } else {
+ if (family == std.os.AF.INET6) {
+ buf[0] = '[';
+ buf[size] = ']';
+ const port_slice = std.fmt.bufPrint(buf[size + 1 ..], ":{d}", .{port}) catch unreachable;
+ values.putIndex(globalThis, i, JSC.ZigString.init(buf[0 .. size + 1 + port_slice.len]).withEncoding().toValueGC(globalThis));
+ } else {
+ const port_slice = std.fmt.bufPrint(buf[size..], ":{d}", .{port}) catch unreachable;
+ values.putIndex(globalThis, i, JSC.ZigString.init(buf[1 .. size + port_slice.len]).withEncoding().toValueGC(globalThis));
+ }
+ }
+ }
+
+ return values;
+ }
+
comptime {
@export(
resolve,
@@ -2082,6 +2167,12 @@ pub const DNSResolver = struct {
.name = "Bun__DNSResolver__resolveCname",
},
);
+ @export(
+ getServers,
+ .{
+ .name = "Bun__DNSResolver__getServers",
+ },
+ );
}
// pub fn lookupService(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
// const arguments = callframe.arguments(3);
diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig
index 216f66b7fa259f..edb666040f17b3 100644
--- a/src/bun.js/api/filesystem_router.zig
+++ b/src/bun.js/api/filesystem_router.zig
@@ -75,6 +75,8 @@ const DeprecatedGlobalRouter = struct {
};
var path_: ?ZigString.Slice = null;
+ var req_url_slice: ZigString.Slice = .{};
+ defer req_url_slice.deinit();
var pathname: string = "";
defer {
if (path_) |path| {
@@ -88,7 +90,8 @@ const DeprecatedGlobalRouter = struct {
var url = URL.parse(path_.?.slice());
pathname = url.pathname;
} else if (arg.as(Request)) |req| {
- var url = URL.parse(req.url);
+ req_url_slice = req.url.toUTF8(bun.default_allocator);
+ var url = URL.parse(req_url_slice.slice());
pathname = url.pathname;
}
@@ -389,11 +392,11 @@ pub const FileSystemRouter = struct {
if (argument.isCell()) {
if (argument.as(JSC.WebCore.Request)) |req| {
req.ensureURL() catch unreachable;
- break :brk ZigString.Slice.fromUTF8NeverFree(req.url).clone(globalThis.allocator()) catch unreachable;
+ break :brk req.url.toUTF8(globalThis.allocator());
}
if (argument.as(JSC.WebCore.Response)) |resp| {
- break :brk ZigString.Slice.fromUTF8NeverFree(resp.url).clone(globalThis.allocator()) catch unreachable;
+ break :brk resp.url.toUTF8(globalThis.allocator());
}
}
diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig
index 92e9790c6c135a..f754e3e239516a 100644
--- a/src/bun.js/api/html_rewriter.zig
+++ b/src/bun.js/api/html_rewriter.zig
@@ -454,8 +454,8 @@ pub const HTMLRewriter = struct {
result.body.init.headers = headers.cloneThis(global);
}
- result.url = bun.default_allocator.dupe(u8, original.url) catch unreachable;
- result.status_text = bun.default_allocator.dupe(u8, original.status_text) catch unreachable;
+ result.url = original.url.clone();
+ result.status_text = original.status_text.clone();
var input = original.body.value.useAsAnyBlob();
sink.input = input;
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 801745aee3b1ce..195d2a3f38e4f7 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -169,8 +169,7 @@ pub const ServerConfig = struct {
const log = Output.scoped(.SSLConfig, false);
pub fn asUSockets(this_: ?SSLConfig) uws.us_bun_socket_context_options_t {
- var ctx_opts: uws.us_bun_socket_context_options_t = undefined;
- @memset(@as([*]u8, @ptrCast(&ctx_opts))[0..@sizeOf(uws.us_bun_socket_context_options_t)], 0);
+ var ctx_opts: uws.us_bun_socket_context_options_t = .{};
if (this_) |ssl_config| {
if (ssl_config.key_file_name != null)
@@ -1069,7 +1068,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
byte_stream: ?*JSC.WebCore.ByteStream = null,
/// Used in errors
- pathname: []const u8 = "",
+ pathname: bun.String = bun.String.empty,
/// Used either for temporary blob data or fallback
/// When the response body is a temporary value
@@ -1550,10 +1549,9 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
stream.unpipe();
}
- if (this.pathname.len > 0) {
- ctxLog("finalizeWithoutDeinit: this.pathname.len > 0 null", .{});
- this.allocator.free(bun.constStrToU8(this.pathname));
- this.pathname = "";
+ if (!this.pathname.isEmpty()) {
+ this.pathname.deref();
+ this.pathname = bun.String.empty;
}
// if we are waiting for the body yet and the request was not aborted we can safely clear the onData callback
@@ -2235,7 +2233,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
request_object.uws_request = req;
request_object.ensureURL() catch {
- request_object.url = "";
+ request_object.url = bun.String.empty;
};
// we have to clone the request headers here since they will soon belong to a different request
@@ -2244,7 +2242,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
if (comptime debug_mode) {
- ctx.pathname = bun.default_allocator.dupe(u8, request_object.url) catch unreachable;
+ ctx.pathname = request_object.url.clone();
}
// This object dies after the stack frame is popped
@@ -2596,15 +2594,28 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
runErrorHandlerWithStatusCode(this, value, 500);
}
- fn ensurePathname(this: *RequestContext) []const u8 {
- if (this.pathname.len > 0)
- return this.pathname;
+ const PathnameFormatter = struct {
+ ctx: *RequestContext,
+
+ pub fn format(formatter: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ var this = formatter.ctx;
+
+ if (!this.pathname.isEmpty()) {
+ try this.pathname.format(fmt, opts, writer);
+ return;
+ }
- if (!this.flags.has_abort_handler) {
- return this.req.url();
+ if (!this.flags.has_abort_handler) {
+ try writer.writeAll(this.req.url());
+ return;
+ }
+
+ try writer.writeAll("/");
}
+ };
- return "/";
+ fn ensurePathname(this: *RequestContext) PathnameFormatter {
+ return .{ .ctx = this };
}
pub inline fn shouldCloseConnection(this: *const RequestContext) bool {
@@ -2625,7 +2636,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
vm.log,
error.ExceptionOcurred,
exception_list.toOwnedSlice() catch @panic("TODO"),
- "{s} - {s} failed",
+ "{s} - {} failed",
.{ @as(string, @tagName(this.method)), this.ensurePathname() },
);
} else {
@@ -4900,8 +4911,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
existing_request = Request{
- .url = url.href,
- .url_was_allocated = true,
+ .url = bun.String.create(url.href),
.headers = headers,
.body = JSC.WebCore.InitRequestBodyValue(body) catch unreachable,
.method = method,
@@ -4943,7 +4953,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
if (response_value.as(JSC.WebCore.Response)) |resp| {
- resp.url = this.allocator.dupe(u8, existing_request.url) catch unreachable;
+ resp.url = existing_request.url.clone();
}
return JSC.JSPromise.resolvedPromiseValue(ctx, response_value).asObjectRef();
}
@@ -5295,7 +5305,6 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
request_object.* = .{
- .url = "",
.method = ctx.method,
.uws_request = req,
.https = ssl_enabled,
@@ -5398,7 +5407,6 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
request_object.* = .{
- .url = "",
.method = ctx.method,
.uws_request = req,
.upgrader = ctx,
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index f7b2eb343cc04b..c964c1d95a8932 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -266,58 +266,21 @@ pub const To = struct {
// Recursion can stack overflow here
if (comptime std.meta.trait.isSlice(Type)) {
- const Child = std.meta.Child(Type);
-
- const prefill = 32;
- if (value.len <= prefill) {
- var array: [prefill]JSC.C.JSValueRef = undefined;
- var i: u8 = 0;
- const len = @min(@as(u8, @intCast(value.len)), prefill);
- while (i < len and exception.* == null) : (i += 1) {
- array[i] = if (comptime Child == JSC.C.JSValueRef)
- value[i]
- else
- To.JS.withType(Child, value[i], context, exception);
- }
-
- if (exception.* != null) {
- return null;
- }
-
- // TODO: this function copies to a MarkedArgumentsBuffer
- // That copy is unnecessary.
- const obj = JSC.C.JSObjectMakeArray(context, len, &array, exception);
-
- if (exception.* != null) {
- return null;
- }
- return obj;
- }
-
- {
- var array = bun.default_allocator.alloc(JSC.C.JSValueRef, value.len) catch unreachable;
- defer bun.default_allocator.free(array);
- var i: usize = 0;
- while (i < value.len and exception.* == null) : (i += 1) {
- array[i] = if (comptime Child == JSC.C.JSValueRef)
- value[i]
- else
- To.JS.withType(Child, value[i], context, exception);
- }
+ const Child = comptime std.meta.Child(Type);
- if (exception.* != null) {
- return null;
- }
+ var array = JSC.JSValue.createEmptyArray(context, value.len);
+ for (value, 0..) |item, i| {
+ array.putIndex(
+ context,
+ @truncate(i),
+ JSC.JSValue.c(To.JS.withType(Child, item, context, exception)),
+ );
- // TODO: this function copies to a MarkedArgumentsBuffer
- // That copy is unnecessary.
- const obj = JSC.C.JSObjectMakeArray(context, value.len, array.ptr, exception);
if (exception.* != null) {
return null;
}
-
- return obj;
}
+ return array.asObjectRef();
}
if (comptime std.meta.trait.isZigString(Type)) {
@@ -4004,78 +3967,7 @@ pub const FilePoll = struct {
}
};
-pub const Strong = extern struct {
- ref: ?*JSC.napi.Ref = null,
-
- pub fn init() Strong {
- return .{};
- }
-
- pub fn create(
- value: JSC.JSValue,
- globalThis: *JSC.JSGlobalObject,
- ) Strong {
- var str = Strong.init();
- if (value != .zero)
- str.set(globalThis, value);
- return str;
- }
-
- pub fn get(this: *Strong) ?JSValue {
- var ref = this.ref orelse return null;
- const result = ref.get();
- if (result == .zero) {
- return null;
- }
-
- return result;
- }
-
- pub fn swap(this: *Strong) JSValue {
- var ref = this.ref orelse return .zero;
- const result = ref.get();
- if (result == .zero) {
- return .zero;
- }
-
- ref.set(.zero);
- return result;
- }
-
- pub fn has(this: *Strong) bool {
- var ref = this.ref orelse return false;
- return ref.get() != .zero;
- }
-
- pub fn trySwap(this: *Strong) ?JSValue {
- const result = this.swap();
- if (result == .zero) {
- return null;
- }
-
- return result;
- }
-
- pub fn set(this: *Strong, globalThis: *JSC.JSGlobalObject, value: JSValue) void {
- var ref: *JSC.napi.Ref = this.ref orelse {
- if (value == .zero) return;
- this.ref = JSC.napi.Ref.create(globalThis, value);
- return;
- };
- ref.set(value);
- }
-
- pub fn clear(this: *Strong) void {
- var ref: *JSC.napi.Ref = this.ref orelse return;
- ref.set(JSC.JSValue.zero);
- }
-
- pub fn deinit(this: *Strong) void {
- var ref: *JSC.napi.Ref = this.ref orelse return;
- this.ref = null;
- ref.destroy();
- }
-};
+pub const Strong = @import("./Strong.zig").Strong;
pub const BinaryType = enum {
Buffer,
diff --git a/src/bun.js/bindings/BunJSCModule.cpp b/src/bun.js/bindings/BunJSCModule.cpp
deleted file mode 100644
index a145f51c5dde7b..00000000000000
--- a/src/bun.js/bindings/BunJSCModule.cpp
+++ /dev/null
@@ -1,641 +0,0 @@
-#include "root.h"
-
-#include "JavaScriptCore/JavaScript.h"
-#include "wtf/FileSystem.h"
-#include "wtf/MemoryFootprint.h"
-#include "wtf/text/WTFString.h"
-#include "JavaScriptCore/CodeBlock.h"
-#include "JavaScriptCore/JSCInlines.h"
-#include "JavaScriptCore/TestRunnerUtils.h"
-#include "JavaScriptCore/JIT.h"
-#include "JavaScriptCore/APICast.h"
-#include "JavaScriptCore/JSBasePrivate.h"
-#include "JavaScriptCore/ObjectConstructor.h"
-#include "JavaScriptCore/AggregateError.h"
-#include "JavaScriptCore/BytecodeIndex.h"
-#include "JavaScriptCore/CallFrameInlines.h"
-#include "JavaScriptCore/ClassInfo.h"
-#include "JavaScriptCore/CodeBlock.h"
-#include "JavaScriptCore/Completion.h"
-#include "JavaScriptCore/Error.h"
-#include "JavaScriptCore/ErrorInstance.h"
-#include "JavaScriptCore/HeapSnapshotBuilder.h"
-#include "JavaScriptCore/JSONObject.h"
-#include "JavaScriptCore/DeferTermination.h"
-#include "JavaScriptCore/SamplingProfiler.h"
-#include "JavaScriptCore/VMTrapsInlines.h"
-#include "SerializedScriptValue.h"
-#include "ExceptionOr.h"
-
-#if ENABLE(REMOTE_INSPECTOR)
-#include "JavaScriptCore/RemoteInspectorServer.h"
-#endif
-
-#include "mimalloc.h"
-#include "JSDOMConvertBase.h"
-
-using namespace JSC;
-using namespace WTF;
-using namespace WebCore;
-
-JSC_DECLARE_HOST_FUNCTION(functionStartRemoteDebugger);
-JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
-#if ENABLE(REMOTE_INSPECTOR)
- static const char* defaultHost = "127.0.0.1\0";
- static uint16_t defaultPort = 9230; // node + 1
- auto& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- JSC::JSValue hostValue = callFrame->argument(0);
- JSC::JSValue portValue = callFrame->argument(1);
- const char* host = defaultHost;
- if (hostValue.isString()) {
-
- auto str = hostValue.toWTFString(globalObject);
- if (!str.isEmpty())
- host = toCString(str).data();
- } else if (!hostValue.isUndefined()) {
- throwVMError(globalObject, scope, createTypeError(globalObject, "host must be a string"_s));
- return JSC::JSValue::encode(JSC::jsUndefined());
- }
-
- uint16_t port = defaultPort;
- if (portValue.isNumber()) {
- auto port_int = portValue.toUInt32(globalObject);
- if (!(port_int > 0 && port_int < 65536)) {
- throwVMError(globalObject, scope, createRangeError(globalObject, "port must be between 0 and 65535"_s));
- return JSC::JSValue::encode(JSC::jsUndefined());
- }
- port = port_int;
- } else if (!portValue.isUndefined()) {
- throwVMError(globalObject, scope, createTypeError(globalObject, "port must be a number between 0 and 65535"_s));
- return JSC::JSValue::encode(JSC::jsUndefined());
- }
-
- globalObject->setInspectable(true);
- auto& server = Inspector::RemoteInspectorServer::singleton();
- if (!server.start(reinterpret_cast(host), port)) {
- throwVMError(globalObject, scope, createError(globalObject, "Failed to start server \""_s + host + ":"_s + port + "\". Is port already in use?"_s));
- return JSC::JSValue::encode(JSC::jsUndefined());
- }
-
- RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::jsUndefined()));
-#else
- auto& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- throwVMError(globalObject, scope, createTypeError(globalObject, "Remote inspector is not enabled in this build of Bun"_s));
- return JSC::JSValue::encode(JSC::jsUndefined());
-#endif
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionDescribe);
-JSC_DEFINE_HOST_FUNCTION(functionDescribe, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- VM& vm = globalObject->vm();
- if (callFrame->argumentCount() < 1)
- return JSValue::encode(jsUndefined());
- return JSValue::encode(jsString(vm, toString(callFrame->argument(0))));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionDescribeArray);
-JSC_DEFINE_HOST_FUNCTION(functionDescribeArray, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- if (callFrame->argumentCount() < 1)
- return JSValue::encode(jsUndefined());
- VM& vm = globalObject->vm();
- JSObject* object = jsDynamicCast(callFrame->argument(0));
- if (!object)
- return JSValue::encode(jsNontrivialString(vm, ""_s));
- return JSValue::encode(jsNontrivialString(vm, toString("butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionGCAndSweep);
-JSC_DEFINE_HOST_FUNCTION(functionGCAndSweep, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- vm.heap.collectNow(Sync, CollectionScope::Full);
- return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionFullGC);
-JSC_DEFINE_HOST_FUNCTION(functionFullGC, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- vm.heap.collectSync(CollectionScope::Full);
- return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionEdenGC);
-JSC_DEFINE_HOST_FUNCTION(functionEdenGC, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- vm.heap.collectSync(CollectionScope::Eden);
- return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionHeapSize);
-JSC_DEFINE_HOST_FUNCTION(functionHeapSize, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- return JSValue::encode(jsNumber(vm.heap.size()));
-}
-
-class JSCMemoryFootprint : public JSDestructibleObject {
- using Base = JSDestructibleObject;
-
-public:
- template
- static CompleteSubspace* subspaceFor(VM& vm)
- {
- return &vm.destructibleObjectSpace();
- }
-
- JSCMemoryFootprint(VM& vm, Structure* structure)
- : Base(vm, structure)
- {
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
- }
-
- static JSCMemoryFootprint* create(VM& vm, JSGlobalObject* globalObject)
- {
- Structure* structure = createStructure(vm, globalObject, jsNull());
- JSCMemoryFootprint* footprint = new (NotNull, allocateCell(vm)) JSCMemoryFootprint(vm, structure);
- footprint->finishCreation(vm);
- return footprint;
- }
-
- void finishCreation(VM& vm)
- {
- Base::finishCreation(vm);
-
- auto addProperty = [&](VM& vm, ASCIILiteral name, JSValue value) {
- JSCMemoryFootprint::addProperty(vm, name, value);
- };
-
- size_t elapsed_msecs = 0;
- size_t user_msecs = 0;
- size_t system_msecs = 0;
- size_t current_rss = 0;
- size_t peak_rss = 0;
- size_t current_commit = 0;
- size_t peak_commit = 0;
- size_t page_faults = 0;
-
- mi_process_info(&elapsed_msecs, &user_msecs, &system_msecs,
- ¤t_rss, &peak_rss,
- ¤t_commit, &peak_commit, &page_faults);
-
- addProperty(vm, "current"_s, jsNumber(current_rss));
- addProperty(vm, "peak"_s, jsNumber(peak_rss));
- addProperty(vm, "currentCommit"_s, jsNumber(current_commit));
- addProperty(vm, "peakCommit"_s, jsNumber(peak_commit));
- addProperty(vm, "pageFaults"_s, jsNumber(page_faults));
- }
-
- DECLARE_INFO;
-
-private:
- void addProperty(VM& vm, ASCIILiteral name, JSValue value)
- {
- Identifier identifier = Identifier::fromString(vm, name);
- putDirect(vm, identifier, value);
- }
-};
-
-const ClassInfo JSCMemoryFootprint::s_info = { "MemoryFootprint"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCMemoryFootprint) };
-
-JSC_DECLARE_HOST_FUNCTION(functionMemoryUsageStatistics);
-JSC_DEFINE_HOST_FUNCTION(functionMemoryUsageStatistics, (JSGlobalObject * globalObject, CallFrame*))
-{
-
- auto& vm = globalObject->vm();
- JSC::DisallowGC disallowGC;
-
- // this is a C API function
- auto* stats = toJS(JSGetMemoryUsageStatistics(toRef(globalObject)));
-
- if (JSValue heapSizeValue = stats->getDirect(vm, Identifier::fromString(vm, "heapSize"_s))) {
- ASSERT(heapSizeValue.isNumber());
- if (heapSizeValue.toInt32(globalObject) == 0) {
- vm.heap.collectNow(Sync, CollectionScope::Full);
- stats = toJS(JSGetMemoryUsageStatistics(toRef(globalObject)));
- }
- }
-
- // This is missing from the C API
- JSC::JSObject* protectedCounts = constructEmptyObject(globalObject);
- auto typeCounts = *vm.heap.protectedObjectTypeCounts();
- for (auto& it : typeCounts)
- protectedCounts->putDirect(vm, Identifier::fromLatin1(vm, it.key), jsNumber(it.value));
-
- stats->putDirect(vm, Identifier::fromLatin1(vm, "protectedObjectTypeCounts"_s), protectedCounts);
- return JSValue::encode(stats);
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionCreateMemoryFootprint);
-JSC_DEFINE_HOST_FUNCTION(functionCreateMemoryFootprint, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- return JSValue::encode(JSCMemoryFootprint::create(vm, globalObject));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionNeverInlineFunction);
-JSC_DEFINE_HOST_FUNCTION(functionNeverInlineFunction, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- return JSValue::encode(setNeverInline(globalObject, callFrame));
-}
-
-extern "C" bool Bun__mkdirp(JSC::JSGlobalObject*, const char*);
-
-JSC_DECLARE_HOST_FUNCTION(functionStartSamplingProfiler);
-JSC_DEFINE_HOST_FUNCTION(functionStartSamplingProfiler, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
-{
- JSC::VM& vm = globalObject->vm();
- JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
-
- JSC::JSValue directoryValue = callFrame->argument(0);
- JSC::JSValue sampleValue = callFrame->argument(1);
-
- auto scope = DECLARE_THROW_SCOPE(vm);
- if (directoryValue.isString()) {
- auto path = directoryValue.toWTFString(globalObject);
- if (!path.isEmpty()) {
- StringPrintStream pathOut;
- auto pathCString = toCString(String(path));
- if (!Bun__mkdirp(globalObject, pathCString.data())) {
- throwVMError(globalObject, scope, createTypeError(globalObject, "directory couldn't be created"_s));
- return JSC::JSValue::encode(jsUndefined());
- }
-
- Options::samplingProfilerPath() = pathCString.data();
- samplingProfiler.registerForReportAtExit();
- }
- }
- if (sampleValue.isNumber()) {
- unsigned sampleInterval = sampleValue.toUInt32(globalObject);
- samplingProfiler.setTimingInterval(Seconds::fromMicroseconds(sampleInterval));
- }
-
- samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
- samplingProfiler.start();
- return JSC::JSValue::encode(jsUndefined());
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionSamplingProfilerStackTraces);
-JSC_DEFINE_HOST_FUNCTION(functionSamplingProfilerStackTraces, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
-{
- JSC::VM& vm = globalObject->vm();
- JSC::DeferTermination deferScope(vm);
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- if (!vm.samplingProfiler())
- return JSC::JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Sampling profiler was never started"_s)));
-
- WTF::String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
- JSC::EncodedJSValue result = JSC::JSValue::encode(JSONParse(globalObject, jsonString));
- scope.releaseAssertNoException();
- return result;
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionGetRandomSeed);
-JSC_DEFINE_HOST_FUNCTION(functionGetRandomSeed, (JSGlobalObject * globalObject, CallFrame*))
-{
- return JSValue::encode(jsNumber(globalObject->weakRandom().seed()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionSetRandomSeed);
-JSC_DEFINE_HOST_FUNCTION(functionSetRandomSeed, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- unsigned seed = callFrame->argument(0).toUInt32(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- globalObject->weakRandom().setSeed(seed);
- return JSValue::encode(jsUndefined());
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionIsRope);
-JSC_DEFINE_HOST_FUNCTION(functionIsRope, (JSGlobalObject*, CallFrame* callFrame))
-{
- JSValue argument = callFrame->argument(0);
- if (!argument.isString())
- return JSValue::encode(jsBoolean(false));
- const StringImpl* impl = asString(argument)->tryGetValueImpl();
- return JSValue::encode(jsBoolean(!impl));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionCallerSourceOrigin);
-JSC_DEFINE_HOST_FUNCTION(functionCallerSourceOrigin, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- VM& vm = globalObject->vm();
- SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
- if (sourceOrigin.url().isNull())
- return JSValue::encode(jsNull());
- return JSValue::encode(jsString(vm, sourceOrigin.string()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionNoFTL);
-JSC_DEFINE_HOST_FUNCTION(functionNoFTL, (JSGlobalObject*, CallFrame* callFrame))
-{
- if (callFrame->argumentCount()) {
- FunctionExecutable* executable = getExecutableForFunction(callFrame->argument(0));
- if (executable)
- executable->setNeverFTLOptimize(true);
- }
- return JSValue::encode(jsUndefined());
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionNoOSRExitFuzzing);
-JSC_DEFINE_HOST_FUNCTION(functionNoOSRExitFuzzing, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- return JSValue::encode(setCannotUseOSRExitFuzzing(globalObject, callFrame));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionOptimizeNextInvocation);
-JSC_DEFINE_HOST_FUNCTION(functionOptimizeNextInvocation, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- return JSValue::encode(optimizeNextInvocation(globalObject, callFrame));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionNumberOfDFGCompiles);
-JSC_DEFINE_HOST_FUNCTION(functionNumberOfDFGCompiles, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- return JSValue::encode(numberOfDFGCompiles(globalObject, callFrame));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionReleaseWeakRefs);
-JSC_DEFINE_HOST_FUNCTION(functionReleaseWeakRefs, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- globalObject->vm().finalizeSynchronousJSExecution();
- return JSValue::encode(jsUndefined());
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionTotalCompileTime);
-JSC_DEFINE_HOST_FUNCTION(functionTotalCompileTime, (JSGlobalObject*, CallFrame*))
-{
- return JSValue::encode(jsNumber(JIT::totalCompileTime().milliseconds()));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionGetProtectedObjects);
-JSC_DEFINE_HOST_FUNCTION(functionGetProtectedObjects, (JSGlobalObject * globalObject, CallFrame*))
-{
- MarkedArgumentBuffer list;
- size_t result = 0;
- globalObject->vm().heap.forEachProtectedCell(
- [&](JSCell* cell) {
- list.append(cell);
- });
- RELEASE_ASSERT(!list.hasOverflowed());
- return JSC::JSValue::encode(constructArray(globalObject, static_cast(nullptr), list));
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionReoptimizationRetryCount);
-JSC_DEFINE_HOST_FUNCTION(functionReoptimizationRetryCount, (JSGlobalObject*, CallFrame* callFrame))
-{
- if (callFrame->argumentCount() < 1)
- return JSValue::encode(jsUndefined());
-
- CodeBlock* block = getSomeBaselineCodeBlockForFunction(callFrame->argument(0));
- if (!block)
- return JSValue::encode(jsNumber(0));
-
- return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
-}
-
-extern "C" void Bun__drainMicrotasks();
-
-JSC_DECLARE_HOST_FUNCTION(functionDrainMicrotasks);
-JSC_DEFINE_HOST_FUNCTION(functionDrainMicrotasks, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- vm.drainMicrotasks();
- Bun__drainMicrotasks();
- return JSValue::encode(jsUndefined());
-}
-
-JSC_DEFINE_HOST_FUNCTION(functionSetTimeZone, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- if (callFrame->argumentCount() < 1) {
- throwTypeError(globalObject, scope, "setTimeZone requires a timezone string"_s);
- return encodedJSValue();
- }
-
- if (!callFrame->argument(0).isString()) {
- throwTypeError(globalObject, scope, "setTimeZone requires a timezone string"_s);
- return encodedJSValue();
- }
-
- String timeZoneName = callFrame->argument(0).toWTFString(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
-
- double time = callFrame->argument(1).toNumber(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
-
- if (!WTF::setTimeZoneOverride(timeZoneName)) {
- throwTypeError(globalObject, scope, makeString("Invalid timezone: \""_s, timeZoneName, "\""_s));
- return encodedJSValue();
- }
- vm.dateCache.resetIfNecessarySlow();
- WTF::Vector buffer;
- WTF::getTimeZoneOverride(buffer);
- WTF::String timeZoneString(buffer.data(), buffer.size());
- return JSValue::encode(jsString(vm, timeZoneString));
-}
-
-JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- JSC::VM& vm = globalObject->vm();
- JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
-
- JSC::JSValue callbackValue = callFrame->argument(0);
- auto throwScope = DECLARE_THROW_SCOPE(vm);
- if (callbackValue.isUndefinedOrNull() || !callbackValue.isCallable()) {
- throwException(globalObject, throwScope, createTypeError(globalObject, "First argument must be a function."_s));
- return JSValue::encode(JSValue {});
- }
-
- JSC::JSFunction* function = jsCast(callbackValue);
-
- JSC::JSValue sampleValue = callFrame->argument(1);
- if (sampleValue.isNumber()) {
- unsigned sampleInterval = sampleValue.toUInt32(globalObject);
- samplingProfiler.setTimingInterval(Seconds::fromMicroseconds(sampleInterval));
- }
-
- JSC::CallData callData = JSC::getCallData(function);
- MarkedArgumentBuffer args;
-
- samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
- samplingProfiler.start();
- JSC::call(globalObject, function, callData, JSC::jsUndefined(), args);
- samplingProfiler.pause();
- if (throwScope.exception()) {
- samplingProfiler.shutdown();
- samplingProfiler.clearData();
- return JSValue::encode(JSValue {});
- }
-
- StringPrintStream topFunctions;
- samplingProfiler.reportTopFunctions(topFunctions);
-
- StringPrintStream byteCodes;
- samplingProfiler.reportTopBytecodes(byteCodes);
-
- JSValue stackTraces = JSONParse(globalObject, samplingProfiler.stackTracesAsJSON());
-
- samplingProfiler.shutdown();
- samplingProfiler.clearData();
-
- JSObject* result = constructEmptyObject(globalObject, globalObject->objectPrototype(), 3);
- result->putDirect(vm, Identifier::fromString(vm, "functions"_s), jsString(vm, topFunctions.toString()));
- result->putDirect(vm, Identifier::fromString(vm, "bytecodes"_s), jsString(vm, byteCodes.toString()));
- result->putDirect(vm, Identifier::fromString(vm, "stackTraces"_s), stackTraces);
-
- return JSValue::encode(result);
-}
-
-JSC_DECLARE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging);
-JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging, (JSGlobalObject * globalObject, CallFrame*))
-{
- VM& vm = globalObject->vm();
- JSLockHolder lock(vm);
- DeferTermination deferScope(vm);
- auto scope = DECLARE_THROW_SCOPE(vm);
- String jsonString;
- {
- DeferGCForAWhile deferGC(vm); // Prevent concurrent GC from interfering with the full GC that the snapshot does.
-
- HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler(), HeapSnapshotBuilder::SnapshotType::GCDebuggingSnapshot);
- snapshotBuilder.buildSnapshot();
-
- jsonString = snapshotBuilder.json();
- }
- scope.releaseAssertNoException();
-
- return JSValue::encode(JSONParse(globalObject, WTFMove(jsonString)));
-}
-
-JSC_DEFINE_HOST_FUNCTION(functionSerialize, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
-{
- auto* globalObject = jsCast(lexicalGlobalObject);
- JSC::VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
-
- JSValue value = callFrame->argument(0);
- JSValue optionsObject = callFrame->argument(1);
- bool asNodeBuffer = false;
- if (optionsObject.isObject()) {
- JSC::JSObject* options = optionsObject.getObject();
- if (JSC::JSValue binaryTypeValue = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "binaryType"_s))) {
- if (!binaryTypeValue.isString()) {
- throwTypeError(globalObject, throwScope, "binaryType must be a string"_s);
- return JSValue::encode(jsUndefined());
- }
-
- asNodeBuffer = binaryTypeValue.toWTFString(globalObject) == "nodebuffer"_s;
- RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- }
- }
-
- Vector> transferList;
-
- ExceptionOr[> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList));
-
- if (serialized.hasException()) {
- WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
- return JSValue::encode(jsUndefined());
- }
-
- auto serializedValue = serialized.releaseReturnValue();
- auto arrayBuffer = serializedValue->toArrayBuffer();
-
- if (asNodeBuffer) {
- size_t byteLength = arrayBuffer->byteLength();
- JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(arrayBuffer), 0, byteLength);
- return JSValue::encode(uint8Array);
- }
-
- if (arrayBuffer->isShared()) {
- return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructureWithSharingMode(), WTFMove(arrayBuffer)));
- }
-
- return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(), WTFMove(arrayBuffer)));
-}
-JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, CallFrame* callFrame))
-{
- JSC::VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
- JSValue value = callFrame->argument(0);
-
- JSValue result;
-
- if (auto* jsArrayBuffer = jsDynamicCast(value)) {
- result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, jsArrayBuffer->impl(), 0, jsArrayBuffer->impl()->byteLength());
- } else if (auto* view = jsDynamicCast(value)) {
- auto arrayBuffer = view->possiblySharedImpl()->possiblySharedBuffer();
- result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, arrayBuffer.get(), view->byteOffset(), view->byteLength());
- } else {
- throwTypeError(globalObject, throwScope, "First argument must be an ArrayBuffer"_s);
- return JSValue::encode(jsUndefined());
- }
-
- RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
-}
-
-JSC::JSObject* createJSCModule(JSC::JSGlobalObject* globalObject)
-{
- VM& vm = globalObject->vm();
- JSC::JSObject* object = nullptr;
-
- {
- JSC::ObjectInitializationScope initializationScope(vm);
- object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 23);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "callerSourceOrigin"_s), 1, functionCallerSourceOrigin, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "describe"_s), 1, functionDescribe, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "describeArray"_s), 1, functionDescribeArray, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "drainMicrotasks"_s), 1, functionDrainMicrotasks, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "edenGC"_s), 1, functionEdenGC, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "fullGC"_s), 1, functionFullGC, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "gcAndSweep"_s), 1, functionGCAndSweep, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "getRandomSeed"_s), 1, functionGetRandomSeed, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "heapSize"_s), 1, functionHeapSize, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "heapStats"_s), 1, functionMemoryUsageStatistics, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "startSamplingProfiler"_s), 1, functionStartSamplingProfiler, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "samplingProfilerStackTraces"_s), 1, functionSamplingProfilerStackTraces, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "noInline"_s), 1, functionNeverInlineFunction, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "isRope"_s), 1, functionIsRope, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "memoryUsage"_s), 1, functionCreateMemoryFootprint, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "noFTL"_s), 1, functionNoFTL, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "noOSRExitFuzzing"_s), 1, functionNoOSRExitFuzzing, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "numberOfDFGCompiles"_s), 1, functionNumberOfDFGCompiles, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "optimizeNextInvocation"_s), 1, functionOptimizeNextInvocation, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "releaseWeakRefs"_s), 1, functionReleaseWeakRefs, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "reoptimizationRetryCount"_s), 1, functionReoptimizationRetryCount, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "setRandomSeed"_s), 1, functionSetRandomSeed, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "startRemoteDebugger"_s), 2, functionStartRemoteDebugger, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "totalCompileTime"_s), 1, functionTotalCompileTime, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "getProtectedObjects"_s), 1, functionGetProtectedObjects, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "generateHeapSnapshotForDebugging"_s), 0, functionGenerateHeapSnapshotForDebugging, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "profile"_s), 0, functionRunProfiler, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "setTimeZone"_s), 0, functionSetTimeZone, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "serialize"_s), 0, functionSerialize, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "deserialize"_s), 0, functionDeserialize, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- }
-
- return object;
-}
diff --git a/src/bun.js/bindings/BunJSCModule.h b/src/bun.js/bindings/BunJSCModule.h
deleted file mode 100644
index 7df47a56640ae4..00000000000000
--- a/src/bun.js/bindings/BunJSCModule.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "root.h"
-#include "JavaScriptCore/JSObject.h"
-
-JSC::JSObject* createJSCModule(JSC::JSGlobalObject* globalObject);
\ No newline at end of file
diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp
index 714f10080cdb53..09b545cba08807 100644
--- a/src/bun.js/bindings/BunString.cpp
+++ b/src/bun.js/bindings/BunString.cpp
@@ -6,6 +6,7 @@
#include "wtf/text/ExternalStringImpl.h"
#include "GCDefferalContext.h"
#include
+#include
using namespace JSC;
@@ -25,11 +26,23 @@ extern "C" void Bun__WTFStringImpl__ref(WTF::StringImpl* impl)
extern "C" bool BunString__fromJS(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, BunString* bunString)
{
+
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
*bunString = Bun::toString(globalObject, value);
return bunString->tag != BunStringTag::Dead;
}
+extern "C" BunString BunString__createAtom(const char* bytes, size_t length)
+{
+ if (simdutf::validate_ascii(bytes, length)) {
+ auto atom = makeAtomString(String(StringImpl::createWithoutCopying(bytes, length)));
+ atom.impl()->ref();
+ return { BunStringTag::WTFStringImpl, { .wtf = atom.impl() } };
+ }
+
+ return { BunStringTag::Dead, {} };
+}
+
namespace Bun {
JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, BunString bunString)
{
@@ -83,6 +96,17 @@ BunString fromJS(JSC::JSGlobalObject* globalObject, JSValue value)
return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
}
+extern "C" void BunString__toThreadSafe(BunString* str)
+{
+ if (str->tag == BunStringTag::WTFStringImpl) {
+ auto impl = str->impl.wtf->isolatedCopy();
+ if (impl.ptr() != str->impl.wtf) {
+ impl->ref();
+ str->impl.wtf = &impl.leakRef();
+ }
+ }
+}
+
BunString toString(JSC::JSGlobalObject* globalObject, JSValue value)
{
return fromJS(globalObject, value);
@@ -179,7 +203,6 @@ extern "C" BunString BunString__fromUTF16Unitialized(size_t length)
if (UNLIKELY(!ptr))
return { BunStringTag::Dead };
- impl->ref();
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}
@@ -190,7 +213,6 @@ extern "C" BunString BunString__fromLatin1Unitialized(size_t length)
auto impl = WTF::StringImpl::createUninitialized(latin1Length, ptr);
if (UNLIKELY(!ptr))
return { BunStringTag::Dead };
- impl->ref();
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}
@@ -256,40 +278,28 @@ extern "C" EncodedJSValue BunString__createArray(
auto& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
- // We must do this or Bun.gc(true) in a loop creating large arrays of strings will crash due to GC'ing.
- MarkedArgumentBuffer arguments;
- JSC::ObjectInitializationScope scope(vm);
- GCDeferralContext context(vm);
-
- arguments.fill(length, [&](JSC::JSValue* value) {
- const BunString* end = ptr + length;
- while (ptr != end) {
- *value++ = Bun::toJS(globalObject, *ptr++);
- }
- });
-
- if (JSC::JSArray* array = JSC::JSArray::tryCreateUninitializedRestricted(
- scope,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
- length)) {
+ // Using tryCreateUninitialized here breaks stuff..
+ // https://github.com/oven-sh/bun/issues/3931
+ JSC::JSArray* array = constructEmptyArray(globalObject, nullptr, length);
+ if (!array) {
+ JSC::throwOutOfMemoryError(globalObject, throwScope);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(JSC::JSValue()));
+ }
- for (size_t i = 0; i < length; ++i) {
- array->initializeIndex(scope, i, arguments.at(i));
- }
- return JSValue::encode(array);
+ for (size_t i = 0; i < length; ++i) {
+ array->putDirectIndex(globalObject, i, Bun::toJS(globalObject, *ptr++));
}
- JSC::throwOutOfMemoryError(globalObject, throwScope);
- RELEASE_AND_RETURN(throwScope, JSValue::encode(JSC::JSValue()));
+ return JSValue::encode(array);
}
extern "C" void BunString__toWTFString(BunString* bunString)
{
if (bunString->tag == BunStringTag::ZigString) {
- if (Zig::isTaggedUTF8Ptr(bunString->impl.zig.ptr)) {
- bunString->impl.wtf = Zig::toStringCopy(bunString->impl.zig).impl();
- } else {
+ if (Zig::isTaggedExternalPtr(bunString->impl.zig.ptr)) {
bunString->impl.wtf = Zig::toString(bunString->impl.zig).impl();
+ } else {
+ bunString->impl.wtf = Zig::toStringCopy(bunString->impl.zig).impl();
}
bunString->tag = BunStringTag::WTFStringImpl;
@@ -299,6 +309,11 @@ extern "C" void BunString__toWTFString(BunString* bunString)
}
}
+extern "C" BunString URL__getFileURLString(BunString* filePath)
+{
+ return Bun::toStringRef(WTF::URL::fileURLWithFileSystemPath(Bun::toWTFString(*filePath)).stringWithoutFragmentIdentifier());
+}
+
extern "C" WTF::URL* URL__fromJS(EncodedJSValue encodedValue, JSC::JSGlobalObject* globalObject)
{
auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm());
@@ -335,7 +350,7 @@ extern "C" BunString URL__getHrefFromJS(EncodedJSValue encodedValue, JSC::JSGlob
extern "C" BunString URL__getHref(BunString* input)
{
- auto str = Bun::toWTFString(*input);
+ auto&& str = Bun::toWTFString(*input);
auto url = WTF::URL(str);
if (!url.isValid() || url.isEmpty())
return { BunStringTag::Dead };
@@ -345,7 +360,7 @@ extern "C" BunString URL__getHref(BunString* input)
extern "C" WTF::URL* URL__fromString(BunString* input)
{
- auto str = Bun::toWTFString(*input);
+ auto&& str = Bun::toWTFString(*input);
auto url = WTF::URL(str);
if (!url.isValid())
return nullptr;
diff --git a/src/bun.js/bindings/BunWorkerGlobalScope.cpp b/src/bun.js/bindings/BunWorkerGlobalScope.cpp
index 60b615e183e33d..ef1f70fdfeb026 100644
--- a/src/bun.js/bindings/BunWorkerGlobalScope.cpp
+++ b/src/bun.js/bindings/BunWorkerGlobalScope.cpp
@@ -1,10 +1,14 @@
#include "config.h"
#include "BunWorkerGlobalScope.h"
+#include "MessagePortChannelProviderImpl.h"
-namespace Bun {
-using namespace WebCore;
+namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(GlobalScope);
+MessagePortChannelProvider& GlobalScope::messagePortChannelProvider()
+{
+ return *reinterpret_cast(&MessagePortChannelProviderImpl::singleton());
+}
}
\ No newline at end of file
diff --git a/src/bun.js/bindings/BunWorkerGlobalScope.h b/src/bun.js/bindings/BunWorkerGlobalScope.h
index 7672897168195b..fff50d6ec6b1bb 100644
--- a/src/bun.js/bindings/BunWorkerGlobalScope.h
+++ b/src/bun.js/bindings/BunWorkerGlobalScope.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include "root.h"
#include "EventTarget.h"
@@ -7,8 +9,12 @@
#include
#include
-namespace Bun {
-class GlobalScope final : public RefCounted, public EventTargetWithInlineData {
+namespace WebCore {
+
+class MessagePortChannelProvider;
+class MessagePortChannelProviderImpl;
+
+class GlobalScope : public RefCounted, public EventTargetWithInlineData {
WTF_MAKE_ISO_ALLOCATED(GlobalScope);
public:
@@ -33,6 +39,11 @@ class GlobalScope final : public RefCounted, public EventTargetWith
void derefEventTarget() final { deref(); }
void eventListenersDidChange() final {}
+ MessagePortChannelProvider& messagePortChannelProvider();
+
ScriptExecutionContext* m_context;
+
+private:
+ MessagePortChannelProviderImpl* m_messagePortChannelProvider;
};
}
\ No newline at end of file
diff --git a/src/bun.js/bindings/CodeCoverage.cpp b/src/bun.js/bindings/CodeCoverage.cpp
new file mode 100644
index 00000000000000..1cb3b6ba20adcc
--- /dev/null
+++ b/src/bun.js/bindings/CodeCoverage.cpp
@@ -0,0 +1,44 @@
+#include "root.h"
+#include "ZigSourceProvider.h"
+#include
+
+using namespace JSC;
+
+extern "C" bool CodeCoverage__withBlocksAndFunctions(
+ JSC::VM* vmPtr,
+ JSC::SourceID sourceID,
+ void* ctx,
+ bool ignoreSourceMap,
+ void (*blockCallback)(void* ctx, JSC::BasicBlockRange* range, size_t len, size_t functionOffset, bool ignoreSourceMap))
+{
+
+ VM& vm = *vmPtr;
+
+ auto basicBlocks = vm.controlFlowProfiler()->getBasicBlocksForSourceIDWithoutFunctionRange(
+ sourceID, vm);
+
+ if (basicBlocks.isEmpty()) {
+ blockCallback(ctx, nullptr, 0, 0, ignoreSourceMap);
+ return true;
+ }
+
+ size_t functionStartOffset = basicBlocks.size();
+
+ const Vector>& functionRanges = vm.functionHasExecutedCache()->getFunctionRanges(sourceID);
+
+ basicBlocks.reserveCapacity(functionRanges.size() + basicBlocks.size());
+
+ for (const auto& functionRange : functionRanges) {
+ BasicBlockRange range;
+ range.m_hasExecuted = std::get<0>(functionRange);
+ range.m_startOffset = static_cast(std::get<1>(functionRange));
+ range.m_endOffset = static_cast(std::get<2>(functionRange));
+ range.m_executionCount = range.m_hasExecuted
+ ? 1
+ : 0; // This is a hack. We don't actually count this.
+ basicBlocks.append(range);
+ }
+
+ blockCallback(ctx, basicBlocks.data(), basicBlocks.size(), functionStartOffset, ignoreSourceMap);
+ return true;
+}
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp
index bcae04500393be..a1f5781d706dd9 100644
--- a/src/bun.js/bindings/CommonJSModuleRecord.cpp
+++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp
@@ -93,7 +93,7 @@ static bool canPerformFastEnumeration(Structure* s)
return true;
}
-static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSString* filename, WTF::NakedPtr& exception)
+static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSValue filename, WTF::NakedPtr& exception)
{
JSC::Structure* thisObjectStructure = globalObject->commonJSFunctionArgumentsStructure();
JSC::JSObject* thisObject = JSC::constructEmptyObject(
@@ -395,7 +395,7 @@ class JSCommonJSModulePrototype final : public JSC::JSNonFinalObject {
const JSC::ClassInfo JSCommonJSModulePrototype::s_info = { "Module"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModulePrototype) };
-void JSCommonJSModule::finishCreation(JSC::VM& vm, JSC::JSString* id, JSC::JSString* filename, JSC::JSString* dirname, JSC::JSSourceCode* sourceCode)
+void JSCommonJSModule::finishCreation(JSC::VM& vm, JSC::JSString* id, JSValue filename, JSC::JSString* dirname, JSC::JSSourceCode* sourceCode)
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
@@ -421,7 +421,7 @@ JSCommonJSModule* JSCommonJSModule::create(
JSC::VM& vm,
JSC::Structure* structure,
JSC::JSString* id,
- JSC::JSString* filename,
+ JSValue filename,
JSC::JSString* dirname,
JSC::JSSourceCode* sourceCode)
{
@@ -489,60 +489,10 @@ bool JSCommonJSModule::evaluate(
auto throwScope = DECLARE_THROW_SCOPE(vm);
generator(globalObject, JSC::Identifier::fromString(vm, key), propertyNames, arguments);
RETURN_IF_EXCEPTION(throwScope, false);
-
- bool needsPut = false;
- auto getDefaultValue = [&]() -> JSValue {
- size_t defaultValueIndex = propertyNames.find(vm.propertyNames->defaultKeyword);
- auto cjsSymbol = Identifier::fromUid(vm.symbolRegistry().symbolForKey("CommonJS"_s));
-
- if (defaultValueIndex != notFound && propertyNames.contains(cjsSymbol)) {
- JSValue current = arguments.at(defaultValueIndex);
- needsPut = true;
- return current;
- }
-
- size_t count = propertyNames.size();
- JSValue existingDefaultObject = this->getIfPropertyExists(globalObject, WebCore::clientData(vm)->builtinNames().exportsPublicName());
- JSObject* defaultObject;
-
- if (existingDefaultObject && existingDefaultObject.isObject()) {
- defaultObject = jsCast(existingDefaultObject);
- } else {
- defaultObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype());
- needsPut = true;
- }
-
- for (size_t i = 0; i < count; ++i) {
- auto prop = propertyNames[i];
- unsigned attributes = 0;
-
- JSValue value = arguments.at(i);
-
- if (prop.isSymbol()) {
- attributes |= JSC::PropertyAttribute::DontEnum;
- }
-
- if (value.isCell() && value.isCallable()) {
- attributes |= JSC::PropertyAttribute::Function;
- }
-
- defaultObject->putDirect(vm, prop, value, attributes);
- }
-
- return defaultObject;
- };
-
- JSValue defaultValue = getDefaultValue();
- if (needsPut) {
- unsigned attributes = 0;
-
- if (defaultValue.isCell() && defaultValue.isCallable()) {
- attributes |= JSC::PropertyAttribute::Function;
- }
-
- this->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), defaultValue, attributes);
- }
-
+ // This goes off of the assumption that you only call this `evaluate` using a generator that explicity
+ // assigns the `default` export first.
+ JSValue defaultValue = arguments.at(0);
+ this->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), defaultValue, 0);
this->hasEvaluated = true;
RELEASE_AND_RETURN(throwScope, true);
}
@@ -556,10 +506,6 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject,
auto& vm = globalObject->vm();
- // This exists to tell ImportMetaObject.ts that this is a CommonJS module.
- exportNames.append(Identifier::fromUid(vm.symbolRegistry().symbolForKey("CommonJS"_s)));
- exportValues.append(jsNumber(0));
-
// Bun's intepretation of the "__esModule" annotation:
//
// - If a "default" export does not exist OR the __esModule annotation is not present, then we
@@ -820,10 +766,11 @@ void RequireResolveFunctionPrototype::finishCreation(JSC::VM& vm)
bool JSCommonJSModule::evaluate(
Zig::GlobalObject* globalObject,
const WTF::String& key,
- ResolvedSource source)
+ ResolvedSource source,
+ bool isBuiltIn)
{
auto& vm = globalObject->vm();
- auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program);
+ auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn);
this->ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule;
JSC::SourceCode rawInputSource(
WTFMove(sourceProvider));
@@ -854,7 +801,8 @@ bool JSCommonJSModule::evaluate(
std::optional createCommonJSModule(
Zig::GlobalObject* globalObject,
- ResolvedSource source)
+ ResolvedSource source,
+ bool isBuiltIn)
{
JSCommonJSModule* moduleObject;
WTF::String sourceURL = toStringCopy(source.source_url);
@@ -862,7 +810,7 @@ std::optional createCommonJSModule(
JSValue specifierValue = Bun::toJS(globalObject, source.specifier);
JSValue entry = globalObject->requireMap()->get(globalObject, specifierValue);
- auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program);
+ auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn);
bool ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule;
SourceOrigin sourceOrigin = sourceProvider->sourceOrigin();
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.h b/src/bun.js/bindings/CommonJSModuleRecord.h
index 20941f45418bf3..e38d2e083aaa34 100644
--- a/src/bun.js/bindings/CommonJSModuleRecord.h
+++ b/src/bun.js/bindings/CommonJSModuleRecord.h
@@ -1,3 +1,4 @@
+#pragma once
#include "root.h"
#include "headers-handwritten.h"
@@ -22,7 +23,7 @@ class JSCommonJSModule final : public JSC::JSDestructibleObject {
static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut;
mutable JSC::WriteBarrier m_id;
- mutable JSC::WriteBarrier m_filename;
+ mutable JSC::WriteBarrier m_filename;
mutable JSC::WriteBarrier m_dirname;
mutable JSC::WriteBarrier m_paths;
mutable JSC::WriteBarrier sourceCode;
@@ -32,18 +33,22 @@ class JSCommonJSModule final : public JSC::JSDestructibleObject {
~JSCommonJSModule();
void finishCreation(JSC::VM& vm,
- JSC::JSString* id, JSC::JSString* filename,
+ JSC::JSString* id, JSValue filename,
JSC::JSString* dirname, JSC::JSSourceCode* sourceCode);
static JSC::Structure* createStructure(JSC::JSGlobalObject* globalObject);
- bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource resolvedSource);
+ bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource resolvedSource, bool isBuiltIn);
+ inline bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& sourceURL, ResolvedSource resolvedSource)
+ {
+ return evaluate(globalObject, sourceURL, resolvedSource, false);
+ }
bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& key, const SyntheticSourceProvider::SyntheticSourceGenerator& generator);
bool evaluate(Zig::GlobalObject* globalObject, const WTF::String& key, JSSourceCode* sourceCode);
static JSCommonJSModule* create(JSC::VM& vm, JSC::Structure* structure,
JSC::JSString* id,
- JSC::JSString* filename,
+ JSValue filename,
JSC::JSString* dirname, JSC::JSSourceCode* sourceCode);
static JSCommonJSModule* create(
@@ -96,7 +101,15 @@ JSC::Structure* createCommonJSModuleStructure(
std::optional createCommonJSModule(
Zig::GlobalObject* globalObject,
- ResolvedSource source);
+ ResolvedSource source,
+ bool isBuiltIn);
+
+inline std::optional createCommonJSModule(
+ Zig::GlobalObject* globalObject,
+ ResolvedSource source)
+{
+ return createCommonJSModule(globalObject, source, false);
+}
class RequireResolveFunctionPrototype final : public JSC::JSNonFinalObject {
public:
diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp
new file mode 100644
index 00000000000000..8413605020b7d8
--- /dev/null
+++ b/src/bun.js/bindings/InternalModuleRegistry.cpp
@@ -0,0 +1,161 @@
+#include "InternalModuleRegistry.h"
+
+#include "ZigGlobalObject.h"
+#include "JavaScriptCore/BuiltinUtils.h"
+#include "JavaScriptCore/JSFunction.h"
+#include "JavaScriptCore/LazyProperty.h"
+#include "JavaScriptCore/LazyPropertyInlines.h"
+#include "JavaScriptCore/VMTrapsInlines.h"
+#include "JavaScriptCore/JSModuleLoader.h"
+
+#include "InternalModuleRegistryConstants.h"
+
+namespace Bun {
+
+extern "C" bool BunTest__shouldGenerateCodeCoverage(BunString sourceURL);
+extern "C" void ByteRangeMapping__generate(BunString sourceURL, BunString code, int sourceID);
+
+static void maybeAddCodeCoverage(JSC::VM& vm, const JSC::SourceCode& code)
+{
+#ifdef BUN_DEBUG
+ bool isCodeCoverageEnabled = !!vm.controlFlowProfiler();
+ bool shouldGenerateCodeCoverage = isCodeCoverageEnabled && BunTest__shouldGenerateCodeCoverage(Bun::toString(code.provider()->sourceURL()));
+ if (shouldGenerateCodeCoverage) {
+ ByteRangeMapping__generate(Bun::toString(code.provider()->sourceURL()), Bun::toString(code.provider()->source().toStringWithoutCopying()), code.provider()->asID());
+ }
+#endif
+}
+
+// The `INTERNAL_MODULE_REGISTRY_GENERATE` macro handles inlining code to compile and run a
+// JS builtin that acts as a module. In debug mode, we use a different implementation that reads
+// from the developer's filesystem. This allows reloading code without recompiling bindings.
+
+#define INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, SOURCE, moduleName) \
+ auto throwScope = DECLARE_THROW_SCOPE(vm); \
+ auto&& origin = SourceOrigin(WTF::URL(makeString("builtin://"_s, moduleName))); \
+ SourceCode source = JSC::makeSource(SOURCE, origin, moduleName); \
+ maybeAddCodeCoverage(vm, source); \
+ JSFunction* func \
+ = JSFunction::create( \
+ vm, \
+ createBuiltinExecutable( \
+ vm, source, \
+ Identifier(), \
+ ImplementationVisibility::Public, \
+ ConstructorKind::None, \
+ ConstructAbility::CannotConstruct) \
+ ->link(vm, nullptr, source), \
+ static_cast(globalObject)); \
+ \
+ RETURN_IF_EXCEPTION(throwScope, {}); \
+ \
+ JSC::MarkedArgumentBuffer argList; \
+ JSValue result = JSC::call( \
+ globalObject, \
+ func, \
+ JSC::getCallData(func), \
+ globalObject, JSC::MarkedArgumentBuffer()); \
+ \
+ RETURN_IF_EXCEPTION(throwScope, {}); \
+ ASSERT_INTERNAL_MODULE(result, moduleName); \
+ return result;
+
+#if BUN_DEBUG
+#include "../../src/js/out/DebugPath.h"
+#define ASSERT_INTERNAL_MODULE(result, moduleName) \
+ if (!result || !result.isCell() || !jsDynamicCast(result)) { \
+ printf("Expected \"%s\" to export a JSObject. Bun is going to crash.", moduleName.utf8().data()); \
+ }
+JSValue initializeInternalModuleFromDisk(
+ JSGlobalObject* globalObject,
+ VM& vm,
+ WTF::String moduleName,
+ WTF::String fileBase,
+ WTF::String fallback)
+{
+ WTF::String file = makeString(BUN_DYNAMIC_JS_LOAD_PATH, "modules_dev/"_s, fileBase);
+ if (auto contents = WTF::FileSystemImpl::readEntireFile(file)) {
+ auto string = WTF::String::fromUTF8(contents.value());
+ INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, string, moduleName);
+ } else {
+ printf("bun-debug failed to load bundled version of \"%s\" at \"%s\" (was it deleted?)\n"
+ "Please run `make js` to rebundle these builtins.\n",
+ moduleName.utf8().data(), file.utf8().data());
+ // Fallback to embedded source
+ INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, fallback, moduleName);
+ }
+}
+#define INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, moduleId, filename, SOURCE) \
+ return initializeInternalModuleFromDisk(globalObject, vm, moduleId, filename, SOURCE)
+#else
+
+#define ASSERT_INTERNAL_MODULE(result, moduleName) \
+ { \
+ }
+#define INTERNAL_MODULE_REGISTRY_GENERATE(globalObject, vm, moduleId, filename, SOURCE) \
+ INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, SOURCE, moduleId)
+#endif
+
+const ClassInfo InternalModuleRegistry::s_info = { "InternalModuleRegistry"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(InternalModuleRegistry) };
+
+InternalModuleRegistry::InternalModuleRegistry(VM& vm, Structure* structure)
+ : Base(vm, structure)
+{
+}
+
+template
+void InternalModuleRegistry::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+}
+
+DEFINE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE, InternalModuleRegistry);
+
+InternalModuleRegistry* InternalModuleRegistry::create(VM& vm, Structure* structure)
+{
+ InternalModuleRegistry* registry = new (NotNull, allocateCell(vm)) InternalModuleRegistry(vm, structure);
+ for (uint8_t i = 0; i < BUN_INTERNAL_MODULE_COUNT; i++) {
+ registry->internalField(static_cast(i))
+ .set(vm, registry, jsUndefined());
+ }
+ return registry;
+}
+
+Structure* InternalModuleRegistry::createStructure(VM& vm, JSGlobalObject* globalObject)
+{
+ return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 48);
+}
+
+JSValue InternalModuleRegistry::requireId(JSGlobalObject* globalObject, VM& vm, Field id)
+{
+ auto value = internalField(id).get();
+ if (!value || value.isUndefined()) {
+ value = createInternalModuleById(globalObject, vm, id);
+ internalField(id).set(vm, this, value);
+ }
+ return value;
+}
+
+#include "../../../src/js/out/InternalModuleRegistry+createInternalModuleById.h"
+
+// This is called like @getInternalField(@internalModuleRegistry, 1) ?? @createInternalModuleById(1)
+// so we want to write it to the internal field when loaded.
+JSC_DEFINE_HOST_FUNCTION(InternalModuleRegistry::jsCreateInternalModuleById, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto id = callframe->argument(0).toUInt32(lexicalGlobalObject);
+
+ auto registry = static_cast(lexicalGlobalObject)->internalModuleRegistry();
+ auto mod = registry->createInternalModuleById(lexicalGlobalObject, vm, static_cast(id));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ registry->internalField(static_cast(id)).set(vm, registry, mod);
+ return JSValue::encode(mod);
+}
+
+} // namespace Bun
+
+#undef INTERNAL_MODULE_REGISTRY_GENERATE_
+#undef INTERNAL_MODULE_REGISTRY_GENERATE
diff --git a/src/bun.js/bindings/InternalModuleRegistry.h b/src/bun.js/bindings/InternalModuleRegistry.h
new file mode 100644
index 00000000000000..d14625e00eee2b
--- /dev/null
+++ b/src/bun.js/bindings/InternalModuleRegistry.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "root.h"
+#include "JavaScriptCore/JSInternalFieldObjectImpl.h"
+#include "JavaScriptCore/JSInternalFieldObjectImplInlines.h"
+#include "BunClientData.h"
+#include "../../../src/js/out/InternalModuleRegistry+numberOfModules.h"
+
+namespace Bun {
+using namespace JSC;
+
+// Internal module registry is an array of lazily initialized "modules". Module IDs are generated
+// pre-build by `make js` and inlined into JS code and the C++ enum (InternalModuleRegistry::Field)
+// This allows modules depending on each other to skip the module resolver.
+//
+// Modules come from two sources:
+// - 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 {
+protected:
+ JS_EXPORT_PRIVATE InternalModuleRegistry(VM&, Structure*);
+ DECLARE_DEFAULT_FINISH_CREATION;
+ DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE);
+
+public:
+ using Base = JSInternalFieldObjectImpl;
+
+ DECLARE_EXPORT_INFO;
+
+ enum Field : uint8_t {
+#include "../../../src/js/out/InternalModuleRegistry+enum.h"
+ };
+ const WriteBarrier& internalField(Field field) const { return Base::internalField(static_cast(field)); }
+ WriteBarrier& internalField(Field field) { return Base::internalField(static_cast(field)); }
+
+ template
+ static GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForInternalModuleRegistry.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForInternalModuleRegistry = std::forward(space); },
+ [](auto& spaces) { return spaces.m_subspaceForInternalModuleRegistry.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForInternalModuleRegistry = std::forward(space); });
+ }
+
+ static InternalModuleRegistry* create(VM& vm, Structure* structure);
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
+
+ JSValue requireId(JSGlobalObject* globalObject, VM& vm, Field id);
+
+ static JSC_DECLARE_HOST_FUNCTION(jsCreateInternalModuleById);
+
+protected:
+ JSValue createInternalModuleById(JSGlobalObject* globalObject, VM& vm, Field id);
+};
+
+} // namespace Bun
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp
index e420e24ef12ab6..26047aa3daac77 100644
--- a/src/bun.js/bindings/JSBuffer.cpp
+++ b/src/bun.js/bindings/JSBuffer.cpp
@@ -949,7 +949,8 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlob
}
targetStart = std::min(targetStart, targetEnd);
- sourceStart = std::min(sourceStart, std::min(sourceEnd, sourceEndInit));
+ sourceEnd = std::min(sourceEnd, sourceEndInit);
+ sourceStart = std::min(sourceStart, sourceEnd);
auto sourceLength = sourceEnd - sourceStart;
auto targetLength = targetEnd - targetStart;
diff --git a/src/bun.js/bindings/JSCTaskScheduler.cpp b/src/bun.js/bindings/JSCTaskScheduler.cpp
index 436be4c0aaea9c..b97b2e9d260788 100644
--- a/src/bun.js/bindings/JSCTaskScheduler.cpp
+++ b/src/bun.js/bindings/JSCTaskScheduler.cpp
@@ -24,9 +24,11 @@ class JSCDeferredWorkTask {
Ticket ticket;
Task task;
- WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_ISO_ALLOCATED(JSCDeferredWorkTask);
};
+WTF_MAKE_ISO_ALLOCATED_IMPL(JSCDeferredWorkTask);
+
static JSC::VM& getVM(Ticket ticket)
{
return ticket->scriptExecutionOwner.get()->vm();
diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp
index 4a9b936b40aada..a8bac7c56c2ffa 100644
--- a/src/bun.js/bindings/JSMockFunction.cpp
+++ b/src/bun.js/bindings/JSMockFunction.cpp
@@ -1435,19 +1435,3 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject
return JSC::JSValue::encode(jsUndefined());
}
} // namespace Bun
-
-namespace JSC {
-
-template
-template
-void JSInternalFieldObjectImpl::visitChildrenImpl(JSCell* cell, Visitor& visitor)
-{
- auto* thisObject = jsCast(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- Base::visitChildren(thisObject, visitor);
- visitor.appendValues(thisObject->m_internalFields, numberOfInternalFields);
-}
-
-DEFINE_VISIT_CHILDREN_WITH_MODIFIER(template, JSInternalFieldObjectImpl);
-
-} // namespace JSC
diff --git a/src/bun.js/bindings/JSSink+custom.h b/src/bun.js/bindings/JSSink+custom.h
deleted file mode 100644
index 8b137891791fe9..00000000000000
--- a/src/bun.js/bindings/JSSink+custom.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp
index ac5ca0b91a7270..2c8b956123b70f 100644
--- a/src/bun.js/bindings/ModuleLoader.cpp
+++ b/src/bun.js/bindings/ModuleLoader.cpp
@@ -27,15 +27,6 @@
#include "EventEmitter.h"
#include "JSEventEmitter.h"
-#include "../modules/BufferModule.h"
-#include "../modules/EventsModule.h"
-#include "../modules/ProcessModule.h"
-#include "../modules/StringDecoderModule.h"
-#include "../modules/ObjectModule.h"
-#include "../modules/NodeModuleModule.h"
-#include "../modules/TTYModule.h"
-#include "../modules/ConstantsModule.h"
-#include "node_util_types.h"
#include "CommonJSModuleRecord.h"
#include
#include
@@ -43,7 +34,13 @@
#include
#include
+#include "../modules/_NativeModule.h"
+#include "../../js/out/NativeModuleImpl.h"
+
+#include "../modules/ObjectModule.h"
+
namespace Bun {
+using namespace JSC;
using namespace Zig;
using namespace WebCore;
@@ -67,14 +64,52 @@ static JSC::JSInternalPromise* resolvedInternalPromise(JSC::JSGlobalObject* glob
return promise;
}
-using namespace JSC;
+// Converts an object from InternalModuleRegistry into { ...obj, default: obj }
+static JSC::SyntheticSourceProvider::SyntheticSourceGenerator
+generateInternalModuleSourceCode(JSC::JSGlobalObject* globalObject, InternalModuleRegistry::Field moduleId)
+{
+ return [moduleId](JSC::JSGlobalObject* lexicalGlobalObject,
+ JSC::Identifier moduleKey,
+ Vector& exportNames,
+ JSC::MarkedArgumentBuffer& exportValues) -> void {
+ JSC::VM& vm = lexicalGlobalObject->vm();
+ GlobalObject* globalObject = jsCast(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ auto* object = jsCast(globalObject->internalModuleRegistry()->requireId(globalObject, vm, moduleId));
+ if (!object) {
+ return;
+ }
+ RETURN_IF_EXCEPTION(throwScope, {});
+
+ JSC::EnsureStillAliveScope stillAlive(object);
+
+ PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+ object->getPropertyNames(globalObject, properties, DontEnumPropertiesMode::Exclude);
+
+ RETURN_IF_EXCEPTION(throwScope, {});
+
+ auto len = properties.size() + 1;
+ exportNames.reserveCapacity(len);
+ exportValues.ensureCapacity(len);
+
+ exportNames.append(vm.propertyNames->defaultKeyword);
+ exportValues.append(object);
+
+ for (auto& entry : properties) {
+ exportNames.append(entry);
+ exportValues.append(object->get(globalObject, entry));
+ }
+ };
+}
static OnLoadResult handleOnLoadObjectResult(Zig::GlobalObject* globalObject, JSC::JSObject* object)
{
OnLoadResult result {};
result.type = OnLoadResultTypeObject;
JSC::VM& vm = globalObject->vm();
- if (JSC::JSValue exportsValue = object->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "exports"_s))) {
+ auto& builtinNames = WebCore::builtinNames(vm);
+ if (JSC::JSValue exportsValue = object->getIfPropertyExists(globalObject, builtinNames.exportsPublicName())) {
if (exportsValue.isObject()) {
result.value.object = exportsValue;
return result;
@@ -352,6 +387,18 @@ extern "C" void Bun__onFulfillAsyncModule(
return promise->reject(promise->globalObject(), exception);
}
+ if (res->result.value.commonJSExportsLen) {
+ auto created = Bun::createCommonJSModule(jsCast(globalObject), res->result.value);
+
+ if (created.has_value()) {
+ return promise->resolve(promise->globalObject(), JSSourceCode::create(vm, WTFMove(created.value())));
+ } else {
+ auto* exception = scope.exception();
+ scope.clearException();
+ return promise->reject(promise->globalObject(), exception);
+ }
+ }
+
auto provider = Zig::SourceProvider::create(jsDynamicCast(globalObject), res->result.value);
promise->resolve(promise->globalObject(), JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
}
@@ -377,45 +424,37 @@ JSValue fetchCommonJSModule(
return JSValue();
}
- switch (res->result.value.tag) {
- case SyntheticModuleType::Module: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateNodeModuleModule);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
+ auto tag = res->result.value.tag;
+ switch (tag) {
+// Generated native module cases
+#define CASE(str, name) \
+ case SyntheticModuleType::name: { \
+ target->evaluate(globalObject, Bun::toWTFString(*specifier), generateNativeModule_##name); \
+ RETURN_IF_EXCEPTION(scope, {}); \
+ RELEASE_AND_RETURN(scope, target); \
+ }
+ BUN_FOREACH_NATIVE_MODULE(CASE)
+#undef CASE
- case SyntheticModuleType::Buffer: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateBufferSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
- case SyntheticModuleType::TTY: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateTTYSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
- case SyntheticModuleType::NodeUtilTypes: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), Bun::generateNodeUtilTypesSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
- case SyntheticModuleType::Process: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateProcessSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
- case SyntheticModuleType::Events: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateEventsSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
- }
- case SyntheticModuleType::StringDecoder: {
- target->evaluate(globalObject, Bun::toWTFString(*specifier), generateStringDecoderSourceCode);
- RETURN_IF_EXCEPTION(scope, {});
- RELEASE_AND_RETURN(scope, target);
+ case SyntheticModuleType::ESM: {
+ RELEASE_AND_RETURN(scope, jsNumber(-1));
}
+
default: {
- RELEASE_AND_RETURN(scope, jsNumber(-1));
+ if (tag & SyntheticModuleType::InternalModuleRegistryFlag) {
+ constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1);
+ auto result = globalObject->internalModuleRegistry()->requireId(globalObject, vm, static_cast(tag & mask));
+ RETURN_IF_EXCEPTION(scope, {});
+
+ target->putDirect(
+ vm,
+ builtinNames.exportsPublicName(),
+ result,
+ JSC::PropertyAttribute::ReadOnly | 0);
+ RELEASE_AND_RETURN(scope, target);
+ } else {
+ RELEASE_AND_RETURN(scope, jsNumber(-1));
+ }
}
}
}
@@ -484,7 +523,7 @@ JSValue fetchCommonJSModule(
}
template
-static JSValue fetchSourceCode(
+static JSValue fetchESMSourceCode(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
BunString* specifier,
@@ -543,67 +582,31 @@ static JSValue fetchSourceCode(
auto moduleKey = Bun::toWTFString(*specifier);
- switch (res->result.value.tag) {
- case SyntheticModuleType::Module: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateNodeModuleModule,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
-
- case SyntheticModuleType::Buffer: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateBufferSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
- case SyntheticModuleType::TTY: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateTTYSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
- case SyntheticModuleType::NodeUtilTypes: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(Bun::generateNodeUtilTypesSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
- case SyntheticModuleType::Process: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateProcessSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
- case SyntheticModuleType::Events: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateEventsSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ auto tag = res->result.value.tag;
+ switch (tag) {
+ case SyntheticModuleType::ESM: {
+ auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true);
+ return rejectOrResolve(JSSourceCode::create(vm, JSC::SourceCode(provider)));
}
- case SyntheticModuleType::StringDecoder: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateStringDecoderSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
- case SyntheticModuleType::Constants: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateConstantsSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
+#define CASE(str, name) \
+ case (SyntheticModuleType::name): { \
+ auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateNativeModule_##name, JSC::SourceOrigin(), WTFMove(moduleKey))); \
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); \
+ }
+ BUN_FOREACH_NATIVE_MODULE(CASE)
+#undef CASE
- return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
- }
+ // CommonJS modules from src/js/*
default: {
- auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true);
- return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
+ if (tag & SyntheticModuleType::InternalModuleRegistryFlag) {
+ constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1);
+ auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://", moduleKey))), moduleKey));
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ } else {
+ auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true);
+ return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
+ }
}
}
}
@@ -703,36 +706,21 @@ extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalO
return JSValue::encode(reason);
}
-JSValue fetchSourceCodeSync(
+JSValue fetchESMSourceCodeSync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
BunString* specifier,
BunString* referrer)
{
- return fetchSourceCode(globalObject, res, specifier, referrer);
+ return fetchESMSourceCode(globalObject, res, specifier, referrer);
}
-JSValue fetchSourceCodeAsync(
+JSValue fetchESMSourceCodeAsync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
BunString* specifier,
BunString* referrer)
{
- return fetchSourceCode(globalObject, res, specifier, referrer);
+ return fetchESMSourceCode(globalObject, res, specifier, referrer);
}
}
-namespace JSC {
-
-template
-template
-void JSInternalFieldObjectImpl::visitChildrenImpl(JSCell* cell, Visitor& visitor)
-{
- auto* thisObject = jsCast(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- Base::visitChildren(thisObject, visitor);
- visitor.appendValues(thisObject->m_internalFields, numberOfInternalFields);
-}
-
-DEFINE_VISIT_CHILDREN_WITH_MODIFIER(template, JSInternalFieldObjectImpl);
-
-} // namespace JSC
diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h
index 6eb04bf409f344..ee726ebcfe9614 100644
--- a/src/bun.js/bindings/ModuleLoader.h
+++ b/src/bun.js/bindings/ModuleLoader.h
@@ -81,13 +81,13 @@ class PendingVirtualModuleResult : public JSC::JSInternalFieldObjectImpl<3> {
};
OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue);
-JSValue fetchSourceCodeSync(
+JSValue fetchESMSourceCodeSync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
BunString* specifier,
BunString* referrer);
-JSValue fetchSourceCodeAsync(
+JSValue fetchESMSourceCodeAsync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
BunString* specifier,
@@ -100,4 +100,4 @@ JSValue fetchCommonJSModule(
BunString* specifier,
BunString* referrer);
-} // namespace Bun
\ No newline at end of file
+} // namespace Bun
diff --git a/src/bun.js/bindings/Process.cpp b/src/bun.js/bindings/Process.cpp
index 78f473ec2042df..9a09eca66e33e1 100644
--- a/src/bun.js/bindings/Process.cpp
+++ b/src/bun.js/bindings/Process.cpp
@@ -397,7 +397,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionExit,
Process__dispatchOnExit(zigGlobal, exitCode);
Bun__Process__exit(zigGlobal, exitCode);
- __builtin_unreachable();
+ return JSC::JSValue::encode(jsUndefined());
}
extern "C" uint64_t Bun__readOriginTimer(void*);
@@ -882,7 +882,10 @@ static JSValue constructProcessReleaseObject(VM& vm, JSObject* processObject)
{
auto* globalObject = processObject->globalObject();
auto* release = JSC::constructEmptyObject(globalObject);
- release->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, WTF::String("bun"_s)), 0);
+
+ // SvelteKit compatibility hack
+ release->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, WTF::String("node"_s)), 0);
+
release->putDirect(vm, Identifier::fromString(vm, "lts"_s), jsBoolean(false), 0);
release->putDirect(vm, Identifier::fromString(vm, "sourceUrl"_s), jsString(vm, WTF::String(Bun__githubURL, strlen(Bun__githubURL))), 0);
release->putDirect(vm, Identifier::fromString(vm, "headersUrl"_s), jsEmptyString(vm), 0);
@@ -1153,7 +1156,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionReallyExit, (JSGlobalObject * globalObj
zigGlobal = Bun__getDefaultGlobal();
}
Bun__Process__exit(zigGlobal, exitCode);
- __builtin_unreachable();
+ return JSC::JSValue::encode(jsUndefined());
}
template
@@ -1313,7 +1316,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage,
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(result));
}
-static int getRSS(size_t* rss)
+int getRSS(size_t* rss)
{
#if defined(__APPLE__)
mach_msg_type_number_t count;
diff --git a/src/bun.js/bindings/Process.h b/src/bun.js/bindings/Process.h
index 0ee6f424381b3d..ab344c7fe4231a 100644
--- a/src/bun.js/bindings/Process.h
+++ b/src/bun.js/bindings/Process.h
@@ -8,6 +8,9 @@
namespace Zig {
+// TODO: find a better place for this
+int getRSS(size_t* rss);
+
using namespace JSC;
class Process : public WebCore::JSEventEmitter {
diff --git a/src/bun.js/bindings/ProcessBindingConstants.cpp b/src/bun.js/bindings/ProcessBindingConstants.cpp
new file mode 100644
index 00000000000000..36a4a7f9654abf
--- /dev/null
+++ b/src/bun.js/bindings/ProcessBindingConstants.cpp
@@ -0,0 +1,1124 @@
+// Modelled off of https://github.com/nodejs/node/blob/main/src/node_constants.cc
+// Note that if you change any of this code, you probably also have to change NodeConstantsModule.h
+#include "ProcessBindingConstants.h"
+#include "JavaScriptCore/ObjectConstructor.h"
+
+// These headers may not all be needed, but they are the ones node references.
+// Most of the constants are defined with #if checks on existing #defines, instead of platform-checks
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef OPENSSL_NO_ENGINE
+#include
+#endif
+
+#if !defined(_MSC_VER)
+#include
+#endif
+
+#if defined(_WIN32)
+#include // _S_IREAD _S_IWRITE
+#ifndef S_IRUSR
+#define S_IRUSR _S_IREAD
+#endif // S_IRUSR
+#ifndef S_IWUSR
+#define S_IWUSR _S_IWRITE
+#endif // S_IWUSR
+#else
+#include
+#endif
+
+namespace Bun {
+using namespace JSC;
+
+static JSValue processBindingConstantsGetOs(VM& vm, JSObject* bindingObject)
+{
+ auto globalObject = bindingObject->globalObject();
+ auto osObj = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ auto dlopenObj = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ auto errnoObj = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ auto signalsObj = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ auto priorityObj = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
+ osObj->putDirect(vm, Identifier::fromString(vm, "UV_UDP_REUSEADDR"_s), jsNumber(4));
+ osObj->putDirect(vm, Identifier::fromString(vm, "dlopen"_s), dlopenObj);
+ osObj->putDirect(vm, Identifier::fromString(vm, "errno"_s), errnoObj);
+ osObj->putDirect(vm, Identifier::fromString(vm, "signals"_s), signalsObj);
+ osObj->putDirect(vm, Identifier::fromString(vm, "priority"_s), priorityObj);
+#ifdef E2BIG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "E2BIG"_s), jsNumber(E2BIG));
+#endif
+#ifdef EACCES
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EACCES"_s), jsNumber(EACCES));
+#endif
+#ifdef EADDRINUSE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EADDRINUSE"_s), jsNumber(EADDRINUSE));
+#endif
+#ifdef EADDRNOTAVAIL
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EADDRNOTAVAIL"_s), jsNumber(EADDRNOTAVAIL));
+#endif
+#ifdef EAFNOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EAFNOSUPPORT"_s), jsNumber(EAFNOSUPPORT));
+#endif
+#ifdef EAGAIN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EAGAIN"_s), jsNumber(EAGAIN));
+#endif
+#ifdef EALREADY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EALREADY"_s), jsNumber(EALREADY));
+#endif
+#ifdef EBADF
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EBADF"_s), jsNumber(EBADF));
+#endif
+#ifdef EBADMSG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EBADMSG"_s), jsNumber(EBADMSG));
+#endif
+#ifdef EBUSY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EBUSY"_s), jsNumber(EBUSY));
+#endif
+#ifdef ECANCELED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ECANCELED"_s), jsNumber(ECANCELED));
+#endif
+#ifdef ECHILD
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ECHILD"_s), jsNumber(ECHILD));
+#endif
+#ifdef ECONNABORTED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ECONNABORTED"_s), jsNumber(ECONNABORTED));
+#endif
+#ifdef ECONNREFUSED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ECONNREFUSED"_s), jsNumber(ECONNREFUSED));
+#endif
+#ifdef ECONNRESET
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ECONNRESET"_s), jsNumber(ECONNRESET));
+#endif
+#ifdef EDEADLK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EDEADLK"_s), jsNumber(EDEADLK));
+#endif
+#ifdef EDESTADDRREQ
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EDESTADDRREQ"_s), jsNumber(EDESTADDRREQ));
+#endif
+#ifdef EDOM
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EDOM"_s), jsNumber(EDOM));
+#endif
+#ifdef EDQUOT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EDQUOT"_s), jsNumber(EDQUOT));
+#endif
+#ifdef EEXIST
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EEXIST"_s), jsNumber(EEXIST));
+#endif
+#ifdef EFAULT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EFAULT"_s), jsNumber(EFAULT));
+#endif
+#ifdef EFBIG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EFBIG"_s), jsNumber(EFBIG));
+#endif
+#ifdef EHOSTUNREACH
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EHOSTUNREACH"_s), jsNumber(EHOSTUNREACH));
+#endif
+#ifdef EIDRM
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EIDRM"_s), jsNumber(EIDRM));
+#endif
+#ifdef EILSEQ
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EILSEQ"_s), jsNumber(EILSEQ));
+#endif
+#ifdef EINPROGRESS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EINPROGRESS"_s), jsNumber(EINPROGRESS));
+#endif
+#ifdef EINTR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EINTR"_s), jsNumber(EINTR));
+#endif
+#ifdef EINVAL
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EINVAL"_s), jsNumber(EINVAL));
+#endif
+#ifdef EIO
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EIO"_s), jsNumber(EIO));
+#endif
+#ifdef EISCONN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EISCONN"_s), jsNumber(EISCONN));
+#endif
+#ifdef EISDIR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EISDIR"_s), jsNumber(EISDIR));
+#endif
+#ifdef ELOOP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ELOOP"_s), jsNumber(ELOOP));
+#endif
+#ifdef EMFILE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EMFILE"_s), jsNumber(EMFILE));
+#endif
+#ifdef EMLINK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EMLINK"_s), jsNumber(EMLINK));
+#endif
+#ifdef EMSGSIZE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EMSGSIZE"_s), jsNumber(EMSGSIZE));
+#endif
+#ifdef EMULTIHOP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EMULTIHOP"_s), jsNumber(EMULTIHOP));
+#endif
+#ifdef ENAMETOOLONG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENAMETOOLONG"_s), jsNumber(ENAMETOOLONG));
+#endif
+#ifdef ENETDOWN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENETDOWN"_s), jsNumber(ENETDOWN));
+#endif
+#ifdef ENETRESET
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENETRESET"_s), jsNumber(ENETRESET));
+#endif
+#ifdef ENETUNREACH
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENETUNREACH"_s), jsNumber(ENETUNREACH));
+#endif
+#ifdef ENFILE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENFILE"_s), jsNumber(ENFILE));
+#endif
+#ifdef ENOBUFS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOBUFS"_s), jsNumber(ENOBUFS));
+#endif
+#ifdef ENODATA
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENODATA"_s), jsNumber(ENODATA));
+#endif
+#ifdef ENODEV
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENODEV"_s), jsNumber(ENODEV));
+#endif
+#ifdef ENOENT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOENT"_s), jsNumber(ENOENT));
+#endif
+#ifdef ENOEXEC
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOEXEC"_s), jsNumber(ENOEXEC));
+#endif
+#ifdef ENOLCK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOLCK"_s), jsNumber(ENOLCK));
+#endif
+#ifdef ENOLINK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOLINK"_s), jsNumber(ENOLINK));
+#endif
+#ifdef ENOMEM
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOMEM"_s), jsNumber(ENOMEM));
+#endif
+#ifdef ENOMSG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOMSG"_s), jsNumber(ENOMSG));
+#endif
+#ifdef ENOPROTOOPT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOPROTOOPT"_s), jsNumber(ENOPROTOOPT));
+#endif
+#ifdef ENOSPC
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOSPC"_s), jsNumber(ENOSPC));
+#endif
+#ifdef ENOSR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOSR"_s), jsNumber(ENOSR));
+#endif
+#ifdef ENOSTR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOSTR"_s), jsNumber(ENOSTR));
+#endif
+#ifdef ENOSYS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOSYS"_s), jsNumber(ENOSYS));
+#endif
+#ifdef ENOTCONN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTCONN"_s), jsNumber(ENOTCONN));
+#endif
+#ifdef ENOTDIR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTDIR"_s), jsNumber(ENOTDIR));
+#endif
+#ifdef ENOTEMPTY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTEMPTY"_s), jsNumber(ENOTEMPTY));
+#endif
+#ifdef ENOTSOCK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTSOCK"_s), jsNumber(ENOTSOCK));
+#endif
+#ifdef ENOTSUP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTSUP"_s), jsNumber(ENOTSUP));
+#endif
+#ifdef ENOTTY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENOTTY"_s), jsNumber(ENOTTY));
+#endif
+#ifdef ENXIO
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ENXIO"_s), jsNumber(ENXIO));
+#endif
+#ifdef EOPNOTSUPP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EOPNOTSUPP"_s), jsNumber(EOPNOTSUPP));
+#endif
+#ifdef EOVERFLOW
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EOVERFLOW"_s), jsNumber(EOVERFLOW));
+#endif
+#ifdef EPERM
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EPERM"_s), jsNumber(EPERM));
+#endif
+#ifdef EPIPE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EPIPE"_s), jsNumber(EPIPE));
+#endif
+#ifdef EPROTO
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EPROTO"_s), jsNumber(EPROTO));
+#endif
+#ifdef EPROTONOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EPROTONOSUPPORT"_s), jsNumber(EPROTONOSUPPORT));
+#endif
+#ifdef EPROTOTYPE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EPROTOTYPE"_s), jsNumber(EPROTOTYPE));
+#endif
+#ifdef ERANGE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ERANGE"_s), jsNumber(ERANGE));
+#endif
+#ifdef EROFS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EROFS"_s), jsNumber(EROFS));
+#endif
+#ifdef ESPIPE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ESPIPE"_s), jsNumber(ESPIPE));
+#endif
+#ifdef ESRCH
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ESRCH"_s), jsNumber(ESRCH));
+#endif
+#ifdef ESTALE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ESTALE"_s), jsNumber(ESTALE));
+#endif
+#ifdef ETIME
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ETIME"_s), jsNumber(ETIME));
+#endif
+#ifdef ETIMEDOUT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ETIMEDOUT"_s), jsNumber(ETIMEDOUT));
+#endif
+#ifdef ETXTBSY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "ETXTBSY"_s), jsNumber(ETXTBSY));
+#endif
+#ifdef EWOULDBLOCK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EWOULDBLOCK"_s), jsNumber(EWOULDBLOCK));
+#endif
+#ifdef EXDEV
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "EXDEV"_s), jsNumber(EXDEV));
+#endif
+#ifdef WSAEINTR
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEINTR"_s), jsNumber(WSAEINTR));
+#endif
+#ifdef WSAEBADF
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEBADF"_s), jsNumber(WSAEBADF));
+#endif
+#ifdef WSAEACCES
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEACCES"_s), jsNumber(WSAEACCES));
+#endif
+#ifdef WSAEFAULT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEFAULT"_s), jsNumber(WSAEFAULT));
+#endif
+#ifdef WSAEINVAL
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEINVAL"_s), jsNumber(WSAEINVAL));
+#endif
+#ifdef WSAEMFILE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEMFILE"_s), jsNumber(WSAEMFILE));
+#endif
+#ifdef WSAEWOULDBLOCK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEWOULDBLOCK"_s), jsNumber(WSAEWOULDBLOCK));
+#endif
+#ifdef WSAEINPROGRESS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEINPROGRESS"_s), jsNumber(WSAEINPROGRESS));
+#endif
+#ifdef WSAEALREADY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEALREADY"_s), jsNumber(WSAEALREADY));
+#endif
+#ifdef WSAENOTSOCK
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOTSOCK"_s), jsNumber(WSAENOTSOCK));
+#endif
+#ifdef WSAEDESTADDRREQ
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEDESTADDRREQ"_s), jsNumber(WSAEDESTADDRREQ));
+#endif
+#ifdef WSAEMSGSIZE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEMSGSIZE"_s), jsNumber(WSAEMSGSIZE));
+#endif
+#ifdef WSAEPROTOTYPE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEPROTOTYPE"_s), jsNumber(WSAEPROTOTYPE));
+#endif
+#ifdef WSAENOPROTOOPT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOPROTOOPT"_s), jsNumber(WSAENOPROTOOPT));
+#endif
+#ifdef WSAEPROTONOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEPROTONOSUPPORT"_s), jsNumber(WSAEPROTONOSUPPORT));
+#endif
+#ifdef WSAESOCKTNOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAESOCKTNOSUPPORT"_s), jsNumber(WSAESOCKTNOSUPPORT));
+#endif
+#ifdef WSAEOPNOTSUPP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEOPNOTSUPP"_s), jsNumber(WSAEOPNOTSUPP));
+#endif
+#ifdef WSAEPFNOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEPFNOSUPPORT"_s), jsNumber(WSAEPFNOSUPPORT));
+#endif
+#ifdef WSAEAFNOSUPPORT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEAFNOSUPPORT"_s), jsNumber(WSAEAFNOSUPPORT));
+#endif
+#ifdef WSAEADDRINUSE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEADDRINUSE"_s), jsNumber(WSAEADDRINUSE));
+#endif
+#ifdef WSAEADDRNOTAVAIL
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEADDRNOTAVAIL"_s), jsNumber(WSAEADDRNOTAVAIL));
+#endif
+#ifdef WSAENETDOWN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENETDOWN"_s), jsNumber(WSAENETDOWN));
+#endif
+#ifdef WSAENETUNREACH
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENETUNREACH"_s), jsNumber(WSAENETUNREACH));
+#endif
+#ifdef WSAENETRESET
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENETRESET"_s), jsNumber(WSAENETRESET));
+#endif
+#ifdef WSAECONNABORTED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAECONNABORTED"_s), jsNumber(WSAECONNABORTED));
+#endif
+#ifdef WSAECONNRESET
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAECONNRESET"_s), jsNumber(WSAECONNRESET));
+#endif
+#ifdef WSAENOBUFS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOBUFS"_s), jsNumber(WSAENOBUFS));
+#endif
+#ifdef WSAEISCONN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEISCONN"_s), jsNumber(WSAEISCONN));
+#endif
+#ifdef WSAENOTCONN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOTCONN"_s), jsNumber(WSAENOTCONN));
+#endif
+#ifdef WSAESHUTDOWN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAESHUTDOWN"_s), jsNumber(WSAESHUTDOWN));
+#endif
+#ifdef WSAETOOMANYREFS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAETOOMANYREFS"_s), jsNumber(WSAETOOMANYREFS));
+#endif
+#ifdef WSAETIMEDOUT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAETIMEDOUT"_s), jsNumber(WSAETIMEDOUT));
+#endif
+#ifdef WSAECONNREFUSED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAECONNREFUSED"_s), jsNumber(WSAECONNREFUSED));
+#endif
+#ifdef WSAELOOP
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAELOOP"_s), jsNumber(WSAELOOP));
+#endif
+#ifdef WSAENAMETOOLONG
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENAMETOOLONG"_s), jsNumber(WSAENAMETOOLONG));
+#endif
+#ifdef WSAEHOSTDOWN
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEHOSTDOWN"_s), jsNumber(WSAEHOSTDOWN));
+#endif
+#ifdef WSAEHOSTUNREACH
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEHOSTUNREACH"_s), jsNumber(WSAEHOSTUNREACH));
+#endif
+#ifdef WSAENOTEMPTY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOTEMPTY"_s), jsNumber(WSAENOTEMPTY));
+#endif
+#ifdef WSAEPROCLIM
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEPROCLIM"_s), jsNumber(WSAEPROCLIM));
+#endif
+#ifdef WSAEUSERS
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEUSERS"_s), jsNumber(WSAEUSERS));
+#endif
+#ifdef WSAEDQUOT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEDQUOT"_s), jsNumber(WSAEDQUOT));
+#endif
+#ifdef WSAESTALE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAESTALE"_s), jsNumber(WSAESTALE));
+#endif
+#ifdef WSAEREMOTE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEREMOTE"_s), jsNumber(WSAEREMOTE));
+#endif
+#ifdef WSASYSNOTREADY
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSASYSNOTREADY"_s), jsNumber(WSASYSNOTREADY));
+#endif
+#ifdef WSAVERNOTSUPPORTED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAVERNOTSUPPORTED"_s), jsNumber(WSAVERNOTSUPPORTED));
+#endif
+#ifdef WSANOTINITIALISED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSANOTINITIALISED"_s), jsNumber(WSANOTINITIALISED));
+#endif
+#ifdef WSAEDISCON
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEDISCON"_s), jsNumber(WSAEDISCON));
+#endif
+#ifdef WSAENOMORE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAENOMORE"_s), jsNumber(WSAENOMORE));
+#endif
+#ifdef WSAECANCELLED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAECANCELLED"_s), jsNumber(WSAECANCELLED));
+#endif
+#ifdef WSAEINVALIDPROCTABLE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEINVALIDPROCTABLE"_s), jsNumber(WSAEINVALIDPROCTABLE));
+#endif
+#ifdef WSAEINVALIDPROVIDER
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEINVALIDPROVIDER"_s), jsNumber(WSAEINVALIDPROVIDER));
+#endif
+#ifdef WSAEPROVIDERFAILEDINIT
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEPROVIDERFAILEDINIT"_s), jsNumber(WSAEPROVIDERFAILEDINIT));
+#endif
+#ifdef WSASYSCALLFAILURE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSASYSCALLFAILURE"_s), jsNumber(WSASYSCALLFAILURE));
+#endif
+#ifdef WSASERVICE_NOT_FOUND
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSASERVICE_NOT_FOUND"_s), jsNumber(WSASERVICE_NOT_FOUND));
+#endif
+#ifdef WSATYPE_NOT_FOUND
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSATYPE_NOT_FOUND"_s), jsNumber(WSATYPE_NOT_FOUND));
+#endif
+#ifdef WSA_E_NO_MORE
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSA_E_NO_MORE"_s), jsNumber(WSA_E_NO_MORE));
+#endif
+#ifdef WSA_E_CANCELLED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSA_E_CANCELLED"_s), jsNumber(WSA_E_CANCELLED));
+#endif
+#ifdef WSAEREFUSED
+ errnoObj->putDirect(vm, Identifier::fromString(vm, "WSAEREFUSED"_s), jsNumber(WSAEREFUSED));
+#endif
+#ifdef SIGHUP
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGHUP"_s), jsNumber(SIGHUP));
+#endif
+#ifdef SIGINT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGINT"_s), jsNumber(SIGINT));
+#endif
+#ifdef SIGQUIT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGQUIT"_s), jsNumber(SIGQUIT));
+#endif
+#ifdef SIGILL
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGILL"_s), jsNumber(SIGILL));
+#endif
+#ifdef SIGTRAP
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGTRAP"_s), jsNumber(SIGTRAP));
+#endif
+#ifdef SIGABRT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGABRT"_s), jsNumber(SIGABRT));
+#endif
+#ifdef SIGIOT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGIOT"_s), jsNumber(SIGIOT));
+#endif
+#ifdef SIGBUS
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGBUS"_s), jsNumber(SIGBUS));
+#endif
+#ifdef SIGFPE
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGFPE"_s), jsNumber(SIGFPE));
+#endif
+#ifdef SIGKILL
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGKILL"_s), jsNumber(SIGKILL));
+#endif
+#ifdef SIGUSR1
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGUSR1"_s), jsNumber(SIGUSR1));
+#endif
+#ifdef SIGSEGV
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGSEGV"_s), jsNumber(SIGSEGV));
+#endif
+#ifdef SIGUSR2
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGUSR2"_s), jsNumber(SIGUSR2));
+#endif
+#ifdef SIGPIPE
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGPIPE"_s), jsNumber(SIGPIPE));
+#endif
+#ifdef SIGALRM
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGALRM"_s), jsNumber(SIGALRM));
+#endif
+#ifdef SIGTERM
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGTERM"_s), jsNumber(SIGTERM));
+#endif
+#ifdef SIGCHLD
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGCHLD"_s), jsNumber(SIGCHLD));
+#endif
+#ifdef SIGSTKFLT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGSTKFLT"_s), jsNumber(SIGSTKFLT));
+#endif
+#ifdef SIGCONT
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGCONT"_s), jsNumber(SIGCONT));
+#endif
+#ifdef SIGSTOP
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGSTOP"_s), jsNumber(SIGSTOP));
+#endif
+#ifdef SIGTSTP
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGTSTP"_s), jsNumber(SIGTSTP));
+#endif
+#ifdef SIGBREAK
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGBREAK"_s), jsNumber(SIGBREAK));
+#endif
+#ifdef SIGTTIN
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGTTIN"_s), jsNumber(SIGTTIN));
+#endif
+#ifdef SIGTTOU
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGTTOU"_s), jsNumber(SIGTTOU));
+#endif
+#ifdef SIGURG
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGURG"_s), jsNumber(SIGURG));
+#endif
+#ifdef SIGXCPU
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGXCPU"_s), jsNumber(SIGXCPU));
+#endif
+#ifdef SIGXFSZ
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGXFSZ"_s), jsNumber(SIGXFSZ));
+#endif
+#ifdef SIGVTALRM
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGVTALRM"_s), jsNumber(SIGVTALRM));
+#endif
+#ifdef SIGPROF
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGPROF"_s), jsNumber(SIGPROF));
+#endif
+#ifdef SIGWINCH
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGWINCH"_s), jsNumber(SIGWINCH));
+#endif
+#ifdef SIGIO
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGIO"_s), jsNumber(SIGIO));
+#endif
+#ifdef SIGPOLL
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGPOLL"_s), jsNumber(SIGPOLL));
+#endif
+#ifdef SIGLOST
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGLOST"_s), jsNumber(SIGLOST));
+#endif
+#ifdef SIGPWR
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGPWR"_s), jsNumber(SIGPWR));
+#endif
+#ifdef SIGINFO
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGINFO"_s), jsNumber(SIGINFO));
+#endif
+#ifdef SIGSYS
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGSYS"_s), jsNumber(SIGSYS));
+#endif
+#ifdef SIGUNUSED
+ signalsObj->putDirect(vm, Identifier::fromString(vm, "SIGUNUSED"_s), jsNumber(SIGUNUSED));
+#endif
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_LOW"_s), jsNumber(19));
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_BELOW_NORMAL"_s), jsNumber(10));
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_NORMAL"_s), jsNumber(0));
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_ABOVE_NORMAL"_s), jsNumber(-7));
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_HIGH"_s), jsNumber(-14));
+ priorityObj->putDirect(vm, Identifier::fromString(vm, "PRIORITY_HIGHEST"_s), jsNumber(-20));
+#ifdef RTLD_LAZY
+ dlopenObj->putDirect(vm, Identifier::fromString(vm, "RTLD_LAZY"_s), jsNumber(RTLD_LAZY));
+#endif
+#ifdef RTLD_NOW
+ dlopenObj->putDirect(vm, Identifier::fromString(vm, "RTLD_NOW"_s), jsNumber(RTLD_NOW));
+#endif
+#ifdef RTLD_GLOBAL
+ dlopenObj->putDirect(vm, Identifier::fromString(vm, "RTLD_GLOBAL"_s), jsNumber(RTLD_GLOBAL));
+#endif
+#ifdef RTLD_LOCAL
+ dlopenObj->putDirect(vm, Identifier::fromString(vm, "RTLD_LOCAL"_s), jsNumber(RTLD_LOCAL));
+#endif
+#ifdef RTLD_DEEPBIND
+ dlopenObj->putDirect(vm, Identifier::fromString(vm, "RTLD_DEEPBIND"_s), jsNumber(RTLD_DEEPBIND));
+#endif
+ return osObj;
+}
+
+static JSValue processBindingConstantsGetTrace(VM& vm, JSObject* bindingObject)
+{
+ auto globalObject = bindingObject->globalObject();
+ auto object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 26);
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_BEGIN"_s)), jsNumber(66));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_END"_s)), jsNumber(69));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_COMPLETE"_s)), jsNumber(88));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_INSTANT"_s)), jsNumber(73));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_ASYNC_BEGIN"_s)), jsNumber(83));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_ASYNC_STEP_INTO"_s)), jsNumber(84));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_ASYNC_STEP_PAST"_s)), jsNumber(112));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_ASYNC_END"_s)), jsNumber(70));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN"_s)), jsNumber(98));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_NESTABLE_ASYNC_END"_s)), jsNumber(101));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT"_s)), jsNumber(110));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_FLOW_BEGIN"_s)), jsNumber(115));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_FLOW_STEP"_s)), jsNumber(116));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_FLOW_END"_s)), jsNumber(102));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_METADATA"_s)), jsNumber(77));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_COUNTER"_s)), jsNumber(67));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_SAMPLE"_s)), jsNumber(80));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_CREATE_OBJECT"_s)), jsNumber(78));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_SNAPSHOT_OBJECT"_s)), jsNumber(79));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_DELETE_OBJECT"_s)), jsNumber(68));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_MEMORY_DUMP"_s)), jsNumber(118));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_MARK"_s)), jsNumber(82));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_CLOCK_SYNC"_s)), jsNumber(99));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_ENTER_CONTEXT"_s)), jsNumber(40));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_LEAVE_CONTEXT"_s)), jsNumber(41));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TRACE_EVENT_PHASE_LINK_IDS"_s)), jsNumber(61));
+ return object;
+}
+
+static JSValue processBindingConstantsGetFs(VM& vm, JSObject* bindingObject)
+{
+ auto globalObject = bindingObject->globalObject();
+ auto object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 26);
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_SYMLINK_DIR"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_SYMLINK_JUNCTION"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_RDONLY"_s)), jsNumber(O_RDONLY));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_WRONLY"_s)), jsNumber(O_WRONLY));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_RDWR"_s)), jsNumber(O_RDWR));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_UNKNOWN"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_FILE"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_DIR"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_LINK"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_FIFO"_s)), jsNumber(4));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_SOCKET"_s)), jsNumber(5));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_CHAR"_s)), jsNumber(6));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_DIRENT_BLOCK"_s)), jsNumber(7));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFMT"_s)), jsNumber(S_IFMT));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFREG"_s)), jsNumber(S_IFREG));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFDIR"_s)), jsNumber(S_IFDIR));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFCHR"_s)), jsNumber(S_IFCHR));
+#ifdef S_IFBLK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFBLK"_s)), jsNumber(S_IFBLK));
+#endif
+#ifdef S_IFIFO
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFIFO"_s)), jsNumber(S_IFIFO));
+#endif
+#ifdef S_IFLNK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFLNK"_s)), jsNumber(S_IFLNK));
+#endif
+#ifdef S_IFSOCK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IFSOCK"_s)), jsNumber(S_IFSOCK));
+#endif
+#ifdef O_CREAT
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_CREAT"_s)), jsNumber(O_CREAT));
+#endif
+#ifdef O_EXCL
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_EXCL"_s)), jsNumber(O_EXCL));
+#endif
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_O_FILEMAP"_s)), jsNumber(0));
+
+#ifdef O_NOCTTY
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_NOCTTY"_s)), jsNumber(O_NOCTTY));
+#endif
+#ifdef O_TRUNC
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_TRUNC"_s)), jsNumber(O_TRUNC));
+#endif
+#ifdef O_APPEND
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_APPEND"_s)), jsNumber(O_APPEND));
+#endif
+#ifdef O_DIRECTORY
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_DIRECTORY"_s)), jsNumber(O_DIRECTORY));
+#endif
+#ifdef O_EXCL
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_EXCL"_s)), jsNumber(O_EXCL));
+#endif
+#ifdef O_NOATIME
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_NOATIME"_s)), jsNumber(O_NOATIME));
+#endif
+#ifdef O_NOFOLLOW
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_NOFOLLOW"_s)), jsNumber(O_NOFOLLOW));
+#endif
+#ifdef O_SYNC
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_SYNC"_s)), jsNumber(O_SYNC));
+#endif
+#ifdef O_DSYNC
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_DSYNC"_s)), jsNumber(O_DSYNC));
+#endif
+#ifdef O_SYMLINK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_SYMLINK"_s)), jsNumber(O_SYMLINK));
+#endif
+#ifdef O_DIRECT
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_DIRECT"_s)), jsNumber(O_DIRECT));
+#endif
+#ifdef O_NONBLOCK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_NONBLOCK"_s)), jsNumber(O_NONBLOCK));
+#endif
+#ifdef S_IRWXU
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IRWXU"_s)), jsNumber(S_IRWXU));
+#endif
+#ifdef S_IRUSR
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IRUSR"_s)), jsNumber(S_IRUSR));
+#endif
+#ifdef S_IWUSR
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IWUSR"_s)), jsNumber(S_IWUSR));
+#endif
+#ifdef S_IXUSR
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IXUSR"_s)), jsNumber(S_IXUSR));
+#endif
+#ifdef S_IRWXG
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IRWXG"_s)), jsNumber(S_IRWXG));
+#endif
+#ifdef S_IRGRP
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IRGRP"_s)), jsNumber(S_IRGRP));
+#endif
+#ifdef S_IWGRP
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IWGRP"_s)), jsNumber(S_IWGRP));
+#endif
+#ifdef S_IXGRP
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IXGRP"_s)), jsNumber(S_IXGRP));
+#endif
+#ifdef S_IRWXO
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IRWXO"_s)), jsNumber(S_IRWXO));
+#endif
+#ifdef S_IROTH
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IROTH"_s)), jsNumber(S_IROTH));
+#endif
+#ifdef S_IWOTH
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IWOTH"_s)), jsNumber(S_IWOTH));
+#endif
+#ifdef S_IXOTH
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "S_IXOTH"_s)), jsNumber(S_IXOTH));
+#endif
+#ifdef F_OK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "F_OK"_s)), jsNumber(F_OK));
+#endif
+#ifdef R_OK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "R_OK"_s)), jsNumber(R_OK));
+#endif
+#ifdef W_OK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "W_OK"_s)), jsNumber(W_OK));
+#endif
+#ifdef X_OK
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "X_OK"_s)), jsNumber(X_OK));
+#endif
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_COPYFILE_EXCL"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "COPYFILE_EXCL"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_COPYFILE_FICLONE"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "COPYFILE_FICLONE"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UV_FS_COPYFILE_FICLONE_FORCE"_s)), jsNumber(4));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "COPYFILE_FICLONE_FORCE"_s)), jsNumber(4));
+ return object;
+}
+
+static JSValue processBindingConstantsGetCrypto(VM& vm, JSObject* bindingObject)
+{
+ auto globalObject = bindingObject->globalObject();
+ auto object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype());
+#ifdef OPENSSL_VERSION_NUMBER
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "OPENSSL_VERSION_NUMBER"_s)), jsNumber(OPENSSL_VERSION_NUMBER));
+#endif
+#ifdef SSL_OP_ALL
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_ALL"_s)), jsNumber(SSL_OP_ALL));
+#endif
+#ifdef SSL_OP_ALLOW_NO_DHE_KEX
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_ALLOW_NO_DHE_KEX"_s)), jsNumber(SSL_OP_ALLOW_NO_DHE_KEX));
+#endif
+#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION"_s)), jsNumber(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+#endif
+#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_CIPHER_SERVER_PREFERENCE"_s)), jsNumber(SSL_OP_CIPHER_SERVER_PREFERENCE));
+#endif
+#ifdef SSL_OP_CISCO_ANYCONNECT
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_CISCO_ANYCONNECT"_s)), jsNumber(SSL_OP_CISCO_ANYCONNECT));
+#endif
+#ifdef SSL_OP_COOKIE_EXCHANGE
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_COOKIE_EXCHANGE"_s)), jsNumber(SSL_OP_COOKIE_EXCHANGE));
+#endif
+#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_CRYPTOPRO_TLSEXT_BUG"_s)), jsNumber(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
+#endif
+#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS"_s)), jsNumber(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
+#endif
+#ifdef SSL_OP_LEGACY_SERVER_CONNECT
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_LEGACY_SERVER_CONNECT"_s)), jsNumber(SSL_OP_LEGACY_SERVER_CONNECT));
+#endif
+#ifdef SSL_OP_NO_COMPRESSION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_COMPRESSION"_s)), jsNumber(SSL_OP_NO_COMPRESSION));
+#endif
+#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_ENCRYPT_THEN_MAC"_s)), jsNumber(SSL_OP_NO_ENCRYPT_THEN_MAC));
+#endif
+#ifdef SSL_OP_NO_QUERY_MTU
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_QUERY_MTU"_s)), jsNumber(SSL_OP_NO_QUERY_MTU));
+#endif
+#ifdef SSL_OP_NO_RENEGOTIATION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_RENEGOTIATION"_s)), jsNumber(SSL_OP_NO_RENEGOTIATION));
+#endif
+#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION"_s)), jsNumber(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION));
+#endif
+#ifdef SSL_OP_NO_SSLv2
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_SSLv2"_s)), jsNumber(SSL_OP_NO_SSLv2));
+#endif
+#ifdef SSL_OP_NO_SSLv3
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_SSLv3"_s)), jsNumber(SSL_OP_NO_SSLv3));
+#endif
+#ifdef SSL_OP_NO_TICKET
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_TICKET"_s)), jsNumber(SSL_OP_NO_TICKET));
+#endif
+#ifdef SSL_OP_NO_TLSv1
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_TLSv1"_s)), jsNumber(SSL_OP_NO_TLSv1));
+#endif
+#ifdef SSL_OP_NO_TLSv1_1
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_TLSv1_1"_s)), jsNumber(SSL_OP_NO_TLSv1_1));
+#endif
+#ifdef SSL_OP_NO_TLSv1_2
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_TLSv1_2"_s)), jsNumber(SSL_OP_NO_TLSv1_2));
+#endif
+#ifdef SSL_OP_NO_TLSv1_3
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_NO_TLSv1_3"_s)), jsNumber(SSL_OP_NO_TLSv1_3));
+#endif
+#ifdef SSL_OP_PRIORITIZE_CHACHA
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_PRIORITIZE_CHACHA"_s)), jsNumber(SSL_OP_PRIORITIZE_CHACHA));
+#endif
+#ifdef SSL_OP_TLS_ROLLBACK_BUG
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "SSL_OP_TLS_ROLLBACK_BUG"_s)), jsNumber(SSL_OP_TLS_ROLLBACK_BUG));
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#ifdef ENGINE_METHOD_RSA
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_RSA"_s)), jsNumber(ENGINE_METHOD_RSA));
+#endif
+#ifdef ENGINE_METHOD_DSA
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_DSA"_s)), jsNumber(ENGINE_METHOD_DSA));
+#endif
+#ifdef ENGINE_METHOD_DH
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_DH"_s)), jsNumber(ENGINE_METHOD_DH));
+#endif
+#ifdef ENGINE_METHOD_RAND
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_RAND"_s)), jsNumber(ENGINE_METHOD_RAND));
+#endif
+#ifdef ENGINE_METHOD_EC
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_EC"_s)), jsNumber(ENGINE_METHOD_EC));
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_CIPHERS"_s)), jsNumber(ENGINE_METHOD_CIPHERS));
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_DIGESTS"_s)), jsNumber(ENGINE_METHOD_DIGESTS));
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_PKEY_METHS"_s)), jsNumber(ENGINE_METHOD_PKEY_METHS));
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_PKEY_ASN1_METHS"_s)), jsNumber(ENGINE_METHOD_PKEY_ASN1_METHS));
+#endif
+#ifdef ENGINE_METHOD_ALL
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_ALL"_s)), jsNumber(ENGINE_METHOD_ALL));
+#endif
+#ifdef ENGINE_METHOD_NONE
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ENGINE_METHOD_NONE"_s)), jsNumber(ENGINE_METHOD_NONE));
+#endif
+#endif // !OPENSSL_NO_ENGINE
+#ifdef DH_CHECK_P_NOT_SAFE_PRIME
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DH_CHECK_P_NOT_SAFE_PRIME"_s)), jsNumber(DH_CHECK_P_NOT_SAFE_PRIME));
+#endif
+#ifdef DH_CHECK_P_NOT_PRIME
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DH_CHECK_P_NOT_PRIME"_s)), jsNumber(DH_CHECK_P_NOT_PRIME));
+#endif
+#ifdef DH_UNABLE_TO_CHECK_GENERATOR
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DH_UNABLE_TO_CHECK_GENERATOR"_s)), jsNumber(DH_UNABLE_TO_CHECK_GENERATOR));
+#endif
+#ifdef DH_NOT_SUITABLE_GENERATOR
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DH_NOT_SUITABLE_GENERATOR"_s)), jsNumber(DH_NOT_SUITABLE_GENERATOR));
+#endif
+#ifdef RSA_PKCS1_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PKCS1_PADDING"_s)), jsNumber(RSA_PKCS1_PADDING));
+#endif
+#ifdef RSA_SSLV23_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_SSLV23_PADDING"_s)), jsNumber(RSA_SSLV23_PADDING));
+#endif
+#ifdef RSA_NO_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_NO_PADDING"_s)), jsNumber(RSA_NO_PADDING));
+#endif
+#ifdef RSA_PKCS1_OAEP_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PKCS1_OAEP_PADDING"_s)), jsNumber(RSA_PKCS1_OAEP_PADDING));
+#endif
+#ifdef RSA_X931_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_X931_PADDING"_s)), jsNumber(RSA_X931_PADDING));
+#endif
+#ifdef RSA_PKCS1_PSS_PADDING
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PKCS1_PSS_PADDING"_s)), jsNumber(RSA_PKCS1_PSS_PADDING));
+#endif
+#ifdef RSA_PSS_SALTLEN_DIGEST
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PSS_SALTLEN_DIGEST"_s)), jsNumber(RSA_PSS_SALTLEN_DIGEST));
+#endif
+#ifdef RSA_PSS_SALTLEN_MAX_SIGN
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PSS_SALTLEN_MAX_SIGN"_s)), jsNumber(RSA_PSS_SALTLEN_MAX_SIGN));
+#endif
+#ifdef RSA_PSS_SALTLEN_AUTO
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "RSA_PSS_SALTLEN_AUTO"_s)), jsNumber(RSA_PSS_SALTLEN_AUTO));
+#endif
+ auto cipherList = String("TLS_AES_256_GCM_SHA384:"
+ "TLS_CHACHA20_POLY1305_SHA256:"
+ "TLS_AES_128_GCM_SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES256-GCM-SHA384:"
+ "ECDHE-ECDSA-AES256-GCM-SHA384:"
+ "DHE-RSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-SHA256:"
+ "DHE-RSA-AES128-SHA256:"
+ "ECDHE-RSA-AES256-SHA384:"
+ "DHE-RSA-AES256-SHA384:"
+ "ECDHE-RSA-AES256-SHA256:"
+ "DHE-RSA-AES256-SHA256:"
+ "HIGH:"
+ "!aNULL:"
+ "!eNULL:"
+ "!EXPORT:"
+ "!DES:"
+ "!RC4:"
+ "!MD5:"
+ "!PSK:"
+ "!SRP:"
+ "!CAMELLIA"_s);
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "defaultCoreCipherList"_s)),
+ jsString(vm, cipherList));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "defaultCipherList"_s)),
+ jsString(vm, cipherList));
+#ifdef TLS1_VERSION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TLS1_VERSION"_s)), jsNumber(TLS1_VERSION));
+#endif
+#ifdef TLS1_1_VERSION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TLS1_1_VERSION"_s)), jsNumber(TLS1_1_VERSION));
+#endif
+#ifdef TLS1_2_VERSION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TLS1_2_VERSION"_s)), jsNumber(TLS1_2_VERSION));
+#endif
+#ifdef TLS1_3_VERSION
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "TLS1_3_VERSION"_s)), jsNumber(TLS1_3_VERSION));
+#endif
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "POINT_CONVERSION_COMPRESSED"_s)), jsNumber(POINT_CONVERSION_COMPRESSED));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "POINT_CONVERSION_UNCOMPRESSED"_s)), jsNumber(POINT_CONVERSION_UNCOMPRESSED));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "POINT_CONVERSION_HYBRID"_s)), jsNumber(POINT_CONVERSION_HYBRID));
+ return object;
+}
+
+static JSValue processBindingConstantsGetZlib(VM& vm, JSObject* bindingObject)
+{
+ auto globalObject = bindingObject->globalObject();
+ auto object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype());
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_NO_FLUSH"_s)), jsNumber(Z_NO_FLUSH));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_PARTIAL_FLUSH"_s)), jsNumber(Z_PARTIAL_FLUSH));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_SYNC_FLUSH"_s)), jsNumber(Z_SYNC_FLUSH));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_FULL_FLUSH"_s)), jsNumber(Z_FULL_FLUSH));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_FINISH"_s)), jsNumber(Z_FINISH));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_BLOCK"_s)), jsNumber(Z_BLOCK));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_OK"_s)), jsNumber(Z_OK));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_STREAM_END"_s)), jsNumber(Z_STREAM_END));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_NEED_DICT"_s)), jsNumber(Z_NEED_DICT));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_ERRNO"_s)), jsNumber(Z_ERRNO));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_STREAM_ERROR"_s)), jsNumber(Z_STREAM_ERROR));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DATA_ERROR"_s)), jsNumber(Z_DATA_ERROR));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MEM_ERROR"_s)), jsNumber(Z_MEM_ERROR));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_BUF_ERROR"_s)), jsNumber(Z_BUF_ERROR));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_VERSION_ERROR"_s)), jsNumber(Z_VERSION_ERROR));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_NO_COMPRESSION"_s)), jsNumber(Z_NO_COMPRESSION));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_BEST_SPEED"_s)), jsNumber(Z_BEST_SPEED));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_BEST_COMPRESSION"_s)), jsNumber(Z_BEST_COMPRESSION));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_COMPRESSION"_s)), jsNumber(Z_DEFAULT_COMPRESSION));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_FILTERED"_s)), jsNumber(Z_FILTERED));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_HUFFMAN_ONLY"_s)), jsNumber(Z_HUFFMAN_ONLY));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_RLE"_s)), jsNumber(Z_RLE));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_FIXED"_s)), jsNumber(Z_FIXED));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_STRATEGY"_s)), jsNumber(Z_DEFAULT_STRATEGY));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "ZLIB_VERNUM"_s)), jsNumber(ZLIB_VERNUM));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DEFLATE"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "INFLATE"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "GZIP"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "GUNZIP"_s)), jsNumber(4));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "DEFLATERAW"_s)), jsNumber(5));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "INFLATERAW"_s)), jsNumber(6));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "UNZIP"_s)), jsNumber(7));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODE"_s)), jsNumber(8));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_ENCODE"_s)), jsNumber(9));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MIN_WINDOWBITS"_s)), jsNumber(8));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MAX_WINDOWBITS"_s)), jsNumber(15));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_WINDOWBITS"_s)), jsNumber(15));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MIN_CHUNK"_s)), jsNumber(64));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MAX_CHUNK"_s)), jsNumber(INFINITY));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_CHUNK"_s)), jsNumber(16384));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MIN_MEMLEVEL"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MAX_MEMLEVEL"_s)), jsNumber(9));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_MEMLEVEL"_s)), jsNumber(8));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MIN_LEVEL"_s)), jsNumber(-1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_MAX_LEVEL"_s)), jsNumber(9));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "Z_DEFAULT_LEVEL"_s)), jsNumber(-1));
+
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_OPERATION_PROCESS"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_OPERATION_FLUSH"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_OPERATION_FINISH"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_OPERATION_EMIT_METADATA"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_MODE"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MODE_GENERIC"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MODE_TEXT"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MODE_FONT"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DEFAULT_MODE"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_QUALITY"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MIN_QUALITY"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MAX_QUALITY"_s)), jsNumber(11));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DEFAULT_QUALITY"_s)), jsNumber(11));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_LGWIN"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MIN_WINDOW_BITS"_s)), jsNumber(10));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MAX_WINDOW_BITS"_s)), jsNumber(24));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_LARGE_MAX_WINDOW_BITS"_s)), jsNumber(30));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DEFAULT_WINDOW"_s)), jsNumber(22));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_LGBLOCK"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MIN_INPUT_BLOCK_BITS"_s)), jsNumber(16));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_MAX_INPUT_BLOCK_BITS"_s)), jsNumber(24));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING"_s)), jsNumber(4));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_SIZE_HINT"_s)), jsNumber(5));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_LARGE_WINDOW"_s)), jsNumber(6));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_NPOSTFIX"_s)), jsNumber(7));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_PARAM_NDIRECT"_s)), jsNumber(8));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_RESULT_ERROR"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_RESULT_SUCCESS"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_PARAM_LARGE_WINDOW"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_NO_ERROR"_s)), jsNumber(0));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_SUCCESS"_s)), jsNumber(1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_NEEDS_MORE_INPUT"_s)), jsNumber(2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_NEEDS_MORE_OUTPUT"_s)), jsNumber(3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE"_s)), jsNumber(-1));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_RESERVED"_s)), jsNumber(-2));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE"_s)), jsNumber(-3));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET"_s)), jsNumber(-4));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME"_s)), jsNumber(-5));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_CL_SPACE"_s)), jsNumber(-6));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE"_s)), jsNumber(-7));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT"_s)), jsNumber(-8));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1"_s)), jsNumber(-9));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2"_s)), jsNumber(-10));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_TRANSFORM"_s)), jsNumber(-11));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_DICTIONARY"_s)), jsNumber(-12));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS"_s)), jsNumber(-13));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_PADDING_1"_s)), jsNumber(-14));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_PADDING_2"_s)), jsNumber(-15));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_FORMAT_DISTANCE"_s)), jsNumber(-16));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET"_s)), jsNumber(-19));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_INVALID_ARGUMENTS"_s)), jsNumber(-20));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES"_s)), jsNumber(-21));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS"_s)), jsNumber(-22));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP"_s)), jsNumber(-25));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1"_s)), jsNumber(-26));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2"_s)), jsNumber(-27));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES"_s)), jsNumber(-30));
+ object->putDirect(vm, PropertyName(Identifier::fromString(vm, "BROTLI_DECODER_ERROR_UNREACHABLE"_s)), jsNumber(-31));
+
+ return object;
+}
+
+static const HashTableValue ProcessBindingConstantsValues[] = {
+ { "os"_s, static_cast(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetOs } },
+ { "fs"_s, static_cast(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetFs } },
+ { "crypto"_s, static_cast]