Compare commits

..

1 Commits

Author SHA1 Message Date
Dylan Conway
2c47a8e45b progress 2024-07-02 19:26:58 -07:00
348 changed files with 5551 additions and 20860 deletions

View File

@@ -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 }}

View File

@@ -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)" `

View File

@@ -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' }}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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
View File

@@ -145,4 +145,3 @@ zig-cache
zig-out
test/node.js/upstream
.zig-cache
scripts/env.local

8
.gitmodules vendored
View File

@@ -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
View File

@@ -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",
},

View File

@@ -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()

View File

@@ -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
```

View File

@@ -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

2
LATEST
View File

@@ -1 +1 @@
1.1.20
1.1.17

View File

@@ -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)

Binary file not shown.

View File

@@ -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",

View File

@@ -6,7 +6,6 @@ const App = () => (
<html>
<body>
<h1>Hello World</h1>
<p>This is an example.</p>
</body>
</html>
);

View File

@@ -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
View File

@@ -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)});
}
}

BIN
bun.lockb

Binary file not shown.

View File

@@ -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";

View File

@@ -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' \

View File

@@ -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'

View File

@@ -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);
```

View File

@@ -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]`.

View File

@@ -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
---

View File

@@ -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

View File

@@ -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
```
---

View File

@@ -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",

View File

@@ -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>
```

View File

@@ -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.

View File

@@ -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):

View File

@@ -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 %}

View File

@@ -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`"),

View File

@@ -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 %}

View File

@@ -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
---

View File

@@ -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

View File

@@ -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');
});
```

View File

@@ -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",

View File

@@ -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`",
"": ""
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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());
* ```
*/

View File

@@ -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.

View File

@@ -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

View File

@@ -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();

View File

@@ -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; }

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();

View File

@@ -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_.?;
}
};

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 {

View 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()) });
}
}
}

View File

@@ -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 => {},

View File

@@ -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;
}

View File

@@ -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));
}

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,
}),
];

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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());
}

View File

@@ -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));

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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