mirror of
https://github.com/oven-sh/bun
synced 2026-02-04 07:58:54 +00:00
Compare commits
1 Commits
build-scri
...
dylan/move
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c47a8e45b |
50
.github/workflows/build-darwin.yml
vendored
50
.github/workflows/build-darwin.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
inputs:
|
||||
runs-on:
|
||||
type: string
|
||||
default: macos-13-large
|
||||
default: macos-12-large
|
||||
tag:
|
||||
type: string
|
||||
required: true
|
||||
@@ -27,12 +27,10 @@ on:
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
LLVM_VERSION: 18
|
||||
LLVM_VERSION: 16
|
||||
BUN_VERSION: 1.1.8
|
||||
LC_CTYPE: "en_US.UTF-8"
|
||||
LC_ALL: "en_US.UTF-8"
|
||||
# LTO is disabled because we cannot use lld on macOS currently
|
||||
BUN_ENABLE_LTO: "0"
|
||||
|
||||
jobs:
|
||||
build-submodules:
|
||||
@@ -55,7 +53,16 @@ jobs:
|
||||
cat $(echo scripts/build*.sh scripts/all-dependencies.sh | tr " " "\n" | sort)
|
||||
}
|
||||
echo "hash=$(print_versions | shasum)" >> $GITHUB_OUTPUT
|
||||
- name: Install Dependencies
|
||||
- if: ${{ !inputs.no-cache }}
|
||||
name: Restore Cache
|
||||
id: cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/bun-deps
|
||||
key: bun-${{ inputs.tag }}-deps-${{ steps.hash.outputs.hash }}
|
||||
# TODO: Figure out how to cache homebrew dependencies
|
||||
- if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
name: Install Dependencies
|
||||
env:
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
@@ -79,16 +86,24 @@ jobs:
|
||||
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
|
||||
brew link --overwrite llvm@$LLVM_VERSION
|
||||
- name: Clone Submodules
|
||||
- if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
name: Clone Submodules
|
||||
run: |
|
||||
./scripts/update-submodules.sh
|
||||
- name: Build Submodules
|
||||
if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
env:
|
||||
CPU_TARGET: ${{ inputs.cpu }}
|
||||
BUN_DEPS_OUT_DIR: ${{ runner.temp }}/bun-deps
|
||||
run: |
|
||||
mkdir -p $BUN_DEPS_OUT_DIR
|
||||
./scripts/all-dependencies.sh
|
||||
- name: Save Cache
|
||||
if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/bun-deps
|
||||
key: ${{ steps.cache.outputs.cache-primary-key }}
|
||||
- name: Upload bun-${{ inputs.tag }}-deps
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -132,6 +147,14 @@ jobs:
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- if: ${{ !inputs.no-cache }}
|
||||
name: Restore Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/ccache
|
||||
key: bun-${{ inputs.tag }}-cpp-${{ hashFiles('Dockerfile', 'Makefile', 'CMakeLists.txt', 'build.zig', 'scripts/**', 'src/**', 'packages/bun-usockets/src/**', 'packages/bun-uws/src/**') }}
|
||||
restore-keys: |
|
||||
bun-${{ inputs.tag }}-cpp-
|
||||
- name: Compile
|
||||
env:
|
||||
CPU_TARGET: ${{ inputs.cpu }}
|
||||
@@ -221,9 +244,18 @@ jobs:
|
||||
with:
|
||||
name: bun-${{ inputs.tag }}-zig
|
||||
path: ${{ runner.temp }}/release
|
||||
- if: ${{ !inputs.no-cache }}
|
||||
name: Restore Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/ccache
|
||||
key: bun-${{ inputs.tag }}-cpp-${{ hashFiles('Dockerfile', 'Makefile', 'CMakeLists.txt', 'build.zig', 'scripts/**', 'src/**', 'packages/bun-usockets/src/**', 'packages/bun-uws/src/**') }}
|
||||
restore-keys: |
|
||||
bun-${{ inputs.tag }}-cpp-
|
||||
- name: Link
|
||||
env:
|
||||
CPU_TARGET: ${{ inputs.cpu }}
|
||||
CCACHE_DIR: ${{ runner.temp }}/ccache
|
||||
run: |
|
||||
SRC_DIR=$PWD
|
||||
mkdir ${{ runner.temp }}/link-build
|
||||
@@ -244,12 +276,6 @@ jobs:
|
||||
chmod +x bun-profile bun
|
||||
mkdir -p bun-${{ inputs.tag }}-profile/ bun-${{ inputs.tag }}/
|
||||
mv bun-profile bun-${{ inputs.tag }}-profile/bun-profile
|
||||
if [ -f bun-profile.dSYM || -d bun-profile.dSYM ]; then
|
||||
mv bun-profile.dSYM bun-${{ inputs.tag }}-profile/bun-profile.dSYM
|
||||
fi
|
||||
if [ -f bun.dSYM || -d bun.dSYM ]; then
|
||||
mv bun.dSYM bun-${{ inputs.tag }}-profile/bun-profile.dSYM
|
||||
fi
|
||||
mv bun bun-${{ inputs.tag }}/bun
|
||||
zip -r bun-${{ inputs.tag }}-profile.zip bun-${{ inputs.tag }}-profile
|
||||
zip -r bun-${{ inputs.tag }}.zip bun-${{ inputs.tag }}
|
||||
|
||||
56
.github/workflows/build-windows.yml
vendored
56
.github/workflows/build-windows.yml
vendored
@@ -31,23 +31,19 @@ on:
|
||||
|
||||
env:
|
||||
# Must specify exact version of LLVM for Windows
|
||||
LLVM_VERSION: 18.1.8
|
||||
LLVM_VERSION: 16.0.6
|
||||
BUN_VERSION: ${{ inputs.bun-version }}
|
||||
BUN_GARBAGE_COLLECTOR_LEVEL: 1
|
||||
BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING: 1
|
||||
CI: true
|
||||
USE_LTO: 1
|
||||
|
||||
jobs:
|
||||
build-submodules:
|
||||
name: Build Submodules
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: Install Scoop
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
|
||||
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
|
||||
- name: Install VS2022 BuildTools 17.9.7
|
||||
run: choco install -y visualstudio2022buildtools --version=117.9.7.0 --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --installChannelUri https://aka.ms/vs/17/release/180911598_-255012421/channel"
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
@@ -78,11 +74,14 @@ jobs:
|
||||
path: bun-deps
|
||||
key: bun-${{ inputs.tag }}-deps-${{ steps.hash.outputs.hash }}
|
||||
- if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
name: Install LLVM and Ninja
|
||||
name: Install LLVM
|
||||
uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b
|
||||
with:
|
||||
version: ${{ env.LLVM_VERSION }}
|
||||
- if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
name: Install Ninja
|
||||
run: |
|
||||
scoop install ninja
|
||||
scoop install llvm@${{ env.LLVM_VERSION }}
|
||||
scoop install nasm@2.16.01
|
||||
choco install -y ninja
|
||||
- if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }}
|
||||
name: Clone Submodules
|
||||
run: |
|
||||
@@ -92,9 +91,9 @@ jobs:
|
||||
env:
|
||||
CPU_TARGET: ${{ inputs.cpu }}
|
||||
CCACHE_DIR: ccache
|
||||
USE_LTO: 1
|
||||
run: |
|
||||
.\scripts\env.ps1 ${{ contains(inputs.tag, '-baseline') && '-Baseline' || '' }}
|
||||
choco install -y nasm --version=2.16.01
|
||||
$env:BUN_DEPS_OUT_DIR = (mkdir -Force "./bun-deps")
|
||||
.\scripts\all-dependencies.ps1
|
||||
- name: Save Cache
|
||||
@@ -142,11 +141,8 @@ jobs:
|
||||
needs: codegen
|
||||
runs-on: ${{ inputs.runs-on }}
|
||||
steps:
|
||||
- name: Install Scoop
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
|
||||
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
|
||||
- name: Install VS2022 BuildTools 17.9.7
|
||||
run: choco install -y visualstudio2022buildtools --version=117.9.7.0 --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --installChannelUri https://aka.ms/vs/17/release/180911598_-255012421/channel"
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
@@ -155,10 +151,13 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install LLVM and Ninja
|
||||
- name: Install LLVM
|
||||
uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b
|
||||
with:
|
||||
version: ${{ env.LLVM_VERSION }}
|
||||
- name: Install Ninja
|
||||
run: |
|
||||
scoop install ninja
|
||||
scoop install llvm@${{ env.LLVM_VERSION }}
|
||||
choco install -y ninja
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
@@ -180,7 +179,6 @@ jobs:
|
||||
env:
|
||||
CPU_TARGET: ${{ inputs.cpu }}
|
||||
CCACHE_DIR: ccache
|
||||
USE_LTO: 1
|
||||
run: |
|
||||
# $CANARY_REVISION = if (Test-Path build/.canary_revision) { Get-Content build/.canary_revision } else { "0" }
|
||||
$CANARY_REVISION = 0
|
||||
@@ -190,7 +188,6 @@ jobs:
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release `
|
||||
-DNO_CODEGEN=1 `
|
||||
-DUSE_LTO=1 `
|
||||
-DNO_CONFIGURE_DEPENDS=1 `
|
||||
"-DCANARY=${CANARY_REVISION}" `
|
||||
-DBUN_CPP_ONLY=1 ${{ contains(inputs.tag, '-baseline') && '-DUSE_BASELINE_BUILD=1' || '' }}
|
||||
@@ -225,11 +222,8 @@ jobs:
|
||||
- build-zig
|
||||
- codegen
|
||||
steps:
|
||||
- name: Install Scoop
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
|
||||
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
|
||||
- name: Install VS2022 BuildTools 17.9.7
|
||||
run: choco install -y visualstudio2022buildtools --version=117.9.7.0 --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --installChannelUri https://aka.ms/vs/17/release/180911598_-255012421/channel"
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
@@ -238,10 +232,13 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install LLVM
|
||||
uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b
|
||||
with:
|
||||
version: ${{ env.LLVM_VERSION }}
|
||||
- name: Install Ninja
|
||||
run: |
|
||||
scoop install ninja
|
||||
scoop install llvm@${{ env.LLVM_VERSION }}
|
||||
choco install -y ninja
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
@@ -289,7 +286,6 @@ jobs:
|
||||
-DNO_CONFIGURE_DEPENDS=1 `
|
||||
"-DCANARY=${CANARY_REVISION}" `
|
||||
-DBUN_LINK_ONLY=1 `
|
||||
-DUSE_LTO=1 `
|
||||
"-DBUN_DEPS_OUT_DIR=$(Resolve-Path ../bun-deps)" `
|
||||
"-DBUN_CPP_ARCHIVE=$(Resolve-Path ../bun-cpp/bun-cpp-objects.a)" `
|
||||
"-DBUN_ZIG_OBJ_DIR=$(Resolve-Path ../bun-zig)" `
|
||||
|
||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -84,7 +84,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64
|
||||
arch: x64
|
||||
cpu: haswell
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64-baseline
|
||||
arch: x64
|
||||
cpu: nehalem
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-12' }}
|
||||
tag: darwin-aarch64
|
||||
arch: aarch64
|
||||
cpu: native
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
with:
|
||||
run-id: ${{ inputs.run-id }}
|
||||
pr-number: ${{ github.event.number }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64
|
||||
darwin-x64-baseline-test:
|
||||
if: ${{ inputs.run-id || github.event_name == 'pull_request' }}
|
||||
@@ -186,7 +186,7 @@ jobs:
|
||||
with:
|
||||
run-id: ${{ inputs.run-id }}
|
||||
pr-number: ${{ github.event.number }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64-baseline
|
||||
darwin-aarch64-test:
|
||||
if: ${{ inputs.run-id || github.event_name == 'pull_request' }}
|
||||
@@ -197,7 +197,7 @@ jobs:
|
||||
with:
|
||||
run-id: ${{ inputs.run-id }}
|
||||
pr-number: ${{ github.event.number }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-12' }}
|
||||
tag: darwin-aarch64
|
||||
windows-x64-test:
|
||||
if: ${{ inputs.run-id || github.event_name == 'pull_request' }}
|
||||
|
||||
6
.github/workflows/create-release-build.yml
vendored
6
.github/workflows/create-release-build.yml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64
|
||||
arch: x64
|
||||
cpu: haswell
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }}
|
||||
tag: darwin-x64-baseline
|
||||
arch: x64
|
||||
cpu: nehalem
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
uses: ./.github/workflows/build-darwin.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'namespace-profile-bun-ci-darwin-aarch64' || 'macos-12' }}
|
||||
tag: darwin-aarch64
|
||||
arch: aarch64
|
||||
cpu: native
|
||||
|
||||
89
.github/workflows/on-submodule-update.yml
vendored
89
.github/workflows/on-submodule-update.yml
vendored
@@ -1,89 +0,0 @@
|
||||
name: Comment on updated submodule
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- "src/generated_versions_list.zig"
|
||||
- ".github/workflows/on-submodule-update.yml"
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
name: Comment
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository_owner == 'oven-sh' }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout current
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
src
|
||||
- name: Hash generated versions list
|
||||
id: hash
|
||||
run: |
|
||||
echo "hash=$(sha256sum src/generated_versions_list.zig | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
sparse-checkout: |
|
||||
src
|
||||
- name: Hash base
|
||||
id: base
|
||||
run: |
|
||||
echo "base=$(sha256sum src/generated_versions_list.zig | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
|
||||
- name: Compare
|
||||
id: compare
|
||||
run: |
|
||||
if [ "${{ steps.hash.outputs.hash }}" != "${{ steps.base.outputs.base }}" ]; then
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Find Comment
|
||||
id: comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: github-actions[bot]
|
||||
body-includes: <!-- generated-comment submodule-updated -->
|
||||
- name: Write Warning Comment
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
if: steps.compare.outputs.changed == 'true'
|
||||
with:
|
||||
comment-id: ${{ steps.comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
edit-mode: replace
|
||||
body: |
|
||||
⚠️ **Warning:** @${{ github.actor }}, this PR has changes to submodule versions.
|
||||
|
||||
If this change was intentional, please ignore this message. If not, please undo changes to submodules and rebase your branch.
|
||||
|
||||
<!-- generated-comment submodule-updated -->
|
||||
- name: Add labels
|
||||
uses: actions-cool/issues-helper@v3
|
||||
if: steps.compare.outputs.changed == 'true'
|
||||
with:
|
||||
actions: "add-labels"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
labels: "changed-submodules"
|
||||
- name: Remove labels
|
||||
uses: actions-cool/issues-helper@v3
|
||||
if: steps.compare.outputs.changed == 'false'
|
||||
with:
|
||||
actions: "remove-labels"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
labels: "changed-submodules"
|
||||
- name: Delete outdated comment
|
||||
uses: actions-cool/issues-helper@v3
|
||||
if: steps.compare.outputs.changed == 'false' && steps.comment.outputs.comment-id != ''
|
||||
with:
|
||||
actions: "delete-comment"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.comment.outputs.comment-id }}
|
||||
26
.github/workflows/release.yml
vendored
26
.github/workflows/release.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.20"
|
||||
bun-version: "1.0.21"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Sign Release
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.20"
|
||||
bun-version: "1.0.21"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
if: ${{ env.BUN_VERSION != 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.20"
|
||||
bun-version: "1.0.21"
|
||||
- name: Setup Bun
|
||||
if: ${{ env.BUN_VERSION == 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
@@ -259,7 +259,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.20"
|
||||
bun-version: "1.0.21"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -270,24 +270,6 @@ jobs:
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
|
||||
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
|
||||
AWS_BUCKET: bun
|
||||
|
||||
notify-sentry:
|
||||
name: Notify Sentry
|
||||
runs-on: ubuntu-latest
|
||||
needs: s3
|
||||
steps:
|
||||
- name: Notify Sentry
|
||||
uses: getsentry/action-release@v1.7.0
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
with:
|
||||
ignore_missing: true
|
||||
ignore_empty: true
|
||||
version: ${{ env.BUN_VERSION }}
|
||||
environment: production
|
||||
|
||||
bump:
|
||||
name: "Bump version"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
2
.github/workflows/run-format.yml
vendored
2
.github/workflows/run-format.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.20"
|
||||
bun-version: "1.1.8"
|
||||
- name: Setup Zig
|
||||
uses: goto-bus-stop/setup-zig@c7b6cdd3adba8f8b96984640ff172c37c93f73ee
|
||||
with:
|
||||
|
||||
2
.github/workflows/run-lint-cpp.yml
vendored
2
.github/workflows/run-lint-cpp.yml
vendored
@@ -17,7 +17,7 @@ on:
|
||||
jobs:
|
||||
lint-cpp:
|
||||
name: Lint C++
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-xlarge' || 'macos-13' }}
|
||||
runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-xlarge' || 'macos-12' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
12
.github/workflows/upload.yml
vendored
12
.github/workflows/upload.yml
vendored
@@ -80,15 +80,3 @@ jobs:
|
||||
bun upgrade --canary
|
||||
# bun upgrade --stable <- to downgrade
|
||||
```
|
||||
# If notifying sentry fails, don't fail the rest of the build.
|
||||
- name: Notify Sentry
|
||||
uses: getsentry/action-release@v1.7.0
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
with:
|
||||
ignore_missing: true
|
||||
ignore_empty: true
|
||||
version: ${{ github.event.workflow_run.head_sha || github.sha }}-canary
|
||||
environment: canary
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -145,4 +145,3 @@ zig-cache
|
||||
zig-out
|
||||
test/node.js/upstream
|
||||
.zig-cache
|
||||
scripts/env.local
|
||||
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -76,14 +76,6 @@ ignore = dirty
|
||||
depth = 1
|
||||
shallow = true
|
||||
fetchRecurseSubmodules = false
|
||||
[submodule "src/deps/libuv"]
|
||||
path = src/deps/libuv
|
||||
url = https://github.com/libuv/libuv.git
|
||||
ignore = dirty
|
||||
depth = 1
|
||||
shallow = true
|
||||
fetchRecurseSubmodules = false
|
||||
branch = v1.48.0
|
||||
[submodule "zig"]
|
||||
path = src/deps/zig
|
||||
url = https://github.com/oven-sh/zig
|
||||
|
||||
3
.vscode/launch.json
generated
vendored
3
.vscode/launch.json
generated
vendored
@@ -145,14 +145,13 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file]",
|
||||
"program": "${workspaceFolder}/build/bun-debug",
|
||||
"args": ["run", "${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "0",
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
"BUN_DEBUG_EventLoop": "1",
|
||||
"BUN_GARBAGE_COLLECTOR_LEVEL": "2",
|
||||
"BUN_DEBUG_ALL": "1",
|
||||
},
|
||||
"console": "internalConsole",
|
||||
},
|
||||
|
||||
182
CMakeLists.txt
182
CMakeLists.txt
@@ -3,8 +3,8 @@ cmake_policy(SET CMP0091 NEW)
|
||||
cmake_policy(SET CMP0067 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||
set(Bun_VERSION "1.1.21")
|
||||
set(WEBKIT_TAG 49907bff8781719bc2ded068b0c934f6d0074d1e)
|
||||
set(Bun_VERSION "1.1.18")
|
||||
set(WEBKIT_TAG 00e8a32b3ca72cefae683cd65140428ff1d4ff09)
|
||||
|
||||
set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}")
|
||||
@@ -15,6 +15,9 @@ set(CMAKE_C_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
|
||||
|
||||
# Should not start with v
|
||||
# Used in process.version, process.versions.node, napi, and elsewhere
|
||||
set(REPORTED_NODEJS_VERSION "22.3.0")
|
||||
|
||||
@@ -22,7 +25,6 @@ set(REPORTED_NODEJS_VERSION "22.3.0")
|
||||
# If we do not set this, it will crash at startup on the first memory allocation.
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
set(CMAKE_CXX_EXTENSIONS ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE FALSE)
|
||||
endif()
|
||||
|
||||
# --- Build Type ---
|
||||
@@ -39,13 +41,6 @@ else()
|
||||
message(STATUS "The CMake build type is: ${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT CMAKE_CL_SHOWINCLUDES_PREFIX)
|
||||
# workaround until cmake fix is shipped https://github.com/ninja-build/ninja/issues/2280
|
||||
# './build/.ninja_deps' may need to be deleted, the bug is "Note: including file: ..." is saved
|
||||
# as part of some file paths
|
||||
set(CMAKE_CL_SHOWINCLUDES_PREFIX "Note: including file:")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(DEBUG ON)
|
||||
set(DEFAULT_ZIG_OPTIMIZE "Debug")
|
||||
@@ -58,8 +53,11 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(DEFAULT_ZIG_OPTIMIZE "ReleaseFast")
|
||||
|
||||
if(WIN32)
|
||||
# Debug symbols are in a separate file: bun.pdb
|
||||
# lld-link will strip it for you, so we can build directly to bun.exe
|
||||
set(bun "bun")
|
||||
|
||||
# TODO(@paperdave): Remove this
|
||||
# it is enabled for the time being to make sure to catch more bugs in the experimental windows builds
|
||||
set(DEFAULT_ZIG_OPTIMIZE "ReleaseSafe")
|
||||
else()
|
||||
if(ZIG_OPTIMIZE STREQUAL "Debug")
|
||||
@@ -72,7 +70,7 @@ endif()
|
||||
|
||||
# --- MacOS SDK ---
|
||||
if(APPLE AND DEFINED ENV{CI})
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
@@ -116,11 +114,7 @@ endif()
|
||||
# we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match.
|
||||
#
|
||||
# If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid.
|
||||
if(WIN32 OR APPLE)
|
||||
set(LLVM_VERSION 18)
|
||||
else()
|
||||
set(LLVM_VERSION 16)
|
||||
endif()
|
||||
set(LLVM_VERSION 16)
|
||||
|
||||
macro(BUN_FIND_LLVM)
|
||||
find_program(
|
||||
@@ -154,12 +148,11 @@ macro(BUN_FIND_LLVM)
|
||||
PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS}
|
||||
DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary"
|
||||
)
|
||||
|
||||
find_program(
|
||||
STRIP
|
||||
NAMES strip
|
||||
PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS}
|
||||
DOC "Path to strip binary"
|
||||
DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary"
|
||||
)
|
||||
find_program(
|
||||
DSYMUTIL
|
||||
@@ -331,16 +324,6 @@ option(USE_STATIC_LIBATOMIC "Statically link libatomic, requires the presence of
|
||||
|
||||
option(USE_LTO "Enable Link-Time Optimization" ${DEFAULT_LTO})
|
||||
|
||||
if(APPLE AND USE_LTO)
|
||||
set(USE_LTO OFF)
|
||||
message(WARNING "Link-Time Optimization is not supported on macOS because it requires -fuse-ld=lld and lld causes many segfaults on macOS (likely related to stack size)")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND USE_LTO)
|
||||
set(CMAKE_LINKER_TYPE LLD)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
|
||||
endif()
|
||||
|
||||
option(BUN_TIDY_ONLY "Only run clang-tidy" OFF)
|
||||
option(BUN_TIDY_ONLY_EXTRA " Only run clang-tidy, with extra checks for local development" OFF)
|
||||
|
||||
@@ -652,6 +635,16 @@ file(GLOB BUN_CPP ${CONFIGURE_DEPENDS}
|
||||
)
|
||||
list(APPEND BUN_RAW_SOURCES ${BUN_CPP})
|
||||
|
||||
# -- Brotli --
|
||||
set(BROTLI_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/deps/brotli")
|
||||
file(GLOB BROTLI_FILES ${CONFIGURE_DEPENDS}
|
||||
"${BROTLI_SRC}/common/*.c"
|
||||
"${BROTLI_SRC}/enc/*.c"
|
||||
"${BROTLI_SRC}/dec/*.c"
|
||||
)
|
||||
list(APPEND BUN_RAW_SOURCES ${BROTLI_FILES})
|
||||
include_directories("${BUN_DEPS_DIR}/brotli/include")
|
||||
|
||||
# -- uSockets --
|
||||
set(USOCKETS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src")
|
||||
file(GLOB USOCKETS_FILES ${CONFIGURE_DEPENDS}
|
||||
@@ -782,8 +775,6 @@ if(NOT NO_CODEGEN)
|
||||
"${BUN_SRC}/js/thirdparty/*.ts"
|
||||
"${BUN_SRC}/js/internal/*.js"
|
||||
"${BUN_SRC}/js/internal/*.ts"
|
||||
"${BUN_SRC}/js/internal/util/*.js"
|
||||
"${BUN_SRC}/js/internal/fs/*.ts"
|
||||
"${BUN_SRC}/js/node/*.js"
|
||||
"${BUN_SRC}/js/node/*.ts"
|
||||
"${BUN_SRC}/js/thirdparty/*.js"
|
||||
@@ -867,24 +858,13 @@ file(GLOB ZIG_FILES
|
||||
"${BUN_SRC}/*/*/*/*/*.zig"
|
||||
)
|
||||
|
||||
if(NOT BUN_ZIG_OBJ_FORMAT)
|
||||
# To use LLVM bitcode from Zig, more work needs to be done. Currently, an install of
|
||||
# LLVM 18.1.7 does not compatible with what bitcode Zig 0.13 outputs (has LLVM 18.1.7)
|
||||
# Change to "bc" to experiment, "Invalid record" means it is not valid output.
|
||||
set(BUN_ZIG_OBJ_FORMAT "obj")
|
||||
endif()
|
||||
|
||||
if(NOT BUN_ZIG_OBJ_DIR)
|
||||
set(BUN_ZIG_OBJ_DIR "${BUN_WORKDIR}/CMakeFiles")
|
||||
endif()
|
||||
|
||||
get_filename_component(BUN_ZIG_OBJ_DIR "${BUN_ZIG_OBJ_DIR}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
|
||||
if(WIN32)
|
||||
set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o")
|
||||
else()
|
||||
set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o")
|
||||
endif()
|
||||
set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o")
|
||||
|
||||
set(USES_TERMINAL_NOT_IN_CI "")
|
||||
|
||||
@@ -899,7 +879,6 @@ if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY)
|
||||
"${ZIG_COMPILER}" "build" "obj"
|
||||
"--zig-lib-dir" "${ZIG_LIB_DIR}"
|
||||
"--prefix" "${BUN_ZIG_OBJ_DIR}"
|
||||
"--verbose"
|
||||
"-Dgenerated-code=${BUN_WORKDIR}/codegen"
|
||||
"-freference-trace=10"
|
||||
"-Dversion=${Bun_VERSION}"
|
||||
@@ -909,7 +888,6 @@ if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY)
|
||||
"-Dtarget=${ZIG_TARGET}"
|
||||
"-Denable_logs=${ENABLE_LOGS}"
|
||||
"-Dreported_nodejs_version=${REPORTED_NODEJS_VERSION}"
|
||||
"-Dobj_format=${BUN_ZIG_OBJ_FORMAT}"
|
||||
DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/build.zig"
|
||||
"${ZIG_FILES}"
|
||||
@@ -973,15 +951,12 @@ set_target_properties(${bun} PROPERTIES
|
||||
VISIBILITY_INLINES_HIDDEN YES
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
add_compile_definitions("__DARWIN_NON_CANCELABLE=1")
|
||||
endif()
|
||||
|
||||
add_compile_definitions(
|
||||
|
||||
# TODO: are all of these variables strictly necessary?
|
||||
"_HAS_EXCEPTIONS=0"
|
||||
"LIBUS_USE_OPENSSL=1"
|
||||
"UWS_HTTPRESPONSE_NO_WRITEMARK=1"
|
||||
"LIBUS_USE_BORINGSSL=1"
|
||||
"WITH_BORINGSSL=1"
|
||||
"STATICALLY_LINKED_WITH_JavaScriptCore=1"
|
||||
@@ -1086,7 +1061,7 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
|
||||
if(NOT WIN32)
|
||||
if(USE_LTO)
|
||||
list(APPEND LTO_FLAG "-flto=full" "-emit-llvm" "-fwhole-program-vtables" "-fforce-emit-vtables")
|
||||
list(APPEND LTO_FLAG "-flto=full" "-emit-llvm")
|
||||
endif()
|
||||
|
||||
# Leave -Werror=unused off in release builds so we avoid errors from being used in ASSERT
|
||||
@@ -1105,38 +1080,13 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(LTO_LINK_FLAG "")
|
||||
|
||||
if(USE_LTO)
|
||||
target_compile_options(${bun} PUBLIC -Xclang -emit-llvm-bc)
|
||||
|
||||
# -emit-llvm seems to not be supported or under a different name on Windows.
|
||||
list(APPEND LTO_FLAG "-flto=full")
|
||||
list(APPEND LTO_LINK_FLAG "-flto=full")
|
||||
list(APPEND LTO_LINK_FLAG "/LTCG")
|
||||
list(APPEND LTO_LINK_FLAG "/OPT:REF")
|
||||
list(APPEND LTO_LINK_FLAG "/OPT:NOICF")
|
||||
endif()
|
||||
|
||||
target_compile_options(${bun} PUBLIC
|
||||
/O2
|
||||
${LTO_FLAG}
|
||||
/Gy
|
||||
/Gw
|
||||
/GF
|
||||
/GA
|
||||
)
|
||||
target_link_options(${bun} PUBLIC
|
||||
${LTO_LINK_FLAG}
|
||||
/DEBUG:FULL
|
||||
|
||||
/delayload:ole32.dll
|
||||
/delayload:WINMM.dll
|
||||
/delayload:dbghelp.dll
|
||||
/delayload:VCRUNTIME140_1.dll
|
||||
|
||||
# libuv loads these two immediately, but for some reason it seems to still be slightly faster to delayload them
|
||||
/delayload:WS2_32.dll
|
||||
/delayload:WSOCK32.dll
|
||||
/delayload:ADVAPI32.dll
|
||||
/delayload:IPHLPAPI.dll
|
||||
)
|
||||
target_compile_options(${bun} PUBLIC /O2 ${LTO_FLAG})
|
||||
target_link_options(${bun} PUBLIC ${LTO_LINK_FLAG} /DEBUG:FULL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1154,11 +1104,6 @@ else()
|
||||
# On arm macOS, we can set it to a minimum of the M1 cpu set. this might be the default already.
|
||||
target_compile_options(${bun} PUBLIC "-mcpu=apple-m1")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE AND ARCH STREQUAL "aarch64")
|
||||
# on arm64 linux, we set a minimum of armv8
|
||||
target_compile_options(${bun} PUBLIC -march=armv8-a+crc -mtune=ampere1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_options(${bun} PUBLIC -ferror-limit=${ERROR_LIMIT})
|
||||
@@ -1172,29 +1117,27 @@ if(WIN32)
|
||||
"BORINGSSL_NO_CXX=1" # lol
|
||||
)
|
||||
|
||||
# set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
||||
# set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
||||
set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
||||
|
||||
target_compile_options(${bun} PUBLIC "/EHsc" "/GR-" -Xclang -fno-c++-static-destructors)
|
||||
if(USE_LTO)
|
||||
target_compile_options(${bun} PUBLIC "-Xclang -emit-llvm-bc")
|
||||
endif()
|
||||
|
||||
target_compile_options(${bun} PUBLIC "/EHsc" "/GR-")
|
||||
target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000" "/DEF:${BUN_SRC}/symbols.def" "/errorlimit:0")
|
||||
else()
|
||||
target_compile_options(${bun} PUBLIC
|
||||
-fPIC
|
||||
-mtune=${CPU_TARGET}
|
||||
-fconstexpr-steps=2542484
|
||||
-fconstexpr-depth=54
|
||||
-fno-exceptions
|
||||
-fno-asynchronous-unwind-tables
|
||||
-fno-unwind-tables
|
||||
-fno-c++-static-destructors
|
||||
-fvisibility=hidden
|
||||
-fvisibility-inlines-hidden
|
||||
-fno-rtti
|
||||
-fno-omit-frame-pointer
|
||||
-mno-omit-leaf-frame-pointer
|
||||
-fno-pic
|
||||
-fno-pie
|
||||
-faddrsig
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1204,18 +1147,17 @@ if(APPLE)
|
||||
target_link_options(${bun} PUBLIC "-Wl,-stack_size,0x1200000")
|
||||
target_link_options(${bun} PUBLIC "-exported_symbols_list" "${BUN_SRC}/symbols.txt")
|
||||
set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.txt")
|
||||
|
||||
target_link_options(${bun} PUBLIC "-fno-keep-static-consts")
|
||||
target_link_libraries(${bun} PRIVATE "resolv")
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_options(${bun} PUBLIC
|
||||
-fuse-ld=lld
|
||||
-fno-pic
|
||||
-static-libstdc++
|
||||
-static-libgcc
|
||||
"-Wl,-no-pie"
|
||||
"-Wl,-icf=safe"
|
||||
"-fuse-ld=lld"
|
||||
"-static-libstdc++"
|
||||
"-static-libgcc"
|
||||
"-Wl,-z,now"
|
||||
"-Wl,--as-needed"
|
||||
"-Wl,--gc-sections"
|
||||
"-Wl,-z,stack-size=12800000"
|
||||
@@ -1244,8 +1186,6 @@ if(UNIX AND NOT APPLE)
|
||||
"-rdynamic"
|
||||
"-Wl,--dynamic-list=${BUN_SRC}/symbols.dyn"
|
||||
"-Wl,--version-script=${BUN_SRC}/linker.lds"
|
||||
-Wl,-z,lazy
|
||||
-Wl,-z,norelro
|
||||
)
|
||||
|
||||
target_link_libraries(${bun} PRIVATE "c")
|
||||
@@ -1279,16 +1219,12 @@ endif()
|
||||
|
||||
# --- Stripped Binary "bun"
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32 AND NOT ASSERT_ENABLED)
|
||||
# if(CI AND APPLE)
|
||||
if(APPLE)
|
||||
add_custom_command(
|
||||
TARGET ${bun}
|
||||
POST_BUILD
|
||||
COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/${bun}.dSYM ${BUN_WORKDIR}/${bun}
|
||||
COMMENT "Generating .dSYM"
|
||||
)
|
||||
endif()
|
||||
|
||||
# add_custom_command(
|
||||
# TARGET ${bun}
|
||||
# POST_BUILD
|
||||
# COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/bun.dSYM ${BUN_WORKDIR}/${bun}
|
||||
# COMMENT "Stripping Symbols"
|
||||
# )
|
||||
add_custom_command(
|
||||
TARGET ${bun}
|
||||
POST_BUILD
|
||||
@@ -1456,11 +1392,6 @@ if(USE_STATIC_SQLITE)
|
||||
"SQLITE_ENABLE_JSON1=1"
|
||||
"SQLITE_ENABLE_MATH_FUNCTIONS=1"
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_options(sqlite3 PRIVATE /MT /U_DLL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${bun} PRIVATE sqlite3)
|
||||
message(STATUS "Using static sqlite3")
|
||||
target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=0")
|
||||
@@ -1469,24 +1400,6 @@ else()
|
||||
target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=1")
|
||||
endif()
|
||||
|
||||
# -- Brotli --
|
||||
set(BROTLI_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/deps/brotli")
|
||||
file(GLOB BROTLI_FILES ${CONFIGURE_DEPENDS}
|
||||
"${BROTLI_SRC}/common/*.c"
|
||||
"${BROTLI_SRC}/enc/*.c"
|
||||
"${BROTLI_SRC}/dec/*.c"
|
||||
)
|
||||
add_library(brotli STATIC ${BROTLI_FILES})
|
||||
target_include_directories(brotli PRIVATE "${BROTLI_SRC}/include")
|
||||
target_compile_definitions(brotli PRIVATE "BROTLI_STATIC")
|
||||
|
||||
if(WIN32)
|
||||
target_compile_options(brotli PRIVATE /MT /U_DLL)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${bun} PRIVATE brotli)
|
||||
include_directories("${BUN_DEPS_DIR}/brotli/include")
|
||||
|
||||
if(USE_CUSTOM_LSHPACK)
|
||||
include_directories(${BUN_DEPS_DIR}/ls-hpack)
|
||||
|
||||
@@ -1506,6 +1419,7 @@ if(NOT WIN32)
|
||||
target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libJavaScriptCore.a")
|
||||
target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libbmalloc.a")
|
||||
else()
|
||||
target_link_options(${bun} PRIVATE "-static")
|
||||
target_link_libraries(${bun} PRIVATE
|
||||
"${WEBKIT_LIB_DIR}/WTF.lib"
|
||||
"${WEBKIT_LIB_DIR}/JavaScriptCore.lib"
|
||||
@@ -1515,10 +1429,10 @@ else()
|
||||
winmm
|
||||
bcrypt
|
||||
ntdll
|
||||
ucrt
|
||||
userenv
|
||||
dbghelp
|
||||
wsock32 # ws2_32 required by TransmitFile aka sendfile on windows
|
||||
delayimp.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -2,11 +2,6 @@ Configuring a development environment for Bun can take 10-30 minutes depending o
|
||||
|
||||
If you are using Windows, please refer to [this guide](/docs/project/building-windows)
|
||||
|
||||
{% details summary="For Ubuntu users" %}
|
||||
TL;DR: Ubuntu 22.04 is suggested.
|
||||
Bun currently requires `glibc >=2.32` in development which means if you're on Ubuntu 20.04 (glibc == 2.31), you may likely meet `error: undefined symbol: __libc_single_threaded `. You need to take extra configurations. Also, according to this [issue](https://github.com/llvm/llvm-project/issues/97314), LLVM 16 is no longer maintained on Ubuntu 24.04 (noble). And instead, you might want `brew` to install LLVM 16 for your Ubuntu 24.04.
|
||||
{% /details %}
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
Using your system's package manager, install Bun's dependencies:
|
||||
@@ -112,7 +107,7 @@ $ export PATH="$PATH:/usr/lib/llvm16/bin"
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
> ⚠️ Ubuntu distributions (<= 20.04) may require installation of the C++ standard library independently. See the [troubleshooting section](#span-file-not-found-on-ubuntu) for more information.
|
||||
> ⚠️ Ubuntu distributions may require installation of the C++ standard library independently. See the [troubleshooting section](#span-file-not-found-on-ubuntu) for more information.
|
||||
|
||||
## Building Bun
|
||||
|
||||
@@ -316,12 +311,3 @@ $ bun setup -DUSE_STATIC_LIBATOMIC=OFF
|
||||
```
|
||||
|
||||
The built version of Bun may not work on other systems if compiled this way.
|
||||
|
||||
## ccache conflicts with building TinyCC on macOS
|
||||
|
||||
If you run into issues with `ccache` when building TinyCC, try reinstalling ccache
|
||||
|
||||
```bash
|
||||
brew uninstall ccache
|
||||
brew install ccache
|
||||
```
|
||||
|
||||
47
Dockerfile
47
Dockerfile
@@ -52,8 +52,11 @@ ENV CI 1
|
||||
ENV CPU_TARGET=${CPU_TARGET}
|
||||
ENV BUILDARCH=${BUILDARCH}
|
||||
ENV BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR}
|
||||
ENV BUN_ENABLE_LTO 1
|
||||
|
||||
ENV CXX=clang++-${LLVM_VERSION}
|
||||
ENV CC=clang-${LLVM_VERSION}
|
||||
ENV AR=/usr/bin/llvm-ar-${LLVM_VERSION}
|
||||
ENV LD=lld-${LLVM_VERSION}
|
||||
ENV LC_CTYPE=en_US.UTF-8
|
||||
ENV LC_ALL=en_US.UTF-8
|
||||
|
||||
@@ -90,8 +93,6 @@ RUN install_packages \
|
||||
clangd-${LLVM_VERSION} \
|
||||
libc++-${LLVM_VERSION}-dev \
|
||||
libc++abi-${LLVM_VERSION}-dev \
|
||||
llvm-${LLVM_VERSION}-runtime \
|
||||
llvm-${LLVM_VERSION}-dev \
|
||||
make \
|
||||
cmake \
|
||||
ninja-build \
|
||||
@@ -118,15 +119,6 @@ RUN install_packages \
|
||||
&& ln -sf /usr/bin/lldb-${LLVM_VERSION} /usr/bin/lldb \
|
||||
&& ln -sf /usr/bin/clangd-${LLVM_VERSION} /usr/bin/clangd \
|
||||
&& ln -sf /usr/bin/llvm-ar-${LLVM_VERSION} /usr/bin/llvm-ar \
|
||||
&& ln -sf /usr/bin/ld.lld /usr/bin/ld \
|
||||
&& ln -sf /usr/bin/llvm-ranlib-${LLVM_VERSION} /usr/bin/ranlib \
|
||||
&& ln -sf /usr/bin/clang /usr/bin/cc \
|
||||
&& ln -sf /usr/bin/clang /usr/bin/c89 \
|
||||
&& ln -sf /usr/bin/clang /usr/bin/c99 \
|
||||
&& ln -sf /usr/bin/clang++ /usr/bin/c++ \
|
||||
&& ln -sf /usr/bin/clang++ /usr/bin/g++ \
|
||||
&& ln -sf /usr/bin/llvm-ar /usr/bin/ar \
|
||||
&& ln -sf /usr/bin/clang /usr/bin/gcc \
|
||||
&& arch="$(dpkg --print-architecture)" \
|
||||
&& case "${arch##*-}" in \
|
||||
amd64) variant="x64";; \
|
||||
@@ -139,7 +131,6 @@ RUN install_packages \
|
||||
&& ln -s /usr/bin/bun /usr/bin/bunx \
|
||||
&& rm -rf bun-linux-${variant} bun-linux-${variant}.zip \
|
||||
&& mkdir -p ${BUN_DIR} ${BUN_DEPS_OUT_DIR}
|
||||
|
||||
# && if [ -n "${SCCACHE_BUCKET}" ]; then \
|
||||
# echo "Setting up sccache" \
|
||||
# && wget https://github.com/mozilla/sccache/releases/download/v0.5.4/sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl.tar.gz \
|
||||
@@ -176,14 +167,13 @@ ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/c-ares ${BUN_DIR}/src/deps/c-ares
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd $BUN_DIR \
|
||||
&& bash ./scripts/build-cares.sh \
|
||||
&& rm -rf ${BUN_DIR}/src/deps/c-ares ${BUN_DIR}/Makefile ${BUN_DIR}/scripts
|
||||
&& make c-ares \
|
||||
&& rm -rf ${BUN_DIR}/src/deps/c-ares ${BUN_DIR}/Makefile
|
||||
|
||||
FROM bun-base as lolhtml
|
||||
|
||||
@@ -214,14 +204,13 @@ ENV CPU_TARGET=${CPU_TARGET}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/mimalloc ${BUN_DIR}/src/deps/mimalloc
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
|
||||
ARG CCACHE_DIR=/ccache
|
||||
ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd ${BUN_DIR} \
|
||||
&& bash ./scripts/build-mimalloc.sh \
|
||||
&& make mimalloc \
|
||||
&& rm -rf src/deps/mimalloc Makefile
|
||||
|
||||
FROM bun-base as mimalloc-debug
|
||||
@@ -251,17 +240,14 @@ ARG CCACHE_DIR=/ccache
|
||||
ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY CMakeLists.txt ${BUN_DIR}/CMakeLists.txt
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
COPY src/deps/zlib ${BUN_DIR}/src/deps/zlib
|
||||
COPY package.json bun.lockb Makefile .gitmodules ${BUN_DIR}/
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd $BUN_DIR \
|
||||
&& bash ./scripts/build-zlib.sh && rm -rf src/deps/zlib scripts
|
||||
|
||||
&& make zlib \
|
||||
&& rm -rf src/deps/zlib Makefile
|
||||
|
||||
FROM bun-base as libarchive
|
||||
|
||||
@@ -300,7 +286,6 @@ ARG CPU_TARGET
|
||||
ENV CPU_TARGET=${CPU_TARGET}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
COPY src/deps/boringssl ${BUN_DIR}/src/deps/boringssl
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
@@ -310,7 +295,7 @@ ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd ${BUN_DIR} \
|
||||
&& bash ./scripts/build-boringssl.sh \
|
||||
&& make boringssl \
|
||||
&& rm -rf src/deps/boringssl Makefile
|
||||
|
||||
|
||||
@@ -326,14 +311,12 @@ ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/zstd ${BUN_DIR}/src/deps/zstd
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd $BUN_DIR \
|
||||
&& bash ./scripts/build-zstd.sh \
|
||||
&& rm -rf src/deps/zstd scripts
|
||||
&& make zstd
|
||||
|
||||
FROM bun-base as ls-hpack
|
||||
|
||||
@@ -347,14 +330,12 @@ ENV CCACHE_DIR=${CCACHE_DIR}
|
||||
|
||||
COPY Makefile ${BUN_DIR}/Makefile
|
||||
COPY src/deps/ls-hpack ${BUN_DIR}/src/deps/ls-hpack
|
||||
COPY scripts ${BUN_DIR}/scripts
|
||||
|
||||
WORKDIR $BUN_DIR
|
||||
|
||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||
cd $BUN_DIR \
|
||||
&& bash ./scripts/build-lshpack.sh \
|
||||
&& rm -rf src/deps/ls-hpack scripts
|
||||
&& make lshpack
|
||||
|
||||
FROM bun-base-with-zig as bun-identifier-cache
|
||||
|
||||
@@ -510,7 +491,6 @@ RUN mkdir -p build bun-webkit
|
||||
|
||||
# lol
|
||||
COPY src/bun.js/bindings/sqlite/sqlite3.c ${BUN_DIR}/src/bun.js/bindings/sqlite/sqlite3.c
|
||||
COPY src/deps/brotli ${BUN_DIR}/src/deps/brotli
|
||||
|
||||
COPY src/symbols.dyn src/linker.lds ${BUN_DIR}/src/
|
||||
|
||||
@@ -525,8 +505,7 @@ COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=c-ares ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=ls-hpack ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
|
||||
COPY --from=bun-compile-zig-obj /tmp/bun-zig.o ${BUN_DIR}/build/bun-zig.o
|
||||
COPY --from=bun-cpp-objects ${BUN_DIR}/build/*.a ${BUN_DIR}/build/
|
||||
COPY --from=bun-cpp-objects ${BUN_DIR}/build/*.o ${BUN_DIR}/build/
|
||||
COPY --from=bun-cpp-objects ${BUN_DIR}/build/bun-cpp-objects.a ${BUN_DIR}/build/bun-cpp-objects.a
|
||||
COPY --from=bun-cpp-objects ${BUN_DIR}/bun-webkit/lib ${BUN_DIR}/bun-webkit/lib
|
||||
|
||||
WORKDIR $BUN_DIR/build
|
||||
|
||||
16
Makefile
16
Makefile
@@ -26,11 +26,8 @@ ifeq ($(ARCH_NAME_RAW),arm64)
|
||||
ARCH_NAME = aarch64
|
||||
DOCKER_BUILDARCH = arm64
|
||||
BREW_PREFIX_PATH = /opt/homebrew
|
||||
DEFAULT_MIN_MACOS_VERSION = 13.0
|
||||
DEFAULT_MIN_MACOS_VERSION = 11.0
|
||||
MARCH_NATIVE = -mtune=$(CPU_TARGET)
|
||||
ifeq ($(OS_NAME),linux)
|
||||
MARCH_NATIVE = -march=armv8-a+crc -mtune=ampere1
|
||||
endif
|
||||
else
|
||||
ARCH_NAME = x64
|
||||
DOCKER_BUILDARCH = amd64
|
||||
@@ -157,12 +154,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \
|
||||
$(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \
|
||||
-DCMAKE_AR=$(AR) \
|
||||
-DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
|
||||
-DCMAKE_CXX_STANDARD=20 \
|
||||
-DCMAKE_C_STANDARD=17 \
|
||||
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
|
||||
-DCMAKE_C_STANDARD_REQUIRED=ON \
|
||||
-DCMAKE_CXX_EXTENSIONS=ON
|
||||
-DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null)
|
||||
|
||||
|
||||
|
||||
@@ -189,8 +181,8 @@ endif
|
||||
|
||||
OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE)
|
||||
DEBUG_OPTIMIZATION_LEVEL= -O1 $(MARCH_NATIVE) -gdwarf-4
|
||||
CFLAGS_WITHOUT_MARCH = $(MACOS_MIN_FLAG) $(OPTIMIZATION_LEVEL) -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pie -fno-pic
|
||||
BUN_CFLAGS = $(MACOS_MIN_FLAG) $(MARCH_NATIVE) $(OPTIMIZATION_LEVEL) -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pie -fno-pic
|
||||
CFLAGS_WITHOUT_MARCH = $(MACOS_MIN_FLAG) $(OPTIMIZATION_LEVEL) -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
BUN_CFLAGS = $(MACOS_MIN_FLAG) $(MARCH_NATIVE) $(OPTIMIZATION_LEVEL) -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
BUN_TMP_DIR := /tmp/make-bun
|
||||
CFLAGS=$(CFLAGS_WITHOUT_MARCH) $(MARCH_NATIVE)
|
||||
|
||||
|
||||
BIN
bench/bun.lockb
BIN
bench/bun.lockb
Binary file not shown.
@@ -3,7 +3,6 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.16.10",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@babel/standalone": "^7.24.7",
|
||||
"@swc/core": "^1.2.133",
|
||||
"benchmark": "^2.1.4",
|
||||
"braces": "^3.0.2",
|
||||
|
||||
@@ -6,7 +6,6 @@ const App = () => (
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<p>This is an example.</p>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { bench, run } from "mitata";
|
||||
import { join } from "path";
|
||||
|
||||
const code = require("fs").readFileSync(
|
||||
process.argv[2] || join(import.meta.dir, "../node_modules/@babel/standalone/babel.min.js"),
|
||||
);
|
||||
|
||||
const transpiler = new Bun.Transpiler({ minify: true });
|
||||
|
||||
bench("transformSync", () => {
|
||||
transpiler.transformSync(code);
|
||||
});
|
||||
|
||||
await run();
|
||||
200
build.zig
200
build.zig
@@ -33,6 +33,8 @@ comptime {
|
||||
}
|
||||
}
|
||||
|
||||
const default_reported_nodejs_version = "22.3.0";
|
||||
|
||||
const zero_sha = "0000000000000000000000000000000000000000";
|
||||
|
||||
const BunBuildOptions = struct {
|
||||
@@ -46,7 +48,7 @@ const BunBuildOptions = struct {
|
||||
sha: []const u8,
|
||||
enable_logs: bool = false,
|
||||
tracy_callstack_depth: u16,
|
||||
reported_nodejs_version: Version,
|
||||
reported_nodejs_version: []const u8 = default_reported_nodejs_version,
|
||||
|
||||
generated_code_dir: []const u8,
|
||||
|
||||
@@ -71,7 +73,14 @@ const BunBuildOptions = struct {
|
||||
opts.addOption([:0]const u8, "sha", b.allocator.dupeZ(u8, this.sha) catch @panic("OOM"));
|
||||
opts.addOption(bool, "baseline", this.isBaseline());
|
||||
opts.addOption(bool, "enable_logs", this.enable_logs);
|
||||
opts.addOption([]const u8, "reported_nodejs_version", b.fmt("{}", .{this.reported_nodejs_version}));
|
||||
opts.addOption([:0]const u8, "reported_nodejs_version", b.allocator.dupeZ(u8, this.reported_nodejs_version) catch @panic("OOM"));
|
||||
if (this.reported_nodejs_version.len > 0 and this.reported_nodejs_version[0] == 'v') {
|
||||
@panic("Node.js version should not start with 'v'");
|
||||
}
|
||||
|
||||
if (this.reported_nodejs_version.len == 0) {
|
||||
@panic("Node.js version should not be empty");
|
||||
}
|
||||
|
||||
const mod = opts.createModule();
|
||||
this.cached_options_module = mod;
|
||||
@@ -113,25 +122,8 @@ pub fn getOSGlibCVersion(os: OperatingSystem) ?Version {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getCpuModel(os: OperatingSystem, arch: Arch) ?Target.Query.CpuModel {
|
||||
// https://github.com/oven-sh/bun/issues/12076
|
||||
if (os == .linux and arch == .aarch64) {
|
||||
return .{ .explicit = &Target.aarch64.cpu.cortex_a35 };
|
||||
}
|
||||
|
||||
// Be explicit and ensure we do not accidentally target a newer M-series chip
|
||||
if (os == .mac and arch == .aarch64) {
|
||||
return .{ .explicit = &Target.aarch64.cpu.apple_m1 };
|
||||
}
|
||||
|
||||
// note: x86_64 is dealt with in the CMake config and passed in.
|
||||
// the reason for the explicit handling on aarch64 is due to troubles
|
||||
// passing the exact target in via flags.
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn build(b: *Build) !void {
|
||||
std.log.info("zig compiler v{s}", .{builtin.zig_version_string});
|
||||
std.debug.print("zig build v{s}\n", .{builtin.zig_version_string});
|
||||
|
||||
b.zig_lib_dir = b.zig_lib_dir orelse b.path("src/deps/zig/lib");
|
||||
|
||||
@@ -155,14 +147,6 @@ pub fn build(b: *Build) !void {
|
||||
break :brk .{ os, arch };
|
||||
};
|
||||
|
||||
// target must be refined to support older but very popular devices on
|
||||
// aarch64, this means moving the minimum supported CPU to support certain
|
||||
// raspberry PIs. there are also a number of cloud hosts that use virtual
|
||||
// machines with surprisingly out of date versions of glibc.
|
||||
if (getCpuModel(os, arch)) |cpu_model| {
|
||||
target_query.cpu_model = cpu_model;
|
||||
}
|
||||
|
||||
target_query.os_version_min = getOSVersionMin(os);
|
||||
target_query.glibc_version = getOSGlibCVersion(os);
|
||||
|
||||
@@ -179,8 +163,6 @@ pub fn build(b: *Build) !void {
|
||||
break :ref_trace if (trace == 0) null else trace;
|
||||
};
|
||||
|
||||
const obj_format = b.option(ObjectFormat, "obj_format", "Output file for object files") orelse .obj;
|
||||
|
||||
var build_options = BunBuildOptions{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
@@ -196,10 +178,7 @@ pub fn build(b: *Build) !void {
|
||||
break :canary if (rev == 0) null else rev;
|
||||
},
|
||||
|
||||
.reported_nodejs_version = try Version.parse(
|
||||
b.option([]const u8, "reported_nodejs_version", "Reported Node.js version") orelse
|
||||
"0.0.0-unset",
|
||||
),
|
||||
.reported_nodejs_version = b.option([]const u8, "reported_nodejs_version", "Reported Node.js version") orelse default_reported_nodejs_version,
|
||||
|
||||
.sha = sha: {
|
||||
const sha = b.option([]const u8, "sha", "Force the git sha") orelse
|
||||
@@ -245,7 +224,7 @@ pub fn build(b: *Build) !void {
|
||||
var step = b.step("obj", "Build Bun's Zig code as a .o file");
|
||||
var bun_obj = addBunObject(b, &build_options);
|
||||
step.dependOn(&bun_obj.step);
|
||||
step.dependOn(addInstallObjectFile(b, bun_obj, "bun-zig", obj_format));
|
||||
step.dependOn(&b.addInstallFile(bun_obj.getEmittedBin(), "bun-zig.o").step);
|
||||
}
|
||||
|
||||
// zig build windows-shim
|
||||
@@ -273,60 +252,96 @@ pub fn build(b: *Build) !void {
|
||||
|
||||
// zig build check-all
|
||||
{
|
||||
const step = b.step("check-all", "Check for semantic analysis errors on all supported platforms");
|
||||
addMultiCheck(b, step, build_options, &.{
|
||||
var step = b.step("check-all", "Check for semantic analysis errors on all supported platforms");
|
||||
inline for (.{
|
||||
.{ .os = .windows, .arch = .x86_64 },
|
||||
.{ .os = .mac, .arch = .x86_64 },
|
||||
.{ .os = .mac, .arch = .aarch64 },
|
||||
.{ .os = .linux, .arch = .x86_64 },
|
||||
.{ .os = .linux, .arch = .aarch64 },
|
||||
});
|
||||
}) |check| {
|
||||
inline for (.{ .Debug, .ReleaseFast }) |mode| {
|
||||
const check_target = b.resolveTargetQuery(.{
|
||||
.os_tag = OperatingSystem.stdOSTag(check.os),
|
||||
.cpu_arch = check.arch,
|
||||
.os_version_min = getOSVersionMin(check.os),
|
||||
.glibc_version = getOSGlibCVersion(check.os),
|
||||
});
|
||||
|
||||
var options = BunBuildOptions{
|
||||
.target = check_target,
|
||||
.os = check.os,
|
||||
.arch = check_target.result.cpu.arch,
|
||||
.optimize = mode,
|
||||
|
||||
.canary_revision = build_options.canary_revision,
|
||||
.sha = build_options.sha,
|
||||
.tracy_callstack_depth = build_options.tracy_callstack_depth,
|
||||
.version = build_options.version,
|
||||
.reported_nodejs_version = build_options.reported_nodejs_version,
|
||||
.generated_code_dir = build_options.generated_code_dir,
|
||||
};
|
||||
var obj = addBunObject(b, &options);
|
||||
obj.generated_bin = null;
|
||||
step.dependOn(&obj.step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// zig build check-windows
|
||||
{
|
||||
const step = b.step("check-windows", "Check for semantic analysis errors on Windows");
|
||||
addMultiCheck(b, step, build_options, &.{
|
||||
var step = b.step("check-windows", "Check for semantic analysis errors on Windows x64");
|
||||
inline for (.{
|
||||
.{ .os = .windows, .arch = .x86_64 },
|
||||
});
|
||||
}
|
||||
}
|
||||
}) |check| {
|
||||
inline for (.{ .Debug, .ReleaseFast }) |mode| {
|
||||
const check_target = b.resolveTargetQuery(.{
|
||||
.os_tag = OperatingSystem.stdOSTag(check.os),
|
||||
.cpu_arch = check.arch,
|
||||
.os_version_min = getOSVersionMin(check.os),
|
||||
.glibc_version = getOSGlibCVersion(check.os),
|
||||
});
|
||||
|
||||
pub inline fn addMultiCheck(
|
||||
b: *Build,
|
||||
parent_step: *Step,
|
||||
root_build_options: BunBuildOptions,
|
||||
to_check: []const struct { os: OperatingSystem, arch: Arch },
|
||||
) void {
|
||||
inline for (to_check) |check| {
|
||||
inline for (.{ .Debug, .ReleaseFast }) |mode| {
|
||||
const check_target = b.resolveTargetQuery(.{
|
||||
.os_tag = OperatingSystem.stdOSTag(check.os),
|
||||
.cpu_arch = check.arch,
|
||||
.cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_cpu_arch,
|
||||
.os_version_min = getOSVersionMin(check.os),
|
||||
.glibc_version = getOSGlibCVersion(check.os),
|
||||
});
|
||||
var options = BunBuildOptions{
|
||||
.target = check_target,
|
||||
.os = check.os,
|
||||
.arch = check_target.result.cpu.arch,
|
||||
.optimize = mode,
|
||||
|
||||
var options: BunBuildOptions = .{
|
||||
.target = check_target,
|
||||
.os = check.os,
|
||||
.arch = check_target.result.cpu.arch,
|
||||
.optimize = mode,
|
||||
|
||||
.canary_revision = root_build_options.canary_revision,
|
||||
.sha = root_build_options.sha,
|
||||
.tracy_callstack_depth = root_build_options.tracy_callstack_depth,
|
||||
.version = root_build_options.version,
|
||||
.reported_nodejs_version = root_build_options.reported_nodejs_version,
|
||||
.generated_code_dir = root_build_options.generated_code_dir,
|
||||
};
|
||||
|
||||
var obj = addBunObject(b, &options);
|
||||
obj.generated_bin = null;
|
||||
parent_step.dependOn(&obj.step);
|
||||
.canary_revision = build_options.canary_revision,
|
||||
.sha = build_options.sha,
|
||||
.tracy_callstack_depth = build_options.tracy_callstack_depth,
|
||||
.version = build_options.version,
|
||||
.reported_nodejs_version = build_options.reported_nodejs_version,
|
||||
.generated_code_dir = build_options.generated_code_dir,
|
||||
};
|
||||
var obj = addBunObject(b, &options);
|
||||
obj.generated_bin = null;
|
||||
step.dependOn(&obj.step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Running `zig build` with no arguments is almost always a mistake.
|
||||
// TODO: revive this error. cannot right now since ZLS runs zig build without arguments
|
||||
{
|
||||
// const mistake_message = b.addSystemCommand(&.{
|
||||
// "echo",
|
||||
// \\
|
||||
// \\To build Bun from source, please use `bun run setup` instead of `zig build`"
|
||||
// \\For more info, see https://bun.sh/docs/project/contributing
|
||||
// \\
|
||||
// \\If you want to build the zig code in isolation, run:
|
||||
// \\ 'zig build obj -Dgenerated-code=./build/codegen [...opts]'
|
||||
// \\
|
||||
// \\If you want to test a compile without emitting an object:
|
||||
// \\ 'zig build check'
|
||||
// \\ 'zig build check-all' (run linux+mac+windows)
|
||||
// \\
|
||||
// });
|
||||
|
||||
// b.default_step.dependOn(&mistake_message.step);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
@@ -338,13 +353,10 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
},
|
||||
.target = opts.target,
|
||||
.optimize = opts.optimize,
|
||||
|
||||
// https://github.com/ziglang/zig/issues/17430
|
||||
.pic = true,
|
||||
|
||||
.omit_frame_pointer = false,
|
||||
.strip = false, // stripped at the end
|
||||
});
|
||||
|
||||
obj.bundle_compiler_rt = false;
|
||||
obj.formatted_panics = true;
|
||||
obj.root_module.omit_frame_pointer = false;
|
||||
@@ -362,10 +374,9 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
}
|
||||
|
||||
if (opts.os == .linux) {
|
||||
obj.link_emit_relocs = false;
|
||||
obj.link_eh_frame_hdr = false;
|
||||
obj.link_emit_relocs = true;
|
||||
obj.link_eh_frame_hdr = true;
|
||||
obj.link_function_sections = true;
|
||||
obj.link_data_sections = true;
|
||||
|
||||
if (opts.optimize == .Debug) {
|
||||
obj.root_module.valgrind = true;
|
||||
@@ -376,25 +387,6 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
return obj;
|
||||
}
|
||||
|
||||
const ObjectFormat = enum {
|
||||
bc,
|
||||
obj,
|
||||
};
|
||||
|
||||
pub fn addInstallObjectFile(
|
||||
b: *Build,
|
||||
compile: *Compile,
|
||||
name: []const u8,
|
||||
out_mode: ObjectFormat,
|
||||
) *Step {
|
||||
// bin always needed to be computed or else the compilation will do nothing. zig build system bug?
|
||||
const bin = compile.getEmittedBin();
|
||||
return &b.addInstallFile(switch (out_mode) {
|
||||
.obj => bin,
|
||||
.bc => compile.getEmittedLlvmBc(),
|
||||
}, b.fmt("{s}.o", .{name})).step;
|
||||
}
|
||||
|
||||
fn exists(path: []const u8) bool {
|
||||
const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false;
|
||||
file.close();
|
||||
@@ -455,11 +447,7 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
|
||||
|
||||
fn validateGeneratedPath(path: []const u8) void {
|
||||
if (!exists(path)) {
|
||||
std.debug.panic(
|
||||
\\Generated file '{s}' is missing!
|
||||
\\
|
||||
\\Make sure to use CMake and Ninja, or pass a manual codegen folder with '-Dgenerated-code=...'
|
||||
, .{path});
|
||||
std.debug.panic("{s} does not exist in generated code directory!", .{std.fs.path.basename(path)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ _bun_completions() {
|
||||
declare -A PACKAGE_OPTIONS;
|
||||
declare -A PM_OPTIONS;
|
||||
|
||||
local SUBCOMMANDS="dev bun create run install add remove upgrade completions discord help init pm x test repl update link unlink build";
|
||||
local SUBCOMMANDS="dev bun create run install add remove upgrade completions discord help init pm x";
|
||||
|
||||
GLOBAL_OPTIONS[LONG_OPTIONS]="--use --cwd --bunfile --server-bunfile --config --disable-react-fast-refresh --disable-hmr --env-file --extension-order --jsx-factory --jsx-fragment --extension-order --jsx-factory --jsx-fragment --jsx-import-source --jsx-production --jsx-runtime --main-fields --no-summary --version --platform --public-dir --tsconfig-override --define --external --help --inject --loader --origin --port --dump-environment-variables --dump-limits --disable-bun-js";
|
||||
GLOBAL_OPTIONS[SHORT_OPTIONS]="-c -v -d -e -h -i -l -u -p";
|
||||
|
||||
@@ -425,7 +425,6 @@ _bun_run_completion() {
|
||||
'--external[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \
|
||||
'-e[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \
|
||||
'--loader[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \
|
||||
'--packages[Exclude dependencies from bundle, e.g. --packages external. Valid options: bundle, external]:packages' \
|
||||
'-l[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \
|
||||
'--origin[Rewrite import URLs to start with --origin. Default: ""]:origin' \
|
||||
'-u[Rewrite import URLs to start with --origin. Default: ""]:origin' \
|
||||
|
||||
@@ -61,7 +61,7 @@ To do anything interesting we need a construct known as a "view". A view is a cl
|
||||
|
||||
The `DataView` class is a lower-level interface for reading and manipulating the data in an `ArrayBuffer`.
|
||||
|
||||
Below we create a new `DataView` and set the first byte to 3.
|
||||
Below we create a new `DataView` and set the first byte to 5.
|
||||
|
||||
```ts
|
||||
const buf = new ArrayBuffer(4);
|
||||
@@ -395,7 +395,7 @@ Bun implements `Buffer`, a Node.js API for working with binary data that pre-dat
|
||||
|
||||
```ts
|
||||
const buf = Buffer.from("hello world");
|
||||
// => Buffer(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ]
|
||||
// => Buffer(16) [ 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103 ]
|
||||
|
||||
buf.length; // => 11
|
||||
buf[0]; // => 104, ascii for 'h'
|
||||
|
||||
@@ -1,308 +0,0 @@
|
||||
Bun implements the WHATWG `fetch` standard, with some extensions to meet the needs of server-side JavaScript.
|
||||
|
||||
Bun also implements `node:http`, but `fetch` is generally recommended instead.
|
||||
|
||||
## Sending an HTTP request
|
||||
|
||||
To send an HTTP request, use `fetch`
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com");
|
||||
|
||||
console.log(response.status); // => 200
|
||||
|
||||
const text = await response.text(); // or response.json(), response.formData(), etc.
|
||||
```
|
||||
|
||||
`fetch` also works with HTTPS URLs.
|
||||
|
||||
```ts
|
||||
const response = await fetch("https://example.com");
|
||||
```
|
||||
|
||||
You can also pass `fetch` a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object.
|
||||
|
||||
```ts
|
||||
const request = new Request("http://example.com", {
|
||||
method: "POST",
|
||||
body: "Hello, world!",
|
||||
});
|
||||
|
||||
const response = await fetch(request);
|
||||
```
|
||||
|
||||
### Sending a POST request
|
||||
|
||||
To send a POST request, pass an object with the `method` property set to `"POST"`.
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
method: "POST",
|
||||
body: "Hello, world!",
|
||||
});
|
||||
```
|
||||
|
||||
`body` can be a string, a `FormData` object, an `ArrayBuffer`, a `Blob`, and more. See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Body/body) for more information.
|
||||
|
||||
### Proxying requests
|
||||
|
||||
To proxy a request, pass an object with the `proxy` property set to a URL.
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
proxy: "http://proxy.com",
|
||||
});
|
||||
```
|
||||
|
||||
### Custom headers
|
||||
|
||||
To set custom headers, pass an object with the `headers` property set to an object.
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
headers: {
|
||||
"X-Custom-Header": "value",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
You can also set headers using the [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object.
|
||||
|
||||
```ts
|
||||
const headers = new Headers();
|
||||
headers.append("X-Custom-Header", "value");
|
||||
|
||||
const response = await fetch("http://example.com", {
|
||||
headers,
|
||||
});
|
||||
```
|
||||
|
||||
### Response bodies
|
||||
|
||||
To read the response body, use one of the following methods:
|
||||
|
||||
- `response.text(): Promise<string>`: Returns a promise that resolves with the response body as a string.
|
||||
- `response.json(): Promise<any>`: Returns a promise that resolves with the response body as a JSON object.
|
||||
- `response.formData(): Promise<FormData>`: Returns a promise that resolves with the response body as a `FormData` object.
|
||||
- `response.bytes(): Promise<Uint8Array>`: Returns a promise that resolves with the response body as a `Uint8Array`.
|
||||
- `response.arrayBuffer(): Promise<ArrayBuffer>`: Returns a promise that resolves with the response body as an `ArrayBuffer`.
|
||||
- `response.blob(): Promise<Blob>`: Returns a promise that resolves with the response body as a `Blob`.
|
||||
|
||||
#### Streaming response bodies
|
||||
|
||||
You can use async iterators to stream the response body.
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com");
|
||||
|
||||
for await (const chunk of response.body) {
|
||||
console.log(chunk);
|
||||
}
|
||||
```
|
||||
|
||||
You can also more directly access the `ReadableStream` object.
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com");
|
||||
|
||||
const stream = response.body;
|
||||
|
||||
const reader = stream.getReader();
|
||||
const { value, done } = await reader.read();
|
||||
```
|
||||
|
||||
### Fetching a URL with a timeout
|
||||
|
||||
To fetch a URL with a timeout, use `AbortSignal.timeout`:
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
signal: AbortSignal.timeout(1000),
|
||||
});
|
||||
```
|
||||
|
||||
#### Canceling a request
|
||||
|
||||
To cancel a request, use an `AbortController`:
|
||||
|
||||
```ts
|
||||
const controller = new AbortController();
|
||||
|
||||
const response = await fetch("http://example.com", {
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
controller.abort();
|
||||
```
|
||||
|
||||
### Unix domain sockets
|
||||
|
||||
To fetch a URL using a Unix domain socket, use the `unix: string` option:
|
||||
|
||||
```ts
|
||||
const response = await fetch("https://hostname/a/path", {
|
||||
unix: "/var/run/path/to/unix.sock",
|
||||
method: "POST",
|
||||
body: JSON.stringify({ message: "Hello from Bun!" }),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### TLS
|
||||
|
||||
To use a client certificate, use the `tls` option:
|
||||
|
||||
```ts
|
||||
await fetch("https://example.com", {
|
||||
tls: {
|
||||
key: Bun.file("/path/to/key.pem"),
|
||||
cert: Bun.file("/path/to/cert.pem"),
|
||||
// ca: [Bun.file("/path/to/ca.pem")],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
#### Custom TLS Validation
|
||||
|
||||
To customize the TLS validation, use the `checkServerIdentity` option in `tls`
|
||||
|
||||
```ts
|
||||
await fetch("https://example.com", {
|
||||
tls: {
|
||||
checkServerIdentity: (hostname, peerCertificate) => {
|
||||
// Return an error if the certificate is invalid
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This is similar to how it works in Node's `net` module.
|
||||
|
||||
## Debugging
|
||||
|
||||
To help with debugging, you can pass `verbose: true` to `fetch`:
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
verbose: true,
|
||||
});
|
||||
```
|
||||
|
||||
This will print the request and response headers to your terminal:
|
||||
|
||||
```sh
|
||||
[fetch] > HTTP/1.1 GET http://example.com/
|
||||
[fetch] > Connection: keep-alive
|
||||
[fetch] > User-Agent: Bun/1.1.21
|
||||
[fetch] > Accept: */*
|
||||
[fetch] > Host: example.com
|
||||
[fetch] > Accept-Encoding: gzip, deflate, br
|
||||
|
||||
[fetch] < 200 OK
|
||||
[fetch] < Content-Encoding: gzip
|
||||
[fetch] < Age: 201555
|
||||
[fetch] < Cache-Control: max-age=604800
|
||||
[fetch] < Content-Type: text/html; charset=UTF-8
|
||||
[fetch] < Date: Sun, 21 Jul 2024 02:41:14 GMT
|
||||
[fetch] < Etag: "3147526947+gzip"
|
||||
[fetch] < Expires: Sun, 28 Jul 2024 02:41:14 GMT
|
||||
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
|
||||
[fetch] < Server: ECAcc (sac/254F)
|
||||
[fetch] < Vary: Accept-Encoding
|
||||
[fetch] < X-Cache: HIT
|
||||
[fetch] < Content-Length: 648
|
||||
```
|
||||
|
||||
Note: `verbose: boolean` is not part of the Web standard `fetch` API and is specific to Bun.
|
||||
|
||||
## Performance
|
||||
|
||||
Before an HTTP request can be sent, the DNS lookup must be performed. This can take a significant amount of time, especially if the DNS server is slow or the network connection is poor.
|
||||
|
||||
After the DNS lookup, the TCP socket must be connected and the TLS handshake might need to be performed. This can also take a significant amount of time.
|
||||
|
||||
After the request completes, consuming the response body can also take a significant amount of time and memory.
|
||||
|
||||
At every step of the way, Bun provides APIs to help you optimize the performance of your application.
|
||||
|
||||
### DNS prefetching
|
||||
|
||||
To prefetch a DNS entry, you can use the `dns.prefetch` API. This API is useful when you know you'll need to connect to a host soon and want to avoid the initial DNS lookup.
|
||||
|
||||
```ts
|
||||
import { dns } from "bun";
|
||||
|
||||
dns.prefetch("bun.sh", 443);
|
||||
```
|
||||
|
||||
#### DNS caching
|
||||
|
||||
By default, Bun caches and deduplicates DNS queries in-memory for up to 30 seconds. You can see the cache stats by calling `dns.getCacheStats()`:
|
||||
|
||||
To learn more about DNS caching in Bun, see the [DNS caching](/docs/api/dns) documentation.
|
||||
|
||||
### Preconnect to a host
|
||||
|
||||
To preconnect to a host, you can use the `fetch.preconnect` API. This API is useful when you know you'll need to connect to a host soon and want to start the initial DNS lookup, TCP socket connection, and TLS handshake early.
|
||||
|
||||
```ts
|
||||
import { fetch } from "bun";
|
||||
|
||||
fetch.preconnect("https://bun.sh");
|
||||
```
|
||||
|
||||
Note: calling `fetch` immediately after `fetch.preconnect` will not make your request faster. Preconnecting only helps if you know you'll need to connect to a host soon, but you're not ready to make the request yet.
|
||||
|
||||
#### Preconnect at startup
|
||||
|
||||
To preconnect to a host at startup, you can pass `--fetch-preconnect`:
|
||||
|
||||
```sh
|
||||
$ bun --fetch-preconnect https://bun.sh ./my-script.ts
|
||||
```
|
||||
|
||||
This is sort of like `<link rel="preconnect">` in HTML.
|
||||
|
||||
This feature is not implemented on Windows yet. If you're interested in using this feature on Windows, please file an issue and we can implement support for it on Windows.
|
||||
|
||||
### Connection pooling & HTTP keep-alive
|
||||
|
||||
Bun automatically reuses connections to the same host. This is known as connection pooling. This can significantly reduce the time it takes to establish a connection. You don't need to do anything to enable this; it's automatic.
|
||||
|
||||
#### Simultaneous connection limit
|
||||
|
||||
By default, Bun limits the maximum number of simultaneous `fetch` requests to 256. We do this for several reasons:
|
||||
|
||||
- It improves overall system stability. Operating systems have an upper limit on the number of simultaneous open TCP sockets, usually in the low thousands. Nearing this limit causes your entire computer to behave strangely. Applications hang and crash.
|
||||
- It encourages HTTP Keep-Alive connection reuse. For short-lived HTTP requests, the slowest step is often the initial connection setup. Reusing connections can save a lot of time.
|
||||
|
||||
When the limit is exceeded, the requests are queued and sent as soon as the next request ends.
|
||||
|
||||
You can increase the maximum number of simultaneous connections via the `BUN_CONFIG_MAX_HTTP_REQUESTS` environment variable:
|
||||
|
||||
```sh
|
||||
$ BUN_CONFIG_MAX_HTTP_REQUESTS=512 bun ./my-script.ts
|
||||
```
|
||||
|
||||
The max value for this limit is currently set to 65,336. The maximum port number is 65,535, so it's quite difficult for any one computer to exceed this limit.
|
||||
|
||||
### Response buffering
|
||||
|
||||
Bun goes to great lengths to optimize the performance of reading the response body. The fastest way to read the response body is to use one of these methods:
|
||||
|
||||
- `response.text(): Promise<string>`
|
||||
- `response.json(): Promise<any>`
|
||||
- `response.formData(): Promise<FormData>`
|
||||
- `response.bytes(): Promise<Uint8Array>`
|
||||
- `response.arrayBuffer(): Promise<ArrayBuffer>`
|
||||
- `response.blob(): Promise<Blob>`
|
||||
|
||||
You can also use `Bun.write` to write the response body to a file on disk:
|
||||
|
||||
```ts
|
||||
import { write } from "bun";
|
||||
|
||||
await write("output.txt", response);
|
||||
```
|
||||
@@ -756,25 +756,6 @@ $ bun build ./index.tsx --outdir ./out --external '*'
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `packages`
|
||||
|
||||
Control whatever package dependencies are included to bundle or not. Possible values: `bundle` (default), `external`. Bun threats any import which path do not start with `.`, `..` or `/` as package.
|
||||
|
||||
{% codetabs group="a" %}
|
||||
|
||||
```ts#JavaScript
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.ts'],
|
||||
packages: 'external',
|
||||
})
|
||||
```
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.ts --packages external
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `naming`
|
||||
|
||||
Customizes the generated file names. Defaults to `./[dir]/[name].[ext]`.
|
||||
|
||||
@@ -94,8 +94,8 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
|
||||
---
|
||||
|
||||
- `--packages`
|
||||
- `--packages`
|
||||
- No differences
|
||||
- n/a
|
||||
- Not supported
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -35,10 +35,6 @@ $ bun add --optional lodash
|
||||
|
||||
## `--exact`
|
||||
|
||||
{% callout %}
|
||||
**Alias** — `-E`
|
||||
{% /callout %}
|
||||
|
||||
To add a package and pin to the resolved version, use `--exact`. This will resolve the version of the package and add it to your `package.json` with an exact version number instead of a version range.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -69,7 +69,7 @@ export const movies = sqliteTable("movies", {
|
||||
We can use the `drizzle-kit` CLI to generate an initial SQL migration.
|
||||
|
||||
```sh
|
||||
$ bunx drizzle-kit generate --dialect sqlite --schema ./schema.ts
|
||||
$ bunx drizzle-kit generate:sqlite --schema ./schema.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -13,7 +13,7 @@ console.log(Bun.argv);
|
||||
Running this file with arguments results in the following:
|
||||
|
||||
```sh
|
||||
$ bun run cli.ts --flag1 --flag2 value
|
||||
$ bun run cli.tsx --flag1 --flag2 value
|
||||
[ '/path/to/bun', '/path/to/cli.ts', '--flag1', '--flag2', 'value' ]
|
||||
```
|
||||
|
||||
@@ -47,7 +47,7 @@ console.log(positionals);
|
||||
then it outputs
|
||||
|
||||
```
|
||||
$ bun run cli.ts --flag1 --flag2 value
|
||||
$ bun run cli.tsx --flag1 --flag2 value
|
||||
{
|
||||
flag1: true,
|
||||
flag2: "value",
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
steps:
|
||||
# ...
|
||||
- uses: actions/checkout@v4
|
||||
+ - uses: oven-sh/setup-bun@v2
|
||||
+ - uses: oven-sh/setup-bun@v1
|
||||
|
||||
# run any `bun` or `bunx` command
|
||||
+ - run: bun install
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# ...
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
+ with:
|
||||
+ bun-version: 1.0.11 # or "latest", "canary", <sha>
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
All packages downloaded from the registry are stored in a global cache at `~/.bun/install/cache`. They are stored in subdirectories named like `${name}@${version}`, so multiple versions of a package can be cached.
|
||||
|
||||
{% details summary="Configuring cache behavior (bunfig.toml)" %}
|
||||
{% details summary="Configuring cache behavior" (bunfig.toml) %}
|
||||
|
||||
```toml
|
||||
[install.cache]
|
||||
@@ -15,6 +15,8 @@ disable = false
|
||||
disableManifest = false
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Minimizing re-downloads
|
||||
|
||||
Bun strives to avoid re-downloading packages multiple times. When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun will use the cached package instead of downloading it again.
|
||||
|
||||
@@ -2,7 +2,7 @@ Bun supports loading configuration options from [`.npmrc`](https://docs.npmjs.co
|
||||
|
||||
{% callout %}
|
||||
|
||||
**NOTE**: We recommend migrating your `.npmrc` file to Bun's [`bunfig.toml`](/docs/runtime/bunfig) format, as it provides more flexible options and can let you configure Bun-specific options.
|
||||
**NOTE**: We recommend migrating your `.npmrc` file to Bun's [`bunfig.toml`](/docs/runtime/bunfig) format, as it provides more flexible options and can let you configure Bun-specific configuration options.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
@@ -50,22 +50,16 @@ Allows you to set options for a specific registry:
|
||||
|
||||
|
||||
# or you could set a username and password
|
||||
# note that the password is base64 encoded
|
||||
//http://localhost:4873/:username=myusername
|
||||
|
||||
//http://localhost:4873/:_password=${NPM_PASSWORD}
|
||||
|
||||
# or use _auth, which is your username and password
|
||||
# combined into a single string, which is then base 64 encoded
|
||||
//http://localhost:4873/:_auth=${NPM_AUTH}
|
||||
```
|
||||
|
||||
The following options are supported:
|
||||
|
||||
- `_authToken`
|
||||
- `username`
|
||||
- `_password` (base64 encoded password)
|
||||
- `_auth` (base64 encoded username:password, e.g. `btoa(username + ":" + password)`)
|
||||
- `_password`
|
||||
|
||||
The equivalent `bunfig.toml` option is to add a key in [`install.scopes`](/docs/runtime/bunfig#install-registry):
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ $ docker pull oven/bun
|
||||
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
|
||||
```
|
||||
|
||||
```bash#Proto
|
||||
$ proto install bun
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### Windows
|
||||
@@ -142,6 +146,7 @@ $ bun upgrade
|
||||
|
||||
**Scoop users** — To avoid conflicts with Scoop, use `scoop update bun` instead.
|
||||
|
||||
**proto users** - Use `proto install bun --pin` instead.
|
||||
{% /callout %}
|
||||
|
||||
## Canary builds
|
||||
@@ -286,4 +291,8 @@ $ npm uninstall -g bun
|
||||
$ brew uninstall bun
|
||||
```
|
||||
|
||||
```bash#Proto
|
||||
$ proto uninstall bun
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
@@ -287,11 +287,8 @@ export default {
|
||||
|
||||
divider("API"),
|
||||
page("api/http", "HTTP server", {
|
||||
description: `Bun implements a fast HTTP server built on Request/Response objects, along with supporting node:http APIs.`,
|
||||
description: `Bun implements Web-standard fetch, plus a Bun-native API for building fast HTTP servers.`,
|
||||
}), // "`Bun.serve`"),
|
||||
page("api/fetch", "HTTP client", {
|
||||
description: `Bun implements Web-standard fetch with some Bun-native extensions.`,
|
||||
}), // "fetch"),
|
||||
page("api/websockets", "WebSockets", {
|
||||
description: `Bun supports server-side WebSockets with on-the-fly compression, TLS support, and a Bun-native pubsub API.`,
|
||||
}), // "`Bun.serve`"),
|
||||
|
||||
@@ -60,7 +60,7 @@ Visual Studio can be installed graphically using the wizard or through WinGet:
|
||||
|
||||
After Visual Studio, you need the following:
|
||||
|
||||
- LLVM 18.1.8
|
||||
- LLVM 16
|
||||
- Go
|
||||
- Rust
|
||||
- NASM
|
||||
@@ -78,14 +78,14 @@ 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
|
||||
> winget install -i LLVM.LLVM -v 16.0.6 && 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
|
||||
# scoop seems to be buggy if you install llvm and the rest at the same time
|
||||
> scoop install llvm@18.1.8
|
||||
> scoop install llvm@16.0.6
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
@@ -179,7 +179,7 @@ These environment variables are read by Bun and configure aspects of its behavio
|
||||
---
|
||||
|
||||
- `BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD`
|
||||
- If `BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD=true`, then `bun --watch` will not clear the console on reload
|
||||
- If `BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD=1`, then `bun --watch` will not clear the console on reload
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -48,6 +48,14 @@ In this case, we are importing from `./hello`, a relative path with no extension
|
||||
- `./hello/index.cjs`
|
||||
- `./hello/index.json`
|
||||
|
||||
Import paths are case-insensitive, meaning these are all valid imports:
|
||||
|
||||
```ts#index.ts
|
||||
import { hello } from "./hello";
|
||||
import { hello } from "./HELLO";
|
||||
import { hello } from "./hElLo";
|
||||
```
|
||||
|
||||
Import paths can optionally include extensions. If an extension is present, Bun will only check for a file with that exact extension.
|
||||
|
||||
```ts#index.ts
|
||||
|
||||
@@ -196,41 +196,3 @@ As of Bun v1.0.19, Bun automatically resolves the `specifier` argument to `mock.
|
||||
After resolution, the mocked module is stored in the ES Module registry **and** the CommonJS require cache. This means that you can use `import` and `require` interchangeably for mocked modules.
|
||||
|
||||
The callback function is called lazily, only if the module is imported or required. This means that you can use `mock.module()` to mock modules that don't exist yet, and it means that you can use `mock.module()` to mock modules that are imported by other modules.
|
||||
|
||||
## Restore all function mocks to their original values with `mock.restore()`
|
||||
|
||||
Instead of manually restoring each mock individually with `mockFn.mockRestore()`, restore all mocks with one command by calling `mock.restore()`. Doing so does not reset the value of modules overridden with `mock.module()`.
|
||||
|
||||
Using `mock.restore()` can reduce the amount of code in your tests by adding it to `afterEach` blocks in each test file or even in your [test preload code](https://bun.sh/docs/runtime/bunfig#test-preload).
|
||||
|
||||
```ts
|
||||
import { expect, mock, spyOn, test } from "bun:test";
|
||||
|
||||
import * as fooModule from './foo.ts';
|
||||
import * as barModule from './bar.ts';
|
||||
import * as bazModule from './baz.ts';
|
||||
|
||||
test('foo, bar, baz', () => {
|
||||
const fooSpy = spyOn(fooModule, 'foo');
|
||||
const barSpy = spyOn(barModule, 'bar');
|
||||
const bazSpy = spyOn(bazModule, 'baz');
|
||||
|
||||
expect(fooSpy).toBe('foo');
|
||||
expect(barSpy).toBe('bar');
|
||||
expect(bazSpy).toBe('baz');
|
||||
|
||||
fooSpy.mockImplementation(() => 42);
|
||||
barSpy.mockImplementation(() => 43);
|
||||
bazSpy.mockImplementation(() => 44);
|
||||
|
||||
expect(fooSpy).toBe(42);
|
||||
expect(barSpy).toBe(43);
|
||||
expect(bazSpy).toBe(44);
|
||||
|
||||
mock.restore();
|
||||
|
||||
expect(fooSpy).toBe('foo');
|
||||
expect(barSpy).toBe('bar');
|
||||
expect(bazSpy).toBe('baz');
|
||||
});
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"workspaces": [
|
||||
"./packages/bun-types"
|
||||
],
|
||||
"devDependencies": {
|
||||
"dependencies": {
|
||||
"@vscode/debugadapter": "^1.65.0",
|
||||
"esbuild": "^0.21.4",
|
||||
"eslint": "^9.4.0",
|
||||
@@ -15,7 +15,9 @@
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"source-map-js": "^1.2.0",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.1.3",
|
||||
"@types/react": "^18.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||
@@ -44,7 +46,6 @@
|
||||
"lint:fix": "eslint './**/*.d.ts' --cache --fix",
|
||||
"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-check": ".cache/zig/zig.exe build check --summary new",
|
||||
"zig-check-all": ".cache/zig/zig.exe build check-all --summary new",
|
||||
"zig-check-windows": ".cache/zig/zig.exe build check-windows --summary new",
|
||||
|
||||
@@ -5,13 +5,9 @@
|
||||
"std.debug.assert": "Use bun.assert instead",
|
||||
"std.debug.dumpStackTrace": "Use bun.handleErrorReturnTrace or bun.crash_handler.dumpStackTrace instead",
|
||||
"std.debug.print": "Don't let this be committed",
|
||||
"std.mem.indexOfAny(u8": "Use bun.strings.indexOfAny",
|
||||
"std.mem.indexOfAny": "Use bun.strings.indexAny or bun.strings.indexAnyComptime",
|
||||
"undefined != ": "This is by definition Undefined Behavior.",
|
||||
"undefined == ": "This is by definition Undefined Behavior.",
|
||||
"bun.toFD(std.fs.cwd().fd)": "Use bun.FD.cwd()",
|
||||
"std.StringArrayHashMapUnmanaged(": "bun.StringArrayHashMapUnmanaged has a faster `eql`",
|
||||
"std.StringArrayHashMap(": "bun.StringArrayHashMap has a faster `eql`",
|
||||
"std.StringHashMapUnmanaged(": "bun.StringHashMapUnmanaged has a faster `eql`",
|
||||
"std.StringHashMap(": "bun.StringHashMaphas a faster `eql`",
|
||||
"": ""
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ for (const [banned, suggestion] of Object.entries(BANNED)) {
|
||||
if (banned.length === 0) continue;
|
||||
// Run git grep to find occurrences of std.debug.assert in .zig files
|
||||
// .nothrow() is here since git will exit with non-zero if no matches are found.
|
||||
let stdout = await $`git grep -n -F "${banned}" "src/**.zig" | grep -v -F '//' | grep -v -F bench`.nothrow().text();
|
||||
let stdout = await $`git grep -n -F "${banned}" "src/**/**.zig" | grep -v -F '//' | grep -v -F bench`
|
||||
.nothrow()
|
||||
.text();
|
||||
|
||||
stdout = stdout.trim();
|
||||
if (stdout.length === 0) continue;
|
||||
|
||||
@@ -22,10 +22,10 @@ bun upgrade
|
||||
- [Linux, arm64](https://www.npmjs.com/package/@oven/bun-linux-aarch64)
|
||||
- [Linux, x64](https://www.npmjs.com/package/@oven/bun-linux-x64)
|
||||
- [Linux, x64 (without AVX2 instructions)](https://www.npmjs.com/package/@oven/bun-linux-x64-baseline)
|
||||
- [Windows](https://www.npmjs.com/package/@oven/bun-windows-x64)
|
||||
- [Windows (without AVX2 instructions)](https://www.npmjs.com/package/@oven/bun-windows-x64-baseline)
|
||||
- [Windows (using Windows Subsystem for Linux, aka. "WSL")](https://relatablecode.com/how-to-set-up-bun-on-a-windows-machine)
|
||||
|
||||
### Future Platforms
|
||||
|
||||
- [Windows](https://github.com/oven-sh/bun/issues/43)
|
||||
- Unix-like variants such as FreeBSD, OpenBSD, etc.
|
||||
- Android and iOS
|
||||
|
||||
7
packages/bun-types/bun.d.ts
vendored
7
packages/bun-types/bun.d.ts
vendored
@@ -1455,7 +1455,7 @@ declare module "bun" {
|
||||
* ```js
|
||||
* const {imports, exports} = transpiler.scan(`
|
||||
* import {foo} from "baz";
|
||||
* export const hello = "hi!";
|
||||
* const hello = "hi!";
|
||||
* `);
|
||||
*
|
||||
* console.log(imports); // ["baz"]
|
||||
@@ -1516,7 +1516,6 @@ declare module "bun" {
|
||||
plugins?: BunPlugin[];
|
||||
// manifest?: boolean; // whether to return manifest
|
||||
external?: string[];
|
||||
packages?: "bundle" | "external";
|
||||
publicPath?: string;
|
||||
define?: Record<string, string>;
|
||||
// origin?: string; // e.g. http://mydomain.com
|
||||
@@ -3100,10 +3099,6 @@ declare module "bun" {
|
||||
*/
|
||||
function openInEditor(path: string, options?: EditorOptions): void;
|
||||
|
||||
const fetch: typeof globalThis.fetch & {
|
||||
preconnect(url: string): void;
|
||||
};
|
||||
|
||||
interface EditorOptions {
|
||||
editor?: "vscode" | "subl";
|
||||
line?: number;
|
||||
|
||||
54
packages/bun-types/globals.d.ts
vendored
54
packages/bun-types/globals.d.ts
vendored
@@ -907,42 +907,26 @@ declare global {
|
||||
new (): ShadowRealm;
|
||||
};
|
||||
|
||||
interface Fetch {
|
||||
/**
|
||||
* Send a HTTP(s) request
|
||||
*
|
||||
* @param request Request object
|
||||
* @param init A structured value that contains settings for the fetch() request.
|
||||
*
|
||||
* @returns A promise that resolves to {@link Response} object.
|
||||
*/
|
||||
(request: Request, init?: RequestInit): Promise<Response>;
|
||||
/**
|
||||
* Send a HTTP(s) request
|
||||
*
|
||||
* @param request Request object
|
||||
* @param init A structured value that contains settings for the fetch() request.
|
||||
*
|
||||
* @returns A promise that resolves to {@link Response} object.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a HTTP(s) request
|
||||
*
|
||||
* @param url URL string
|
||||
* @param init A structured value that contains settings for the fetch() request.
|
||||
*
|
||||
* @returns A promise that resolves to {@link Response} object.
|
||||
*/
|
||||
(url: string | URL | Request, init?: FetchRequestInit): Promise<Response>;
|
||||
|
||||
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
|
||||
|
||||
/**
|
||||
* Start the DNS resolution, TCP connection, and TLS handshake for a request
|
||||
* before the request is actually sent.
|
||||
*
|
||||
* This can reduce the latency of a request when you know there's some
|
||||
* long-running task that will delay the request starting.
|
||||
*
|
||||
* This is a bun-specific API and is not part of the Fetch API specification.
|
||||
*/
|
||||
preconnect(url: string | URL): void;
|
||||
}
|
||||
|
||||
var fetch: Fetch;
|
||||
// tslint:disable-next-line:unified-signatures
|
||||
function fetch(request: Request, init?: RequestInit): Promise<Response>;
|
||||
/**
|
||||
* Send a HTTP(s) request
|
||||
*
|
||||
* @param url URL string
|
||||
* @param init A structured value that contains settings for the fetch() request.
|
||||
*
|
||||
* @returns A promise that resolves to {@link Response} object.
|
||||
*/
|
||||
function fetch(url: string | URL | Request, init?: FetchRequestInit): Promise<Response>;
|
||||
|
||||
function queueMicrotask(callback: (...args: any[]) => void): void;
|
||||
/**
|
||||
|
||||
35
packages/bun-types/jsc.d.ts
vendored
35
packages/bun-types/jsc.d.ts
vendored
@@ -78,7 +78,21 @@ declare module "bun:jsc" {
|
||||
*/
|
||||
function setTimeZone(timeZone: string): string;
|
||||
|
||||
interface SamplingProfile {
|
||||
/**
|
||||
* Run JavaScriptCore's sampling profiler for a particular function
|
||||
*
|
||||
* This is pretty low-level.
|
||||
*
|
||||
* Things to know:
|
||||
* - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation
|
||||
* - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile
|
||||
* - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile
|
||||
* - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile
|
||||
*/
|
||||
function profile(
|
||||
callback: CallableFunction,
|
||||
sampleInterval?: number,
|
||||
): {
|
||||
/**
|
||||
* A formatted summary of the top functions
|
||||
*
|
||||
@@ -169,24 +183,7 @@ declare module "bun:jsc" {
|
||||
* Stack traces of the top functions
|
||||
*/
|
||||
stackTraces: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run JavaScriptCore's sampling profiler for a particular function
|
||||
*
|
||||
* This is pretty low-level.
|
||||
*
|
||||
* Things to know:
|
||||
* - LLint means "Low Level Interpreter", which is the interpreter that runs before any JIT compilation
|
||||
* - Baseline is the first JIT compilation tier. It's the least optimized, but the fastest to compile
|
||||
* - DFG means "Data Flow Graph", which is the second JIT compilation tier. It has some optimizations, but is slower to compile
|
||||
* - FTL means "Faster Than Light", which is the third JIT compilation tier. It has the most optimizations, but is the slowest to compile
|
||||
*/
|
||||
function profile<T extends (...args: any[]) => any>(
|
||||
callback: T,
|
||||
sampleInterval?: number,
|
||||
...args: Parameters<T>
|
||||
): ReturnType<T> extends Promise<infer U> ? Promise<SamplingProfile> : SamplingProfile;
|
||||
};
|
||||
|
||||
/**
|
||||
* This returns objects which native code has explicitly protected from being
|
||||
|
||||
10
packages/bun-types/sqlite.d.ts
vendored
10
packages/bun-types/sqlite.d.ts
vendored
@@ -36,7 +36,7 @@ declare module "bun:sqlite" {
|
||||
* ```ts
|
||||
* const db = new Database("mydb.sqlite");
|
||||
* db.run("CREATE TABLE foo (bar TEXT)");
|
||||
* db.run("INSERT INTO foo VALUES (?)", ["baz"]);
|
||||
* db.run("INSERT INTO foo VALUES (?)", "baz");
|
||||
* console.log(db.query("SELECT * FROM foo").all());
|
||||
* ```
|
||||
*
|
||||
@@ -47,7 +47,7 @@ declare module "bun:sqlite" {
|
||||
* ```ts
|
||||
* const db = new Database(":memory:");
|
||||
* db.run("CREATE TABLE foo (bar TEXT)");
|
||||
* db.run("INSERT INTO foo VALUES (?)", ["hiiiiii"]);
|
||||
* db.run("INSERT INTO foo VALUES (?)", "hiiiiii");
|
||||
* console.log(db.query("SELECT * FROM foo").all());
|
||||
* ```
|
||||
*
|
||||
@@ -158,7 +158,7 @@ declare module "bun:sqlite" {
|
||||
* @example
|
||||
* ```ts
|
||||
* db.run("CREATE TABLE foo (bar TEXT)");
|
||||
* db.run("INSERT INTO foo VALUES (?)", ["baz"]);
|
||||
* db.run("INSERT INTO foo VALUES (?)", "baz");
|
||||
* ```
|
||||
*
|
||||
* Useful for queries like:
|
||||
@@ -268,9 +268,9 @@ declare module "bun:sqlite" {
|
||||
* @example
|
||||
* ```ts
|
||||
* db.run("CREATE TABLE foo (bar TEXT)");
|
||||
* db.run("INSERT INTO foo VALUES (?)", ["baz"]);
|
||||
* db.run("INSERT INTO foo VALUES (?)", "baz");
|
||||
* db.run("BEGIN");
|
||||
* db.run("INSERT INTO foo VALUES (?)", ["qux"]);
|
||||
* db.run("INSERT INTO foo VALUES (?)", "qux");
|
||||
* console.log(db.inTransaction());
|
||||
* ```
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#define HAS_MSGX
|
||||
#endif
|
||||
|
||||
|
||||
/* We need to emulate sendmmsg, recvmmsg on platform who don't have it */
|
||||
int bsd_sendmmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct udp_sendbuf* sendbuf, int flags) {
|
||||
#if defined(_WIN32)// || defined(__APPLE__)
|
||||
@@ -398,9 +397,7 @@ int bsd_addr_get_port(struct bsd_addr_t *addr) {
|
||||
// called by dispatch_ready_poll
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr) {
|
||||
LIBUS_SOCKET_DESCRIPTOR accepted_fd;
|
||||
|
||||
while (1) {
|
||||
addr->len = sizeof(addr->mem);
|
||||
addr->len = sizeof(addr->mem);
|
||||
|
||||
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
|
||||
// Linux, FreeBSD
|
||||
@@ -408,18 +405,12 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd
|
||||
#else
|
||||
// Windows, OS X
|
||||
accepted_fd = accept(fd, (struct sockaddr *) addr, &addr->len);
|
||||
|
||||
#endif
|
||||
|
||||
if (UNLIKELY(IS_EINTR(accepted_fd))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We cannot rely on addr since it is not initialized if failed */
|
||||
if (accepted_fd == LIBUS_SOCKET_ERROR) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
/* We cannot rely on addr since it is not initialized if failed */
|
||||
if (accepted_fd == LIBUS_SOCKET_ERROR) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
internal_finalize_bsd_addr(addr);
|
||||
@@ -432,22 +423,14 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
|
||||
while (1) {
|
||||
ssize_t ret = recv(fd, buf, length, flags);
|
||||
|
||||
if (UNLIKELY(IS_EINTR(ret))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
|
||||
return recv(fd, buf, length, flags);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/uio.h>
|
||||
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
struct iovec chunks[2];
|
||||
|
||||
chunks[0].iov_base = (char *)header;
|
||||
@@ -455,21 +438,13 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
|
||||
chunks[1].iov_base = (char *)payload;
|
||||
chunks[1].iov_len = payload_length;
|
||||
|
||||
while (1) {
|
||||
ssize_t written = writev(fd, chunks, 2);
|
||||
|
||||
if (UNLIKELY(IS_EINTR(written))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
return writev(fd, chunks, 2);
|
||||
}
|
||||
#else
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
ssize_t written = bsd_send(fd, header, header_length, 0);
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
|
||||
int written = bsd_send(fd, header, header_length, 0);
|
||||
if (written == header_length) {
|
||||
ssize_t second_write = bsd_send(fd, payload, payload_length, 0);
|
||||
int second_write = bsd_send(fd, payload, payload_length, 0);
|
||||
if (second_write > 0) {
|
||||
written += second_write;
|
||||
}
|
||||
@@ -478,28 +453,26 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
|
||||
while (1) {
|
||||
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
|
||||
|
||||
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#ifdef MSG_MORE
|
||||
// for Linux we do not want signals
|
||||
ssize_t rc = send(fd, buf, length, ((msg_more != 0) * MSG_MORE) | MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
#else
|
||||
// use TCP_NOPUSH
|
||||
ssize_t rc = send(fd, buf, length, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
#endif
|
||||
#ifdef MSG_MORE
|
||||
|
||||
if (UNLIKELY(IS_EINTR(rc))) {
|
||||
continue;
|
||||
}
|
||||
// for Linux we do not want signals
|
||||
return send(fd, buf, length, ((msg_more != 0) * MSG_MORE) | MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
|
||||
// use TCP_NOPUSH
|
||||
|
||||
return send(fd, buf, length, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int bsd_would_block() {
|
||||
@@ -510,23 +483,6 @@ int bsd_would_block() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int us_internal_bind_and_listen(LIBUS_SOCKET_DESCRIPTOR listenFd, struct sockaddr *listenAddr, socklen_t listenAddrLength, int backlog) {
|
||||
int result;
|
||||
do
|
||||
result = bind(listenFd, listenAddr, listenAddrLength);
|
||||
while (IS_EINTR(result));
|
||||
|
||||
if (result == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do
|
||||
result = listen(listenFd, backlog);
|
||||
while (IS_EINTR(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline __attribute__((always_inline)) LIBUS_SOCKET_DESCRIPTOR bsd_bind_listen_fd(
|
||||
LIBUS_SOCKET_DESCRIPTOR listenFd,
|
||||
struct addrinfo *listenAddr,
|
||||
@@ -556,7 +512,7 @@ inline __attribute__((always_inline)) LIBUS_SOCKET_DESCRIPTOR bsd_bind_listen_fd
|
||||
setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &disabled, sizeof(disabled));
|
||||
#endif
|
||||
|
||||
if (us_internal_bind_and_listen(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen, 512)) {
|
||||
if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen) || listen(listenFd, 512)) {
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
@@ -734,7 +690,7 @@ static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_listen_socket_unix(const char
|
||||
unlink(path);
|
||||
#endif
|
||||
|
||||
if (us_internal_bind_and_listen(listenFd, (struct sockaddr *) server_address, (socklen_t) addrlen, 512)) {
|
||||
if (bind(listenFd, (struct sockaddr *)server_address, addrlen) || listen(listenFd, 512)) {
|
||||
#if defined(_WIN32)
|
||||
int shouldSimulateENOENT = WSAGetLastError() == WSAENETDOWN;
|
||||
#endif
|
||||
@@ -882,7 +838,7 @@ int bsd_connect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd, const char *host, int por
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return (int)LIBUS_SOCKET_ERROR;
|
||||
return LIBUS_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
|
||||
@@ -969,7 +925,7 @@ static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr,
|
||||
do {
|
||||
errno = 0;
|
||||
r = connect(fd, (struct sockaddr *)addr, namelen);
|
||||
} while (IS_EINTR(r));
|
||||
} while (r == -1 && errno == EINTR);
|
||||
|
||||
// connect() can return -1 with an errno of 0.
|
||||
// the errno is the correct one in that case.
|
||||
|
||||
@@ -1740,20 +1740,15 @@ void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t *s) {
|
||||
loop_ssl_data->ssl_socket = &s->s;
|
||||
|
||||
loop_ssl_data->msg_more = 0;
|
||||
|
||||
// sets SSL_SENT_SHUTDOWN no matter what (not actually true if error!)
|
||||
int ret = SSL_shutdown(s->ssl);
|
||||
if (ret == 0) {
|
||||
ret = SSL_shutdown(s->ssl);
|
||||
}
|
||||
|
||||
if (SSL_in_init(s->ssl) || SSL_get_quiet_shutdown(s->ssl)) {
|
||||
// when SSL_in_init or quiet shutdown in BoringSSL, we call shutdown
|
||||
// directly
|
||||
us_socket_shutdown(0, &s->s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
|
||||
int err = SSL_get_error(s->ssl, ret);
|
||||
if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
|
||||
// clear
|
||||
|
||||
@@ -109,51 +109,6 @@ struct us_loop_t *us_timer_loop(struct us_timer_t *t) {
|
||||
return internal_cb->loop;
|
||||
}
|
||||
|
||||
|
||||
#if defined(LIBUS_USE_EPOLL)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
static int has_epoll_pwait2 = -1;
|
||||
|
||||
#ifndef SYS_epoll_pwait2
|
||||
// It's consistent on multiple architectures
|
||||
// https://github.com/torvalds/linux/blob/9d1ddab261f3e2af7c384dc02238784ce0cf9f98/include/uapi/asm-generic/unistd.h#L795
|
||||
// https://github.com/google/gvisor/blob/master/test/syscalls/linux/epoll.cc#L48C1-L50C7
|
||||
#define SYS_epoll_pwait2 441
|
||||
#endif
|
||||
|
||||
static ssize_t sys_epoll_pwait2(int epfd, struct epoll_event *events, int maxevents, const struct timespec *timeout, const sigset_t *sigmask, size_t sigsetsize) {
|
||||
return syscall(SYS_epoll_pwait2, epfd, events, maxevents, timeout, sigmask, sigsetsize);
|
||||
}
|
||||
|
||||
static int bun_epoll_pwait2(int epfd, struct epoll_event *events, int maxevents, const struct timespec *timeout) {
|
||||
int ret;
|
||||
if (has_epoll_pwait2 != 0) {
|
||||
do {
|
||||
ret = sys_epoll_pwait2(epfd, events, maxevents, timeout, NULL, 0);
|
||||
} while (IS_EINTR(ret));
|
||||
|
||||
if (LIKELY(ret != -1 || errno != ENOSYS)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
has_epoll_pwait2 = 0;
|
||||
}
|
||||
|
||||
int timeoutMs = -1;
|
||||
if (timeout) {
|
||||
timeoutMs = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = epoll_wait(epfd, events, maxevents, timeoutMs);
|
||||
} while (IS_EINTR(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Loop */
|
||||
struct us_loop_t *us_create_loop(void *hint, void (*wakeup_cb)(struct us_loop_t *loop), void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop), unsigned int ext_size) {
|
||||
struct us_loop_t *loop = (struct us_loop_t *) us_calloc(1, sizeof(struct us_loop_t) + ext_size);
|
||||
@@ -184,11 +139,9 @@ void us_loop_run(struct us_loop_t *loop) {
|
||||
|
||||
/* Fetch ready polls */
|
||||
#ifdef LIBUS_USE_EPOLL
|
||||
loop->num_ready_polls = bun_epoll_pwait2(loop->fd, loop->ready_polls, 1024, NULL);
|
||||
loop->num_ready_polls = epoll_wait(loop->fd, loop->ready_polls, 1024, -1);
|
||||
#else
|
||||
do {
|
||||
loop->num_ready_polls = kevent64(loop->fd, NULL, 0, loop->ready_polls, 1024, 0, NULL);
|
||||
} while (IS_EINTR(loop->num_ready_polls));
|
||||
loop->num_ready_polls = kevent64(loop->fd, NULL, 0, loop->ready_polls, 1024, 0, NULL);
|
||||
#endif
|
||||
|
||||
/* Iterate ready polls, dispatching them by type */
|
||||
@@ -230,6 +183,12 @@ void us_loop_run(struct us_loop_t *loop) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(LIBUS_USE_EPOLL)
|
||||
|
||||
// static int has_epoll_pwait2 = 0;
|
||||
// TODO:
|
||||
|
||||
#endif
|
||||
|
||||
void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout) {
|
||||
if (loop->num_polls == 0)
|
||||
@@ -248,12 +207,13 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout
|
||||
|
||||
/* Fetch ready polls */
|
||||
#ifdef LIBUS_USE_EPOLL
|
||||
|
||||
loop->num_ready_polls = bun_epoll_pwait2(loop->fd, loop->ready_polls, 1024, timeout);
|
||||
int timeoutMs = -1;
|
||||
if (timeout) {
|
||||
timeoutMs = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;
|
||||
}
|
||||
loop->num_ready_polls = epoll_wait(loop->fd, loop->ready_polls, 1024, timeoutMs);
|
||||
#else
|
||||
do {
|
||||
loop->num_ready_polls = kevent64(loop->fd, NULL, 0, loop->ready_polls, 1024, 0, timeout);
|
||||
} while (IS_EINTR(loop->num_ready_polls));
|
||||
loop->num_ready_polls = kevent64(loop->fd, NULL, 0, loop->ready_polls, 1024, 0, timeout);
|
||||
#endif
|
||||
|
||||
/* Iterate ready polls, dispatching them by type */
|
||||
@@ -336,10 +296,7 @@ int kqueue_change(int kqfd, int fd, int old_events, int new_events, void *user_d
|
||||
EV_SET64(&change_list[change_length++], fd, EVFILT_WRITE, (new_events & LIBUS_SOCKET_WRITABLE) ? EV_ADD : EV_DELETE, 0, 0, (uint64_t)(void*)user_data, 0, 0);
|
||||
}
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = kevent64(kqfd, change_list, change_length, change_list, change_length, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
} while (IS_EINTR(ret));
|
||||
int ret = kevent64(kqfd, change_list, change_length, change_list, change_length, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
|
||||
// ret should be 0 in most cases (not guaranteed when removing async)
|
||||
|
||||
@@ -375,10 +332,7 @@ void us_poll_start(struct us_poll_t *p, struct us_loop_t *loop, int events) {
|
||||
struct epoll_event event;
|
||||
event.events = events;
|
||||
event.data.ptr = p;
|
||||
int ret;
|
||||
do {
|
||||
ret = epoll_ctl(loop->fd, EPOLL_CTL_ADD, p->state.fd, &event);
|
||||
} while (IS_EINTR(ret));
|
||||
epoll_ctl(loop->fd, EPOLL_CTL_ADD, p->state.fd, &event);
|
||||
#else
|
||||
kqueue_change(loop->fd, p->state.fd, 0, events, p);
|
||||
#endif
|
||||
@@ -394,10 +348,7 @@ void us_poll_change(struct us_poll_t *p, struct us_loop_t *loop, int events) {
|
||||
struct epoll_event event;
|
||||
event.events = events;
|
||||
event.data.ptr = p;
|
||||
int rc;
|
||||
do {
|
||||
rc = epoll_ctl(loop->fd, EPOLL_CTL_MOD, p->state.fd, &event);
|
||||
} while (IS_EINTR(rc));
|
||||
epoll_ctl(loop->fd, EPOLL_CTL_MOD, p->state.fd, &event);
|
||||
#else
|
||||
kqueue_change(loop->fd, p->state.fd, old_events, events, p);
|
||||
#endif
|
||||
@@ -411,10 +362,7 @@ void us_poll_stop(struct us_poll_t *p, struct us_loop_t *loop) {
|
||||
int new_events = 0;
|
||||
#ifdef LIBUS_USE_EPOLL
|
||||
struct epoll_event event;
|
||||
int rc;
|
||||
do {
|
||||
rc = epoll_ctl(loop->fd, EPOLL_CTL_DEL, p->state.fd, &event);
|
||||
} while (IS_EINTR(rc));
|
||||
epoll_ctl(loop->fd, EPOLL_CTL_DEL, p->state.fd, &event);
|
||||
#else
|
||||
if (old_events) {
|
||||
kqueue_change(loop->fd, p->state.fd, old_events, new_events, NULL);
|
||||
@@ -425,14 +373,12 @@ void us_poll_stop(struct us_poll_t *p, struct us_loop_t *loop) {
|
||||
us_internal_loop_update_pending_ready_polls(loop, p, 0, old_events, new_events);
|
||||
}
|
||||
|
||||
size_t us_internal_accept_poll_event(struct us_poll_t *p) {
|
||||
unsigned int us_internal_accept_poll_event(struct us_poll_t *p) {
|
||||
#ifdef LIBUS_USE_EPOLL
|
||||
int fd = us_poll_fd(p);
|
||||
uint64_t buf;
|
||||
ssize_t read_length = 0;
|
||||
do {
|
||||
read_length = read(fd, &buf, 8);
|
||||
} while (IS_EINTR(read_length));
|
||||
int read_length = read(fd, &buf, 8);
|
||||
(void)read_length;
|
||||
return buf;
|
||||
#else
|
||||
/* Kqueue has no underlying FD for timers or user events */
|
||||
@@ -521,11 +467,7 @@ void us_timer_close(struct us_timer_t *timer, int fallthrough) {
|
||||
|
||||
struct kevent64_s event;
|
||||
EV_SET64(&event, (uint64_t) (void*) internal_cb, EVFILT_TIMER, EV_DELETE, 0, 0, (uint64_t)internal_cb, 0, 0);
|
||||
int ret;
|
||||
do {
|
||||
ret = kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
} while (IS_EINTR(ret));
|
||||
|
||||
kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
|
||||
/* (regular) sockets are the only polls which are not freed immediately */
|
||||
if(fallthrough){
|
||||
@@ -544,11 +486,7 @@ void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms
|
||||
struct kevent64_s event;
|
||||
uint64_t ptr = (uint64_t)(void*)internal_cb;
|
||||
EV_SET64(&event, ptr, EVFILT_TIMER, EV_ADD | (repeat_ms ? 0 : EV_ONESHOT), 0, ms, (uint64_t)internal_cb, 0, 0);
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
} while (IS_EINTR(ret));
|
||||
kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -643,11 +581,7 @@ void us_internal_async_close(struct us_internal_async *a) {
|
||||
struct kevent64_s event;
|
||||
uint64_t ptr = (uint64_t)(void*)internal_cb;
|
||||
EV_SET64(&event, ptr, EVFILT_MACHPORT, EV_DELETE, 0, 0, (uint64_t)(void*)internal_cb, 0,0);
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
} while (IS_EINTR(ret));
|
||||
kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), internal_cb->port);
|
||||
us_free(internal_cb->machport_buf);
|
||||
@@ -675,10 +609,7 @@ void us_internal_async_set(struct us_internal_async *a, void (*cb)(struct us_int
|
||||
event.ext[1] = MACHPORT_BUF_LEN;
|
||||
event.udata = (uint64_t)(void*)internal_cb;
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
} while (IS_EINTR(ret));
|
||||
int ret = kevent64(internal_cb->loop->fd, &event, 1, &event, 1, KEVENT_FLAG_ERROR_EVENTS, NULL);
|
||||
|
||||
if (UNLIKELY(ret == -1)) {
|
||||
abort();
|
||||
|
||||
@@ -125,7 +125,7 @@ int us_poll_events(struct us_poll_t *p) {
|
||||
((p->poll_type & POLL_TYPE_POLLING_OUT) ? LIBUS_SOCKET_WRITABLE : 0);
|
||||
}
|
||||
|
||||
size_t us_internal_accept_poll_event(struct us_poll_t *p) { return 0; }
|
||||
unsigned int 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; }
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef INTERNAL_H
|
||||
#define INTERNAL_H
|
||||
|
||||
@@ -22,10 +22,6 @@
|
||||
#ifndef __cplusplus
|
||||
#define alignas(x) __declspec(align(x))
|
||||
#endif
|
||||
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
|
||||
#else
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
@@ -56,17 +52,6 @@ void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop,
|
||||
#include "internal/eventing/libuv.h"
|
||||
#endif
|
||||
|
||||
#ifndef LIKELY
|
||||
#define LIKELY(cond) __builtin_expect((_Bool)(cond), 1)
|
||||
#define UNLIKELY(cond) __builtin_expect((_Bool)(cond), 0)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_EINTR(rc) (rc == SOCKET_ERROR && WSAGetLastError() == WSAEINTR)
|
||||
#else
|
||||
#define IS_EINTR(rc) (rc == -1 && errno == EINTR)
|
||||
#endif
|
||||
|
||||
/* Poll type and what it polls for */
|
||||
enum {
|
||||
/* Three first bits */
|
||||
@@ -133,7 +118,7 @@ void us_internal_async_set(struct us_internal_async *a,
|
||||
void us_internal_async_wakeup(struct us_internal_async *a);
|
||||
|
||||
/* Eventing related */
|
||||
size_t us_internal_accept_poll_event(struct us_poll_t *p);
|
||||
unsigned int us_internal_accept_poll_event(struct us_poll_t *p);
|
||||
int us_internal_poll_type(struct us_poll_t *p);
|
||||
void us_internal_poll_set_type(struct us_poll_t *p, int poll_type);
|
||||
|
||||
|
||||
@@ -134,9 +134,9 @@ int bsd_addr_get_port(struct bsd_addr_t *addr);
|
||||
// called by dispatch_ready_poll
|
||||
LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr);
|
||||
|
||||
ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
|
||||
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
|
||||
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
|
||||
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
|
||||
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
|
||||
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
|
||||
int bsd_would_block();
|
||||
|
||||
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
|
||||
|
||||
@@ -75,6 +75,14 @@ public:
|
||||
void writeMark() {
|
||||
/* Date is always written */
|
||||
writeHeader("Date", std::string_view(((LoopData *) us_loop_ext(us_socket_context_loop(SSL, (us_socket_context(SSL, (us_socket_t *) this)))))->date, 29));
|
||||
|
||||
/* You can disable this altogether */
|
||||
// #ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
|
||||
// if (!Super::getLoopData()->noMark) {
|
||||
// /* We only expose major version */
|
||||
// writeHeader("uWebSockets", "20");
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
|
||||
/* Returns true on success, indicating that it might be feasible to write more data.
|
||||
@@ -580,19 +588,7 @@ public:
|
||||
httpResponseData->onAborted = std::move(handler);
|
||||
return this;
|
||||
}
|
||||
HttpResponse* clearOnWritableAndAborted() {
|
||||
HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
|
||||
|
||||
httpResponseData->onWritable = nullptr;
|
||||
httpResponseData->onAborted = nullptr;
|
||||
return this;
|
||||
}
|
||||
HttpResponse* clearOnAborted() {
|
||||
HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
|
||||
|
||||
httpResponseData->onAborted = nullptr;
|
||||
return this;
|
||||
}
|
||||
/* Attach a read handler for data sent. Will be called with FIN set true if last segment. */
|
||||
void onData(MoveOnlyFunction<void(std::string_view, bool)> &&handler) {
|
||||
HttpResponseData<SSL> *data = getHttpResponseData();
|
||||
|
||||
@@ -95,14 +95,13 @@ private:
|
||||
// This is both a performance thing, and also to prevent freeing some things which are not meant to be freed
|
||||
// such as uv_tty_t
|
||||
if(loop && cleanMe && !bun_is_exiting()) {
|
||||
cleanMe = false;
|
||||
loop->free();
|
||||
}
|
||||
}
|
||||
Loop *loop = nullptr;
|
||||
bool cleanMe = false;
|
||||
};
|
||||
|
||||
|
||||
static LoopCleaner &getLazyLoop() {
|
||||
static thread_local LoopCleaner lazyLoop;
|
||||
return lazyLoop;
|
||||
@@ -127,12 +126,6 @@ public:
|
||||
return getLazyLoop().loop;
|
||||
}
|
||||
|
||||
static void clearLoopAtThreadExit() {
|
||||
if (getLazyLoop().cleanMe) {
|
||||
getLazyLoop().loop->free();
|
||||
}
|
||||
}
|
||||
|
||||
/* Freeing the default loop should be done once */
|
||||
void free() {
|
||||
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
|
||||
|
||||
@@ -6,7 +6,7 @@ cd $BUN_DEPS_DIR/boringssl
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
cmake "${CMAKE_FLAGS[@]}" -GNinja ..
|
||||
cmake "${CMAKE_FLAGS[@]}" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -GNinja ..
|
||||
ninja libcrypto.a libssl.a libdecrepit.a
|
||||
|
||||
cp **/libcrypto.a $BUN_DEPS_OUT_DIR/libcrypto.a
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -exo pipefail
|
||||
|
||||
export FORCE_PIC=1
|
||||
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
|
||||
|
||||
cd $BUN_DEPS_DIR/c-ares
|
||||
|
||||
rm -rf build CMakeCache.txt CMakeFiles
|
||||
rm -rf build
|
||||
mkdir -p build
|
||||
|
||||
cd build
|
||||
@@ -14,9 +12,8 @@ cd build
|
||||
cmake "${CMAKE_FLAGS[@]}" .. \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DCARES_STATIC=ON \
|
||||
-DCARES_STATIC_PIC=OFF \
|
||||
-DCARES_STATIC_PIC=ON \
|
||||
-DCARES_SHARED=OFF \
|
||||
-DCARES_BUILD_TOOLS=ON \
|
||||
-G "Ninja"
|
||||
|
||||
ninja
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -exo pipefail
|
||||
export FORCE_PIC=1
|
||||
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
|
||||
|
||||
mkdir -p $BUN_DEPS_OUT_DIR
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
set -exo pipefail
|
||||
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
|
||||
|
||||
rm -rf CMakeFiles CMakeCache build.ninja
|
||||
mkdir -p $BUN_DEPS_OUT_DIR
|
||||
|
||||
cd $BUN_DEPS_DIR/ls-hpack
|
||||
|
||||
|
||||
rm -rf CMakeCache* CMakeFiles
|
||||
|
||||
cmake "${CMAKE_FLAGS[@]}" . \
|
||||
@@ -15,6 +15,6 @@ cmake "${CMAKE_FLAGS[@]}" . \
|
||||
-DSHARED=0 \
|
||||
-GNinja
|
||||
|
||||
ninja libls-hpack.a
|
||||
ninja
|
||||
|
||||
cp ./libls-hpack.a $BUN_DEPS_OUT_DIR/liblshpack.a
|
||||
|
||||
@@ -22,7 +22,8 @@ try {
|
||||
|
||||
$Baseline = $env:BUN_DEV_ENV_SET -eq "Baseline=True"
|
||||
|
||||
Run clang-cl @($env:CFLAGS -split ' ') libtcc.c -o tcc.obj "-DTCC_TARGET_PE" "-DTCC_TARGET_X86_64" "-O2" "-W2" "-Zi" "-MD" "-GS-" "-c" "-MT"
|
||||
# TODO: -MT
|
||||
Run clang-cl @($env:CFLAGS -split ' ') libtcc.c -o tcc.obj "-DTCC_TARGET_PE" "-DTCC_TARGET_X86_64" "-O2" "-W2" "-Zi" "-MD" "-GS-" "-c"
|
||||
Run llvm-lib "tcc.obj" "-OUT:tcc.lib"
|
||||
|
||||
Copy-Item tcc.obj $BUN_DEPS_OUT_DIR/tcc.lib
|
||||
|
||||
@@ -4,9 +4,10 @@ source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
|
||||
|
||||
mkdir -p $BUN_DEPS_OUT_DIR
|
||||
cd $BUN_DEPS_DIR/zlib
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake $CMAKE_FLAGS -G Ninja -DCMAKE_BUILD_TYPE=Release ..
|
||||
ninja
|
||||
export CFLAGS="-O3"
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
||||
fi
|
||||
CFLAGS="${CFLAGS}" ./configure --static
|
||||
make -j${CPUS}
|
||||
cp ./libz.a $BUN_DEPS_OUT_DIR/libz.a
|
||||
|
||||
@@ -3,10 +3,9 @@ $ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pip
|
||||
|
||||
Push-Location (Join-Path $BUN_DEPS_DIR 'zstd')
|
||||
try {
|
||||
Remove-Item CMakeCache.txt, CMakeFiles -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item CMakeCache.txt -ErrorAction SilentlyContinue
|
||||
|
||||
# CL_SHOWINCLUDES_PREFIX is workaround for cmake bug in 3.28. .ninja_deps still needs to be deleted. Bug is fixed in 3.30
|
||||
Run cmake -S "build/cmake" @CMAKE_FLAGS -DZSTD_BUILD_STATIC=ON -DCMAKE_CL_SHOWINCLUDES_PREFIX="Note: including file:"
|
||||
Run cmake -S "build/cmake" @CMAKE_FLAGS -DZSTD_BUILD_STATIC=ON
|
||||
Run cmake --build . --clean-first --config Release
|
||||
|
||||
Copy-Item lib/zstd_static.lib $BUN_DEPS_OUT_DIR/zstd.lib
|
||||
|
||||
@@ -7,5 +7,5 @@ mkdir -p $BUN_DEPS_OUT_DIR
|
||||
cd $BUN_DEPS_DIR/zstd
|
||||
rm -rf Release CMakeCache.txt CMakeFiles
|
||||
cmake "${CMAKE_FLAGS[@]}" -DZSTD_BUILD_STATIC=ON -B Release -S build/cmake -G Ninja
|
||||
ninja libzstd_static -C Release
|
||||
ninja -C Release
|
||||
cp Release/lib/libzstd.a $BUN_DEPS_OUT_DIR/libzstd.a
|
||||
|
||||
1415
scripts/build.sh
1415
scripts/build.sh
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,9 @@ if ($env:VSINSTALLDIR -eq $null) {
|
||||
}
|
||||
Push-Location $vsDir
|
||||
try {
|
||||
Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll'
|
||||
Enter-VsDevShell -VsInstallPath 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools' -DevCmdArguments '-arch=x64 -host_arch=x64'
|
||||
} catch {
|
||||
$launchps = (Join-Path -Path $vsDir -ChildPath "Common7\Tools\Launch-VsDevShell.ps1")
|
||||
. $launchps -Arch amd64 -HostArch amd64
|
||||
} finally { Pop-Location }
|
||||
@@ -49,13 +52,10 @@ $CPUS = if ($env:CPUS) { $env:CPUS } else { (Get-CimInstance -Class Win32_Proces
|
||||
$CC = "clang-cl"
|
||||
$CXX = "clang-cl"
|
||||
|
||||
$CFLAGS = '/O2 /Z7 /MT /O2 /Ob2 /DNDEBUG /U_DLL'
|
||||
$CXXFLAGS = '/O2 /Z7 /MT /O2 /Ob2 /DNDEBUG /U_DLL'
|
||||
|
||||
if ($env:USE_LTO -eq "1") {
|
||||
$CXXFLAGS += " -fuse-ld=lld -flto -Xclang -emit-llvm-bc"
|
||||
$CFLAGS += " -fuse-ld=lld -flto -Xclang -emit-llvm-bc"
|
||||
}
|
||||
$CFLAGS = '/O2 /Zi'
|
||||
# $CFLAGS = '/O2 /Z7 /MT'
|
||||
$CXXFLAGS = '/O2 /Zi'
|
||||
# $CXXFLAGS = '/O2 /Z7 /MT'
|
||||
|
||||
$CPU_NAME = if ($Baseline) { "nehalem" } else { "haswell" };
|
||||
$env:CPU_TARGET = $CPU_NAME
|
||||
@@ -69,20 +69,8 @@ $CMAKE_FLAGS = @(
|
||||
"-DCMAKE_C_COMPILER=$CC",
|
||||
"-DCMAKE_CXX_COMPILER=$CXX",
|
||||
"-DCMAKE_C_FLAGS=$CFLAGS",
|
||||
"-DCMAKE_CXX_FLAGS=$CXXFLAGS",
|
||||
"-DCMAKE_C_FLAGS_RELEASE=$CFLAGS",
|
||||
"-DCMAKE_CXX_FLAGS_RELEASE=$CXXFLAGS",
|
||||
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded"
|
||||
"-DCMAKE_CXX_FLAGS=$CXXFLAGS"
|
||||
)
|
||||
|
||||
if ($env:USE_LTO -eq "1") {
|
||||
if (Get-Command lld-lib -ErrorAction SilentlyContinue) {
|
||||
$AR = Get-Command lld-lib -ErrorAction SilentlyContinue
|
||||
$env:AR = $AR
|
||||
$CMAKE_FLAGS += "-DCMAKE_AR=$AR"
|
||||
}
|
||||
}
|
||||
|
||||
$env:CC = "clang-cl"
|
||||
$env:CXX = "clang-cl"
|
||||
$env:CFLAGS = $CFLAGS
|
||||
|
||||
@@ -7,12 +7,6 @@ if [[ "${CI:-}" == "1" || "${CI:-}" == "true" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
export LLVM_VERSION=18
|
||||
else
|
||||
export LLVM_VERSION=16
|
||||
fi
|
||||
|
||||
# this is the environment script for building bun's dependencies
|
||||
# it sets c compiler and flags
|
||||
export SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||
@@ -24,74 +18,17 @@ export BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR:-$BUN_BASE_DIR/build/bun-deps}
|
||||
export LC_CTYPE="en_US.UTF-8"
|
||||
export LC_ALL="en_US.UTF-8"
|
||||
|
||||
if [[ "$CI" != "1" && "$CI" != "true" ]]; then
|
||||
if [ -f $SCRIPT_DIR/env.local ]; then
|
||||
echo "Sourcing $SCRIPT_DIR/env.local"
|
||||
source $SCRIPT_DIR/env.local
|
||||
fi
|
||||
elif [[ $(uname -s) == 'Darwin' ]]; then
|
||||
export CXX="$(brew --prefix llvm)@$LLVM_VERSION/bin/clang++"
|
||||
export CC="$(brew --prefix llvm)@$LLVM_VERSION/bin/clang"
|
||||
export AR="$(brew --prefix llvm)@$LLVM_VERSION/bin/llvm-ar"
|
||||
export RANLIB="$(brew --prefix llvm)@$LLVM_VERSION/bin/llvm-ranlib"
|
||||
export LIBTOOL="$(brew --prefix llvm)@$LLVM_VERSION/bin/llvm-libtool-darwin"
|
||||
export PATH="$(brew --prefix llvm)@$LLVM_VERSION/bin:$PATH"
|
||||
ln -sf $LIBTOOL "$(brew --prefix llvm)@$LLVM_VERSION/bin/libtool" || true
|
||||
fi
|
||||
|
||||
# this compiler detection could be better
|
||||
export CC=${CC:-$(which clang-$LLVM_VERSION || which clang || which cc)}
|
||||
export CXX=${CXX:-$(which clang++-$LLVM_VERSION || which clang++ || which c++)}
|
||||
export CC=${CC:-$(which clang-16 || which clang || which cc)}
|
||||
export CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)}
|
||||
export AR=${AR:-$(which llvm-ar || which ar)}
|
||||
export CPUS=${CPUS:-$(nproc || sysctl -n hw.ncpu || echo 1)}
|
||||
export RANLIB=${RANLIB:-$(which llvm-ranlib-$LLVM_VERSION || which llvm-ranlib || which ranlib)}
|
||||
|
||||
# on Linux, force using lld as the linker
|
||||
if [[ $(uname -s) == 'Linux' ]]; then
|
||||
export LD=${LD:-$(which ld.lld-$LLVM_VERSION || which ld.lld || which ld)}
|
||||
export LDFLAGS="${LDFLAGS} -fuse-ld=lld "
|
||||
fi
|
||||
|
||||
export CMAKE_CXX_COMPILER=${CXX}
|
||||
export CMAKE_C_COMPILER=${CC}
|
||||
|
||||
export CFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables '
|
||||
export CXXFLAGS='-O3 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-c++-static-destructors '
|
||||
|
||||
# Add flags for LTO
|
||||
# We cannot enable LTO on macOS for dependencies because it requires -fuse-ld=lld and lld causes many segfaults on macOS (likely related to stack size)
|
||||
if [ "$BUN_ENABLE_LTO" == "1" ]; then
|
||||
export CFLAGS="$CFLAGS -flto=full "
|
||||
export CXXFLAGS="$CXXFLAGS -flto=full -fwhole-program-vtables -fforce-emit-vtables "
|
||||
export LDFLAGS="$LDFLAGS -flto=full -fwhole-program-vtables -fforce-emit-vtables "
|
||||
fi
|
||||
|
||||
if [[ $(uname -s) == 'Linux' ]]; then
|
||||
export CFLAGS="$CFLAGS -ffunction-sections -fdata-sections -faddrsig "
|
||||
export CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -faddrsig "
|
||||
export LDFLAGS="${LDFLAGS} -Wl,-z,norelro"
|
||||
fi
|
||||
|
||||
# Clang 18 on macOS needs to have -fno-define-target-os-macros to fix a zlib build issue
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/25755
|
||||
if [[ $(uname -s) == 'Darwin' && $LLVM_VERSION == '18' ]]; then
|
||||
export CFLAGS="$CFLAGS -fno-define-target-os-macros "
|
||||
export CXXFLAGS="$CXXFLAGS -fno-define-target-os-macros "
|
||||
fi
|
||||
|
||||
# libarchive needs position-independent executables to compile successfully
|
||||
if [ -n "$FORCE_PIC" ]; then
|
||||
export CFLAGS="$CFLAGS -fPIC "
|
||||
export CXXFLAGS="$CXXFLAGS -fPIC "
|
||||
elif [[ $(uname -s) == 'Linux' ]]; then
|
||||
export CFLAGS="$CFLAGS -fno-pie -fno-pic "
|
||||
export CXXFLAGS="$CXXFLAGS -fno-pie -fno-pic "
|
||||
fi
|
||||
|
||||
if [[ $(uname -s) == 'Linux' && ($(uname -m) == 'aarch64' || $(uname -m) == 'arm64') ]]; then
|
||||
export CFLAGS="$CFLAGS -march=armv8-a+crc -mtune=ampere1 "
|
||||
export CXXFLAGS="$CXXFLAGS -march=armv8-a+crc -mtune=ampere1 "
|
||||
fi
|
||||
export CFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer'
|
||||
export CXXFLAGS='-O3 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer'
|
||||
|
||||
export CMAKE_FLAGS=(
|
||||
-DCMAKE_C_COMPILER="${CC}"
|
||||
@@ -106,7 +43,7 @@ export CMAKE_FLAGS=(
|
||||
)
|
||||
|
||||
CCACHE=$(which ccache || which sccache || echo "")
|
||||
if [ -f "$CCACHE" ]; then
|
||||
if [ -n "$CCACHE" ]; then
|
||||
CMAKE_FLAGS+=(
|
||||
-DCMAKE_C_COMPILER_LAUNCHER="$CCACHE"
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER="$CCACHE"
|
||||
@@ -119,22 +56,22 @@ if [[ $(uname -s) == 'Linux' ]]; then
|
||||
fi
|
||||
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-13.0}
|
||||
export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-12.0}
|
||||
|
||||
CMAKE_FLAGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -D__DARWIN_NON_CANCELABLE=1 "
|
||||
export CXXFLAGS="$CXXFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} -D__DARWIN_NON_CANCELABLE=1 "
|
||||
CMAKE_FLAGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
||||
export CXXFLAGS="$CXXFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
||||
fi
|
||||
|
||||
mkdir -p $BUN_DEPS_OUT_DIR
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
echo "C Compiler: ${CC}"
|
||||
echo "C++ Compiler: ${CXX}"
|
||||
if [ -n "$CCACHE" ]; then
|
||||
echo "Ccache: ${CCACHE}"
|
||||
fi
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
echo "OSX Deployment Target: ${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
||||
fi
|
||||
echo "C Compiler: ${CC}"
|
||||
echo "C++ Compiler: ${CXX}"
|
||||
if [ -n "$CCACHE" ]; then
|
||||
echo "Ccache: ${CCACHE}"
|
||||
fi
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
echo "OSX Deployment Target: ${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -5,20 +5,11 @@ $npm_client = "npm"
|
||||
$root = Join-Path (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent) "..\"
|
||||
|
||||
# search for .cmd or .exe
|
||||
function Get-Esbuild-Path {
|
||||
param(
|
||||
$Path
|
||||
)
|
||||
|
||||
$Result = Join-Path $Path "node_modules\.bin\esbuild.cmd"
|
||||
if (Test-Path $Result) {
|
||||
return $Result
|
||||
}
|
||||
|
||||
return Join-Path $Path "node_modules\.bin\esbuild.exe"
|
||||
$esbuild = Join-Path $root "node_modules\.bin\esbuild.cmd"
|
||||
if (!(Test-Path $esbuild)) {
|
||||
$esbuild = Join-Path $root "node_modules\.bin\esbuild.exe"
|
||||
}
|
||||
|
||||
$esbuild = Get-Esbuild-Path $root
|
||||
|
||||
$env:NODE_ENV = "production"
|
||||
|
||||
@@ -43,5 +34,5 @@ Pop-Location
|
||||
# node-fallbacks
|
||||
Push-Location src\node-fallbacks
|
||||
& ${npm_client} install
|
||||
& (Get-Esbuild-Path (Get-Location)) --bundle @(Get-Item .\*.js) --outdir=out --format=esm --minify --platform=browser
|
||||
& ${esbuild} --bundle @(Get-Item .\*.js) --outdir=out --format=esm --minify --platform=browser
|
||||
Pop-Location
|
||||
|
||||
@@ -15,35 +15,12 @@ fail() {
|
||||
printf "${C_RED}setup error${C_RESET}: %s\n" "$@"
|
||||
}
|
||||
|
||||
if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
export LLVM_VERSION=18
|
||||
LLVM_VERSION=16
|
||||
|
||||
# Use from brew --prefix if available
|
||||
if has_exec brew; then
|
||||
export PKG_CONFIG_PATH=$(brew --prefix)/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
# if llvm@18/bin/clang exists, use it
|
||||
if [ -x "$(brew --prefix)/opt/llvm@$LLVM_VERSION/bin/clang" ]; then
|
||||
export PATH=$(brew --prefix)/opt/llvm@$LLVM_VERSION/bin:$PATH
|
||||
export CC=$(brew --prefix)/opt/llvm@$LLVM_VERSION/bin/clang
|
||||
export CXX=$(brew --prefix)/opt/llvm@$LLVM_VERSION/bin/clang++
|
||||
export AR=$(brew --prefix)/opt/llvm@$LLVM_VERSION/bin/llvm-ar
|
||||
else
|
||||
export CC=$(which clang-$LLVM_VERSION || which clang || which cc)
|
||||
export CXX=$(which clang++-$LLVM_VERSION || which clang++ || which c++)
|
||||
export AR=$(which llvm-ar-$LLVM_VERSION || which llvm-ar || which ar)
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$CC" || fail "missing LLVM $LLVM_VERSION (could not find clang)"
|
||||
test -n "$CXX" || fail "missing LLVM $LLVM_VERSION (could not find clang++)"
|
||||
else
|
||||
export LLVM_VERSION=16
|
||||
|
||||
export CC=$(which clang-$LLVM_VERSION || which clang || which cc)
|
||||
export CXX=$(which clang++-$LLVM_VERSION || which clang++ || which c++)
|
||||
export AR=$(which llvm-ar-$LLVM_VERSION || which llvm-ar || which ar)
|
||||
fi
|
||||
# this compiler detection could be better
|
||||
# it is copy pasted from ./env.sh
|
||||
CC=${CC:-$(which clang-16 || which clang || which cc)}
|
||||
CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)}
|
||||
|
||||
test -n "$CC" || fail "missing LLVM $LLVM_VERSION (could not find clang)"
|
||||
test -n "$CXX" || fail "missing LLVM $LLVM_VERSION (could not find clang++)"
|
||||
@@ -59,9 +36,9 @@ has_exec "bun" || fail "you need an existing copy of 'bun' in your path to build
|
||||
has_exec "cmake" || fail "'cmake' is missing"
|
||||
has_exec "ninja" || fail "'ninja' is missing"
|
||||
$(
|
||||
has_exec "rustc" &&
|
||||
(test $(cargo --version | awk '{print $2}' | cut -d. -f2) -gt 57) &&
|
||||
has_exec "cargo"
|
||||
has_exec "rustc" \
|
||||
&& (test $(cargo --version | awk '{print $2}' | cut -d. -f2) -gt 57) \
|
||||
&& has_exec "cargo"
|
||||
) || fail "Rust and Cargo version must be installed (minimum version 1.57)"
|
||||
has_exec "go" || fail "'go' is missing"
|
||||
|
||||
@@ -82,15 +59,6 @@ printf "C Compiler for dependencies: ${CC}\n"
|
||||
printf "C++ Compiler for dependencies: ${CXX}\n"
|
||||
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||
|
||||
rm -rf env.local
|
||||
echo "# Environment variables as of last setup.sh run at $(date)" >env.local
|
||||
echo "export CC=\"${CC}\"" >>env.local
|
||||
echo "export CXX\"=${CXX}\"" >>env.local
|
||||
echo "export AR=\"${AR}\"" >>env.local
|
||||
echo "export PATH=\"${PATH}\"" >>env.local
|
||||
echo "Saved environment variables to $(pwd)/env.local"
|
||||
|
||||
bash ./update-submodules.sh
|
||||
bash ./all-dependencies.sh
|
||||
|
||||
@@ -99,9 +67,7 @@ cd ../
|
||||
# Install bun dependencies
|
||||
bun i
|
||||
# Install test dependencies
|
||||
cd test
|
||||
bun i
|
||||
cd ..
|
||||
cd test; bun i; cd ..
|
||||
|
||||
# TODO(@paperdave): do not use the Makefile please
|
||||
has_exec "make" || fail "'make' is missing"
|
||||
@@ -115,7 +81,7 @@ cmake -B build -S . \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_C_COMPILER="$CC" \
|
||||
-DCMAKE_CXX_COMPILER="$CXX" \
|
||||
-UZIG_COMPILER "$*"
|
||||
-UZIG_COMPILER "$*" \
|
||||
|
||||
ninja -C build
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
set -exo pipefail
|
||||
|
||||
WEBKIT_VERSION=$(grep 'set(WEBKIT_TAG' "CMakeLists.txt" | awk '{print $2}' | cut -f 1 -d ')')
|
||||
WEBKIT_VERSION=$(git rev-parse HEAD:./src/bun.js/WebKit)
|
||||
MIMALLOC_VERSION=$(git rev-parse HEAD:./src/deps/mimalloc)
|
||||
LIBARCHIVE_VERSION=$(git rev-parse HEAD:./src/deps/libarchive)
|
||||
PICOHTTPPARSER_VERSION=$(git rev-parse HEAD:./src/deps/picohttpparser)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const std = @import("std");
|
||||
const bun = @import("root").bun;
|
||||
const assert = bun.assert;
|
||||
const assert = @import("root").bun.assert;
|
||||
const mem = std.mem;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
|
||||
@@ -171,7 +171,18 @@ pub inline fn configureAllocator(_: AllocatorConfiguration) void {
|
||||
// if (!config.long_running) Mimalloc.mi_option_set(Mimalloc.mi_option_reset_delay, 0);
|
||||
}
|
||||
|
||||
pub const panic = Output.panic; // deprecated
|
||||
pub fn panic(comptime fmt: string, args: anytype) noreturn {
|
||||
@setCold(true);
|
||||
if (comptime Environment.isWasm) {
|
||||
Output.printErrorln(fmt, args);
|
||||
Output.flush();
|
||||
@panic(fmt);
|
||||
} else {
|
||||
Output.prettyErrorln(fmt, args);
|
||||
Output.flush();
|
||||
std.debug.panic(fmt, args);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notimpl() noreturn {
|
||||
@setCold(true);
|
||||
|
||||
@@ -18,7 +18,7 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const windows = std.os.windows;
|
||||
const testing = std.testing;
|
||||
const assert = (std.debug).assert;
|
||||
const assert = std.debug.assert;
|
||||
const Progress = @This();
|
||||
|
||||
/// `null` if the current node (and its children) should
|
||||
@@ -246,7 +246,7 @@ fn clearWithHeldLock(p: *Progress, end_ptr: *usize) void {
|
||||
end += (std.fmt.bufPrint(p.output_buffer[end..], "\x1b[{d}D", .{p.columns_written}) catch unreachable).len;
|
||||
end += (std.fmt.bufPrint(p.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
|
||||
} else if (builtin.os.tag == .windows) winapi: {
|
||||
assert(p.is_windows_terminal);
|
||||
std.debug.assert(p.is_windows_terminal);
|
||||
|
||||
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||
if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) {
|
||||
@@ -357,7 +357,7 @@ fn refreshWithHeldLock(self: *Progress) void {
|
||||
|
||||
pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void {
|
||||
const file = self.terminal orelse {
|
||||
(std.debug).print(format, args);
|
||||
std.debug.print(format, args);
|
||||
return;
|
||||
};
|
||||
self.refresh();
|
||||
|
||||
@@ -74,30 +74,31 @@ pub const StandaloneModuleGraph = struct {
|
||||
loader: bun.options.Loader,
|
||||
contents: []const u8 = "",
|
||||
sourcemap: LazySourceMap,
|
||||
cached_blob: ?*bun.JSC.WebCore.Blob = null,
|
||||
blob_: ?*bun.JSC.WebCore.Blob = null,
|
||||
|
||||
pub fn blob(this: *File, globalObject: *bun.JSC.JSGlobalObject) *bun.JSC.WebCore.Blob {
|
||||
if (this.cached_blob == null) {
|
||||
if (this.blob_ == null) {
|
||||
var store = bun.JSC.WebCore.Blob.Store.init(@constCast(this.contents), bun.default_allocator);
|
||||
// make it never free
|
||||
store.ref();
|
||||
|
||||
const b = bun.JSC.WebCore.Blob.initWithStore(store, globalObject).new();
|
||||
b.allocator = bun.default_allocator;
|
||||
var blob_ = bun.default_allocator.create(bun.JSC.WebCore.Blob) catch bun.outOfMemory();
|
||||
blob_.* = bun.JSC.WebCore.Blob.initWithStore(store, globalObject);
|
||||
blob_.allocator = bun.default_allocator;
|
||||
|
||||
if (bun.http.MimeType.byExtensionNoDefault(bun.strings.trimLeadingChar(std.fs.path.extension(this.name), '.'))) |mime| {
|
||||
store.mime_type = mime;
|
||||
b.content_type = mime.value;
|
||||
b.content_type_was_set = true;
|
||||
b.content_type_allocated = false;
|
||||
blob_.content_type = mime.value;
|
||||
blob_.content_type_was_set = true;
|
||||
blob_.content_type_allocated = false;
|
||||
}
|
||||
|
||||
store.data.bytes.stored_name = bun.PathString.init(this.name);
|
||||
|
||||
this.cached_blob = b;
|
||||
this.blob_ = blob_;
|
||||
}
|
||||
|
||||
return this.cached_blob.?;
|
||||
return this.blob_.?;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ const mem = std.mem;
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
|
||||
const bun = @import("root").bun;
|
||||
const assert = bun.assert;
|
||||
const assert = @import("root").bun.assert;
|
||||
|
||||
pub fn AutoHashMap(comptime K: type, comptime V: type, comptime max_load_percentage: comptime_int) type {
|
||||
return HashMap(K, V, std.hash_map.AutoContext(K), max_load_percentage);
|
||||
|
||||
@@ -101,6 +101,7 @@ pub const Features = struct {
|
||||
pub var loaders: usize = 0;
|
||||
pub var lockfile_migration_from_package_lock: usize = 0;
|
||||
pub var macros: usize = 0;
|
||||
pub var origin: usize = 0;
|
||||
pub var shell: usize = 0;
|
||||
pub var spawn: usize = 0;
|
||||
pub var standalone_shell: usize = 0;
|
||||
@@ -109,9 +110,7 @@ pub const Features = struct {
|
||||
pub var tsconfig: usize = 0;
|
||||
pub var virtual_modules: usize = 0;
|
||||
pub var WebSocket: usize = 0;
|
||||
pub var no_avx: usize = 0;
|
||||
pub var no_avx2: usize = 0;
|
||||
pub var binlinks: usize = 0;
|
||||
|
||||
pub var builtin_modules = std.enums.EnumSet(bun.JSC.HardcodedModule).initEmpty();
|
||||
|
||||
pub fn formatter() Formatter {
|
||||
|
||||
@@ -1684,9 +1684,6 @@ pub const Api = struct {
|
||||
/// conditions
|
||||
conditions: []const []const u8,
|
||||
|
||||
/// packages
|
||||
packages: ?PackagesMode = null,
|
||||
|
||||
pub fn decode(reader: anytype) anyerror!TransformOptions {
|
||||
var this = std.mem.zeroes(TransformOptions);
|
||||
|
||||
@@ -1774,9 +1771,6 @@ pub const Api = struct {
|
||||
26 => {
|
||||
this.conditions = try reader.readArray([]const u8);
|
||||
},
|
||||
27 => {
|
||||
this.packages = try reader.readValue(PackagesMode);
|
||||
},
|
||||
else => {
|
||||
return error.InvalidMessage;
|
||||
},
|
||||
@@ -1892,11 +1886,6 @@ pub const Api = struct {
|
||||
try writer.writeArray([]const u8, conditions);
|
||||
}
|
||||
|
||||
if (this.packages) |packages| {
|
||||
try writer.writeFieldID(27);
|
||||
try writer.writeValue([]const u8, packages);
|
||||
}
|
||||
|
||||
try writer.endMessage();
|
||||
}
|
||||
};
|
||||
@@ -1919,20 +1908,6 @@ pub const Api = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const PackagesMode = enum(u8) {
|
||||
/// bundle
|
||||
bundle,
|
||||
|
||||
/// external
|
||||
external,
|
||||
|
||||
_,
|
||||
|
||||
pub fn jsonStringify(self: @This(), writer: anytype) !void {
|
||||
return try writer.write(@tagName(self));
|
||||
}
|
||||
};
|
||||
|
||||
pub const FileHandle = struct {
|
||||
/// path
|
||||
path: []const u8,
|
||||
@@ -2888,7 +2863,7 @@ pub const Api = struct {
|
||||
};
|
||||
|
||||
pub const NpmRegistryMap = struct {
|
||||
scopes: bun.StringArrayHashMapUnmanaged(NpmRegistry) = .{},
|
||||
scopes: std.StringArrayHashMapUnmanaged(NpmRegistry) = .{},
|
||||
|
||||
pub fn decode(reader: anytype) anyerror!NpmRegistryMap {
|
||||
var this = std.mem.zeroes(NpmRegistryMap);
|
||||
|
||||
131
src/ast/base.zig
131
src/ast/base.zig
@@ -2,10 +2,27 @@ const std = @import("std");
|
||||
const bun = @import("root").bun;
|
||||
const unicode = std.unicode;
|
||||
|
||||
pub const JavascriptString = []u16;
|
||||
pub fn newJavascriptString(comptime text: []const u8) JavascriptString {
|
||||
return unicode.utf8ToUtf16LeStringLiteral(text);
|
||||
}
|
||||
|
||||
pub const NodeIndex = u32;
|
||||
pub const NodeIndexNone = 4294967293;
|
||||
|
||||
// TODO: figure out if we actually need this
|
||||
// -- original comment --
|
||||
// Files are parsed in parallel for speed. We want to allow each parser to
|
||||
// generate symbol IDs that won't conflict with each other. We also want to be
|
||||
// able to quickly merge symbol tables from all files into one giant symbol
|
||||
// table.
|
||||
//
|
||||
// We can accomplish both goals by giving each symbol ID two parts: a source
|
||||
// index that is unique to the parser goroutine, and an inner index that
|
||||
// increments as the parser generates new symbol IDs. Then a symbol map can
|
||||
// be an array of arrays indexed first by source index, then by inner index.
|
||||
// The maps can be merged quickly by creating a single outer array containing
|
||||
// all inner arrays from all parsed files.
|
||||
|
||||
pub const RefHashCtx = struct {
|
||||
pub fn hash(_: @This(), key: Ref) u32 {
|
||||
@@ -27,6 +44,89 @@ pub const RefCtx = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Sets the range of bits starting at `start_bit` upto and excluding `start_bit` + `number_of_bits`
|
||||
/// to be specific, if the range is N bits long, the N lower bits of `value` will be used; if any of
|
||||
/// the other bits in `value` are set to 1, this function will panic.
|
||||
///
|
||||
/// ```zig
|
||||
/// var val: u8 = 0b10000000;
|
||||
/// setBits(&val, 2, 4, 0b00001101);
|
||||
/// try testing.expectEqual(@as(u8, 0b10110100), val);
|
||||
/// ```
|
||||
///
|
||||
/// ## Panics
|
||||
/// This method will panic if the `value` exceeds the bit range of the type of `target`
|
||||
pub fn setBits(
|
||||
comptime TargetType: type,
|
||||
target: TargetType,
|
||||
comptime start_bit: comptime_int,
|
||||
comptime number_of_bits: comptime_int,
|
||||
value: TargetType,
|
||||
) TargetType {
|
||||
const end_bit = start_bit + number_of_bits;
|
||||
|
||||
comptime {
|
||||
if (number_of_bits == 0) @compileError("non-zero number_of_bits must be provided");
|
||||
|
||||
if (@typeInfo(TargetType) == .Int) {
|
||||
if (@typeInfo(TargetType).Int.signedness != .unsigned) {
|
||||
@compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
|
||||
}
|
||||
if (start_bit >= @bitSizeOf(TargetType)) {
|
||||
@compileError("start_bit index is out of bounds of the bit field");
|
||||
}
|
||||
if (end_bit > @bitSizeOf(TargetType)) {
|
||||
@compileError("start_bit + number_of_bits is out of bounds of the bit field");
|
||||
}
|
||||
} else if (@typeInfo(TargetType) == .ComptimeInt) {
|
||||
@compileError("comptime_int is unsupported");
|
||||
} else {
|
||||
@compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
if (getBits(TargetType, value, 0, (end_bit - start_bit)) != value) @panic("value exceeds bit range");
|
||||
}
|
||||
|
||||
const bitmask: TargetType = comptime blk: {
|
||||
var bitmask = ~@as(TargetType, 0);
|
||||
bitmask <<= (@bitSizeOf(TargetType) - end_bit);
|
||||
bitmask >>= (@bitSizeOf(TargetType) - end_bit);
|
||||
bitmask >>= start_bit;
|
||||
bitmask <<= start_bit;
|
||||
break :blk ~bitmask;
|
||||
};
|
||||
|
||||
return (target & bitmask) | (value << start_bit);
|
||||
}
|
||||
|
||||
pub inline fn getBits(comptime TargetType: type, target: anytype, comptime start_bit: comptime_int, comptime number_of_bits: comptime_int) TargetType {
|
||||
comptime {
|
||||
if (number_of_bits == 0) @compileError("non-zero number_of_bits must be provided");
|
||||
|
||||
if (@typeInfo(TargetType) == .Int) {
|
||||
if (@typeInfo(TargetType).Int.signedness != .unsigned) {
|
||||
@compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
|
||||
}
|
||||
if (start_bit >= @bitSizeOf(TargetType)) {
|
||||
@compileError("start_bit index is out of bounds of the bit field");
|
||||
}
|
||||
if (start_bit + number_of_bits > @bitSizeOf(TargetType)) {
|
||||
@compileError("start_bit + number_of_bits is out of bounds of the bit field");
|
||||
}
|
||||
} else if (@typeInfo(TargetType) == .ComptimeInt) {
|
||||
if (target < 0) {
|
||||
@compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
|
||||
}
|
||||
} else {
|
||||
@compileError("requires an unsigned integer, found " ++ @typeName(TargetType));
|
||||
}
|
||||
}
|
||||
|
||||
return @as(TargetType, @truncate(target >> start_bit));
|
||||
}
|
||||
|
||||
/// In some parts of Bun, we have many different IDs pointing to different things.
|
||||
/// It's easy for them to get mixed up, so we use this type to make sure we don't.
|
||||
///
|
||||
@@ -86,19 +186,6 @@ pub const Index = packed struct(u32) {
|
||||
}
|
||||
};
|
||||
|
||||
/// -- original comment from esbuild --
|
||||
///
|
||||
/// Files are parsed in parallel for speed. We want to allow each parser to
|
||||
/// generate symbol IDs that won't conflict with each other. We also want to be
|
||||
/// able to quickly merge symbol tables from all files into one giant symbol
|
||||
/// table.
|
||||
///
|
||||
/// We can accomplish both goals by giving each symbol ID two parts: a source
|
||||
/// index that is unique to the parser goroutine, and an inner index that
|
||||
/// increments as the parser generates new symbol IDs. Then a symbol map can
|
||||
/// be an array of arrays indexed first by source index, then by inner index.
|
||||
/// The maps can be merged quickly by creating a single outer array containing
|
||||
/// all inner arrays from all parsed files.
|
||||
pub const Ref = packed struct(u64) {
|
||||
inner_index: Int = 0,
|
||||
|
||||
@@ -111,9 +198,6 @@ pub const Ref = packed struct(u64) {
|
||||
|
||||
source_index: Int = 0,
|
||||
|
||||
/// Represents a null state without using an extra bit
|
||||
pub const None = Ref{ .inner_index = 0, .source_index = 0, .tag = .invalid };
|
||||
|
||||
pub inline fn isEmpty(this: Ref) bool {
|
||||
return this.asU64() == 0;
|
||||
}
|
||||
@@ -138,7 +222,7 @@ pub const Ref = packed struct(u64) {
|
||||
pub fn format(ref: Ref, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
try std.fmt.format(
|
||||
writer,
|
||||
"Ref[inner={d}, src={d}, .{s}]",
|
||||
"Ref[{d}, {d}, {s}]",
|
||||
.{
|
||||
ref.sourceIndex(),
|
||||
ref.innerIndex(),
|
||||
@@ -151,6 +235,9 @@ pub const Ref = packed struct(u64) {
|
||||
return this.tag != .invalid;
|
||||
}
|
||||
|
||||
// 2 bits of padding for whatever is the parent
|
||||
pub const None = Ref{ .inner_index = 0, .source_index = 0, .tag = .invalid };
|
||||
|
||||
pub inline fn sourceIndex(this: Ref) Int {
|
||||
return this.source_index;
|
||||
}
|
||||
@@ -166,7 +253,10 @@ pub const Ref = packed struct(u64) {
|
||||
pub fn init(inner_index: Int, source_index: usize, is_source_contents_slice: bool) Ref {
|
||||
return .{
|
||||
.inner_index = inner_index,
|
||||
.source_index = @intCast(source_index),
|
||||
|
||||
// if we overflow, we want a panic
|
||||
.source_index = @as(Int, @intCast(source_index)),
|
||||
|
||||
.tag = if (is_source_contents_slice) .source_contents_slice else .allocated_name,
|
||||
};
|
||||
}
|
||||
@@ -188,10 +278,9 @@ pub const Ref = packed struct(u64) {
|
||||
return bun.hash(&@as([8]u8, @bitCast(key.asU64())));
|
||||
}
|
||||
|
||||
pub fn eql(ref: Ref, other: Ref) bool {
|
||||
return ref.asU64() == other.asU64();
|
||||
pub fn eql(ref: Ref, b: Ref) bool {
|
||||
return asU64(ref) == b.asU64();
|
||||
}
|
||||
|
||||
pub inline fn isNull(self: Ref) bool {
|
||||
return self.tag == .invalid;
|
||||
}
|
||||
|
||||
@@ -34,16 +34,6 @@ pub fn decode(destination: []u8, source: []const u8) bun.simdutf.SIMDUTFResult {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn decodeAlloc(allocator: std.mem.Allocator, input: []const u8) ![]u8 {
|
||||
var dest = try allocator.alloc(u8, decodeLen(input));
|
||||
const result = decode(dest, input);
|
||||
if (!result.isSuccessful()) {
|
||||
allocator.free(dest);
|
||||
return error.DecodingFailed;
|
||||
}
|
||||
return dest[0..result.count];
|
||||
}
|
||||
|
||||
pub fn encode(destination: []u8, source: []const u8) usize {
|
||||
return bun.simdutf.base64.encode(source, destination, false);
|
||||
}
|
||||
@@ -64,11 +54,7 @@ pub fn decodeLen(source: anytype) usize {
|
||||
}
|
||||
|
||||
pub fn encodeLen(source: anytype) usize {
|
||||
return encodeLenFromSize(source.len);
|
||||
}
|
||||
|
||||
pub fn encodeLenFromSize(source: usize) usize {
|
||||
return zig_base64.standard.Encoder.calcSize(source);
|
||||
return zig_base64.standard.Encoder.calcSize(source.len);
|
||||
}
|
||||
|
||||
pub fn urlSafeEncodeLen(source: anytype) usize {
|
||||
|
||||
64
src/bench/string-handling.zig
Normal file
64
src/bench/string-handling.zig
Normal file
@@ -0,0 +1,64 @@
|
||||
const strings = bun.strings;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
const args = try std.process.argsAlloc(std.heap.c_allocator);
|
||||
const filepath = args[args.len - 3];
|
||||
const find = args[args.len - 2];
|
||||
const amount = try std.fmt.parseInt(usize, args[args.len - 1], 10);
|
||||
var file = try std.fs.cwd().openFile(filepath, .{ .mode = .read_only });
|
||||
var contents = try file.readToEndAlloc(std.heap.c_allocator, std.math.maxInt(usize));
|
||||
var list = try std.ArrayList(u8).initCapacity(std.heap.c_allocator, contents.len);
|
||||
var duped = list.items.ptr[0..contents.len];
|
||||
{
|
||||
var timer = try std.time.Timer.start();
|
||||
var index: usize = std.math.maxInt(usize);
|
||||
var j: usize = 0;
|
||||
var i: usize = 0;
|
||||
while (j < amount) : (j += 1) {
|
||||
i = 0;
|
||||
strings.copy(duped, contents);
|
||||
}
|
||||
|
||||
if (index == std.math.maxInt(usize)) {
|
||||
std.debug.print("manual [{d} byte file] {s} NOT found in {}\n", .{ contents.len, find, std.fmt.fmtDuration(timer.read()) });
|
||||
} else {
|
||||
std.debug.print("manual [{d} byte file] {s} found at {d} in {}\n", .{ contents.len, find, index, std.fmt.fmtDuration(timer.read()) });
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var timer = try std.time.Timer.start();
|
||||
var index: usize = std.math.maxInt(usize);
|
||||
var j: usize = 0;
|
||||
var i: usize = 0;
|
||||
while (j < amount) : (j += 1) {
|
||||
i = 0;
|
||||
@memcpy(duped[0..contents.len], contents);
|
||||
}
|
||||
|
||||
if (index == std.math.maxInt(usize)) {
|
||||
std.debug.print("memcpy [{d} byte file] {s} NOT found in {}\n", .{ contents.len, find, std.fmt.fmtDuration(timer.read()) });
|
||||
} else {
|
||||
std.debug.print("memcpy [{d} byte file] {s} found at {d} in {}\n", .{ contents.len, find, index, std.fmt.fmtDuration(timer.read()) });
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var timer = try std.time.Timer.start();
|
||||
var index: usize = std.math.maxInt(usize);
|
||||
var j: usize = 0;
|
||||
var i: usize = 0;
|
||||
while (j < amount) : (j += 1) {
|
||||
i = 0;
|
||||
list.clearRetainingCapacity();
|
||||
list.appendSliceAssumeCapacity(contents);
|
||||
}
|
||||
|
||||
if (index == std.math.maxInt(usize)) {
|
||||
std.debug.print("ArrayList [{d} byte file] {s} NOT found in {}\n", .{ contents.len, find, std.fmt.fmtDuration(timer.read()) });
|
||||
} else {
|
||||
std.debug.print("ArrayList [{d} byte file] {s} found at {d} in {}\n", .{ contents.len, find, index, std.fmt.fmtDuration(timer.read()) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,16 +517,6 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets all bits
|
||||
pub fn setAll(self: *Self, value: bool) void {
|
||||
@memset(&self.masks, if (value) std.math.maxInt(MaskInt) else 0);
|
||||
|
||||
// Zero the padding bits
|
||||
if (num_masks > 0) {
|
||||
self.masks[num_masks - 1] &= last_item_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs a union of two bit sets, and stores the
|
||||
/// result in the first one. Bits in the result are
|
||||
/// set if the corresponding bits were set in either input.
|
||||
@@ -1256,12 +1246,6 @@ pub const AutoBitSet = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setAll(this: *AutoBitSet, value: bool) void {
|
||||
switch (this.*) {
|
||||
inline else => |*bitset| bitset.setAll(value),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(this: *AutoBitSet, allocator: std.mem.Allocator) void {
|
||||
switch (std.meta.activeTag(this.*)) {
|
||||
.static => {},
|
||||
|
||||
@@ -11,17 +11,17 @@ const mimalloc = bun.Mimalloc;
|
||||
|
||||
const BrotliAllocator = struct {
|
||||
pub fn alloc(_: ?*anyopaque, len: usize) callconv(.C) *anyopaque {
|
||||
if (bun.heap_breakdown.enabled) {
|
||||
const zone = bun.heap_breakdown.getZone(BrotliAllocator);
|
||||
return zone.malloc_zone_malloc(len) orelse bun.outOfMemory();
|
||||
if (comptime bun.is_heap_breakdown_enabled) {
|
||||
const zone = bun.HeapBreakdown.malloc_zone_t.get(BrotliAllocator);
|
||||
return zone.malloc_zone_malloc(len).?;
|
||||
}
|
||||
|
||||
return mimalloc.mi_malloc(len) orelse bun.outOfMemory();
|
||||
return mimalloc.mi_malloc(len) orelse unreachable;
|
||||
}
|
||||
|
||||
pub fn free(_: ?*anyopaque, data: ?*anyopaque) callconv(.C) void {
|
||||
if (bun.heap_breakdown.enabled) {
|
||||
const zone = bun.heap_breakdown.getZone(BrotliAllocator);
|
||||
if (comptime bun.is_heap_breakdown_enabled) {
|
||||
const zone = bun.HeapBreakdown.malloc_zone_t.get(BrotliAllocator);
|
||||
zone.malloc_zone_free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/// ** Update the version number when any breaking changes are made to the cache format or to the JS parser **
|
||||
/// Version 3: "Infinity" becomes "1/0".
|
||||
/// Version 4: TypeScript enums are properly handled + more constant folding
|
||||
const expected_version = 4;
|
||||
// ** Update the version number when any breaking changes are made to the cache format or to the JS parser **
|
||||
// Version 2 -> 3: "Infinity" becomes "1/0".
|
||||
const expected_version = 3;
|
||||
|
||||
const bun = @import("root").bun;
|
||||
const std = @import("std");
|
||||
@@ -201,10 +200,10 @@ pub const RuntimeTranspilerCache = struct {
|
||||
|
||||
try metadata.encode(metadata_stream.writer());
|
||||
|
||||
if (comptime bun.Environment.isDebug) {
|
||||
if (comptime bun.Environment.allow_assert) {
|
||||
var metadata_stream2 = std.io.fixedBufferStream(metadata_buf[0..Metadata.size]);
|
||||
var metadata2 = Metadata{};
|
||||
metadata2.decode(metadata_stream2.reader()) catch |err| bun.Output.panic("Metadata did not roundtrip encode -> decode successfully: {s}", .{@errorName(err)});
|
||||
metadata2.decode(metadata_stream2.reader()) catch |err| bun.Output.panic("Metadata did not rountrip encode -> decode successfully: {s}", .{@errorName(err)});
|
||||
bun.assert(std.meta.eql(metadata, metadata2));
|
||||
}
|
||||
|
||||
|
||||
Submodule src/bun.js/WebKit updated: 49018961cc...00e8a32b3c
@@ -1299,7 +1299,7 @@ extern fn dump_zone_malloc_stats() void;
|
||||
|
||||
fn dump_mimalloc(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue {
|
||||
globalObject.bunVM().arena.dumpStats();
|
||||
if (bun.heap_breakdown.enabled) {
|
||||
if (comptime bun.is_heap_breakdown_enabled) {
|
||||
dump_zone_malloc_stats();
|
||||
}
|
||||
return .undefined;
|
||||
@@ -1471,29 +1471,6 @@ pub const Crypto = struct {
|
||||
|
||||
pub const Digest = [BoringSSL.EVP_MAX_MD_SIZE]u8;
|
||||
|
||||
/// For usage in Zig
|
||||
pub fn pbkdf2(
|
||||
output: []u8,
|
||||
password: []const u8,
|
||||
salt: []const u8,
|
||||
iteration_count: u32,
|
||||
algorithm: Algorithm,
|
||||
) ?[]const u8 {
|
||||
var pbk = PBKDF2{
|
||||
.algorithm = algorithm,
|
||||
.password = JSC.Node.StringOrBuffer{ .encoded_slice = JSC.ZigString.Slice.fromUTF8NeverFree(password) },
|
||||
.salt = JSC.Node.StringOrBuffer{ .encoded_slice = JSC.ZigString.Slice.fromUTF8NeverFree(salt) },
|
||||
.iteration_count = iteration_count,
|
||||
.length = @intCast(output.len),
|
||||
};
|
||||
|
||||
if (!pbk.run(output)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
pub const PBKDF2 = struct {
|
||||
password: JSC.Node.StringOrBuffer = JSC.Node.StringOrBuffer.empty,
|
||||
salt: JSC.Node.StringOrBuffer = JSC.Node.StringOrBuffer.empty,
|
||||
@@ -2246,7 +2223,13 @@ pub const Crypto = struct {
|
||||
};
|
||||
this.ref = .{};
|
||||
this.promise.strong = .{};
|
||||
this.event_loop.enqueueTaskConcurrent(JSC.ConcurrentTask.createFrom(&result.task));
|
||||
|
||||
const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch bun.outOfMemory();
|
||||
concurrent_task.* = JSC.ConcurrentTask{
|
||||
.task = JSC.Task.init(&result.task),
|
||||
.auto_delete = true,
|
||||
};
|
||||
this.event_loop.enqueueTaskConcurrent(concurrent_task);
|
||||
this.deinit();
|
||||
}
|
||||
};
|
||||
@@ -2482,7 +2465,13 @@ pub const Crypto = struct {
|
||||
};
|
||||
this.ref = .{};
|
||||
this.promise.strong = .{};
|
||||
this.event_loop.enqueueTaskConcurrent(JSC.ConcurrentTask.createFrom(&result.task));
|
||||
|
||||
const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch bun.outOfMemory();
|
||||
concurrent_task.* = JSC.ConcurrentTask{
|
||||
.task = JSC.Task.init(&result.task),
|
||||
.auto_delete = true,
|
||||
};
|
||||
this.event_loop.enqueueTaskConcurrent(concurrent_task);
|
||||
this.deinit();
|
||||
}
|
||||
};
|
||||
@@ -2772,10 +2761,6 @@ pub const Crypto = struct {
|
||||
const thisValue = callframe.this();
|
||||
const arguments = callframe.arguments(2);
|
||||
const input = arguments.ptr[0];
|
||||
if (input.isEmptyOrUndefinedOrNull()) {
|
||||
globalThis.throwInvalidArguments("expected blob, string or buffer", .{});
|
||||
return JSC.JSValue.zero;
|
||||
}
|
||||
const encoding = arguments.ptr[1];
|
||||
const buffer = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValue(globalThis, globalThis.bunVM().allocator, input, encoding) orelse {
|
||||
globalThis.throwInvalidArguments("expected blob, string or buffer", .{});
|
||||
@@ -3895,7 +3880,7 @@ const TOMLObject = struct {
|
||||
return .zero;
|
||||
};
|
||||
var writer = js_printer.BufferPrinter.init(buffer_writer);
|
||||
_ = js_printer.printJSON(*js_printer.BufferPrinter, &writer, parse_result, &source, .{}) catch {
|
||||
_ = js_printer.printJSON(*js_printer.BufferPrinter, &writer, parse_result, &source) catch {
|
||||
globalThis.throwValue(log.toJS(globalThis, default_allocator, "Failed to print toml"));
|
||||
return .zero;
|
||||
};
|
||||
|
||||
@@ -67,7 +67,6 @@ pub const JSBundler = struct {
|
||||
source_map: options.SourceMapOption = .none,
|
||||
public_path: OwnedString = OwnedString.initEmpty(bun.default_allocator),
|
||||
conditions: bun.StringSet = bun.StringSet.init(bun.default_allocator),
|
||||
packages: options.PackagesOption = .bundle,
|
||||
|
||||
pub const List = bun.StringArrayHashMapUnmanaged(Config);
|
||||
|
||||
@@ -224,10 +223,6 @@ pub const JSBundler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (try config.getOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
this.packages = packages;
|
||||
}
|
||||
|
||||
if (try config.getOptionalEnum(globalThis, "format", options.Format)) |format| {
|
||||
switch (format) {
|
||||
.esm => {},
|
||||
@@ -688,7 +683,16 @@ pub const JSBundler = struct {
|
||||
completion.ref();
|
||||
|
||||
this.js_task = AnyTask.init(this);
|
||||
completion.jsc_event_loop.enqueueTaskConcurrent(JSC.ConcurrentTask.create(this.js_task.task()));
|
||||
const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch {
|
||||
completion.deref();
|
||||
this.deinit();
|
||||
return;
|
||||
};
|
||||
concurrent_task.* = JSC.ConcurrentTask{
|
||||
.auto_delete = true,
|
||||
.task = this.js_task.task(),
|
||||
};
|
||||
completion.jsc_event_loop.enqueueTaskConcurrent(concurrent_task);
|
||||
}
|
||||
|
||||
pub fn runOnJSThread(this: *Resolve) void {
|
||||
@@ -835,7 +839,15 @@ pub const JSBundler = struct {
|
||||
completion.ref();
|
||||
|
||||
this.js_task = AnyTask.init(this);
|
||||
const concurrent_task = JSC.ConcurrentTask.createFrom(&this.js_task);
|
||||
const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch {
|
||||
completion.deref();
|
||||
this.deinit();
|
||||
return;
|
||||
};
|
||||
concurrent_task.* = JSC.ConcurrentTask{
|
||||
.auto_delete = true,
|
||||
.task = this.js_task.task(),
|
||||
};
|
||||
completion.jsc_event_loop.enqueueTaskConcurrent(concurrent_task);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,9 +140,10 @@ pub const TransformTask = struct {
|
||||
.allocator = allocator,
|
||||
};
|
||||
ast_memory_allocator.reset();
|
||||
|
||||
JSAst.Stmt.Data.Store.memory_allocator = ast_memory_allocator;
|
||||
JSAst.Expr.Data.Store.memory_allocator = ast_memory_allocator;
|
||||
JSAst.Stmt.Data.Store.create(bun.default_allocator);
|
||||
JSAst.Expr.Data.Store.create(bun.default_allocator);
|
||||
|
||||
defer {
|
||||
JSAst.Stmt.Data.Store.reset();
|
||||
@@ -586,10 +587,6 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
|
||||
}
|
||||
}
|
||||
|
||||
if (try object.getOptionalEnum(globalThis, "packages", options.PackagesOption)) |packages| {
|
||||
transpiler.transform.packages = packages.toAPI();
|
||||
}
|
||||
|
||||
var tree_shaking: ?bool = null;
|
||||
if (object.getOptional(globalThis, "treeShaking", bool) catch return transpiler) |treeShaking| {
|
||||
tree_shaking = treeShaking;
|
||||
|
||||
@@ -1513,10 +1513,8 @@ pub fn spawnProcessWindows(
|
||||
const allocator = stack_allocator.get();
|
||||
const loop = options.windows.loop.platformEventLoop().uv_loop;
|
||||
|
||||
var cwd_buf: bun.PathBuffer = undefined;
|
||||
@memcpy(cwd_buf[0..options.cwd.len], options.cwd);
|
||||
cwd_buf[options.cwd.len] = 0;
|
||||
const cwd = cwd_buf[0..options.cwd.len :0];
|
||||
const cwd = try allocator.dupeZ(u8, options.cwd);
|
||||
defer allocator.free(cwd);
|
||||
|
||||
uv_process_options.cwd = cwd.ptr;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ fn onClose(socket: *uws.udp.Socket) callconv(.C) void {
|
||||
|
||||
const this: *UDPSocket = bun.cast(*UDPSocket, socket.user().?);
|
||||
this.closed = true;
|
||||
this.poll_ref.disable();
|
||||
this.poll_ref.unref(this.globalThis.bunVM());
|
||||
_ = this.js_refcount.fetchSub(1, .monotonic);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,6 @@ fn onDrain(socket: *uws.udp.Socket) callconv(.C) void {
|
||||
const callback = this.config.on_drain;
|
||||
if (callback == .zero) return;
|
||||
|
||||
const vm = JSC.VirtualMachine.get();
|
||||
const event_loop = vm.eventLoop();
|
||||
event_loop.enter();
|
||||
defer event_loop.exit();
|
||||
const result = callback.callWithThis(this.globalThis, this.thisValue, &[_]JSValue{this.thisValue});
|
||||
if (result.toError()) |err| {
|
||||
_ = this.callErrorHandler(.zero, &[_]JSValue{err});
|
||||
@@ -579,7 +575,9 @@ pub const UDPSocket = struct {
|
||||
}
|
||||
|
||||
pub fn unref(this: *This, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue {
|
||||
this.poll_ref.unref(globalThis.bunVM());
|
||||
if (!this.closed) {
|
||||
this.poll_ref.unref(globalThis.bunVM());
|
||||
}
|
||||
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import { define } from "../../codegen/class-definitions";
|
||||
|
||||
export default [
|
||||
define({
|
||||
name: "PostgresSQLConnection",
|
||||
construct: true,
|
||||
finalize: true,
|
||||
hasPendingActivity: true,
|
||||
configurable: false,
|
||||
klass: {
|
||||
// escapeString: {
|
||||
// fn: "escapeString",
|
||||
// },
|
||||
// escapeIdentifier: {
|
||||
// fn: "escapeIdentifier",
|
||||
// },
|
||||
},
|
||||
JSType: "0b11101110",
|
||||
proto: {
|
||||
close: {
|
||||
fn: "doClose",
|
||||
},
|
||||
flush: {
|
||||
fn: "doFlush",
|
||||
},
|
||||
connected: {
|
||||
getter: "getConnected",
|
||||
},
|
||||
ref: {
|
||||
fn: "doRef",
|
||||
},
|
||||
unref: {
|
||||
fn: "doUnref",
|
||||
},
|
||||
query: {
|
||||
fn: "createQuery",
|
||||
},
|
||||
},
|
||||
}),
|
||||
define({
|
||||
name: "PostgresSQLQuery",
|
||||
construct: true,
|
||||
finalize: true,
|
||||
configurable: false,
|
||||
hasPendingActivity: true,
|
||||
JSType: "0b11101110",
|
||||
klass: {},
|
||||
proto: {
|
||||
run: {
|
||||
fn: "doRun",
|
||||
length: 2,
|
||||
},
|
||||
cancel: {
|
||||
fn: "doCancel",
|
||||
length: 0,
|
||||
},
|
||||
done: {
|
||||
fn: "doDone",
|
||||
length: 0,
|
||||
},
|
||||
},
|
||||
values: ["pendingValue", "binding"],
|
||||
estimatedSize: true,
|
||||
}),
|
||||
];
|
||||
@@ -1421,10 +1421,11 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
/// We can only safely free once the request body promise is finalized
|
||||
/// and the response is rejected
|
||||
response_jsvalue: JSC.JSValue = JSC.JSValue.zero,
|
||||
ref_count: u8 = 1,
|
||||
pending_promises_for_abort: u8 = 0,
|
||||
|
||||
response_ptr: ?*JSC.WebCore.Response = null,
|
||||
blob: JSC.WebCore.AnyBlob = JSC.WebCore.AnyBlob{ .Blob = .{} },
|
||||
promise: ?*JSC.JSValue = null,
|
||||
|
||||
sendfile: SendfileContext = undefined,
|
||||
request_body: ?*JSC.WebCore.BodyValueRef = null,
|
||||
@@ -1474,15 +1475,14 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
const result = arguments.ptr[0];
|
||||
result.ensureStillAlive();
|
||||
|
||||
defer ctx.deref();
|
||||
|
||||
if (ctx.isAbortedOrEnded()) {
|
||||
ctx.deref();
|
||||
ctx.pending_promises_for_abort -|= 1;
|
||||
if (ctx.flags.aborted) {
|
||||
ctx.finalizeForAbort();
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
if (ctx.didUpgradeWebSocket()) {
|
||||
ctx.deref();
|
||||
ctx.finalize();
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
@@ -1536,75 +1536,10 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctx.render(response);
|
||||
}
|
||||
|
||||
pub fn shouldRenderMissing(this: *RequestContext) bool {
|
||||
// If we did not respond yet, we should render missing
|
||||
// To allow this all the conditions above should be true:
|
||||
// 1 - still has a response (not detached)
|
||||
// 2 - not aborted
|
||||
// 3 - not marked completed
|
||||
// 4 - not marked pending
|
||||
// 5 - is the only reference of the context
|
||||
// 6 - is not waiting for request body
|
||||
// 7 - did not call sendfile
|
||||
return this.resp != null and !this.flags.aborted and !this.flags.has_marked_complete and !this.flags.has_marked_pending and this.ref_count == 1 and !this.flags.is_waiting_for_request_body and !this.flags.has_sendfile_ctx;
|
||||
}
|
||||
|
||||
pub fn isDeadRequest(this: *RequestContext) bool {
|
||||
// check if has pending promise or extra reference (aka not the only reference)
|
||||
if (this.ref_count > 1) return false;
|
||||
// check if the body is Locked (streaming)
|
||||
if (this.request_body) |body| {
|
||||
if (body.value == .Locked) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// destroy RequestContext, should be only called by deref or if defer_deinit_until_callback_completes is ref is set to true
|
||||
fn deinit(this: *RequestContext) void {
|
||||
this.detachResponse();
|
||||
// TODO: has_marked_complete is doing something?
|
||||
this.flags.has_marked_complete = true;
|
||||
|
||||
if (this.defer_deinit_until_callback_completes) |defer_deinit| {
|
||||
defer_deinit.* = true;
|
||||
ctxLog("deferred deinit <d> ({*})<r>", .{this});
|
||||
return;
|
||||
}
|
||||
|
||||
ctxLog("deinit<d> ({*})<r>", .{this});
|
||||
if (comptime Environment.allow_assert)
|
||||
assert(this.flags.has_finalized);
|
||||
|
||||
this.request_body_buf.clearAndFree(this.allocator);
|
||||
this.response_buf_owned.clearAndFree(this.allocator);
|
||||
|
||||
if (this.request_body) |body| {
|
||||
_ = body.unref();
|
||||
this.request_body = null;
|
||||
}
|
||||
|
||||
const server = this.server;
|
||||
server.request_pool_allocator.put(this);
|
||||
server.onRequestComplete();
|
||||
}
|
||||
|
||||
pub fn deref(this: *RequestContext) void {
|
||||
streamLog("deref", .{});
|
||||
bun.assert(this.ref_count > 0);
|
||||
const ref_count = this.ref_count;
|
||||
this.ref_count -= 1;
|
||||
if (ref_count == 1) {
|
||||
this.finalizeWithoutDeinit();
|
||||
this.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ref(this: *RequestContext) void {
|
||||
streamLog("ref", .{});
|
||||
this.ref_count += 1;
|
||||
pub fn finalizeForAbort(this: *RequestContext) void {
|
||||
streamLog("finalizeForAbort", .{});
|
||||
this.pending_promises_for_abort -|= 1;
|
||||
if (this.pending_promises_for_abort == 0) this.finalize();
|
||||
}
|
||||
|
||||
pub fn onReject(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue {
|
||||
@@ -1614,44 +1549,36 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
var ctx = arguments.ptr[1].asPromisePtr(@This());
|
||||
const err = arguments.ptr[0];
|
||||
|
||||
defer ctx.deref();
|
||||
ctx.pending_promises_for_abort -|= 1;
|
||||
|
||||
if (ctx.flags.aborted) {
|
||||
ctx.finalizeForAbort();
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
handleReject(ctx, if (!err.isEmptyOrUndefinedOrNull()) err else JSC.JSValue.jsUndefined());
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
fn handleReject(ctx: *RequestContext, value: JSC.JSValue) void {
|
||||
if (ctx.isAbortedOrEnded()) {
|
||||
ctx.deref();
|
||||
if (ctx.resp == null) {
|
||||
ctx.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
const resp = ctx.resp.?;
|
||||
const has_responded = resp.hasResponded();
|
||||
if (!has_responded) {
|
||||
const original_state = ctx.defer_deinit_until_callback_completes;
|
||||
var should_deinit_context = false;
|
||||
ctx.defer_deinit_until_callback_completes = &should_deinit_context;
|
||||
if (!has_responded)
|
||||
ctx.runErrorHandler(
|
||||
value,
|
||||
);
|
||||
ctx.defer_deinit_until_callback_completes = original_state;
|
||||
// we try to deinit inside runErrorHandler so we just return here and let it deinit
|
||||
if (should_deinit_context) {
|
||||
ctx.deinit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check again in case it get aborted after runErrorHandler
|
||||
if (ctx.isAbortedOrEnded()) {
|
||||
ctx.deref();
|
||||
if (ctx.flags.aborted) {
|
||||
ctx.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
// I don't think this case happens?
|
||||
if (ctx.didUpgradeWebSocket()) {
|
||||
ctx.deref();
|
||||
ctx.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1665,7 +1592,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
if (ctx.resp) |resp| {
|
||||
resp.runCorkedWithType(*RequestContext, renderMissingCorked, ctx);
|
||||
}
|
||||
ctx.deref();
|
||||
ctx.finalize();
|
||||
}
|
||||
|
||||
pub fn renderMissingCorked(ctx: *RequestContext) void {
|
||||
@@ -1784,7 +1711,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.deref();
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
/// Drain a partial response buffer
|
||||
@@ -1802,27 +1729,41 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
pub fn end(this: *RequestContext, data: []const u8, closeConnection: bool) void {
|
||||
if (this.resp) |resp| {
|
||||
this.detachResponse();
|
||||
if (this.flags.is_waiting_for_request_body) {
|
||||
this.flags.is_waiting_for_request_body = false;
|
||||
resp.clearOnData();
|
||||
}
|
||||
resp.end(data, closeConnection);
|
||||
this.resp = null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn endStream(this: *RequestContext, closeConnection: bool) void {
|
||||
ctxLog("endStream", .{});
|
||||
if (this.resp) |resp| {
|
||||
this.detachResponse();
|
||||
if (this.flags.is_waiting_for_request_body) {
|
||||
this.flags.is_waiting_for_request_body = false;
|
||||
resp.clearOnData();
|
||||
}
|
||||
|
||||
// This will send a terminating 0\r\n\r\n chunk to the client
|
||||
// We only want to do that if they're still expecting a body
|
||||
// We cannot call this function if the Content-Length header was previously set
|
||||
if (resp.state().isResponsePending())
|
||||
resp.endStream(closeConnection);
|
||||
|
||||
this.resp = null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn endWithoutBody(this: *RequestContext, closeConnection: bool) void {
|
||||
if (this.resp) |resp| {
|
||||
this.detachResponse();
|
||||
if (this.flags.is_waiting_for_request_body) {
|
||||
this.flags.is_waiting_for_request_body = false;
|
||||
resp.clearOnData();
|
||||
}
|
||||
resp.endWithoutBody(closeConnection);
|
||||
this.resp = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1830,12 +1771,12 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctxLog("onWritableResponseBuffer", .{});
|
||||
|
||||
assert(this.resp == resp);
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return false;
|
||||
}
|
||||
this.end("", this.shouldCloseConnection());
|
||||
this.deref();
|
||||
this.finalize();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1844,8 +1785,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctxLog("onWritableCompleteResponseBufferAndMetadata", .{});
|
||||
assert(this.resp == resp);
|
||||
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1855,7 +1796,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
if (this.method == .HEAD) {
|
||||
this.end("", this.shouldCloseConnection());
|
||||
this.deref();
|
||||
this.finalize();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1865,8 +1806,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
pub fn onWritableCompleteResponseBuffer(this: *RequestContext, write_offset: u64, resp: *App.Response) callconv(.C) bool {
|
||||
ctxLog("onWritableCompleteResponseBuffer", .{});
|
||||
assert(this.resp == resp);
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return false;
|
||||
}
|
||||
return this.sendWritableBytesForCompleteResponseBuffer(this.response_buf_owned.items, write_offset, resp);
|
||||
@@ -1884,13 +1825,27 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctxLog("create<d> ({*})<r>", .{this});
|
||||
}
|
||||
|
||||
pub fn isDeadRequest(this: *RequestContext) bool {
|
||||
if (this.pending_promises_for_abort > 0) return false;
|
||||
|
||||
if (this.promise != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.request_body) |body| {
|
||||
if (body.value == .Locked) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn onAbort(this: *RequestContext, resp: *App.Response) void {
|
||||
assert(this.resp == resp);
|
||||
assert(!this.flags.aborted);
|
||||
// mark request as aborted
|
||||
this.flags.aborted = true;
|
||||
// we should not use the response anymore
|
||||
this.resp = null;
|
||||
var any_js_calls = false;
|
||||
var vm = this.server.vm;
|
||||
defer {
|
||||
@@ -1922,36 +1877,55 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
// if we can, free the request now.
|
||||
if (this.isDeadRequest()) {
|
||||
this.finalizeWithoutDeinit();
|
||||
this.deref();
|
||||
this.markComplete();
|
||||
this.deinit();
|
||||
} else {
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
this.pending_promises_for_abort = 0;
|
||||
|
||||
// if we cannot, we have to reject pending promises
|
||||
// first, we reject the request body promise
|
||||
if (this.request_body) |body| {
|
||||
// User called .blob(), .json(), text(), or .arrayBuffer() on the Request object
|
||||
// but we received nothing or the connection was aborted
|
||||
|
||||
if (body.value == .Locked) {
|
||||
// the promise is pending
|
||||
if (body.value.Locked.action != .none or body.value.Locked.promise != null) {
|
||||
this.pending_promises_for_abort += 1;
|
||||
} else if (body.value.Locked.readable.get()) |readable| {
|
||||
readable.abort(this.server.globalThis);
|
||||
body.value.Locked.readable.deinit();
|
||||
any_js_calls = true;
|
||||
}
|
||||
body.value.toErrorInstance(JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis), this.server.globalThis);
|
||||
any_js_calls = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.response_ptr) |response| {
|
||||
if (response.body.value == .Locked) {
|
||||
var strong_readable = response.body.value.Locked.readable;
|
||||
response.body.value.Locked.readable = .{};
|
||||
defer strong_readable.deinit();
|
||||
if (strong_readable.get()) |readable| {
|
||||
if (response.body.value.Locked.readable.get()) |readable| {
|
||||
defer response.body.value.Locked.readable.deinit();
|
||||
readable.abort(this.server.globalThis);
|
||||
any_js_calls = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then, we reject the response promise
|
||||
if (this.promise) |promise| {
|
||||
this.pending_promises_for_abort += 1;
|
||||
this.promise = null;
|
||||
promise.asAnyPromise().?.reject(this.server.globalThis, JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis));
|
||||
any_js_calls = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markComplete(this: *RequestContext) void {
|
||||
if (!this.flags.has_marked_complete) this.server.onRequestComplete();
|
||||
this.flags.has_marked_complete = true;
|
||||
}
|
||||
|
||||
// This function may be called multiple times
|
||||
// so it's important that we can safely do that
|
||||
pub fn finalizeWithoutDeinit(this: *RequestContext) void {
|
||||
@@ -1998,6 +1972,16 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
}
|
||||
|
||||
if (this.promise) |promise| {
|
||||
ctxLog("finalizeWithoutDeinit: this.promise != null", .{});
|
||||
this.promise = null;
|
||||
|
||||
if (promise.asAnyPromise()) |prom| {
|
||||
prom.rejectAsHandled(this.server.globalThis, (JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis)));
|
||||
}
|
||||
JSC.C.JSValueUnprotect(this.server.globalThis, promise.asObjectRef());
|
||||
}
|
||||
|
||||
if (this.byte_stream) |stream| {
|
||||
ctxLog("finalizeWithoutDeinit: stream != null", .{});
|
||||
|
||||
@@ -2020,6 +2004,42 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn finalize(this: *RequestContext) void {
|
||||
ctxLog("finalize<d> ({*})<r>", .{this});
|
||||
this.finalizeWithoutDeinit();
|
||||
this.markComplete();
|
||||
this.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit(this: *RequestContext) void {
|
||||
if (!this.isDeadRequest()) {
|
||||
ctxLog("deinit<d> ({*})<r> waiting request", .{this});
|
||||
return;
|
||||
}
|
||||
if (this.defer_deinit_until_callback_completes) |defer_deinit| {
|
||||
defer_deinit.* = true;
|
||||
ctxLog("deferred deinit <d> ({*})<r>", .{this});
|
||||
return;
|
||||
}
|
||||
|
||||
ctxLog("deinit<d> ({*})<r>", .{this});
|
||||
if (comptime Environment.allow_assert)
|
||||
assert(this.flags.has_finalized);
|
||||
|
||||
if (comptime Environment.allow_assert)
|
||||
assert(this.flags.has_marked_complete);
|
||||
|
||||
var server = this.server;
|
||||
this.request_body_buf.clearAndFree(this.allocator);
|
||||
this.response_buf_owned.clearAndFree(this.allocator);
|
||||
|
||||
if (this.request_body) |body| {
|
||||
_ = body.unref();
|
||||
this.request_body = null;
|
||||
}
|
||||
|
||||
server.request_pool_allocator.put(this);
|
||||
}
|
||||
|
||||
fn writeHeaders(
|
||||
this: *RequestContext,
|
||||
@@ -2057,7 +2077,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
if (this.sendfile.auto_close)
|
||||
_ = bun.sys.close(this.sendfile.fd);
|
||||
this.sendfile = undefined;
|
||||
this.deref();
|
||||
this.finalize();
|
||||
}
|
||||
const separator: string = "\r\n";
|
||||
const separator_iovec = [1]std.posix.iovec_const{.{
|
||||
@@ -2066,7 +2086,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}};
|
||||
|
||||
pub fn onSendfile(this: *RequestContext) bool {
|
||||
if (this.isAbortedOrEnded()) {
|
||||
if (this.flags.aborted or this.resp == null) {
|
||||
this.cleanupAndFinalizeAfterSendfile();
|
||||
return false;
|
||||
}
|
||||
@@ -2086,7 +2106,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
this.sendfile.remain -|= @as(Blob.SizeType, @intCast(this.sendfile.offset -| start));
|
||||
|
||||
if (errcode != .SUCCESS or this.isAbortedOrEnded() or this.sendfile.remain == 0 or val == 0) {
|
||||
if (errcode != .SUCCESS or this.flags.aborted or this.sendfile.remain == 0 or val == 0) {
|
||||
if (errcode != .AGAIN and errcode != .SUCCESS and errcode != .PIPE and errcode != .NOTCONN) {
|
||||
Output.prettyErrorln("Error: {s}", .{@tagName(errcode)});
|
||||
Output.flush();
|
||||
@@ -2108,7 +2128,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
const wrote = @as(Blob.SizeType, @intCast(sbytes));
|
||||
this.sendfile.offset +|= wrote;
|
||||
this.sendfile.remain -|= wrote;
|
||||
if (errcode != .AGAIN or this.isAbortedOrEnded() or this.sendfile.remain == 0 or sbytes == 0) {
|
||||
if (errcode != .AGAIN or this.flags.aborted or this.sendfile.remain == 0 or sbytes == 0) {
|
||||
if (errcode != .AGAIN and errcode != .SUCCESS and errcode != .PIPE and errcode != .NOTCONN) {
|
||||
Output.prettyErrorln("Error: {s}", .{@tagName(errcode)});
|
||||
Output.flush();
|
||||
@@ -2133,8 +2153,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
pub fn onWritableBytes(this: *RequestContext, write_offset: u64, resp: *App.Response) callconv(.C) bool {
|
||||
ctxLog("onWritableBytes", .{});
|
||||
assert(this.resp == resp);
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2152,7 +2172,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
const bytes = bytes_[@min(bytes_.len, @as(usize, @truncate(write_offset)))..];
|
||||
if (resp.tryEnd(bytes, bytes_.len, this.shouldCloseConnection())) {
|
||||
this.deref();
|
||||
this.finalize();
|
||||
return true;
|
||||
} else {
|
||||
this.flags.has_marked_pending = true;
|
||||
@@ -2168,7 +2188,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
const bytes = bytes_[@min(bytes_.len, @as(usize, @truncate(write_offset)))..];
|
||||
if (resp.tryEnd(bytes, bytes_.len, this.shouldCloseConnection())) {
|
||||
this.response_buf_owned.items.len = 0;
|
||||
this.deref();
|
||||
this.finalize();
|
||||
} else {
|
||||
this.flags.has_marked_pending = true;
|
||||
resp.onWritable(*RequestContext, onWritableCompleteResponseBuffer, this);
|
||||
@@ -2267,7 +2287,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
.remain = this.blob.Blob.offset + original_size,
|
||||
.offset = this.blob.Blob.offset,
|
||||
.auto_close = auto_close,
|
||||
.socket_fd = if (!this.isAbortedOrEnded()) resp.getNativeHandle() else bun.invalid_fd,
|
||||
.socket_fd = if (!this.flags.aborted) resp.getNativeHandle() else bun.invalid_fd,
|
||||
};
|
||||
|
||||
// if we are sending only part of a file, include the content-range header
|
||||
@@ -2301,8 +2321,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
pub fn doSendfile(this: *RequestContext, blob: Blob) void {
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2315,15 +2335,12 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
this.setAbortHandler();
|
||||
this.ref();
|
||||
this.blob.Blob.doReadFileInternal(*RequestContext, this, onReadFile, this.server.globalThis);
|
||||
}
|
||||
|
||||
pub fn onReadFile(this: *RequestContext, result: Blob.ReadFile.ResultType) void {
|
||||
defer this.deref();
|
||||
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted or this.resp == null) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2375,8 +2392,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
fn renderWithBlobFromBodyValue(this: *RequestContext) void {
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2402,10 +2419,10 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctxLog("doRenderStream", .{});
|
||||
var this = pair.this;
|
||||
var stream = pair.stream;
|
||||
if (this.isAbortedOrEnded()) {
|
||||
if (this.resp == null or this.flags.aborted) {
|
||||
stream.cancel(this.server.globalThis);
|
||||
this.readable_stream_ref.deinit();
|
||||
this.deref();
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
const resp = this.resp.?;
|
||||
@@ -2457,7 +2474,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
if (assignment_result.toError()) |err_value| {
|
||||
streamLog("returned an error", .{});
|
||||
if (!this.isAbortedOrEnded()) resp.clearAborted();
|
||||
if (!this.flags.aborted) resp.clearAborted();
|
||||
response_stream.detach();
|
||||
this.sink = null;
|
||||
response_stream.sink.destroy();
|
||||
@@ -2465,7 +2482,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
if (resp.hasResponded()) {
|
||||
if (!this.isAbortedOrEnded()) resp.clearAborted();
|
||||
if (!this.flags.aborted) resp.clearAborted();
|
||||
streamLog("done", .{});
|
||||
response_stream.detach();
|
||||
this.sink = null;
|
||||
@@ -2473,7 +2490,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
stream.done(this.server.globalThis);
|
||||
this.readable_stream_ref.deinit();
|
||||
this.endStream(this.shouldCloseConnection());
|
||||
this.deref();
|
||||
this.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2495,7 +2512,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
// TODO: should this timeout?
|
||||
this.setAbortHandler();
|
||||
this.ref();
|
||||
this.pending_promises_for_abort += 1;
|
||||
this.response_ptr.?.body.value = .{
|
||||
.Locked = .{
|
||||
.readable = JSC.WebCore.ReadableStream.Strong.init(stream, globalThis),
|
||||
@@ -2533,7 +2550,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
} else {
|
||||
// if is not a promise we treat it as Error
|
||||
streamLog("returned an error", .{});
|
||||
if (!this.isAbortedOrEnded()) resp.clearAborted();
|
||||
if (!this.flags.aborted) resp.clearAborted();
|
||||
response_stream.detach();
|
||||
this.sink = null;
|
||||
response_stream.sink.destroy();
|
||||
@@ -2541,13 +2558,13 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isAbortedOrEnded()) {
|
||||
if (this.flags.aborted) {
|
||||
response_stream.detach();
|
||||
stream.cancel(globalThis);
|
||||
defer this.readable_stream_ref.deinit();
|
||||
|
||||
response_stream.sink.markDone();
|
||||
this.deref();
|
||||
this.finalizeForAbort();
|
||||
response_stream.sink.onFirstWrite = null;
|
||||
|
||||
response_stream.sink.finalize();
|
||||
@@ -2615,28 +2632,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
ctx.setAbortHandler();
|
||||
}
|
||||
|
||||
fn detachResponse(this: *RequestContext) void {
|
||||
if (this.resp) |resp| {
|
||||
this.resp = null;
|
||||
|
||||
// onAbort should have set this to null
|
||||
bun.assert(!this.flags.aborted);
|
||||
if (this.flags.is_waiting_for_request_body) {
|
||||
this.flags.is_waiting_for_request_body = false;
|
||||
resp.clearOnData();
|
||||
}
|
||||
if (this.flags.has_abort_handler) {
|
||||
resp.clearAborted();
|
||||
this.flags.has_abort_handler = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn isAbortedOrEnded(this: *const RequestContext) bool {
|
||||
// resp == null or aborted or server.stop(true)
|
||||
return this.resp == null or this.flags.aborted or this.server.flags.terminated;
|
||||
}
|
||||
|
||||
// Each HTTP request or TCP socket connection is effectively a "task".
|
||||
//
|
||||
// However, unlike the regular task queue, we don't drain the microtask
|
||||
@@ -2661,8 +2656,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
response_value.ensureStillAlive();
|
||||
ctx.drainMicrotasks();
|
||||
|
||||
if (ctx.isAbortedOrEnded()) {
|
||||
ctx.deref();
|
||||
if (ctx.flags.aborted) {
|
||||
ctx.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2671,7 +2666,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
// just ignore the Response object. It doesn't do anything.
|
||||
// it's better to do that than to throw an error
|
||||
if (ctx.didUpgradeWebSocket()) {
|
||||
ctx.deref();
|
||||
ctx.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2724,7 +2719,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
// just ignore the Response object. It doesn't do anything.
|
||||
// it's better to do that than to throw an error
|
||||
if (ctx.didUpgradeWebSocket()) {
|
||||
ctx.deref();
|
||||
ctx.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2769,7 +2764,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
if (wait_for_promise) {
|
||||
ctx.ref();
|
||||
ctx.pending_promises_for_abort += 1;
|
||||
response_value.then(this.globalThis, ctx, RequestContext.onResolve, RequestContext.onReject);
|
||||
return;
|
||||
}
|
||||
@@ -2803,8 +2798,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
streamLog("onResolve({any})", .{wrote_anything});
|
||||
//aborted so call finalizeForAbort
|
||||
if (req.isAbortedOrEnded()) {
|
||||
req.deref();
|
||||
if (req.flags.aborted or req.resp == null) {
|
||||
req.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
const resp = req.resp.?;
|
||||
@@ -2819,14 +2814,14 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
req.endStream(req.shouldCloseConnection());
|
||||
}
|
||||
|
||||
req.deref();
|
||||
req.finalize();
|
||||
}
|
||||
|
||||
pub fn onResolveStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue {
|
||||
streamLog("onResolveStream", .{});
|
||||
var args = callframe.arguments(2);
|
||||
var req: *@This() = args.ptr[args.len - 1].asPromisePtr(@This());
|
||||
defer req.deref();
|
||||
req.pending_promises_for_abort -|= 1;
|
||||
req.handleResolveStream();
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
@@ -2834,7 +2829,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
streamLog("onRejectStream", .{});
|
||||
const args = callframe.arguments(2);
|
||||
var req = args.ptr[args.len - 1].asPromisePtr(@This());
|
||||
defer req.deref();
|
||||
req.pending_promises_for_abort -|= 1;
|
||||
const err = args.ptr[0];
|
||||
req.handleRejectStream(globalThis, err);
|
||||
return JSValue.jsUndefined();
|
||||
@@ -2864,8 +2859,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
// aborted so call finalizeForAbort
|
||||
if (req.isAbortedOrEnded()) {
|
||||
req.deref();
|
||||
if (req.flags.aborted) {
|
||||
req.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2883,7 +2878,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
req.server.vm.runErrorHandler(err, &exception_list);
|
||||
}
|
||||
}
|
||||
req.deref();
|
||||
req.finalize();
|
||||
}
|
||||
|
||||
pub fn doRenderWithBody(this: *RequestContext, value: *JSC.WebCore.Body.Value) void {
|
||||
@@ -2897,8 +2892,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
.Error => {
|
||||
const err = value.Error;
|
||||
_ = value.use();
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
this.runErrorHandler(err);
|
||||
@@ -2915,8 +2910,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
return;
|
||||
},
|
||||
.Locked => |*lock| {
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3030,8 +3025,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted or this.resp == null) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
const resp = this.resp.?;
|
||||
@@ -3044,7 +3039,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
if (resp.write(chunk)) {
|
||||
if (stream.isDone()) {
|
||||
this.endStream(this.shouldCloseConnection());
|
||||
this.deref();
|
||||
this.finalize();
|
||||
}
|
||||
} else {
|
||||
// when it's the last one, we just want to know if it's done
|
||||
@@ -3078,8 +3073,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
pub fn doRender(this: *RequestContext) void {
|
||||
ctxLog("doRender", .{});
|
||||
|
||||
if (this.isAbortedOrEnded()) {
|
||||
this.deref();
|
||||
if (this.flags.aborted) {
|
||||
this.finalizeForAbort();
|
||||
return;
|
||||
}
|
||||
var response = this.response_ptr.?;
|
||||
@@ -3107,7 +3102,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
},
|
||||
}
|
||||
}
|
||||
this.deref();
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
pub fn runErrorHandler(
|
||||
@@ -3265,7 +3260,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
// Promise is not fulfilled yet
|
||||
{
|
||||
ctx.flags.is_error_promise_pending = true;
|
||||
ctx.ref();
|
||||
ctx.pending_promises_for_abort += 1;
|
||||
promise_js.then(
|
||||
ctx.server.globalThis,
|
||||
ctx,
|
||||
@@ -3419,7 +3414,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
}
|
||||
|
||||
this.deref();
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void {
|
||||
@@ -3435,7 +3430,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
assert(this.resp == resp);
|
||||
|
||||
this.flags.is_waiting_for_request_body = last == false;
|
||||
if (this.isAbortedOrEnded() or this.flags.has_marked_complete) return;
|
||||
if (this.flags.aborted or this.flags.has_marked_complete) return;
|
||||
if (!last and chunk.len == 0) {
|
||||
// Sometimes, we get back an empty chunk
|
||||
// We have to ignore those chunks unless it's the last one
|
||||
@@ -3534,7 +3529,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
pub fn onStartStreamingRequestBody(this: *RequestContext) JSC.WebCore.DrainResult {
|
||||
ctxLog("onStartStreamingRequestBody", .{});
|
||||
if (this.isAbortedOrEnded()) {
|
||||
if (this.flags.aborted) {
|
||||
return JSC.WebCore.DrainResult{
|
||||
.aborted = {},
|
||||
};
|
||||
@@ -5390,7 +5385,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
}
|
||||
|
||||
var upgrader = bun.cast(*RequestContext, request.upgrader.?);
|
||||
if (upgrader.isAbortedOrEnded()) {
|
||||
if (upgrader.flags.aborted or upgrader.resp == null) {
|
||||
return JSC.jsBoolean(false);
|
||||
}
|
||||
|
||||
@@ -6171,7 +6166,6 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
&writer,
|
||||
bun.Global.BunInfo.generate(*Bundler, &JSC.VirtualMachine.get().bundler, allocator) catch unreachable,
|
||||
&source,
|
||||
.{},
|
||||
) catch unreachable;
|
||||
|
||||
resp.writeStatus("200 OK");
|
||||
@@ -6313,7 +6307,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
// uWS request will not live longer than this function
|
||||
request_object.request_context = JSC.API.AnyRequestContext.Null;
|
||||
}
|
||||
const original_state = ctx.defer_deinit_until_callback_completes;
|
||||
|
||||
var should_deinit_context = false;
|
||||
ctx.defer_deinit_until_callback_completes = &should_deinit_context;
|
||||
ctx.onResponse(
|
||||
@@ -6323,7 +6317,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
request_value,
|
||||
response_value,
|
||||
);
|
||||
ctx.defer_deinit_until_callback_completes = original_state;
|
||||
ctx.defer_deinit_until_callback_completes = null;
|
||||
|
||||
if (should_deinit_context) {
|
||||
request_object.request_context = JSC.API.AnyRequestContext.Null;
|
||||
@@ -6331,7 +6325,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.shouldRenderMissing()) {
|
||||
if (!ctx.flags.has_marked_complete and !ctx.flags.has_marked_pending and ctx.pending_promises_for_abort == 0 and !ctx.flags.is_waiting_for_request_body and !ctx.flags.has_sendfile_ctx) {
|
||||
ctx.renderMissing();
|
||||
return;
|
||||
}
|
||||
@@ -6382,7 +6376,6 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
request_object.request_context = JSC.API.AnyRequestContext.Null;
|
||||
}
|
||||
|
||||
const original_state = ctx.defer_deinit_until_callback_completes;
|
||||
var should_deinit_context = false;
|
||||
ctx.defer_deinit_until_callback_completes = &should_deinit_context;
|
||||
ctx.onResponse(
|
||||
@@ -6392,7 +6385,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
request_value,
|
||||
response_value,
|
||||
);
|
||||
ctx.defer_deinit_until_callback_completes = original_state;
|
||||
ctx.defer_deinit_until_callback_completes = null;
|
||||
|
||||
if (should_deinit_context) {
|
||||
request_object.request_context = JSC.API.AnyRequestContext.Null;
|
||||
@@ -6400,7 +6393,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.shouldRenderMissing()) {
|
||||
if (!ctx.flags.has_marked_complete and !ctx.flags.has_marked_pending and ctx.pending_promises_for_abort == 0 and !ctx.flags.is_waiting_for_request_body and !ctx.flags.has_sendfile_ctx) {
|
||||
ctx.renderMissing();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ JSValue BunInjectedScriptHost::subtype(JSGlobalObject* exec, JSValue value)
|
||||
static JSObject* constructInternalProperty(VM& vm, JSGlobalObject* exec, const String& name, JSValue value)
|
||||
{
|
||||
auto* object = constructEmptyObject(exec);
|
||||
object->putDirect(vm, vm.propertyNames->name, jsString(vm, name));
|
||||
object->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, name));
|
||||
object->putDirect(vm, Identifier::fromString(vm, "value"_s), value);
|
||||
return object;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ static JSObject* constructInternalProperty(VM& vm, JSGlobalObject* exec, const S
|
||||
static JSObject* constructInternalProperty(VM& vm, JSGlobalObject* exec, const Identifier& name, JSValue value)
|
||||
{
|
||||
auto* object = constructEmptyObject(exec);
|
||||
object->putDirect(vm, vm.propertyNames->name, JSC::identifierToJSValue(vm, name));
|
||||
object->putDirect(vm, Identifier::fromString(vm, "name"_s), JSC::identifierToJSValue(vm, name));
|
||||
object->putDirect(vm, Identifier::fromString(vm, "value"_s), value);
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__lookupService);
|
||||
BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__prefetch);
|
||||
BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__getCacheStats);
|
||||
BUN_DECLARE_HOST_FUNCTION(Bun__fetch);
|
||||
BUN_DECLARE_HOST_FUNCTION(Bun__fetchPreconnect);
|
||||
|
||||
namespace Bun {
|
||||
|
||||
@@ -268,17 +267,6 @@ static JSValue constructPasswordObject(VM& vm, JSObject* bunObject)
|
||||
return JSValue::decode(JSPasswordObject__create(bunObject->globalObject()));
|
||||
}
|
||||
|
||||
JSValue constructBunFetchObject(VM& vm, JSObject* bunObject)
|
||||
{
|
||||
JSFunction* fetchFn = JSFunction::create(vm, bunObject->globalObject(), 1, "fetch"_s, Bun__fetch, ImplementationVisibility::Public, NoIntrinsic);
|
||||
|
||||
auto* globalObject = jsCast<Zig::GlobalObject*>(bunObject->globalObject());
|
||||
fetchFn->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "preconnect"_s), 1, Bun__fetchPreconnect, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
|
||||
|
||||
return fetchFn;
|
||||
}
|
||||
|
||||
static JSValue constructBunShell(VM& vm, JSObject* bunObject)
|
||||
{
|
||||
auto* globalObject = jsCast<Zig::GlobalObject*>(bunObject->globalObject());
|
||||
@@ -561,14 +549,14 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj
|
||||
cwd BunObject_getter_wrap_cwd DontEnum|DontDelete|PropertyCallback
|
||||
deepEquals functionBunDeepEquals DontDelete|Function 2
|
||||
deepMatch functionBunDeepMatch DontDelete|Function 2
|
||||
deflateSync BunObject_callback_deflateSync DontDelete|Function 1
|
||||
deflateSync BunObject_callback_deflateSync DontDelete|Function 1
|
||||
dns constructDNSObject ReadOnly|DontDelete|PropertyCallback
|
||||
enableANSIColors BunObject_getter_wrap_enableANSIColors DontDelete|PropertyCallback
|
||||
env constructEnvObject ReadOnly|DontDelete|PropertyCallback
|
||||
escapeHTML functionBunEscapeHTML DontDelete|Function 2
|
||||
fetch constructBunFetchObject ReadOnly|DontDelete|PropertyCallback
|
||||
file BunObject_callback_file DontDelete|Function 1
|
||||
fileURLToPath functionFileURLToPath DontDelete|Function 1
|
||||
fetch Bun__fetch ReadOnly|DontDelete|Function 1
|
||||
file BunObject_callback_file DontDelete|Function 1
|
||||
fileURLToPath functionFileURLToPath DontDelete|Function 1
|
||||
gc BunObject_callback_gc DontDelete|Function 1
|
||||
generateHeapSnapshot BunObject_callback_generateHeapSnapshot DontDelete|Function 1
|
||||
gunzipSync BunObject_callback_gunzipSync DontDelete|Function 1
|
||||
|
||||
@@ -12,7 +12,5 @@ JSC_DECLARE_HOST_FUNCTION(functionBunNanoseconds);
|
||||
JSC_DECLARE_HOST_FUNCTION(functionPathToFileURL);
|
||||
JSC_DECLARE_HOST_FUNCTION(functionFileURLToPath);
|
||||
|
||||
JSC::JSValue constructBunFetchObject(VM& vm, JSObject* bunObject);
|
||||
JSC::JSObject* createBunObject(VM& vm, JSObject* globalObject);
|
||||
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ static JSValue constructProcessReleaseObject(VM& vm, JSObject* processObject)
|
||||
auto* release = JSC::constructEmptyObject(globalObject);
|
||||
|
||||
// SvelteKit compatibility hack
|
||||
release->putDirect(vm, vm.propertyNames->name, jsString(vm, WTF::String("node"_s)), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, WTF::String("node"_s)), 0);
|
||||
|
||||
release->putDirect(vm, Identifier::fromString(vm, "lts"_s), jsBoolean(false), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "sourceUrl"_s), jsString(vm, WTF::String(std::span { Bun__githubURL, strlen(Bun__githubURL) })), 0);
|
||||
@@ -423,7 +423,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUmask,
|
||||
}
|
||||
|
||||
if (!numberValue.isAnyInt()) {
|
||||
throwNodeRangeError(globalObject, throwScope, "The \"mask\" argument must be an integer"_s);
|
||||
throwRangeError(globalObject, throwScope, "The \"mask\" argument must be an integer"_s);
|
||||
return JSValue::encode({});
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUmask,
|
||||
StringBuilder messageBuilder;
|
||||
messageBuilder.append("The \"mask\" value must be in range [0, 4294967295]. Received value: "_s);
|
||||
messageBuilder.append(int52ToString(vm, newUmask, 10)->getString(globalObject));
|
||||
throwNodeRangeError(globalObject, throwScope, messageBuilder.toString());
|
||||
throwRangeError(globalObject, throwScope, messageBuilder.toString());
|
||||
return JSValue::encode({});
|
||||
}
|
||||
|
||||
@@ -1068,7 +1068,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_emitWarning, (JSGlobalObject * lexicalGlobalObj
|
||||
return createError(globalObject, str);
|
||||
})();
|
||||
|
||||
errorInstance->putDirect(vm, vm.propertyNames->name, jsString(vm, String("warn"_s)), JSC::PropertyAttribute::DontEnum | 0);
|
||||
errorInstance->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, String("warn"_s)), JSC::PropertyAttribute::DontEnum | 0);
|
||||
|
||||
auto ident = Identifier::fromString(vm, "warning"_s);
|
||||
if (process->wrapped().hasEventListeners(ident)) {
|
||||
@@ -2637,7 +2637,7 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessDebugPort,
|
||||
JSValue value = JSValue::decode(encodedValue);
|
||||
|
||||
if (!value.isInt32AsAnyInt()) {
|
||||
throwNodeRangeError(globalObject, scope, "debugPort must be 0 or in range 1024 to 65535"_s);
|
||||
throwRangeError(globalObject, scope, "debugPort must be 0 or in range 1024 to 65535"_s);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2645,7 +2645,7 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessDebugPort,
|
||||
|
||||
if (port != 0) {
|
||||
if (port < 1024 || port > 65535) {
|
||||
throwNodeRangeError(globalObject, scope, "debugPort must be 0 or in range 1024 to 65535"_s);
|
||||
throwRangeError(globalObject, scope, "debugPort must be 0 or in range 1024 to 65535"_s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2739,7 +2739,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill,
|
||||
int pid = callFrame->argument(0).toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (pid < 0) {
|
||||
throwNodeRangeError(globalObject, scope, "pid must be a positive integer"_s);
|
||||
throwRangeError(globalObject, scope, "pid must be a positive integer"_s);
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
@@ -2754,7 +2754,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill,
|
||||
signal = num;
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
} else {
|
||||
throwNodeRangeError(globalObject, scope, "Unknown signal name"_s);
|
||||
throwRangeError(globalObject, scope, "Unknown signal name"_s);
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +61,6 @@ extern "C" bool BunString__fromJS(JSC::JSGlobalObject* globalObject, JSC::Encode
|
||||
return bunString->tag != BunStringTag::Dead;
|
||||
}
|
||||
|
||||
extern "C" bool BunString__fromJSRef(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, BunString* bunString)
|
||||
{
|
||||
|
||||
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
|
||||
*bunString = Bun::toStringRef(globalObject, value);
|
||||
return bunString->tag != BunStringTag::Dead;
|
||||
}
|
||||
|
||||
extern "C" BunString BunString__createAtom(const char* bytes, size_t length)
|
||||
{
|
||||
ASSERT(simdutf::validate_ascii(bytes, length));
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
#include "root.h"
|
||||
|
||||
enum class X86CPUFeature : uint8_t {
|
||||
sse42 = 1,
|
||||
popcnt = 2,
|
||||
avx = 3,
|
||||
avx2 = 4,
|
||||
avx512 = 5,
|
||||
};
|
||||
|
||||
enum class AArch64CPUFeature : uint8_t {
|
||||
neon = 1,
|
||||
fp = 2,
|
||||
aes = 3,
|
||||
crc32 = 4,
|
||||
atomics = 5,
|
||||
sve = 6,
|
||||
};
|
||||
|
||||
#if CPU(X86_64)
|
||||
|
||||
#if OS(WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif
|
||||
|
||||
static uint8_t x86_cpu_features()
|
||||
{
|
||||
uint8_t features = 0;
|
||||
|
||||
#if OS(WINDOWS)
|
||||
if (IsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::sse42);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx2);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX512F_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx512);
|
||||
|
||||
#else
|
||||
|
||||
#if __has_builtin(__builtin_cpu_supports)
|
||||
__builtin_cpu_init();
|
||||
|
||||
if (__builtin_cpu_supports("sse4.2"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::sse42);
|
||||
if (__builtin_cpu_supports("popcnt"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::popcnt);
|
||||
if (__builtin_cpu_supports("avx"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx);
|
||||
if (__builtin_cpu_supports("avx2"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx2);
|
||||
if (__builtin_cpu_supports("avx512f"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx512);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CPU(ARM64)
|
||||
|
||||
static uint8_t aarch64_cpu_features()
|
||||
{
|
||||
uint8_t features = 0;
|
||||
|
||||
#if OS(WINDOWS)
|
||||
#pragma error "TODO: Implement AArch64 CPU features for Windows"
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_cpu_supports)
|
||||
__builtin_cpu_init();
|
||||
|
||||
if (__builtin_cpu_supports("neon"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::neon);
|
||||
if (__builtin_cpu_supports("crypto"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::fp);
|
||||
if (__builtin_cpu_supports("aes"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::aes);
|
||||
if (__builtin_cpu_supports("crc32"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::crc32);
|
||||
if (__builtin_cpu_supports("atomics"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::atomics);
|
||||
if (__builtin_cpu_supports("sve"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::sve);
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" uint8_t bun_cpu_features()
|
||||
{
|
||||
#if CPU(X86_64)
|
||||
return x86_cpu_features();
|
||||
#elif CPU(ARM64)
|
||||
return aarch64_cpu_features();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
const bun = @import("root").bun;
|
||||
const std = @import("std");
|
||||
|
||||
fn Impl(comptime T: type) type {
|
||||
return struct {
|
||||
pub fn format(this: T, comptime _: []const u8, _: anytype, writer: anytype) !void {
|
||||
var is_first = true;
|
||||
inline for (comptime std.meta.fieldNames(T)) |fieldName| {
|
||||
if (comptime bun.strings.eqlComptime(fieldName, "padding") or bun.strings.eqlComptime(fieldName, "none"))
|
||||
continue;
|
||||
|
||||
const value = @field(this, fieldName);
|
||||
if (value) {
|
||||
if (!is_first)
|
||||
try writer.writeAll(" ");
|
||||
is_first = false;
|
||||
try writer.writeAll(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isEmpty(this: T) bool {
|
||||
return @as(u8, @bitCast(this)) == 0;
|
||||
}
|
||||
|
||||
pub fn get() T {
|
||||
const this: T = @bitCast(bun_cpu_features());
|
||||
|
||||
// sanity check
|
||||
assert(this.none == false and this.padding == 0);
|
||||
|
||||
if (bun.Environment.isX64) {
|
||||
bun.analytics.Features.no_avx += @as(usize, @intFromBool(!this.avx));
|
||||
bun.analytics.Features.no_avx2 += @as(usize, @intFromBool(!this.avx2));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const X86CPUFeatures = packed struct(u8) {
|
||||
none: bool = false,
|
||||
|
||||
sse42: bool = false,
|
||||
popcnt: bool = false,
|
||||
avx: bool = false,
|
||||
avx2: bool = false,
|
||||
avx512: bool = false,
|
||||
|
||||
padding: u2 = 0,
|
||||
|
||||
pub usingnamespace Impl(@This());
|
||||
};
|
||||
const AArch64CPUFeatures = packed struct(u8) {
|
||||
none: bool = false,
|
||||
|
||||
neon: bool = false,
|
||||
fp: bool = false,
|
||||
aes: bool = false,
|
||||
crc32: bool = false,
|
||||
atomics: bool = false,
|
||||
sve: bool = false,
|
||||
|
||||
padding: u1 = 0,
|
||||
|
||||
pub usingnamespace Impl(@This());
|
||||
};
|
||||
|
||||
pub const CPUFeatures = if (bun.Environment.isX64)
|
||||
X86CPUFeatures
|
||||
else if (bun.Environment.isAarch64)
|
||||
AArch64CPUFeatures
|
||||
else
|
||||
struct {
|
||||
pub fn get() @This() {
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn format(_: @This(), comptime _: []const u8, _: anytype, _: anytype) !void {}
|
||||
|
||||
pub fn isEmpty(_: @This()) bool {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" fn bun_cpu_features() u8;
|
||||
|
||||
const assert = bun.debugAssert;
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "root.h"
|
||||
#include "wtf/dtoa.h"
|
||||
#include "wtf/text/StringView.h"
|
||||
#include "JavaScriptCore/JSGlobalObjectFunctions.h"
|
||||
#include <cstring>
|
||||
|
||||
/// Must be called with a buffer of exactly 124
|
||||
@@ -11,11 +9,3 @@ extern "C" void WTF__dtoa(char* buf_124_bytes, double number)
|
||||
NumberToStringBuffer& buf = *reinterpret_cast<NumberToStringBuffer*>(buf_124_bytes);
|
||||
WTF::numberToString(number, buf);
|
||||
}
|
||||
|
||||
/// This is the equivalent of the unary '+' operator on a JS string
|
||||
/// See https://262.ecma-international.org/14.0/#sec-stringtonumber
|
||||
/// Grammar: https://262.ecma-international.org/14.0/#prod-StringNumericLiteral
|
||||
extern "C" double JSC__jsToNumber(char* latin1_ptr, size_t len)
|
||||
{
|
||||
return JSC::jsToNumber(WTF::StringView(latin1_ptr, len, true));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user