mirror of
https://github.com/oven-sh/bun
synced 2026-02-07 09:28:51 +00:00
Compare commits
53 Commits
jarred/sta
...
fix-format
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88063eaad5 | ||
|
|
da2d1e12ed | ||
|
|
6b54dbfa07 | ||
|
|
1dfa557ca4 | ||
|
|
29d1b4db74 | ||
|
|
85edb39a2f | ||
|
|
f0384f39b7 | ||
|
|
2e1b19b9fd | ||
|
|
53ce1ff6c1 | ||
|
|
eee9b51df3 | ||
|
|
f0036cc6c1 | ||
|
|
77a25c0188 | ||
|
|
a3777b8c22 | ||
|
|
0d9d7a3436 | ||
|
|
d5e7846eaf | ||
|
|
582a53e26e | ||
|
|
57d9cfc24d | ||
|
|
31dc58fa79 | ||
|
|
03bb9fd9b5 | ||
|
|
f270f235c8 | ||
|
|
8d1b5856d3 | ||
|
|
bf488d0b19 | ||
|
|
9dc0672840 | ||
|
|
b1d0cb0ea3 | ||
|
|
155ba7ebdf | ||
|
|
3757a3e30f | ||
|
|
4b443db0d8 | ||
|
|
d74ae08946 | ||
|
|
a7a5ed2fba | ||
|
|
7d7c9877a4 | ||
|
|
1cd43f5bae | ||
|
|
56b6ed6d97 | ||
|
|
85dd8ef0d4 | ||
|
|
6cb0de3921 | ||
|
|
2c1dcb5a1d | ||
|
|
d3f3900da7 | ||
|
|
ef18731db1 | ||
|
|
7fb15e5a03 | ||
|
|
2b017cd0ad | ||
|
|
9f857fa418 | ||
|
|
1cde69d0f1 | ||
|
|
800e378b6e | ||
|
|
dfe8fb50d9 | ||
|
|
0f6cfc0b16 | ||
|
|
019cfb7927 | ||
|
|
7887689fd0 | ||
|
|
888d8301ca | ||
|
|
704c169e04 | ||
|
|
c16e34078a | ||
|
|
bc9e022c86 | ||
|
|
a88b8130b9 | ||
|
|
2139e8442a | ||
|
|
f50a80a7c1 |
@@ -12,14 +12,14 @@ steps:
|
||||
- key: "darwin-aarch64"
|
||||
group: ":darwin: aarch64"
|
||||
steps:
|
||||
- key: "darwin-aarch64-build-deps"
|
||||
label: ":darwin: aarch64 - build-deps"
|
||||
- key: "darwin-aarch64-build-vendor"
|
||||
label: ":darwin: aarch64 - build-vendor"
|
||||
agents:
|
||||
queue: "build-darwin"
|
||||
os: "darwin"
|
||||
arch: "aarch64"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "darwin-aarch64-build-cpp"
|
||||
label: ":darwin: aarch64 - build-cpp"
|
||||
@@ -46,7 +46,7 @@ steps:
|
||||
os: "darwin"
|
||||
arch: "aarch64"
|
||||
depends_on:
|
||||
- "darwin-aarch64-build-deps"
|
||||
- "darwin-aarch64-build-vendor"
|
||||
- "darwin-aarch64-build-cpp"
|
||||
- "darwin-aarch64-build-zig"
|
||||
env:
|
||||
@@ -114,14 +114,14 @@ steps:
|
||||
- key: "darwin-x64"
|
||||
group: ":darwin: x64"
|
||||
steps:
|
||||
- key: "darwin-x64-build-deps"
|
||||
label: ":darwin: x64 - build-deps"
|
||||
- key: "darwin-x64-build-vendor"
|
||||
label: ":darwin: x64 - build-vendor"
|
||||
agents:
|
||||
queue: "build-darwin"
|
||||
os: "darwin"
|
||||
arch: "x64"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "darwin-x64-build-cpp"
|
||||
label: ":darwin: x64 - build-cpp"
|
||||
@@ -148,7 +148,7 @@ steps:
|
||||
os: "darwin"
|
||||
arch: "x64"
|
||||
depends_on:
|
||||
- "darwin-x64-build-deps"
|
||||
- "darwin-x64-build-vendor"
|
||||
- "darwin-x64-build-cpp"
|
||||
- "darwin-x64-build-zig"
|
||||
env:
|
||||
@@ -216,14 +216,14 @@ steps:
|
||||
- key: "linux-x64"
|
||||
group: ":linux: x64"
|
||||
steps:
|
||||
- key: "linux-x64-build-deps"
|
||||
label: ":linux: x64 - build-deps"
|
||||
- key: "linux-x64-build-vendor"
|
||||
label: ":linux: x64 - build-vendor"
|
||||
agents:
|
||||
queue: "build-linux"
|
||||
os: "linux"
|
||||
arch: "x64"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "linux-x64-build-cpp"
|
||||
label: ":linux: x64 - build-cpp"
|
||||
@@ -250,7 +250,7 @@ steps:
|
||||
os: "linux"
|
||||
arch: "x64"
|
||||
depends_on:
|
||||
- "linux-x64-build-deps"
|
||||
- "linux-x64-build-vendor"
|
||||
- "linux-x64-build-cpp"
|
||||
- "linux-x64-build-zig"
|
||||
env:
|
||||
@@ -349,8 +349,8 @@ steps:
|
||||
- key: "linux-x64-baseline"
|
||||
group: ":linux: x64-baseline"
|
||||
steps:
|
||||
- key: "linux-x64-baseline-build-deps"
|
||||
label: ":linux: x64-baseline - build-deps"
|
||||
- key: "linux-x64-baseline-build-vendor"
|
||||
label: ":linux: x64-baseline - build-vendor"
|
||||
agents:
|
||||
queue: "build-linux"
|
||||
os: "linux"
|
||||
@@ -358,7 +358,7 @@ steps:
|
||||
env:
|
||||
ENABLE_BASELINE: "ON"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "linux-x64-baseline-build-cpp"
|
||||
label: ":linux: x64-baseline - build-cpp"
|
||||
@@ -388,7 +388,7 @@ steps:
|
||||
os: "linux"
|
||||
arch: "x64"
|
||||
depends_on:
|
||||
- "linux-x64-baseline-build-deps"
|
||||
- "linux-x64-baseline-build-vendor"
|
||||
- "linux-x64-baseline-build-cpp"
|
||||
- "linux-x64-baseline-build-zig"
|
||||
env:
|
||||
@@ -488,14 +488,14 @@ steps:
|
||||
- key: "linux-aarch64"
|
||||
group: ":linux: aarch64"
|
||||
steps:
|
||||
- key: "linux-aarch64-build-deps"
|
||||
label: ":linux: aarch64 - build-deps"
|
||||
- key: "linux-aarch64-build-vendor"
|
||||
label: ":linux: aarch64 - build-vendor"
|
||||
agents:
|
||||
queue: "build-linux"
|
||||
os: "linux"
|
||||
arch: "aarch64"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "linux-aarch64-build-cpp"
|
||||
label: ":linux: aarch64 - build-cpp"
|
||||
@@ -522,7 +522,7 @@ steps:
|
||||
os: "linux"
|
||||
arch: "aarch64"
|
||||
depends_on:
|
||||
- "linux-aarch64-build-deps"
|
||||
- "linux-aarch64-build-vendor"
|
||||
- "linux-aarch64-build-cpp"
|
||||
- "linux-aarch64-build-zig"
|
||||
env:
|
||||
@@ -621,18 +621,14 @@ steps:
|
||||
- key: "windows-x64"
|
||||
group: ":windows: x64"
|
||||
steps:
|
||||
- key: "windows-x64-build-deps"
|
||||
label: ":windows: x64 - build-deps"
|
||||
- key: "windows-x64-build-vendor"
|
||||
label: ":windows: x64 - build-vendor"
|
||||
agents:
|
||||
queue: "build-windows"
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "windows-x64-build-cpp"
|
||||
label: ":windows: x64 - build-cpp"
|
||||
@@ -640,10 +636,6 @@ steps:
|
||||
queue: "build-windows"
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
env:
|
||||
BUN_CPP_ONLY: "ON"
|
||||
command:
|
||||
@@ -663,13 +655,9 @@ steps:
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
depends_on:
|
||||
- "windows-x64-build-deps"
|
||||
- "windows-x64-build-vendor"
|
||||
- "windows-x64-build-cpp"
|
||||
- "windows-x64-build-zig"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
env:
|
||||
BUN_LINK_ONLY: "ON"
|
||||
command:
|
||||
@@ -704,20 +692,16 @@ steps:
|
||||
- key: "windows-x64-baseline"
|
||||
group: ":windows: x64-baseline"
|
||||
steps:
|
||||
- key: "windows-x64-baseline-build-deps"
|
||||
label: ":windows: x64-baseline - build-deps"
|
||||
- key: "windows-x64-baseline-build-vendor"
|
||||
label: ":windows: x64-baseline - build-vendor"
|
||||
agents:
|
||||
queue: "build-windows"
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
env:
|
||||
ENABLE_BASELINE: "ON"
|
||||
command:
|
||||
- "bun run build:ci --target dependencies"
|
||||
- "bun run build:ci --target vendor"
|
||||
|
||||
- key: "windows-x64-baseline-build-cpp"
|
||||
label: ":windows: x64-baseline - build-cpp"
|
||||
@@ -725,10 +709,6 @@ steps:
|
||||
queue: "build-windows"
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
env:
|
||||
ENABLE_BASELINE: "ON"
|
||||
BUN_CPP_ONLY: "ON"
|
||||
@@ -751,13 +731,9 @@ steps:
|
||||
os: "windows"
|
||||
arch: "x64"
|
||||
depends_on:
|
||||
- "windows-x64-baseline-build-deps"
|
||||
- "windows-x64-baseline-build-vendor"
|
||||
- "windows-x64-baseline-build-cpp"
|
||||
- "windows-x64-baseline-build-zig"
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: 255
|
||||
limit: 5
|
||||
env:
|
||||
ENABLE_BASELINE: "ON"
|
||||
BUN_LINK_ONLY: "ON"
|
||||
|
||||
1539
.docker/chrome.json
Normal file
1539
.docker/chrome.json
Normal file
File diff suppressed because it is too large
Load Diff
14
.docker/chromium.pref
Normal file
14
.docker/chromium.pref
Normal file
@@ -0,0 +1,14 @@
|
||||
# Note: 2 blank lines are required between entries
|
||||
Package: *
|
||||
Pin: release a=eoan
|
||||
Pin-Priority: 500
|
||||
|
||||
Package: *
|
||||
Pin: origin "ftp.debian.org"
|
||||
Pin-Priority: 300
|
||||
|
||||
# Pattern includes 'chromium', 'chromium-browser' and similarly
|
||||
# named dependencies:
|
||||
Package: chromium*
|
||||
Pin: origin "ftp.debian.org"
|
||||
Pin-Priority: 700
|
||||
8
.docker/copy-bun-binary.sh
Normal file
8
.docker/copy-bun-binary.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
name=$(openssl rand -hex 12)
|
||||
id=$(docker create --name=bun-binary-$name $CONTAINER_TAG)
|
||||
docker container cp bun-binary-$name:$BUN_RELEASE_DIR bun-binary
|
||||
echo -e "bun-binary-$name"
|
||||
3
.docker/debian.list
Normal file
3
.docker/debian.list
Normal file
@@ -0,0 +1,3 @@
|
||||
deb http://deb.debian.org/debian buster main
|
||||
deb http://deb.debian.org/debian buster-updates main
|
||||
deb http://deb.debian.org/debian-security buster/updates main
|
||||
34
.docker/dockerfile-common.sh
Normal file
34
.docker/dockerfile-common.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
export BUILDKIT_ARCH=$(uname -m)
|
||||
export ARCH=${BUILDKIT_ARCH}
|
||||
|
||||
if [ "$BUILDKIT_ARCH" == "amd64" ]; then
|
||||
export BUILDKIT_ARCH="amd64"
|
||||
export ARCH=x64
|
||||
fi
|
||||
|
||||
if [ "$BUILDKIT_ARCH" == "x86_64" ]; then
|
||||
export BUILDKIT_ARCH="amd64"
|
||||
export ARCH=x64
|
||||
fi
|
||||
|
||||
if [ "$BUILDKIT_ARCH" == "arm64" ]; then
|
||||
export BUILDKIT_ARCH="arm64"
|
||||
export ARCH=aarch64
|
||||
fi
|
||||
|
||||
if [ "$BUILDKIT_ARCH" == "aarch64" ]; then
|
||||
export BUILDKIT_ARCH="arm64"
|
||||
export ARCH=aarch64
|
||||
fi
|
||||
|
||||
if [ "$BUILDKIT_ARCH" == "armv7l" ]; then
|
||||
echo "Unsupported platform: $BUILDKIT_ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export BUILD_ID=$(cat build-id)
|
||||
export CONTAINER_NAME=bun-linux-$ARCH
|
||||
export DEBUG_CONTAINER_NAME=debug-bun-linux-$ARCH
|
||||
export TEMP=/tmp/bun-0.0.$BUILD_ID
|
||||
11
.docker/pull.sh
Normal file
11
.docker/pull.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
docker pull bunbunbunbun/bun-test-base:latest --platform=linux/amd64
|
||||
docker pull bunbunbunbun/bun-base:latest --platform=linux/amd64
|
||||
docker pull bunbunbunbun/bun-base-with-zig-and-webkit:latest --platform=linux/amd64
|
||||
|
||||
docker tag bunbunbunbun/bun-test-base:latest bun-base:latest
|
||||
docker tag bunbunbunbun/bun-base:latest bun-base:latest
|
||||
docker tag bunbunbunbun/bun-base-with-zig-and-webkit:latest bun-base-with-zig-and-webkit:latest
|
||||
47
.docker/run-dockerfile.sh
Normal file
47
.docker/run-dockerfile.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
source "dockerfile-common.sh"
|
||||
|
||||
export $CONTAINER_NAME=$CONTAINER_NAME-local
|
||||
|
||||
rm -rf $TEMP
|
||||
mkdir -p $TEMP
|
||||
|
||||
docker build . --target release --progress=plain -t $CONTAINER_NAME:latest --build-arg BUILDKIT_INLINE_CACHE=1 --platform=linux/$BUILDKIT_ARCH --cache-from $CONTAINER_NAME:latest
|
||||
|
||||
if (($?)); then
|
||||
echo "Failed to build container"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
id=$(docker create $CONTAINER_NAME:latest)
|
||||
docker cp $id:/home/ubuntu/bun-release $TEMP/$CONTAINER_NAME
|
||||
if (($?)); then
|
||||
echo "Failed to cp container"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $TEMP
|
||||
mkdir -p $TEMP/$CONTAINER_NAME $TEMP/$DEBUG_CONTAINER_NAME
|
||||
mv $CONTAINER_NAME/bun-profile $DEBUG_CONTAINER_NAME/bun
|
||||
zip -r $CONTAINER_NAME.zip $CONTAINER_NAME
|
||||
zip -r $DEBUG_CONTAINER_NAME.zip $DEBUG_CONTAINER_NAME
|
||||
docker rm -v $id
|
||||
abs=$(realpath $TEMP/$CONTAINER_NAME.zip)
|
||||
debug_abs=$(realpath $TEMP/$DEBUG_CONTAINER_NAME.zip)
|
||||
|
||||
case $(uname -s) in
|
||||
"Linux") target="linux" ;;
|
||||
*) target="other" ;;
|
||||
esac
|
||||
|
||||
if [ "$target" = "linux" ]; then
|
||||
if command -v bun --version >/dev/null; then
|
||||
cp $TEMP/$CONTAINER_NAME/bun $(which bun)
|
||||
cp $TEMP/$DEBUG_CONTAINER_NAME/bun $(which bun-profile)
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Saved to:"
|
||||
echo $debug_abs
|
||||
echo $abs
|
||||
9
.docker/run-test.sh
Executable file
9
.docker/run-test.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
bun install
|
||||
bun install --cwd ./test/snippets
|
||||
bun install --cwd ./test/scripts
|
||||
|
||||
make $BUN_TEST_NAME
|
||||
5
.docker/runner.sh
Normal file
5
.docker/runner.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
docker container run --security-opt seccomp=.docker/chrome.json --env GITHUB_WORKSPACE=$GITHUB_WORKSPACE --env BUN_TEST_NAME=$BUN_TEST_NAME --ulimit memlock=-1:-1 --init --rm bun-test:latest
|
||||
5
.docker/unit-tests.sh
Normal file
5
.docker/unit-tests.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
docker container run --security-opt seccomp=.docker/chrome.json --env GITHUB_WORKSPACE=$GITHUB_WORKSPACE --ulimit memlock=-1:-1 --init --rm bun-unit-tests:latest
|
||||
1
.github/actions/setup-bun/action.yml
vendored
1
.github/actions/setup-bun/action.yml
vendored
@@ -47,5 +47,4 @@ runs:
|
||||
mkdir -p ${{ runner.temp }}/.bun/bin
|
||||
mv ${target}/bun* ${{ runner.temp }}/.bun/bin/
|
||||
chmod +x ${{ runner.temp }}/.bun/bin/*
|
||||
ln -fs ${{ runner.temp }}/.bun/bin/bun ${{ runner.temp }}/.bun/bin/bunx
|
||||
echo "${{ runner.temp }}/.bun/bin" >> ${GITHUB_PATH}
|
||||
|
||||
60
.github/workflows/clang-format.yml
vendored
60
.github/workflows/clang-format.yml
vendored
@@ -1,60 +0,0 @@
|
||||
name: clang-format
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/clang-format.yml"
|
||||
- ".clang-format"
|
||||
- "package.json"
|
||||
- "scripts/**"
|
||||
- "cmake/**"
|
||||
- "src/**/*.c"
|
||||
- "src/**/*.cpp"
|
||||
- "src/**/*.h"
|
||||
- "packages/**/*.c"
|
||||
- "packages/**/*.cpp"
|
||||
- "packages/**/*.h"
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.27"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
name: clang-format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
.clang-format
|
||||
package.json
|
||||
scripts
|
||||
cmake
|
||||
src
|
||||
packages
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- name: Install LLVM
|
||||
run: |
|
||||
curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s -- ${{ env.LLVM_VERSION_MAJOR }} all
|
||||
- name: Clang Format
|
||||
env:
|
||||
ENABLE_CCACHE: OFF
|
||||
LLVM_VERSION: ${{ env.LLVM_VERSION }}
|
||||
run: |
|
||||
bun run clang-format:diff
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "`bun run clang-format`"
|
||||
60
.github/workflows/clang-tidy.yml
vendored
60
.github/workflows/clang-tidy.yml
vendored
@@ -1,60 +0,0 @@
|
||||
name: clang-tidy
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/clang-tidy.yml"
|
||||
- ".clang-tidy"
|
||||
- "package.json"
|
||||
- "scripts/**"
|
||||
- "cmake/**"
|
||||
- "src/**/*.c"
|
||||
- "src/**/*.cpp"
|
||||
- "src/**/*.h"
|
||||
- "packages/**/*.c"
|
||||
- "packages/**/*.cpp"
|
||||
- "packages/**/*.h"
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.27"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
jobs:
|
||||
clang-tidy:
|
||||
name: clang-tidy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
.clang-tidy
|
||||
package.json
|
||||
scripts
|
||||
cmake
|
||||
src
|
||||
packages
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- name: Install LLVM
|
||||
run: |
|
||||
curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s -- ${{ env.LLVM_VERSION_MAJOR }} all
|
||||
- name: Clang Tidy
|
||||
env:
|
||||
ENABLE_CCACHE: OFF
|
||||
LLVM_VERSION: ${{ env.LLVM_VERSION }}
|
||||
run: |
|
||||
bun run clang-tidy:diff
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "`bun run clang-tidy`"
|
||||
61
.github/workflows/format.yml
vendored
Normal file
61
.github/workflows/format.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: Format
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: format-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && inputs.run-id || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run-id:
|
||||
type: string
|
||||
description: The workflow ID to download artifacts (skips the build step)
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
format:
|
||||
name: Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.prettierrc-ci
|
||||
.github
|
||||
.vscode
|
||||
src
|
||||
scripts
|
||||
packages
|
||||
test
|
||||
bench
|
||||
package.json
|
||||
bun.lockb
|
||||
.clang-format
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.25"
|
||||
- name: Setup Zig
|
||||
uses: mlugg/setup-zig@v1
|
||||
with:
|
||||
version: 0.13.0
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
bun install
|
||||
- name: Format
|
||||
run: |
|
||||
bun fmt
|
||||
- name: Format Zig
|
||||
run: |
|
||||
bun fmt:zig
|
||||
- name: Format Cpp
|
||||
run: |
|
||||
bun fmt:cpp
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Apply formatting changes
|
||||
49
.github/workflows/prettier-format.yml
vendored
49
.github/workflows/prettier-format.yml
vendored
@@ -1,49 +0,0 @@
|
||||
name: prettier-format
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/prettier-format.yml"
|
||||
- "package.json"
|
||||
- "scripts/**"
|
||||
- "**.yml"
|
||||
- "**.json"
|
||||
- "**.js"
|
||||
- "**.jsx"
|
||||
- "**.ts"
|
||||
- "**.tsx"
|
||||
- "**.mjs"
|
||||
- "**.cjs"
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.27"
|
||||
|
||||
jobs:
|
||||
prettier-format:
|
||||
name: prettier-format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- name: Setup Dependencies
|
||||
run: |
|
||||
bun install
|
||||
- name: Prettier Format
|
||||
env:
|
||||
ENABLE_CCACHE: OFF
|
||||
SKIP_LLVM: ON
|
||||
run: |
|
||||
bun run prettier:diff
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "`bun run prettier:extra`"
|
||||
56
.github/workflows/run-format.yml
vendored
Normal file
56
.github/workflows/run-format.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Format
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
zig-version:
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
format:
|
||||
name: Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.prettierrc-ci
|
||||
.github
|
||||
.vscode
|
||||
src
|
||||
scripts
|
||||
packages
|
||||
test
|
||||
bench
|
||||
package.json
|
||||
bun.lockb
|
||||
.clang-format
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.25"
|
||||
- name: Setup Zig
|
||||
uses: mlugg/setup-zig@v1
|
||||
with:
|
||||
version: ${{ inputs.zig-version }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
bun install
|
||||
- name: Format
|
||||
run: |
|
||||
bun fmt
|
||||
- name: Format Zig
|
||||
run: |
|
||||
bun fmt:zig
|
||||
- name: Format Cpp
|
||||
run: |
|
||||
bun fmt:cpp
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Apply formatting changes
|
||||
48
.github/workflows/zig-format.yml
vendored
48
.github/workflows/zig-format.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: zig-format
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/zig-format.yml"
|
||||
- "package.json"
|
||||
- "scripts/**"
|
||||
- "cmake/**"
|
||||
- "src/**/*.zig"
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.27"
|
||||
|
||||
jobs:
|
||||
zig-format:
|
||||
name: zig-format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
package.json
|
||||
scripts
|
||||
cmake
|
||||
src
|
||||
packages
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- name: Zig Format
|
||||
env:
|
||||
ENABLE_CCACHE: OFF
|
||||
SKIP_LLVM: ON
|
||||
run: |
|
||||
bun run zig-format:diff
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "`bun run zig-format`"
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -142,6 +142,9 @@ test/node.js/upstream
|
||||
scripts/env.local
|
||||
*.generated.ts
|
||||
|
||||
# Temporary files
|
||||
/tmp
|
||||
|
||||
# Dependencies
|
||||
/vendor
|
||||
|
||||
|
||||
31
.prettierrc-ci
Normal file
31
.prettierrc-ci
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 120,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"quoteProps": "preserve",
|
||||
"plugins": [
|
||||
"prettier-plugin-organize-imports"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
".vscode/*.json"
|
||||
],
|
||||
"options": {
|
||||
"parser": "jsonc",
|
||||
"quoteProps": "preserve",
|
||||
"singleQuote": false,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.md"
|
||||
],
|
||||
"options": {
|
||||
"printWidth": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -52,15 +52,12 @@
|
||||
"cmake.configureOnOpen": false,
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"[cpp]": {
|
||||
"editor.tabSize": 4,
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
},
|
||||
"[c]": {
|
||||
"editor.tabSize": 4,
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
},
|
||||
"[h]": {
|
||||
"editor.tabSize": 4,
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
},
|
||||
"clangd.arguments": ["-header-insertion=never"],
|
||||
|
||||
52
.vscode/tasks.json
vendored
52
.vscode/tasks.json
vendored
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Install Dependencies",
|
||||
"command": "scripts/all-dependencies.sh",
|
||||
"windows": {
|
||||
"command": "scripts/all-dependencies.ps1",
|
||||
},
|
||||
"icon": {
|
||||
"id": "arrow-down",
|
||||
},
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Setup Environment",
|
||||
"dependsOn": ["Install Dependencies"],
|
||||
"command": "scripts/setup.sh",
|
||||
"windows": {
|
||||
"command": "scripts/setup.ps1",
|
||||
},
|
||||
"icon": {
|
||||
"id": "check",
|
||||
},
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Build Bun",
|
||||
"dependsOn": ["Setup Environment"],
|
||||
"command": "bun",
|
||||
"args": ["run", "build"],
|
||||
"icon": {
|
||||
"id": "gear",
|
||||
},
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
},
|
||||
"isBuildCommand": true,
|
||||
"runOptions": {
|
||||
"instanceLimit": 1,
|
||||
"reevaluateOnRerun": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -30,7 +30,6 @@ include(CompilerFlags)
|
||||
|
||||
# --- Tools ---
|
||||
|
||||
include(SetupGit)
|
||||
include(SetupBuildkite)
|
||||
include(SetupBun)
|
||||
include(SetupEsbuild)
|
||||
@@ -39,6 +38,21 @@ include(SetupRust)
|
||||
|
||||
# --- Targets ---
|
||||
|
||||
include(BuildBoringSSL)
|
||||
include(BuildBrotli)
|
||||
include(BuildCares)
|
||||
include(BuildLibDeflate)
|
||||
include(BuildLibuv)
|
||||
include(BuildLolHtml)
|
||||
include(BuildLshpack)
|
||||
include(BuildMimalloc)
|
||||
include(BuildPicoHTTPParser)
|
||||
include(BuildTinyCC)
|
||||
include(BuildSQLite)
|
||||
include(BuildWebKit)
|
||||
include(BuildZlib)
|
||||
include(BuildLibArchive) # must be loaded after zlib
|
||||
include(BuildZstd)
|
||||
include(BuildBun)
|
||||
|
||||
# --- Analysis ---
|
||||
@@ -46,4 +60,3 @@ include(BuildBun)
|
||||
include(RunClangFormat)
|
||||
include(RunClangTidy)
|
||||
include(RunZigFormat)
|
||||
include(RunPrettier)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { bench, run } from "mitata";
|
||||
const crypto = require("node:crypto");
|
||||
|
||||
const keyPair = crypto.generateKeyPairSync("rsa", {
|
||||
modulusLength: 2048,
|
||||
publicKeyEncoding: {
|
||||
type: "spki",
|
||||
format: "pem",
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
},
|
||||
});
|
||||
|
||||
// Max message size for 2048-bit RSA keys
|
||||
const plaintext = crypto.getRandomValues(Buffer.alloc(245));
|
||||
|
||||
bench("RSA sign RSA_PKCS1_PADDING round-trip", () => {
|
||||
const sig = crypto.privateEncrypt(keyPair.privateKey, plaintext);
|
||||
crypto.publicDecrypt(keyPair.publicKey, sig);
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,8 +1,6 @@
|
||||
# clang: https://clang.llvm.org/docs/CommandGuide/clang.html
|
||||
# clang-cl: https://clang.llvm.org/docs/UsersManual.html#id11
|
||||
|
||||
# --- Macros ---
|
||||
|
||||
macro(setb variable)
|
||||
if(${variable})
|
||||
set(${variable} ON)
|
||||
@@ -11,20 +9,20 @@ macro(setb variable)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(targets WIN32 APPLE UNIX LINUX)
|
||||
|
||||
foreach(target ${targets})
|
||||
setb(${target})
|
||||
set(bvariables WIN32 APPLE UNIX LINUX)
|
||||
foreach(bvariable ${bvariables})
|
||||
setb(${bvariable})
|
||||
endforeach()
|
||||
|
||||
# --- CPU target ---
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM|arm64|ARM64|aarch64|AARCH64")
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64")
|
||||
if(APPLE)
|
||||
register_compiler_flags(-mcpu=apple-m1)
|
||||
else()
|
||||
register_compiler_flags(-march=armv8-a+crc -mtune=ampere1)
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|X86_64|x64|X64|amd64|AMD64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|AMD64|x86_64|X86_64|x64|X64")
|
||||
if(ENABLE_BASELINE)
|
||||
register_compiler_flags(-march=nehalem)
|
||||
else()
|
||||
@@ -35,6 +33,7 @@ else()
|
||||
endif()
|
||||
|
||||
# --- MSVC runtime ---
|
||||
|
||||
if(WIN32)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Use static MSVC runtime"
|
||||
@@ -45,6 +44,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# --- Optimization level ---
|
||||
|
||||
if(DEBUG)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Disable optimization"
|
||||
@@ -66,6 +66,7 @@ else()
|
||||
endif()
|
||||
|
||||
# --- Debug level ---
|
||||
|
||||
if(WIN32)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Enable debug symbols (.pdb)"
|
||||
@@ -97,6 +98,7 @@ endif()
|
||||
# -fno-eliminate-unused-debug-types # Don't eliminate unused debug symbols
|
||||
|
||||
# --- C/C++ flags ---
|
||||
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Disable C/C++ exceptions"
|
||||
-fno-exceptions ${UNIX}
|
||||
@@ -104,8 +106,8 @@ register_compiler_flags(
|
||||
)
|
||||
|
||||
register_compiler_flags(
|
||||
LANGUAGE CXX
|
||||
DESCRIPTION "Disable C++ static destructors"
|
||||
LANGUAGES CXX
|
||||
-Xclang ${WIN32}
|
||||
-fno-c++-static-destructors
|
||||
)
|
||||
@@ -149,9 +151,9 @@ register_compiler_flags(
|
||||
/Gw ${WIN32}
|
||||
)
|
||||
|
||||
# having this enabled in debug mode on macOS >=14 causes libarchive to fail to configure with the error:
|
||||
# This causes libarchive to fail on macOS, with the error:
|
||||
# > pid_t doesn't exist on this platform?
|
||||
if((DEBUG AND LINUX) OR((NOT DEBUG) AND UNIX))
|
||||
if((DEBUG AND LINUX) OR ((NOT DEBUG) AND UNIX))
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Emit an address-significance table"
|
||||
-faddrsig
|
||||
@@ -171,6 +173,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# --- Linker flags ---
|
||||
|
||||
if(LINUX)
|
||||
register_linker_flags(
|
||||
DESCRIPTION "Disable relocation read-only (RELRO)"
|
||||
@@ -182,6 +185,7 @@ endif()
|
||||
|
||||
# Note: This is a helpful guide about assertions:
|
||||
# https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++
|
||||
|
||||
if(ENABLE_ASSERTIONS)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Do not eliminate null-pointer checks"
|
||||
@@ -227,6 +231,7 @@ else()
|
||||
endif()
|
||||
|
||||
# --- Diagnostics ---
|
||||
|
||||
if(UNIX)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Enable color diagnostics"
|
||||
@@ -240,6 +245,7 @@ register_compiler_flags(
|
||||
)
|
||||
|
||||
# --- LTO ---
|
||||
|
||||
if(ENABLE_LTO)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Enable link-time optimization (LTO)"
|
||||
@@ -249,8 +255,8 @@ if(ENABLE_LTO)
|
||||
|
||||
if(UNIX)
|
||||
register_compiler_flags(
|
||||
LANGUAGE CXX
|
||||
DESCRIPTION "Enable virtual tables"
|
||||
LANGUAGES CXX
|
||||
-fforce-emit-vtables
|
||||
-fwhole-program-vtables
|
||||
)
|
||||
@@ -265,6 +271,7 @@ if(ENABLE_LTO)
|
||||
endif()
|
||||
|
||||
# --- Remapping ---
|
||||
|
||||
if(UNIX)
|
||||
register_compiler_flags(
|
||||
DESCRIPTION "Remap source files"
|
||||
@@ -282,6 +289,12 @@ if(ENABLE_VALGRIND AND ARCH STREQUAL "x64")
|
||||
register_compiler_definitions(__SSE4_2__=0)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# The $NOCANCEL variants of various system calls are activated by compiling
|
||||
# with __DARWIN_NON_CANCELABLE, which prevents them from being pthread cancellation points.
|
||||
register_compiler_definitions(__DARWIN_NON_CANCELABLE=1)
|
||||
endif()
|
||||
|
||||
# --- Other ---
|
||||
|
||||
# Workaround for CMake and clang-cl bug.
|
||||
|
||||
@@ -124,19 +124,12 @@ optionx(CACHE_STRATEGY "read-write|read-only|write-only|none" "The strategy to u
|
||||
optionx(CI BOOL "If CI is enabled" DEFAULT OFF)
|
||||
|
||||
if(CI)
|
||||
set(WARNING FATAL_ERROR)
|
||||
set(DEFAULT_VENDOR_PATH ${CACHE_PATH}/vendor)
|
||||
else()
|
||||
set(WARNING WARNING)
|
||||
set(DEFAULT_VENDOR_PATH ${CWD}/vendor)
|
||||
endif()
|
||||
|
||||
# TODO: This causes flaky zig builds in CI, so temporarily disable it.
|
||||
# if(CI)
|
||||
# set(DEFAULT_VENDOR_PATH ${CACHE_PATH}/vendor)
|
||||
# else()
|
||||
# set(DEFAULT_VENDOR_PATH ${CWD}/vendor)
|
||||
# endif()
|
||||
|
||||
optionx(VENDOR_PATH FILEPATH "The path to the vendor directory" DEFAULT ${CWD}/vendor)
|
||||
optionx(VENDOR_PATH FILEPATH "The path to the vendor directory" DEFAULT ${DEFAULT_VENDOR_PATH})
|
||||
optionx(TMP_PATH FILEPATH "The path to the temporary directory" DEFAULT ${BUILD_PATH}/tmp)
|
||||
|
||||
optionx(FRESH BOOL "Set when --fresh is used" DEFAULT OFF)
|
||||
@@ -305,19 +298,18 @@ endfunction()
|
||||
# SOURCES string[] - The files that this command depends on
|
||||
# OUTPUTS string[] - The files that this command produces
|
||||
# ARTIFACTS string[] - The files that this command produces, and uploads as an artifact in CI
|
||||
# ALWAYS_RUN bool - If true, the command will always run
|
||||
# TARGET string - The target to register the command with
|
||||
# TARGET_PHASE string - The target phase to register the command with (e.g. PRE_BUILD, PRE_LINK, POST_BUILD)
|
||||
# GROUP string - The group to register the command with (e.g. similar to JOB_POOL)
|
||||
function(register_command)
|
||||
set(options ALWAYS_RUN)
|
||||
set(args COMMENT CWD TARGET TARGET_PHASE GROUP)
|
||||
set(multiArgs COMMAND ENVIRONMENT TARGETS SOURCES OUTPUTS ARTIFACTS)
|
||||
cmake_parse_arguments(CMD "${options}" "${args}" "${multiArgs}" ${ARGN})
|
||||
cmake_parse_arguments(CMD "" "${args}" "${multiArgs}" ${ARGN})
|
||||
|
||||
if(NOT CMD_COMMAND)
|
||||
message(FATAL_ERROR "register_command: COMMAND is required")
|
||||
endif()
|
||||
parse_list(CMD_COMMAND CMD_COMMAND)
|
||||
|
||||
if(NOT CMD_CWD)
|
||||
set(CMD_CWD ${CWD})
|
||||
@@ -356,10 +348,6 @@ function(register_command)
|
||||
list(APPEND CMD_EFFECTIVE_DEPENDS ${source})
|
||||
endforeach()
|
||||
|
||||
if(NOT CMD_EFFECTIVE_DEPENDS AND NOT CMD_ALWAYS_RUN)
|
||||
message(FATAL_ERROR "register_command: TARGETS or SOURCES is required")
|
||||
endif()
|
||||
|
||||
set(CMD_EFFECTIVE_OUTPUTS)
|
||||
|
||||
foreach(output ${CMD_OUTPUTS})
|
||||
@@ -383,12 +371,13 @@ function(register_command)
|
||||
foreach(output ${CMD_EFFECTIVE_OUTPUTS})
|
||||
get_source_file_property(generated ${output} GENERATED)
|
||||
if(generated)
|
||||
list(REMOVE_ITEM CMD_EFFECTIVE_OUTPUTS ${output})
|
||||
list(APPEND CMD_EFFECTIVE_OUTPUTS ${output}.always_run_${CMD_TARGET})
|
||||
add_custom_target(${CMD_TARGET})
|
||||
message(WARNING "Skipping ${CMD_TARGET}, since ${output} is generated by another target")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CMD_ALWAYS_RUN)
|
||||
if(NOT CMD_EFFECTIVE_OUTPUTS)
|
||||
list(APPEND CMD_EFFECTIVE_OUTPUTS ${CMD_CWD}/.always_run_${CMD_TARGET})
|
||||
endif()
|
||||
|
||||
@@ -410,10 +399,6 @@ function(register_command)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT CMD_EFFECTIVE_OUTPUTS)
|
||||
message(FATAL_ERROR "register_command: OUTPUTS or ARTIFACTS is required, or set ALWAYS_RUN")
|
||||
endif()
|
||||
|
||||
if(CMD_TARGET)
|
||||
if(TARGET ${CMD_TARGET})
|
||||
message(FATAL_ERROR "register_command: TARGET is already registered: ${CMD_TARGET}")
|
||||
@@ -426,6 +411,8 @@ function(register_command)
|
||||
if(TARGET clone-${CMD_TARGET})
|
||||
add_dependencies(${CMD_TARGET} clone-${CMD_TARGET})
|
||||
endif()
|
||||
set_property(TARGET ${CMD_TARGET} PROPERTY OUTPUT ${CMD_EFFECTIVE_OUTPUTS} APPEND)
|
||||
set_property(TARGET ${CMD_TARGET} PROPERTY DEPENDS ${CMD_EFFECTIVE_DEPENDS} APPEND)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
@@ -596,298 +583,664 @@ function(register_repository)
|
||||
${CMAKE_COMMAND}
|
||||
-DGIT_PATH=${GIT_PATH}
|
||||
-DGIT_REPOSITORY=${GIT_REPOSITORY}
|
||||
-DGIT_NAME=${GIT_NAME}
|
||||
-DGIT_COMMIT=${GIT_COMMIT}
|
||||
-DGIT_TAG=${GIT_TAG}
|
||||
-DGIT_BRANCH=${GIT_BRANCH}
|
||||
-DGIT_TAG=${GIT_TAG}
|
||||
-DGIT_COMMIT=${GIT_COMMIT}
|
||||
-DGIT_NAME=${GIT_NAME}
|
||||
-P ${CWD}/cmake/scripts/GitClone.cmake
|
||||
OUTPUTS
|
||||
${GIT_PATH}
|
||||
${GIT_EFFECTIVE_OUTPUTS}
|
||||
)
|
||||
|
||||
register_outputs(TARGET clone-${GIT_NAME} ${GIT_PATH})
|
||||
endfunction()
|
||||
|
||||
# register_cmake_command()
|
||||
function(parse_language variable)
|
||||
if(NOT ${variable})
|
||||
set(${variable} C CXX PARENT_SCOPE)
|
||||
endif()
|
||||
foreach(value ${${variable}})
|
||||
if(NOT value MATCHES "^(C|CXX)$")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid language: \"${value}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(parse_target variable)
|
||||
foreach(value ${${variable}})
|
||||
if(NOT TARGET ${value})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid target: \"${value}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(parse_path variable)
|
||||
foreach(value ${${variable}})
|
||||
if(NOT IS_ABSOLUTE ${value})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: ${variable} is not an absolute path: \"${value}\"")
|
||||
endif()
|
||||
if(NOT ${value} MATCHES "^(${CWD}|${BUILD_PATH}|${CACHE_PATH}|${VENDOR_PATH})")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: ${variable} is not in the source, build, cache, or vendor path: \"${value}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(parse_list list variable)
|
||||
set(result)
|
||||
|
||||
macro(check_expression)
|
||||
if(DEFINED expression)
|
||||
if(NOT (${expression}))
|
||||
list(POP_BACK result)
|
||||
endif()
|
||||
unset(expression)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
foreach(item ${${list}})
|
||||
if(item MATCHES "^(ON|OFF|AND|OR|NOT)$")
|
||||
set(expression ${expression} ${item})
|
||||
else()
|
||||
check_expression()
|
||||
list(APPEND result ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
check_expression()
|
||||
|
||||
set(${variable} ${result} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# register_target()
|
||||
# Description:
|
||||
# Registers a command that builds an external CMake project.
|
||||
# Registers a target that does nothing.
|
||||
# Arguments:
|
||||
# TARGET string - The target to register the command with
|
||||
# ARGS string[] - The arguments to pass to CMake (e.g. -DKEY=VALUE)
|
||||
# CWD string - The directory where the CMake files are located
|
||||
# BUILD_PATH string - The path to build the project to
|
||||
# LIB_PATH string - The path to the libraries
|
||||
# TARGETS string[] - The targets to build from CMake
|
||||
# LIBRARIES string[] - The libraries that are built
|
||||
# INCLUDES string[] - The include paths
|
||||
function(register_cmake_command)
|
||||
set(args TARGET CWD BUILD_PATH LIB_PATH)
|
||||
set(multiArgs ARGS TARGETS LIBRARIES INCLUDES)
|
||||
# Use "MAKE" instead of "CMAKE" to prevent conflicts with CMake's own CMAKE_* variables
|
||||
cmake_parse_arguments(MAKE "" "${args}" "${multiArgs}" ${ARGN})
|
||||
# target string - The name of the target
|
||||
function(register_target target)
|
||||
add_custom_target(${target})
|
||||
|
||||
if(NOT MAKE_TARGET)
|
||||
message(FATAL_ERROR "register_cmake_command: TARGET is required")
|
||||
endif()
|
||||
|
||||
if(TARGET ${MAKE_TARGET})
|
||||
message(FATAL_ERROR "register_cmake_command: TARGET is already a target: ${MAKE_TARGET}")
|
||||
endif()
|
||||
|
||||
if(NOT MAKE_CWD)
|
||||
set(MAKE_CWD ${VENDOR_PATH}/${MAKE_TARGET})
|
||||
endif()
|
||||
|
||||
if(NOT MAKE_BUILD_PATH)
|
||||
set(MAKE_BUILD_PATH ${BUILD_PATH}/${MAKE_TARGET})
|
||||
endif()
|
||||
|
||||
if(MAKE_LIB_PATH)
|
||||
set(MAKE_LIB_PATH ${MAKE_BUILD_PATH}/${MAKE_LIB_PATH})
|
||||
else()
|
||||
set(MAKE_LIB_PATH ${MAKE_BUILD_PATH})
|
||||
endif()
|
||||
|
||||
set(MAKE_EFFECTIVE_ARGS -B${MAKE_BUILD_PATH} ${CMAKE_ARGS})
|
||||
|
||||
set(setFlags GENERATOR BUILD_TYPE)
|
||||
set(appendFlags C_FLAGS CXX_FLAGS LINKER_FLAGS)
|
||||
set(specialFlags POSITION_INDEPENDENT_CODE)
|
||||
set(flags ${setFlags} ${appendFlags} ${specialFlags})
|
||||
|
||||
foreach(arg ${MAKE_ARGS})
|
||||
foreach(flag ${flags})
|
||||
if(arg MATCHES "-DCMAKE_${flag}=(.*)")
|
||||
if(DEFINED MAKE_${flag})
|
||||
message(FATAL_ERROR "register_cmake_command: CMAKE_${flag} was already set: \"${MAKE_${flag}}\"")
|
||||
endif()
|
||||
set(MAKE_${flag} ${CMAKE_MATCH_1})
|
||||
set(${arg}_USED ON)
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT ${arg}_USED)
|
||||
list(APPEND MAKE_EFFECTIVE_ARGS ${arg})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(flag ${setFlags})
|
||||
if(NOT DEFINED MAKE_${flag} AND DEFINED CMAKE_${flag})
|
||||
set(MAKE_${flag} ${CMAKE_${flag}})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(flag ${appendFlags})
|
||||
if(MAKE_${flag})
|
||||
set(MAKE_${flag} "${CMAKE_${flag}} ${MAKE_${flag}}")
|
||||
else()
|
||||
set(MAKE_${flag} ${CMAKE_${flag}})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(MAKE_POSITION_INDEPENDENT_CODE AND NOT WIN32)
|
||||
set(MAKE_C_FLAGS "${MAKE_C_FLAGS} -fPIC")
|
||||
set(MAKE_CXX_FLAGS "${MAKE_CXX_FLAGS} -fPIC")
|
||||
elseif(APPLE)
|
||||
set(MAKE_C_FLAGS "${MAKE_C_FLAGS} -fno-pic -fno-pie")
|
||||
set(MAKE_CXX_FLAGS "${MAKE_CXX_FLAGS} -fno-pic -fno-pie")
|
||||
endif()
|
||||
|
||||
set(effectiveFlags ${setFlags} ${appendFlags})
|
||||
foreach(flag ${effectiveFlags})
|
||||
list(APPEND MAKE_EFFECTIVE_ARGS "-DCMAKE_${flag}=${MAKE_${flag}}")
|
||||
endforeach()
|
||||
|
||||
if(DEFINED FRESH)
|
||||
list(APPEND MAKE_EFFECTIVE_ARGS --fresh)
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
COMMENT "Configuring ${MAKE_TARGET}"
|
||||
TARGET configure-${MAKE_TARGET}
|
||||
COMMAND ${CMAKE_COMMAND} ${MAKE_EFFECTIVE_ARGS}
|
||||
CWD ${MAKE_CWD}
|
||||
OUTPUTS ${MAKE_BUILD_PATH}/CMakeCache.txt
|
||||
)
|
||||
|
||||
if(TARGET clone-${MAKE_TARGET})
|
||||
add_dependencies(configure-${MAKE_TARGET} clone-${MAKE_TARGET})
|
||||
endif()
|
||||
|
||||
set(MAKE_BUILD_ARGS --build ${MAKE_BUILD_PATH} --config ${MAKE_BUILD_TYPE})
|
||||
|
||||
set(MAKE_EFFECTIVE_LIBRARIES)
|
||||
set(MAKE_ARTIFACTS)
|
||||
foreach(lib ${MAKE_LIBRARIES})
|
||||
if(lib MATCHES "^(WIN32|UNIX|APPLE)$")
|
||||
if(${lib})
|
||||
continue()
|
||||
else()
|
||||
list(POP_BACK MAKE_ARTIFACTS)
|
||||
endif()
|
||||
else()
|
||||
list(APPEND MAKE_EFFECTIVE_LIBRARIES ${lib})
|
||||
if(lib MATCHES "\\.")
|
||||
list(APPEND MAKE_ARTIFACTS ${MAKE_LIB_PATH}/${lib})
|
||||
else()
|
||||
list(APPEND MAKE_ARTIFACTS ${MAKE_LIB_PATH}/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT MAKE_TARGETS)
|
||||
set(MAKE_TARGETS ${MAKE_EFFECTIVE_LIBRARIES})
|
||||
endif()
|
||||
|
||||
foreach(target ${MAKE_TARGETS})
|
||||
list(APPEND MAKE_BUILD_ARGS --target ${target})
|
||||
endforeach()
|
||||
|
||||
set(MAKE_EFFECTIVE_INCLUDES)
|
||||
foreach(include ${MAKE_INCLUDES})
|
||||
if(include STREQUAL ".")
|
||||
list(APPEND MAKE_EFFECTIVE_INCLUDES ${MAKE_CWD})
|
||||
else()
|
||||
list(APPEND MAKE_EFFECTIVE_INCLUDES ${MAKE_CWD}/${include})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
register_command(
|
||||
COMMENT "Building ${MAKE_TARGET}"
|
||||
TARGET ${MAKE_TARGET}
|
||||
TARGETS configure-${MAKE_TARGET}
|
||||
COMMAND ${CMAKE_COMMAND} ${MAKE_BUILD_ARGS}
|
||||
CWD ${MAKE_CWD}
|
||||
ARTIFACTS ${MAKE_ARTIFACTS}
|
||||
)
|
||||
|
||||
if(MAKE_EFFECTIVE_INCLUDES)
|
||||
target_include_directories(${bun} PRIVATE ${MAKE_EFFECTIVE_INCLUDES})
|
||||
if(TARGET clone-${MAKE_TARGET} AND NOT BUN_LINK_ONLY)
|
||||
add_dependencies(${bun} clone-${MAKE_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# HACK: Workaround for duplicate symbols when linking mimalloc.o
|
||||
# >| duplicate symbol '_mi_page_queue_append(mi_heap_s*, mi_page_queue_s*, mi_page_queue_s*)' in:
|
||||
# >| mimalloc/CMakeFiles/mimalloc-obj.dir/src/static.c.o
|
||||
# >| ld: 287 duplicate symbols for architecture arm64
|
||||
if(NOT BUN_LINK_ONLY OR NOT MAKE_ARTIFACTS MATCHES "static.c.o")
|
||||
target_link_libraries(${bun} PRIVATE ${MAKE_ARTIFACTS})
|
||||
endif()
|
||||
|
||||
if(BUN_LINK_ONLY)
|
||||
target_sources(${bun} PRIVATE ${MAKE_ARTIFACTS})
|
||||
endif()
|
||||
set(${target} ${target} PARENT_SCOPE)
|
||||
set(${target}_CWD ${CWD} PARENT_SCOPE)
|
||||
set(${target}_BUILD_PATH ${BUILD_PATH} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# register_compiler_flag()
|
||||
# register_vendor_target()
|
||||
# Description:
|
||||
# Registers a target that does nothing.
|
||||
# Arguments:
|
||||
# target string - The name of the target
|
||||
function(register_vendor_target target)
|
||||
add_custom_target(${target})
|
||||
|
||||
set(${target} ${target} PARENT_SCOPE)
|
||||
set(${target}_CWD ${VENDOR_PATH}/${target} PARENT_SCOPE)
|
||||
set(${target}_BUILD_PATH ${BUILD_PATH}/vendor/${target} PARENT_SCOPE)
|
||||
|
||||
if(NOT TARGET vendor)
|
||||
add_custom_target(vendor)
|
||||
endif()
|
||||
add_dependencies(vendor ${target})
|
||||
endfunction()
|
||||
|
||||
# register_outputs()
|
||||
# Description:
|
||||
# Registers outputs that are built from a target.
|
||||
# Arguments:
|
||||
# TARGET string - The target that builds the outputs
|
||||
# outputs string[] - The list of outputs
|
||||
function(register_outputs)
|
||||
set(args TARGET PATH)
|
||||
cmake_parse_arguments(OUTPUT "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(OUTPUT_TARGET)
|
||||
parse_list(OUTPUT_UNPARSED_ARGUMENTS OUTPUT_PATHS)
|
||||
parse_path(OUTPUT_PATHS)
|
||||
|
||||
foreach(path ${OUTPUT_PATHS})
|
||||
set_property(GLOBAL PROPERTY ${path} ${OUTPUT_TARGET} APPEND)
|
||||
set_property(TARGET ${OUTPUT_TARGET} PROPERTY OUTPUT ${path} APPEND)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# register_inputs()
|
||||
# Description:
|
||||
# Registers inputs that are required to build a target.
|
||||
# Arguments:
|
||||
# TARGET string - The target that builds the inputs
|
||||
# inputs string[] - The list of inputs
|
||||
function(register_inputs)
|
||||
set(args TARGET)
|
||||
cmake_parse_arguments(INPUT "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(INPUT_TARGET)
|
||||
parse_list(INPUT_UNPARSED_ARGUMENTS INPUT_PATHS)
|
||||
|
||||
foreach(path ${INPUT_PATHS})
|
||||
set(search ${path})
|
||||
set(found OFF)
|
||||
while(search)
|
||||
if(EXISTS ${search})
|
||||
set(found ON)
|
||||
break()
|
||||
endif()
|
||||
get_property(target GLOBAL PROPERTY ${search})
|
||||
if(TARGET ${target})
|
||||
set(found ON)
|
||||
set_property(TARGET ${target} PROPERTY OUTPUT ${path} APPEND)
|
||||
break()
|
||||
endif()
|
||||
get_filename_component(next_search ${search} DIRECTORY)
|
||||
if(next_search STREQUAL search OR next_search STREQUAL ${CWD} OR next_search STREQUAL ${VENDOR_PATH})
|
||||
break()
|
||||
endif()
|
||||
set(search ${next_search})
|
||||
endwhile()
|
||||
if(NOT found)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: ${path} does not have a target")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# upload_artifacts()
|
||||
# Description:
|
||||
# Uploads artifacts after a target has been built.
|
||||
# Arguments:
|
||||
# TARGET string - The target to upload artifacts for
|
||||
# artifacts string[] - The artifacts to upload
|
||||
function(upload_artifacts)
|
||||
set(args TARGET)
|
||||
cmake_parse_arguments(ARTIFACT "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(ARTIFACT_TARGET)
|
||||
get_target_property(imported ${ARTIFACT_TARGET} IMPORTED)
|
||||
if(imported)
|
||||
return()
|
||||
endif()
|
||||
|
||||
parse_list(ARTIFACT_UNPARSED_ARGUMENTS ARTIFACT_PATHS)
|
||||
|
||||
foreach(artifact ${ARTIFACT_PATHS})
|
||||
file(RELATIVE_PATH filename ${BUILD_PATH} ${artifact})
|
||||
add_custom_command(
|
||||
TARGET ${ARTIFACT_TARGET} POST_BUILD
|
||||
COMMENT "Uploading ${filename}"
|
||||
COMMAND ${CMAKE_COMMAND} -E chdir ${BUILD_PATH} buildkite-agent artifact upload ${filename}
|
||||
)
|
||||
set_property(TARGET ${ARTIFACT_TARGET} PROPERTY OUTPUT ${artifact} APPEND)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
|
||||
# register_compiler_flags()
|
||||
# Description:
|
||||
# Registers a compiler flag, similar to `add_compile_options()`, but has more validation and features.
|
||||
# Arguments:
|
||||
# flags string[] - The flags to register
|
||||
# TARGET string - The target to register the flag (default: all)
|
||||
# LANGUAGE string - The language to register the flag (default: C, CXX)
|
||||
# DESCRIPTION string - The description of the flag
|
||||
# LANGUAGES string[] - The languages to register the flag (default: C, CXX)
|
||||
# TARGETS string[] - The targets to register the flag (default: all)
|
||||
# flags string[] - The flags to register
|
||||
function(register_compiler_flags)
|
||||
set(args DESCRIPTION)
|
||||
set(multiArgs LANGUAGES TARGETS)
|
||||
cmake_parse_arguments(COMPILER "" "${args}" "${multiArgs}" ${ARGN})
|
||||
set(args TARGET LANGUAGE DESCRIPTION)
|
||||
cmake_parse_arguments(COMPILER "" "${args}" "" ${ARGN})
|
||||
|
||||
if(NOT COMPILER_LANGUAGES)
|
||||
set(COMPILER_LANGUAGES C CXX)
|
||||
endif()
|
||||
parse_target(COMPILER_TARGET)
|
||||
parse_language(COMPILER_LANGUAGE)
|
||||
parse_list(COMPILER_UNPARSED_ARGUMENTS COMPILER_FLAGS)
|
||||
|
||||
set(COMPILER_FLAGS)
|
||||
foreach(flag ${COMPILER_UNPARSED_ARGUMENTS})
|
||||
if(flag STREQUAL "ON")
|
||||
continue()
|
||||
elseif(flag STREQUAL "OFF")
|
||||
list(POP_BACK COMPILER_FLAGS)
|
||||
elseif(flag MATCHES "^(-|/)")
|
||||
list(APPEND COMPILER_FLAGS ${flag})
|
||||
else()
|
||||
message(FATAL_ERROR "register_compiler_flags: Invalid flag: \"${flag}\"")
|
||||
foreach(flag ${COMPILER_FLAGS})
|
||||
if(NOT flag MATCHES "^(-|/)")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid flag: \"${flag}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(target ${COMPILER_TARGETS})
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "register_compiler_flags: \"${target}\" is not a target")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(lang ${COMPILER_LANGUAGES})
|
||||
foreach(language ${COMPILER_LANGUAGE})
|
||||
list(JOIN COMPILER_FLAGS " " COMPILER_FLAGS_STRING)
|
||||
|
||||
if(NOT COMPILER_TARGETS)
|
||||
set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
if(NOT COMPILER_TARGET)
|
||||
set(CMAKE_${language}_FLAGS "${CMAKE_${language}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
foreach(target ${COMPILER_TARGETS})
|
||||
set(${target}_CMAKE_${lang}_FLAGS "${${target}_CMAKE_${lang}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
foreach(target ${COMPILER_TARGET})
|
||||
set(${target}_CMAKE_${language}_FLAGS "${${target}_CMAKE_${language}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
foreach(lang ${COMPILER_LANGUAGES})
|
||||
foreach(language ${COMPILER_LANGUAGE})
|
||||
foreach(flag ${COMPILER_FLAGS})
|
||||
if(NOT COMPILER_TARGETS)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:${lang}>:${flag}>)
|
||||
if(NOT COMPILER_TARGET)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:${language}>:${flag}>)
|
||||
endif()
|
||||
|
||||
foreach(target ${COMPILER_TARGETS})
|
||||
foreach(target ${COMPILER_TARGET})
|
||||
get_target_property(type ${target} TYPE)
|
||||
if(type MATCHES "EXECUTABLE|LIBRARY")
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:${lang}>:${flag}>)
|
||||
get_target_property(imported ${target} IMPORTED)
|
||||
if(type MATCHES "EXECUTABLE|LIBRARY" AND NOT imported)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:${language}>:${flag}>)
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# register_compiler_definitions()
|
||||
# Description:
|
||||
# Registers a compiler definition, similar to `add_compile_definitions()`.
|
||||
# Arguments:
|
||||
# TARGET string - The target to register the definitions (default: all)
|
||||
# LANGUAGE string - The language to register the definitions (default: C, CXX)
|
||||
# DESCRIPTION string - The description of the definitions
|
||||
# definitions string[] - The definitions to register
|
||||
function(register_compiler_definitions)
|
||||
|
||||
set(args TARGET LANGUAGE DESCRIPTION)
|
||||
cmake_parse_arguments(COMPILER "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_language(COMPILER_LANGUAGE)
|
||||
parse_target(COMPILER_TARGET)
|
||||
parse_list(COMPILER_UNPARSED_ARGUMENTS COMPILER_DEFINITIONS)
|
||||
|
||||
foreach(definition ${COMPILER_DEFINITIONS})
|
||||
if(NOT definition MATCHES "^([A-Z_][A-Z0-9_]*)")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid definition: \"${definition}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(WIN32)
|
||||
list(TRANSFORM COMPILER_DEFINITIONS PREPEND "/D" OUTPUT_VARIABLE COMPILER_FLAGS)
|
||||
else()
|
||||
list(TRANSFORM COMPILER_DEFINITIONS PREPEND "-D" OUTPUT_VARIABLE COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
foreach(language ${COMPILER_LANGUAGE})
|
||||
list(JOIN COMPILER_FLAGS " " COMPILER_FLAGS_STRING)
|
||||
if(NOT COMPILER_TARGET)
|
||||
set(CMAKE_${language}_FLAGS "${CMAKE_${language}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endif()
|
||||
foreach(target ${COMPILER_TARGET})
|
||||
set(${target}_CMAKE_${language}_FLAGS "${${target}_CMAKE_${language}_FLAGS} ${COMPILER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
foreach(definition ${COMPILER_DEFINITIONS})
|
||||
foreach(language ${COMPILER_LANGUAGE})
|
||||
if(NOT COMPILER_TARGET)
|
||||
add_compile_definitions($<$<COMPILE_LANGUAGE:${language}>:${definition}>)
|
||||
endif()
|
||||
foreach(target ${COMPILER_TARGET})
|
||||
get_target_property(type ${target} TYPE)
|
||||
get_target_property(imported ${target} IMPORTED)
|
||||
if(type MATCHES "EXECUTABLE|LIBRARY" AND NOT imported)
|
||||
target_compile_definitions(${target} PRIVATE $<$<COMPILE_LANGUAGE:${language}>:${definition}>)
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# register_linker_flags()
|
||||
# Description:
|
||||
# Registers a linker flag, similar to `add_link_options()`.
|
||||
# Arguments:
|
||||
# flags string[] - The flags to register
|
||||
# TARGET string - The target to register the flag (default: all)
|
||||
# DESCRIPTION string - The description of the flag
|
||||
# flags string[] - The flags to register
|
||||
function(register_linker_flags)
|
||||
set(args DESCRIPTION)
|
||||
set(args TARGET DESCRIPTION)
|
||||
cmake_parse_arguments(LINKER "" "${args}" "" ${ARGN})
|
||||
|
||||
foreach(flag ${LINKER_UNPARSED_ARGUMENTS})
|
||||
if(flag STREQUAL "ON")
|
||||
continue()
|
||||
elseif(flag STREQUAL "OFF")
|
||||
list(POP_FRONT LINKER_FLAGS)
|
||||
elseif(flag MATCHES "^(-|/)")
|
||||
list(APPEND LINKER_FLAGS ${flag})
|
||||
else()
|
||||
message(FATAL_ERROR "register_linker_flags: Invalid flag: \"${flag}\"")
|
||||
parse_target(LINKER_TARGET)
|
||||
parse_list(LINKER_UNPARSED_ARGUMENTS LINKER_FLAGS)
|
||||
|
||||
foreach(flag ${LINKER_FLAGS})
|
||||
if(NOT flag MATCHES "^(-|/)")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid flag: \"${flag}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_link_options(${LINKER_FLAGS})
|
||||
list(JOIN LINKER_FLAGS " " LINKER_FLAGS_STRING)
|
||||
if(NOT LINKER_TARGET)
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${LINKER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endif()
|
||||
foreach(target ${LINKER_TARGET})
|
||||
set(${target}_CMAKE_LINKER_FLAGS "${${target}_CMAKE_LINKER_FLAGS} ${LINKER_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
|
||||
if(NOT LINKER_TARGET)
|
||||
add_link_options(${LINKER_FLAGS})
|
||||
endif()
|
||||
foreach(target ${LINKER_TARGET})
|
||||
get_target_property(type ${target} TYPE)
|
||||
if(type MATCHES "EXECUTABLE|LIBRARY")
|
||||
target_link_options(${target} PUBLIC ${LINKER_FLAGS})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(print_compiler_flags)
|
||||
get_property(targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS)
|
||||
set(languages C CXX)
|
||||
foreach(target ${targets})
|
||||
get_target_property(type ${target} TYPE)
|
||||
message(STATUS "Target: ${target}")
|
||||
foreach(lang ${languages})
|
||||
if(${target}_CMAKE_${lang}_FLAGS)
|
||||
message(STATUS " ${lang} Flags: ${${target}_CMAKE_${lang}_FLAGS}")
|
||||
# register_includes()
|
||||
# Description:
|
||||
# Registers a include directory, similar to `target_include_directories()`.
|
||||
# Arguments:
|
||||
# TARGET string - The target to register the include (default: all)
|
||||
# LANGUAGE string - The language to register the include (default: C, CXX)
|
||||
# DESCRIPTION string - The description of the include
|
||||
# paths string[] - The include paths to register
|
||||
function(register_includes)
|
||||
set(args TARGET LANGUAGE DESCRIPTION)
|
||||
cmake_parse_arguments(INCLUDE "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(INCLUDE_TARGET)
|
||||
parse_language(INCLUDE_LANGUAGE)
|
||||
parse_list(INCLUDE_UNPARSED_ARGUMENTS INCLUDE_PATHS)
|
||||
parse_path(INCLUDE_PATHS)
|
||||
|
||||
register_inputs(TARGET ${INCLUDE_TARGET} ${INCLUDE_PATHS})
|
||||
|
||||
list(TRANSFORM INCLUDE_PATHS PREPEND "-I" OUTPUT_VARIABLE INCLUDE_FLAGS)
|
||||
list(JOIN INCLUDE_FLAGS " " INCLUDE_FLAGS_STRING)
|
||||
|
||||
foreach(language ${INCLUDE_LANGUAGE})
|
||||
if(NOT INCLUDE_TARGET)
|
||||
set(CMAKE_${language}_FLAGS "${CMAKE_${language}_FLAGS} ${INCLUDE_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endif()
|
||||
foreach(target ${INCLUDE_TARGET})
|
||||
set(${target}_CMAKE_${language}_FLAGS "${${target}_CMAKE_${language}_FLAGS} ${INCLUDE_FLAGS_STRING}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
|
||||
if(NOT INCLUDE_TARGET)
|
||||
add_include_directories(${INCLUDE_PATHS})
|
||||
endif()
|
||||
foreach(target ${INCLUDE_TARGET})
|
||||
get_target_property(type ${target} TYPE)
|
||||
get_target_property(imported ${target} IMPORTED)
|
||||
if(type MATCHES "EXECUTABLE|LIBRARY" AND NOT imported)
|
||||
target_include_directories(${target} PUBLIC ${INCLUDE_PATHS})
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
foreach(lang ${languages})
|
||||
message(STATUS "Language: ${lang}")
|
||||
if(CMAKE_${lang}_FLAGS)
|
||||
message(STATUS " Flags: ${CMAKE_${lang}_FLAGS}")
|
||||
endfunction()
|
||||
|
||||
# register_libraries()
|
||||
# Description:
|
||||
# Registers libraries that are built from a target.
|
||||
# Arguments:
|
||||
# TARGET string - The target that builds the libraries
|
||||
# PATH string - The relative path to the libraries
|
||||
# VARIABLE string - The variable to set to the libraries
|
||||
# libraries string[] - The libraries to register
|
||||
function(register_libraries)
|
||||
set(args TARGET PATH VARIABLE)
|
||||
cmake_parse_arguments(LIBRARY "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(LIBRARY_TARGET)
|
||||
parse_list(LIBRARY_UNPARSED_ARGUMENTS LIBRARY_NAMES)
|
||||
|
||||
if(LIBRARY_PATH)
|
||||
if(NOT IS_ABSOLUTE ${LIBRARY_PATH})
|
||||
set(LIBRARY_PATH ${${LIBRARY_TARGET}_BUILD_PATH}/${LIBRARY_PATH})
|
||||
endif()
|
||||
else()
|
||||
set(LIBRARY_PATH ${${LIBRARY_TARGET}_BUILD_PATH})
|
||||
endif()
|
||||
parse_path(LIBRARY_PATH)
|
||||
|
||||
set(LIBRARY_PATHS)
|
||||
foreach(name ${LIBRARY_NAMES})
|
||||
if(name MATCHES "\\.")
|
||||
list(APPEND LIBRARY_PATHS ${LIBRARY_PATH}/${name})
|
||||
else()
|
||||
list(APPEND LIBRARY_PATHS ${LIBRARY_PATH}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${LIBRARY_TARGET} PROPERTY OUTPUT ${LIBRARY_PATHS} APPEND)
|
||||
|
||||
if(LIBRARY_VARIABLE)
|
||||
set(${LIBRARY_VARIABLE} ${LIBRARY_PATHS} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(get_libraries target variable)
|
||||
get_target_property(libraries ${target} OUTPUT)
|
||||
if(libraries MATCHES "NOTFOUND")
|
||||
set(libraries)
|
||||
endif()
|
||||
set(${variable} ${libraries} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# register_cmake_project()
|
||||
# Description:
|
||||
# Registers an external CMake project.
|
||||
# Arguments:
|
||||
# TARGET string - The target to associate the project
|
||||
# CWD string - The working directory of the project
|
||||
# CMAKE_TARGET string[] - The CMake targets to build
|
||||
# CMAKE_PATH string - The path to the CMake project (default: CWD)
|
||||
function(register_cmake_project)
|
||||
set(args TARGET CWD CMAKE_PATH LIBRARY_PATH)
|
||||
set(multiArgs CMAKE_TARGET)
|
||||
cmake_parse_arguments(PROJECT "" "${args}" "${multiArgs}" ${ARGN})
|
||||
|
||||
parse_target(PROJECT_TARGET)
|
||||
|
||||
if(NOT PROJECT_CWD)
|
||||
set(PROJECT_CWD ${VENDOR_PATH}/${PROJECT_TARGET})
|
||||
endif()
|
||||
parse_path(PROJECT_CWD)
|
||||
|
||||
if(PROJECT_CMAKE_PATH)
|
||||
set(PROJECT_CMAKE_PATH ${PROJECT_CWD}/${PROJECT_CMAKE_PATH})
|
||||
else()
|
||||
set(PROJECT_CMAKE_PATH ${PROJECT_CWD})
|
||||
endif()
|
||||
parse_path(PROJECT_CMAKE_PATH)
|
||||
|
||||
set(PROJECT_BUILD_PATH ${BUILD_PATH}/vendor/${PROJECT_TARGET})
|
||||
set(PROJECT_TOOLCHAIN_PATH ${PROJECT_BUILD_PATH}/CMakeLists-toolchain.txt)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
configure-${PROJECT_TARGET}
|
||||
COMMENT
|
||||
"Configuring ${PROJECT_TARGET}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-G ${CMAKE_GENERATOR}
|
||||
-B ${PROJECT_BUILD_PATH}
|
||||
-S ${PROJECT_CMAKE_PATH}
|
||||
--toolchain ${PROJECT_TOOLCHAIN_PATH}
|
||||
--fresh
|
||||
-DCMAKE_POLICY_DEFAULT_CMP0077=NEW
|
||||
CWD
|
||||
${PROJECT_CWD}
|
||||
SOURCES
|
||||
${PROJECT_TOOLCHAIN_PATH}
|
||||
OUTPUTS
|
||||
${PROJECT_BUILD_PATH}/CMakeCache.txt
|
||||
)
|
||||
|
||||
if(TARGET clone-${PROJECT_TARGET})
|
||||
add_dependencies(configure-${PROJECT_TARGET} clone-${PROJECT_TARGET})
|
||||
endif()
|
||||
|
||||
set(PROJECT_BUILD_ARGS --build ${PROJECT_BUILD_PATH})
|
||||
|
||||
parse_list(PROJECT_CMAKE_TARGET PROJECT_CMAKE_TARGET)
|
||||
foreach(target ${PROJECT_CMAKE_TARGET})
|
||||
list(APPEND PROJECT_BUILD_ARGS --target ${target})
|
||||
endforeach()
|
||||
|
||||
if(NOT BUN_LINK_ONLY)
|
||||
get_libraries(${PROJECT_TARGET} PROJECT_OUTPUTS)
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
build-${PROJECT_TARGET}
|
||||
COMMENT
|
||||
"Building ${PROJECT_TARGET}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
${PROJECT_BUILD_ARGS}
|
||||
CWD
|
||||
${PROJECT_CWD}
|
||||
TARGETS
|
||||
configure-${PROJECT_TARGET}
|
||||
ARTIFACTS
|
||||
${PROJECT_OUTPUTS}
|
||||
)
|
||||
|
||||
add_dependencies(${PROJECT_TARGET} build-${PROJECT_TARGET})
|
||||
|
||||
cmake_language(EVAL CODE "cmake_language(DEFER CALL create_toolchain_file ${PROJECT_TOOLCHAIN_PATH} ${PROJECT_TARGET})")
|
||||
endfunction()
|
||||
|
||||
# register_cmake_definitions()
|
||||
# Description:
|
||||
# Registers definitions, when compiling an external CMake project.
|
||||
# Arguments:
|
||||
# TARGET string - The target to register the definitions (if not defined, sets for all targets)
|
||||
# DESCRIPTION string - The description of the definitions
|
||||
# definitions string[] - The definitions to register
|
||||
function(register_cmake_definitions)
|
||||
set(args TARGET DESCRIPTION)
|
||||
cmake_parse_arguments(CMAKE "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(CMAKE_TARGET)
|
||||
parse_list(CMAKE_UNPARSED_ARGUMENTS CMAKE_EXTRA_DEFINITIONS)
|
||||
|
||||
foreach(definition ${CMAKE_EXTRA_DEFINITIONS})
|
||||
string(REGEX MATCH "^([^=]+)=(.*)$" match ${definition})
|
||||
if(NOT match)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid definition: \"${definition}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_TARGET)
|
||||
set(${CMAKE_TARGET}_CMAKE_DEFINITIONS ${${CMAKE_TARGET}_CMAKE_DEFINITIONS} ${CMAKE_EXTRA_DEFINITIONS} PARENT_SCOPE)
|
||||
else()
|
||||
set(CMAKE_DEFINITIONS ${CMAKE_DEFINITIONS} ${CMAKE_EXTRA_DEFINITIONS} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# register_link_targets()
|
||||
# Description:
|
||||
# Links the libraries of one target to another.
|
||||
# Arguments:
|
||||
# TARGET string - The main target
|
||||
# targets string[] - The targets to link to the main target
|
||||
function(register_link_targets)
|
||||
set(args TARGET)
|
||||
cmake_parse_arguments(LINK "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(LINK_TARGET)
|
||||
get_target_property(type ${LINK_TARGET} TYPE)
|
||||
if(NOT type MATCHES "EXECUTABLE|LIBRARY")
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Target is not an executable or library: ${LINK_TARGET}")
|
||||
endif()
|
||||
|
||||
parse_list(LINK_UNPARSED_ARGUMENTS LINK_TARGETS)
|
||||
parse_target(LINK_TARGETS)
|
||||
|
||||
foreach(target ${LINK_TARGETS})
|
||||
get_target_property(libraries ${target} OUTPUT)
|
||||
if(NOT libraries)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Target does not have libraries: ${target}")
|
||||
endif()
|
||||
register_link_libraries(TARGET ${LINK_TARGET} ${libraries})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(register_link_libraries)
|
||||
set(args TARGET)
|
||||
cmake_parse_arguments(LINK "" "${args}" "" ${ARGN})
|
||||
|
||||
parse_target(LINK_TARGET)
|
||||
parse_list(LINK_UNPARSED_ARGUMENTS LINK_TARGETS)
|
||||
|
||||
foreach(target ${LINK_TARGETS})
|
||||
target_link_libraries(${LINK_TARGET} PUBLIC ${target})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# create_toolchain_file()
|
||||
# Description:
|
||||
# Creates a CMake toolchain file.
|
||||
# Arguments:
|
||||
# filename string - The path to create the toolchain file
|
||||
# target string - The target to create the toolchain file
|
||||
function(create_toolchain_file filename target)
|
||||
parse_path(filename)
|
||||
parse_target(target)
|
||||
|
||||
set(lines)
|
||||
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
file(STRINGS ${CMAKE_TOOLCHAIN_FILE} lines)
|
||||
list(PREPEND lines "# Copied from ${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
|
||||
list(APPEND lines "# Generated from ${CMAKE_CURRENT_FUNCTION} in ${CMAKE_CURRENT_LIST_FILE}")
|
||||
|
||||
set(variables
|
||||
CMAKE_BUILD_TYPE
|
||||
CMAKE_EXPORT_COMPILE_COMMANDS
|
||||
CMAKE_COLOR_DIAGNOSTICS
|
||||
CMAKE_C_COMPILER
|
||||
CMAKE_C_COMPILER_LAUNCHER
|
||||
CMAKE_CXX_COMPILER
|
||||
CMAKE_CXX_COMPILER_LAUNCHER
|
||||
CMAKE_LINKER
|
||||
CMAKE_AR
|
||||
CMAKE_RANLIB
|
||||
CMAKE_STRIP
|
||||
CMAKE_OSX_SYSROOT
|
||||
CMAKE_OSX_DEPLOYMENT_TARGET
|
||||
)
|
||||
|
||||
macro(append variable value)
|
||||
if(value MATCHES " ")
|
||||
list(APPEND lines "set(${variable} \"${value}\")")
|
||||
else()
|
||||
list(APPEND lines "set(${variable} ${value})")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
foreach(variable ${variables})
|
||||
if(DEFINED ${variable})
|
||||
append(${variable} ${${variable}})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(flags
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_LINKER_FLAGS
|
||||
)
|
||||
|
||||
foreach(flag ${flags})
|
||||
set(value)
|
||||
if(DEFINED ${flag})
|
||||
set(value "${${flag}}")
|
||||
endif()
|
||||
if(DEFINED ${target}_${flag})
|
||||
set(value "${value} ${${target}_${flag}}")
|
||||
endif()
|
||||
if(value)
|
||||
append(${flag} ${value})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(definitions
|
||||
CMAKE_DEFINITIONS
|
||||
${target}_CMAKE_DEFINITIONS
|
||||
)
|
||||
|
||||
foreach(definition ${definitions})
|
||||
foreach(entry ${${definition}})
|
||||
string(REGEX MATCH "^([^=]+)=(.*)$" match ${entry})
|
||||
if(NOT match)
|
||||
message(FATAL_ERROR "Invalid definition: ${entry}")
|
||||
endif()
|
||||
append(${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
list(JOIN lines "\n" lines)
|
||||
file(GENERATE OUTPUT ${filename} CONTENT "${lines}\n")
|
||||
endfunction()
|
||||
|
||||
@@ -2,8 +2,8 @@ if(NOT CMAKE_SYSTEM_NAME OR NOT CMAKE_SYSTEM_PROCESSOR)
|
||||
message(FATAL_ERROR "CMake included this file before project() was called")
|
||||
endif()
|
||||
|
||||
optionx(BUN_LINK_ONLY BOOL "If only the linking step should be built" DEFAULT OFF)
|
||||
optionx(BUN_CPP_ONLY BOOL "If only the C++ part of Bun should be built" DEFAULT OFF)
|
||||
optionx(BUN_CPP_ONLY BOOL "If only the C++ library should be built" DEFAULT OFF)
|
||||
optionx(BUN_LINK_ONLY BOOL "If only the executable should be linked" DEFAULT OFF)
|
||||
|
||||
optionx(BUILDKITE BOOL "If Buildkite is enabled" DEFAULT OFF)
|
||||
optionx(GITHUB_ACTIONS BOOL "If GitHub Actions is enabled" DEFAULT OFF)
|
||||
@@ -143,15 +143,4 @@ endif()
|
||||
|
||||
optionx(USE_STATIC_LIBATOMIC BOOL "If libatomic should be statically linked" DEFAULT ${DEFAULT_STATIC_LIBATOMIC})
|
||||
|
||||
if(APPLE)
|
||||
set(DEFAULT_WEBKIT_ICU OFF)
|
||||
else()
|
||||
set(DEFAULT_WEBKIT_ICU ON)
|
||||
endif()
|
||||
|
||||
optionx(USE_WEBKIT_ICU BOOL "Use the ICU libraries from WebKit" DEFAULT ${DEFAULT_WEBKIT_ICU})
|
||||
|
||||
optionx(ERROR_LIMIT STRING "Maximum number of errors to show when compiling C++ code" DEFAULT "100")
|
||||
|
||||
list(APPEND CMAKE_ARGS -DCMAKE_EXPORT_COMPILE_COMMANDS=ON)
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
|
||||
find_command(
|
||||
VARIABLE
|
||||
CLANG_FORMAT_PROGRAM
|
||||
@@ -9,8 +7,6 @@ find_command(
|
||||
OFF
|
||||
)
|
||||
|
||||
set(CLANG_FORMAT_SOURCES ${BUN_C_SOURCES} ${BUN_CXX_SOURCES})
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
clang-format-check
|
||||
@@ -21,8 +17,8 @@ register_command(
|
||||
-Werror
|
||||
--dry-run
|
||||
--verbose
|
||||
${CLANG_FORMAT_SOURCES}
|
||||
ALWAYS_RUN
|
||||
${BUN_C_SOURCES}
|
||||
${BUN_CXX_SOURCES}
|
||||
)
|
||||
|
||||
register_command(
|
||||
@@ -34,38 +30,6 @@ register_command(
|
||||
${CLANG_FORMAT_PROGRAM}
|
||||
-i # edits files in-place
|
||||
--verbose
|
||||
${CLANG_FORMAT_SOURCES}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
if(GIT_CHANGED_SOURCES)
|
||||
set(CLANG_FORMAT_CHANGED_SOURCES)
|
||||
foreach(source ${CLANG_FORMAT_SOURCES})
|
||||
list(FIND GIT_CHANGED_SOURCES ${source} index)
|
||||
if(NOT ${index} EQUAL -1)
|
||||
list(APPEND CLANG_FORMAT_CHANGED_SOURCES ${source})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(CLANG_FORMAT_CHANGED_SOURCES)
|
||||
set(CLANG_FORMAT_DIFF_COMMAND ${CLANG_FORMAT_PROGRAM}
|
||||
-i # edits files in-place
|
||||
--verbose
|
||||
${CLANG_FORMAT_CHANGED_SOURCES}
|
||||
)
|
||||
else()
|
||||
set(CLANG_FORMAT_DIFF_COMMAND ${CMAKE_COMMAND} -E echo "No changed files for clang-format")
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
clang-format-diff
|
||||
COMMENT
|
||||
"Running clang-format on changed files"
|
||||
COMMAND
|
||||
${CLANG_FORMAT_DIFF_COMMAND}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
ALWAYS_RUN
|
||||
${BUN_C_SOURCES}
|
||||
${BUN_CXX_SOURCES}
|
||||
)
|
||||
|
||||
@@ -13,13 +13,58 @@ find_command(
|
||||
|
||||
set(CLANG_TIDY_SOURCES ${BUN_C_SOURCES} ${BUN_CXX_SOURCES})
|
||||
|
||||
set(CLANG_TIDY_COMMAND ${CLANG_TIDY_PROGRAM}
|
||||
-p ${BUILD_PATH}
|
||||
--config-file=${CWD}/.clang-tidy
|
||||
find_command(
|
||||
VARIABLE
|
||||
GIT_PROGRAM
|
||||
COMMAND
|
||||
git
|
||||
REQUIRED
|
||||
OFF
|
||||
)
|
||||
|
||||
if(CMAKE_COLOR_DIAGNOSTICS)
|
||||
list(APPEND CLANG_TIDY_COMMAND --use-color)
|
||||
if(GIT_PROGRAM)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GIT_PROGRAM}
|
||||
diff
|
||||
--name-only
|
||||
--diff-filter=AM
|
||||
main
|
||||
WORKING_DIRECTORY
|
||||
${CWD}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE
|
||||
GIT_CHANGED_FILES
|
||||
ERROR_QUIET
|
||||
)
|
||||
string(REPLACE "\n" ";" GIT_CHANGED_FILES ${GIT_CHANGED_FILES})
|
||||
list(TRANSFORM GIT_CHANGED_FILES PREPEND ${CWD}/)
|
||||
|
||||
set(CLANG_TIDY_CHANGED_SOURCES)
|
||||
foreach(source ${CLANG_TIDY_SOURCES})
|
||||
list(FIND GIT_CHANGED_FILES ${source} index)
|
||||
if(NOT ${index} EQUAL -1)
|
||||
list(APPEND CLANG_TIDY_CHANGED_SOURCES ${source})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CLANG_TIDY_CHANGED_SOURCES)
|
||||
set(CLANG_TIDY_SOURCES ${CLANG_TIDY_CHANGED_SOURCES})
|
||||
else()
|
||||
set(CLANG_TIDY_COMMAND ${CMAKE_COMMAND} -E echo "No files changed for clang-tidy")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CLANG_TIDY_COMMAND)
|
||||
set(CLANG_TIDY_COMMAND ${CLANG_TIDY_PROGRAM}
|
||||
-p ${BUILD_PATH}
|
||||
--config-file=${CWD}/.clang-tidy
|
||||
--fix
|
||||
--fix-errors
|
||||
--fix-notes
|
||||
--use-color
|
||||
${CLANG_TIDY_SOURCES}
|
||||
)
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
@@ -28,58 +73,7 @@ register_command(
|
||||
COMMENT
|
||||
"Running clang-tidy"
|
||||
COMMAND
|
||||
${CLANG_TIDY_COMMAND}
|
||||
${CLANG_TIDY_SOURCES}
|
||||
--fix
|
||||
--fix-errors
|
||||
--fix-notes
|
||||
${CLANG_TIDY_COMMAND}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
clang-tidy-check
|
||||
COMMENT
|
||||
"Checking clang-tidy"
|
||||
COMMAND
|
||||
${CLANG_TIDY_COMMAND}
|
||||
${CLANG_TIDY_SOURCES}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
if(GIT_CHANGED_SOURCES)
|
||||
set(CLANG_TIDY_CHANGED_SOURCES)
|
||||
foreach(source ${CLANG_TIDY_SOURCES})
|
||||
list(FIND GIT_CHANGED_SOURCES ${source} index)
|
||||
if(NOT ${index} EQUAL -1)
|
||||
list(APPEND CLANG_TIDY_CHANGED_SOURCES ${source})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(CLANG_TIDY_CHANGED_SOURCES)
|
||||
set(CLANG_TIDY_DIFF_COMMAND ${CLANG_TIDY_PROGRAM}
|
||||
${CLANG_TIDY_CHANGED_SOURCES}
|
||||
--fix
|
||||
--fix-errors
|
||||
--fix-notes
|
||||
)
|
||||
else()
|
||||
set(CLANG_TIDY_DIFF_COMMAND ${CMAKE_COMMAND} -E echo "No changed files for clang-tidy")
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
clang-tidy-diff
|
||||
COMMENT
|
||||
"Running clang-tidy on changed files"
|
||||
COMMAND
|
||||
${CLANG_TIDY_DIFF_COMMAND}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
if(CMAKE_HOST_WIN32)
|
||||
setx(PRETTIER_EXECUTABLE ${CWD}/node_modules/.bin/prettier.exe)
|
||||
else()
|
||||
setx(PRETTIER_EXECUTABLE ${CWD}/node_modules/.bin/prettier)
|
||||
endif()
|
||||
|
||||
set(PRETTIER_PATHS
|
||||
${CWD}/src
|
||||
${CWD}/packages/bun-error
|
||||
${CWD}/packages/bun-types
|
||||
${CWD}/packages/bun-inspector-protocol
|
||||
${CWD}/packages/bun-inspector-frontend
|
||||
${CWD}/packages/bun-debug-adapter-protocol
|
||||
${CWD}/packages/bun-vscode
|
||||
${CWD}/test
|
||||
${CWD}/bench
|
||||
${CWD}/.vscode
|
||||
${CWD}/.buildkite
|
||||
${CWD}/.github
|
||||
)
|
||||
|
||||
set(PRETTIER_EXTENSIONS
|
||||
*.jsonc?
|
||||
*.ya?ml
|
||||
*.jsx?
|
||||
*.tsx?
|
||||
*.mjs
|
||||
*.cjs
|
||||
*.mts
|
||||
*.cts
|
||||
)
|
||||
|
||||
set(PRETTIER_GLOBS)
|
||||
foreach(path ${PRETTIER_PATHS})
|
||||
foreach(extension ${PRETTIER_EXTENSIONS})
|
||||
list(APPEND PRETTIER_GLOBS ${path}/${extension})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
file(GLOB_RECURSE PRETTIER_SOURCES ${PRETTIER_GLOBS})
|
||||
|
||||
register_command(
|
||||
COMMAND
|
||||
${BUN_EXECUTABLE}
|
||||
install
|
||||
--frozen-lockfile
|
||||
SOURCES
|
||||
${CWD}/package.json
|
||||
OUTPUTS
|
||||
${PRETTIER_EXECUTABLE}
|
||||
)
|
||||
|
||||
set(PRETTIER_COMMAND ${PRETTIER_EXECUTABLE}
|
||||
--config=${CWD}/.prettierrc
|
||||
--cache
|
||||
)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
prettier
|
||||
COMMENT
|
||||
"Running prettier"
|
||||
COMMAND
|
||||
${PRETTIER_COMMAND}
|
||||
--write
|
||||
${PRETTIER_SOURCES}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
prettier-extra
|
||||
COMMENT
|
||||
"Running prettier with extra plugins"
|
||||
COMMAND
|
||||
${PRETTIER_COMMAND}
|
||||
--write
|
||||
--plugin=prettier-plugin-organize-imports
|
||||
${PRETTIER_SOURCES}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
prettier-check
|
||||
COMMENT
|
||||
"Checking prettier"
|
||||
COMMAND
|
||||
${PRETTIER_COMMAND}
|
||||
--check
|
||||
${PRETTIER_SOURCES}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
if(GIT_CHANGED_SOURCES)
|
||||
set(PRETTIER_CHANGED_SOURCES)
|
||||
foreach(source ${PRETTIER_SOURCES})
|
||||
list(FIND PRETTIER_CHANGED_SOURCES ${source} index)
|
||||
if(NOT ${index} EQUAL -1)
|
||||
list(APPEND PRETTIER_CHANGED_SOURCES ${source})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(PRETTIER_CHANGED_SOURCES)
|
||||
set(PRETTIER_DIFF_COMMAND ${PRETTIER_COMMAND}
|
||||
--write
|
||||
--plugin=prettier-plugin-organize-imports
|
||||
${PRETTIER_CHANGED_SOURCES}
|
||||
)
|
||||
else()
|
||||
set(PRETTIER_DIFF_COMMAND ${CMAKE_COMMAND} -E echo "No changed files for prettier")
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
prettier-diff
|
||||
COMMENT
|
||||
"Running prettier on changed files"
|
||||
COMMAND
|
||||
${PRETTIER_DIFF_COMMAND}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
@@ -1,5 +1,3 @@
|
||||
set(ZIG_FORMAT_SOURCES ${BUN_ZIG_SOURCES})
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
zig-format-check
|
||||
@@ -9,8 +7,7 @@ register_command(
|
||||
${ZIG_EXECUTABLE}
|
||||
fmt
|
||||
--check
|
||||
${ZIG_FORMAT_SOURCES}
|
||||
ALWAYS_RUN
|
||||
${BUN_ZIG_SOURCES}
|
||||
)
|
||||
|
||||
register_command(
|
||||
@@ -21,37 +18,5 @@ register_command(
|
||||
COMMAND
|
||||
${ZIG_EXECUTABLE}
|
||||
fmt
|
||||
${ZIG_FORMAT_SOURCES}
|
||||
ALWAYS_RUN
|
||||
)
|
||||
|
||||
if(GIT_CHANGED_SOURCES)
|
||||
set(ZIG_FORMAT_CHANGED_SOURCES)
|
||||
foreach(source ${ZIG_FORMAT_SOURCES})
|
||||
list(FIND GIT_CHANGED_SOURCES ${source} index)
|
||||
if(NOT ${index} EQUAL -1)
|
||||
list(APPEND ZIG_FORMAT_CHANGED_SOURCES ${source})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ZIG_FORMAT_CHANGED_SOURCES)
|
||||
set(ZIG_FORMAT_DIFF_COMMAND ${ZIG_EXECUTABLE}
|
||||
fmt
|
||||
${ZIG_FORMAT_CHANGED_SOURCES}
|
||||
)
|
||||
else()
|
||||
set(ZIG_FORMAT_DIFF_COMMAND ${CMAKE_COMMAND} -E echo "No changed files for zig-format")
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
zig-format-diff
|
||||
COMMENT
|
||||
"Running zig fmt on changed files"
|
||||
COMMAND
|
||||
${ZIG_FORMAT_DIFF_COMMAND}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
ALWAYS_RUN
|
||||
${BUN_ZIG_SOURCES}
|
||||
)
|
||||
|
||||
@@ -125,5 +125,7 @@ else()
|
||||
file(RENAME ${DOWNLOAD_TMP_FILE} ${DOWNLOAD_PATH})
|
||||
endif()
|
||||
|
||||
get_filename_component(DOWNLOAD_FILENAME ${DOWNLOAD_PATH} NAME)
|
||||
message(STATUS "Saved ${DOWNLOAD_FILENAME}")
|
||||
|
||||
file(REMOVE_RECURSE ${DOWNLOAD_TMP_PATH})
|
||||
message(STATUS "Saved ${DOWNLOAD_PATH}")
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
get_filename_component(SCRIPT_NAME ${CMAKE_CURRENT_LIST_FILE} NAME)
|
||||
message(STATUS "Running script: ${SCRIPT_NAME}")
|
||||
|
||||
if(NOT ZIG_PATH OR NOT ZIG_COMMIT OR NOT ZIG_VERSION)
|
||||
message(FATAL_ERROR "ZIG_PATH, ZIG_COMMIT, and ZIG_VERSION are required")
|
||||
if(NOT ZIG_PATH)
|
||||
message(FATAL_ERROR "ZIG_PATH is required")
|
||||
endif()
|
||||
|
||||
if(ZIG_REPOSITORY)
|
||||
if(NOT ZIG_COMMIT)
|
||||
message(FATAL_ERROR "ZIG_COMMIT is required when ZIG_REPOSITORY is set")
|
||||
endif()
|
||||
elseif(NOT ZIG_COMMIT)
|
||||
set(ZIG_REPOSITORY "oven-sh/zig")
|
||||
set(ZIG_COMMIT "131a009ba2eb127a3447d05b9e12f710429aa5ee")
|
||||
endif()
|
||||
|
||||
if(NOT ZIG_VERSION)
|
||||
set(ZIG_VERSION "0.13.0")
|
||||
endif()
|
||||
|
||||
if(CMAKE_HOST_APPLE)
|
||||
@@ -38,6 +51,7 @@ else()
|
||||
set(ZIG_FILENAME ${ZIG_NAME}.tar.xz)
|
||||
endif()
|
||||
|
||||
message(STATUS "Downloading ${ZIG_EXE} ${ZIG_VERSION} on ${ZIG_OS} ${ZIG_ARCH}...")
|
||||
set(ZIG_DOWNLOAD_URL https://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILENAME})
|
||||
|
||||
execute_process(
|
||||
@@ -58,7 +72,7 @@ if(NOT ZIG_DOWNLOAD_RESULT EQUAL 0)
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${ZIG_PATH}/${ZIG_EXE})
|
||||
message(FATAL_ERROR "Executable not found: \"${ZIG_PATH}/${ZIG_EXE}\"")
|
||||
message(FATAL_ERROR "Download failed: executable not found: \"${ZIG_PATH}/${ZIG_EXE}\"")
|
||||
endif()
|
||||
|
||||
# Tools like VSCode need a stable path to the zig executable, on both Unix and Windows
|
||||
@@ -67,30 +81,31 @@ if(NOT WIN32)
|
||||
file(CREATE_LINK ${ZIG_PATH}/${ZIG_EXE} ${ZIG_PATH}/zig.exe SYMBOLIC)
|
||||
endif()
|
||||
|
||||
set(ZIG_REPOSITORY_PATH ${ZIG_PATH}/repository)
|
||||
if(ZIG_REPOSITORY AND ZIG_COMMIT)
|
||||
message(STATUS "Downloading zig library from ${ZIG_REPOSITORY} at ${ZIG_COMMIT}...")
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DGIT_PATH=${ZIG_REPOSITORY_PATH}
|
||||
-DGIT_REPOSITORY=oven-sh/zig
|
||||
-DGIT_COMMIT=${ZIG_COMMIT}
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/GitClone.cmake
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_VARIABLE
|
||||
ZIG_REPOSITORY_ERROR
|
||||
RESULT_VARIABLE
|
||||
ZIG_REPOSITORY_RESULT
|
||||
)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DGIT_PATH=${ZIG_PATH}/tmp
|
||||
-DGIT_REPOSITORY=${ZIG_REPOSITORY}
|
||||
-DGIT_COMMIT=${ZIG_COMMIT}
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/GitClone.cmake
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_VARIABLE
|
||||
ZIG_REPOSITORY_ERROR
|
||||
RESULT_VARIABLE
|
||||
ZIG_REPOSITORY_RESULT
|
||||
)
|
||||
|
||||
if(NOT ZIG_REPOSITORY_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Download failed: ${ZIG_REPOSITORY_ERROR}")
|
||||
if(NOT ZIG_REPOSITORY_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Download failed: ${ZIG_REPOSITORY_ERROR}")
|
||||
endif()
|
||||
|
||||
file(REMOVE_RECURSE ${ZIG_PATH}/lib)
|
||||
file(RENAME ${ZIG_PATH}/tmp/lib ${ZIG_PATH}/lib)
|
||||
file(REMOVE_RECURSE ${ZIG_PATH}/tmp)
|
||||
message(STATUS "Saved ${ZIG_PATH}/lib")
|
||||
endif()
|
||||
|
||||
file(REMOVE_RECURSE ${ZIG_PATH}/lib)
|
||||
|
||||
# Use copy_directory instead of file(RENAME) because there were
|
||||
# race conditions in CI where some files were not copied.
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${ZIG_REPOSITORY_PATH}/lib ${ZIG_PATH}/lib)
|
||||
|
||||
file(REMOVE_RECURSE ${ZIG_REPOSITORY_PATH})
|
||||
message(STATUS "Saved ${ZIG_EXE}")
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
register_vendor_target(boringssl)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
boringssl
|
||||
${boringssl}
|
||||
REPOSITORY
|
||||
oven-sh/boringssl
|
||||
COMMIT
|
||||
29a2cd359458c9384694b75456026e4b57e3e567
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
register_libraries(
|
||||
TARGET ${boringssl}
|
||||
crypto
|
||||
ssl
|
||||
decrepit
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
boringssl
|
||||
LIBRARIES
|
||||
${boringssl}
|
||||
CMAKE_TARGET
|
||||
crypto
|
||||
ssl
|
||||
decrepit
|
||||
ARGS
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
INCLUDES
|
||||
include
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${boringssl}
|
||||
BUILD_SHARED_LIBS=OFF
|
||||
)
|
||||
|
||||
@@ -1,31 +1,43 @@
|
||||
register_vendor_target(brotli)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
brotli
|
||||
${brotli}
|
||||
REPOSITORY
|
||||
google/brotli
|
||||
TAG
|
||||
v1.1.0
|
||||
COMMIT
|
||||
ed738e842d2fbdf2d6459e39267a633c4a9b2f5d
|
||||
)
|
||||
|
||||
register_libraries(
|
||||
TARGET ${brotli}
|
||||
brotlicommon
|
||||
brotlidec
|
||||
brotlienc
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${brotli}
|
||||
CMAKE_TARGET
|
||||
brotlicommon
|
||||
brotlidec
|
||||
brotlienc
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${brotli}
|
||||
BUILD_SHARED_LIBS=OFF
|
||||
BROTLI_BUILD_TOOLS=OFF
|
||||
BROTLI_EMSCRIPTEN=OFF
|
||||
BROTLI_DISABLE_TESTS=ON
|
||||
)
|
||||
|
||||
# Tests fail with "BrotliDecompressionError" when LTO is enabled
|
||||
# only on Linux x64 (non-baseline). It's a mystery.
|
||||
if(LINUX AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|X86_64|x64|X64|amd64|AMD64" AND NOT ENABLE_BASELINE)
|
||||
set(BROTLI_CMAKE_ARGS "-DCMAKE_C_FLAGS=-fno-lto")
|
||||
if(LINUX AND CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|AMD64|x86_64|X86_64|x64|X64" AND NOT ENABLE_BASELINE)
|
||||
register_compiler_flags(
|
||||
TARGET ${brotli}
|
||||
-fno-lto
|
||||
)
|
||||
endif()
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
brotli
|
||||
LIBRARIES
|
||||
brotlicommon
|
||||
brotlidec
|
||||
brotlienc
|
||||
ARGS
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DBROTLI_BUILD_TOOLS=OFF
|
||||
-DBROTLI_EMSCRIPTEN=OFF
|
||||
-DBROTLI_DISABLE_TESTS=ON
|
||||
${BROTLI_CMAKE_ARGS}
|
||||
INCLUDES
|
||||
c/include
|
||||
)
|
||||
|
||||
@@ -12,15 +12,6 @@ else()
|
||||
set(bunStrip bun)
|
||||
endif()
|
||||
|
||||
set(bunExe ${bun}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
if(bunStrip)
|
||||
set(bunStripExe ${bunStrip}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
set(buns ${bun} ${bunStrip})
|
||||
else()
|
||||
set(buns ${bun})
|
||||
endif()
|
||||
|
||||
# Some commands use this path, and some do not.
|
||||
# In the future, change those commands so that generated files are written to this path.
|
||||
optionx(CODEGEN_PATH FILEPATH "Path to the codegen directory" DEFAULT ${BUILD_PATH}/codegen)
|
||||
@@ -60,8 +51,6 @@ register_command(
|
||||
${BUN_ZIG_IDENTIFIER_SCRIPT}
|
||||
SOURCES
|
||||
${BUN_ZIG_IDENTIFIER_SOURCES}
|
||||
TARGETS
|
||||
clone-zig
|
||||
OUTPUTS
|
||||
${BUN_ZIG_IDENTIFIER_OUTPUTS}
|
||||
)
|
||||
@@ -474,6 +463,19 @@ WEBKIT_ADD_SOURCE_DEPENDENCIES(
|
||||
${CODEGEN_PATH}/InternalModuleRegistryConstants.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(ENABLE_CANARY)
|
||||
set(Bun_VERSION_WITH_TAG ${VERSION}-canary.${CANARY_REVISION})
|
||||
else()
|
||||
set(Bun_VERSION_WITH_TAG ${VERSION})
|
||||
endif()
|
||||
set(BUN_ICO_PATH ${CWD}/src/bun.ico)
|
||||
configure_file(
|
||||
${CWD}/src/windows-app-info.rc
|
||||
${CODEGEN_PATH}/windows-app-info.rc
|
||||
)
|
||||
endif()
|
||||
|
||||
# --- Zig ---
|
||||
|
||||
file(GLOB_RECURSE BUN_ZIG_SOURCES ${CONFIGURE_DEPENDS}
|
||||
@@ -546,17 +548,15 @@ register_command(
|
||||
-Dgenerated-code=${CODEGEN_PATH}
|
||||
ARTIFACTS
|
||||
${BUN_ZIG_OUTPUT}
|
||||
TARGETS
|
||||
clone-zig
|
||||
SOURCES
|
||||
${BUN_ZIG_SOURCES}
|
||||
${BUN_ZIG_GENERATED_SOURCES}
|
||||
)
|
||||
|
||||
set_property(TARGET bun-zig PROPERTY JOB_POOL compile_pool)
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "build.zig")
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CWD}/build.zig)
|
||||
|
||||
# --- C/C++ Sources ---
|
||||
# --- C/C++ Object ---
|
||||
|
||||
set(BUN_USOCKETS_SOURCE ${CWD}/packages/bun-usockets)
|
||||
|
||||
@@ -581,41 +581,15 @@ file(GLOB BUN_C_SOURCES ${CONFIGURE_DEPENDS}
|
||||
${BUN_USOCKETS_SOURCE}/src/crypto/*.c
|
||||
)
|
||||
|
||||
list(APPEND BUN_C_SOURCES ${VENDOR_PATH}/picohttpparser/picohttpparser.c)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND BUN_C_SOURCES ${CWD}/src/bun.js/bindings/windows/musl-memmem.c)
|
||||
endif()
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
picohttpparser
|
||||
REPOSITORY
|
||||
h2o/picohttpparser
|
||||
COMMIT
|
||||
066d2b1e9ab820703db0837a7255d92d30f0c9f5
|
||||
OUTPUTS
|
||||
picohttpparser.c
|
||||
)
|
||||
|
||||
set(NODEJS_HEADERS_PATH ${VENDOR_PATH}/nodejs)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
bun-node-headers
|
||||
COMMENT
|
||||
"Download node ${NODEJS_VERSION} headers"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DDOWNLOAD_PATH=${NODEJS_HEADERS_PATH}
|
||||
-DDOWNLOAD_URL=https://nodejs.org/dist/v${NODEJS_VERSION}/node-v${NODEJS_VERSION}-headers.tar.gz
|
||||
-P ${CWD}/cmake/scripts/DownloadUrl.cmake
|
||||
OUTPUTS
|
||||
${NODEJS_HEADERS_PATH}/include/node/node_version.h
|
||||
)
|
||||
|
||||
list(APPEND BUN_CPP_SOURCES
|
||||
${BUN_C_SOURCES}
|
||||
${BUN_CXX_SOURCES}
|
||||
${VENDOR_PATH}/picohttpparser/picohttpparser.c
|
||||
${BUN_ZIG_GENERATED_CLASSES_OUTPUTS}
|
||||
${BUN_JS_SINK_OUTPUTS}
|
||||
${BUN_JAVASCRIPT_OUTPUTS}
|
||||
@@ -623,22 +597,12 @@ list(APPEND BUN_CPP_SOURCES
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(ENABLE_CANARY)
|
||||
set(Bun_VERSION_WITH_TAG ${VERSION}-canary.${CANARY_REVISION})
|
||||
else()
|
||||
set(Bun_VERSION_WITH_TAG ${VERSION})
|
||||
endif()
|
||||
set(BUN_ICO_PATH ${CWD}/src/bun.ico)
|
||||
configure_file(
|
||||
${CWD}/src/windows-app-info.rc
|
||||
${CODEGEN_PATH}/windows-app-info.rc
|
||||
)
|
||||
list(APPEND BUN_CPP_SOURCES ${CODEGEN_PATH}/windows-app-info.rc)
|
||||
endif()
|
||||
|
||||
# --- Executable ---
|
||||
|
||||
set(BUN_CPP_OUTPUT ${BUILD_PATH}/${CMAKE_STATIC_LIBRARY_PREFIX}${bun}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
set(BUN_EXE_OUTPUT ${BUILD_PATH}/${CMAKE_EXECUTABLE_PREFIX}${bun}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
set(BUN_EXE_STRIP_OUTPUT ${BUILD_PATH}/${CMAKE_EXECUTABLE_PREFIX}bun${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
if(BUN_LINK_ONLY)
|
||||
add_executable(${bun} ${BUN_CPP_OUTPUT} ${BUN_ZIG_OUTPUT})
|
||||
@@ -646,30 +610,21 @@ if(BUN_LINK_ONLY)
|
||||
target_link_libraries(${bun} PRIVATE ${BUN_CPP_OUTPUT})
|
||||
elseif(BUN_CPP_ONLY)
|
||||
add_library(${bun} STATIC ${BUN_CPP_SOURCES})
|
||||
register_command(
|
||||
TARGET
|
||||
${bun}
|
||||
TARGET_PHASE
|
||||
POST_BUILD
|
||||
COMMENT
|
||||
"Uploading ${bun}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E true
|
||||
ARTIFACTS
|
||||
${BUN_CPP_OUTPUT}
|
||||
upload_artifacts(
|
||||
TARGET ${bun}
|
||||
${BUN_CPP_OUTPUT}
|
||||
)
|
||||
else()
|
||||
add_executable(${bun} ${BUN_CPP_SOURCES})
|
||||
target_link_libraries(${bun} PRIVATE ${BUN_ZIG_OUTPUT})
|
||||
upload_artifacts(
|
||||
TARGET ${bun}
|
||||
${BUN_EXE_OUTPUT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT bun STREQUAL "bun")
|
||||
add_custom_target(bun DEPENDS ${bun})
|
||||
endif()
|
||||
|
||||
# --- C/C++ Properties ---
|
||||
|
||||
set_target_properties(${bun} PROPERTIES
|
||||
OUTPUT_NAME ${bun}
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
CXX_EXTENSIONS YES
|
||||
@@ -679,6 +634,17 @@ set_target_properties(${bun} PROPERTIES
|
||||
VISIBILITY_INLINES_HIDDEN YES
|
||||
)
|
||||
|
||||
if(BUN_LINK_ONLY)
|
||||
set_target_properties(${bun} PROPERTIES
|
||||
OUTPUT_NAME ${bun}
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT bun STREQUAL "bun")
|
||||
add_custom_target(bun DEPENDS ${bun})
|
||||
endif()
|
||||
|
||||
# --- C/C++ Includes ---
|
||||
|
||||
if(WIN32)
|
||||
@@ -733,7 +699,6 @@ target_compile_definitions(${bun} PRIVATE
|
||||
WITH_BORINGSSL=1
|
||||
STATICALLY_LINKED_WITH_JavaScriptCore=1
|
||||
STATICALLY_LINKED_WITH_BMALLOC=1
|
||||
BUILDING_WITH_CMAKE=1
|
||||
JSC_OBJC_API_ENABLED=0
|
||||
BUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1
|
||||
NAPI_EXPERIMENTAL=ON
|
||||
@@ -750,7 +715,6 @@ if(DEBUG AND NOT CI)
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# --- Compiler options ---
|
||||
|
||||
if(NOT WIN32)
|
||||
@@ -925,8 +889,6 @@ set_target_properties(${bun} PROPERTIES LINK_DEPENDS ${BUN_SYMBOLS_PATH})
|
||||
|
||||
# --- WebKit ---
|
||||
|
||||
include(SetupWebKit)
|
||||
|
||||
if(WIN32)
|
||||
if(DEBUG)
|
||||
target_link_libraries(${bun} PRIVATE
|
||||
@@ -963,34 +925,38 @@ endif()
|
||||
|
||||
# --- Dependencies ---
|
||||
|
||||
set(BUN_DEPENDENCIES
|
||||
BoringSSL
|
||||
Brotli
|
||||
Cares
|
||||
LibDeflate
|
||||
LolHtml
|
||||
Lshpack
|
||||
Mimalloc
|
||||
TinyCC
|
||||
Zlib
|
||||
LibArchive # must be loaded after zlib
|
||||
Zstd
|
||||
register_link_targets(
|
||||
TARGET ${bun}
|
||||
${boringssl}
|
||||
${brotli}
|
||||
${cares}
|
||||
${libarchive}
|
||||
${libdeflate}
|
||||
${libuv} ${WIN32}
|
||||
${lolhtml}
|
||||
${lshpack}
|
||||
${mimalloc}
|
||||
${tinycc}
|
||||
${sqlite} ${USE_STATIC_SQLITE}
|
||||
${webkit}
|
||||
${zlib}
|
||||
${zstd}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND BUN_DEPENDENCIES Libuv)
|
||||
endif()
|
||||
|
||||
if(USE_STATIC_SQLITE)
|
||||
list(APPEND BUN_DEPENDENCIES SQLite)
|
||||
endif()
|
||||
|
||||
foreach(dependency ${BUN_DEPENDENCIES})
|
||||
include(Build${dependency})
|
||||
endforeach()
|
||||
|
||||
list(TRANSFORM BUN_DEPENDENCIES TOLOWER OUTPUT_VARIABLE BUN_TARGETS)
|
||||
add_custom_target(dependencies DEPENDS ${BUN_TARGETS})
|
||||
register_includes(
|
||||
TARGET ${bun}
|
||||
${${picohttpparser}_CWD}
|
||||
${${boringssl}_CWD}/include
|
||||
${${brotli}_CWD}/c/include
|
||||
${${cares}_CWD}/include
|
||||
${${libarchive}_CWD}/include
|
||||
${${libdeflate}_CWD}
|
||||
${${libuv}_CWD}/include ${WIN32}
|
||||
${${lshpack}_CWD}
|
||||
${${lshpack}_CWD}/compat/queue ${WIN32}
|
||||
${${mimalloc}_CWD}/include
|
||||
${${zlib}_CWD}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(${bun} PRIVATE icucore resolv)
|
||||
@@ -1036,6 +1002,12 @@ endif()
|
||||
|
||||
# --- Packaging ---
|
||||
|
||||
if(bunStrip)
|
||||
set(buns ${bun} ${bunStrip})
|
||||
else()
|
||||
set(buns ${bun})
|
||||
endif()
|
||||
|
||||
if(NOT BUN_CPP_ONLY)
|
||||
if(bunStrip)
|
||||
register_command(
|
||||
@@ -1047,15 +1019,15 @@ if(NOT BUN_CPP_ONLY)
|
||||
"Stripping ${bun}"
|
||||
COMMAND
|
||||
${CMAKE_STRIP}
|
||||
${bunExe}
|
||||
${BUN_EXE_OUTPUT}
|
||||
--strip-all
|
||||
--strip-debug
|
||||
--discard-all
|
||||
-o ${bunStripExe}
|
||||
-o ${BUN_EXE_STRIP_OUTPUT}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
OUTPUTS
|
||||
${BUILD_PATH}/${bunStripExe}
|
||||
${BUN_EXE_STRIP_OUTPUT}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1068,9 +1040,9 @@ if(NOT BUN_CPP_ONLY)
|
||||
"Testing ${bun}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-E env BUN_DEBUG_QUIET_LOGS=1
|
||||
${BUILD_PATH}/${bunExe}
|
||||
--revision
|
||||
-E env BUN_DEBUG_QUIET_LOGS=1
|
||||
${BUN_EXE_OUTPUT}
|
||||
--revision
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
)
|
||||
@@ -1090,7 +1062,7 @@ if(NOT BUN_CPP_ONLY)
|
||||
BUN_GARBAGE_COLLECTOR_LEVEL=1
|
||||
BUN_DEBUG_QUIET_LOGS=1
|
||||
BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING=1
|
||||
${BUILD_PATH}/${bunExe}
|
||||
${BUN_EXE_OUTPUT}
|
||||
${BUN_FEATURES_SCRIPT}
|
||||
CWD
|
||||
${BUILD_PATH}
|
||||
@@ -1099,7 +1071,7 @@ if(NOT BUN_CPP_ONLY)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_HOST_APPLE AND bunStrip)
|
||||
if(bunStrip AND APPLE)
|
||||
register_command(
|
||||
TARGET
|
||||
${bun}
|
||||
@@ -1129,7 +1101,7 @@ if(NOT BUN_CPP_ONLY)
|
||||
set(bunTriplet bun-${OS}-${ARCH})
|
||||
endif()
|
||||
string(REPLACE bun ${bunTriplet} bunPath ${bun})
|
||||
set(bunFiles ${bunExe} features.json)
|
||||
set(bunFiles ${BUN_EXE_OUTPUT} features.json)
|
||||
if(WIN32)
|
||||
list(APPEND bunFiles ${bun}.pdb)
|
||||
elseif(APPLE)
|
||||
@@ -1166,7 +1138,7 @@ if(NOT BUN_CPP_ONLY)
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -rf ${bunStripPath} ${bunStripPath}.zip
|
||||
&& ${CMAKE_COMMAND} -E make_directory ${bunStripPath}
|
||||
&& ${CMAKE_COMMAND} -E copy ${bunStripExe} ${bunStripPath}
|
||||
&& ${CMAKE_COMMAND} -E copy ${${BUN_EXE_STRIP_OUTPUT}} ${bunStripPath}
|
||||
&& ${CMAKE_COMMAND} -E tar cfv ${bunStripPath}.zip --format=zip ${bunStripPath}
|
||||
&& ${CMAKE_COMMAND} -E rm -rf ${bunStripPath}
|
||||
CWD
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
register_vendor_target(cares)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
cares
|
||||
${cares}
|
||||
REPOSITORY
|
||||
c-ares/c-ares
|
||||
COMMIT
|
||||
d1722e6e8acaf10eb73fa995798a9cd421d9f85e
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
cares
|
||||
TARGETS
|
||||
c-ares
|
||||
ARGS
|
||||
-DCARES_STATIC=ON
|
||||
-DCARES_STATIC_PIC=ON # FORCE_PIC was set to 1, but CARES_STATIC_PIC was set to OFF??
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
-DCARES_SHARED=OFF
|
||||
-DCARES_BUILD_TOOLS=OFF # this was set to ON?
|
||||
LIB_PATH
|
||||
lib
|
||||
LIBRARIES
|
||||
cares
|
||||
INCLUDES
|
||||
include
|
||||
register_libraries(
|
||||
TARGET ${cares}
|
||||
PATH lib
|
||||
cares
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${cares}
|
||||
CMAKE_TARGET
|
||||
c-ares
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${cares}
|
||||
CARES_STATIC=ON
|
||||
CARES_STATIC_PIC=ON
|
||||
CARES_SHARED=OFF
|
||||
CARES_BUILD_TOOLS=OFF
|
||||
CMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
)
|
||||
|
||||
@@ -1,53 +1,61 @@
|
||||
register_vendor_target(libarchive)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
libarchive
|
||||
${libarchive}
|
||||
REPOSITORY
|
||||
libarchive/libarchive
|
||||
COMMIT
|
||||
898dc8319355b7e985f68a9819f182aaed61b53a
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
libarchive
|
||||
TARGETS
|
||||
archive_static
|
||||
ARGS
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DENABLE_INSTALL=OFF
|
||||
-DENABLE_TEST=OFF
|
||||
-DENABLE_WERROR=OFF
|
||||
-DENABLE_BZIP2=OFF
|
||||
-DENABLE_CAT=OFF
|
||||
-DENABLE_EXPAT=OFF
|
||||
-DENABLE_ICONV=OFF
|
||||
-DENABLE_LIBB2=OFF
|
||||
-DENABLE_LibGCC=OFF
|
||||
-DENABLE_LIBXML2=OFF
|
||||
-DENABLE_LZ4=OFF
|
||||
-DENABLE_LZMA=OFF
|
||||
-DENABLE_LZO=OFF
|
||||
-DENABLE_MBEDTLS=OFF
|
||||
-DENABLE_NETTLE=OFF
|
||||
-DENABLE_OPENSSL=OFF
|
||||
-DENABLE_PCRE2POSIX=OFF
|
||||
-DENABLE_PCREPOSIX=OFF
|
||||
-DENABLE_ZSTD=OFF
|
||||
# libarchive depends on zlib headers, otherwise it will
|
||||
# spawn a processes to compress instead of using the library.
|
||||
-DENABLE_ZLIB=OFF
|
||||
-DHAVE_ZLIB_H=ON
|
||||
-DCMAKE_C_FLAGS="-I${VENDOR_PATH}/zlib"
|
||||
LIB_PATH
|
||||
libarchive
|
||||
LIBRARIES
|
||||
archive
|
||||
INCLUDES
|
||||
include
|
||||
register_libraries(
|
||||
TARGET ${libarchive}
|
||||
PATH libarchive
|
||||
archive
|
||||
)
|
||||
|
||||
# Must be loaded after zlib is defined
|
||||
if(TARGET clone-zlib)
|
||||
add_dependencies(libarchive clone-zlib)
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${libarchive}
|
||||
CMAKE_TARGET
|
||||
archive_static
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${libarchive}
|
||||
CMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
BUILD_SHARED_LIBS=OFF
|
||||
ENABLE_INSTALL=OFF
|
||||
ENABLE_TEST=OFF
|
||||
ENABLE_WERROR=OFF
|
||||
ENABLE_BZIP2=OFF
|
||||
ENABLE_CAT=OFF
|
||||
ENABLE_EXPAT=OFF
|
||||
ENABLE_ICONV=OFF
|
||||
ENABLE_LIBB2=OFF
|
||||
ENABLE_LibGCC=OFF
|
||||
ENABLE_LIBXML2=OFF
|
||||
ENABLE_LZ4=OFF
|
||||
ENABLE_LZMA=OFF
|
||||
ENABLE_LZO=OFF
|
||||
ENABLE_MBEDTLS=OFF
|
||||
ENABLE_NETTLE=OFF
|
||||
ENABLE_OPENSSL=OFF
|
||||
ENABLE_PCRE2POSIX=OFF
|
||||
ENABLE_PCREPOSIX=OFF
|
||||
ENABLE_ZSTD=OFF
|
||||
ENABLE_ZLIB=OFF
|
||||
HAVE_ZLIB_H=ON
|
||||
)
|
||||
|
||||
# libarchive depends on zlib headers, otherwise it will
|
||||
# spawn a processes to compress instead of using the library.
|
||||
register_includes(
|
||||
TARGET ${libarchive}
|
||||
${VENDOR_PATH}/${zlib}
|
||||
)
|
||||
|
||||
if(TARGET clone-${zlib})
|
||||
add_dependencies(${libarchive} clone-${zlib})
|
||||
endif()
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
register_vendor_target(libdeflate)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
libdeflate
|
||||
${libdeflate}
|
||||
REPOSITORY
|
||||
ebiggers/libdeflate
|
||||
COMMIT
|
||||
dc76454a39e7e83b68c3704b6e3784654f8d5ac5
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
libdeflate
|
||||
TARGETS
|
||||
libdeflate_static
|
||||
ARGS
|
||||
-DLIBDEFLATE_BUILD_STATIC_LIB=ON
|
||||
-DLIBDEFLATE_BUILD_SHARED_LIB=OFF
|
||||
-DLIBDEFLATE_BUILD_GZIP=OFF
|
||||
LIBRARIES
|
||||
deflatestatic WIN32
|
||||
deflate UNIX
|
||||
INCLUDES
|
||||
.
|
||||
register_libraries(
|
||||
TARGET ${libdeflate}
|
||||
deflatestatic ${WIN32}
|
||||
deflate ${UNIX}
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${libdeflate}
|
||||
CMAKE_TARGET
|
||||
libdeflate_static
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${libdeflate}
|
||||
LIBDEFLATE_BUILD_STATIC_LIB=ON
|
||||
LIBDEFLATE_BUILD_SHARED_LIB=OFF
|
||||
LIBDEFLATE_BUILD_GZIP=OFF
|
||||
)
|
||||
|
||||
@@ -1,29 +1,39 @@
|
||||
register_vendor_target(libuv)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
libuv
|
||||
${libuv}
|
||||
REPOSITORY
|
||||
libuv/libuv
|
||||
COMMIT
|
||||
da527d8d2a908b824def74382761566371439003
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(LIBUV_CMAKE_C_FLAGS "/DWIN32 /D_WINDOWS -Wno-int-conversion")
|
||||
endif()
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
libuv
|
||||
TARGETS
|
||||
uv_a
|
||||
ARGS
|
||||
-DLIBUV_BUILD_SHARED=OFF
|
||||
-DLIBUV_BUILD_TESTS=OFF
|
||||
-DLIBUV_BUILD_BENCH=OFF
|
||||
-DCMAKE_C_FLAGS=${LIBUV_CMAKE_C_FLAGS}
|
||||
LIBRARIES
|
||||
libuv WIN32
|
||||
uv UNIX
|
||||
INCLUDES
|
||||
include
|
||||
register_libraries(
|
||||
TARGET ${libuv}
|
||||
uv_a ${WIN32}
|
||||
uv ${UNIX}
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${libuv}
|
||||
CMAKE_TARGET
|
||||
uv_a
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${libuv}
|
||||
LIBUV_BUILD_SHARED=OFF
|
||||
LIBUV_BUILD_TESTS=OFF
|
||||
LIBUV_BUILD_BENCH=OFF
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
register_compiler_flags(
|
||||
TARGET ${libuv}
|
||||
/DWIN32
|
||||
/D_WINDOWS
|
||||
-Wno-int-conversion
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,45 +1,50 @@
|
||||
register_vendor_target(lolhtml)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
lolhtml
|
||||
${lolhtml}
|
||||
REPOSITORY
|
||||
cloudflare/lol-html
|
||||
COMMIT
|
||||
8d4c273ded322193d017042d1f48df2766b0f88b
|
||||
)
|
||||
|
||||
set(LOLHTML_CWD ${VENDOR_PATH}/lolhtml/c-api)
|
||||
set(LOLHTML_BUILD_PATH ${BUILD_PATH}/lolhtml)
|
||||
|
||||
if(DEBUG)
|
||||
set(LOLHTML_BUILD_TYPE debug)
|
||||
set(${lolhtml}_BUILD_TYPE debug)
|
||||
else()
|
||||
set(LOLHTML_BUILD_TYPE release)
|
||||
set(${lolhtml}_BUILD_TYPE release)
|
||||
endif()
|
||||
|
||||
set(LOLHTML_LIBRARY ${LOLHTML_BUILD_PATH}/${LOLHTML_BUILD_TYPE}/${CMAKE_STATIC_LIBRARY_PREFIX}lolhtml${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
register_libraries(
|
||||
TARGET ${lolhtml}
|
||||
PATH ${${lolhtml}_BUILD_TYPE}
|
||||
VARIABLE ${lolhtml}_LIBRARY
|
||||
lolhtml
|
||||
)
|
||||
|
||||
set(LOLHTML_BUILD_ARGS
|
||||
--target-dir ${BUILD_PATH}/lolhtml
|
||||
set(${lolhtml}_BUILD_COMMAND
|
||||
${CARGO_EXECUTABLE}
|
||||
build
|
||||
--target-dir ${${lolhtml}_BUILD_PATH}
|
||||
)
|
||||
|
||||
if(RELEASE)
|
||||
list(APPEND LOLHTML_BUILD_ARGS --release)
|
||||
list(APPEND ${lolhtml}_BUILD_COMMAND --release)
|
||||
endif()
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
lolhtml
|
||||
build-${lolhtml}
|
||||
CWD
|
||||
${LOLHTML_CWD}
|
||||
${${lolhtml}_CWD}/c-api
|
||||
COMMAND
|
||||
${CARGO_EXECUTABLE}
|
||||
build
|
||||
${LOLHTML_BUILD_ARGS}
|
||||
${${lolhtml}_BUILD_COMMAND}
|
||||
ARTIFACTS
|
||||
${LOLHTML_LIBRARY}
|
||||
${${lolhtml}_LIBRARY}
|
||||
)
|
||||
|
||||
target_link_libraries(${bun} PRIVATE ${LOLHTML_LIBRARY})
|
||||
if(BUN_LINK_ONLY)
|
||||
target_sources(${bun} PRIVATE ${LOLHTML_LIBRARY})
|
||||
if(TARGET clone-${lolhtml})
|
||||
add_dependencies(build-${lolhtml} clone-${lolhtml})
|
||||
endif()
|
||||
|
||||
add_dependencies(${lolhtml} build-${lolhtml})
|
||||
|
||||
@@ -1,33 +1,42 @@
|
||||
register_vendor_target(lshpack)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
lshpack
|
||||
${lshpack}
|
||||
REPOSITORY
|
||||
litespeedtech/ls-hpack
|
||||
COMMIT
|
||||
3d0f1fc1d6e66a642e7a98c55deb38aa986eb4b0
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(LSHPACK_INCLUDES . compat/queue)
|
||||
else()
|
||||
set(LSHPACK_INCLUDES .)
|
||||
endif()
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
lshpack
|
||||
LIBRARIES
|
||||
ls-hpack
|
||||
ARGS
|
||||
-DSHARED=OFF
|
||||
-DLSHPACK_XXH=ON
|
||||
# There are linking errors when built with non-Release
|
||||
# Undefined symbols for architecture arm64:
|
||||
# "___asan_handle_no_return", referenced from:
|
||||
# _lshpack_enc_get_static_nameval in libls-hpack.a(lshpack.c.o)
|
||||
# _lshpack_enc_get_static_name in libls-hpack.a(lshpack.c.o)
|
||||
# _update_hash in libls-hpack.a(lshpack.c.o)
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
INCLUDES
|
||||
${LSHPACK_INCLUDES}
|
||||
register_libraries(
|
||||
TARGET ${lshpack}
|
||||
ls-hpack
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${lshpack}
|
||||
CMAKE_TARGET
|
||||
ls-hpack
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${lshpack}
|
||||
SHARED=OFF
|
||||
LSHPACK_XXH=ON
|
||||
BUILD_TESTING=OFF
|
||||
)
|
||||
|
||||
# FIXME: There are linking errors when built with non-Release
|
||||
# Undefined symbols for architecture arm64:
|
||||
# "___asan_handle_no_return", referenced from:
|
||||
# _lshpack_enc_get_static_nameval in libls-hpack.a(lshpack.c.o)
|
||||
# _lshpack_enc_get_static_name in libls-hpack.a(lshpack.c.o)
|
||||
# _update_hash in libls-hpack.a(lshpack.c.o)
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
register_cmake_definitions(
|
||||
TARGET ${lshpack}
|
||||
CMAKE_BUILD_TYPE=Release
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,60 +1,63 @@
|
||||
register_vendor_target(mimalloc)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
mimalloc
|
||||
${mimalloc}
|
||||
REPOSITORY
|
||||
oven-sh/mimalloc
|
||||
COMMIT
|
||||
4c283af60cdae205df5a872530c77e2a6a307d43
|
||||
)
|
||||
|
||||
set(MIMALLOC_CMAKE_ARGS
|
||||
-DMI_BUILD_STATIC=ON
|
||||
-DMI_BUILD_OBJECT=ON
|
||||
-DMI_BUILD_SHARED=OFF
|
||||
-DMI_BUILD_TESTS=OFF
|
||||
-DMI_USE_CXX=ON
|
||||
-DMI_OVERRIDE=OFF
|
||||
-DMI_OSX_ZONE=OFF
|
||||
-DMI_OSX_INTERPOSE=OFF
|
||||
-DMI_SKIP_COLLECT_ON_EXIT=ON
|
||||
)
|
||||
|
||||
if(DEBUG)
|
||||
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_DEBUG_FULL=ON)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VALGRIND)
|
||||
list(APPEND MIMALLOC_CMAKE_ARGS -DMI_VALGRIND=ON)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(DEBUG)
|
||||
set(MIMALLOC_LIBRARY mimalloc-static-debug)
|
||||
else()
|
||||
set(MIMALLOC_LIBRARY mimalloc-static)
|
||||
endif()
|
||||
elseif(DEBUG)
|
||||
set(MIMALLOC_LIBRARY mimalloc-debug)
|
||||
else()
|
||||
set(MIMALLOC_LIBRARY mimalloc)
|
||||
endif()
|
||||
|
||||
# Workaround for linker issue on macOS and Linux x64
|
||||
# https://github.com/microsoft/mimalloc/issues/512
|
||||
if(APPLE OR (LINUX AND NOT DEBUG))
|
||||
set(MIMALLOC_LIBRARY CMakeFiles/mimalloc-obj.dir/src/static.c.o)
|
||||
register_libraries(
|
||||
TARGET ${mimalloc}
|
||||
PATH CMakeFiles/mimalloc-obj.dir/src
|
||||
static.c.o
|
||||
)
|
||||
else()
|
||||
register_libraries(
|
||||
TARGET ${mimalloc}
|
||||
mimalloc-static-debug ${WIN32} AND ${DEBUG}
|
||||
mimalloc-static ${WIN32} AND ${RELEASE}
|
||||
mimalloc-debug ${UNIX} AND ${DEBUG}
|
||||
mimalloc ${UNIX} AND ${RELEASE}
|
||||
)
|
||||
endif()
|
||||
|
||||
register_cmake_command(
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
mimalloc
|
||||
TARGETS
|
||||
${mimalloc}
|
||||
CMAKE_TARGETS
|
||||
mimalloc-static
|
||||
mimalloc-obj
|
||||
ARGS
|
||||
${MIMALLOC_CMAKE_ARGS}
|
||||
LIBRARIES
|
||||
${MIMALLOC_LIBRARY}
|
||||
INCLUDES
|
||||
include
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${mimalloc}
|
||||
MI_BUILD_STATIC=ON
|
||||
MI_BUILD_OBJECT=ON
|
||||
MI_BUILD_SHARED=OFF
|
||||
MI_BUILD_TESTS=OFF
|
||||
MI_USE_CXX=ON
|
||||
MI_OVERRIDE=OFF
|
||||
MI_OSX_ZONE=OFF
|
||||
MI_OSX_INTERPOSE=OFF
|
||||
MI_SKIP_COLLECT_ON_EXIT=ON
|
||||
)
|
||||
|
||||
if(ENABLE_ASSERTIONS)
|
||||
register_cmake_definitions(
|
||||
TARGET ${mimalloc}
|
||||
MI_DEBUG_FULL=ON
|
||||
MI_SHOW_ERRORS=ON
|
||||
)
|
||||
if(ENABLE_VALGRIND)
|
||||
register_cmake_definitions(
|
||||
TARGET ${mimalloc}
|
||||
MI_VALGRIND=ON
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
12
cmake/targets/BuildPicoHTTPParser.cmake
Normal file
12
cmake/targets/BuildPicoHTTPParser.cmake
Normal file
@@ -0,0 +1,12 @@
|
||||
register_vendor_target(picohttpparser)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
${picohttpparser}
|
||||
REPOSITORY
|
||||
h2o/picohttpparser
|
||||
COMMIT
|
||||
066d2b1e9ab820703db0837a7255d92d30f0c9f5
|
||||
OUTPUTS
|
||||
picohttpparser.c
|
||||
)
|
||||
@@ -1,10 +1,13 @@
|
||||
register_cmake_command(
|
||||
register_vendor_target(sqlite)
|
||||
|
||||
register_libraries(
|
||||
TARGET ${sqlite}
|
||||
sqlite3
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
sqlite
|
||||
${sqlite}
|
||||
CWD
|
||||
${CWD}/src/bun.js/bindings/sqlite
|
||||
LIBRARIES
|
||||
sqlite3
|
||||
INCLUDES
|
||||
.
|
||||
)
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
register_vendor_target(tinycc)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
tinycc
|
||||
${tinycc}
|
||||
REPOSITORY
|
||||
oven-sh/tinycc
|
||||
COMMIT
|
||||
29985a3b59898861442fa3b43f663fc1af2591d7
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
tinycc
|
||||
LIBRARIES
|
||||
tcc
|
||||
register_libraries(
|
||||
TARGET ${tinycc}
|
||||
tcc
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${tinycc}
|
||||
)
|
||||
|
||||
88
cmake/targets/BuildWebKit.cmake
Normal file
88
cmake/targets/BuildWebKit.cmake
Normal file
@@ -0,0 +1,88 @@
|
||||
optionx(WEBKIT_LOCAL BOOL "If a local version of WebKit should be used instead of downloading" DEFAULT OFF)
|
||||
optionx(WEBKIT_VERSION STRING "The version of WebKit to use" DEFAULT "4a2db3254a9535949a5d5380eb58cf0f77c8e15a")
|
||||
|
||||
if(WEBKIT_LOCAL)
|
||||
set(DEFAULT_WEBKIT_PATH ${VENDOR_PATH}/WebKit/WebKitBuild/${CMAKE_BUILD_TYPE})
|
||||
else()
|
||||
set(DEFAULT_WEBKIT_PATH ${VENDOR_PATH}/webkit)
|
||||
endif()
|
||||
|
||||
optionx(WEBKIT_PATH FILEPATH "The path to the WebKit directory" DEFAULT ${DEFAULT_WEBKIT_PATH})
|
||||
|
||||
set(WEBKIT_INCLUDE_PATH ${WEBKIT_PATH}/include)
|
||||
set(WEBKIT_LIB_PATH ${WEBKIT_PATH}/lib)
|
||||
|
||||
register_vendor_target(webkit)
|
||||
|
||||
register_libraries(
|
||||
TARGET ${webkit}
|
||||
PATH ${WEBKIT_PATH}/lib
|
||||
JavaScriptCore
|
||||
WTF
|
||||
bmalloc ${LINUX}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
register_libraries(
|
||||
TARGET ${webkit}
|
||||
PATH ${WEBKIT_PATH}/lib
|
||||
sicudt ${RELEASE}
|
||||
sicudtd ${DEBUG}
|
||||
sicuin ${RELEASE}
|
||||
sicuind ${DEBUG}
|
||||
sicuuc ${RELEASE}
|
||||
sicuucd ${DEBUG}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WEBKIT_LOCAL)
|
||||
# Must be built seperately, in the future this can be integrated into the build process
|
||||
register_target(build-webkit)
|
||||
else()
|
||||
if(WIN32)
|
||||
set(WEBKIT_OS "windows")
|
||||
elseif(APPLE)
|
||||
set(WEBKIT_OS "macos")
|
||||
elseif(LINUX)
|
||||
set(WEBKIT_OS "linux")
|
||||
else()
|
||||
unsupported(CMAKE_SYSTEM_NAME)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|ARM64|aarch64|AARCH64")
|
||||
set(WEBKIT_ARCH "arm64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|AMD64|x86_64|X86_64|x64|X64")
|
||||
set(WEBKIT_ARCH "amd64")
|
||||
else()
|
||||
unsupported(CMAKE_SYSTEM_PROCESSOR)
|
||||
endif()
|
||||
|
||||
if(DEBUG)
|
||||
set(WEBKIT_SUFFIX "-debug")
|
||||
elseif(ENABLE_LTO AND NOT WIN32)
|
||||
set(WEBKIT_SUFFIX "-lto")
|
||||
else()
|
||||
set(WEBKIT_SUFFIX "")
|
||||
endif()
|
||||
|
||||
set(WEBKIT_NAME bun-webkit-${WEBKIT_OS}-${WEBKIT_ARCH}${WEBKIT_SUFFIX})
|
||||
set(WEBKIT_DOWNLOAD_URL https://github.com/oven-sh/WebKit/releases/download/autobuild-${WEBKIT_VERSION}/${WEBKIT_NAME}.tar.gz)
|
||||
|
||||
get_libraries(${webkit} WEBKIT_LIBRARIES)
|
||||
register_command(
|
||||
TARGET
|
||||
clone-${webkit}
|
||||
COMMENT
|
||||
"Downloading ${WEBKIT_NAME}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DDOWNLOAD_PATH=${WEBKIT_PATH}
|
||||
-DDOWNLOAD_URL=${WEBKIT_DOWNLOAD_URL}
|
||||
-P ${CWD}/cmake/scripts/DownloadUrl.cmake
|
||||
OUTPUTS
|
||||
${WEBKIT_PATH}/package.json
|
||||
${WEBKIT_LIBRARIES}
|
||||
)
|
||||
|
||||
register_outputs(TARGET clone-${webkit} ${WEBKIT_PATH})
|
||||
endif()
|
||||
@@ -1,40 +1,38 @@
|
||||
register_vendor_target(zlib)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
zlib
|
||||
${zlib}
|
||||
REPOSITORY
|
||||
cloudflare/zlib
|
||||
COMMIT
|
||||
886098f3f339617b4243b286f5ed364b9989e245
|
||||
)
|
||||
|
||||
register_libraries(
|
||||
TARGET ${zlib}
|
||||
z ${UNIX}
|
||||
zlib ${WIN32} AND ${RELEASE}
|
||||
zlibd ${WIN32} AND ${DEBUG}
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${zlib}
|
||||
CMAKE_TARGET
|
||||
zlib
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${zlib}
|
||||
BUILD_SHARED_LIBS=OFF
|
||||
BUILD_EXAMPLES=OFF
|
||||
)
|
||||
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/25755
|
||||
if(APPLE)
|
||||
set(ZLIB_CMAKE_C_FLAGS "-fno-define-target-os-macros")
|
||||
set(ZLIB_CMAKE_CXX_FLAGS "-fno-define-target-os-macros")
|
||||
register_compiler_flags(
|
||||
TARGET ${zlib}
|
||||
-fno-define-target-os-macros
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(DEBUG)
|
||||
set(ZLIB_LIBRARY "zlibd")
|
||||
else()
|
||||
set(ZLIB_LIBRARY "zlib")
|
||||
endif()
|
||||
else()
|
||||
set(ZLIB_LIBRARY "z")
|
||||
endif()
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
zlib
|
||||
TARGETS
|
||||
zlib
|
||||
ARGS
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DBUILD_EXAMPLES=OFF
|
||||
"-DCMAKE_C_FLAGS=${ZLIB_CMAKE_C_FLAGS}"
|
||||
"-DCMAKE_CXX_FLAGS=${ZLIB_CMAKE_CXX_FLAGS}"
|
||||
LIBRARIES
|
||||
${ZLIB_LIBRARY}
|
||||
INCLUDES
|
||||
.
|
||||
)
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
register_vendor_target(zstd)
|
||||
|
||||
register_repository(
|
||||
NAME
|
||||
zstd
|
||||
${zstd}
|
||||
REPOSITORY
|
||||
facebook/zstd
|
||||
COMMIT
|
||||
794ea1b0afca0f020f4e57b6732332231fb23c70
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
TARGET
|
||||
zstd
|
||||
TARGETS
|
||||
libzstd_static
|
||||
ARGS
|
||||
-Sbuild/cmake
|
||||
-DZSTD_BUILD_STATIC=ON
|
||||
-DZSTD_BUILD_PROGRAMS=OFF
|
||||
-DZSTD_BUILD_TESTS=OFF
|
||||
-DZSTD_BUILD_CONTRIB=OFF
|
||||
LIB_PATH
|
||||
lib
|
||||
LIBRARIES
|
||||
zstd_static WIN32
|
||||
zstd UNIX
|
||||
register_libraries(
|
||||
TARGET ${zstd}
|
||||
PATH lib
|
||||
zstd_static ${WIN32}
|
||||
zstd ${UNIX}
|
||||
)
|
||||
|
||||
register_cmake_project(
|
||||
TARGET
|
||||
${zstd}
|
||||
CMAKE_TARGET
|
||||
libzstd_static
|
||||
CMAKE_PATH
|
||||
build/cmake
|
||||
)
|
||||
|
||||
register_cmake_definitions(
|
||||
TARGET ${zstd}
|
||||
ZSTD_BUILD_STATIC=ON
|
||||
ZSTD_BUILD_PROGRAMS=OFF
|
||||
ZSTD_BUILD_TESTS=OFF
|
||||
ZSTD_BUILD_CONTRIB=OFF
|
||||
)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
optionx(BUILDKITE_CACHE BOOL "If the build can use Buildkite caches, even if not running in Buildkite" DEFAULT ${BUILDKITE})
|
||||
|
||||
if(NOT BUILDKITE_CACHE OR NOT BUN_LINK_ONLY)
|
||||
if(NOT BUN_LINK_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -33,7 +31,7 @@ if(NOT BUILDKITE_BUILD_ID)
|
||||
endif()
|
||||
|
||||
setx(BUILDKITE_BUILD_URL https://buildkite.com/${BUILDKITE_ORGANIZATION_SLUG}/${BUILDKITE_PIPELINE_SLUG}/builds/${BUILDKITE_BUILD_ID})
|
||||
setx(BUILDKITE_BUILD_PATH ${BUILDKITE_BUILDS_PATH}/builds/${BUILDKITE_BUILD_ID})
|
||||
setx(BUILDKITE_BUILD_PATH ${BUILDKITE_BUILDS_PATH}/${BUILDKITE_BUILD_ID})
|
||||
|
||||
file(
|
||||
DOWNLOAD ${BUILDKITE_BUILD_URL}
|
||||
@@ -125,15 +123,14 @@ foreach(i RANGE ${BUILDKITE_JOBS_MAX_INDEX})
|
||||
set(BUILDKITE_DOWNLOAD_COMMAND curl -L -o ${BUILDKITE_ARTIFACT_PATH} ${BUILDKITE_ARTIFACTS_URL}/${BUILDKITE_ARTIFACT_ID})
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
COMMENT
|
||||
"Downloading ${BUILDKITE_ARTIFACT_PATH}"
|
||||
VERBATIM COMMAND
|
||||
${BUILDKITE_DOWNLOAD_COMMAND}
|
||||
WORKING_DIRECTORY
|
||||
${BUILD_PATH}
|
||||
OUTPUT
|
||||
${BUILD_PATH}/${BUILDKITE_ARTIFACT_PATH}
|
||||
message(STATUS "Downloading ${BUILD_PATH}/${BUILDKITE_ARTIFACT_PATH}")
|
||||
get_filename_component(BUILDKITE_ARTIFACT_NAME ${BUILDKITE_ARTIFACT_PATH} NAME_WE)
|
||||
register_command(
|
||||
TARGET download-${BUILDKITE_ARTIFACT_NAME}
|
||||
COMMENT "Downloading ${BUILDKITE_ARTIFACT_PATH}"
|
||||
COMMAND ${BUILDKITE_DOWNLOAD_COMMAND}
|
||||
CWD ${BUILD_PATH}
|
||||
OUTPUTS ${BUILD_PATH}/${BUILDKITE_ARTIFACT_PATH}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
@@ -14,11 +14,8 @@ find_command(
|
||||
ON
|
||||
)
|
||||
|
||||
set(CCACHE_ARGS CMAKE_C_COMPILER_LAUNCHER CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
foreach(arg ${CCACHE_ARGS})
|
||||
setx(${arg} ${CCACHE_PROGRAM})
|
||||
list(APPEND CMAKE_ARGS -D${arg}=${${arg}})
|
||||
endforeach()
|
||||
setx(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
setx(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
|
||||
setenv(CCACHE_DIR ${CACHE_PATH}/ccache)
|
||||
setenv(CCACHE_BASEDIR ${CWD})
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
find_command(
|
||||
VARIABLE
|
||||
GIT_PROGRAM
|
||||
COMMAND
|
||||
git
|
||||
REQUIRED
|
||||
OFF
|
||||
)
|
||||
|
||||
if(NOT GIT_PROGRAM)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(GIT_DIFF_COMMAND ${GIT_PROGRAM} diff --no-color --name-only --diff-filter=AMCR)
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${GIT_DIFF_COMMAND}
|
||||
WORKING_DIRECTORY
|
||||
${CWD}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE
|
||||
GIT_DIFF
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_VARIABLE
|
||||
GIT_DIFF_ERROR
|
||||
RESULT_VARIABLE
|
||||
GIT_DIFF_RESULT
|
||||
)
|
||||
|
||||
if(NOT GIT_DIFF_RESULT EQUAL 0)
|
||||
message(${WARNING} "Command failed: ${GIT_DIFF_COMMAND} ${GIT_DIFF_ERROR}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(REPLACE "\n" ";" GIT_CHANGED_SOURCES "${GIT_DIFF}")
|
||||
list(TRANSFORM GIT_CHANGED_SOURCES PREPEND ${CWD}/)
|
||||
list(LENGTH GIT_CHANGED_SOURCES GIT_CHANGED_SOURCES_COUNT)
|
||||
@@ -1,9 +1,3 @@
|
||||
optionx(SKIP_LLVM BOOL "If LLVM setup should be skipped" DEFAULT OFF)
|
||||
|
||||
if(SKIP_LLVM)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(CMAKE_HOST_WIN32 OR CMAKE_HOST_APPLE)
|
||||
set(DEFAULT_LLVM_VERSION "18.1.8")
|
||||
else()
|
||||
@@ -39,7 +33,6 @@ macro(find_llvm_command VARIABLE COMMAND)
|
||||
PATHS ${LLVM_PATH}
|
||||
VERSION ${LLVM_VERSION}
|
||||
)
|
||||
list(APPEND CMAKE_ARGS -D${VARIABLE}=${${VARIABLE}})
|
||||
endmacro()
|
||||
|
||||
macro(find_llvm_command_no_version VARIABLE COMMAND)
|
||||
@@ -49,7 +42,6 @@ macro(find_llvm_command_no_version VARIABLE COMMAND)
|
||||
PATHS ${LLVM_PATH}
|
||||
REQUIRED ON
|
||||
)
|
||||
list(APPEND CMAKE_ARGS -D${VARIABLE}=${${VARIABLE}})
|
||||
endmacro()
|
||||
|
||||
if(WIN32)
|
||||
|
||||
@@ -52,8 +52,3 @@ if(CMAKE_OSX_SYSROOT_ERROR)
|
||||
endif()
|
||||
|
||||
optionx(CMAKE_OSX_SYSROOT STRING "The macOS SDK path to target" DEFAULT ${DEFAULT_CMAKE_OSX_SYSROOT})
|
||||
|
||||
list(APPEND CMAKE_ARGS
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}
|
||||
-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}
|
||||
)
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
option(WEBKIT_VERSION "The version of WebKit to use")
|
||||
option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading")
|
||||
|
||||
if(NOT WEBKIT_VERSION)
|
||||
set(WEBKIT_VERSION a303e09b6535ee560969b0310de50878cb66b454)
|
||||
endif()
|
||||
|
||||
if(WEBKIT_LOCAL)
|
||||
set(DEFAULT_WEBKIT_PATH ${VENDOR_PATH}/WebKit/WebKitBuild/${CMAKE_BUILD_TYPE})
|
||||
else()
|
||||
set(DEFAULT_WEBKIT_PATH ${CACHE_PATH}/webkit-${WEBKIT_VERSION})
|
||||
endif()
|
||||
|
||||
option(WEBKIT_PATH "The path to the WebKit directory")
|
||||
|
||||
if(NOT WEBKIT_PATH)
|
||||
set(WEBKIT_PATH ${DEFAULT_WEBKIT_PATH})
|
||||
endif()
|
||||
|
||||
set(WEBKIT_INCLUDE_PATH ${WEBKIT_PATH}/include)
|
||||
set(WEBKIT_LIB_PATH ${WEBKIT_PATH}/lib)
|
||||
|
||||
if(WEBKIT_LOCAL)
|
||||
if(EXISTS ${WEBKIT_PATH}/cmakeconfig.h)
|
||||
# You may need to run:
|
||||
# make jsc-compile-debug jsc-copy-headers
|
||||
include_directories(
|
||||
${WEBKIT_PATH}
|
||||
${WEBKIT_PATH}/JavaScriptCore/Headers/JavaScriptCore
|
||||
${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders
|
||||
${WEBKIT_PATH}/bmalloc/Headers
|
||||
${WEBKIT_PATH}/WTF/Headers
|
||||
)
|
||||
endif()
|
||||
|
||||
# After this point, only prebuilt WebKit is supported
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(EXISTS ${WEBKIT_PATH}/package.json)
|
||||
file(READ ${WEBKIT_PATH}/package.json WEBKIT_PACKAGE_JSON)
|
||||
|
||||
if(WEBKIT_PACKAGE_JSON MATCHES ${WEBKIT_VERSION})
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(WEBKIT_OS "windows")
|
||||
elseif(APPLE)
|
||||
set(WEBKIT_OS "macos")
|
||||
elseif(UNIX)
|
||||
set(WEBKIT_OS "linux")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported operating system: ${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
|
||||
set(WEBKIT_ARCH "arm64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|x64|AMD64")
|
||||
set(WEBKIT_ARCH "amd64")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if(DEBUG)
|
||||
set(WEBKIT_SUFFIX "-debug")
|
||||
elseif(ENABLE_LTO AND NOT WIN32)
|
||||
set(WEBKIT_SUFFIX "-lto")
|
||||
else()
|
||||
set(WEBKIT_SUFFIX "")
|
||||
endif()
|
||||
|
||||
set(WEBKIT_NAME bun-webkit-${WEBKIT_OS}-${WEBKIT_ARCH}${WEBKIT_SUFFIX})
|
||||
set(WEBKIT_FILENAME ${WEBKIT_NAME}.tar.gz)
|
||||
setx(WEBKIT_DOWNLOAD_URL https://github.com/oven-sh/WebKit/releases/download/autobuild-${WEBKIT_VERSION}/${WEBKIT_FILENAME})
|
||||
|
||||
file(DOWNLOAD ${WEBKIT_DOWNLOAD_URL} ${CACHE_PATH}/${WEBKIT_FILENAME} SHOW_PROGRESS)
|
||||
file(ARCHIVE_EXTRACT INPUT ${CACHE_PATH}/${WEBKIT_FILENAME} DESTINATION ${CACHE_PATH} TOUCH)
|
||||
file(REMOVE ${CACHE_PATH}/${WEBKIT_FILENAME})
|
||||
file(REMOVE_RECURSE ${WEBKIT_PATH})
|
||||
file(RENAME ${CACHE_PATH}/bun-webkit ${WEBKIT_PATH})
|
||||
|
||||
if(APPLE)
|
||||
file(REMOVE_RECURSE ${WEBKIT_INCLUDE_PATH}/unicode)
|
||||
endif()
|
||||
@@ -16,8 +16,6 @@ else()
|
||||
unsupported(CMAKE_SYSTEM_NAME)
|
||||
endif()
|
||||
|
||||
optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.13.0")
|
||||
optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "131a009ba2eb127a3447d05b9e12f710429aa5ee")
|
||||
optionx(ZIG_TARGET STRING "The zig target to use" DEFAULT ${DEFAULT_ZIG_TARGET})
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
@@ -66,18 +64,12 @@ set(CMAKE_ZIG_FLAGS
|
||||
)
|
||||
|
||||
register_command(
|
||||
TARGET
|
||||
clone-zig
|
||||
COMMENT
|
||||
"Downloading zig"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DZIG_PATH=${ZIG_PATH}
|
||||
-DZIG_VERSION=${ZIG_VERSION}
|
||||
-DZIG_COMMIT=${ZIG_COMMIT}
|
||||
-P ${CWD}/cmake/scripts/DownloadZig.cmake
|
||||
SOURCES
|
||||
${CWD}/cmake/scripts/DownloadZig.cmake
|
||||
OUTPUTS
|
||||
${ZIG_EXECUTABLE}
|
||||
)
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
---
|
||||
name: Migrate from npm install to bun install
|
||||
---
|
||||
|
||||
`bun install` is a Node.js compatible npm client designed to be an incredibly fast successor to npm.
|
||||
|
||||
We've put a lot of work into making sure that the migration path from `npm install` to `bun install` is as easy as running `bun install` instead of `npm install`.
|
||||
|
||||
- **Designed for Node.js & Bun**: `bun install` installs a Node.js compatible `node_modules` folder. You can use it in place of `npm install` for Node.js projects without any code changes and without using Bun's runtime.
|
||||
- **Automatically converts `package-lock.json`** to bun's `bun.lockb` lockfile format, preserving your existing resolved dependency versions without any manual work on your part. You can secretly use `bun install` in place of `npm install` at work without anyone noticing.
|
||||
- **`.npmrc` compatible**: bun install reads npm registry configuration from npm's `.npmrc`, so you can use the same configuration for both npm and Bun.
|
||||
- **Hardlinks**: On Windows and Linux, `bun install` uses hardlinks to conserve disk space and install times.
|
||||
|
||||
```bash
|
||||
# It only takes one command to migrate
|
||||
$ bun i
|
||||
|
||||
# To add dependencies:
|
||||
$ bun i @types/bun
|
||||
|
||||
# To add devDependencies:
|
||||
$ bun i -d @types/bun
|
||||
|
||||
# To remove a dependency:
|
||||
$ bun rm @types/bun
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Run package.json scripts faster
|
||||
|
||||
Run scripts from package.json, executables from `node_modules/.bin` (sort of like `npx`), and JavaScript/TypeScript files (just like `node`) - all from a single simple command.
|
||||
|
||||
| NPM | Bun |
|
||||
| ------------------ | ---------------- |
|
||||
| `npm run <script>` | `bun <script>` |
|
||||
| `npm exec <bin>` | `bun <bin>` |
|
||||
| `node <file>` | `bun <file>` |
|
||||
| `npx <package>` | `bunx <package>` |
|
||||
|
||||
When you use `bun run <executable>`, it will choose the locally-installed executable
|
||||
|
||||
```sh
|
||||
# Run a package.json script:
|
||||
$ bun my-script
|
||||
$ bun run my-script
|
||||
|
||||
# Run an executable in node_modules/.bin:
|
||||
$ bun my-executable # such as tsc, esbuild, etc.
|
||||
$ bun run my-executable
|
||||
|
||||
# Run a JavaScript/TypeScript file:
|
||||
$ bun ./index.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workspaces? Yes.
|
||||
|
||||
`bun install` supports workspaces similarly to npm, with more features.
|
||||
|
||||
In package.json, you can set `"workspaces"` to an array of relative paths.
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"name": "my-app",
|
||||
"workspaces": ["packages/*", "apps/*"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Filter scripts by workspace name
|
||||
|
||||
In Bun, the `--filter` flag accepts a glob pattern, and will run the command concurrently for all workspace packages with a `name` that matches the pattern, respecting dependency order.
|
||||
|
||||
```sh
|
||||
$ bun --filter 'lib-*' my-script
|
||||
# instead of:
|
||||
# npm run --workspace lib-foo --workspace lib-bar my-script
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update dependencies
|
||||
|
||||
To update a dependency, you can use `bun update <package>`. This will update the dependency to the latest version that satisfies the semver range specified in package.json.
|
||||
|
||||
```sh
|
||||
# Update a single dependency
|
||||
$ bun update @types/bun
|
||||
|
||||
# Update all dependencies
|
||||
$ bun update
|
||||
|
||||
# Ignore semver, update to the latest version
|
||||
$ bun update @types/bun --latest
|
||||
|
||||
# Update a dependency to a specific version
|
||||
$ bun update @types/bun@1.1.10
|
||||
|
||||
# Update all dependencies to the latest versions
|
||||
$ bun update --latest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### View outdated dependencies
|
||||
|
||||
To view outdated dependencies, run `bun outdated`. This is like `npm outdated` but with more compact output.
|
||||
|
||||
```sh
|
||||
$ bun outdated
|
||||
┌────────────────────────────────────────┬─────────┬────────┬────────┐
|
||||
│ Package │ Current │ Update │ Latest │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ @types/bun (dev) │ 1.1.6 │ 1.1.10 │ 1.1.10 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ @types/react (dev) │ 18.3.3 │ 18.3.8 │ 18.3.8 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ @typescript-eslint/eslint-plugin (dev) │ 7.16.1 │ 7.18.0 │ 8.6.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ @typescript-eslint/parser (dev) │ 7.16.1 │ 7.18.0 │ 8.6.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ @vscode/debugadapter (dev) │ 1.66.0 │ 1.67.0 │ 1.67.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ esbuild (dev) │ 0.21.5 │ 0.21.5 │ 0.24.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ eslint (dev) │ 9.7.0 │ 9.11.0 │ 9.11.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ mitata (dev) │ 0.1.11 │ 0.1.14 │ 1.0.2 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ prettier-plugin-organize-imports (dev) │ 4.0.0 │ 4.1.0 │ 4.1.0 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ source-map-js (dev) │ 1.2.0 │ 1.2.1 │ 1.2.1 │
|
||||
├────────────────────────────────────────┼─────────┼────────┼────────┤
|
||||
│ typescript (dev) │ 5.5.3 │ 5.6.2 │ 5.6.2 │
|
||||
└────────────────────────────────────────┴─────────┴────────┴────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## List installed packages
|
||||
|
||||
To list installed packages, you can use `bun pm ls`. This will list all the packages that are installed in the `node_modules` folder using Bun's lockfile as the source of truth. You can pass the `-a` flag to list all installed packages, including transitive dependencies.
|
||||
|
||||
```sh
|
||||
# List top-level installed packages:
|
||||
$ bun pm ls
|
||||
my-pkg node_modules (781)
|
||||
├── @types/node@20.16.5
|
||||
├── @types/react@18.3.8
|
||||
├── @types/react-dom@18.3.0
|
||||
├── eslint@8.57.1
|
||||
├── eslint-config-next@14.2.8
|
||||
|
||||
# List all installed packages:
|
||||
$ bun pm ls -a
|
||||
my-pkg node_modules
|
||||
├── @alloc/quick-lru@5.2.0
|
||||
├── @isaacs/cliui@8.0.2
|
||||
│ └── strip-ansi@7.1.0
|
||||
│ └── ansi-regex@6.1.0
|
||||
├── @jridgewell/gen-mapping@0.3.5
|
||||
├── @jridgewell/resolve-uri@3.1.2
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create a package tarball
|
||||
|
||||
To create a package tarball, you can use `bun pm pack`. This will create a tarball of the package in the current directory.
|
||||
|
||||
```sh
|
||||
# Create a tarball
|
||||
$ bun pm pack
|
||||
|
||||
Total files: 46
|
||||
Shasum: 2ee19b6f0c6b001358449ca0eadead703f326216
|
||||
Integrity: sha512-ZV0lzWTEkGAMz[...]Gl4f8lA9sl97g==
|
||||
Unpacked size: 0.41MB
|
||||
Packed size: 117.50KB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shebang
|
||||
|
||||
If the package references `node` in the `#!/usr/bin/env node` shebang, `bun run` will by default respect it and use the system's `node` executable. You can force it to use Bun's `node` by passing `--bun` to `bun run`.
|
||||
|
||||
When you pass `--bun` to `bun run`, we create a symlink to the locally-installed Bun executable named `"node"` in a temporary directory and add that to your `PATH` for the duration of the script's execution.
|
||||
|
||||
```sh
|
||||
# Force using Bun's runtime instead of node
|
||||
$ bun --bun my-script
|
||||
|
||||
# This also works:
|
||||
$ bun run --bun my-script
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Global installs
|
||||
|
||||
You can install packages globally using `bun i -g <package>`. This will install into a `.bun/install/global/node_modules` folder inside your home directory by default.
|
||||
|
||||
```sh
|
||||
# Install a package globally
|
||||
$ bun i -g eslint
|
||||
|
||||
# Run a globally-installed package without the `bun run` prefix
|
||||
$ eslint --init
|
||||
```
|
||||
@@ -67,7 +67,6 @@ After Visual Studio, you need the following:
|
||||
- Perl
|
||||
- Ruby
|
||||
- Node.js
|
||||
- Ccache
|
||||
|
||||
{% callout %}
|
||||
**Note** – The Zig compiler is automatically downloaded, installed, and updated by the building process.
|
||||
@@ -79,12 +78,12 @@ After Visual Studio, you need the following:
|
||||
|
||||
```ps1#WinGet
|
||||
## Select "Add LLVM to the system PATH for all users" in the LLVM installer
|
||||
> winget install -i LLVM.LLVM -v 18.1.8 && winget install GoLang.Go Rustlang.Rustup NASM.NASM StrawberryPerl.StrawberryPerl RubyInstallerTeam.Ruby.3.2 OpenJS.NodeJS.LTS Ccache.Ccache
|
||||
> winget install -i LLVM.LLVM -v 18.1.8 && winget install GoLang.Go Rustlang.Rustup NASM.NASM StrawberryPerl.StrawberryPerl RubyInstallerTeam.Ruby.3.2 OpenJS.NodeJS.LTS
|
||||
```
|
||||
|
||||
```ps1#Scoop
|
||||
> irm https://get.scoop.sh | iex
|
||||
> scoop install nodejs-lts go rust nasm ruby perl ccache
|
||||
> scoop install nodejs-lts go rust nasm ruby perl
|
||||
# scoop seems to be buggy if you install llvm and the rest at the same time
|
||||
> scoop install llvm@18.1.8
|
||||
```
|
||||
@@ -105,10 +104,10 @@ If you intend on building WebKit locally (optional), you should install these pa
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
From here on out, it is **expected you use a PowerShell Terminal with `.\scripts\vs-shell.ps1` sourced**. This script is available in the Bun repository and can be loaded by executing it:
|
||||
From here on out, it is **expected you use a PowerShell Terminal with `.\scripts\env.ps1` sourced**. This script is available in the Bun repository and can be loaded by executing it:
|
||||
|
||||
```ps1
|
||||
> .\scripts\vs-shell.ps1
|
||||
> .\scripts\env.ps1
|
||||
```
|
||||
|
||||
To verify, you can check for an MSVC-only command line such as `mt.exe`
|
||||
@@ -118,41 +117,49 @@ To verify, you can check for an MSVC-only command line such as `mt.exe`
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
It is not recommended to install `ninja` / `cmake` into your global path, because you may run into a situation where you try to build bun without .\scripts\vs-shell.ps1 sourced.
|
||||
It is not recommended to install `ninja` / `cmake` into your global path, because you may run into a situation where you try to build bun without .\scripts\env.ps1 sourced.
|
||||
{% /callout %}
|
||||
|
||||
## Building
|
||||
|
||||
```ps1
|
||||
> bun run build
|
||||
> bun install
|
||||
|
||||
# after the initial `bun run build` you can use the following to build
|
||||
> ninja -Cbuild/debug
|
||||
> .\scripts\env.ps1
|
||||
> .\scripts\update-submodules.ps1 # this syncs git submodule state
|
||||
> .\scripts\all-dependencies.ps1 # this builds all dependencies
|
||||
> .\scripts\make-old-js.ps1 # runs some old code generators
|
||||
|
||||
# Configure build environment
|
||||
> cmake -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Debug
|
||||
|
||||
# Build bun
|
||||
> ninja -Cbuild
|
||||
```
|
||||
|
||||
If this was successful, you should have a `bun-debug.exe` in the `build/debug` folder.
|
||||
If this was successful, you should have a `bun-debug.exe` in the `build` folder.
|
||||
|
||||
```ps1
|
||||
> .\build\debug\bun-debug.exe --revision
|
||||
> .\build\bun-debug.exe --revision
|
||||
```
|
||||
|
||||
You should add this to `$Env:PATH`. The simplest way to do so is to open the start menu, type "Path", and then navigate the environment variables menu to add `C:\.....\bun\build\debug` to the user environment variable `PATH`. You should then restart your editor (if it does not update still, log out and log back in).
|
||||
You should add this to `$Env:PATH`. The simplest way to do so is to open the start menu, type "Path", and then navigate the environment variables menu to add `C:\.....\bun\build` to the user environment variable `PATH`. You should then restart your editor (if it does not update still, log out and log back in).
|
||||
|
||||
## Extra paths
|
||||
|
||||
- WebKit is extracted to `build/debug/cache/webkit/`
|
||||
- Zig is extracted to `build/debug/cache/zig/bin/zig.exe`
|
||||
- WebKit is extracted to `build/bun-webkit`
|
||||
- Zig is extracted to `.cache/zig/zig.exe`
|
||||
|
||||
## Tests
|
||||
|
||||
You can run the test suite either using `bun test <path>`, or by using the wrapper script `packages\bun-internal-test`. The internal test package is a wrapper cli to run every test file in a separate instance of bun.exe, to prevent a crash in the test runner from stopping the entire suite.
|
||||
You can run the test suite either using `bun test`, or by using the wrapper script `packages\bun-internal-test`. The internal test package is a wrapper cli to run every test file in a separate instance of bun.exe, to prevent a crash in the test runner from stopping the entire suite.
|
||||
|
||||
```ps1
|
||||
# Setup
|
||||
> bun i --cwd packages\bun-internal-test
|
||||
|
||||
# Run the entire test suite with reporter
|
||||
# the package.json script "test" uses "build/debug/bun-debug.exe" by default
|
||||
# the package.json script "test" uses "build/bun-debug.exe" by default
|
||||
> bun run test
|
||||
|
||||
# Run an individual test file:
|
||||
|
||||
@@ -40,7 +40,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionWrite, (JSC::JSGlobalObject * globalObject,
|
||||
int32_t fd = STDOUT_FILENO;
|
||||
if (callframe->argumentCount() > 1) {
|
||||
fd = arg1.toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
RETURN_IF_EXCEPTION(scope, encodedJSValue());
|
||||
} else {
|
||||
toWriteArg = arg1;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionWrite, (JSC::JSGlobalObject * globalObject,
|
||||
}
|
||||
|
||||
auto string = toWriteArg.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
RETURN_IF_EXCEPTION(scope, encodedJSValue());
|
||||
auto utf8 = string.utf8();
|
||||
auto length = utf8.length();
|
||||
auto written = write(fd, utf8.data(), length);
|
||||
|
||||
35
package.json
35
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "bun",
|
||||
"version": "1.1.30",
|
||||
"version": "1.1.29",
|
||||
"workspaces": [
|
||||
"./packages/bun-types"
|
||||
],
|
||||
@@ -40,34 +40,25 @@
|
||||
"build:release:local": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Release -DWEBKIT_LOCAL=ON -B build/release",
|
||||
"build:release:with_logs": "cmake . -DCMAKE_BUILD_TYPE=Release -DENABLE_LOGS=true -GNinja -Bbuild-release && ninja -Cbuild-release",
|
||||
"build:debug-zig-release": "cmake . -DCMAKE_BUILD_TYPE=Release -DZIG_OPTIMIZE=Debug -GNinja -Bbuild-debug-zig-release && ninja -Cbuild-debug-zig-release",
|
||||
"bump": "bun ./scripts/bump.ts",
|
||||
"typecheck": "tsc --noEmit && cd test && bun run typecheck",
|
||||
"fmt": "bun run prettier",
|
||||
"fmt:cpp": "bun run clang-format",
|
||||
"fmt:zig": "bun run zig-format",
|
||||
"fmt": "prettier --config=.prettierrc-ci --write --cache './{.vscode,src,test,bench,packages/{bun-types,bun-inspector-*,bun-vscode,bun-debug-adapter-protocol}}/**/*.{mjs,ts,tsx,js,jsx}'",
|
||||
"fmt:cpp": "bun run build --target clang-format",
|
||||
"fmt:zig": "bun run build --target zig-format",
|
||||
"lint": "eslint './**/*.d.ts' --cache",
|
||||
"lint:fix": "eslint './**/*.d.ts' --cache --fix",
|
||||
"test": "node scripts/runner.node.mjs --exec-path ./build/debug/bun-debug",
|
||||
"test:release": "node scripts/runner.node.mjs --exec-path ./build/release/bun",
|
||||
"test": "node scripts/runner.node.mjs ./build/bun-debug",
|
||||
"test:release": "node scripts/runner.node.mjs ./build-release/bun",
|
||||
"banned": "bun packages/bun-internal-test/src/linter.ts",
|
||||
"zig": "vendor/zig/zig.exe",
|
||||
"zig:fmt": "bun run zig-format",
|
||||
"zig:fmt": "bun run fmt:zig",
|
||||
"zig:check": "bun run zig build check --summary new",
|
||||
"zig:check-all": "bun run zig build check-all --summary new",
|
||||
"zig:check-windows": "bun run zig build check-windows --summary new",
|
||||
"cmake": "bun ./scripts/build.mjs -DCMAKE_BUILD_TYPE=Debug -B build/debug",
|
||||
"clang-format": "bun run cmake --target clang-format",
|
||||
"clang-format:check": "bun run cmake --target clang-format-check",
|
||||
"clang-format:diff": "bun run cmake --target clang-format-diff",
|
||||
"clang-tidy": "bun run cmake --target clang-tidy",
|
||||
"clang-tidy:check": "bun run cmake --target clang-tidy-check",
|
||||
"clang-tidy:diff": "bun run cmake --target clang-tidy-diff",
|
||||
"zig-format": "bun run cmake --target zig-format",
|
||||
"zig-format:check": "bun run cmake --target zig-format-check",
|
||||
"zig-format:diff": "bun run cmake --target zig-format-diff",
|
||||
"prettier": "bun run cmake --target prettier",
|
||||
"prettier:check": "bun run cmake --target prettier-check",
|
||||
"prettier:extra": "bun run cmake --target prettier-extra",
|
||||
"prettier:diff": "bun run cmake --target prettier-diff"
|
||||
"clang-format": "bun run build --target clang-format --fresh",
|
||||
"clang-format:check": "bun run build --target clang-format-check --fresh",
|
||||
"clang-tidy": "bun run build --target clang-tidy --fresh",
|
||||
"clang-tidy:check": "bun run build --target clang-tidy --fresh",
|
||||
"zig-format": "bun run build --target zig-format --fresh",
|
||||
"zig-format:check": "bun run build --target zig-format-check --fresh"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,27 +2,13 @@ import type { InspectorEventMap } from "../../../bun-inspector-protocol/src/insp
|
||||
import type { JSC } from "../../../bun-inspector-protocol/src/protocol";
|
||||
import type { DAP } from "../protocol";
|
||||
// @ts-ignore
|
||||
import { ChildProcess, spawn } from "node:child_process";
|
||||
import type { ChildProcess } from "node:child_process";
|
||||
import { spawn } from "node:child_process";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { AddressInfo, createServer } from "node:net";
|
||||
import * as path from "node:path";
|
||||
import { remoteObjectToString, WebSocketInspector } from "../../../bun-inspector-protocol/index";
|
||||
import { randomUnixPath, TCPSocketSignal, UnixSignal } from "./signal";
|
||||
import { WebSocketInspector, remoteObjectToString } from "../../../bun-inspector-protocol/index";
|
||||
import { UnixSignal, randomUnixPath } from "./signal";
|
||||
import { Location, SourceMap } from "./sourcemap";
|
||||
|
||||
export async function getAvailablePort(): Promise<number> {
|
||||
const server = createServer();
|
||||
server.listen(0);
|
||||
return new Promise((resolve, reject) => {
|
||||
server.on("listening", () => {
|
||||
const { port } = server.address() as AddressInfo;
|
||||
server.close(() => {
|
||||
resolve(port);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const capabilities: DAP.Capabilities = {
|
||||
supportsConfigurationDoneRequest: true,
|
||||
supportsFunctionBreakpoints: true,
|
||||
@@ -503,73 +489,36 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
...env,
|
||||
};
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
// we're on unix
|
||||
const url = `ws+unix://${randomUnixPath()}`;
|
||||
const signal = new UnixSignal();
|
||||
const url = `ws+unix://${randomUnixPath()}`;
|
||||
const signal = new UnixSignal();
|
||||
|
||||
signal.on("Signal.received", () => {
|
||||
this.#attach({ url });
|
||||
});
|
||||
signal.on("Signal.received", () => {
|
||||
this.#attach({ url });
|
||||
});
|
||||
|
||||
this.once("Adapter.terminated", () => {
|
||||
signal.close();
|
||||
});
|
||||
this.once("Adapter.terminated", () => {
|
||||
signal.close();
|
||||
});
|
||||
|
||||
const query = stopOnEntry ? "break=1" : "wait=1";
|
||||
processEnv["BUN_INSPECT"] = `${url}?${query}`;
|
||||
processEnv["BUN_INSPECT_NOTIFY"] = signal.url;
|
||||
const query = stopOnEntry ? "break=1" : "wait=1";
|
||||
processEnv["BUN_INSPECT"] = `${url}?${query}`;
|
||||
processEnv["BUN_INSPECT_NOTIFY"] = signal.url;
|
||||
|
||||
// This is probably not correct, but it's the best we can do for now.
|
||||
processEnv["FORCE_COLOR"] = "1";
|
||||
processEnv["BUN_QUIET_DEBUG_LOGS"] = "1";
|
||||
processEnv["BUN_DEBUG_QUIET_LOGS"] = "1";
|
||||
// This is probably not correct, but it's the best we can do for now.
|
||||
processEnv["FORCE_COLOR"] = "1";
|
||||
processEnv["BUN_QUIET_DEBUG_LOGS"] = "1";
|
||||
processEnv["BUN_DEBUG_QUIET_LOGS"] = "1";
|
||||
|
||||
const started = await this.#spawn({
|
||||
command: runtime,
|
||||
args: processArgs,
|
||||
env: processEnv,
|
||||
cwd,
|
||||
isDebugee: true,
|
||||
});
|
||||
const started = await this.#spawn({
|
||||
command: runtime,
|
||||
args: processArgs,
|
||||
env: processEnv,
|
||||
cwd,
|
||||
isDebugee: true,
|
||||
});
|
||||
|
||||
if (!started) {
|
||||
throw new Error("Program could not be started.");
|
||||
}
|
||||
} else {
|
||||
// we're on windows
|
||||
// Create TCPSocketSignal
|
||||
const url = `ws://127.0.0.1:${await getAvailablePort()}/${getRandomId()}`; // 127.0.0.1 so it resolves correctly on windows
|
||||
const signal = new TCPSocketSignal(await getAvailablePort());
|
||||
|
||||
signal.on("Signal.received", async () => {
|
||||
this.#attach({ url });
|
||||
});
|
||||
|
||||
this.once("Adapter.terminated", () => {
|
||||
signal.close();
|
||||
});
|
||||
|
||||
const query = stopOnEntry ? "break=1" : "wait=1";
|
||||
processEnv["BUN_INSPECT"] = `${url}?${query}`;
|
||||
processEnv["BUN_INSPECT_NOTIFY"] = signal.url; // 127.0.0.1 so it resolves correctly on windows
|
||||
|
||||
// This is probably not correct, but it's the best we can do for now.
|
||||
processEnv["FORCE_COLOR"] = "1";
|
||||
processEnv["BUN_QUIET_DEBUG_LOGS"] = "1";
|
||||
processEnv["BUN_DEBUG_QUIET_LOGS"] = "1";
|
||||
|
||||
const started = await this.#spawn({
|
||||
command: runtime,
|
||||
args: processArgs,
|
||||
env: processEnv,
|
||||
cwd,
|
||||
isDebugee: true,
|
||||
});
|
||||
|
||||
if (!started) {
|
||||
throw new Error("Program could not be started.");
|
||||
}
|
||||
if (!started) {
|
||||
throw new Error("Program could not be started.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,9 +684,6 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
|
||||
async breakpointLocations(request: DAP.BreakpointLocationsRequest): Promise<DAP.BreakpointLocationsResponse> {
|
||||
const { line, endLine, column, endColumn, source: source0 } = request;
|
||||
if (process.platform === "win32") {
|
||||
source0.path = source0.path ? normalizeWindowsPath(source0.path) : source0.path;
|
||||
}
|
||||
const source = await this.#getSource(sourceToId(source0));
|
||||
|
||||
const { locations } = await this.send("Debugger.getBreakpointLocations", {
|
||||
@@ -842,9 +788,6 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
}
|
||||
|
||||
async #setBreakpointsByUrl(url: string, requests: DAP.SourceBreakpoint[], unsetOld?: boolean): Promise<Breakpoint[]> {
|
||||
if (process.platform === "win32") {
|
||||
url = url ? normalizeWindowsPath(url) : url;
|
||||
}
|
||||
const source = this.#getSourceIfPresent(url);
|
||||
|
||||
// If the source is not loaded, set a placeholder breakpoint at the start of the file.
|
||||
@@ -1218,9 +1161,6 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
|
||||
async gotoTargets(request: DAP.GotoTargetsRequest): Promise<DAP.GotoTargetsResponse> {
|
||||
const { source: source0 } = request;
|
||||
if (process.platform === "win32") {
|
||||
source0.path = source0.path ? normalizeWindowsPath(source0.path) : source0.path;
|
||||
}
|
||||
const source = await this.#getSource(sourceToId(source0));
|
||||
|
||||
const { breakpoints } = await this.breakpointLocations(request);
|
||||
@@ -1387,7 +1327,7 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
// 1. If it has a `path`, the client retrieves the source from the file system.
|
||||
// 2. If it has a `sourceReference`, the client sends a `source` request.
|
||||
// Moreover, the code is usually shown in a read-only editor.
|
||||
const isUserCode = path.isAbsolute(url);
|
||||
const isUserCode = url.startsWith("/");
|
||||
const sourceMap = SourceMap(sourceMapURL);
|
||||
const name = sourceName(url);
|
||||
const presentationHint = sourcePresentationHint(url);
|
||||
@@ -1706,11 +1646,12 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
|
||||
// If the source does not have a path or is a builtin module,
|
||||
// it cannot be retrieved from the file system.
|
||||
if (typeof sourceId === "number" || !path.isAbsolute(sourceId)) {
|
||||
if (typeof sourceId === "number" || !sourceId.startsWith("/")) {
|
||||
throw new Error(`Source not found: ${sourceId}`);
|
||||
}
|
||||
|
||||
// If the source is not present, it may not have been loaded yet.
|
||||
// In that case, wait for it to be loaded.
|
||||
let resolves = this.#pendingSources.get(sourceId);
|
||||
if (!resolves) {
|
||||
this.#pendingSources.set(sourceId, (resolves = []));
|
||||
@@ -2166,6 +2107,7 @@ export class DebugAdapter extends EventEmitter<DebugAdapterEventMap> implements
|
||||
|
||||
close(): void {
|
||||
this.#process?.kill();
|
||||
// this.#signal?.close();
|
||||
this.#inspector.close();
|
||||
this.#reset();
|
||||
}
|
||||
@@ -2207,10 +2149,10 @@ function titleize(name: string): string {
|
||||
}
|
||||
|
||||
function sourcePresentationHint(url?: string): DAP.Source["presentationHint"] {
|
||||
if (!url || !path.isAbsolute(url)) {
|
||||
if (!url || !url.startsWith("/")) {
|
||||
return "deemphasize";
|
||||
}
|
||||
if (url.includes("/node_modules/") || url.includes("\\node_modules\\")) {
|
||||
if (url.includes("/node_modules/")) {
|
||||
return "normal";
|
||||
}
|
||||
return "emphasize";
|
||||
@@ -2221,9 +2163,6 @@ function sourceName(url?: string): string {
|
||||
return "unknown.js";
|
||||
}
|
||||
if (isJavaScript(url)) {
|
||||
if (process.platform === "win32") {
|
||||
url = url.replaceAll("\\", "/");
|
||||
}
|
||||
return url.split("/").pop() || url;
|
||||
}
|
||||
return `${url}.js`;
|
||||
@@ -2628,15 +2567,3 @@ let sequence = 1;
|
||||
function nextId(): number {
|
||||
return sequence++;
|
||||
}
|
||||
|
||||
export function getRandomId() {
|
||||
return Math.random().toString(36).slice(2);
|
||||
}
|
||||
|
||||
export function normalizeWindowsPath(winPath: string): string {
|
||||
winPath = path.normalize(winPath);
|
||||
if (winPath[1] === ":" && (winPath[2] === "\\" || winPath[2] === "/")) {
|
||||
return (winPath.charAt(0).toUpperCase() + winPath.slice(1)).replaceAll("\\\\", "\\");
|
||||
}
|
||||
return winPath;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventEmitter } from "node:events";
|
||||
import type { Server, Socket } from "node:net";
|
||||
import type { Server } from "node:net";
|
||||
import { createServer } from "node:net";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
@@ -85,75 +85,3 @@ function parseUnixPath(path: string | URL): string {
|
||||
throw new Error(`Invalid UNIX path: ${path}`);
|
||||
}
|
||||
}
|
||||
|
||||
export type TCPSocketSignalEventMap = {
|
||||
"Signal.listening": [];
|
||||
"Signal.error": [Error];
|
||||
"Signal.closed": [];
|
||||
"Signal.received": [string];
|
||||
};
|
||||
|
||||
export class TCPSocketSignal extends EventEmitter {
|
||||
#port: number;
|
||||
#server: ReturnType<typeof createServer>;
|
||||
#ready: Promise<void>;
|
||||
|
||||
constructor(port: number) {
|
||||
super();
|
||||
this.#port = port;
|
||||
|
||||
this.#server = createServer((socket: Socket) => {
|
||||
socket.on("data", data => {
|
||||
this.emit("Signal.received", data.toString());
|
||||
});
|
||||
|
||||
socket.on("error", error => {
|
||||
this.emit("Signal.error", error);
|
||||
});
|
||||
|
||||
socket.on("close", () => {
|
||||
this.emit("Signal.closed");
|
||||
});
|
||||
});
|
||||
|
||||
this.#ready = new Promise((resolve, reject) => {
|
||||
this.#server.listen(this.#port, () => {
|
||||
this.emit("Signal.listening");
|
||||
resolve();
|
||||
});
|
||||
this.#server.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
emit<E extends keyof TCPSocketSignalEventMap>(event: E, ...args: TCPSocketSignalEventMap[E]): boolean {
|
||||
if (isDebug) {
|
||||
console.log(event, ...args);
|
||||
}
|
||||
return super.emit(event, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* The TCP port.
|
||||
*/
|
||||
get port(): number {
|
||||
return this.#port;
|
||||
}
|
||||
|
||||
get url(): string {
|
||||
return `tcp://127.0.0.1:${this.#port}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves when the server is listening or rejects if an error occurs.
|
||||
*/
|
||||
get ready(): Promise<void> {
|
||||
return this.#ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the server.
|
||||
*/
|
||||
close(): void {
|
||||
this.#server.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,27 +2,6 @@ import { AwsClient } from "aws4fetch";
|
||||
import { getBuild, getRelease, getSemver, getSha } from "../src/github";
|
||||
import { join, tmp } from "../src/fs";
|
||||
|
||||
// The source of truth for the git sha is what's in the local build, extracted from features.json
|
||||
// NOT the git tag revision.
|
||||
// Ideally, these are always the same, but mistakes can happen.
|
||||
const local =
|
||||
"bun-" +
|
||||
(
|
||||
{
|
||||
darwin: "darwin",
|
||||
win32: "windows",
|
||||
linux: "linux",
|
||||
} as any
|
||||
)[process.platform] +
|
||||
"-" +
|
||||
(
|
||||
{
|
||||
arm64: "aarch64",
|
||||
x64: "x64",
|
||||
} as any
|
||||
)[process.arch] +
|
||||
".zip";
|
||||
|
||||
const dryRun = process.argv.includes("--dry-run");
|
||||
|
||||
const [tag] = process.argv.slice(2);
|
||||
@@ -49,68 +28,40 @@ const full_commit_hash = await getSha(tag, "long");
|
||||
console.log("Found release:", release.tag_name, "with commit hash:", full_commit_hash);
|
||||
|
||||
console.log("Found build:", full_commit_hash);
|
||||
const isCanary = release.tag_name === "canary";
|
||||
|
||||
let paths: string[] = [];
|
||||
async function setPaths(revision: string, isCanary: boolean) {
|
||||
const releaseSha = `releases/${revision + (isCanary ? "-canary" : "")}`;
|
||||
if (latest.tag_name === release.tag_name) {
|
||||
paths = ["releases/latest", `releases/${release.tag_name}`, releaseSha];
|
||||
} else if (isCanary) {
|
||||
try {
|
||||
const build = await getSemver("canary", await getBuild());
|
||||
paths = ["releases/canary", `releases/${build}`, releaseSha];
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
paths = ["releases/canary", releaseSha];
|
||||
}
|
||||
} else {
|
||||
paths = [`releases/${release.tag_name}`, releaseSha];
|
||||
let paths: string[];
|
||||
if (latest.tag_name === release.tag_name) {
|
||||
paths = ["releases/latest", `releases/${release.tag_name}`, `releases/${full_commit_hash}`];
|
||||
} else if (release.tag_name === "canary") {
|
||||
try {
|
||||
const build = await getSemver("canary", await getBuild());
|
||||
paths = ["releases/canary", `releases/${build}`, `releases/${full_commit_hash}-canary`];
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
paths = ["releases/canary"];
|
||||
}
|
||||
|
||||
console.log("Found paths:", paths);
|
||||
} else {
|
||||
paths = [`releases/${release.tag_name}`, `releases/${full_commit_hash}`];
|
||||
}
|
||||
console.log("Found paths:", paths);
|
||||
|
||||
async function getFeaturesJSON(body: ArrayBuffer) {
|
||||
// extract feature data using the local build
|
||||
const temp = tmp();
|
||||
await Bun.write(join(temp, "bun.zip"), body);
|
||||
let unzip = Bun.spawnSync({
|
||||
cmd: ["unzip", join(temp, "bun.zip")],
|
||||
cwd: temp,
|
||||
});
|
||||
if (!unzip.success) throw new Error("Failed to unzip");
|
||||
let data = Bun.spawnSync({
|
||||
cmd: [
|
||||
join(temp, local.replace(".zip", ""), "bun"),
|
||||
"--print",
|
||||
'JSON.stringify(require("bun:internal-for-testing").crash_handler.getFeatureData())',
|
||||
],
|
||||
cwd: temp,
|
||||
env: {
|
||||
...process.env,
|
||||
BUN_DEBUG_QUIET_LOGS: "1",
|
||||
BUN_GARBAGE_COLLECTOR_LEVEL: "0",
|
||||
BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING: "1",
|
||||
},
|
||||
stdio: ["ignore", "pipe", "inherit"],
|
||||
});
|
||||
return data.stdout.toString("utf8").trim();
|
||||
}
|
||||
|
||||
// Make the first asset the local build
|
||||
for (let i = 0; i < release.assets.length; i++) {
|
||||
const asset = release.assets[i];
|
||||
if (asset.name === local) {
|
||||
release.assets.splice(i, 1);
|
||||
release.assets.unshift(asset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (release?.assets?.[0]?.name !== local) {
|
||||
throw new Error("Expected local build to be the first asset");
|
||||
}
|
||||
const local =
|
||||
"bun-" +
|
||||
(
|
||||
{
|
||||
darwin: "darwin",
|
||||
win32: "windows",
|
||||
linux: "linux",
|
||||
} as any
|
||||
)[process.platform] +
|
||||
"-" +
|
||||
(
|
||||
{
|
||||
arm64: "aarch64",
|
||||
x64: "x64",
|
||||
} as any
|
||||
)[process.arch] +
|
||||
".zip";
|
||||
|
||||
for (const asset of release.assets) {
|
||||
const url = asset.browser_download_url;
|
||||
@@ -132,25 +83,39 @@ for (const asset of release.assets) {
|
||||
contentType = response.headers.get("Content-Type") || "";
|
||||
}
|
||||
|
||||
console.log("Downloading asset:", name);
|
||||
const body = await response.arrayBuffer();
|
||||
|
||||
if (name == local) {
|
||||
const text = await getFeaturesJSON(body);
|
||||
const features = JSON.parse(text);
|
||||
const sha = features.revision;
|
||||
if (features.is_canary && !isCanary) {
|
||||
console.warn("Local build is a canary but release is not tagged as canary.");
|
||||
}
|
||||
await setPaths(sha, features.is_canary);
|
||||
console.log("features.json:", JSON.stringify(features, null, 2));
|
||||
|
||||
// extract feature data using the local build
|
||||
const temp = tmp();
|
||||
await Bun.write(join(temp, "bun.zip"), body);
|
||||
let unzip = Bun.spawnSync({
|
||||
cmd: ["unzip", join(temp, "bun.zip")],
|
||||
cwd: temp,
|
||||
});
|
||||
if (!unzip.success) throw new Error("Failed to unzip");
|
||||
let data = Bun.spawnSync({
|
||||
cmd: [
|
||||
join(temp, local.replace(".zip", ""), "bun"),
|
||||
"--print",
|
||||
'JSON.stringify(require("bun:internal-for-testing").crash_handler.getFeatureData())',
|
||||
],
|
||||
cwd: temp,
|
||||
env: {
|
||||
...process.env,
|
||||
BUN_DEBUG_QUIET_LOGS: "1",
|
||||
BUN_GARBAGE_COLLECTOR_LEVEL: "0",
|
||||
BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING: "1",
|
||||
},
|
||||
stdio: ["ignore", "pipe", "inherit"],
|
||||
});
|
||||
const json = data.stdout.toString("utf8");
|
||||
for (const path of paths) {
|
||||
const key = `${path}/features.json`;
|
||||
console.log("Uploading:", key);
|
||||
await uploadToS3({
|
||||
key,
|
||||
body: new TextEncoder().encode(text).buffer,
|
||||
body: new TextEncoder().encode(json).buffer,
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
"Content-Disposition": `attachment; filename="${name}"`,
|
||||
|
||||
2
packages/bun-types/bun.d.ts
vendored
2
packages/bun-types/bun.d.ts
vendored
@@ -2660,7 +2660,7 @@ declare module "bun" {
|
||||
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
|
||||
* @default false
|
||||
*/
|
||||
stop(closeActiveConnections?: boolean): Promise<void>;
|
||||
stop(closeActiveConnections?: boolean): void;
|
||||
|
||||
/**
|
||||
* Update the `fetch` and `error` handlers without restarting the server.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
DisableFormat: true
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,20 +15,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This Server Name Indication hostname tree is written in C++ but could be ported to C.
|
||||
* Overall it looks like crap, but has no memory allocations in fast path and is O(log n). */
|
||||
/* This Server Name Indication hostname tree is written in C++ but could be
|
||||
* ported to C. Overall it looks like crap, but has no memory allocations in
|
||||
* fast path and is O(log n). */
|
||||
|
||||
#ifndef SNI_TREE_H
|
||||
#define SNI_TREE_H
|
||||
|
||||
#ifndef LIBUS_NO_SSL
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
/* We only handle a maximum of 10 labels per hostname */
|
||||
#define MAX_LABELS 10
|
||||
@@ -37,180 +38,186 @@
|
||||
thread_local void (*sni_free_cb)(void *);
|
||||
|
||||
struct sni_node {
|
||||
/* Empty nodes must always hold null */
|
||||
void *user = nullptr;
|
||||
std::map<std::string_view, std::unique_ptr<sni_node>> children;
|
||||
/* Empty nodes must always hold null */
|
||||
void *user = nullptr;
|
||||
std::map<std::string_view, std::unique_ptr<sni_node>> children;
|
||||
|
||||
~sni_node() {
|
||||
for (auto &p : children) {
|
||||
/* The data of our string_views are managed by malloc */
|
||||
free((void *) p.first.data());
|
||||
~sni_node() {
|
||||
for (auto &p : children) {
|
||||
/* The data of our string_views are managed by malloc */
|
||||
free((void *)p.first.data());
|
||||
|
||||
/* Call destructor passed to sni_free only if we hold data.
|
||||
* This is important since sni_remove does not have sni_free_cb set */
|
||||
if (p.second.get()->user) {
|
||||
sni_free_cb(p.second.get()->user);
|
||||
}
|
||||
}
|
||||
/* Call destructor passed to sni_free only if we hold data.
|
||||
* This is important since sni_remove does not have sni_free_cb set */
|
||||
if (p.second.get()->user) {
|
||||
sni_free_cb(p.second.get()->user);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// this can only delete ONE single node, but may cull "empty nodes with null as data"
|
||||
void *removeUser(struct sni_node *root, unsigned int label, std::string_view *labels, unsigned int numLabels) {
|
||||
// this can only delete ONE single node, but may cull "empty nodes with null as
|
||||
// data"
|
||||
void *removeUser(struct sni_node *root, unsigned int label,
|
||||
std::string_view *labels, unsigned int numLabels) {
|
||||
|
||||
/* If we are in the bottom (past bottom by one), there is nothing to remove */
|
||||
if (label == numLabels) {
|
||||
void *user = root->user;
|
||||
/* Mark us for culling on the way up */
|
||||
root->user = nullptr;
|
||||
return user;
|
||||
}
|
||||
/* If we are in the bottom (past bottom by one), there is nothing to remove */
|
||||
if (label == numLabels) {
|
||||
void *user = root->user;
|
||||
/* Mark us for culling on the way up */
|
||||
root->user = nullptr;
|
||||
return user;
|
||||
}
|
||||
|
||||
/* Is this label a child of root? */
|
||||
auto it = root->children.find(labels[label]);
|
||||
if (it == root->children.end()) {
|
||||
/* We cannot continue */
|
||||
return nullptr;
|
||||
}
|
||||
/* Is this label a child of root? */
|
||||
auto it = root->children.find(labels[label]);
|
||||
if (it == root->children.end()) {
|
||||
/* We cannot continue */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *removedUser = removeUser(it->second.get(), label + 1, labels, numLabels);
|
||||
void *removedUser =
|
||||
removeUser(it->second.get(), label + 1, labels, numLabels);
|
||||
|
||||
/* On the way back up, we may cull empty nodes with no children.
|
||||
* This ends up being where we remove all nodes */
|
||||
if (it->second.get()->children.empty() && it->second.get()->user == nullptr) {
|
||||
/* On the way back up, we may cull empty nodes with no children.
|
||||
* This ends up being where we remove all nodes */
|
||||
if (it->second.get()->children.empty() && it->second.get()->user == nullptr) {
|
||||
|
||||
/* The data of our string_views are managed by malloc */
|
||||
free((void *) it->first.data());
|
||||
/* The data of our string_views are managed by malloc */
|
||||
free((void *)it->first.data());
|
||||
|
||||
/* This can only happen with user set to null, otherwise we use sni_free_cb which is unset by sni_remove */
|
||||
root->children.erase(it);
|
||||
}
|
||||
/* This can only happen with user set to null, otherwise we use sni_free_cb
|
||||
* which is unset by sni_remove */
|
||||
root->children.erase(it);
|
||||
}
|
||||
|
||||
return removedUser;
|
||||
return removedUser;
|
||||
}
|
||||
|
||||
void *getUser(struct sni_node *root, unsigned int label, std::string_view *labels, unsigned int numLabels) {
|
||||
void *getUser(struct sni_node *root, unsigned int label,
|
||||
std::string_view *labels, unsigned int numLabels) {
|
||||
|
||||
/* Do we have labels to match? Otherwise, return where we stand */
|
||||
if (label == numLabels) {
|
||||
return root->user;
|
||||
/* Do we have labels to match? Otherwise, return where we stand */
|
||||
if (label == numLabels) {
|
||||
return root->user;
|
||||
}
|
||||
|
||||
/* Try and match by our label */
|
||||
auto it = root->children.find(labels[label]);
|
||||
if (it != root->children.end()) {
|
||||
void *user = getUser(it->second.get(), label + 1, labels, numLabels);
|
||||
if (user) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try and match by our label */
|
||||
auto it = root->children.find(labels[label]);
|
||||
if (it != root->children.end()) {
|
||||
void *user = getUser(it->second.get(), label + 1, labels, numLabels);
|
||||
if (user) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
/* Try and match by wildcard */
|
||||
it = root->children.find("*");
|
||||
if (it == root->children.end()) {
|
||||
/* Matching has failed for both label and wildcard */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Try and match by wildcard */
|
||||
it = root->children.find("*");
|
||||
if (it == root->children.end()) {
|
||||
/* Matching has failed for both label and wildcard */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* We matched by wildcard */
|
||||
return getUser(it->second.get(), label + 1, labels, numLabels);
|
||||
/* We matched by wildcard */
|
||||
return getUser(it->second.get(), label + 1, labels, numLabels);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *sni_new() {
|
||||
return new sni_node;
|
||||
void *sni_new() { return new sni_node; }
|
||||
|
||||
void sni_free(void *sni, void (*cb)(void *)) {
|
||||
/* We want to run this callback for every remaining name */
|
||||
sni_free_cb = cb;
|
||||
|
||||
delete (sni_node *)sni;
|
||||
}
|
||||
|
||||
/* Returns non-null if this name already exists */
|
||||
int sni_add(void *sni, const char *hostname, void *user) {
|
||||
struct sni_node *root = (struct sni_node *)sni;
|
||||
|
||||
/* Traverse all labels in hostname */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label; view.length();
|
||||
view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
|
||||
auto it = root->children.find(label);
|
||||
if (it == root->children.end()) {
|
||||
/* Duplicate this label for our kept string_view of it */
|
||||
void *labelString = malloc(label.length());
|
||||
memcpy(labelString, label.data(), label.length());
|
||||
|
||||
it = root->children
|
||||
.emplace(std::string_view((char *)labelString, label.length()),
|
||||
std::make_unique<sni_node>())
|
||||
.first; // NOLINT(clang-analyzer-unix.Malloc)
|
||||
}
|
||||
|
||||
void sni_free(void *sni, void (*cb)(void *)) {
|
||||
/* We want to run this callback for every remaining name */
|
||||
sni_free_cb = cb;
|
||||
root = it->second.get();
|
||||
}
|
||||
|
||||
delete (sni_node *) sni;
|
||||
/* We must never add multiple contexts for the same name, as that would
|
||||
* overwrite and leak */
|
||||
if (root->user) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
root->user = user;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Removes the exact match. Wildcards are treated as the verbatim asterisk char,
|
||||
* not as an actual wildcard */
|
||||
void *sni_remove(void *sni, const char *hostname) {
|
||||
struct sni_node *root = (struct sni_node *)sni;
|
||||
|
||||
/* I guess 10 labels is an okay limit */
|
||||
std::string_view labels[10];
|
||||
unsigned int numLabels = 0;
|
||||
|
||||
/* We traverse all labels first of all */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label; view.length();
|
||||
view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
|
||||
/* Anything longer than 10 labels is forbidden */
|
||||
if (numLabels == 10) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Returns non-null if this name already exists */
|
||||
int sni_add(void *sni, const char *hostname, void *user) {
|
||||
struct sni_node *root = (struct sni_node *) sni;
|
||||
labels[numLabels++] = label;
|
||||
}
|
||||
|
||||
/* Traverse all labels in hostname */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label;
|
||||
view.length(); view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
return removeUser(root, 0, labels, numLabels);
|
||||
}
|
||||
|
||||
auto it = root->children.find(label);
|
||||
if (it == root->children.end()) {
|
||||
/* Duplicate this label for our kept string_view of it */
|
||||
void *labelString = malloc(label.length());
|
||||
memcpy(labelString, label.data(), label.length());
|
||||
void *sni_find(void *sni, const char *hostname) {
|
||||
struct sni_node *root = (struct sni_node *)sni;
|
||||
|
||||
it = root->children.emplace(std::string_view((char *) labelString, label.length()),
|
||||
std::make_unique<sni_node>()).first; // NOLINT(clang-analyzer-unix.Malloc)
|
||||
}
|
||||
/* I guess 10 labels is an okay limit */
|
||||
std::string_view labels[10];
|
||||
unsigned int numLabels = 0;
|
||||
|
||||
root = it->second.get();
|
||||
}
|
||||
/* We traverse all labels first of all */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label; view.length();
|
||||
view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
|
||||
/* We must never add multiple contexts for the same name, as that would overwrite and leak */
|
||||
if (root->user) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
root->user = user;
|
||||
|
||||
return 0;
|
||||
/* Anything longer than 10 labels is forbidden */
|
||||
if (numLabels == 10) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Removes the exact match. Wildcards are treated as the verbatim asterisk char, not as an actual wildcard */
|
||||
void *sni_remove(void *sni, const char *hostname) {
|
||||
struct sni_node *root = (struct sni_node *) sni;
|
||||
|
||||
/* I guess 10 labels is an okay limit */
|
||||
std::string_view labels[10];
|
||||
unsigned int numLabels = 0;
|
||||
|
||||
/* We traverse all labels first of all */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label;
|
||||
view.length(); view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
|
||||
/* Anything longer than 10 labels is forbidden */
|
||||
if (numLabels == 10) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
labels[numLabels++] = label;
|
||||
}
|
||||
|
||||
return removeUser(root, 0, labels, numLabels);
|
||||
}
|
||||
|
||||
void *sni_find(void *sni, const char *hostname) {
|
||||
struct sni_node *root = (struct sni_node *) sni;
|
||||
|
||||
/* I guess 10 labels is an okay limit */
|
||||
std::string_view labels[10];
|
||||
unsigned int numLabels = 0;
|
||||
|
||||
/* We traverse all labels first of all */
|
||||
for (std::string_view view(hostname, strlen(hostname)), label;
|
||||
view.length(); view.remove_prefix(std::min(view.length(), label.length() + 1))) {
|
||||
/* Label is the token separated by dot */
|
||||
label = view.substr(0, view.find('.', 0));
|
||||
|
||||
/* Anything longer than 10 labels is forbidden */
|
||||
if (numLabels == 10) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
labels[numLabels++] = label;
|
||||
}
|
||||
|
||||
return getUser(root, 0, labels, numLabels);
|
||||
}
|
||||
labels[numLabels++] = label;
|
||||
}
|
||||
|
||||
return getUser(root, 0, labels, numLabels);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -127,7 +127,9 @@ int us_poll_events(struct us_poll_t *p) {
|
||||
|
||||
size_t us_internal_accept_poll_event(struct us_poll_t *p) { return 0; }
|
||||
|
||||
int us_internal_poll_type(struct us_poll_t *p) { return p->poll_type & POLL_TYPE_KIND_MASK; }
|
||||
int us_internal_poll_type(struct us_poll_t *p) {
|
||||
return p->poll_type & POLL_TYPE_KIND_MASK;
|
||||
}
|
||||
|
||||
void us_internal_poll_set_type(struct us_poll_t *p, int poll_type) {
|
||||
p->poll_type = poll_type | (p->poll_type & POLL_TYPE_POLLING_MASK);
|
||||
|
||||
@@ -371,8 +371,6 @@ void us_poll_init(us_poll_r p, LIBUS_SOCKET_DESCRIPTOR fd, int poll_type);
|
||||
|
||||
/* Start, change and stop polling for events */
|
||||
void us_poll_start(us_poll_r p, us_loop_r loop, int events) nonnull_fn_decl;
|
||||
/* Returns 0 if successful */
|
||||
int us_poll_start_rc(us_poll_r p, us_loop_r loop, int events) nonnull_fn_decl;
|
||||
void us_poll_change(us_poll_r p, us_loop_r loop, int events) nonnull_fn_decl;
|
||||
void us_poll_stop(us_poll_r p, struct us_loop_t *loop) nonnull_fn_decl;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef WIN32
|
||||
@@ -309,11 +310,7 @@ struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socke
|
||||
#else
|
||||
struct us_poll_t *p1 = us_create_poll(ctx->loop, 0, sizeof(struct us_socket_t) + socket_ext_size);
|
||||
us_poll_init(p1, fd, POLL_TYPE_SOCKET);
|
||||
int rc = us_poll_start_rc(p1, ctx->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
if (rc != 0) {
|
||||
us_poll_free(p1, ctx->loop);
|
||||
return 0;
|
||||
}
|
||||
us_poll_start(p1, ctx->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
|
||||
struct us_socket_t *s = (struct us_socket_t *) p1;
|
||||
s->context = ctx;
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "libusockets.h"
|
||||
#include "internal/internal.h"
|
||||
#include "libusockets.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -24,56 +24,65 @@
|
||||
// return bsd_udp_packet_buffer_ecn((struct udp_recvbuf *)buf, index);
|
||||
// }
|
||||
|
||||
int us_udp_packet_buffer_local_ip(struct us_udp_packet_buffer_t *buf, int index, char *ip) {
|
||||
return bsd_udp_packet_buffer_local_ip((struct udp_recvbuf *)buf, index, ip);
|
||||
int us_udp_packet_buffer_local_ip(struct us_udp_packet_buffer_t *buf, int index,
|
||||
char *ip) {
|
||||
return bsd_udp_packet_buffer_local_ip((struct udp_recvbuf *)buf, index, ip);
|
||||
}
|
||||
|
||||
char *us_udp_packet_buffer_peer(struct us_udp_packet_buffer_t *buf, int index) {
|
||||
return bsd_udp_packet_buffer_peer((struct udp_recvbuf *)buf, index);
|
||||
return bsd_udp_packet_buffer_peer((struct udp_recvbuf *)buf, index);
|
||||
}
|
||||
|
||||
char *us_udp_packet_buffer_payload(struct us_udp_packet_buffer_t *buf, int index) {
|
||||
return bsd_udp_packet_buffer_payload((struct udp_recvbuf *)buf, index);
|
||||
char *us_udp_packet_buffer_payload(struct us_udp_packet_buffer_t *buf,
|
||||
int index) {
|
||||
return bsd_udp_packet_buffer_payload((struct udp_recvbuf *)buf, index);
|
||||
}
|
||||
|
||||
int us_udp_packet_buffer_payload_length(struct us_udp_packet_buffer_t *buf, int index) {
|
||||
return bsd_udp_packet_buffer_payload_length((struct udp_recvbuf *)buf, index);
|
||||
int us_udp_packet_buffer_payload_length(struct us_udp_packet_buffer_t *buf,
|
||||
int index) {
|
||||
return bsd_udp_packet_buffer_payload_length((struct udp_recvbuf *)buf, index);
|
||||
}
|
||||
|
||||
int us_udp_socket_send(struct us_udp_socket_t *s, void** payloads, size_t* lengths, void** addresses, int num) {
|
||||
if (num == 0) return 0;
|
||||
int fd = us_poll_fd((struct us_poll_t *) s);
|
||||
int us_udp_socket_send(struct us_udp_socket_t *s, void **payloads,
|
||||
size_t *lengths, void **addresses, int num) {
|
||||
if (num == 0)
|
||||
return 0;
|
||||
int fd = us_poll_fd((struct us_poll_t *)s);
|
||||
|
||||
struct udp_sendbuf *buf = (struct udp_sendbuf *)s->loop->data.send_buf;
|
||||
struct udp_sendbuf *buf = (struct udp_sendbuf *)s->loop->data.send_buf;
|
||||
|
||||
int total_sent = 0;
|
||||
while (total_sent < num) {
|
||||
int count = bsd_udp_setup_sendbuf(buf, LIBUS_SEND_BUFFER_LENGTH, payloads, lengths, addresses, num);
|
||||
payloads += count;
|
||||
lengths += count;
|
||||
addresses += count;
|
||||
num -= count;
|
||||
// TODO nohang flag?
|
||||
int sent = bsd_sendmmsg(fd, buf, MSG_DONTWAIT);
|
||||
if (sent < 0) {
|
||||
return sent;
|
||||
}
|
||||
total_sent += sent;
|
||||
if (0 <= sent && sent < num) {
|
||||
// if we couldn't send all packets, register a writable event so we can call the drain callback
|
||||
us_poll_change((struct us_poll_t *) s, s->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
}
|
||||
int total_sent = 0;
|
||||
while (total_sent < num) {
|
||||
int count = bsd_udp_setup_sendbuf(buf, LIBUS_SEND_BUFFER_LENGTH, payloads,
|
||||
lengths, addresses, num);
|
||||
payloads += count;
|
||||
lengths += count;
|
||||
addresses += count;
|
||||
num -= count;
|
||||
// TODO nohang flag?
|
||||
int sent = bsd_sendmmsg(fd, buf, MSG_DONTWAIT);
|
||||
if (sent < 0) {
|
||||
return sent;
|
||||
}
|
||||
return total_sent;
|
||||
total_sent += sent;
|
||||
if (0 <= sent && sent < num) {
|
||||
// if we couldn't send all packets, register a writable event so we can
|
||||
// call the drain callback
|
||||
us_poll_change((struct us_poll_t *)s, s->loop,
|
||||
LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
}
|
||||
}
|
||||
return total_sent;
|
||||
}
|
||||
|
||||
int us_udp_socket_bound_port(struct us_udp_socket_t *s) {
|
||||
return ((struct us_udp_socket_t *) s)->port;
|
||||
return ((struct us_udp_socket_t *)s)->port;
|
||||
}
|
||||
|
||||
void us_udp_socket_bound_ip(struct us_udp_socket_t *s, char *buf, int *length) {
|
||||
struct bsd_addr_t addr;
|
||||
if (bsd_local_addr(us_poll_fd((struct us_poll_t *)s), &addr) || *length < bsd_addr_get_ip_length(&addr)) {
|
||||
if (bsd_local_addr(us_poll_fd((struct us_poll_t *)s), &addr) ||
|
||||
*length < bsd_addr_get_ip_length(&addr)) {
|
||||
*length = 0;
|
||||
} else {
|
||||
*length = bsd_addr_get_ip_length(&addr);
|
||||
@@ -81,9 +90,11 @@ void us_udp_socket_bound_ip(struct us_udp_socket_t *s, char *buf, int *length) {
|
||||
}
|
||||
}
|
||||
|
||||
void us_udp_socket_remote_ip(struct us_udp_socket_t *s, char *buf, int *length) {
|
||||
void us_udp_socket_remote_ip(struct us_udp_socket_t *s, char *buf,
|
||||
int *length) {
|
||||
struct bsd_addr_t addr;
|
||||
if (bsd_remote_addr(us_poll_fd((struct us_poll_t *)s), &addr) || *length < bsd_addr_get_ip_length(&addr)) {
|
||||
if (bsd_remote_addr(us_poll_fd((struct us_poll_t *)s), &addr) ||
|
||||
*length < bsd_addr_get_ip_length(&addr)) {
|
||||
*length = 0;
|
||||
} else {
|
||||
*length = bsd_addr_get_ip_length(&addr);
|
||||
@@ -92,71 +103,71 @@ void us_udp_socket_remote_ip(struct us_udp_socket_t *s, char *buf, int *length)
|
||||
}
|
||||
|
||||
void *us_udp_socket_user(struct us_udp_socket_t *s) {
|
||||
struct us_udp_socket_t *udp = (struct us_udp_socket_t *) s;
|
||||
struct us_udp_socket_t *udp = (struct us_udp_socket_t *)s;
|
||||
|
||||
return udp->user;
|
||||
return udp->user;
|
||||
}
|
||||
|
||||
void us_udp_socket_close(struct us_udp_socket_t *s) {
|
||||
struct us_loop_t *loop = s->loop;
|
||||
struct us_poll_t *p = (struct us_poll_t *) s;
|
||||
us_poll_stop(p, loop);
|
||||
bsd_close_socket(us_poll_fd(p));
|
||||
s->closed = 1;
|
||||
s->next = loop->data.closed_udp_head;
|
||||
loop->data.closed_udp_head = s;
|
||||
s->on_close(s);
|
||||
struct us_loop_t *loop = s->loop;
|
||||
struct us_poll_t *p = (struct us_poll_t *)s;
|
||||
us_poll_stop(p, loop);
|
||||
bsd_close_socket(us_poll_fd(p));
|
||||
s->closed = 1;
|
||||
s->next = loop->data.closed_udp_head;
|
||||
loop->data.closed_udp_head = s;
|
||||
s->on_close(s);
|
||||
}
|
||||
|
||||
int us_udp_socket_connect(struct us_udp_socket_t *s, const char* host, unsigned short port) {
|
||||
return bsd_connect_udp_socket(us_poll_fd((struct us_poll_t *)s), host, port);
|
||||
int us_udp_socket_connect(struct us_udp_socket_t *s, const char *host,
|
||||
unsigned short port) {
|
||||
return bsd_connect_udp_socket(us_poll_fd((struct us_poll_t *)s), host, port);
|
||||
}
|
||||
|
||||
int us_udp_socket_disconnect(struct us_udp_socket_t *s) {
|
||||
return bsd_disconnect_udp_socket(us_poll_fd((struct us_poll_t *)s));
|
||||
return bsd_disconnect_udp_socket(us_poll_fd((struct us_poll_t *)s));
|
||||
}
|
||||
|
||||
struct us_udp_socket_t *us_create_udp_socket(
|
||||
struct us_loop_t *loop,
|
||||
void (*data_cb)(struct us_udp_socket_t *, void *, int),
|
||||
void (*drain_cb)(struct us_udp_socket_t *),
|
||||
void (*close_cb)(struct us_udp_socket_t *),
|
||||
const char *host,
|
||||
unsigned short port,
|
||||
void *user
|
||||
) {
|
||||
struct us_udp_socket_t *
|
||||
us_create_udp_socket(struct us_loop_t *loop,
|
||||
void (*data_cb)(struct us_udp_socket_t *, void *, int),
|
||||
void (*drain_cb)(struct us_udp_socket_t *),
|
||||
void (*close_cb)(struct us_udp_socket_t *),
|
||||
const char *host, unsigned short port, void *user) {
|
||||
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_udp_socket(host, port);
|
||||
if (fd == LIBUS_SOCKET_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_udp_socket(host, port);
|
||||
if (fd == LIBUS_SOCKET_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext_size = 0;
|
||||
int fallthrough = 0;
|
||||
int ext_size = 0;
|
||||
int fallthrough = 0;
|
||||
|
||||
struct us_poll_t *p = us_create_poll(loop, fallthrough, sizeof(struct us_udp_socket_t) + ext_size);
|
||||
us_poll_init(p, fd, POLL_TYPE_UDP);
|
||||
struct us_poll_t *p = us_create_poll(
|
||||
loop, fallthrough, sizeof(struct us_udp_socket_t) + ext_size);
|
||||
us_poll_init(p, fd, POLL_TYPE_UDP);
|
||||
|
||||
struct us_udp_socket_t *udp = (struct us_udp_socket_t *)p;
|
||||
struct us_udp_socket_t *udp = (struct us_udp_socket_t *)p;
|
||||
|
||||
/* Get and store the port once */
|
||||
struct bsd_addr_t tmp = {0};
|
||||
bsd_local_addr(fd, &tmp);
|
||||
udp->port = bsd_addr_get_port(&tmp);
|
||||
udp->loop = loop;
|
||||
/* Get and store the port once */
|
||||
struct bsd_addr_t tmp = {0};
|
||||
bsd_local_addr(fd, &tmp);
|
||||
udp->port = bsd_addr_get_port(&tmp);
|
||||
udp->loop = loop;
|
||||
|
||||
/* There is no udp socket context, only user data */
|
||||
/* This should really be ext like everything else */
|
||||
udp->user = user;
|
||||
/* There is no udp socket context, only user data */
|
||||
/* This should really be ext like everything else */
|
||||
udp->user = user;
|
||||
|
||||
udp->closed = 0;
|
||||
udp->connected = 0;
|
||||
udp->on_data = data_cb;
|
||||
udp->on_drain = drain_cb;
|
||||
udp->on_close = close_cb;
|
||||
udp->next = NULL;
|
||||
udp->closed = 0;
|
||||
udp->connected = 0;
|
||||
udp->on_data = data_cb;
|
||||
udp->on_drain = drain_cb;
|
||||
udp->on_close = close_cb;
|
||||
udp->next = NULL;
|
||||
|
||||
us_poll_start((struct us_poll_t *) udp, udp->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
|
||||
return (struct us_udp_socket_t *) udp;
|
||||
us_poll_start((struct us_poll_t *)udp, udp->loop,
|
||||
LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
|
||||
|
||||
return (struct us_udp_socket_t *)udp;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
DisableFormat: true
|
||||
13
packages/bun-vscode/.gitignore
vendored
13
packages/bun-vscode/.gitignore
vendored
@@ -1,10 +1,3 @@
|
||||
# Project files
|
||||
|
||||
/node_modules
|
||||
/extension
|
||||
/example/.vscode
|
||||
/.vscode-test
|
||||
|
||||
# macOS files
|
||||
|
||||
.DS_Store
|
||||
node_modules
|
||||
extension
|
||||
example/.vscode
|
||||
|
||||
Binary file not shown.
8
packages/bun-vscode/example/hello.js
Normal file
8
packages/bun-vscode/example/hello.js
Normal file
@@ -0,0 +1,8 @@
|
||||
console.log("HELLO");
|
||||
console.log("HELLO 2");
|
||||
console.log("HELLO 3");
|
||||
a();
|
||||
|
||||
function a() {
|
||||
console.log("HELLO 4");
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
type OS = "Windows";
|
||||
|
||||
Bun.serve({
|
||||
fetch(req: Request) {
|
||||
return new Response(`Hello, ${"Windows" as OS}!`);
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bun-vscode",
|
||||
"version": "0.0.15",
|
||||
"version": "0.0.8",
|
||||
"author": "oven",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -8,13 +8,11 @@
|
||||
},
|
||||
"main": "dist/extension.js",
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.1.10",
|
||||
"@types/vscode": "^1.60.0",
|
||||
"@vscode/debugadapter": "^1.56.0",
|
||||
"@vscode/debugadapter-testsupport": "^1.56.0",
|
||||
"@vscode/test-cli": "^0.0.10",
|
||||
"@vscode/test-electron": "^2.4.1",
|
||||
"@vscode/vsce": "^2.20.1",
|
||||
"bun-types": "^0.7.3",
|
||||
"esbuild": "^0.19.2",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
@@ -45,7 +43,6 @@
|
||||
"build": "node scripts/build.mjs",
|
||||
"pretest": "bun run build",
|
||||
"test": "node scripts/test.mjs",
|
||||
"dev": "vscode-test --config scripts/dev.mjs",
|
||||
"prepublish": "npm version patch && bun run build",
|
||||
"publish": "cd extension && bunx vsce publish"
|
||||
},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { buildSync } from "esbuild";
|
||||
import { execSync } from "node:child_process";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { cpSync, mkdirSync, rmSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
process.chdir(dirname(import.meta.dirname));
|
||||
const { pathname } = new URL("..", import.meta.url);
|
||||
process.chdir(pathname);
|
||||
|
||||
buildSync({
|
||||
entryPoints: ["src/extension.ts", "src/web-extension.ts"],
|
||||
@@ -26,7 +26,7 @@ cpSync("LICENSE", "extension/LICENSE");
|
||||
cpSync("package.json", "extension/package.json");
|
||||
|
||||
const cmd = process.isBun ? "bunx" : "npx";
|
||||
execSync(`${cmd} vsce package --no-dependencies`, {
|
||||
spawnSync(cmd, ["vsce", "package"], {
|
||||
cwd: "extension",
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { defineConfig } from "@vscode/test-cli";
|
||||
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
|
||||
const workspacePath = dirname(import.meta.dirname);
|
||||
const vscodePath = join(workspacePath, ".vscode-test");
|
||||
const vscodeTestPath = join(vscodePath, "launch.test.js");
|
||||
|
||||
if (!existsSync(vscodeTestPath)) {
|
||||
mkdirSync(vscodePath, { recursive: true });
|
||||
writeFileSync(
|
||||
vscodeTestPath,
|
||||
`// Generated by ${import.meta.filename}
|
||||
// A test that intentionally waits forever and does nothing,
|
||||
// so you can debug and test the VSCode extension in a clean environment.
|
||||
suite("VSCode extension", function () {
|
||||
this.timeout(Number.MAX_SAFE_INTEGER);
|
||||
test("wait forever", (done) => {});
|
||||
});
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
workspaceFolder: join(workspacePath, "example"),
|
||||
extensionDevelopmentPath: workspacePath,
|
||||
skipExtensionDependencies: true,
|
||||
files: vscodeTestPath,
|
||||
});
|
||||
@@ -1,21 +1,21 @@
|
||||
import { exec } from "node:child_process";
|
||||
import { spawn } from "node:child_process";
|
||||
import { readdirSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
process.chdir(dirname(import.meta.dirname));
|
||||
const { pathname } = new URL("..", import.meta.url);
|
||||
process.chdir(pathname);
|
||||
|
||||
let extPath;
|
||||
let path;
|
||||
for (const filename of readdirSync("extension")) {
|
||||
if (filename.endsWith(".vsix")) {
|
||||
extPath = `extension/${filename}`;
|
||||
path = `extension/${filename}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!extPath) {
|
||||
if (!path) {
|
||||
throw new Error("No .vsix file found");
|
||||
}
|
||||
|
||||
exec(`code --new-window --install-extension=${extPath} --extensionDevelopmentPath=${process.cwd()} example`, {
|
||||
spawn("code", ["--new-window", `--install-extension=${path}`, `--extensionDevelopmentPath=${pathname}`, "example"], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { DebugSession } from "@vscode/debugadapter";
|
||||
import { tmpdir } from "node:os";
|
||||
import * as vscode from "vscode";
|
||||
import {
|
||||
DAP,
|
||||
DebugAdapter,
|
||||
getAvailablePort,
|
||||
getRandomId,
|
||||
TCPSocketSignal,
|
||||
UnixSignal,
|
||||
} from "../../../bun-debug-adapter-protocol";
|
||||
import type { DAP } from "../../../bun-debug-adapter-protocol";
|
||||
import { DebugAdapter, UnixSignal } from "../../../bun-debug-adapter-protocol";
|
||||
|
||||
export const DEBUG_CONFIGURATION: vscode.DebugConfiguration = {
|
||||
type: "bun",
|
||||
@@ -87,7 +81,7 @@ function debugFileCommand(resource?: vscode.Uri) {
|
||||
if (path) debugCommand(path);
|
||||
}
|
||||
|
||||
async function injectDebugTerminal(terminal: vscode.Terminal): Promise<void> {
|
||||
function injectDebugTerminal(terminal: vscode.Terminal): void {
|
||||
if (!getConfig("debugTerminal.enabled")) return;
|
||||
|
||||
const { name, creationOptions } = terminal;
|
||||
@@ -103,16 +97,14 @@ async function injectDebugTerminal(terminal: vscode.Terminal): Promise<void> {
|
||||
const stopOnEntry = getConfig("debugTerminal.stopOnEntry") === true;
|
||||
const query = stopOnEntry ? "break=1" : "wait=1";
|
||||
|
||||
const debugSession = new TerminalDebugSession();
|
||||
await debugSession.initialize();
|
||||
const { adapter, signal } = debugSession;
|
||||
const { adapter, signal } = new TerminalDebugSession();
|
||||
const debug = vscode.window.createTerminal({
|
||||
...creationOptions,
|
||||
name: "JavaScript Debug Terminal",
|
||||
env: {
|
||||
...env,
|
||||
"BUN_INSPECT": `${adapter.url}?${query}`,
|
||||
"BUN_INSPECT_NOTIFY": signal.url,
|
||||
"BUN_INSPECT_NOTIFY": `${signal.url}`,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -161,9 +153,7 @@ class DebugConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
}
|
||||
|
||||
class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
async createDebugAdapterDescriptor(
|
||||
session: vscode.DebugSession,
|
||||
): Promise<vscode.ProviderResult<vscode.DebugAdapterDescriptor>> {
|
||||
createDebugAdapterDescriptor(session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
const { configuration } = session;
|
||||
const { request, url } = configuration;
|
||||
|
||||
@@ -176,28 +166,18 @@ class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory
|
||||
}
|
||||
|
||||
const adapter = new FileDebugSession(session.id);
|
||||
await adapter.initialize();
|
||||
return new vscode.DebugAdapterInlineImplementation(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
class FileDebugSession extends DebugSession {
|
||||
adapter: DebugAdapter;
|
||||
sessionId?: string;
|
||||
readonly adapter: DebugAdapter;
|
||||
|
||||
constructor(sessionId?: string) {
|
||||
super();
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
const uniqueId = sessionId ?? Math.random().toString(36).slice(2);
|
||||
const url = `ws+unix://${tmpdir()}/${uniqueId}.sock`;
|
||||
|
||||
async initialize() {
|
||||
const uniqueId = this.sessionId ?? Math.random().toString(36).slice(2);
|
||||
let url;
|
||||
if (process.platform === "win32") {
|
||||
url = `ws://127.0.0.1:${await getAvailablePort()}/${getRandomId()}`;
|
||||
} else {
|
||||
url = `ws+unix://${tmpdir()}/${uniqueId}.sock`;
|
||||
}
|
||||
this.adapter = new DebugAdapter(url);
|
||||
this.adapter.on("Adapter.response", response => this.sendResponse(response));
|
||||
this.adapter.on("Adapter.event", event => this.sendEvent(event));
|
||||
@@ -224,19 +204,11 @@ class FileDebugSession extends DebugSession {
|
||||
}
|
||||
|
||||
class TerminalDebugSession extends FileDebugSession {
|
||||
signal: TCPSocketSignal | UnixSignal;
|
||||
readonly signal: UnixSignal;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
await super.initialize();
|
||||
if (process.platform === "win32") {
|
||||
this.signal = new TCPSocketSignal(await getAvailablePort());
|
||||
} else {
|
||||
this.signal = new UnixSignal();
|
||||
}
|
||||
this.signal = new UnixSignal();
|
||||
this.signal.on("Signal.received", () => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
...ATTACH_CONFIGURATION,
|
||||
@@ -250,7 +222,7 @@ class TerminalDebugSession extends FileDebugSession {
|
||||
name: "Bun Terminal",
|
||||
env: {
|
||||
"BUN_INSPECT": `${this.adapter.url}?wait=1`,
|
||||
"BUN_INSPECT_NOTIFY": this.signal.url,
|
||||
"BUN_INSPECT_NOTIFY": `${this.signal.url}`,
|
||||
},
|
||||
isTransient: true,
|
||||
iconPath: new vscode.ThemeIcon("debug-console"),
|
||||
|
||||
@@ -19,9 +19,9 @@ add_compile_options(-Wall)
|
||||
if(NOT CMAKE_C_COMPILER_ID MATCHES "tcc")
|
||||
add_compile_options(
|
||||
-fno-strict-aliasing
|
||||
-Wdeclaration-after-statement
|
||||
-Wno-declaration-after-statement
|
||||
-Wpointer-sign
|
||||
-Wsign-compare
|
||||
-Wno-sign-compare
|
||||
-Wunused-result
|
||||
-Wformat-truncation
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawn as nodeSpawn } from "node:child_process";
|
||||
import { existsSync, readFileSync, mkdirSync, cpSync, chmodSync } from "node:fs";
|
||||
import { basename, join, resolve } from "node:path";
|
||||
import { existsSync, readFileSync, readdirSync, mkdirSync, cpSync, chmodSync } from "node:fs";
|
||||
import { basename, join, relative, resolve } from "node:path";
|
||||
|
||||
// https://cmake.org/cmake/help/latest/manual/cmake.1.html#generate-a-project-buildsystem
|
||||
const generateFlags = [
|
||||
@@ -118,6 +118,26 @@ async function build(args) {
|
||||
.flatMap(([flag, value]) => [flag, value]);
|
||||
await spawn("cmake", buildArgs, { env }, "compilation");
|
||||
|
||||
const buildFiles = ["ccache.log", "compile_commands.json"];
|
||||
const buildPaths = [buildPath, ...readdirSync(buildPath).map(path => join(buildPath, path))];
|
||||
const buildArtifacts = [];
|
||||
for (const buildPath of buildPaths) {
|
||||
for (const buildFile of buildFiles) {
|
||||
const path = join(buildPath, buildFile);
|
||||
if (existsSync(path)) {
|
||||
buildArtifacts.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isBuildkite()) {
|
||||
await Promise.all(
|
||||
buildArtifacts.map(path =>
|
||||
spawn("buildkite-agent", ["artifact", "upload", relative(buildPath, path)], { cwd: buildPath, env }),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
printDuration("total", Date.now() - startTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -999,7 +999,7 @@ pub const StandaloneModuleGraph = struct {
|
||||
bun.JSAst.Expr.Data.Store.reset();
|
||||
bun.JSAst.Stmt.Data.Store.reset();
|
||||
}
|
||||
var json = bun.JSON.ParseJSON(&json_src, &log, arena, false) catch
|
||||
var json = bun.JSON.ParseJSON(&json_src, &log, arena) catch
|
||||
return error.InvalidSourceMap;
|
||||
|
||||
const mappings_str = json.get("mappings") orelse
|
||||
|
||||
@@ -9,7 +9,7 @@ const BrotliEncoder = c.BrotliEncoder;
|
||||
|
||||
const mimalloc = bun.Mimalloc;
|
||||
|
||||
pub const BrotliAllocator = struct {
|
||||
const BrotliAllocator = struct {
|
||||
pub fn alloc(_: ?*anyopaque, len: usize) callconv(.C) *anyopaque {
|
||||
if (bun.heap_breakdown.enabled) {
|
||||
const zone = bun.heap_breakdown.getZone("brotli");
|
||||
|
||||
@@ -1118,7 +1118,7 @@ pub const Formatter = struct {
|
||||
|
||||
// Is this a react element?
|
||||
if (js_type.isObject()) {
|
||||
if (value.getOwnTruthy(globalThis, "$$typeof")) |typeof_symbol| {
|
||||
if (value.get(globalThis, "$$typeof")) |typeof_symbol| {
|
||||
var reactElement = ZigString.init("react.element");
|
||||
var react_fragment = ZigString.init("react.fragment");
|
||||
|
||||
|
||||
@@ -435,8 +435,7 @@ pub fn shellEscape(
|
||||
globalThis.throw("String has invalid utf-16: {s}", .{bunstr.byteSlice()});
|
||||
return .undefined;
|
||||
}
|
||||
var str = bun.String.createUTF8(outbuf.items[0..]);
|
||||
return str.transferToJS(globalThis);
|
||||
return bun.String.createUTF8(outbuf.items[0..]).toJS(globalThis);
|
||||
}
|
||||
return jsval;
|
||||
}
|
||||
@@ -446,8 +445,7 @@ pub fn shellEscape(
|
||||
globalThis.throwOutOfMemory();
|
||||
return .undefined;
|
||||
};
|
||||
var str = bun.String.createUTF8(outbuf.items[0..]);
|
||||
return str.transferToJS(globalThis);
|
||||
return bun.String.createUTF8(outbuf.items[0..]).toJS(globalThis);
|
||||
}
|
||||
|
||||
return jsval;
|
||||
@@ -477,11 +475,11 @@ pub fn braces(
|
||||
if (arguments.nextEat()) |opts_val| {
|
||||
if (opts_val.isObject()) {
|
||||
if (comptime bun.Environment.allow_assert) {
|
||||
if (opts_val.getOwnTruthy(globalThis, "tokenize")) |tokenize_val| {
|
||||
if (opts_val.getTruthy(globalThis, "tokenize")) |tokenize_val| {
|
||||
tokenize = if (tokenize_val.isBoolean()) tokenize_val.asBoolean() else false;
|
||||
}
|
||||
|
||||
if (opts_val.getOwnTruthy(globalThis, "parse")) |tokenize_val| {
|
||||
if (opts_val.getTruthy(globalThis, "parse")) |tokenize_val| {
|
||||
parse = if (tokenize_val.isBoolean()) tokenize_val.asBoolean() else false;
|
||||
}
|
||||
}
|
||||
@@ -609,11 +607,11 @@ pub fn which(
|
||||
|
||||
if (arguments.nextEat()) |arg| {
|
||||
if (!arg.isEmptyOrUndefinedOrNull() and arg.isObject()) {
|
||||
if (arg.getOwn(globalThis, "PATH")) |str_| {
|
||||
if (arg.get(globalThis, "PATH")) |str_| {
|
||||
path_str = str_.toSlice(globalThis, globalThis.bunVM().allocator);
|
||||
}
|
||||
|
||||
if (arg.getOwn(globalThis, "cwd")) |str_| {
|
||||
if (arg.get(globalThis, "cwd")) |str_| {
|
||||
cwd_str = str_.toSlice(globalThis, globalThis.bunVM().allocator);
|
||||
}
|
||||
}
|
||||
@@ -662,7 +660,7 @@ pub fn inspect(
|
||||
const arg1 = arguments[1];
|
||||
|
||||
if (arg1.isObject()) {
|
||||
if (arg1.getOwnTruthy(globalThis, "depth")) |opt| {
|
||||
if (arg1.getTruthy(globalThis, "depth")) |opt| {
|
||||
if (opt.isInt32()) {
|
||||
const arg = opt.toInt32();
|
||||
if (arg < 0) {
|
||||
@@ -934,7 +932,7 @@ pub fn openInEditor(
|
||||
|
||||
if (arguments.nextEat()) |opts| {
|
||||
if (!opts.isUndefinedOrNull()) {
|
||||
if (opts.getOwnTruthy(globalThis, "editor")) |editor_val| {
|
||||
if (opts.getTruthy(globalThis, "editor")) |editor_val| {
|
||||
var sliced = editor_val.toSlice(globalThis, arguments.arena.allocator());
|
||||
const prev_name = edit.name;
|
||||
|
||||
@@ -954,11 +952,11 @@ pub fn openInEditor(
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalThis, "line")) |line_| {
|
||||
if (opts.getTruthy(globalThis, "line")) |line_| {
|
||||
line = line_.toSlice(globalThis, arguments.arena.allocator()).slice();
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalThis, "column")) |column_| {
|
||||
if (opts.getTruthy(globalThis, "column")) |column_| {
|
||||
column = column_.toSlice(globalThis, arguments.arena.allocator()).slice();
|
||||
}
|
||||
}
|
||||
@@ -1830,7 +1828,7 @@ pub const Crypto = struct {
|
||||
|
||||
pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) ?Value {
|
||||
if (value.isObject()) {
|
||||
if (value.getOwnTruthy(globalObject, "algorithm")) |algorithm_value| {
|
||||
if (value.getTruthy(globalObject, "algorithm")) |algorithm_value| {
|
||||
if (!algorithm_value.isString()) {
|
||||
globalObject.throwInvalidArgumentType("hash", "algorithm", "string");
|
||||
return null;
|
||||
@@ -1847,7 +1845,7 @@ pub const Crypto = struct {
|
||||
.bcrypt = PasswordObject.Algorithm.Value.bcrpyt_default,
|
||||
};
|
||||
|
||||
if (value.getOwnTruthy(globalObject, "cost")) |rounds_value| {
|
||||
if (value.getTruthy(globalObject, "cost")) |rounds_value| {
|
||||
if (!rounds_value.isNumber()) {
|
||||
globalObject.throwInvalidArgumentType("hash", "cost", "number");
|
||||
return null;
|
||||
@@ -1868,7 +1866,7 @@ pub const Crypto = struct {
|
||||
inline .argon2id, .argon2d, .argon2i => |tag| {
|
||||
var argon = Algorithm.Argon2Params{};
|
||||
|
||||
if (value.getOwnTruthy(globalObject, "timeCost")) |time_value| {
|
||||
if (value.getTruthy(globalObject, "timeCost")) |time_value| {
|
||||
if (!time_value.isNumber()) {
|
||||
globalObject.throwInvalidArgumentType("hash", "timeCost", "number");
|
||||
return null;
|
||||
@@ -1884,7 +1882,7 @@ pub const Crypto = struct {
|
||||
argon.time_cost = @as(u32, @intCast(time_cost));
|
||||
}
|
||||
|
||||
if (value.getOwnTruthy(globalObject, "memoryCost")) |memory_value| {
|
||||
if (value.getTruthy(globalObject, "memoryCost")) |memory_value| {
|
||||
if (!memory_value.isNumber()) {
|
||||
globalObject.throwInvalidArgumentType("hash", "memoryCost", "number");
|
||||
return null;
|
||||
@@ -4612,11 +4610,11 @@ fn stringWidth(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC
|
||||
var ambiguous_as_wide = false;
|
||||
|
||||
if (options_object.isObject()) {
|
||||
if (options_object.getOwnTruthy(globalObject, "countAnsiEscapeCodes")) |count_ansi_escapes_value| {
|
||||
if (options_object.getTruthy(globalObject, "countAnsiEscapeCodes")) |count_ansi_escapes_value| {
|
||||
if (count_ansi_escapes_value.isBoolean())
|
||||
count_ansi_escapes = count_ansi_escapes_value.toBoolean();
|
||||
}
|
||||
if (options_object.getOwnTruthy(globalObject, "ambiguousIsNarrow")) |ambiguous_is_narrow| {
|
||||
if (options_object.getTruthy(globalObject, "ambiguousIsNarrow")) |ambiguous_is_narrow| {
|
||||
if (ambiguous_is_narrow.isBoolean())
|
||||
ambiguous_as_wide = !ambiguous_is_narrow.toBoolean();
|
||||
}
|
||||
@@ -4797,7 +4795,7 @@ pub const JSZlib = struct {
|
||||
library = .zlib;
|
||||
}
|
||||
|
||||
if (options_val.getOwnTruthy(globalThis, "library")) |library_value| {
|
||||
if (options_val.getTruthy(globalThis, "library")) |library_value| {
|
||||
if (!library_value.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected library to be a string", .{});
|
||||
return .zero;
|
||||
@@ -4924,7 +4922,7 @@ pub const JSZlib = struct {
|
||||
library = .zlib;
|
||||
}
|
||||
|
||||
if (options_val.getOwnTruthy(globalThis, "library")) |library_value| {
|
||||
if (options_val.getTruthy(globalThis, "library")) |library_value| {
|
||||
if (!library_value.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected library to be a string", .{});
|
||||
return .zero;
|
||||
|
||||
@@ -100,8 +100,8 @@ pub const JSBundler = struct {
|
||||
globalThis.throwInvalidArguments("Expected plugin to be an object", .{});
|
||||
return error.JSError;
|
||||
}
|
||||
if (try plugin.getOwnObject(globalThis, "SECRET_SERVER_COMPONENTS_INTERNALS")) |internals| {
|
||||
if (internals.getOwn(globalThis, "router")) |router_value| {
|
||||
if (try plugin.getObject(globalThis, "SECRET_SERVER_COMPONENTS_INTERNALS")) |internals| {
|
||||
if (internals.get(globalThis, "router")) |router_value| {
|
||||
if (router_value.as(JSC.API.FileSystemRouter) != null) {
|
||||
this.server_components.router.set(globalThis, router_value);
|
||||
} else {
|
||||
@@ -110,7 +110,7 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
const directive_object = (try internals.getOwnObject(globalThis, "directive")) orelse {
|
||||
const directive_object = (try internals.getObject(globalThis, "directive")) orelse {
|
||||
globalThis.throwInvalidArguments("Expected directive to be an object", .{});
|
||||
return error.JSError;
|
||||
};
|
||||
@@ -154,7 +154,7 @@ pub const JSBundler = struct {
|
||||
// };
|
||||
// defer decl.deinit();
|
||||
|
||||
if (plugin.getOwnOptional(globalThis, "name", ZigString.Slice) catch null) |slice| {
|
||||
if (plugin.getOptional(globalThis, "name", ZigString.Slice) catch null) |slice| {
|
||||
defer slice.deinit();
|
||||
if (slice.len == 0) {
|
||||
globalThis.throwInvalidArguments("Expected plugin to have a non-empty name", .{});
|
||||
@@ -198,24 +198,24 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "macros")) |macros_flag| {
|
||||
if (config.getTruthy(globalThis, "macros")) |macros_flag| {
|
||||
if (!macros_flag.coerce(bool, globalThis)) {
|
||||
this.no_macros = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (try config.getOwnOptionalEnum(globalThis, "target", options.Target)) |target| {
|
||||
if (try config.getOptionalEnum(globalThis, "target", options.Target)) |target| {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
var has_out_dir = false;
|
||||
if (try config.getOwnOptional(globalThis, "outdir", ZigString.Slice)) |slice| {
|
||||
if (try config.getOptional(globalThis, "outdir", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
try this.outdir.appendSliceExact(slice.slice());
|
||||
has_out_dir = true;
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "sourcemap")) |source_map_js| {
|
||||
if (config.getTruthy(globalThis, "sourcemap")) |source_map_js| {
|
||||
if (bun.FeatureFlags.breaking_changes_1_2 and config.isBoolean()) {
|
||||
if (source_map_js == .true) {
|
||||
this.source_map = if (has_out_dir)
|
||||
@@ -232,11 +232,11 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (try config.getOwnOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
if (try config.getOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
this.packages = packages;
|
||||
}
|
||||
|
||||
if (try config.getOwnOptionalEnum(globalThis, "format", options.Format)) |format| {
|
||||
if (try config.getOptionalEnum(globalThis, "format", options.Format)) |format| {
|
||||
switch (format) {
|
||||
.esm => {},
|
||||
else => {
|
||||
@@ -246,28 +246,28 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// if (try config.getOwnOptional(globalThis, "hot", bool)) |hot| {
|
||||
// if (try config.getOptional(globalThis, "hot", bool)) |hot| {
|
||||
// this.hot = hot;
|
||||
// }
|
||||
|
||||
if (try config.getOwnOptional(globalThis, "splitting", bool)) |hot| {
|
||||
if (try config.getOptional(globalThis, "splitting", bool)) |hot| {
|
||||
this.code_splitting = hot;
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "minify")) |hot| {
|
||||
if (config.getTruthy(globalThis, "minify")) |hot| {
|
||||
if (hot.isBoolean()) {
|
||||
const value = hot.coerce(bool, globalThis);
|
||||
this.minify.whitespace = value;
|
||||
this.minify.syntax = value;
|
||||
this.minify.identifiers = value;
|
||||
} else if (hot.isObject()) {
|
||||
if (try hot.getOwnOptional(globalThis, "whitespace", bool)) |whitespace| {
|
||||
if (try hot.getOptional(globalThis, "whitespace", bool)) |whitespace| {
|
||||
this.minify.whitespace = whitespace;
|
||||
}
|
||||
if (try hot.getOwnOptional(globalThis, "syntax", bool)) |syntax| {
|
||||
if (try hot.getOptional(globalThis, "syntax", bool)) |syntax| {
|
||||
this.minify.syntax = syntax;
|
||||
}
|
||||
if (try hot.getOwnOptional(globalThis, "identifiers", bool)) |syntax| {
|
||||
if (try hot.getOptional(globalThis, "identifiers", bool)) |syntax| {
|
||||
this.minify.identifiers = syntax;
|
||||
}
|
||||
} else {
|
||||
@@ -291,19 +291,19 @@ pub const JSBundler = struct {
|
||||
return error.JSError;
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "emitDCEAnnotations")) |flag| {
|
||||
if (config.getTruthy(globalThis, "emitDCEAnnotations")) |flag| {
|
||||
if (flag.coerce(bool, globalThis)) {
|
||||
this.emit_dce_annotations = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "ignoreDCEAnnotations")) |flag| {
|
||||
if (config.getTruthy(globalThis, "ignoreDCEAnnotations")) |flag| {
|
||||
if (flag.coerce(bool, globalThis)) {
|
||||
this.ignore_dce_annotations = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "conditions")) |conditions_value| {
|
||||
if (config.getTruthy(globalThis, "conditions")) |conditions_value| {
|
||||
if (conditions_value.isString()) {
|
||||
var slice = conditions_value.toSliceOrNull(globalThis) orelse {
|
||||
globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{});
|
||||
@@ -329,7 +329,7 @@ pub const JSBundler = struct {
|
||||
|
||||
{
|
||||
const path: ZigString.Slice = brk: {
|
||||
if (try config.getOwnOptional(globalThis, "root", ZigString.Slice)) |slice| {
|
||||
if (try config.getOptional(globalThis, "root", ZigString.Slice)) |slice| {
|
||||
break :brk slice;
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ pub const JSBundler = struct {
|
||||
try this.rootdir.appendSliceExact(rootdir);
|
||||
}
|
||||
|
||||
if (try config.getOwnArray(globalThis, "external")) |externals| {
|
||||
if (try config.getArray(globalThis, "external")) |externals| {
|
||||
var iter = externals.arrayIterator(globalThis);
|
||||
while (iter.next()) |entry_point| {
|
||||
var slice = entry_point.toSliceOrNull(globalThis) orelse {
|
||||
@@ -370,21 +370,21 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// if (try config.getOwnOptional(globalThis, "dir", ZigString.Slice)) |slice| {
|
||||
// if (try config.getOptional(globalThis, "dir", ZigString.Slice)) |slice| {
|
||||
// defer slice.deinit();
|
||||
// this.appendSliceExact(slice.slice()) catch unreachable;
|
||||
// } else {
|
||||
// this.appendSliceExact(globalThis.bunVM().bundler.fs.top_level_dir) catch unreachable;
|
||||
// }
|
||||
|
||||
if (try config.getOwnOptional(globalThis, "publicPath", ZigString.Slice)) |slice| {
|
||||
if (try config.getOptional(globalThis, "publicPath", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
try this.public_path.appendSliceExact(slice.slice());
|
||||
}
|
||||
|
||||
if (config.getOwnTruthy(globalThis, "naming")) |naming| {
|
||||
if (config.getTruthy(globalThis, "naming")) |naming| {
|
||||
if (naming.isString()) {
|
||||
if (try config.getOwnOptional(globalThis, "naming", ZigString.Slice)) |slice| {
|
||||
if (try config.getOptional(globalThis, "naming", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
|
||||
try this.names.owned_entry_point.appendSliceExact("./");
|
||||
@@ -393,7 +393,7 @@ pub const JSBundler = struct {
|
||||
this.names.entry_point.data = this.names.owned_entry_point.list.items;
|
||||
}
|
||||
} else if (naming.isObject()) {
|
||||
if (try naming.getOwnOptional(globalThis, "entry", ZigString.Slice)) |slice| {
|
||||
if (try naming.getOptional(globalThis, "entry", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
|
||||
try this.names.owned_entry_point.appendSliceExact("./");
|
||||
@@ -402,7 +402,7 @@ pub const JSBundler = struct {
|
||||
this.names.entry_point.data = this.names.owned_entry_point.list.items;
|
||||
}
|
||||
|
||||
if (try naming.getOwnOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
|
||||
if (try naming.getOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
|
||||
try this.names.owned_chunk.appendSliceExact("./");
|
||||
@@ -411,7 +411,7 @@ pub const JSBundler = struct {
|
||||
this.names.chunk.data = this.names.owned_chunk.list.items;
|
||||
}
|
||||
|
||||
if (try naming.getOwnOptional(globalThis, "asset", ZigString.Slice)) |slice| {
|
||||
if (try naming.getOptional(globalThis, "asset", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
|
||||
try this.names.owned_asset.appendSliceExact("./");
|
||||
@@ -425,7 +425,7 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (try config.getOwnObject(globalThis, "define")) |define| {
|
||||
if (try config.getObject(globalThis, "define")) |define| {
|
||||
if (!define.isObject()) {
|
||||
globalThis.throwInvalidArguments("define must be an object", .{});
|
||||
return error.JSError;
|
||||
@@ -463,7 +463,7 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (try config.getOwnObject(globalThis, "loader")) |loaders| {
|
||||
if (try config.getObject(globalThis, "loader")) |loaders| {
|
||||
var loader_iter = JSC.JSPropertyIterator(.{
|
||||
.skip_empty_name = true,
|
||||
.include_value = true,
|
||||
@@ -967,8 +967,6 @@ pub const JSBundler = struct {
|
||||
else
|
||||
bun.String.createUTF8(path.namespace);
|
||||
const path_string = bun.String.createUTF8(path.text);
|
||||
defer namespace_string.deref();
|
||||
defer path_string.deref();
|
||||
return JSBundlerPlugin__anyMatches(this, &namespace_string, &path_string, is_onLoad);
|
||||
}
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
return transpiler;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalObject, "define")) |define| {
|
||||
if (object.getIfPropertyExists(globalObject, "define")) |define| {
|
||||
define: {
|
||||
if (define.isUndefinedOrNull()) {
|
||||
break :define;
|
||||
@@ -379,7 +379,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "external")) |external| {
|
||||
if (object.get(globalThis, "external")) |external| {
|
||||
external: {
|
||||
if (external.isUndefinedOrNull()) break :external;
|
||||
|
||||
@@ -419,7 +419,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "loader")) |loader| {
|
||||
if (object.get(globalThis, "loader")) |loader| {
|
||||
if (Loader.fromJS(globalThis, loader, exception)) |resolved| {
|
||||
if (!resolved.isJavaScriptLike()) {
|
||||
JSC.throwInvalidArguments("only JavaScript-like loaders supported for now", .{}, globalObject, exception);
|
||||
@@ -434,7 +434,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "target")) |target| {
|
||||
if (object.get(globalThis, "target")) |target| {
|
||||
if (Target.fromJS(globalThis, target, exception)) |resolved| {
|
||||
transpiler.transform.target = resolved.toAPI();
|
||||
}
|
||||
@@ -444,7 +444,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "tsconfig")) |tsconfig| {
|
||||
if (object.get(globalThis, "tsconfig")) |tsconfig| {
|
||||
tsconfig: {
|
||||
if (tsconfig.isUndefinedOrNull()) break :tsconfig;
|
||||
const kind = tsconfig.jsType();
|
||||
@@ -483,7 +483,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
else => false,
|
||||
};
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "macro")) |macros| {
|
||||
if (object.getIfPropertyExists(globalThis, "macro")) |macros| {
|
||||
macros: {
|
||||
if (macros.isUndefinedOrNull()) break :macros;
|
||||
if (macros.isBoolean()) {
|
||||
@@ -518,39 +518,39 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwnOptional(globalThis, "autoImportJSX", bool) catch return transpiler) |flag| {
|
||||
if (object.getOptional(globalThis, "autoImportJSX", bool) catch return transpiler) |flag| {
|
||||
transpiler.runtime.auto_import_jsx = flag;
|
||||
}
|
||||
|
||||
if (object.getOwnOptional(globalThis, "allowBunRuntime", bool) catch return transpiler) |flag| {
|
||||
if (object.getOptional(globalThis, "allowBunRuntime", bool) catch return transpiler) |flag| {
|
||||
transpiler.runtime.allow_runtime = flag;
|
||||
}
|
||||
|
||||
if (object.getOwnOptional(globalThis, "inline", bool) catch return transpiler) |flag| {
|
||||
if (object.getOptional(globalThis, "inline", bool) catch return transpiler) |flag| {
|
||||
transpiler.runtime.inlining = flag;
|
||||
}
|
||||
|
||||
if (object.getOwnOptional(globalThis, "minifyWhitespace", bool) catch return transpiler) |flag| {
|
||||
if (object.getOptional(globalThis, "minifyWhitespace", bool) catch return transpiler) |flag| {
|
||||
transpiler.minify_whitespace = flag;
|
||||
}
|
||||
|
||||
if (object.getOwnOptional(globalThis, "deadCodeElimination", bool) catch return transpiler) |flag| {
|
||||
if (object.getOptional(globalThis, "deadCodeElimination", bool) catch return transpiler) |flag| {
|
||||
transpiler.dead_code_elimination = flag;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "minify")) |hot| {
|
||||
if (object.getTruthy(globalThis, "minify")) |hot| {
|
||||
if (hot.isBoolean()) {
|
||||
transpiler.minify_whitespace = hot.coerce(bool, globalThis);
|
||||
transpiler.minify_syntax = transpiler.minify_whitespace;
|
||||
transpiler.minify_identifiers = transpiler.minify_syntax;
|
||||
} else if (hot.isObject()) {
|
||||
if (try hot.getOwnOptional(globalThis, "whitespace", bool)) |whitespace| {
|
||||
if (try hot.getOptional(globalThis, "whitespace", bool)) |whitespace| {
|
||||
transpiler.minify_whitespace = whitespace;
|
||||
}
|
||||
if (try hot.getOwnOptional(globalThis, "syntax", bool)) |syntax| {
|
||||
if (try hot.getOptional(globalThis, "syntax", bool)) |syntax| {
|
||||
transpiler.minify_syntax = syntax;
|
||||
}
|
||||
if (try hot.getOwnOptional(globalThis, "identifiers", bool)) |syntax| {
|
||||
if (try hot.getOptional(globalThis, "identifiers", bool)) |syntax| {
|
||||
transpiler.minify_identifiers = syntax;
|
||||
}
|
||||
} else {
|
||||
@@ -559,7 +559,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "sourcemap")) |flag| {
|
||||
if (object.get(globalThis, "sourcemap")) |flag| {
|
||||
if (flag.isBoolean() or flag.isUndefinedOrNull()) {
|
||||
if (flag.toBoolean()) {
|
||||
transpiler.transform.source_map = .@"inline";
|
||||
@@ -576,21 +576,21 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (try object.getOwnOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
if (try object.getOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
transpiler.transform.packages = packages.toAPI();
|
||||
}
|
||||
|
||||
var tree_shaking: ?bool = null;
|
||||
if (object.getOwnOptional(globalThis, "treeShaking", bool) catch return transpiler) |treeShaking| {
|
||||
if (object.getOptional(globalThis, "treeShaking", bool) catch return transpiler) |treeShaking| {
|
||||
tree_shaking = treeShaking;
|
||||
}
|
||||
|
||||
var trim_unused_imports: ?bool = null;
|
||||
if (object.getOwnOptional(globalThis, "trimUnusedImports", bool) catch return transpiler) |trimUnusedImports| {
|
||||
if (object.getOptional(globalThis, "trimUnusedImports", bool) catch return transpiler) |trimUnusedImports| {
|
||||
trim_unused_imports = trimUnusedImports;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "exports")) |exports| {
|
||||
if (object.getTruthy(globalThis, "exports")) |exports| {
|
||||
if (!exports.isObject()) {
|
||||
JSC.throwInvalidArguments("exports must be an object", .{}, globalObject, exception);
|
||||
return transpiler;
|
||||
@@ -599,7 +599,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
var replacements = Runtime.Features.ReplaceableExport.Map{};
|
||||
errdefer replacements.clearAndFree(bun.default_allocator);
|
||||
|
||||
if (exports.getOwnTruthy(globalThis, "eliminate")) |eliminate| {
|
||||
if (exports.getTruthy(globalThis, "eliminate")) |eliminate| {
|
||||
if (!eliminate.jsType().isArray()) {
|
||||
JSC.throwInvalidArguments("exports.eliminate must be an array", .{}, globalObject, exception);
|
||||
return transpiler;
|
||||
@@ -641,7 +641,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (exports.getOwnTruthy(globalThis, "replace")) |replace| {
|
||||
if (exports.getTruthy(globalThis, "replace")) |replace| {
|
||||
if (!replace.isObject()) {
|
||||
JSC.throwInvalidArguments("replace must be an object", .{}, globalObject, exception);
|
||||
return transpiler;
|
||||
@@ -718,7 +718,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
transpiler.runtime.replace_exports = replacements;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "logLevel")) |logLevel| {
|
||||
if (object.getTruthy(globalThis, "logLevel")) |logLevel| {
|
||||
if (logger.Log.Level.Map.fromJS(globalObject, logLevel)) |level| {
|
||||
transpiler.log.level = level;
|
||||
} else {
|
||||
|
||||
@@ -239,7 +239,7 @@ const Handlers = struct {
|
||||
.{ "onHandshake", "handshake" },
|
||||
};
|
||||
inline for (pairs) |pair| {
|
||||
if (opts.getOwnTruthyComptime(globalObject, pair.@"1")) |callback_value| {
|
||||
if (opts.getTruthyComptime(globalObject, pair.@"1")) |callback_value| {
|
||||
if (!callback_value.isCell() or !callback_value.isCallable(globalObject.vm())) {
|
||||
exception.* = JSC.toInvalidArguments(comptime std.fmt.comptimePrint("Expected \"{s}\" callback to be a function", .{pair.@"1"}), .{}, globalObject).asObjectRef();
|
||||
return null;
|
||||
@@ -254,7 +254,7 @@ const Handlers = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalObject, "binaryType")) |binary_type_value| {
|
||||
if (opts.getTruthy(globalObject, "binaryType")) |binary_type_value| {
|
||||
if (!binary_type_value.isString()) {
|
||||
exception.* = JSC.toInvalidArguments("Expected \"binaryType\" to be a string", .{}, globalObject).asObjectRef();
|
||||
return null;
|
||||
@@ -341,13 +341,13 @@ pub const SocketConfig = struct {
|
||||
}
|
||||
|
||||
hostname_or_unix: {
|
||||
if (opts.getOwnTruthy(globalObject, "fd")) |fd_| {
|
||||
if (opts.getTruthy(globalObject, "fd")) |fd_| {
|
||||
if (fd_.isNumber()) {
|
||||
break :hostname_or_unix;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalObject, "unix")) |unix_socket| {
|
||||
if (opts.getTruthy(globalObject, "unix")) |unix_socket| {
|
||||
if (!unix_socket.isString()) {
|
||||
exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a string", .{}, globalObject).asObjectRef();
|
||||
return null;
|
||||
@@ -365,17 +365,17 @@ pub const SocketConfig = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalObject, "exclusive")) |_| {
|
||||
if (opts.getTruthy(globalObject, "exclusive")) |_| {
|
||||
exclusive = true;
|
||||
}
|
||||
|
||||
if (opts.getOwnTruthy(globalObject, "hostname") orelse opts.getOwnTruthy(globalObject, "host")) |hostname| {
|
||||
if (opts.getTruthy(globalObject, "hostname") orelse opts.getTruthy(globalObject, "host")) |hostname| {
|
||||
if (!hostname.isString()) {
|
||||
exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a string", .{}, globalObject).asObjectRef();
|
||||
return null;
|
||||
}
|
||||
|
||||
var port_value = opts.getOwn(globalObject, "port") orelse JSValue.zero;
|
||||
var port_value = opts.get(globalObject, "port") orelse JSValue.zero;
|
||||
hostname_or_unix = hostname.getZigString(globalObject).toSlice(bun.default_allocator);
|
||||
|
||||
if (port_value.isEmptyOrUndefinedOrNull() and hostname_or_unix.len > 0) {
|
||||
@@ -423,7 +423,7 @@ pub const SocketConfig = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
var handlers = Handlers.fromJS(globalObject, opts.getOwn(globalObject, "socket") orelse JSValue.zero, exception) orelse {
|
||||
var handlers = Handlers.fromJS(globalObject, opts.get(globalObject, "socket") orelse JSValue.zero, exception) orelse {
|
||||
hostname_or_unix.deinit();
|
||||
return null;
|
||||
};
|
||||
@@ -542,7 +542,7 @@ pub const Listener = struct {
|
||||
|
||||
var exception: JSC.C.JSValueRef = null;
|
||||
|
||||
const socket_obj = opts.getOwn(globalObject, "socket") orelse {
|
||||
const socket_obj = opts.get(globalObject, "socket") orelse {
|
||||
globalObject.throw("Expected \"socket\" object", .{});
|
||||
return .zero;
|
||||
};
|
||||
@@ -1069,7 +1069,7 @@ pub const Listener = struct {
|
||||
vm.eventLoop().ensureWaker();
|
||||
|
||||
var connection: Listener.UnixOrHost = blk: {
|
||||
if (opts.getOwnTruthy(globalObject, "fd")) |fd_| {
|
||||
if (opts.getTruthy(globalObject, "fd")) |fd_| {
|
||||
if (fd_.isNumber()) {
|
||||
const fd = fd_.asFileDescriptor();
|
||||
break :blk .{ .fd = fd };
|
||||
@@ -1236,30 +1236,46 @@ pub const Listener = struct {
|
||||
const promise_value = promise.asValue(globalObject);
|
||||
handlers_ptr.promise.set(globalObject, promise_value);
|
||||
|
||||
switch (ssl_enabled) {
|
||||
inline else => |is_ssl_enabled| {
|
||||
const SocketType = NewSocket(is_ssl_enabled);
|
||||
var socket = SocketType.new(.{
|
||||
.handlers = handlers_ptr,
|
||||
.this_value = .zero,
|
||||
.socket = SocketType.Socket.detached,
|
||||
.connection = connection,
|
||||
.protos = if (protos) |p| (bun.default_allocator.dupe(u8, p) catch bun.outOfMemory()) else null,
|
||||
.server_name = server_name,
|
||||
.socket_context = socket_context, // owns the socket context
|
||||
});
|
||||
if (ssl_enabled) {
|
||||
var tls = TLSSocket.new(.{
|
||||
.handlers = handlers_ptr,
|
||||
.this_value = .zero,
|
||||
.socket = TLSSocket.Socket.detached,
|
||||
.connection = connection,
|
||||
.protos = if (protos) |p| (bun.default_allocator.dupe(u8, p) catch bun.outOfMemory()) else null,
|
||||
.server_name = server_name,
|
||||
.socket_context = socket_context, // owns the socket context
|
||||
});
|
||||
|
||||
SocketType.dataSetCached(socket.getThisValue(globalObject), globalObject, default_data);
|
||||
|
||||
socket.doConnect(connection) catch {
|
||||
socket.handleConnectError(@intFromEnum(if (port == null) bun.C.SystemErrno.ENOENT else bun.C.SystemErrno.ECONNREFUSED));
|
||||
return promise_value;
|
||||
};
|
||||
|
||||
socket.poll_ref.ref(handlers.vm);
|
||||
TLSSocket.dataSetCached(tls.getThisValue(globalObject), globalObject, default_data);
|
||||
|
||||
tls.doConnect(connection) catch {
|
||||
tls.handleConnectError(@intFromEnum(if (port == null) bun.C.SystemErrno.ENOENT else bun.C.SystemErrno.ECONNREFUSED));
|
||||
return promise_value;
|
||||
},
|
||||
};
|
||||
|
||||
tls.poll_ref.ref(handlers.vm);
|
||||
|
||||
return promise_value;
|
||||
} else {
|
||||
var tcp = TCPSocket.new(.{
|
||||
.handlers = handlers_ptr,
|
||||
.this_value = .zero,
|
||||
.socket = TCPSocket.Socket.detached,
|
||||
.connection = null,
|
||||
.protos = null,
|
||||
.server_name = null,
|
||||
.socket_context = socket_context, // owns the socket context
|
||||
});
|
||||
|
||||
TCPSocket.dataSetCached(tcp.getThisValue(globalObject), globalObject, default_data);
|
||||
tcp.doConnect(connection) catch {
|
||||
tcp.handleConnectError(@intFromEnum(if (port == null) bun.C.SystemErrno.ENOENT else bun.C.SystemErrno.ECONNREFUSED));
|
||||
return promise_value;
|
||||
};
|
||||
tcp.poll_ref.ref(handlers.vm);
|
||||
|
||||
return promise_value;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1355,13 +1371,9 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
pub fn doConnect(this: *This, connection: Listener.UnixOrHost) !void {
|
||||
bun.assert(this.socket_context != null);
|
||||
this.ref();
|
||||
errdefer {
|
||||
this.deref();
|
||||
}
|
||||
|
||||
switch (connection) {
|
||||
.host => |c| {
|
||||
this.ref();
|
||||
this.socket = try This.Socket.connectAnon(
|
||||
normalizeHost(c.host),
|
||||
c.port,
|
||||
@@ -1370,6 +1382,8 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
);
|
||||
},
|
||||
.unix => |u| {
|
||||
this.ref();
|
||||
|
||||
this.socket = try This.Socket.connectUnixAnon(
|
||||
u,
|
||||
this.socket_context.?,
|
||||
@@ -1455,14 +1469,10 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
fn handleConnectError(this: *This, errno: c_int) void {
|
||||
log("onConnectError({d}, {})", .{ errno, this.ref_count });
|
||||
// Ensure the socket is still alive for any defer's we have
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
|
||||
const needs_deref = !this.socket.isDetached();
|
||||
this.socket = Socket.detached;
|
||||
defer this.markInactive();
|
||||
defer if (needs_deref) this.deref();
|
||||
defer this.markInactive();
|
||||
|
||||
const handlers = this.handlers;
|
||||
const vm = handlers.vm;
|
||||
@@ -1490,11 +1500,6 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
if (callback == .zero) {
|
||||
if (handlers.promise.trySwap()) |promise| {
|
||||
if (this.this_value != .zero) {
|
||||
this.this_value = .zero;
|
||||
}
|
||||
this.has_pending_activity.store(false, .release);
|
||||
|
||||
// reject the promise on connect() error
|
||||
const err_value = err.toErrorInstance(globalObject);
|
||||
promise.asPromise().?.rejectOnNextTick(globalObject, err_value);
|
||||
@@ -1504,9 +1509,6 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
|
||||
const this_value = this.getThisValue(globalObject);
|
||||
this.this_value = .zero;
|
||||
this.has_pending_activity.store(false, .release);
|
||||
|
||||
const err_value = err.toErrorInstance(globalObject);
|
||||
const result = callback.call(globalObject, this_value, &[_]JSValue{
|
||||
this_value,
|
||||
@@ -1522,6 +1524,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
var promise = val.asPromise().?;
|
||||
const err_ = err.toErrorInstance(globalObject);
|
||||
promise.rejectOnNextTickAsHandled(globalObject, err_);
|
||||
this.has_pending_activity.store(false, .release);
|
||||
}
|
||||
}
|
||||
pub fn onConnectError(this: *This, _: Socket, errno: c_int) void {
|
||||
@@ -1563,10 +1566,6 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
}
|
||||
|
||||
pub fn onOpen(this: *This, socket: Socket) void {
|
||||
// Ensure the socket remains alive until this is finished
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
|
||||
log("onOpen {} {}", .{ this.socket.isDetached(), this.ref_count });
|
||||
// update the internal socket instance to the one that was just connected
|
||||
// This socket must be replaced because the previous one is a connecting socket not a uSockets socket
|
||||
@@ -1665,9 +1664,6 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
JSC.markBinding(@src());
|
||||
log("onEnd", .{});
|
||||
if (this.socket.isDetached()) return;
|
||||
// Ensure the socket remains alive until this is finished
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
|
||||
const handlers = this.handlers;
|
||||
|
||||
@@ -2308,7 +2304,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
|
||||
var exception: JSC.C.JSValueRef = null;
|
||||
|
||||
const socket_obj = opts.getOwn(globalObject, "socket") orelse {
|
||||
const socket_obj = opts.get(globalObject, "socket") orelse {
|
||||
globalObject.throw("Expected \"socket\" option", .{});
|
||||
return .zero;
|
||||
};
|
||||
@@ -3082,7 +3078,7 @@ fn NewSocket(comptime ssl: bool) type {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const socket_obj = opts.getOwn(globalObject, "socket") orelse {
|
||||
const socket_obj = opts.get(globalObject, "socket") orelse {
|
||||
globalObject.throw("Expected \"socket\" option", .{});
|
||||
return .zero;
|
||||
};
|
||||
@@ -4007,7 +4003,7 @@ pub fn jsUpgradeDuplexToTLS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.C
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const socket_obj = opts.getOwn(globalObject, "socket") orelse {
|
||||
const socket_obj = opts.get(globalObject, "socket") orelse {
|
||||
globalObject.throw("Expected \"socket\" option", .{});
|
||||
return .zero;
|
||||
};
|
||||
@@ -4125,25 +4121,3 @@ pub fn createNodeTLSBinding(global: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
JSC.JSFunction.create(global, "isNamedPipeSocket", JSC.toJSHostFunction(jsIsNamedPipeSocket), 1, .{}),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn jsCreateSocketPair(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) JSValue {
|
||||
JSC.markBinding(@src());
|
||||
|
||||
if (Environment.isWindows) {
|
||||
global.throw("Not implemented on Windows", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
var fds_: [2]std.c.fd_t = .{ 0, 0 };
|
||||
const rc = std.c.socketpair(std.posix.AF.UNIX, std.posix.SOCK.STREAM, 0, &fds_);
|
||||
if (rc != 0) {
|
||||
const err = bun.sys.Error.fromCode(bun.C.getErrno(rc), .socketpair);
|
||||
global.throwValue(err.toJSC(global));
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const array = JSC.JSValue.createEmptyArray(global, 2);
|
||||
array.putIndex(global, 0, JSC.jsNumber(fds_[0]));
|
||||
array.putIndex(global, 1, JSC.jsNumber(fds_[1]));
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -211,7 +211,6 @@ pub const Subprocess = struct {
|
||||
killed: bool = false,
|
||||
has_stdin_destructor_called: bool = false,
|
||||
finalized: bool = false,
|
||||
deref_on_stdin_destroyed: bool = false,
|
||||
};
|
||||
|
||||
pub const SignalCode = bun.SignalCode;
|
||||
@@ -704,13 +703,9 @@ pub const Subprocess = struct {
|
||||
}
|
||||
|
||||
pub fn onStdinDestroyed(this: *Subprocess) void {
|
||||
const must_deref = this.flags.deref_on_stdin_destroyed;
|
||||
this.flags.deref_on_stdin_destroyed = false;
|
||||
defer if (must_deref) this.deref();
|
||||
|
||||
this.flags.has_stdin_destructor_called = true;
|
||||
this.weak_file_sink_stdin_ptr = null;
|
||||
|
||||
defer this.deref();
|
||||
if (!this.flags.finalized) {
|
||||
// otherwise update the pending activity flag
|
||||
this.updateHasPendingActivity();
|
||||
@@ -1245,7 +1240,6 @@ pub const Subprocess = struct {
|
||||
pipe.writer.setParent(pipe);
|
||||
subprocess.weak_file_sink_stdin_ptr = pipe;
|
||||
subprocess.ref();
|
||||
subprocess.flags.deref_on_stdin_destroyed = true;
|
||||
subprocess.flags.has_stdin_destructor_called = false;
|
||||
|
||||
return Writable{
|
||||
@@ -1306,7 +1300,6 @@ pub const Subprocess = struct {
|
||||
subprocess.weak_file_sink_stdin_ptr = pipe;
|
||||
subprocess.ref();
|
||||
subprocess.flags.has_stdin_destructor_called = false;
|
||||
subprocess.flags.deref_on_stdin_destroyed = true;
|
||||
|
||||
pipe.writer.handle.poll.flags.insert(.socket);
|
||||
|
||||
@@ -1352,23 +1345,12 @@ pub const Subprocess = struct {
|
||||
.pipe => |pipe| {
|
||||
this.* = .{ .ignore = {} };
|
||||
if (subprocess.process.hasExited() and !subprocess.flags.has_stdin_destructor_called) {
|
||||
// onAttachedProcessExit() can call deref on the
|
||||
// subprocess. Since we never called ref(), it would be
|
||||
// unbalanced to do so, leading to a use-after-free.
|
||||
// So, let's not do that.
|
||||
// https://github.com/oven-sh/bun/pull/14092
|
||||
bun.debugAssert(!subprocess.flags.deref_on_stdin_destroyed);
|
||||
const debug_ref_count: if (Environment.isDebug) u32 else u0 = if (Environment.isDebug) subprocess.ref_count else 0;
|
||||
pipe.onAttachedProcessExit();
|
||||
if (comptime Environment.isDebug) {
|
||||
bun.debugAssert(subprocess.ref_count == debug_ref_count);
|
||||
}
|
||||
return pipe.toJS(globalThis);
|
||||
} else {
|
||||
subprocess.flags.has_stdin_destructor_called = false;
|
||||
subprocess.weak_file_sink_stdin_ptr = pipe;
|
||||
subprocess.ref();
|
||||
subprocess.flags.deref_on_stdin_destroyed = true;
|
||||
if (@intFromPtr(pipe.signal.ptr) == @intFromPtr(subprocess)) {
|
||||
pipe.signal.clear();
|
||||
}
|
||||
@@ -1465,7 +1447,6 @@ pub const Subprocess = struct {
|
||||
if (stdin) |pipe| {
|
||||
this.weak_file_sink_stdin_ptr = null;
|
||||
this.flags.has_stdin_destructor_called = true;
|
||||
// It is okay if it does call deref() here, as in that case it was truly ref'd.
|
||||
pipe.onAttachedProcessExit();
|
||||
}
|
||||
|
||||
@@ -1716,7 +1697,7 @@ pub const Subprocess = struct {
|
||||
} else if (!args.isObject()) {
|
||||
globalThis.throwInvalidArguments("cmd must be an array", .{});
|
||||
return .zero;
|
||||
} else if (args.getOwnTruthy(globalThis, "cmd")) |cmd_value_| {
|
||||
} else if (args.getTruthy(globalThis, "cmd")) |cmd_value_| {
|
||||
cmd_value = cmd_value_;
|
||||
} else {
|
||||
globalThis.throwInvalidArguments("cmd must be an array", .{});
|
||||
@@ -1724,7 +1705,7 @@ pub const Subprocess = struct {
|
||||
}
|
||||
|
||||
if (args.isObject()) {
|
||||
if (args.getOwnTruthy(globalThis, "argv0")) |argv0_| {
|
||||
if (args.getTruthy(globalThis, "argv0")) |argv0_| {
|
||||
const argv0_str = argv0_.getZigString(globalThis);
|
||||
if (argv0_str.len > 0) {
|
||||
argv0 = argv0_str.toOwnedSliceZ(allocator) catch {
|
||||
@@ -1735,7 +1716,7 @@ pub const Subprocess = struct {
|
||||
}
|
||||
|
||||
// need to update `cwd` before searching for executable with `Which.which`
|
||||
if (args.getOwnTruthy(globalThis, "cwd")) |cwd_| {
|
||||
if (args.getTruthy(globalThis, "cwd")) |cwd_| {
|
||||
const cwd_str = cwd_.getZigString(globalThis);
|
||||
if (cwd_str.len > 0) {
|
||||
cwd = cwd_str.toOwnedSliceZ(allocator) catch {
|
||||
@@ -1820,21 +1801,21 @@ pub const Subprocess = struct {
|
||||
if (args != .zero and args.isObject()) {
|
||||
// This must run before the stdio parsing happens
|
||||
if (!is_sync) {
|
||||
if (args.getOwnTruthy(globalThis, "ipc")) |val| {
|
||||
if (args.getTruthy(globalThis, "ipc")) |val| {
|
||||
if (val.isCell() and val.isCallable(globalThis.vm())) {
|
||||
maybe_ipc_mode = ipc_mode: {
|
||||
if (args.getOwnTruthy(globalThis, "serialization")) |mode_val| {
|
||||
if (args.get(globalThis, "serialization")) |mode_val| {
|
||||
if (mode_val.isString()) {
|
||||
break :ipc_mode IPC.Mode.fromJS(globalThis, mode_val) orelse {
|
||||
if (!globalThis.hasException()) {
|
||||
globalThis.throwInvalidArguments("serialization must be \"json\" or \"advanced\"", .{});
|
||||
}
|
||||
const mode_str = mode_val.toBunString(globalThis);
|
||||
defer mode_str.deref();
|
||||
const slice = mode_str.toUTF8(bun.default_allocator);
|
||||
defer slice.deinit();
|
||||
break :ipc_mode IPC.Mode.fromString(slice.slice()) orelse {
|
||||
globalThis.throwInvalidArguments("serialization must be \"json\" or \"advanced\"", .{});
|
||||
return .zero;
|
||||
};
|
||||
} else {
|
||||
if (!globalThis.hasException()) {
|
||||
globalThis.throwInvalidArgumentType("spawn", "serialization", "string");
|
||||
}
|
||||
globalThis.throwInvalidArguments("serialization must be a 'string'", .{});
|
||||
return .zero;
|
||||
}
|
||||
}
|
||||
@@ -1846,7 +1827,7 @@ pub const Subprocess = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (args.getOwnTruthy(globalThis, "onDisconnect")) |onDisconnect_| {
|
||||
if (args.getTruthy(globalThis, "onDisconnect")) |onDisconnect_| {
|
||||
if (!onDisconnect_.isCell() or !onDisconnect_.isCallable(globalThis.vm())) {
|
||||
globalThis.throwInvalidArguments("onDisconnect must be a function or undefined", .{});
|
||||
return .zero;
|
||||
@@ -1858,7 +1839,7 @@ pub const Subprocess = struct {
|
||||
onDisconnect_.withAsyncContextIfNeeded(globalThis);
|
||||
}
|
||||
|
||||
if (args.getOwnTruthy(globalThis, "onExit")) |onExit_| {
|
||||
if (args.getTruthy(globalThis, "onExit")) |onExit_| {
|
||||
if (!onExit_.isCell() or !onExit_.isCallable(globalThis.vm())) {
|
||||
globalThis.throwInvalidArguments("onExit must be a function or undefined", .{});
|
||||
return .zero;
|
||||
@@ -1870,7 +1851,7 @@ pub const Subprocess = struct {
|
||||
onExit_.withAsyncContextIfNeeded(globalThis);
|
||||
}
|
||||
|
||||
if (args.getOwnTruthy(globalThis, "env")) |object| {
|
||||
if (args.getTruthy(globalThis, "env")) |object| {
|
||||
if (!object.isObject()) {
|
||||
globalThis.throwInvalidArguments("env must be an object", .{});
|
||||
return .zero;
|
||||
@@ -1886,7 +1867,7 @@ pub const Subprocess = struct {
|
||||
};
|
||||
env_array = envp_managed.moveToUnmanaged();
|
||||
}
|
||||
if (args.getOwn(globalThis, "stdio")) |stdio_val| {
|
||||
if (args.get(globalThis, "stdio")) |stdio_val| {
|
||||
if (!stdio_val.isEmptyOrUndefinedOrNull()) {
|
||||
if (stdio_val.jsType().isArray()) {
|
||||
var stdio_iter = stdio_val.arrayIterator(globalThis);
|
||||
@@ -1925,44 +1906,44 @@ pub const Subprocess = struct {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (args.getOwn(globalThis, "stdin")) |value| {
|
||||
if (args.get(globalThis, "stdin")) |value| {
|
||||
if (!stdio[0].extract(globalThis, 0, value))
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (args.getOwn(globalThis, "stderr")) |value| {
|
||||
if (args.get(globalThis, "stderr")) |value| {
|
||||
if (!stdio[2].extract(globalThis, 2, value))
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (args.getOwn(globalThis, "stdout")) |value| {
|
||||
if (args.get(globalThis, "stdout")) |value| {
|
||||
if (!stdio[1].extract(globalThis, 1, value))
|
||||
return .zero;
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime !is_sync) {
|
||||
if (args.getOwn(globalThis, "lazy")) |lazy_val| {
|
||||
if (args.get(globalThis, "lazy")) |lazy_val| {
|
||||
if (lazy_val.isBoolean()) {
|
||||
lazy = lazy_val.toBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.getOwn(globalThis, "detached")) |detached_val| {
|
||||
if (args.get(globalThis, "detached")) |detached_val| {
|
||||
if (detached_val.isBoolean()) {
|
||||
detached = detached_val.toBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
if (Environment.isWindows) {
|
||||
if (args.getOwn(globalThis, "windowsHide")) |val| {
|
||||
if (args.get(globalThis, "windowsHide")) |val| {
|
||||
if (val.isBoolean()) {
|
||||
windows_hide = val.asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
if (args.getOwn(globalThis, "windowsVerbatimArguments")) |val| {
|
||||
if (args.get(globalThis, "windowsVerbatimArguments")) |val| {
|
||||
if (val.isBoolean()) {
|
||||
windows_verbatim_arguments = val.asBoolean();
|
||||
}
|
||||
@@ -2086,35 +2067,13 @@ pub const Subprocess = struct {
|
||||
} else {},
|
||||
};
|
||||
|
||||
var spawned = switch (bun.spawn.spawnProcess(
|
||||
&spawn_options,
|
||||
@ptrCast(argv.items.ptr),
|
||||
@ptrCast(env_array.items.ptr),
|
||||
) catch |err| {
|
||||
spawn_options.deinit();
|
||||
globalThis.throwError(err, ": failed to spawn process");
|
||||
|
||||
return .zero;
|
||||
}) {
|
||||
.err => |err| {
|
||||
spawn_options.deinit();
|
||||
globalThis.throwValue(err.toJSC(globalThis));
|
||||
return .zero;
|
||||
},
|
||||
.result => |result| result,
|
||||
};
|
||||
|
||||
const loop = jsc_vm.eventLoop();
|
||||
|
||||
const process = spawned.toProcess(loop, is_sync);
|
||||
|
||||
var subprocess = Subprocess.new(.{
|
||||
.globalThis = globalThis,
|
||||
.process = process,
|
||||
.process = undefined,
|
||||
.pid_rusage = null,
|
||||
.stdin = .{ .ignore = {} },
|
||||
.stdout = .{ .ignore = {} },
|
||||
.stderr = .{ .ignore = {} },
|
||||
.stdin = undefined,
|
||||
.stdout = undefined,
|
||||
.stderr = undefined,
|
||||
.stdio_pipes = .{},
|
||||
.on_exit_callback = .{},
|
||||
.on_disconnect_callback = .{},
|
||||
@@ -2125,15 +2084,51 @@ pub const Subprocess = struct {
|
||||
},
|
||||
});
|
||||
|
||||
const posix_ipc_fd = if (Environment.isPosix and !is_sync and maybe_ipc_mode != null)
|
||||
spawned.extra_pipes.items[@intCast(ipc_channel)]
|
||||
else
|
||||
bun.invalid_fd;
|
||||
var spawned = switch (bun.spawn.spawnProcess(
|
||||
&spawn_options,
|
||||
@ptrCast(argv.items.ptr),
|
||||
@ptrCast(env_array.items.ptr),
|
||||
) catch |err| {
|
||||
subprocess.deref();
|
||||
spawn_options.deinit();
|
||||
globalThis.throwError(err, ": failed to spawn process");
|
||||
|
||||
return .zero;
|
||||
}) {
|
||||
.err => |err| {
|
||||
subprocess.deref();
|
||||
spawn_options.deinit();
|
||||
globalThis.throwValue(err.toJSC(globalThis));
|
||||
return .zero;
|
||||
},
|
||||
.result => |result| result,
|
||||
};
|
||||
|
||||
var posix_ipc_info: if (Environment.isPosix) IPC.Socket else void = undefined;
|
||||
if (Environment.isPosix and !is_sync) {
|
||||
if (maybe_ipc_mode != null) {
|
||||
posix_ipc_info = IPC.Socket.from(
|
||||
// we initialize ext later in the function
|
||||
uws.us_socket_from_fd(
|
||||
jsc_vm.rareData().spawnIPCContext(jsc_vm),
|
||||
@sizeOf(*Subprocess),
|
||||
spawned.extra_pipes.items[@intCast(ipc_channel)].cast(),
|
||||
) orelse {
|
||||
subprocess.deref();
|
||||
spawn_options.deinit();
|
||||
globalThis.throw("failed to create socket pair", .{});
|
||||
return .zero;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const loop = jsc_vm.eventLoop();
|
||||
|
||||
// When run synchronously, subprocess isn't garbage collected
|
||||
subprocess.* = Subprocess{
|
||||
.globalThis = globalThis,
|
||||
.process = process,
|
||||
.process = spawned.toProcess(loop, is_sync),
|
||||
.pid_rusage = null,
|
||||
.stdin = Writable.init(
|
||||
stdio[0],
|
||||
@@ -2142,7 +2137,6 @@ pub const Subprocess = struct {
|
||||
spawned.stdin,
|
||||
) catch {
|
||||
globalThis.throwOutOfMemory();
|
||||
subprocess.deref();
|
||||
return .zero;
|
||||
},
|
||||
.stdout = Readable.init(
|
||||
@@ -2163,16 +2157,19 @@ pub const Subprocess = struct {
|
||||
default_max_buffer_size,
|
||||
is_sync,
|
||||
),
|
||||
// 1. JavaScript.
|
||||
// 2. Process.
|
||||
.ref_count = 2,
|
||||
.stdio_pipes = spawned.extra_pipes.moveToUnmanaged(),
|
||||
.on_exit_callback = if (on_exit_callback != .zero) JSC.Strong.create(on_exit_callback, globalThis) else .{},
|
||||
.on_disconnect_callback = if (on_disconnect_callback != .zero) JSC.Strong.create(on_disconnect_callback, globalThis) else .{},
|
||||
.ipc_data = if (!is_sync and comptime Environment.isWindows)
|
||||
if (maybe_ipc_mode) |ipc_mode| .{
|
||||
.mode = ipc_mode,
|
||||
} else null
|
||||
.ipc_data = if (!is_sync)
|
||||
if (maybe_ipc_mode) |ipc_mode|
|
||||
if (Environment.isWindows) .{
|
||||
.mode = ipc_mode,
|
||||
} else .{
|
||||
.socket = posix_ipc_info,
|
||||
.mode = ipc_mode,
|
||||
}
|
||||
else
|
||||
null
|
||||
else
|
||||
null,
|
||||
.ipc_callback = if (ipc_callback != .zero) JSC.Strong.create(ipc_callback, globalThis) else .{},
|
||||
@@ -2180,26 +2177,9 @@ pub const Subprocess = struct {
|
||||
.is_sync = is_sync,
|
||||
},
|
||||
};
|
||||
|
||||
subprocess.ref(); // + one ref for the process
|
||||
subprocess.process.setExitHandler(subprocess);
|
||||
|
||||
var posix_ipc_info: if (Environment.isPosix) IPC.Socket else void = undefined;
|
||||
if (Environment.isPosix and !is_sync) {
|
||||
if (maybe_ipc_mode) |mode| {
|
||||
if (uws.us_socket_from_fd(
|
||||
jsc_vm.rareData().spawnIPCContext(jsc_vm),
|
||||
@sizeOf(*Subprocess),
|
||||
posix_ipc_fd.cast(),
|
||||
)) |socket| {
|
||||
posix_ipc_info = IPC.Socket.from(socket);
|
||||
subprocess.ipc_data = .{
|
||||
.socket = posix_ipc_info,
|
||||
.mode = mode,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subprocess.ipc_data) |*ipc_data| {
|
||||
if (Environment.isPosix) {
|
||||
if (posix_ipc_info.ext(*Subprocess)) |ctx| {
|
||||
|
||||
@@ -129,7 +129,7 @@ pub const UDPSocketConfig = struct {
|
||||
}
|
||||
|
||||
const hostname = brk: {
|
||||
if (options.getOwnTruthy(globalThis, "hostname")) |value| {
|
||||
if (options.getTruthy(globalThis, "hostname")) |value| {
|
||||
if (!value.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected \"hostname\" to be a string", .{});
|
||||
return null;
|
||||
@@ -144,7 +144,7 @@ pub const UDPSocketConfig = struct {
|
||||
defer if (globalThis.hasException()) default_allocator.free(hostname);
|
||||
|
||||
const port: u16 = brk: {
|
||||
if (options.getOwnTruthy(globalThis, "port")) |value| {
|
||||
if (options.getTruthy(globalThis, "port")) |value| {
|
||||
const number = value.coerceToInt32(globalThis);
|
||||
if (number < 0 or number > 0xffff) {
|
||||
globalThis.throwInvalidArguments("Expected \"port\" to be an integer between 0 and 65535", .{});
|
||||
@@ -161,13 +161,13 @@ pub const UDPSocketConfig = struct {
|
||||
.port = port,
|
||||
};
|
||||
|
||||
if (options.getOwnTruthy(globalThis, "socket")) |socket| {
|
||||
if (options.getTruthy(globalThis, "socket")) |socket| {
|
||||
if (!socket.isObject()) {
|
||||
globalThis.throwInvalidArguments("Expected \"socket\" to be an object", .{});
|
||||
return null;
|
||||
}
|
||||
|
||||
if (options.getOwnTruthy(globalThis, "binaryType")) |value| {
|
||||
if (options.getTruthy(globalThis, "binaryType")) |value| {
|
||||
if (!value.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected \"socket.binaryType\" to be a string", .{});
|
||||
return null;
|
||||
@@ -180,7 +180,7 @@ pub const UDPSocketConfig = struct {
|
||||
}
|
||||
|
||||
inline for (handlers) |handler| {
|
||||
if (socket.getOwnTruthyComptime(globalThis, handler.@"0")) |value| {
|
||||
if (socket.getTruthyComptime(globalThis, handler.@"0")) |value| {
|
||||
if (!value.isCell() or !value.isCallable(globalThis.vm())) {
|
||||
globalThis.throwInvalidArguments("Expected \"socket.{s}\" to be a function", .{handler.@"0"});
|
||||
return null;
|
||||
@@ -198,13 +198,13 @@ pub const UDPSocketConfig = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (options.getOwnTruthy(globalThis, "connect")) |connect| {
|
||||
if (options.getTruthy(globalThis, "connect")) |connect| {
|
||||
if (!connect.isObject()) {
|
||||
globalThis.throwInvalidArguments("Expected \"connect\" to be an object", .{});
|
||||
return null;
|
||||
}
|
||||
|
||||
const connect_host_js = connect.getOwnTruthy(globalThis, "hostname") orelse {
|
||||
const connect_host_js = connect.getTruthy(globalThis, "hostname") orelse {
|
||||
globalThis.throwInvalidArguments("Expected \"connect.hostname\" to be a string", .{});
|
||||
return null;
|
||||
};
|
||||
@@ -214,7 +214,7 @@ pub const UDPSocketConfig = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
const connect_port_js = connect.getOwnTruthy(globalThis, "port") orelse {
|
||||
const connect_port_js = connect.getTruthy(globalThis, "port") orelse {
|
||||
globalThis.throwInvalidArguments("Expected \"connect.port\" to be an integer", .{});
|
||||
return null;
|
||||
};
|
||||
@@ -631,8 +631,7 @@ pub const UDPSocket = struct {
|
||||
};
|
||||
|
||||
const slice = bun.fmt.formatIp(address, &text_buf) catch unreachable;
|
||||
var str = bun.String.createLatin1(slice);
|
||||
return str.transferToJS(globalThis);
|
||||
return bun.String.createLatin1(slice).toJS(globalThis);
|
||||
}
|
||||
|
||||
pub fn getAddress(this: *This, globalThis: *JSGlobalObject) JSValue {
|
||||
|
||||
@@ -627,7 +627,7 @@ pub const FFI = struct {
|
||||
}
|
||||
}
|
||||
|
||||
const symbols_object = object.getOwn(globalThis, "symbols") orelse .undefined;
|
||||
const symbols_object = object.get(globalThis, "symbols") orelse .undefined;
|
||||
if (!globalThis.hasException() and (symbols_object == .zero or !symbols_object.isObject())) {
|
||||
_ = globalThis.throwInvalidArgumentTypeValue("symbols", "object", symbols_object);
|
||||
}
|
||||
@@ -647,7 +647,7 @@ pub const FFI = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "library")) |library_value| {
|
||||
if (object.get(globalThis, "library")) |library_value| {
|
||||
compile_c.libraries = StringArray.fromJS(globalThis, library_value, "library");
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ pub const FFI = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "flags")) |flags_value| {
|
||||
if (object.getTruthy(globalThis, "flags")) |flags_value| {
|
||||
if (flags_value.isArray()) {
|
||||
var iter = flags_value.arrayIterator(globalThis);
|
||||
|
||||
@@ -692,7 +692,7 @@ pub const FFI = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "define")) |define_value| {
|
||||
if (object.getTruthy(globalThis, "define")) |define_value| {
|
||||
if (define_value.isObject()) {
|
||||
const Iter = JSC.JSPropertyIterator(.{ .include_value = true, .skip_empty_name = true });
|
||||
var iter = Iter.init(globalThis, define_value);
|
||||
@@ -722,7 +722,7 @@ pub const FFI = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (object.getOwnTruthy(globalThis, "include")) |include_value| {
|
||||
if (object.getTruthy(globalThis, "include")) |include_value| {
|
||||
compile_c.include_dirs = StringArray.fromJS(globalThis, include_value, "include");
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ pub const FFI = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (object.getOwn(globalThis, "source")) |source_value| {
|
||||
if (object.get(globalThis, "source")) |source_value| {
|
||||
if (source_value.isArray()) {
|
||||
compile_c.source = .{ .files = .{} };
|
||||
var iter = source_value.arrayIterator(globalThis);
|
||||
@@ -1301,7 +1301,7 @@ pub const FFI = struct {
|
||||
|
||||
var abi_types = std.ArrayListUnmanaged(ABIType){};
|
||||
|
||||
if (value.getOwn(global, "args")) |args| {
|
||||
if (value.get(global, "args")) |args| {
|
||||
if (args.isEmptyOrUndefinedOrNull() or !args.jsType().isArray()) {
|
||||
return ZigString.static("Expected an object with \"args\" as an array").toErrorInstance(global);
|
||||
}
|
||||
@@ -1347,11 +1347,11 @@ pub const FFI = struct {
|
||||
|
||||
var threadsafe = false;
|
||||
|
||||
if (value.getOwnTruthy(global, "threadsafe")) |threadsafe_value| {
|
||||
if (value.getTruthy(global, "threadsafe")) |threadsafe_value| {
|
||||
threadsafe = threadsafe_value.toBoolean();
|
||||
}
|
||||
|
||||
if (value.getOwnTruthy(global, "returns")) |ret_value| brk: {
|
||||
if (value.getTruthy(global, "returns")) |ret_value| brk: {
|
||||
if (ret_value.isAnyInt()) {
|
||||
const int = ret_value.toInt32();
|
||||
switch (int) {
|
||||
|
||||
@@ -69,7 +69,7 @@ pub const FileSystemRouter = struct {
|
||||
var asset_prefix_slice: ZigString.Slice = .{};
|
||||
|
||||
var out_buf: [bun.MAX_PATH_BYTES * 2]u8 = undefined;
|
||||
if (argument.getOwn(globalThis, "style")) |style_val| {
|
||||
if (argument.get(globalThis, "style")) |style_val| {
|
||||
if (!style_val.getZigString(globalThis).eqlComptime("nextjs")) {
|
||||
globalThis.throwInvalidArguments("Only 'nextjs' style is currently implemented", .{});
|
||||
return null;
|
||||
@@ -79,7 +79,7 @@ pub const FileSystemRouter = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (argument.getOwn(globalThis, "dir")) |dir| {
|
||||
if (argument.get(globalThis, "dir")) |dir| {
|
||||
if (!dir.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected dir to be a string", .{});
|
||||
return null;
|
||||
@@ -104,7 +104,7 @@ pub const FileSystemRouter = struct {
|
||||
arena.* = bun.ArenaAllocator.init(globalThis.allocator());
|
||||
const allocator = arena.allocator();
|
||||
var extensions = std.ArrayList(string).init(allocator);
|
||||
if (argument.getOwn(globalThis, "fileExtensions")) |file_extensions| {
|
||||
if (argument.get(globalThis, "fileExtensions")) |file_extensions| {
|
||||
if (!file_extensions.jsType().isArray()) {
|
||||
globalThis.throwInvalidArguments("Expected fileExtensions to be an Array", .{});
|
||||
origin_str.deinit();
|
||||
@@ -128,7 +128,7 @@ pub const FileSystemRouter = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (argument.getOwnTruthy(globalThis, "assetPrefix")) |asset_prefix| {
|
||||
if (argument.getTruthy(globalThis, "assetPrefix")) |asset_prefix| {
|
||||
if (!asset_prefix.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected assetPrefix to be a string", .{});
|
||||
origin_str.deinit();
|
||||
@@ -174,7 +174,7 @@ pub const FileSystemRouter = struct {
|
||||
return null;
|
||||
};
|
||||
|
||||
if (argument.getOwn(globalThis, "origin")) |origin| {
|
||||
if (argument.get(globalThis, "origin")) |origin| {
|
||||
if (!origin.isString()) {
|
||||
globalThis.throwInvalidArguments("Expected origin to be a string", .{});
|
||||
arena.deinit();
|
||||
|
||||
@@ -120,23 +120,23 @@ const ScanOpts = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "onlyFiles")) |only_files| {
|
||||
if (optsObj.getTruthy(globalThis, "onlyFiles")) |only_files| {
|
||||
out.only_files = if (only_files.isBoolean()) only_files.asBoolean() else false;
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "throwErrorOnBrokenSymlink")) |error_on_broken| {
|
||||
if (optsObj.getTruthy(globalThis, "throwErrorOnBrokenSymlink")) |error_on_broken| {
|
||||
out.error_on_broken_symlinks = if (error_on_broken.isBoolean()) error_on_broken.asBoolean() else false;
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "followSymlinks")) |followSymlinksVal| {
|
||||
if (optsObj.getTruthy(globalThis, "followSymlinks")) |followSymlinksVal| {
|
||||
out.follow_symlinks = if (followSymlinksVal.isBoolean()) followSymlinksVal.asBoolean() else false;
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "absolute")) |absoluteVal| {
|
||||
if (optsObj.getTruthy(globalThis, "absolute")) |absoluteVal| {
|
||||
out.absolute = if (absoluteVal.isBoolean()) absoluteVal.asBoolean() else false;
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "cwd")) |cwdVal| {
|
||||
if (optsObj.getTruthy(globalThis, "cwd")) |cwdVal| {
|
||||
if (!cwdVal.isString()) {
|
||||
globalThis.throw("{s}: invalid `cwd`, not a string", .{fnName});
|
||||
return null;
|
||||
@@ -152,7 +152,7 @@ const ScanOpts = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (optsObj.getOwnTruthy(globalThis, "dot")) |dot| {
|
||||
if (optsObj.getTruthy(globalThis, "dot")) |dot| {
|
||||
out.dot = if (dot.isBoolean()) dot.asBoolean() else false;
|
||||
}
|
||||
|
||||
|
||||
811
src/bun.js/api/js_brotli.zig
Normal file
811
src/bun.js/api/js_brotli.zig
Normal file
@@ -0,0 +1,811 @@
|
||||
const bun = @import("root").bun;
|
||||
const JSC = bun.JSC;
|
||||
const std = @import("std");
|
||||
const brotli = bun.brotli;
|
||||
|
||||
const Queue = std.fifo.LinearFifo(JSC.Node.BlobOrStringOrBuffer, .Dynamic);
|
||||
|
||||
// We cannot free outside the JavaScript thread.
|
||||
const FreeList = struct {
|
||||
write_lock: bun.Lock = .{},
|
||||
list: std.ArrayListUnmanaged(JSC.Node.BlobOrStringOrBuffer) = .{},
|
||||
|
||||
pub fn append(this: *FreeList, slice: []const JSC.Node.BlobOrStringOrBuffer) void {
|
||||
this.write_lock.lock();
|
||||
defer this.write_lock.unlock();
|
||||
this.list.appendSlice(bun.default_allocator, slice) catch bun.outOfMemory();
|
||||
}
|
||||
|
||||
pub fn drain(this: *FreeList) void {
|
||||
this.write_lock.lock();
|
||||
defer this.write_lock.unlock();
|
||||
const out = this.list.items;
|
||||
for (out) |*item| {
|
||||
item.deinitAndUnprotect();
|
||||
}
|
||||
this.list.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn deinit(this: *FreeList) void {
|
||||
this.drain();
|
||||
this.list.deinit(bun.default_allocator);
|
||||
}
|
||||
};
|
||||
|
||||
pub const BrotliEncoder = struct {
|
||||
pub usingnamespace bun.New(@This());
|
||||
pub usingnamespace JSC.Codegen.JSBrotliEncoder;
|
||||
|
||||
stream: brotli.BrotliCompressionStream,
|
||||
chunkSize: c_uint,
|
||||
maxOutputLength: usize,
|
||||
|
||||
freelist: FreeList = .{},
|
||||
|
||||
globalThis: *JSC.JSGlobalObject,
|
||||
mode: u8,
|
||||
|
||||
input: Queue = Queue.init(bun.default_allocator),
|
||||
input_lock: bun.Lock = .{},
|
||||
|
||||
has_called_end: bool = false,
|
||||
callback_value: JSC.Strong = .{},
|
||||
|
||||
output: std.ArrayListUnmanaged(u8) = .{},
|
||||
output_lock: bun.Lock = .{},
|
||||
|
||||
has_pending_activity: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
pending_encode_job_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
ref_count: u32 = 1,
|
||||
write_failure: ?JSC.DeferredError = null,
|
||||
poll_ref: bun.Async.KeepAlive = .{},
|
||||
closed: bool = false,
|
||||
|
||||
pub fn hasPendingActivity(this: *BrotliEncoder) bool {
|
||||
return this.has_pending_activity.load(.monotonic) > 0;
|
||||
}
|
||||
|
||||
pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*BrotliEncoder {
|
||||
globalThis.throw("BrotliEncoder is not constructable", .{});
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(4).slice();
|
||||
|
||||
if (arguments.len < 4) {
|
||||
globalThis.throwNotEnoughArguments("BrotliEncoder", 4, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const opts = arguments[0];
|
||||
const callback = arguments[2];
|
||||
const mode = arguments[3].to(u8);
|
||||
|
||||
const chunkSize = globalThis.getInteger(opts, u32, 1024 * 48, .{ .min = 64, .field_name = "chunkSize" }) orelse return .zero;
|
||||
const maxOutputLength = globalThis.getInteger(opts, usize, 0, .{ .max = std.math.maxInt(u52), .field_name = "maxOutputLength" }) orelse return .zero;
|
||||
const flush = globalThis.getInteger(opts, u8, 0, .{ .max = 3, .field_name = "flush" }) orelse return .zero;
|
||||
const finishFlush = globalThis.getInteger(opts, u8, 2, .{ .max = 3, .field_name = "finishFlush" }) orelse return .zero;
|
||||
const fullFlush = globalThis.getInteger(opts, u8, 1, .{ .max = 3, .field_name = "fullFlush" }) orelse return .zero;
|
||||
|
||||
var this: *BrotliEncoder = BrotliEncoder.new(.{
|
||||
.globalThis = globalThis,
|
||||
.stream = brotli.BrotliCompressionStream.init(@enumFromInt(flush), @enumFromInt(finishFlush), @enumFromInt(fullFlush)) catch {
|
||||
globalThis.throw("Failed to create BrotliEncoder", .{});
|
||||
return .zero;
|
||||
},
|
||||
.chunkSize = chunkSize,
|
||||
.maxOutputLength = maxOutputLength,
|
||||
.mode = mode,
|
||||
});
|
||||
|
||||
if (opts.get(globalThis, "params")) |params| {
|
||||
inline for (std.meta.fields(bun.brotli.c.BrotliEncoderParameter)) |f| {
|
||||
if (!params.isObject()) break;
|
||||
if (params.hasOwnPropertyValue(globalThis, JSC.ZigString.static(std.fmt.comptimePrint("{d}", .{f.value})).toJS(globalThis))) {
|
||||
const idx = params.getIndex(globalThis, f.value);
|
||||
if (!idx.isNumber()) {
|
||||
globalThis.throwValue(globalThis.ERR_INVALID_ARG_TYPE_static(
|
||||
JSC.ZigString.static("options.params[key]"),
|
||||
JSC.ZigString.static("number"),
|
||||
idx,
|
||||
));
|
||||
this.deinit();
|
||||
return .zero;
|
||||
}
|
||||
const was_set = this.stream.brotli.setParameter(@enumFromInt(f.value), idx.toU32());
|
||||
if (!was_set) {
|
||||
globalThis.ERR_ZLIB_INITIALIZATION_FAILED("Initialization failed", .{}).throw();
|
||||
this.deinit();
|
||||
return .zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (globalThis.hasException()) return .zero;
|
||||
|
||||
const out = this.toJS(globalThis);
|
||||
this.callback_value.set(globalThis, callback);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
pub fn finalize(this: *BrotliEncoder) void {
|
||||
this.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit(this: *BrotliEncoder) void {
|
||||
this.callback_value.deinit();
|
||||
this.freelist.deinit();
|
||||
this.output.deinit(bun.default_allocator);
|
||||
this.stream.deinit();
|
||||
this.input.deinit();
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
fn drainFreelist(this: *BrotliEncoder) void {
|
||||
this.freelist.drain();
|
||||
}
|
||||
|
||||
fn collectOutputValue(this: *BrotliEncoder) JSC.JSValue {
|
||||
this.output_lock.lock();
|
||||
defer this.output_lock.unlock();
|
||||
|
||||
defer this.output.clearRetainingCapacity();
|
||||
return JSC.ArrayBuffer.createBuffer(this.globalThis, this.output.items);
|
||||
}
|
||||
|
||||
pub fn runFromJSThread(this: *BrotliEncoder) void {
|
||||
this.poll_ref.unref(this.globalThis.bunVM());
|
||||
|
||||
defer _ = this.has_pending_activity.fetchSub(1, .monotonic);
|
||||
this.drainFreelist();
|
||||
|
||||
_ = this.callback_value.get().?.call(
|
||||
this.globalThis,
|
||||
.undefined,
|
||||
if (this.write_failure != null)
|
||||
&.{this.write_failure.?.toError(this.globalThis)}
|
||||
else
|
||||
&.{ .null, this.collectOutputValue() },
|
||||
) catch |err| this.globalThis.reportActiveExceptionAsUnhandled(err);
|
||||
}
|
||||
|
||||
// We can only run one encode job at a time
|
||||
// But we don't have an idea of a serial dispatch queue
|
||||
// So instead, we let you enqueue as many times as you want
|
||||
// and if one is already running, we just don't do anything
|
||||
const EncodeJob = struct {
|
||||
task: JSC.WorkPoolTask = .{ .callback = &runTask },
|
||||
encoder: *BrotliEncoder,
|
||||
is_async: bool,
|
||||
vm: *JSC.VirtualMachine,
|
||||
|
||||
pub usingnamespace bun.New(@This());
|
||||
|
||||
pub fn runTask(this: *JSC.WorkPoolTask) void {
|
||||
var job: *EncodeJob = @fieldParentPtr("task", this);
|
||||
job.run();
|
||||
job.destroy();
|
||||
}
|
||||
|
||||
pub fn run(this: *EncodeJob) void {
|
||||
defer {
|
||||
_ = this.encoder.has_pending_activity.fetchSub(1, .monotonic);
|
||||
}
|
||||
|
||||
var any = false;
|
||||
|
||||
if (this.encoder.pending_encode_job_count.fetchAdd(1, .monotonic) >= 0) {
|
||||
const is_last = this.encoder.has_called_end;
|
||||
while (true) {
|
||||
this.encoder.input_lock.lock();
|
||||
defer this.encoder.input_lock.unlock();
|
||||
const readable = this.encoder.input.readableSlice(0);
|
||||
defer this.encoder.input.discard(readable.len);
|
||||
const pending = readable;
|
||||
|
||||
const Writer = struct {
|
||||
encoder: *BrotliEncoder,
|
||||
|
||||
pub const Error = error{OutOfMemory};
|
||||
pub fn writeAll(writer: @This(), chunk: []const u8) Error!void {
|
||||
writer.encoder.output_lock.lock();
|
||||
defer writer.encoder.output_lock.unlock();
|
||||
|
||||
try writer.encoder.output.appendSlice(bun.default_allocator, chunk);
|
||||
}
|
||||
};
|
||||
|
||||
defer {
|
||||
this.encoder.freelist.append(pending);
|
||||
}
|
||||
for (pending) |*input| {
|
||||
var writer = this.encoder.stream.writer(Writer{ .encoder = this.encoder });
|
||||
writer.writeAll(input.slice()) catch {
|
||||
_ = this.encoder.pending_encode_job_count.fetchSub(1, .monotonic);
|
||||
if (!this.is_async) {
|
||||
this.encoder.closed = true;
|
||||
this.encoder.globalThis.throw("BrotliError", .{});
|
||||
return;
|
||||
}
|
||||
this.encoder.write_failure = JSC.DeferredError.from(.plainerror, .ERR_OPERATION_FAILED, "BrotliError", .{}); // TODO propogate better error
|
||||
return;
|
||||
};
|
||||
if (this.encoder.output.items.len > this.encoder.maxOutputLength) {
|
||||
_ = this.encoder.pending_encode_job_count.fetchSub(1, .monotonic);
|
||||
this.encoder.write_failure = JSC.DeferredError.from(.rangeerror, .ERR_BUFFER_TOO_LARGE, "Cannot create a Buffer larger than {d} bytes", .{this.encoder.maxOutputLength});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
any = any or pending.len > 0;
|
||||
|
||||
if (this.encoder.pending_encode_job_count.fetchSub(1, .monotonic) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_last and any) {
|
||||
var output = &this.encoder.output;
|
||||
this.encoder.output_lock.lock();
|
||||
defer this.encoder.output_lock.unlock();
|
||||
|
||||
output.appendSlice(bun.default_allocator, this.encoder.stream.end() catch {
|
||||
_ = this.encoder.pending_encode_job_count.fetchSub(1, .monotonic);
|
||||
this.encoder.write_failure = JSC.DeferredError.from(.plainerror, .ERR_OPERATION_FAILED, "BrotliError", .{}); // TODO propogate better error
|
||||
return;
|
||||
}) catch {
|
||||
_ = this.encoder.pending_encode_job_count.fetchSub(1, .monotonic);
|
||||
this.encoder.write_failure = JSC.DeferredError.from(.plainerror, .ERR_OPERATION_FAILED, "BrotliError", .{}); // TODO propogate better error
|
||||
return;
|
||||
};
|
||||
if (output.items.len > this.encoder.maxOutputLength) {
|
||||
_ = this.encoder.pending_encode_job_count.fetchSub(1, .monotonic);
|
||||
this.encoder.write_failure = JSC.DeferredError.from(.rangeerror, .ERR_BUFFER_TOO_LARGE, "Cannot create a Buffer larger than {d} bytes", .{this.encoder.maxOutputLength});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.is_async and any) {
|
||||
_ = this.encoder.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
this.vm.enqueueTaskConcurrent(JSC.ConcurrentTask.create(JSC.Task.init(this.encoder)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn transform(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(3);
|
||||
|
||||
if (arguments.len < 3) {
|
||||
globalThis.throwNotEnoughArguments("BrotliEncoder.encode", 3, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (this.has_called_end) {
|
||||
globalThis.throw("BrotliEncoder.encode called after BrotliEncoder.end", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const input = callframe.argument(0);
|
||||
const optional_encoding = callframe.argument(1);
|
||||
const is_last = callframe.argument(2).toBoolean();
|
||||
|
||||
const input_to_queue = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalThis, bun.default_allocator, input, optional_encoding, true) orelse {
|
||||
globalThis.throwInvalidArgumentType("BrotliEncoder.encode", "input", "Blob, String, or Buffer");
|
||||
return .zero;
|
||||
};
|
||||
|
||||
_ = this.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
if (is_last)
|
||||
this.has_called_end = true;
|
||||
|
||||
var task = EncodeJob.new(.{
|
||||
.encoder = this,
|
||||
.is_async = true,
|
||||
.vm = this.globalThis.bunVM(),
|
||||
});
|
||||
|
||||
{
|
||||
this.input_lock.lock();
|
||||
defer this.input_lock.unlock();
|
||||
|
||||
// need to protect because no longer on the stack. unprotected in FreeList.deinit
|
||||
input_to_queue.protect();
|
||||
this.input.writeItem(input_to_queue) catch bun.outOfMemory();
|
||||
}
|
||||
this.poll_ref.ref(task.vm);
|
||||
JSC.WorkPool.schedule(&task.task);
|
||||
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn transformSync(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(4);
|
||||
|
||||
if (arguments.len < 3) {
|
||||
globalThis.throwNotEnoughArguments("BrotliEncoder.encode", 3, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (this.has_called_end) {
|
||||
globalThis.throw("BrotliEncoder.encode called after BrotliEncoder.end", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const input = callframe.argument(0);
|
||||
const optional_encoding = callframe.argument(1);
|
||||
const is_last = callframe.argument(2).toBoolean();
|
||||
const optional_flushFlag = arguments.ptr[3];
|
||||
|
||||
const old_flushFlag = this.stream.flushOp;
|
||||
defer this.stream.flushOp = old_flushFlag;
|
||||
blk: {
|
||||
if (!optional_flushFlag.isInt32()) break :blk;
|
||||
const int = optional_flushFlag.asInt32();
|
||||
if (int < 0) break :blk;
|
||||
if (int > 3) break :blk;
|
||||
this.stream.flushOp = @enumFromInt(int);
|
||||
}
|
||||
|
||||
const input_to_queue = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalThis, bun.default_allocator, input, optional_encoding, true) orelse {
|
||||
globalThis.throwInvalidArgumentType("BrotliEncoder.encode", "input", "Blob, String, or Buffer");
|
||||
return .zero;
|
||||
};
|
||||
|
||||
_ = this.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
if (is_last)
|
||||
this.has_called_end = true;
|
||||
|
||||
var task: EncodeJob = .{
|
||||
.encoder = this,
|
||||
.is_async = false,
|
||||
.vm = this.globalThis.bunVM(),
|
||||
};
|
||||
|
||||
{
|
||||
this.input_lock.lock();
|
||||
defer this.input_lock.unlock();
|
||||
|
||||
// need to protect because no longer on the stack. unprotected in FreeList.deinit
|
||||
input_to_queue.protect();
|
||||
this.input.writeItem(input_to_queue) catch bun.outOfMemory();
|
||||
}
|
||||
task.run();
|
||||
if (!is_last and this.output.items.len == 0) {
|
||||
return JSC.Buffer.fromBytes(&.{}, bun.default_allocator, .Uint8Array).toNodeBuffer(globalThis);
|
||||
}
|
||||
if (this.write_failure != null) {
|
||||
globalThis.vm().throwError(globalThis, this.write_failure.?.toError(globalThis));
|
||||
return .zero;
|
||||
}
|
||||
return this.collectOutputValue();
|
||||
}
|
||||
|
||||
pub fn reset(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
_ = this;
|
||||
_ = globalThis;
|
||||
_ = callframe;
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn getBytesWritten(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.total_in);
|
||||
}
|
||||
|
||||
pub fn getClosed(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsBoolean(this.closed);
|
||||
}
|
||||
|
||||
pub fn close(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
||||
_ = this;
|
||||
_ = globalThis;
|
||||
_ = callframe;
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn getChunkSize(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.chunkSize);
|
||||
}
|
||||
|
||||
pub fn getFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.flushOp);
|
||||
}
|
||||
|
||||
pub fn getFinishFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.finishFlushOp);
|
||||
}
|
||||
|
||||
pub fn getFullFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.fullFlushOp);
|
||||
}
|
||||
|
||||
pub fn getMaxOutputLength(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.maxOutputLength);
|
||||
}
|
||||
};
|
||||
|
||||
pub const BrotliDecoder = struct {
|
||||
pub usingnamespace bun.New(@This());
|
||||
pub usingnamespace JSC.Codegen.JSBrotliDecoder;
|
||||
|
||||
globalThis: *JSC.JSGlobalObject,
|
||||
stream: brotli.BrotliReaderArrayList,
|
||||
chunkSize: c_uint,
|
||||
maxOutputLength: usize,
|
||||
mode: u8,
|
||||
|
||||
has_pending_activity: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
ref_count: u32 = 1,
|
||||
poll_ref: bun.Async.KeepAlive = .{},
|
||||
write_failure: ?JSC.DeferredError = null,
|
||||
callback_value: JSC.Strong = .{},
|
||||
has_called_end: bool = false,
|
||||
pending_decode_job_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
closed: bool = false,
|
||||
|
||||
input: Queue = Queue.init(bun.default_allocator),
|
||||
input_lock: bun.Lock = .{},
|
||||
|
||||
output: std.ArrayListUnmanaged(u8) = .{},
|
||||
output_lock: bun.Lock = .{},
|
||||
|
||||
freelist: FreeList = .{},
|
||||
|
||||
pub fn hasPendingActivity(this: *BrotliDecoder) bool {
|
||||
return this.has_pending_activity.load(.monotonic) > 0;
|
||||
}
|
||||
|
||||
pub fn deinit(this: *BrotliDecoder) void {
|
||||
this.callback_value.deinit();
|
||||
this.freelist.deinit();
|
||||
this.output.deinit(bun.default_allocator);
|
||||
this.stream.brotli.destroyInstance();
|
||||
this.input.deinit();
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*BrotliDecoder {
|
||||
globalThis.throw("BrotliDecoder is not constructable", .{});
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(4).slice();
|
||||
|
||||
if (arguments.len < 4) {
|
||||
globalThis.throwNotEnoughArguments("BrotliDecoder", 4, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const opts = arguments[0];
|
||||
const callback = arguments[2];
|
||||
const mode = arguments[3].to(u8);
|
||||
|
||||
const chunkSize = globalThis.getInteger(opts, u32, 1024 * 48, .{ .min = 64, .field_name = "chunkSize" }) orelse return .zero;
|
||||
const maxOutputLength = globalThis.getInteger(opts, usize, 0, .{ .max = std.math.maxInt(u52), .field_name = "maxOutputLength" }) orelse return .zero;
|
||||
const flush = globalThis.getInteger(opts, u8, 0, .{ .max = 6, .field_name = "flush" }) orelse return .zero;
|
||||
const finishFlush = globalThis.getInteger(opts, u8, 2, .{ .max = 6, .field_name = "finishFlush" }) orelse return .zero;
|
||||
const fullFlush = globalThis.getInteger(opts, u8, 1, .{ .max = 6, .field_name = "fullFlush" }) orelse return .zero;
|
||||
|
||||
var this: *BrotliDecoder = BrotliDecoder.new(.{
|
||||
.globalThis = globalThis,
|
||||
.stream = undefined, // &this.output needs to be a stable pointer
|
||||
.chunkSize = chunkSize,
|
||||
.maxOutputLength = maxOutputLength,
|
||||
.mode = mode,
|
||||
});
|
||||
this.stream = brotli.BrotliReaderArrayList.initWithOptions("", &this.output, bun.default_allocator, .{}, @enumFromInt(flush), @enumFromInt(finishFlush), @enumFromInt(fullFlush)) catch {
|
||||
globalThis.throw("Failed to create BrotliDecoder", .{});
|
||||
return .zero;
|
||||
};
|
||||
|
||||
if (opts.get(globalThis, "params")) |params| {
|
||||
inline for (std.meta.fields(bun.brotli.c.BrotliDecoderParameter)) |f| {
|
||||
if (!params.isObject()) break;
|
||||
const idx = params.getIndex(globalThis, f.value);
|
||||
if (!idx.isNumber()) break;
|
||||
const was_set = this.stream.brotli.setParameter(@enumFromInt(f.value), idx.toU32());
|
||||
if (!was_set) {
|
||||
globalThis.ERR_ZLIB_INITIALIZATION_FAILED("Initialization failed", .{}).throw();
|
||||
this.deinit();
|
||||
return .zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (globalThis.hasException()) return .zero;
|
||||
|
||||
const out = this.toJS(globalThis);
|
||||
this.callback_value.set(globalThis, callback);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
pub fn finalize(this: *BrotliDecoder) void {
|
||||
this.deinit();
|
||||
}
|
||||
|
||||
fn collectOutputValue(this: *BrotliDecoder) JSC.JSValue {
|
||||
this.output_lock.lock();
|
||||
defer this.output_lock.unlock();
|
||||
|
||||
defer this.output.clearRetainingCapacity();
|
||||
return JSC.ArrayBuffer.createBuffer(this.globalThis, this.output.items);
|
||||
}
|
||||
|
||||
pub fn runFromJSThread(this: *BrotliDecoder) void {
|
||||
this.poll_ref.unref(this.globalThis.bunVM());
|
||||
|
||||
defer _ = this.has_pending_activity.fetchSub(1, .monotonic);
|
||||
this.drainFreelist();
|
||||
|
||||
_ = this.callback_value.get().?.call(
|
||||
this.globalThis,
|
||||
.undefined,
|
||||
if (this.write_failure != null)
|
||||
&.{this.write_failure.?.toError(this.globalThis)}
|
||||
else
|
||||
&.{ .null, this.collectOutputValue() },
|
||||
) catch |err| this.globalThis.reportActiveExceptionAsUnhandled(err);
|
||||
}
|
||||
|
||||
fn drainFreelist(this: *BrotliDecoder) void {
|
||||
this.freelist.drain();
|
||||
}
|
||||
|
||||
pub fn transform(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(3);
|
||||
|
||||
if (arguments.len < 3) {
|
||||
globalThis.throwNotEnoughArguments("BrotliEncoder.decode", 3, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (this.has_called_end) {
|
||||
globalThis.throw("BrotliEncoder.decode called after BrotliEncoder.end", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const input = callframe.argument(0);
|
||||
const optional_encoding = callframe.argument(1);
|
||||
const is_last = callframe.argument(2).toBoolean();
|
||||
|
||||
const input_to_queue = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalThis, bun.default_allocator, input, optional_encoding, true) orelse {
|
||||
globalThis.throwInvalidArgumentType("BrotliEncoder.decode", "input", "Blob, String, or Buffer");
|
||||
return .zero;
|
||||
};
|
||||
|
||||
_ = this.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
if (is_last)
|
||||
this.has_called_end = true;
|
||||
|
||||
var task = DecodeJob.new(.{
|
||||
.decoder = this,
|
||||
.is_async = true,
|
||||
.vm = this.globalThis.bunVM(),
|
||||
});
|
||||
|
||||
{
|
||||
this.input_lock.lock();
|
||||
defer this.input_lock.unlock();
|
||||
|
||||
// need to protect because no longer on the stack. unprotected in FreeList.deinit
|
||||
input_to_queue.protect();
|
||||
this.input.writeItem(input_to_queue) catch bun.outOfMemory();
|
||||
}
|
||||
this.poll_ref.ref(task.vm);
|
||||
JSC.WorkPool.schedule(&task.task);
|
||||
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn transformSync(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
const arguments = callframe.arguments(4);
|
||||
|
||||
if (arguments.len < 3) {
|
||||
globalThis.throwNotEnoughArguments("BrotliEncoder.decode", 3, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (this.has_called_end) {
|
||||
globalThis.throw("BrotliEncoder.decode called after BrotliEncoder.end", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const input = callframe.argument(0);
|
||||
const optional_encoding = callframe.argument(1);
|
||||
const is_last = callframe.argument(2).toBoolean();
|
||||
// const optional_flushFlag = arguments.ptr[3];
|
||||
|
||||
// const old_flushFlag = this.stream.flushOp;
|
||||
// defer this.stream.flushOp = old_flushFlag;
|
||||
// blk: {
|
||||
// if (!optional_flushFlag.isInt32()) break :blk;
|
||||
// const int = optional_flushFlag.asInt32();
|
||||
// if (int < 0) break :blk;
|
||||
// if (int > 3) break :blk;
|
||||
// this.stream.flushOp = @enumFromInt(int);
|
||||
// }
|
||||
|
||||
const input_to_queue = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalThis, bun.default_allocator, input, optional_encoding, true) orelse {
|
||||
globalThis.throwInvalidArgumentType("BrotliEncoder.decode", "input", "Blob, String, or Buffer");
|
||||
return .zero;
|
||||
};
|
||||
|
||||
_ = this.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
if (is_last)
|
||||
this.has_called_end = true;
|
||||
|
||||
var task: DecodeJob = .{
|
||||
.decoder = this,
|
||||
.is_async = false,
|
||||
.vm = this.globalThis.bunVM(),
|
||||
};
|
||||
|
||||
{
|
||||
this.input_lock.lock();
|
||||
defer this.input_lock.unlock();
|
||||
|
||||
// need to protect because no longer on the stack. unprotected in FreeList.deinit
|
||||
input_to_queue.protect();
|
||||
this.input.writeItem(input_to_queue) catch bun.outOfMemory();
|
||||
}
|
||||
task.run();
|
||||
if (!is_last and this.output.items.len == 0) {
|
||||
return JSC.Buffer.fromBytes(&.{}, bun.default_allocator, .Uint8Array).toNodeBuffer(globalThis);
|
||||
}
|
||||
if (this.write_failure != null) {
|
||||
globalThis.throwValue(this.write_failure.?.toError(globalThis));
|
||||
return .zero;
|
||||
}
|
||||
return this.collectOutputValue();
|
||||
}
|
||||
|
||||
// We can only run one decode job at a time
|
||||
// But we don't have an idea of a serial dispatch queue
|
||||
// So instead, we let you enqueue as many times as you want
|
||||
// and if one is already running, we just don't do anything
|
||||
const DecodeJob = struct {
|
||||
task: JSC.WorkPoolTask = .{ .callback = &runTask },
|
||||
decoder: *BrotliDecoder,
|
||||
is_async: bool,
|
||||
vm: *JSC.VirtualMachine,
|
||||
|
||||
pub usingnamespace bun.New(@This());
|
||||
|
||||
pub fn runTask(this: *JSC.WorkPoolTask) void {
|
||||
var job: *DecodeJob = @fieldParentPtr("task", this);
|
||||
job.run();
|
||||
job.destroy();
|
||||
}
|
||||
|
||||
pub fn run(this: *DecodeJob) void {
|
||||
defer {
|
||||
_ = this.decoder.has_pending_activity.fetchSub(1, .monotonic);
|
||||
}
|
||||
|
||||
var any = false;
|
||||
|
||||
if (this.decoder.pending_decode_job_count.fetchAdd(1, .monotonic) >= 0) {
|
||||
const is_last = this.decoder.has_called_end;
|
||||
while (true) {
|
||||
this.decoder.input_lock.lock();
|
||||
defer this.decoder.input_lock.unlock();
|
||||
if (!is_last) break;
|
||||
const pending = this.decoder.input.readableSlice(0);
|
||||
|
||||
defer {
|
||||
this.decoder.freelist.append(pending);
|
||||
}
|
||||
|
||||
var input_list = std.ArrayListUnmanaged(u8){};
|
||||
defer input_list.deinit(bun.default_allocator);
|
||||
|
||||
if (pending.len > 1) {
|
||||
var count: usize = 0;
|
||||
for (pending) |input| {
|
||||
count += input.slice().len;
|
||||
}
|
||||
|
||||
input_list.ensureTotalCapacityPrecise(bun.default_allocator, count) catch bun.outOfMemory();
|
||||
|
||||
for (pending) |*input| {
|
||||
input_list.appendSliceAssumeCapacity(input.slice());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
this.decoder.output_lock.lock();
|
||||
defer this.decoder.output_lock.unlock();
|
||||
|
||||
const input = if (pending.len <= 1) pending[0].slice() else input_list.items;
|
||||
this.decoder.stream.input = input;
|
||||
this.decoder.stream.readAll(false) catch {
|
||||
any = true;
|
||||
_ = this.decoder.pending_decode_job_count.fetchSub(1, .monotonic);
|
||||
if (!this.is_async) {
|
||||
this.decoder.closed = true;
|
||||
this.decoder.globalThis.throw("BrotliError", .{});
|
||||
return;
|
||||
}
|
||||
this.decoder.write_failure = JSC.DeferredError.from(.plainerror, .ERR_OPERATION_FAILED, "BrotliError", .{}); // TODO propogate better error
|
||||
break;
|
||||
};
|
||||
if (this.decoder.output.items.len > this.decoder.maxOutputLength) {
|
||||
any = true;
|
||||
_ = this.decoder.pending_decode_job_count.fetchSub(1, .monotonic);
|
||||
this.decoder.write_failure = JSC.DeferredError.from(.rangeerror, .ERR_BUFFER_TOO_LARGE, "Cannot create a Buffer larger than {d} bytes", .{this.decoder.maxOutputLength});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
any = any or pending.len > 0;
|
||||
|
||||
if (this.decoder.pending_decode_job_count.fetchSub(1, .monotonic) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.is_async and any) {
|
||||
_ = this.decoder.has_pending_activity.fetchAdd(1, .monotonic);
|
||||
this.vm.enqueueTaskConcurrent(JSC.ConcurrentTask.create(JSC.Task.init(this.decoder)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn reset(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
||||
_ = this;
|
||||
_ = globalThis;
|
||||
_ = callframe;
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn getBytesWritten(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.total_in);
|
||||
}
|
||||
|
||||
pub fn getClosed(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsBoolean(this.closed);
|
||||
}
|
||||
|
||||
pub fn close(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
||||
_ = this;
|
||||
_ = globalThis;
|
||||
_ = callframe;
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
pub fn getChunkSize(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.chunkSize);
|
||||
}
|
||||
|
||||
pub fn getFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.flushOp);
|
||||
}
|
||||
|
||||
pub fn getFinishFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.finishFlushOp);
|
||||
}
|
||||
|
||||
pub fn getFullFlush(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.stream.fullFlushOp);
|
||||
}
|
||||
|
||||
pub fn getMaxOutputLength(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
_ = globalObject;
|
||||
return JSC.JSValue.jsNumber(this.maxOutputLength);
|
||||
}
|
||||
};
|
||||
1014
src/bun.js/api/js_zlib.zig
Normal file
1014
src/bun.js/api/js_zlib.zig
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user