Compare commits

..

1 Commits

Author SHA1 Message Date
Dylan Conway
baa8934545 some of it 2023-09-20 00:25:59 -07:00
459 changed files with 13235 additions and 38943 deletions

View File

@@ -8,7 +8,7 @@ body:
Thank you for submitting an idea. It helps make Bun better.
If you want to discuss Bun, or learn how others are using Bun, please
join our [Discord](https://discord.gg/CXdq2DP29u) server, where you can share in the [`#feedback`](https://discord.gg/unwUnHBNqy) channel.
join our [Discord](https://discord.gg/CXdq2DP29u) server, where you can share in the [`#feedback-ideas`](https://discord.gg/unwUnHBNqy) channel.
- type: textarea
attributes:
label: What is the problem this feature would solve?

View File

@@ -0,0 +1,50 @@
name: bun-ecosystem-test
on:
schedule:
- cron: "0 15 * * *" # every day at 7am PST
workflow_dispatch:
inputs:
version:
description: "The version of Bun to run"
required: true
default: "canary"
type: string
jobs:
test:
name: ${{ matrix.tag }}
runs-on: ${{ matrix.os }}
if: github.repository_owner == 'oven-sh'
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
tag: linux-x64
url: linux/x64?avx2=true
- os: ubuntu-latest
tag: linux-x64-baseline
url: linux/x64?baseline=true
# FIXME: runner fails with "No tests found"?
#- os: macos-latest
# tag: darwin-x64
# url: darwin/x64?avx2=true
- os: macos-latest
tag: darwin-x64-baseline
url: darwin/x64?baseline=true
steps:
- id: checkout
name: Checkout
uses: Bhacaz/checkout-files@v2
with:
files: packages/bun-internal-test
- id: setup
name: Setup
uses: oven-sh/setup-bun@v1
with:
bun-download-url: https://bun.sh/download/${{ github.event.inputs.version }}/${{ matrix.url }}
- id: test
name: Test
working-directory: packages/bun-internal-test
run: bun run test:ecosystem

View File

@@ -37,7 +37,7 @@ jobs:
arch: aarch64
build_arch: arm64
runner: linux-arm64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-arm64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-linux-arm64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-arm64-lto"
build_machine_arch: aarch64

View File

@@ -47,7 +47,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
- cpu: nehalem
@@ -55,7 +55,7 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-linux-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
@@ -153,33 +153,13 @@ jobs:
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/bun-${{matrix.tag}}.zip,${{runner.temp}}/release/bun-${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
noprefix: true
nocontext: true
description: |
Pull Request
### [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}
Build failed on ${{ matrix.tag }}:
**[View build output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
[Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
linux-test:
name: Tests ${{matrix.tag}}
runs-on: ubuntu-latest
needs: [linux]
if: github.event_name == 'pull_request'
timeout-minutes: 20
permissions:
pull-requests: write
outputs:
failing_tests: ${{ steps.test.outputs.failing_tests }}
failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
@@ -201,8 +181,8 @@ jobs:
with:
name: bun-${{matrix.tag}}
path: ${{runner.temp}}/release
- id: install-bun
name: Install Bun
- id: install
name: Install
run: |
cd ${{runner.temp}}/release
unzip bun-${{matrix.tag}}.zip
@@ -210,13 +190,6 @@ jobs:
chmod +x bun
pwd >> $GITHUB_PATH
./bun --version
- id: install-dependnecies
name: Install dependencies
run: |
sudo apt-get update && sudo apt-get install -y openssl
bun install --verbose
bun install --cwd=test --verbose
bun install --cwd=packages/bun-internal-test --verbose
- id: test
name: Test (node runner)
env:
@@ -225,24 +198,11 @@ jobs:
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
# if: ${{github.event.inputs.use_bun == 'false'}}
run: |
sudo apt-get update && sudo apt-get install -y openssl
bun install
bun install --cwd test
bun install --cwd packages/bun-internal-test
node packages/bun-internal-test/src/runner.node.mjs || true
- uses: sarisia/actions-status-discord@v1
if: always() && steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: "failure"
noprefix: true
nocontext: true
description: |
Pull Request
### ❌ [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}, there are ${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:
${{ steps.test.outputs.failing_tests }}
**[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
- name: Comment on PR
if: steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v2

View File

@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: native
@@ -152,7 +152,7 @@ jobs:
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
artifact: bun-obj-darwin-aarch64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
dependencies: true
compile_obj: true
@@ -258,7 +258,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -266,14 +266,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: native
arch: aarch64
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
package: bun-darwin-aarch64
artifact: bun-obj-darwin-aarch64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
steps:
- uses: actions/checkout@v3
@@ -393,32 +393,11 @@ jobs:
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
noprefix: true
nocontext: true
description: |
Pull Request
### [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}
Build failed on ${{ matrix.tag }}:
**[View build output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
[Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
macOS-test:
name: Tests ${{matrix.tag}}
runs-on: ${{ matrix.runner }}
needs: [macOS]
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
permissions:
pull-requests: write
timeout-minutes: 30
outputs:
failing_tests: ${{ steps.test.outputs.failing_tests }}
@@ -441,8 +420,8 @@ jobs:
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release
- id: install-bun
name: Install Bun
- id: install
name: Install
run: |
cd ${{runner.temp}}/release
unzip ${{matrix.tag}}.zip
@@ -450,12 +429,6 @@ jobs:
chmod +x bun
pwd >> $GITHUB_PATH
./bun --version
- id: install
name: Install dependencies
run: |
bun install --verbose
bun install --cwd=test --verbose
bun install --cwd=packages/bun-internal-test --verbose
- id: test
name: Test (node runner)
env:
@@ -464,24 +437,10 @@ jobs:
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
# if: ${{github.event.inputs.use_bun == 'false'}}
run: |
bun install
bun install --cwd test
bun install --cwd packages/bun-internal-test
node packages/bun-internal-test/src/runner.node.mjs || true
- uses: sarisia/actions-status-discord@v1
if: always() && steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: "failure"
noprefix: true
nocontext: true
description: |
Pull Request
### ❌ [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}, there are ${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:
${{ steps.test.outputs.failing_tests }}
**[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
- name: Comment on PR
if: steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v2

View File

@@ -117,7 +117,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-12
artifact: bun-obj-darwin-x64-baseline
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: haswell
@@ -126,7 +126,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
obj: bun-obj-darwin-x64-baseline
runner: macos-12
artifact: bun-obj-darwin-x64-baseline
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: haswell
@@ -144,7 +144,7 @@ jobs:
# obj: bun-obj-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -259,7 +259,7 @@ jobs:
package: bun-darwin-x64
runner: macos-12
artifact: bun-obj-darwin-x64-baseline
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
@@ -267,14 +267,14 @@ jobs:
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
@@ -397,32 +397,11 @@ jobs:
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
noprefix: true
nocontext: true
description: |
Pull Request
### [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}
Build failed on ${{ matrix.tag }}:
**[View build output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
[Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
macOS-test:
name: Tests ${{matrix.tag}}
runs-on: ${{ matrix.runner }}
needs: [macOS]
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
permissions:
pull-requests: write
timeout-minutes: 30
outputs:
failing_tests: ${{ steps.test.outputs.failing_tests }}
@@ -445,8 +424,8 @@ jobs:
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release
- id: install-bun
name: Install Bun
- id: install
name: Install
run: |
cd ${{runner.temp}}/release
unzip ${{matrix.tag}}.zip
@@ -454,12 +433,6 @@ jobs:
chmod +x bun
pwd >> $GITHUB_PATH
./bun --version
- id: install
name: Install dependencies
run: |
bun install --verbose
bun install --cwd=test --verbose
bun install --cwd=packages/bun-internal-test --verbose
- id: test
name: Test (node runner)
env:
@@ -468,27 +441,10 @@ jobs:
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
# if: ${{github.event.inputs.use_bun == 'false'}}
run: |
bun install
bun install --cwd test
bun install --cwd packages/bun-internal-test
node packages/bun-internal-test/src/runner.node.mjs || true
- uses: sarisia/actions-status-discord@v1
if: always() && steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: "failure"
noprefix: true
nocontext: true
description: |
Pull Request
### ❌ [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
Hey @${{ github.actor }},
${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:
${{ steps.test.outputs.failing_tests }}
**[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
- name: Comment on PR
if: steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v2

View File

@@ -117,7 +117,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: haswell
@@ -126,7 +126,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-12
artifact: bun-obj-darwin-x64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: nehalem
@@ -135,7 +135,7 @@ jobs:
# obj: bun-obj-darwin-x64-baseline
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: haswell
@@ -144,7 +144,7 @@ jobs:
obj: bun-obj-darwin-x64
runner: macos-12
artifact: bun-obj-darwin-x64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: native
@@ -152,7 +152,7 @@ jobs:
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
@@ -261,7 +261,7 @@ jobs:
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64-baseline
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
@@ -269,14 +269,14 @@ jobs:
package: bun-darwin-x64
runner: macos-12
artifact: bun-obj-darwin-x64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-amd64-lto.tar.gz"
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3/bun-webkit-macos-arm64-lto.tar.gz"
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-sept15-1/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
@@ -399,32 +399,11 @@ jobs:
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
noprefix: true
nocontext: true
description: |
Pull Request
### [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}
Build failed on ${{ matrix.tag }}:
**[View build output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
[Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
macOS-test:
name: Tests ${{matrix.tag}}
runs-on: ${{ matrix.runner }}
needs: [macOS]
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
permissions:
pull-requests: write
timeout-minutes: 30
outputs:
failing_tests: ${{ steps.test.outputs.failing_tests }}
@@ -447,8 +426,8 @@ jobs:
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release
- id: install-bun
name: Install Bun
- id: install
name: Install
run: |
cd ${{runner.temp}}/release
unzip ${{matrix.tag}}.zip
@@ -456,12 +435,6 @@ jobs:
chmod +x bun
pwd >> $GITHUB_PATH
./bun --version
- id: install
name: Install dependencies
run: |
bun install --verbose
bun install --cwd=test --verbose
bun install --cwd=packages/bun-internal-test --verbose
- id: test
name: Test (node runner)
env:
@@ -470,24 +443,10 @@ jobs:
TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
# if: ${{github.event.inputs.use_bun == 'false'}}
run: |
bun install
bun install --cwd test
bun install --cwd packages/bun-internal-test
node packages/bun-internal-test/src/runner.node.mjs || true
- uses: sarisia/actions-status-discord@v1
if: always() && steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
with:
title: ""
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: "failure"
noprefix: true
nocontext: true
description: |
Pull Request
### ❌ [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})
@${{ github.actor }}, there are ${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:
${{ steps.test.outputs.failing_tests }}
**[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
- name: Comment on PR
if: steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v2

179
.github/workflows/bun-release-canary.yml vendored Normal file
View File

@@ -0,0 +1,179 @@
name: bun-release-canary
concurrency: release-canary
on:
schedule:
- cron: "0 14 * * *" # every day at 6am PST
workflow_dispatch:
jobs:
sign:
name: Sign Release
runs-on: ubuntu-latest
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- id: checkout
name: Checkout
uses: actions/checkout@v3
- id: setup-gpg
name: Setup GPG
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- id: bun-run
name: Sign Release
run: |
echo "$GPG_PASSPHRASE" | bun upload-assets -- "canary"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
npm:
name: Release to NPM
runs-on: ubuntu-latest
needs: sign
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- id: checkout
name: Checkout
uses: actions/checkout@v3
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- id: bun-run
name: Release
run: bun upload-npm -- canary publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# npm-types:
# name: Release types to NPM
# runs-on: ubuntu-latest
# defaults:
# run:
# working-directory: packages/bun-types
# steps:
# - id: checkout
# name: Checkout
# uses: actions/checkout@v3
# - id: setup-node
# name: Setup Node.js
# uses: actions/setup-node@v3
# with:
# node-version: latest
# - id: setup-bun
# name: Setup Bun
# uses: oven-sh/setup-bun@v1
# with:
# bun-version: canary
# - id: bun-install
# name: Install Dependencies
# run: bun install
# - id: setup-env
# name: Setup Environment
# run: |
# SHA=$(git rev-parse --short "$GITHUB_SHA")
# VERSION=$(bun --version)
# TAG="${VERSION}-canary.$(date '+%Y%m%d').1+${SHA}"
# echo "Setup tag: ${TAG}"
# echo "TAG=${TAG}" >> ${GITHUB_ENV}
# - id: bun-run
# name: Build
# run: bun run build
# env:
# BUN_VERSION: ${{ env.TAG }}
# - id: npm-publish
# name: Release
# uses: JS-DevTools/npm-publish@v1
# with:
# package: packages/bun-types/dist/package.json
# token: ${{ secrets.NPM_TOKEN }}
# tag: canary
docker:
name: Release to Dockerhub
runs-on: ubuntu-latest
needs: sign
if: github.repository_owner == 'oven-sh'
steps:
- id: checkout
name: Checkout
uses: actions/checkout@v3
- id: qemu
name: Setup Docker QEMU
uses: docker/setup-qemu-action@v2
- id: buildx
name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
with:
platforms: linux/amd64,linux/arm64
- id: metadata
name: Setup Docker metadata
uses: docker/metadata-action@v4
with:
images: oven/bun
tags: canary
- id: login
name: Login to Docker
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- id: push
name: Push to Docker
uses: docker/build-push-action@v3
with:
context: ./dockerhub
file: ./dockerhub/Dockerfile-debian
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
build-args: |
BUN_VERSION=canary
s3:
name: Upload to S3
runs-on: ubuntu-latest
needs: sign
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- id: checkout
name: Checkout
uses: actions/checkout@v3
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- id: bun-run
name: Release
run: bun upload-s3 -- canary
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
AWS_BUCKET: bun

View File

@@ -0,0 +1,54 @@
name: bun-release-types-canary
concurrency: release-canary
on:
push:
branches:
- main
paths:
- "packages/bun-types/**"
workflow_dispatch:
jobs:
npm-types:
name: Release types to NPM
runs-on: ubuntu-latest
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-types
steps:
- id: checkout
name: Checkout
uses: actions/checkout@v3
- id: setup-node
name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: latest
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- id: setup-env
name: Setup Environment
run: |
SHA=$(git rev-parse --short "$GITHUB_SHA")
VERSION=$(bun --version)
TAG="${VERSION}-canary.$(date +'%Y%m%dT%H%M%S')"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: bun-run
name: Build
run: bun run build
env:
BUN_VERSION: ${{ env.TAG }}
- id: npm-publish
name: Release
uses: JS-DevTools/npm-publish@v1
with:
package: packages/bun-types/dist/package.json
token: ${{ secrets.NPM_TOKEN }}
tag: canary

View File

@@ -1,95 +1,87 @@
name: bun-release
concurrency: release
env:
BUN_VERSION: ${{ github.event.inputs.tag || github.event.release.tag_name || 'canary' }}
BUN_LATEST: ${{ github.event.inputs.is-latest || github.event.release.prerelease == 'false' }}
on:
release:
types:
- published
schedule:
- cron: "0 14 * * *" # every day at 6am PST
workflow_dispatch:
inputs:
is-latest:
description: Is this the latest release?
type: boolean
default: false
tag:
type: string
description: What is the release tag? (e.g. "1.0.2", "canary")
description: The tag to publish
required: true
use-docker:
description: Should Docker images be released?
type: boolean
default: false
use-npm:
description: Should npm packages be published?
type: boolean
default: false
use-homebrew:
description: Should binaries be released to Homebrew?
type: boolean
default: false
use-s3:
description: Should binaries be uploaded to S3?
type: boolean
default: false
use-types:
description: Should types be released to npm?
type: boolean
default: false
jobs:
sign:
name: Sign Release
permissions: write-all
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'oven-sh' }}
permissions:
contents: write
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
- name: Setup GPG
- id: setup-env
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: setup-gpg
name: Setup GPG
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
- name: Setup Bun
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- name: Sign Release
- id: bun-run
name: Sign Release
run: |
echo "$GPG_PASSPHRASE" | bun upload-assets -- "${{ env.BUN_VERSION }}"
echo "$GPG_PASSPHRASE" | bun upload-assets -- "${{ env.TAG }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
npm:
name: Release to NPM
runs-on: ubuntu-latest
permissions: write-all
needs: sign
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.use-npm == 'true' }}
permissions:
contents: read
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
- name: Setup Bun
- id: setup-env
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- name: Release
run: bun upload-npm -- "${{ env.BUN_VERSION }}" publish
- id: bun-run
name: Release
run: bun upload-npm -- "${{ env.TAG }}" publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -97,45 +89,41 @@ jobs:
name: Release types to NPM
runs-on: ubuntu-latest
needs: sign
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.use-types == 'true' }}
permissions:
contents: read
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-types
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
- id: setup-env
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: setup-node
name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: latest
- name: Setup Bun
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- name: Setup Tag
if: ${{ env.BUN_VERSION == 'canary' }}
run: |
VERSION=$(bun --version)
TAG="${VERSION}-canary.$(date +'%Y%m%dT%H%M%S')"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- name: Build
- id: bun-run
name: Build
run: bun run build
env:
BUN_VERSION: ${{ env.TAG || env.BUN_VERSION }}
- name: Release (canary)
if: ${{ env.BUN_VERSION == 'canary' }}
uses: JS-DevTools/npm-publish@v1
with:
package: packages/bun-types/dist/package.json
token: ${{ secrets.NPM_TOKEN }}
tag: canary
- name: Release (latest)
if: ${{ env.BUN_LATEST == 'true' }}
BUN_VERSION: ${{ env.TAG }}
- id: npm-publish
name: Release
uses: JS-DevTools/npm-publish@v1
with:
package: packages/bun-types/dist/package.json
@@ -144,28 +132,20 @@ jobs:
name: Release to Dockerhub
runs-on: ubuntu-latest
needs: sign
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.use-docker == 'true' }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- variant: debian
suffix: ''
- variant: debian
suffix: -debian
- variant: slim
suffix: -slim
dir: debian-slim
- variant: alpine
suffix: -alpine
- variant: distroless
suffix: -distroless
if: github.repository_owner == 'oven-sh'
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
- name: Setup Docker emulator
- id: environment
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: qemu
name: Setup Docker QEMU
uses: docker/setup-qemu-action@v2
- id: buildx
name: Setup Docker buildx
@@ -177,84 +157,102 @@ jobs:
uses: docker/metadata-action@v4
with:
images: oven/bun
flavor: |
latest=false
tags: |
type=raw,value=latest,enable=${{ env.BUN_LATEST == 'true' && matrix.suffix == '' }}
type=raw,value=${{ matrix.variant }},enable=${{ env.BUN_LATEST == 'true' }}
type=match,pattern=(bun-v)?(canary|\d+.\d+.\d+),group=2,value=${{ env.BUN_VERSION }},suffix=${{ matrix.suffix }}
type=match,pattern=(bun-v)?(canary|\d+.\d+),group=2,value=${{ env.BUN_VERSION }},suffix=${{ matrix.suffix }}
type=match,pattern=(bun-v)?(canary|\d+),group=2,value=${{ env.BUN_VERSION }},suffix=${{ matrix.suffix }}
- name: Login to Docker
type=match,pattern=(bun-v)?(\d+.\d+.\d+),group=2,value=${{ env.TAG }}
type=match,pattern=(bun-v)?(\d+.\d+),group=2,value=${{ env.TAG }}
- id: login
name: Login to Docker
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push to Docker
- id: push
name: Push to Docker
uses: docker/build-push-action@v3
with:
context: ./dockerhub/${{ matrix.dir || matrix.variant }}
context: ./dockerhub
file: ./dockerhub/Dockerfile-debian
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
build-args: |
BUN_VERSION=${{ env.BUN_VERSION }}
BUN_VERSION=${{ env.TAG }}
homebrew:
name: Release to Homebrew
permissions: write-all
runs-on: ubuntu-latest
needs: sign
permissions:
contents: read
if: ${{ github.event_name == 'release' || github.event.inputs.use-homebrew == 'true' }}
if: github.repository_owner == 'oven-sh'
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
with:
repository: oven-sh/homebrew-bun
token: ${{ secrets.ROBOBUN_TOKEN }}
- id: gpg
- id: setup-gpg
name: Setup GPG
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
- name: Setup Ruby
- id: setup-env
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: setup-ruby
name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "2.6"
- name: Update Tap
run: ruby scripts/release.rb "${{ env.BUN_VERSION }}"
- name: Commit Tap
- id: update-tap
name: Update Tap
run: ruby scripts/release.rb "${{ env.TAG }}"
- id: commit-tap
name: Commit Tap
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_options: --gpg-sign=${{ steps.gpg.outputs.keyid }}
commit_message: Release ${{ env.BUN_VERSION }}
commit_options: --gpg-sign=${{ steps.setup-gpg.outputs.keyid }}
commit_message: Release ${{ env.TAG }}
commit_user_name: robobun
commit_user_email: robobun@oven.sh
commit_author: robobun <robobun@oven.sh>
s3:
name: Upload to S3
runs-on: ubuntu-latest
permissions: write-all
needs: sign
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.use-s3 == 'true' }}
permissions:
contents: read
if: github.repository_owner == 'oven-sh'
defaults:
run:
working-directory: packages/bun-release
steps:
- name: Checkout
- id: checkout
name: Checkout
uses: actions/checkout@v3
- name: Setup Bun
- id: setup-env
name: Setup Environment
run: |
TAG="${{ github.event.inputs.tag }}"
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
echo "Setup tag: ${TAG}"
echo "TAG=${TAG}" >> ${GITHUB_ENV}
- id: setup-bun
name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
bun-version: canary
- id: bun-install
name: Install Dependencies
run: bun install
- name: Release
run: bun upload-s3 -- "${{ env.BUN_VERSION }}"
- id: bun-run
name: Release
run: bun upload-s3 -- "${{ env.TAG }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}

View File

@@ -12,8 +12,6 @@ jobs:
prettier-fmt:
name: prettier
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
prettier_fmt_errs: ${{ steps.fmt.outputs.prettier_fmt_errs }}
steps:

View File

@@ -18,8 +18,6 @@ jobs:
zig-fmt:
name: zig fmt
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
zig_fmt_errs: ${{ steps.fmt.outputs.zig_fmt_errs }}
steps:

4
.gitignore vendored
View File

@@ -6,7 +6,6 @@ packages/*/*.wasm
profile.json
node_modules
.envrc
.swcrc
yarn.lock
dist
@@ -124,7 +123,6 @@ cold-jsc-start
cold-jsc-start.d
/test.ts
/test.js
src/js/out/modules*
src/js/out/functions*
@@ -134,4 +132,4 @@ src/js/out/DebugPath.h
make-dev-stats.csv
.uuid
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo

View File

@@ -27,8 +27,7 @@
"editor.formatOnSave": true
},
"zig.zls.enableInlayHints": false,
"zig.zls.enabled": true,
"git.ignoreSubmodules": true,
"[jsx]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
@@ -81,9 +80,7 @@
"src/deps/zstd": true,
"test/snippets/package-json-exports/_node_modules_copy": true,
"src/js/out": true,
"packages/bun-uws/fuzzing/seed-corpus/": true,
"**/*.dep": true,
"**/CMakeFiles": true
"src/packages/bun-uws/fuzzing/seed-corpus/": true
},
"C_Cpp.files.exclude": {
"**/.vscode": true,

View File

@@ -10,7 +10,7 @@ ARG ARCH=x86_64
ARG BUILD_MACHINE_ARCH=x86_64
ARG TRIPLET=${ARCH}-linux-gnu
ARG BUILDARCH=amd64
ARG WEBKIT_TAG=2023-oct3
ARG WEBKIT_TAG=2023-sept15
ARG ZIG_TAG=jul1
ARG ZIG_VERSION="0.12.0-dev.163+6780a6bbf"
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
@@ -286,7 +286,6 @@ COPY packages/bun-uws ${BUN_DIR}/packages/bun-uws
COPY packages/bun-usockets ${BUN_DIR}/packages/bun-usockets
COPY src/deps/zlib ${BUN_DIR}/src/deps/zlib
COPY src/deps/boringssl/include ${BUN_DIR}/src/deps/boringssl/include
COPY src/deps/c-ares/include ${BUN_DIR}/src/deps/c-ares/include
COPY src/deps/libuwsockets.cpp ${BUN_DIR}/src/deps/libuwsockets.cpp
COPY src/deps/_libusockets.h ${BUN_DIR}/src/deps/_libusockets.h

View File

@@ -1291,7 +1291,7 @@ jsc-build-linux-compile-config:
jsc-build-linux-compile-build:
mkdir -p $(WEBKIT_RELEASE_DIR) && \
cd $(WEBKIT_RELEASE_DIR) && \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects" -DUSE_BUN_JSC_ADDITIONS=ON \
cmake --build $(WEBKIT_RELEASE_DIR) --config relwithdebuginfo --target jsc

View File

@@ -31,7 +31,7 @@ Bun is an all-in-one toolkit for JavaScript and TypeScript apps. It ships as a s
At its core is the _Bun runtime_, a fast JavaScript runtime designed as a drop-in replacement for Node.js. It's written in Zig and powered by JavaScriptCore under the hood, dramatically reducing startup times and memory usage.
```bash
bun run index.tsx # TS and JSX supported out-of-the-box
bun run index.tsx # TS and JSX supported out of the box
```
The `bun` command-line tool also implements a test runner, script runner, and Node.js-compatible package manager. Instead of 1,000 node_modules for development, you only need `bun`. Bun's built-in tools are significantly faster than existing options and usable in existing Node.js projects with little to no changes.
@@ -93,8 +93,7 @@ bun upgrade --canary
- [`bun run`](https://bun.sh/docs/cli/run)
- [`bun install`](https://bun.sh/docs/cli/install)
- [`bun test`](https://bun.sh/docs/cli/test)
- [`bun init`](https://bun.sh/docs/templates#bun-init)
- [`bun create`](https://bun.sh/docs/templates#bun-create)
- [`bun create`](https://bun.sh/docs/cli/create)
- [`bunx`](https://bun.sh/docs/cli/bunx)
- Runtime
- [Runtime](https://bun.sh/docs/runtime/index)

View File

@@ -77,24 +77,4 @@ bench("ConventionalPrivates", () => {
new Foo().run();
});
const _state = Symbol("state");
const _inc = Symbol("inc");
bench("SymbolPrivates", () => {
class Foo {
[_state] = 1;
[_inc] = 13;
run() {
let n = 1000000;
while (n-- > 0) {
this[_state] += this[_inc];
}
return n;
}
}
new Foo().run();
});
await run();

View File

@@ -1,22 +0,0 @@
import { tmpdir } from "node:os";
import { promises, existsSync, mkdirSync } from "node:fs";
const count = 1024 * 12;
var queue = new Array(count);
var paths = new Array(count);
for (let i = 0; i < count; i++) {
const path = `${tmpdir()}/${Date.now()}.rm.dir${i}`;
try {
mkdirSync(path);
} catch (e) {}
paths[i] = path;
queue[i] = promises.rmdir(path);
}
await Promise.all(queue);
for (let i = 0; i < count; i++) {
if (existsSync(paths[i])) {
throw new Error(`Path ${paths[i]} was not removed`);
}
}

BIN
bun.lockb

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
# bun:alpine
# Not officially supported (yet)
ARG GLIBC_RELEASE=2.35-r0
FROM alpine:latest AS build
WORKDIR /tmp
RUN apk --no-cache add unzip
ARG GLIBC_RELEASE
RUN wget https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_RELEASE}/glibc-${GLIBC_RELEASE}.apk
ADD https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip bun-linux-x64.zip
RUN unzip bun-linux-x64.zip
FROM alpine:latest
ARG GLIBC_RELEASE
COPY --from=build /tmp/sgerrand.rsa.pub /etc/apk/keys
COPY --from=build /tmp/glibc-${GLIBC_RELEASE}.apk /tmp
COPY --from=build /tmp/bun-linux-x64/bun /usr/local/bin
RUN apk --no-cache --force-overwrite add /tmp/glibc-${GLIBC_RELEASE}.apk \
&& rm /etc/apk/keys/sgerrand.rsa.pub \
&& rm /tmp/glibc-${GLIBC_RELEASE}.apk
RUN bun --version

View File

@@ -0,0 +1,77 @@
FROM debian:bullseye-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest
RUN apt-get update -qq \
&& apt-get install -qq --no-install-recommends \
ca-certificates \
curl \
dirmngr \
gpg \
gpg-agent \
unzip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& arch="$(dpkg --print-architecture)" \
&& case "${arch##*-}" in \
amd64) build="x64-baseline";; \
arm64) build="aarch64";; \
*) echo "error: unsupported architecture: ($arch)"; exit 1 ;; \
esac \
&& version="$BUN_VERSION" \
&& case "$version" in \
latest | canary | bun-v*) tag="$version"; ;; \
v*) tag="bun-$version"; ;; \
*) tag="bun-v$version"; ;; \
esac \
&& case "$tag" in \
latest) release="latest/download"; ;; \
*) release="download/$tag"; ;; \
esac \
&& curl "https://github.com/oven-sh/bun/releases/$release/bun-linux-$build.zip" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: unknown release: ($tag)" && exit 1) \
&& for key in \
"F3DCC08A8572C0749B3E18888EAB4D40A7B22B59" \
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" \
|| gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& gpg --update-trustdb \
&& curl "https://github.com/oven-sh/bun/releases/$release/SHASUMS256.txt.asc" \
-fsSLO \
--compressed \
--retry 5 \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& grep " bun-linux-$build.zip\$" SHASUMS256.txt | sha256sum -c - \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& unzip "bun-linux-$build.zip" \
&& mv "bun-linux-$build/bun" /usr/local/bin/bun \
&& rm -f "bun-linux-$build.zip" SHASUMS256.txt.asc SHASUMS256.txt \
&& chmod +x /usr/local/bin/bun \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
FROM debian:bullseye-slim
RUN groupadd bun \
--gid 1000 \
&& useradd bun \
--uid 1000 \
--gid bun \
--shell /bin/sh \
--create-home
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin
COPY --from=build /usr/local/bin/bunx /usr/local/bin
WORKDIR /home/bun/app
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/usr/local/bin/bun"]

View File

@@ -1,4 +1,5 @@
FROM debian:bullseye-slim AS build
# Not officially supported (yet)
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest
@@ -17,7 +18,7 @@ RUN apt-get update -qq \
&& case "${arch##*-}" in \
amd64) build="x64-baseline";; \
arm64) build="aarch64";; \
*) echo "error: unsupported architecture: $arch"; exit 1 ;; \
*) echo "error: unsupported architecture: ($arch)"; exit 1 ;; \
esac \
&& version="$BUN_VERSION" \
&& case "$version" in \
@@ -33,37 +34,36 @@ RUN apt-get update -qq \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: $tag" && exit 1) \
|| (echo "error: unknown release: ($tag)" && exit 1) \
&& for key in \
"F3DCC08A8572C0749B3E18888EAB4D40A7B22B59" \
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" \
|| gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& gpg --update-trustdb \
&& curl "https://github.com/oven-sh/bun/releases/$release/SHASUMS256.txt.asc" \
-fsSLO \
--compressed \
--retry 5 \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& grep " bun-linux-$build.zip\$" SHASUMS256.txt | sha256sum -c - \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& unzip "bun-linux-$build.zip" \
&& mv "bun-linux-$build/bun" /usr/local/bin/bun \
&& rm -f "bun-linux-$build.zip" SHASUMS256.txt.asc SHASUMS256.txt \
&& chmod +x /usr/local/bin/bun \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
FROM gcr.io/distroless/base-nossl-debian11
COPY --from=build /usr/local/bin/bun /usr/local/bin/
# Temporarily use the `build`-stage image binaries to create a symlink:
RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \
--mount=type=bind,from=build,source=/bin,target=/bin <<EOF
ln -s /usr/local/bin/bun /usr/local/bin/bunx
which bunx
EOF
COPY --from=build /usr/local/bin/bun /usr/local/bin
COPY --from=build /usr/local/bin/bunx /usr/local/bin
WORKDIR /app
ENTRYPOINT ["/usr/local/bin/bun"]
CMD ["/usr/local/bin/bun"]

View File

@@ -1,113 +0,0 @@
FROM alpine:3.18 AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest
# TODO: Instead of downloading glibc from a third-party source, we should
# build it from source. This is a temporary solution.
# See: https://github.com/sgerrand/alpine-pkg-glibc
# https://github.com/sgerrand/alpine-pkg-glibc/releases
# https://github.com/sgerrand/alpine-pkg-glibc/issues/176
ARG GLIBC_VERSION=2.34-r0
# https://github.com/oven-sh/bun/issues/5545#issuecomment-1722461083
ARG GLIBC_VERSION_AARCH64=2.26-r1
RUN apk --no-cache add \
ca-certificates \
curl \
dirmngr \
gpg \
gpg-agent \
unzip \
&& arch="$(apk --print-arch)" \
&& case "${arch##*-}" in \
x86_64) build="x64-baseline";; \
aarch64) build="aarch64";; \
*) echo "error: unsupported architecture: $arch"; exit 1 ;; \
esac \
&& version="$BUN_VERSION" \
&& case "$version" in \
latest | canary | bun-v*) tag="$version"; ;; \
v*) tag="bun-$version"; ;; \
*) tag="bun-v$version"; ;; \
esac \
&& case "$tag" in \
latest) release="latest/download"; ;; \
*) release="download/$tag"; ;; \
esac \
&& curl "https://github.com/oven-sh/bun/releases/$release/bun-linux-$build.zip" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: $tag" && exit 1) \
&& for key in \
"F3DCC08A8572C0749B3E18888EAB4D40A7B22B59" \
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" \
|| gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& curl "https://github.com/oven-sh/bun/releases/$release/SHASUMS256.txt.asc" \
-fsSLO \
--compressed \
--retry 5 \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|| (echo "error: failed to verify: $tag" && exit 1) \
&& grep " bun-linux-$build.zip\$" SHASUMS256.txt | sha256sum -c - \
|| (echo "error: failed to verify: $tag" && exit 1) \
&& unzip "bun-linux-$build.zip" \
&& mv "bun-linux-$build/bun" /usr/local/bin/bun \
&& rm -f "bun-linux-$build.zip" SHASUMS256.txt.asc SHASUMS256.txt \
&& chmod +x /usr/local/bin/bun \
&& cd /tmp \
&& case "${arch##*-}" in \
x86_64) curl "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: glibc v${GLIBC_VERSION}" && exit 1) \
&& mv "glibc-${GLIBC_VERSION}.apk" glibc.apk \
&& curl "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: glibc-bin v${GLIBC_VERSION}" && exit 1) \
&& mv "glibc-bin-${GLIBC_VERSION}.apk" glibc-bin.apk ;; \
aarch64) curl "https://raw.githubusercontent.com/squishyu/alpine-pkg-glibc-aarch64-bin/master/glibc-${GLIBC_VERSION_AARCH64}.apk" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: glibc v${GLIBC_VERSION_AARCH64}" && exit 1) \
&& mv "glibc-${GLIBC_VERSION_AARCH64}.apk" glibc.apk \
&& curl "https://raw.githubusercontent.com/squishyu/alpine-pkg-glibc-aarch64-bin/master/glibc-bin-${GLIBC_VERSION_AARCH64}.apk" \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: glibc-bin v${GLIBC_VERSION_AARCH64}" && exit 1) \
&& mv "glibc-bin-${GLIBC_VERSION_AARCH64}.apk" glibc-bin.apk ;; \
*) echo "error: unsupported architecture '$arch'"; exit 1 ;; \
esac
FROM alpine:3.18
COPY --from=build /tmp/glibc.apk /tmp/
COPY --from=build /tmp/glibc-bin.apk /tmp/
COPY --from=build /usr/local/bin/bun /usr/local/bin/
COPY docker-entrypoint.sh /usr/local/bin/
RUN addgroup -g 1000 bun \
&& adduser -u 1000 -G bun -s /bin/sh -D bun \
&& apk --no-cache --force-overwrite --allow-untrusted add \
/tmp/glibc.apk \
/tmp/glibc-bin.apk \
&& rm /tmp/glibc.apk \
&& rm /tmp/glibc-bin.apk \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
WORKDIR /home/bun/app
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/usr/local/bin/bun"]

View File

@@ -1,7 +1,7 @@
FROM debian:bullseye-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest
ARG BUN_VERSION=0.5.7
RUN apt-get update -qq \
&& apt-get install -qq --no-install-recommends \
@@ -17,7 +17,7 @@ RUN apt-get update -qq \
&& case "${arch##*-}" in \
amd64) build="x64-baseline";; \
arm64) build="aarch64";; \
*) echo "error: unsupported architecture: $arch"; exit 1 ;; \
*) echo "error: unsupported architecture: ($arch)"; exit 1 ;; \
esac \
&& version="$BUN_VERSION" \
&& case "$version" in \
@@ -33,44 +33,44 @@ RUN apt-get update -qq \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: $tag" && exit 1) \
|| (echo "error: unknown release: ($tag)" && exit 1) \
&& for key in \
"F3DCC08A8572C0749B3E18888EAB4D40A7B22B59" \
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" \
|| gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& gpg --update-trustdb \
&& curl "https://github.com/oven-sh/bun/releases/$release/SHASUMS256.txt.asc" \
-fsSLO \
--compressed \
--retry 5 \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& grep " bun-linux-$build.zip\$" SHASUMS256.txt | sha256sum -c - \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& unzip "bun-linux-$build.zip" \
&& mv "bun-linux-$build/bun" /usr/local/bin/bun \
&& rm -f "bun-linux-$build.zip" SHASUMS256.txt.asc SHASUMS256.txt \
&& chmod +x /usr/local/bin/bun \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
FROM debian:bullseye-slim
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
RUN groupadd bun \
--gid 1000 \
&& useradd bun \
--uid 1000 \
--gid bun \
--shell /bin/sh \
--create-home \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
--create-home
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin
COPY --from=build /usr/local/bin/bunx /usr/local/bin
WORKDIR /home/bun/app
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

View File

@@ -1,7 +1,7 @@
FROM debian:bullseye-slim AS build
# https://github.com/oven-sh/bun/releases
ARG BUN_VERSION=latest
ARG BUN_VERSION=0.5.7
RUN apt-get update -qq \
&& apt-get install -qq --no-install-recommends \
@@ -17,7 +17,7 @@ RUN apt-get update -qq \
&& case "${arch##*-}" in \
amd64) build="x64-baseline";; \
arm64) build="aarch64";; \
*) echo "error: unsupported architecture: $arch"; exit 1 ;; \
*) echo "error: unsupported architecture: ($arch)"; exit 1 ;; \
esac \
&& version="$BUN_VERSION" \
&& case "$version" in \
@@ -33,42 +33,44 @@ RUN apt-get update -qq \
-fsSLO \
--compressed \
--retry 5 \
|| (echo "error: failed to download: $tag" && exit 1) \
|| (echo "error: unknown release: ($tag)" && exit 1) \
&& for key in \
"F3DCC08A8572C0749B3E18888EAB4D40A7B22B59" \
; do \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" \
|| gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
done \
&& gpg --update-trustdb \
&& curl "https://github.com/oven-sh/bun/releases/$release/SHASUMS256.txt.asc" \
-fsSLO \
--compressed \
--retry 5 \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& grep " bun-linux-$build.zip\$" SHASUMS256.txt | sha256sum -c - \
|| (echo "error: failed to verify: $tag" && exit 1) \
|| (echo "error: failed to verify release: ($tag)" && exit 1) \
&& unzip "bun-linux-$build.zip" \
&& mv "bun-linux-$build/bun" /usr/local/bin/bun \
&& rm -f "bun-linux-$build.zip" SHASUMS256.txt.asc SHASUMS256.txt \
&& chmod +x /usr/local/bin/bun
&& chmod +x /usr/local/bin/bun \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
FROM debian:bullseye
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
RUN groupadd bun \
--gid 1000 \
&& useradd bun \
--uid 1000 \
--gid bun \
--shell /bin/sh \
--create-home \
&& ln -s /usr/local/bin/bun /usr/local/bin/bunx \
&& which bun \
&& which bunx \
&& bun --version
--create-home
COPY docker-entrypoint.sh /usr/local/bin
COPY --from=build /usr/local/bin/bun /usr/local/bin
COPY --from=build /usr/local/bin/bunx /usr/local/bin
WORKDIR /home/bun/app
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

View File

@@ -93,7 +93,6 @@ interface Bun {
style: "nextjs";
origin?: string;
assetPrefix?: string;
fileExtensions?: string[];
});
reload(): void;

View File

@@ -99,20 +99,6 @@ const query = db.prepare("SELECT * FROM foo WHERE bar = ?");
{% /callout %}
## WAL mode
SQLite supports [write-ahead log mode](https://www.sqlite.org/wal.html) (WAL) which dramatically improves performance, especially in situations with many concurrent writes. It's broadly recommended to enable WAL mode for most typical applications.
To enable WAL mode, run this pragma query at the beginning of your application:
```ts
db.exec("PRAGMA journal_mode = WAL;");
```
{% details summary="What is WAL mode" %}
In WAL mode, writes to the database are written directly to a separate file called the "WAL file" (write-ahead log). This file will be later integrated into the main database file. Think of it as a buffer for pending writes. Refer to the [SQLite docs](https://www.sqlite.org/wal.html) for a more detailed overview.
{% /details %}
## Statements
A `Statement` is a _prepared query_, which means it's been parsed and compiled into an efficient binary form. It can be executed multiple times in a performant way.

View File

@@ -161,7 +161,7 @@ socket.addEventListener("message", event => {
### Pub/Sub
Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic (excluding itself). This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic. This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
```ts
const server = Bun.serve<{ username: string }>({
@@ -192,7 +192,7 @@ const server = Bun.serve<{ username: string }>({
close(ws) {
const msg = `${ws.data.username} has left the chat`;
ws.unsubscribe("the-group-chat");
server.publish("the-group-chat", msg);
ws.publish("the-group-chat", msg);
},
},
});
@@ -200,18 +200,7 @@ const server = Bun.serve<{ username: string }>({
console.log(`Listening on ${server.hostname}:${server.port}`);
```
Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`. To send a message to all subscribers of a topic, use the `.publish()` method on the `Server` instance.
```ts
const server = Bun.serve({
websocket: {
// ...
},
});
// listen for some external event
server.publish("the-group-chat", "Hello world");
```
Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`.
### Compression

View File

@@ -1096,7 +1096,7 @@ interface BuildArtifact extends Blob {
The `outputs` array contains all the files that were generated by the build. Each artifact implements the `Blob` interface.
```ts
const build = await Bun.build({
const build = Bun.build({
/* */
});
@@ -1140,7 +1140,7 @@ Each artifact also contains the following properties:
Similar to `BunFile`, `BuildArtifact` objects can be passed directly into `new Response()`.
```ts
const build = await Bun.build({
const build = Bun.build({
/* */
});
@@ -1156,7 +1156,7 @@ The Bun runtime implements special pretty-printing of `BuildArtifact` object to
```ts#Build_script
// build.ts
const build = await Bun.build({/* */});
const build = Bun.build({/* */});
const artifact = build.outputs[0];
console.log(artifact);

View File

@@ -21,7 +21,7 @@ Configuring with `bunfig.toml` is optional. Bun tries to be zero configuration i
# Scope name The value can be a URL string or an object
"@mybigcompany" = { token = "123456", url = "https://registry.mybigcompany.com" }
# URL is optional and falls back to the default registry
# URL is optional and fallsback to the default registry
# The "@" in the scope is optional
mybigcompany2 = { token = "123456" }
@@ -62,9 +62,6 @@ dev = true
# Install peerDependencies (default: false)
peer = false
# Whether to use the github REST api (unauthenticated)
github.api = true
# When using `bun install -g`, install packages here
globalDir = "~/.bun/install/global"

View File

@@ -23,7 +23,9 @@ sudo apt install --install-recommends linux-generic-hwe-20.04
{% /details %}
## `bun install`
## Manage dependencies
### `bun install`
To install all dependencies of a project:
@@ -89,14 +91,11 @@ frozenLockfile = false
# equivalent to `--dry-run` flag
dryRun = false
# whether to use the github REST api (unauthenticated)
github.api = true
```
{% /details %}
## `bun add`
### `bun add`
To add a particular package:
@@ -178,7 +177,7 @@ To view a complete list of options for a given command:
$ bun add --help
```
## `bun remove`
### `bun remove`
To remove a dependency:
@@ -186,17 +185,7 @@ To remove a dependency:
$ bun remove preact
```
## `bun update`
To update all dependencies to the latest version _that's compatible with the version range specified in your `package.json`_:
```sh
$ bun update
```
This will not edit your `package.json`. There's currently no command to force-update all dependencies to the latest version regardless version ranges.
## `bun link`
## Local packages (`bun link`)
Use `bun link` in a local directory to register the current package as a "linkable" package.

View File

@@ -72,7 +72,7 @@ $ bun --watch run dev # ✔️ do this
$ bun run dev --watch # ❌ don't do this
```
Flags that occur at the end of the command will be ignored and passed through to the `"dev"` script itself.
Flags that occur at the end of the command will be ignores and passed through to the `"dev"` script itself.
{% /callout %}
### `--smol`
@@ -89,10 +89,6 @@ $ bun --smol run index.tsx
Compare to `npm run <script>` or `yarn <script>`
{% /note %}
```sh
$ bun [bun flags] run <script> [script flags]
```
Your `package.json` can define a number of named `"scripts"` that correspond to shell commands.
```jsonc
@@ -105,10 +101,10 @@ Your `package.json` can define a number of named `"scripts"` that correspond to
}
```
Use `bun run <script>` to execute these scripts.
Use `bun <script>` or `bun run <script>` to execute these scripts.
```bash
$ bun run clean
$ bun clean
$ rm -rf dist && echo 'Done.'
Cleaning...
Done.

View File

@@ -49,7 +49,7 @@ This is useful for preventing flash of unstyled content.
## With `bun bun`
Bun bundles `.css` files imported via `@import` into a single file. It doesnt auto-prefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. Youll have to import those from a `.css` file.
Bun bundles `.css` files imported via `@import` into a single file. It doesnt autoprefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. Youll have to import those from a `.css` file.
This input:

View File

@@ -10,7 +10,7 @@ $ bun create astro
│ ◠ ◡ ◠ We're glad to have you on board.
╰─────╯
astro v3.1.4 Launch sequence initiated.
astro v2.10.5 Launch sequence initiated.
dir Where should we create your new project?
./fumbling-field
@@ -55,17 +55,21 @@ By default, Bun will run the dev server with Node.js. To use the Bun runtime ins
```sh
$ bunx --bun astro dev
🚀 astro v3.1.4 started in 200ms
🚀 astro v2.10.5 started in 200ms
┃ Local http://localhost:4321/
┃ Local http://localhost:3000/
┃ Network use --host to expose
01:48:34 PM [content] Watching src/content/ for changes
01:48:34 PM [content] Types generated
01:48:34 PM [astro] update /.astro/types.d.ts
```
---
Open [http://localhost:4321](http://localhost:4321) with your browser to see the result. Astro will hot-reload your app as you edit your source files.
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Astro will hot-reload your app as you edit your source files.
{% image src="https://i.imgur.com/Dswiu6w.png" caption="An Astro v3 starter app running on Bun" %}
{% image src="https://github.com/vitejs/vite/assets/3084745/bb1d5063-32f4-4598-b33e-50b44a1c4e8a" caption="An Astro starter app running on Bun" %}
---

View File

@@ -2,26 +2,20 @@
name: Get started using Prisma
---
{% callout %}
**Note** At the moment Prisma needs Node.js to be installed to run certain generation code. Make sure Node.js is installed in the environment where you're running `bunx prisma` commands.
{% /callout %}
---
Prisma works out of the box with Bun. First, create a directory and initialize it with `bun init`.
```bash
$ mkdir prisma-app
$ cd prisma-app
$ bun init
mkdir prisma-app
cd prisma-app
bun init
```
---
Then install the Prisma CLI (`prisma`) and Prisma Client (`@prisma/client`) as dependencies.
Then add Prisma as a dependency.
```bash
$ bun add prisma @prisma/client
bun add prisma
```
---
@@ -29,7 +23,7 @@ $ bun add prisma @prisma/client
We'll use the Prisma CLI with `bunx` to initialize our schema and migration directory. For simplicity we'll be using an in-memory SQLite database.
```bash
$ bunx prisma init --datasource-provider sqlite
bunx prisma init --datasource-provider sqlite
```
---
@@ -60,37 +54,14 @@ Then generate and run initial migration.
This will generate a `.sql` migration file in `prisma/migrations`, create a new SQLite instance, and execute the migration against the new instance.
```bash
$ bunx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
SQLite database dev.db created at file:./dev.db
Applying migration `20230928182242_init`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20230928182242_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (v5.3.1) to ./node_modules/@prisma/client in 41ms
bunx prisma migrate dev --name init
```
---
As indicated in the output, Prisma re-generates our _Prisma client_ whenever we execute a new migration. The client provides a fully typed API for reading and writing from our database. You can manually re-generate the client with the Prisma CLI.
Prisma automatically generates our _Prisma client_ whenever we execute a new migration. The client provides a fully typed API for reading and writing from our database.
```sh
$ bunx prisma generate
```
---
We can import the generated client from `@prisma/client`.
It can be imported from `@prisma/client`.
```ts#src/index.ts
import {PrismaClient} from "@prisma/client";

View File

@@ -18,7 +18,7 @@ $ bun create remix
dir Where should we create your new project?
./my-app
◼ Using basic template See https://remix.run/docs/en/main/guides/templates#templates for more
◼ Using basic template See https://remix.run/docs/pages/templates for more
✔ Template copied
git Initialize a new git repository?

View File

@@ -8,7 +8,7 @@ The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `
const path = "/path/to/package.json";
const file = Bun.file(path);
const stream = file.stream();
const stream = await file.stream();
```
---

View File

@@ -2,12 +2,6 @@
name: Debugging Bun with the VS Code extension
---
{% note %}
VSCode extension support is currently buggy. We recommend the [Web Debugger](https://bun.sh/guides/runtime/web-debugger) for now.
{% /note %}
Bun speaks the [WebKit Inspector Protocol](https://github.com/oven-sh/bun/blob/main/packages/bun-vscode/types/jsc.d.ts) so you can debug your code with an interactive debugger.
---

View File

@@ -47,7 +47,7 @@ Bun.serve<WebSocketData>({
// use a library to parse cookies
const cookies = parseCookies(req.headers.get("Cookie"));
const token = cookies["X-Token"];
const user = await getUserFromToken(token);
const user = await getUserFromToken(ws.data.authToken);
const upgraded = server.upgrade(req, {
data: {

View File

@@ -91,9 +91,6 @@ frozenLockfile = false
# equivalent to `--dry-run` flag
dryRun = false
# whether to use the github REST api (unauthenticated)
github.api = true
```
{% /details %}

View File

@@ -1,30 +1,6 @@
Bun supports [`workspaces`](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true#description) in `package.json`. Workspaces make it easy to develop complex software as a _monorepo_ consisting of several independent packages.
It's common for a monorepo to have the following structure:
```
tree
<root>
├── README.md
├── bun.lockb
├── package.json
├── tsconfig.json
└── packages
   ├── pkg-a
   │   ├── index.ts
   │   ├── package.json
   │   └── tsconfig.json
   ├── pkg-b
   │   ├── index.ts
   │   ├── package.json
   │   └── tsconfig.json
   └── pkg-c
   ├── index.ts
   ├── package.json
   └── tsconfig.json
```
In the root `package.json`, the `"workspaces"` key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It conventional to place all the workspace in a directory called `packages`.
To try it, specify a list of sub-packages in the `workspaces` field of your `package.json`; it's conventional to place these sub-packages in a directory called `packages`.
```json
{
@@ -41,7 +17,7 @@ In the root `package.json`, the `"workspaces"` key is used to indicate which sub
**Glob support** — Bun supports simple `<directory>/*` globs in `"workspaces"`. Full glob syntax (e.g. `**` and `?`) is not yet supported.
{% /callout %}
Each workspace has it's own `package.json` When referencing other packages in the monorepo, use `"workspace:*"` as the version field in your `package.json`.
When referencing other packages in the monorepo, use `"workspace:*"` as the version field in your `package.json`.
```json
{
@@ -59,7 +35,7 @@ Each workspace has it's own `package.json` When referencing other packages in th
Workspaces have a couple major benefits.
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency in `package.json`. If package `b` depends on `a`, `bun install` will install your local `packages/a` directory into `node_modules` instead of downloading it from the npm registry.
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency with `bun add`. If package `b` depends on `a`, `bun install` will symlink your local `packages/a` directory into the `node_modules` folder of `b`, instead of trying to download it from the npm registry.
- **Dependencies can be de-duplicated.** If `a` and `b` share a common dependency, it will be _hoisted_ to the root `node_modules` directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.
{% callout %}

View File

@@ -3,8 +3,7 @@ Bun ships as a single executable that can be installed a few different ways.
## macOS and Linux
{% callout %}
**Linux users** — The `unzip` package is required to install Bun. Use `sudo apt install unzip` to install `unzip` package.
Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1. Use `uname -r` to check Kernel version.
**Linux users** — The `unzip` package is required to install Bun. Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1.
{% /callout %}
{% codetabs %}
@@ -49,24 +48,6 @@ The test runner, package manager, and bundler are still under development. The f
- `bun link/unlink`
- `bun build`
## Docker
Bun provides a [Docker image](https://hub.docker.com/r/oven/bun/tags) that supports both Linux x64 and arm64.
```bash
$ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```
There are also image variants for different operating systems.
```bash
$ docker pull oven/bun:debian
$ docker pull oven/bun:slim
$ docker pull oven/bun:alpine
$ docker pull oven/bun:distroless
```
## Upgrading
Once installed, the binary can upgrade itself.
@@ -89,10 +70,6 @@ $ bun upgrade --canary
[View canary build](https://github.com/oven-sh/bun/releases/tag/canary)
{% callout %}
**Note** — To switch back to a stable release from canary, run `bun upgrade` again with no flags.
{% /callout %}
<!--
## Native

View File

@@ -46,13 +46,8 @@ $ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 16 all
```
```bash#Arch
$ sudo pacman -S llvm clang lld
```
$ sudo pacman -S llvm16 clang16 lld
```bash#Fedora
$ sudo dnf install 'dnf-command(copr)'
$ sudo dnf copr enable -y @fedora-llvm-team/llvm-snapshots
$ sudo dnf install llvm clang lld
```
{% /codetabs %}
@@ -101,11 +96,7 @@ $ sudo apt install cargo ccache cmake git golang libtool ninja-build pkg-config
```
```bash#Arch
$ sudo pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
```
```bash#Fedora
$ sudo dnf install cargo ccache cmake git golang libtool ninja-build pkg-config rustc golang-github-evanw-esbuild libatomic-static libstdc++-static sed unzip
$ pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
```
{% /codetabs %}
@@ -385,13 +376,35 @@ $ valgrind --fair-sched=try --track-origins=yes bun-debug <args>
## Updating `WebKit`
The Bun team will occasionally bump the version of WebKit used in Bun. When this happens, you may see errors in `src/bun.js/bindings` during builds. When you see this, install the latest version of `bun-webkit` and re-compile.
The Bun team will occasionally bump the version of WebKit used in Bun. When this happens, you may see something like this with you run `git status`.
```bash
$ git status
On branch my-branch
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: src/bun.js/WebKit (new commits)
```
For performance reasons, `make submodule` does not automatically update the WebKit submodule. To update, run the following commands from the root of the Bun repo:
```bash
$ bun install
$ make cpp
```
<!-- Check the [Bun repo](https://github.com/oven-sh/bun/tree/main/src/bun.js) to get the hash of the commit of WebKit is currently being used.
{% image width="270" src="https://github.com/oven-sh/bun/assets/3084745/51730b73-89ef-4358-9a41-9563a60a54be" /%} -->
<!--
```bash
$ cd src/bun.js/WebKit
$ git fetch
$ git checkout <hash>
``` -->
## Troubleshooting
### 'span' file not found on Ubuntu
@@ -451,7 +464,7 @@ If you see an error about `cmakeconfig.h` not being found, this is because the p
$ bun install
```
Check to see the command installed webkit, and you can manually look for `node_modules/bun-webkit-{platform}-{arch}`:
Check to see the command installed webkit, and you can manully look for `node_modules/bun-webkit-{platform}-{arch}`:
```bash
# this should reveal two directories. if not, something went wrong

View File

@@ -42,22 +42,6 @@ const server = Bun.serve({
console.log(`Listening on http://localhost:${server.port} ...`);
```
If you're using TypeScript, you may see a type error on the `Bun` global. To fix this, install `bun-types`.
```sh
$ bun add -d bun-types
```
Then add the following line to your `compilerOptions` in `tsconfig.json`.
```json-diff#tsconfig.json
{
"compilerOptions": {
+ "types": ["bun-types"]
}
}
```
Run the file from your shell.
```bash

View File

@@ -19,11 +19,11 @@ Bun's runtime behavior is configured using top-level fields in the `bunfig.toml`
### `preload`
An array of scripts/plugins to execute before running a file or script.
An array of scripts to execute before running a file or script. This is useful for registering plugins.
```toml
# scripts to run before `bun run`-ing a file or script
# register plugins by adding them to this list
# scripts to run before `bun run`ning a file or script
# useful for registering plugins
preload = ["./preload.ts"]
```
@@ -100,14 +100,6 @@ Bun supports the following loaders:
- `dataurl`
- `text`
### `telemetry`
The `telemetry` field permit to enable/disable the analytics records. Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data. By default the telemetry is enabled. Equivalent of `DO_NOT_TRACK` env variable.
```toml
telemetry = false
```
## Test runner
The test runner is configured under the `[test]` section of your bunfig.toml.
@@ -216,17 +208,6 @@ Whether to install peer dependencies. Default `false`.
peer = false
```
### `install.github.api`
Enable using the github REST API to install github dependencies. Default `true`.
Private github repositories will fail to install if this option is true because the REST API is unauthenticated.
```toml
[install]
github.api = true
```
### `install.production`
Whether `bun install` will run in "production mode". Default `false`.

View File

@@ -5,7 +5,7 @@ Bun reads your `.env` files automatically and provides idiomatic ways to read an
Bun reads the following files automatically (listed in order of increasing precedence).
- `.env`
- `.env.production`, `.env.development`, `.env.test` (depending on value of `NODE_ENV`)
- `.env.production` or `.env.development` (depending on value of `NODE_ENV`)
- `.env.local`
```txt#.env
@@ -25,47 +25,9 @@ Or programmatically by assigning a property to `process.env`.
process.env.FOO = "hello";
```
### Quotation marks
Bun supports double quotes, single quotes, and
### Expansion
Environment variables are automatically _expanded_. This means you can reference previously-defined variables in your environment variables.
```txt#.env
FOO=world
BAR=hello$FOO
```
```ts
process.env.BAR; // => "helloworld"
```
This is useful for constructing connection strings or other compound values.
```txt#.env
DB_USER=postgres
DB_PASSWORD=secret
DB_HOST=localhost
DB_PORT=5432
DB_URL=postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME
```
This can be disabled by escaping the `$` with a backslash.
```txt#.env
FOO=world
BAR=hello\$FOO
```
```ts
process.env.BAR; // => "hello$FOO"
```
### `dotenv`
Generally speaking, you won't need `dotenv` or `dotenv-expand` anymore, because Bun reads `.env` files automatically.
Generally speaking, you won't need `dotenv` anymore, because Bun reads `.env` files automatically.
## Reading environment variables
@@ -90,31 +52,6 @@ FOOBAR=aaaaaa
<lots more lines>
```
## TypeScript
In TypeScript, all properties of `process.env` are typed as `string | undefined`.
```ts
Bun.env.whatever;
// string | undefined
```
To get autocompletion and tell TypeScript to treat a variable as a non-optional string, we'll use [interface merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces).
```ts
declare module "bun" {
interface Env {
AWESOME: string;
}
}
```
Add this line to any file in your project. It will globally add the `AWESOME` property to `process.env` and `Bun.env`.
```ts
process.env.AWESOME; // => string
```
## Configuring Bun
These environment variables are read by Bun and configure aspects of its behavior.
@@ -142,6 +79,6 @@ These environment variables are read by Bun and configure aspects of its behavio
---
- `DO_NOT_TRACK`
- If `DO_NOT_TRACK=1`, then analytics are [disabled](https://do-not-track.dev/). Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data. Equivalent of `telemetry=false` in bunfig.
- If `DO_NOT_TRACK=1`, then analytics are [disabled](https://do-not-track.dev/). Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data.
{% /table %}

View File

@@ -52,7 +52,6 @@ serve({
{% /codetabs %}
In this example, Bun is
![bun watch gif](https://user-images.githubusercontent.com/709451/228439002-7b9fad11-0db2-4e48-b82d-2b88c8625625.gif)
Running `bun test` in watch mode and `save-on-keypress` enabled:
@@ -65,9 +64,7 @@ $ bun --watch test
## `--hot` mode
Use `bun --hot` to enable hot reloading when executing code with Bun. This is distinct from `--watch` mode in that Bun does not hard-restart the entire process. Instead, it detects code changes and updates its internal module cache with the new code.
**Note** — This is not the same as hot reloading in the browser! Many frameworks provide a "hot reloading" experience, where you can edit & save your frontend code (say, a React component) and see the changes reflected in the browser without refreshing the page. Bun's `--hot` is the server-side equivalent of this experience. To get hot reloading in the browser, use a framework like [Vite](https://vitejs.dev).
Use `bun --hot` to enable hot reloading when executing code with Bun.
```bash
$ bun --hot server.ts
@@ -102,13 +99,15 @@ Traditional file watchers like `nodemon` restart the entire process, so HTTP ser
### HTTP servers
This makes it possible, for instance, to update your HTTP request handler without shutting down the server itself. When you save the file, your HTTP server will be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
Bun provides the following simplified API for implementing HTTP servers. Refer to [API > HTTP](/docs/api/http) for full details.
```ts#server.ts
import {serve} from "bun";
globalThis.count ??= 0;
globalThis.count++;
Bun.serve({
serve({
fetch(req: Request) {
return new Response(`Reloaded ${globalThis.count} times`);
},
@@ -116,16 +115,18 @@ Bun.serve({
});
```
<!-- The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`. -->
The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`.
<!-- {% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%} -->
When you save the file, your HTTP server will be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
{% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%}
{% callout %}
**Note** — In a future version of Bun, support for Vite's `import.meta.hot` is planned to enable better lifecycle management for hot reloading and to align with the ecosystem.
{% /callout %}
{% details summary="Implementation details" %}
{% details summary="Implementation `details`" %}
On hot reload, Bun:

View File

@@ -33,20 +33,15 @@ Hello world!
In this case, we are importing from `./hello`, a relative path with no extension. **Extensioned imports are optional but supported.** To resolve this import, Bun will check for the following files in order:
- `./hello.tsx`
- `./hello.jsx`
- `./hello.ts`
- `./hello.mjs`
- `./hello.tsx`
- `./hello.js`
- `./hello.mjs`
- `./hello.cjs`
- `./hello.json`
- `./hello/index.tsx`
- `./hello/index.jsx`
- `./hello/index.ts`
- `./hello/index.mjs`
- `./hello/index.js`
- `./hello/index.cjs`
- `./hello/index.json`
- `./hello/index.mjs`
Import paths are case-insensitive, meaning these are all valid imports:

View File

@@ -1,16 +1,16 @@
Bun aims for complete Node.js API compatibility. Most `npm` packages intended for `Node.js` environments will work with Bun out of the box; the best way to know for certain is to try it.
This page is updated regularly to reflect compatibility status of the latest version of Bun. The information below reflects Bun's compatibility with _Node.js v20_. If you run into any bugs with a particular package, please [open an issue](https://bun.sh/issues). Opening issues for compatibility bugs helps us prioritize what to work on next.
This page is updated regularly to reflect compatibility status of the latest version of Bun. If you run into any bugs with a particular package, please [open an issue](https://bun.sh/issues). Opening issues for compatibility bugs helps us prioritize what to work on next.
## Built-in modules
### [`node:assert`](https://nodejs.org/api/assert.html)
🟡 Missing `doesNotMatch`
🟢 Fully implemented.
### [`node:async_hooks`](https://nodejs.org/api/async_hooks.html)
🟡 Only `AsyncLocalStorage`, and `AsyncResource` are implemented. `AsyncResource` is missing `bind`.
🟡 Only `AsyncLocalStorage`, and `AsyncResource` are implemented.
### [`node:buffer`](https://nodejs.org/api/buffer.html)
@@ -18,7 +18,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:child_process`](https://nodejs.org/api/child_process.html)
🟡 Missing `Stream` stdio, `proc.gid` `proc.uid`. IPC has partial support and only current only works with other `bun` processes.
🟡 Missing `Stream` stdio, `proc.gid`, `proc.uid`. IPC has partial support and only current only works with other `bun` processes.
### [`node:cluster`](https://nodejs.org/api/cluster.html)
@@ -26,13 +26,11 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:console`](https://nodejs.org/api/console.html)
🟢 Fully implemented.
🟡 Missing `Console` constructor.
### [`node:crypto`](https://nodejs.org/api/crypto.html)
🟡 Missing `Certificate` `ECDH` `KeyObject` `X509Certificate` `checkPrime` `checkPrimeSync` `createPrivateKey` `createPublicKey` `createSecretKey` `diffieHellman` `generateKey` `generateKeyPair` `generateKeyPairSync` `generateKeySync` `generatePrime` `generatePrimeSync` `getCipherInfo` `getFips` `hkdf` `hkdfSync` `secureHeapUsed` `setEngine` `setFips` `sign` `verify`
Some methods are not optimized yet.
🟡 Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`. Some methods are not optimized yet.
### [`node:dgram`](https://nodejs.org/api/dgram.html)
@@ -44,19 +42,19 @@ Some methods are not optimized yet.
### [`node:dns`](https://nodejs.org/api/dns.html)
🟡 Missing `cancel` `setServers` `getDefaultResultOrder`
🟢 Fully implemented.
### [`node:domain`](https://nodejs.org/api/domain.html)
🟡 Missing `Domain` `active`
🟢 Fully implemented.
### [`node:events`](https://nodejs.org/api/events.html)
🟡 Missing `on` `addAbortListener` `getMaxListeners`
🟡 Missing `on`.
### [`node:fs`](https://nodejs.org/api/fs.html)
🟡 Missing `Dir` `fdatasync` `fdatasyncSync` `openAsBlob` `opendir` `opendirSync` `statfs` `statfsSync`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
🟡 Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
### [`node:http`](https://nodejs.org/api/http.html)
@@ -76,11 +74,11 @@ Some methods are not optimized yet.
### [`node:module`](https://nodejs.org/api/module.html)
🟢 Missing `runMain` `syncBuiltinESMExports`, `Module#load()`. Attempts to override or patch the module cache will fail.
🟢 Fully implemented.
### [`node:net`](https://nodejs.org/api/net.html)
🟡 Missing `BlockList` `SocketAddress` `Stream` `getDefaultAutoSelectFamily` `getDefaultAutoSelectFamilyAttemptTimeout` `setDefaultAutoSelectFamily` `setDefaultAutoSelectFamilyAttemptTimeout` `Server#ref()` `Server#unref()` `Socket#ref()` `Socket#unref()`.
🟡 Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList` `net.Server.ref()` `net.Server.unref()` `net.Socket.ref()` `net.Socket.unref()`.
### [`node:os`](https://nodejs.org/api/os.html)
@@ -92,7 +90,7 @@ Some methods are not optimized yet.
### [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html)
🟡 Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Missing `Performance` `PerformanceMark` `PerformanceMeasure` `PerformanceObserverEntryList` `PerformanceResourceTiming` `createHistogram` `monitorEventLoopDelay`. It's recommended to use `performance` global instead of `perf_hooks.performance`.
🟡 Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
### [`node:process`](https://nodejs.org/api/process.html)
@@ -116,7 +114,7 @@ Some methods are not optimized yet.
### [`node:stream`](https://nodejs.org/api/stream.html)
🟡 Missing `getDefaultHighWaterMark` `setDefaultHighWaterMark`
🟢 Fully implemented.
### [`node:string_decoder`](https://nodejs.org/api/string_decoder.html)
@@ -144,11 +142,11 @@ Some methods are not optimized yet.
### [`node:url`](https://nodejs.org/api/url.html)
🟡 Missing `domainToASCII` `domainToUnicode`. It's recommended to use `URL` and `URLSearchParams` globals instead.
🟡 Missing `url.domainTo{ASCII|Unicode}`. Recommended to use `URL` and `URLSearchParams` globals instead.
### [`node:util`](https://nodejs.org/api/util.html)
🟡 Missing `MIMEParams` `MIMEType` `aborted` `debug` `getSystemErrorMap` `getSystemErrorName` `parseArgs` `transferableAbortController` `transferableAbortSignal` `stripVTControlCharacters`
🟡 Missing `util.MIMEParams` `util.MIMEType` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
### [`node:v8`](https://nodejs.org/api/v8.html)
@@ -156,7 +154,7 @@ Some methods are not optimized yet.
### [`node:vm`](https://nodejs.org/api/vm.html)
🟡 Core functionality works, but VM modules are not implemented. Missing `createScript`. `ShadowRealm` can be used.
🟡 Core functionality works, but VM modules are not implemented. `ShadowRealm` can be used.
### [`node:wasi`](https://nodejs.org/api/wasi.html)
@@ -164,11 +162,266 @@ Some methods are not optimized yet.
### [`node:worker_threads`](https://nodejs.org/api/worker_threads.html)
🟡 `Worker` doesn't support the following options: `eval` `argv` `execArgv` `stdin` `stdout` `stderr` `trackedUnmanagedFds` `resourceLimits`. Missing `markAsUntransferable` `moveMessagePortToContext` `getHeapSnapshot`.
🟡 `Worker` doesn't support the following options: `eval`, `argv`, `execArgv`, `stdin`, `stdout`, `stderr`, `trackedUnmanagedFds`, `resourceLimits`. Missing `markAsUntransferable`, `moveMessagePortToContext`, `getHeapSnapshot`.
### [`node:zlib`](https://nodejs.org/api/zlib.html)
🟡 Missing `BrotliCompress` `BrotliDecompress` `brotliCompressSync` `brotliDecompress` `brotliDecompressSync` `createBrotliCompress` `createBrotliDecompress`. Unoptimized.
🟡 Missing `zlib.brotli*`. Has not been optimized.
<!-- {% block className="ScrollFrame" %}
{% table %}
- Module
- Status
- Notes
---
- {% anchor id="node_assert" %} [`node:assert`](https://nodejs.org/api/assert.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_async_hooks" %} [`node:async_hooks`](https://nodejs.org/api/async_hooks.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_buffer" %} [`node:buffer`](https://nodejs.org/api/buffer.html) {% /anchor %}
- 🟢
---
- {% anchor id="node_child_process" %} [`node:child_process`](https://nodejs.org/api/child_process.html) {% /anchor %}
- 🟡
- Missing IPC, `Stream` stdio, `proc.gid`, `proc.uid`, advanced serialization.
---
- {% anchor id="node_cluster" %} [`node:cluster`](https://nodejs.org/api/cluster.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_console" %} [`node:console`](https://nodejs.org/api/console.html) {% /anchor %}
- 🟢
- Recommended to use `console` global instead
---
- {% anchor id="node_crypto" %} [`node:crypto`](https://nodejs.org/api/crypto.html) {% /anchor %}
- 🟡
- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`. Some methods are not optimized yet.
---
- {% anchor id="node_dgram" %} [`node:dgram`](https://nodejs.org/api/dgram.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_diagnostics_channel" %} [`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_dns" %} [`node:dns`](https://nodejs.org/api/dns.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_domain" %} [`node:domain`](https://nodejs.org/api/domain.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_events" %} [`node:events`](https://nodejs.org/api/events.html) {% /anchor %}
- 🟡
- Missing `EventEmitterAsyncResource` `events.on`.
---
- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
- 🟡
- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
---
- {% anchor id="node_http" %} [`node:http`](https://nodejs.org/api/http.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_http2" %} [`node:http2`](https://nodejs.org/api/http2.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_https" %} [`node:https`](https://nodejs.org/api/https.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_inspector" %} [`node:inspector`](https://nodejs.org/api/inspector.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_module" %} [`node:module`](https://nodejs.org/api/module.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_net" %} [`node:net`](https://nodejs.org/api/net.html) {% /anchor %}
- 🟡
- Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
---
- {% anchor id="node_os" %} [`node:os`](https://nodejs.org/api/os.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_path" %} [`node:path`](https://nodejs.org/api/path.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_perf_hooks" %} [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html) {% /anchor %}
- 🟡
- Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
---
- {% anchor id="node_process" %} [`node:process`](https://nodejs.org/api/process.html) {% /anchor %}
- 🟡
- See `Globals > process`.
---
- {% anchor id="node_punycode" %} [`node:punycode`](https://nodejs.org/api/punycode.html) {% /anchor %}
- 🟢
- Fully implemented. _Deprecated by Node.js._
---
- {% anchor id="node_querystring" %} [`node:querystring`](https://nodejs.org/api/querystring.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_readline" %} [`node:readline`](https://nodejs.org/api/readline.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_repl" %} [`node:repl`](https://nodejs.org/api/repl.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_stream" %} [`node:stream`](https://nodejs.org/api/stream.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_string_decoder" %} [`node:string_decoder`](https://nodejs.org/api/string_decoder.html) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_sys" %} [`node:sys`](https://nodejs.org/api/util.html) {% /anchor %}
- 🟡
- See `node:util`.
---
- {% anchor id="node_timers" %} [`node:timers`](https://nodejs.org/api/timers.html) {% /anchor %}
- 🟢
- Recommended to use global `setTimeout`, et. al. instead.
---
- {% anchor id="node_tls" %} [`node:tls`](https://nodejs.org/api/tls.html) {% /anchor %}
- 🟡
- Missing `tls.createSecurePair`.
---
- {% anchor id="node_trace_events" %} [`node:trace_events`](https://nodejs.org/api/tracing.html) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_tty" %} [`node:tty`](https://nodejs.org/api/tty.html) {% /anchor %}
- 🟡
- Missing `tty.ReadStream` and `tty.WriteStream`.
---
- {% anchor id="node_url" %} [`node:url`](https://nodejs.org/api/url.html) {% /anchor %}
- 🟡
- Missing `url.domainTo{ASCII|Unicode}`. Recommended to use `URL` and `URLSearchParams` globals instead.
---
- {% anchor id="node_util" %} [`node:util`](https://nodejs.org/api/util.html) {% /anchor %}
- 🟡
- Missing `util.MIMEParams` `util.MIMEType` `util.formatWithOptions()` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
---
- {% anchor id="node_v8" %} [`node:v8`](https://nodejs.org/api/v8.html) {% /anchor %}
- 🔴
- `serialize` and `deserialize` use JavaScriptCore's wire format instead of V8's. Otherwise, not implemented. For profiling, use [`bun:jsc`](/docs/project/benchmarking#bunjsc) instead.
---
- {% anchor id="node_vm" %} [`node:vm`](https://nodejs.org/api/vm.html) {% /anchor %}
- 🟡
- Core functionality works, but VM modules are not implemented. `ShadowRealm` can be used.
---
- {% anchor id="node_wasi" %} [`node:wasi`](https://nodejs.org/api/wasi.html) {% /anchor %}
- 🟡
- Partially implemented.
---
- {% anchor id="node_worker_threads" %} [`node:worker_threads`](https://nodejs.org/api/worker_threads.html) {% /anchor %}
- 🔴
- Not implemented, but coming soon.
---
- {% anchor id="node_zlib" %} [`node:zlib`](https://nodejs.org/api/zlib.html) {% /anchor %}
- 🟡
- Missing `zlib.brotli*`.
{% /table %}
{% /block %} -->
## Globals
@@ -232,7 +485,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
🟢 Fully implemented.
🟡 Missing `Console` constructor.
### [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy)
@@ -336,7 +589,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`process`](https://nodejs.org/api/process.html)
🟡 Missing `domain` `hasUncaughtExceptionCaptureCallback` `initgroups` `report` `resourceUsage` `setUncaughtExceptionCaptureCallback` `setegid` `seteuid` `setgid` `setgroups` `setuid` `allowedNodeEnvironmentFlags` `getActiveResourcesInfo` `setActiveResourcesInfo` `moduleLoadList` `setSourceMapsEnabled` `channel`. `process.binding` is partially implemented.
🟡 Missing `process.allowedNodeEnvironmentFlags` `process.channel` `process.constrainedMemory()` `process.getActiveResourcesInfo/setActiveResourcesInfo()` `process.setuid/setgid/setegid/seteuid/setgroups()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.report` `process.resourceUsage()`. `process.binding` is partially implemented.
### [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
@@ -368,7 +621,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`require()`](https://nodejs.org/api/globals.html#require)
🟢 Fully implemented, including [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
🟢 Fully implemented, as well as [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), and [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options).
### [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
@@ -449,3 +702,421 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)
🟢 Fully implemented.
<!-- {% table %}
---
- {% anchor id="node_abortcontroller" %} [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_abortsignal" %} [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_blob" %} [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_buffer" %} [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer) {% /anchor %}
- 🟡
- Incomplete implementation of `base64` and `base64url` encodings.
---
- {% anchor id="node_bytelengthqueuingstrategy" %} [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_dirname" %} [`__dirname`](https://nodejs.org/api/globals.html#__dirname) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_filename" %} [`__filename`](https://nodejs.org/api/globals.html#__filename) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_atob" %} [`atob()`](https://developer.mozilla.org/en-US/docs/Web/API/atob) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_broadcastchannel" %} [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_btoa" %} [`btoa()`](https://developer.mozilla.org/en-US/docs/Web/API/btoa) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_clearimmediate" %} [`clearImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearImmediate) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_clearinterval" %} [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_cleartimeout" %} [`clearTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_compressionstream" %} [`CompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_console" %} [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_countqueuingstrategy" %} [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_crypto" %} [`Crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_crypto" %} [`SubtleCrypto (crypto)`](https://developer.mozilla.org/en-US/docs/Web/API/crypto) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_cryptokey" %} [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_customevent" %} [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_decompressionstream" %} [`DecompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_event" %} [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_eventtarget" %} [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_exports" %} [`exports`](https://nodejs.org/api/globals.html#exports) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_fetch" %} [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_formdata" %} [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_global" %} [`global`](https://nodejs.org/api/globals.html#global) {% /anchor %}
- 🟢
- Implemented. This is an object containing all objects in the global namespace. It's rarely referenced directly, as its contents are available without an additional prefix, e.g. `__dirname` instead of `global.__dirname`.
---
- {% anchor id="node_globalthis" %} [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) {% /anchor %}
- 🟢
- Aliases to `global`.
---
- {% anchor id="node_headers" %} [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_messagechannel" %} [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_messageevent" %} [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_messageport" %} [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_module" %} [`module`](https://nodejs.org/api/globals.html#module) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_performanceentry" %} [`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performancemark" %} [`PerformanceMark`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performancemeasure" %} [`PerformanceMeasure`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performanceobserver" %} [`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performanceobserverentrylist" %} [`PerformanceObserverEntryList`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserverEntryList) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performanceresourcetiming" %} [`PerformanceResourceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_performance" %} [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/performance) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_process" %} [`process`](https://nodejs.org/api/process.html) {% /anchor %}
- 🟡
- Missing `process.allowedNodeEnvironmentFlags` `process.channel()` `process.connected` `process.constrainedMemory()` `process.disconnect()` `process.getActiveResourcesInfo/setActiveResourcesInfo()` `process.setuid/setgid/setegid/seteuid/setgroups()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.report` `process.resourceUsage()` `process.send()`.
---
- {% anchor id="node_queuemicrotask" %} [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_readablebytestreamcontroller" %} [`ReadableByteStreamController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableByteStreamController) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_readablestream" %} [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_readablestreambyobreader" %} [`ReadableStreamBYOBReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_readablestreambyobrequest" %} [`ReadableStreamBYOBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBRequest) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_readablestreamdefaultcontroller" %} [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_readablestreamdefaultreader" %} [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_require" %} [`require()`](https://nodejs.org/api/globals.html#require) {% /anchor %}
- 🟢
- Fully implemented, as well as [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), and [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
---
- {% anchor id="node_response" %} [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_request" %} [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_setimmediate" %} [`setImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_setinterval" %} [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_settimeout" %} [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_structuredclone" %} [`structuredClone()`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_subtlecrypto" %} [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_domexception" %} [`DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_textdecoder" %} [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_textdecoderstream" %} [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_textencoder" %} [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_textencoderstream" %} [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) {% /anchor %}
- 🔴
- Not implemented.
---
- {% anchor id="node_transformstream" %} [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_transformstreamdefaultcontroller" %} [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_url" %} [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_urlsearchparams" %} [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_webassembly" %} [`WebAssembly`](https://nodejs.org/api/globals.html#webassembly) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_writablestream" %} [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_writablestreamdefaultcontroller" %} [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController) {% /anchor %}
- 🟢
- Fully implemented.
---
- {% anchor id="node_writablestreamdefaultwriter" %} [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter) {% /anchor %}
- 🟢
- Fully implemented.
{% /table %} -->

View File

@@ -45,7 +45,7 @@ plugin(
);
```
Bun's plugin API is loosely based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
```jsx
import { plugin } from "bun";
@@ -61,7 +61,7 @@ Plugins are primarily used to extend Bun with loaders for additional file types.
```ts#yamlPlugin.ts
import { plugin } from "bun";
plugin({
await plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
@@ -90,7 +90,7 @@ Register this file in `preload`:
preload = ["./yamlPlugin.ts"]
```
Once the plugin is registered, `.yaml` and `.yml` files can be directly imported.
Once the plugin is registed, `.yaml` and `.yml` files can be directly imported.
{% codetabs %}
@@ -217,91 +217,6 @@ import MySvelteComponent from "./component.svelte";
console.log(mySvelteComponent.render());
```
## Virtual Modules
{% note %}
This feature is currently only available at runtime with `Bun.plugin` and not yet supported in the bundler, but you can mimick the behavior using `onResolve` and `onLoad`.
{% /note %}
To create virtual modules at runtime, use `builder.module(specifier, callback)` in the `setup` function of a `Bun.plugin`.
For example:
```js
import { plugin } from "bun";
plugin({
name: "my-virtual-module",
setup(build) {
build.module(
// The specifier, which can be any string
"my-transpiled-virtual-module",
// The callback to run when the module is imported or required for the first time
() => {
return {
contents: "console.log('hello world!')",
loader: "js",
};
},
);
build.module("my-object-virtual-module", () => {
return {
exports: {
foo: "bar",
},
loader: "object",
};
});
},
});
// Sometime later
// All of these work
import "my-transpiled-virtual-module";
require("my-transpiled-virtual-module");
await import("my-transpiled-virtual-module");
require.resolve("my-transpiled-virtual-module");
import { foo } from "my-object-virtual-module";
const object = require("my-object-virtual-module");
await import("my-object-virtual-module");
require.resolve("my-object-virtual-module");
```
### Overriding existing modules
You can also override existing modules with `build.module`.
```js
import { plugin } from "bun";
build.module("my-object-virtual-module", () => {
return {
exports: {
foo: "bar",
},
loader: "object",
};
});
require("my-object-virtual-module"); // { foo: "bar" }
await import("my-object-virtual-module"); // { foo: "bar" }
build.module("my-object-virtual-module", () => {
return {
exports: {
baz: "quix",
},
loader: "object",
};
});
require("my-object-virtual-module"); // { baz: "quix" }
await import("my-object-virtual-module"); // { baz: "quix" }
```
## Reading the config
Plugins can read and write to the [build config](/docs/bundler#api) with `build.config`.

View File

@@ -139,6 +139,12 @@ $ bun test --only
To run a test conditionally, use `test.if()`. The test will run if the condition is truthy. This is particularly useful for tests that should only run on specific architectures or operating systems.
```ts
test.if(Math.random() > 0.5)("runs half the time", () => {
// ...
});
```
```ts
test.if(Math.random() > 0.5)("runs half the time", () => {
// ...
@@ -168,252 +174,252 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
---
-
- ✔️
- [`.not`](https://jestjs.io/docs/expect#not)
---
-
- ✔️
- [`.toBe()`](https://jestjs.io/docs/expect#tobevalue)
---
-
- ✔️
- [`.toEqual()`](https://jestjs.io/docs/expect#toequalvalue)
---
-
- ✔️
- [`.toBeNull()`](https://jestjs.io/docs/expect#tobenull)
---
-
- ✔️
- [`.toBeUndefined()`](https://jestjs.io/docs/expect#tobeundefined)
---
-
- ✔️
- [`.toBeNaN()`](https://jestjs.io/docs/expect#tobenan)
---
-
- ✔️
- [`.toBeDefined()`](https://jestjs.io/docs/expect#tobedefined)
---
-
- ✔️
- [`.toBeFalsy()`](https://jestjs.io/docs/expect#tobefalsy)
---
-
- ✔️
- [`.toBeTruthy()`](https://jestjs.io/docs/expect#tobetruthy)
---
-
- ✔️
- [`.toContain()`](https://jestjs.io/docs/expect#tocontainitem)
---
-
- ✔️
- [`.toStrictEqual()`](https://jestjs.io/docs/expect#tostrictequalvalue)
---
-
- ✔️
- [`.toThrow()`](https://jestjs.io/docs/expect#tothrowerror)
---
-
- ✔️
- [`.toHaveLength()`](https://jestjs.io/docs/expect#tohavelengthnumber)
---
-
- ✔️
- [`.toHaveProperty()`](https://jestjs.io/docs/expect#tohavepropertykeypath-value)
---
-
- ✖️
- [`.extend`](https://jestjs.io/docs/expect#expectextendmatchers)
---
-
- ✔️
- [`.anything()`](https://jestjs.io/docs/expect#expectanything)
---
-
- ✔️
- [`.any()`](https://jestjs.io/docs/expect#expectanyconstructor)
---
-
- ✖️
- [`.arrayContaining()`](https://jestjs.io/docs/expect#expectarraycontainingarray)
---
-
- ✖️
- [`.assertions()`](https://jestjs.io/docs/expect#expectassertionsnumber)
---
-
- ✖️
- [`.closeTo()`](https://jestjs.io/docs/expect#expectclosetonumber-numdigits)
---
-
- ✖️
- [`.hasAssertions()`](https://jestjs.io/docs/expect#expecthasassertions)
---
-
- ✖️
- [`.objectContaining()`](https://jestjs.io/docs/expect#expectobjectcontainingobject)
---
-
- ✔️
- [`.stringContaining()`](https://jestjs.io/docs/expect#expectstringcontainingstring)
---
-
- ✔️
- [`.stringMatching()`](https://jestjs.io/docs/expect#expectstringmatchingstring--regexp)
---
-
- ✖️
- [`.addSnapshotSerializer()`](https://jestjs.io/docs/expect#expectaddsnapshotserializerserializer)
---
-
- ✔️
- [`.resolves()`](https://jestjs.io/docs/expect#resolves)
---
-
- ✔️
- [`.rejects()`](https://jestjs.io/docs/expect#rejects)
---
-
- ✔️
- [`.toHaveBeenCalled()`](https://jestjs.io/docs/expect#tohavebeencalled)
---
-
- ✔️
- [`.toHaveBeenCalledTimes()`](https://jestjs.io/docs/expect#tohavebeencalledtimesnumber)
---
-
- ✖️
- [`.toHaveBeenCalledWith()`](https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-)
---
-
- ✖️
- [`.toHaveBeenLastCalledWith()`](https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-)
---
-
- ✖️
- [`.toHaveBeenNthCalledWith()`](https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-)
---
-
- ✖️
- [`.toHaveReturned()`](https://jestjs.io/docs/expect#tohavereturned)
---
-
- ✖️
- [`.toHaveReturnedTimes()`](https://jestjs.io/docs/expect#tohavereturnedtimesnumber)
---
-
- ✖️
- [`.toHaveReturnedWith()`](https://jestjs.io/docs/expect#tohavereturnedwithvalue)
---
-
- ✖️
- [`.toHaveLastReturnedWith()`](https://jestjs.io/docs/expect#tohavelastreturnedwithvalue)
---
-
- ✖️
- [`.toHaveNthReturnedWith()`](https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value)
---
-
- ✔️
- [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits)
---
-
- ✔️
- [`.toBeGreaterThan()`](https://jestjs.io/docs/expect#tobegreaterthannumber--bigint)
---
-
- ✔️
- [`.toBeGreaterThanOrEqual()`](https://jestjs.io/docs/expect#tobegreaterthanorequalnumber--bigint)
---
-
- ✔️
- [`.toBeLessThan()`](https://jestjs.io/docs/expect#tobelessthannumber--bigint)
---
-
- ✔️
- [`.toBeLessThanOrEqual()`](https://jestjs.io/docs/expect#tobelessthanorequalnumber--bigint)
---
-
- ✔️
- [`.toBeInstanceOf()`](https://jestjs.io/docs/expect#tobeinstanceofclass)
---
-
- ✖️
- [`.toContainEqual()`](https://jestjs.io/docs/expect#tocontainequalitem)
---
-
- ✔️
- [`.toMatch()`](https://jestjs.io/docs/expect#tomatchregexp--string)
---
-
- ✔️
- [`.toMatchObject()`](https://jestjs.io/docs/expect#tomatchobjectobject)
---
-
- ✔️
- [`.toMatchSnapshot()`](https://jestjs.io/docs/expect#tomatchsnapshotpropertymatchers-hint)
---
-
- ✖️
- [`.toMatchInlineSnapshot()`](https://jestjs.io/docs/expect#tomatchinlinesnapshotpropertymatchers-inlinesnapshot)
---
-
- ✖️
- [`.toThrowErrorMatchingSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchingsnapshothint)
---
-
- ✖️
- [`.toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
{% /table %}

View File

@@ -31,7 +31,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh
"types": ["bun-types"],
// enable latest features
"lib": ["ESNext"],
"lib": ["esnext"],
"module": "esnext",
"target": "esnext",
@@ -45,6 +45,7 @@ Bun supports things like top-level await, JSX, and extensioned `.ts` imports, wh
"jsx": "react-jsx", // support JSX
"allowJs": true, // allow importing `.js` from `.ts`
"esModuleInterop": true, // allow default imports for CommonJS modules
// best practices
"strict": true,

View File

@@ -1,210 +0,0 @@
const nodejsBuiltinModules = [
"assert",
"async_hooks",
"buffer",
"child_process",
"cluster",
"console",
"constants",
"crypto",
"dgram",
"diagnostics_channel",
"dns",
"domain",
"events",
"fs",
"http",
"http2",
"https",
"inspector",
"module",
"net",
"os",
"path",
"perf_hooks",
"process",
"punycode",
"querystring",
"readline",
"repl",
"stream",
"string_decoder",
"timers",
"tls",
"trace_events",
"tty",
"url",
"util",
"v8",
"vm",
"wasi",
"worker_threads",
"zlib",
];
function getModuleKeys(moduleName: string): string[] {
const script = `import('${moduleName}').then(mod=>console.log(JSON.stringify(Object.keys(mod))))`;
const nodeProc = Bun.spawnSync(["node", "-e", script], {
stderr: "ignore",
});
const nodeKeys: string[] = JSON.parse(nodeProc.stdout.toString());
return nodeKeys;
}
function getAllProperties(obj = {}) {
const allKeys = new Set();
do {
Reflect.ownKeys(obj).forEach(key => allKeys.add(key));
} while ((obj = Object.getPrototypeOf(obj)));
return [...allKeys];
}
function getPrototypeKeys(moduleName: string, className: string): string[] {
// const script = `import('${moduleName}').then(mod=>console.log(JSON.stringify(Object.keys(mod.${className}.prototype))))`;
const script = `
import("${moduleName}").then((mod) => {
const lines = new Set();
let obj = mod.${className}.prototype;
do {
Reflect.ownKeys(obj).forEach((key) => lines.add(key));
} while ((obj = Object.getPrototypeOf(obj)));
console.log("[", [...lines].map(k => \`"\${String(k)}"\`).join(","), "]");
});`.replace(/\n/g, "");
// remove whitespace
// .replace(/\s+/g, "");
// console.log(script);
const nodeProc = Bun.spawnSync(["node", "-e", script], {
// stderr: "inherit",
// stdout: "inherit",
});
// console.log(nodeProc.stdout.toString());
const nodeKeys: string[] = JSON.parse(nodeProc.stdout.toString());
return nodeKeys;
}
const SKIP: Record<string, boolean> = {
"buffer.File": true,
"process.abort": true,
"process.exit": true,
"process.kill": true,
"process.reallyExit": true,
"vm.Script": true,
"zlib.deflate": true,
"zlib.inflate": true,
"zlib.unzip": true,
"zlib.deflateRaw": true,
"zlib.gunzip": true,
"zlib.gzip": true,
"zlib.inflateRaw": true,
"console.assert": true,
"console.count": true,
// "fs.mkdtempSync": true,
// "fs.read": true,
// "fs.readv": true,
// "fs.writev": true,
// "fs.writeSync": true,
// "fs.writeFileSync": true,
// "fs.writeFile": true,
// "fs.write": true,
// "fs.writevSync": true,
// "fs.watchFile": true,
// "fs.watch": true,
// "fs.utimesSync": true,
// "fs.utimes": true,
// "fs.unwatchFile": true,
// "fs.unlinkSync": true,
// "fs.unlink": true,
// "fs.truncateSync": true,
// "fs.truncate": true,
// "fs.symlinkSync": true,
};
for (const moduleName of nodejsBuiltinModules) {
const heading = `======== ${moduleName} ========`;
// print equals sign to match the length of heading
console.log("\n\n" + "=".repeat(heading.length));
console.log(heading);
console.log("=".repeat(heading.length));
const mod = await import(moduleName);
const bunKeys: string[] = Object.keys(mod);
const nodeKeys = getModuleKeys(moduleName);
// print top-level elements that are missing
// const missingKeys = nodeKeys
// .filter((key) => !bunKeys.includes(key))
// .filter((k) => !k.startsWith("_"));
// const notMissing = nodeKeys.filter((key) => bunKeys.includes(key));
// if (missingKeys.length === 0) {
// console.log(`Fully implemented.`);
// } else {
// console.log(`Missing ${missingKeys.map((k) => `\`${k}\``).join(" ")}`);
// }
console.log();
// check for prototype compatibility
let missing = false;
for (const k of nodeKeys) {
if (k.startsWith("_")) continue;
if (!bunKeys.includes(k)) {
missing = true;
console.log(` [${moduleName}.${k}] Not implemented.`);
continue;
}
if (mod[k] && typeof mod[k] === "function") {
if (!!mod[k].prototype) {
const className = `${moduleName}.${k}`;
const bunProtoKeys = getAllProperties(mod[k].prototype);
// console.log(mod[k].prototype);
// getAllProperties;
// for (const l in mod[k].prototype) {
// bunProtoKeys.push(l);
// }
const nodeProtoKeys = getPrototypeKeys(moduleName, k);
// console.log("nodeProtoKeys", nodeProtoKeys);
// console.log("bunProtoKeys", bunProtoKeys);
// console.log("nodeProtoKeys", nodeProtoKeys);
// console.log("bunProtoKeys", bunProtoKeys);
const missingProtoKeys = nodeProtoKeys.filter(key => !bunProtoKeys.includes(key));
// const notMissingProtoKeys = nodeProtoKeys.filter((key) =>
// bunProtoKeys.includes(key)
// );
if (missingProtoKeys.length === 0) {
console.log(` [${className}] Fully implemented.`);
} else {
missing = true;
console.log(
` [${className}] Missing ${missingProtoKeys
.filter(k => !k.startsWith("_"))
.map(k => `\`${k}\``)
.join(" ")}`,
);
}
} else {
if (moduleName === "console") continue;
if (moduleName === "fs") continue;
if (SKIP[`${moduleName}.${k}`]) continue;
try {
// console.log(`trying ${moduleName}.${k}...`);
await mod[k]();
await Bun.sleep(1);
} catch (err: any) {
if ((err?.message as string).includes("not yet implemented")) {
missing = true;
console.log(` [${moduleName}.${k}] Not implemented.`);
}
}
}
}
}
if (!missing) {
console.log(`[${moduleName}] Fully implemented.`);
}
}
console.log("\n\n================\nDONE.");
process.exit();

View File

@@ -26,7 +26,7 @@
"@types/react": "^18.0.25",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
"bun-webkit": "0.0.1-2c4d07c9499a65f36f554dc4cd4e9e0640632b8c"
"bun-webkit": "0.0.1-4d995edbc44062b251be638818edcd88d7d14dd7"
},
"version": "0.0.0",
"prettier": "./.prettierrc.cjs"

3
packages/bun-ecosystem/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.DS_Store
node_modules
tmp

View File

@@ -0,0 +1,7 @@
# bun-ecosystem
A registry to test `npm` packages using Bun. This can be used as a tool to find bugs in Bun by running the test suites of these packages. In the future, we will run theses tests to catch regressions between releases.
```sh
bun run test
```

BIN
packages/bun-ecosystem/bun.lockb Executable file

Binary file not shown.

View File

@@ -0,0 +1,15 @@
{
"name": "bun-ecosystem-ci",
"private": true,
"dependencies": {
"globby": "^13.1.3"
},
"devDependencies": {
"bun-types": "canary",
"prettier": "^2.8.2"
},
"scripts": {
"format": "prettier --write src",
"test": "bun run src/runner.ts"
}
}

View File

@@ -0,0 +1,69 @@
export type Package = {
readonly name: string;
readonly repository: string;
readonly cwd?: string;
readonly tests?: {
readonly style: "jest" | "ava" | "tape" | "custom";
readonly include: string[];
readonly exclude?: string[];
readonly disabled?: boolean;
};
};
export const packages: Package[] = [
{
name: "lodash",
repository: github("lodash/lodash"),
tests: {
style: "jest",
include: ["test/*.js"],
exclude: [
"debounce.test.js", // hangs runner
"size.test.js", // require('vm').runInNewContext()
"merge.test.js", // failing
],
},
},
{
name: "chalk",
repository: github("chalk/chalk"),
tests: {
style: "ava",
include: ["test/*.js"],
},
},
{
name: "request",
repository: github("request/request"),
tests: {
style: "tape",
include: ["tests/*.js"],
},
},
{
name: "commander",
repository: github("tj/commander.js"),
tests: {
style: "jest",
include: ["tests/*.js"],
},
},
{
name: "express",
repository: github("expressjs/express"),
tests: {
style: "jest",
include: ["test/**/*.js"],
exclude: [
"test/res.sendStatus.js", // https://github.com/oven-sh/bun/issues/887
"test/Route.js", // https://github.com/oven-sh/bun/issues/2030
],
// Most tests fail due to lack of "http2"
disabled: true,
},
},
];
function github(repository: string): string {
return `git@github.com:${repository}.git`;
}

View File

@@ -0,0 +1,92 @@
import type { Package } from "./packages";
import { packages } from "./packages";
import { existsSync, copyFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { globby } from "globby";
for (const pkg of packages) {
try {
await loadPackage(pkg, "tmp");
} catch (error) {
console.error(pkg.name, error);
}
}
async function loadPackage(pkg: Package, cwd?: string): Promise<void> {
await gitClone({
cwd,
repository: pkg.repository,
name: pkg.name,
});
const dir = join(cwd ?? "", pkg.name, pkg.cwd ?? "");
await spawn({
cwd: dir,
cmd: ["bun", "install"],
});
if (!pkg.tests || pkg.tests.style !== "jest") {
return;
}
const files = await globby(pkg.tests.include, {
cwd: dir,
ignore: pkg.tests.exclude ?? [crypto.randomUUID()],
onlyFiles: true,
caseSensitiveMatch: false,
});
if (!files.length) {
throw new Error("No tests found");
}
for (const file of files) {
let path = file;
if (!file.includes(".test.")) {
const ext = path.lastIndexOf(".");
path = file.substring(0, ext) + ".test" + file.substring(ext);
copyFileSync(join(dir, file), join(dir, path));
}
await spawn({
cwd: dir,
cmd: ["bun", "test", path],
});
}
}
type GitCloneOptions = {
repository: string;
cwd?: string;
name?: string;
};
async function gitClone(options: GitCloneOptions): Promise<void> {
const name = options.name ?? dirname(options.repository);
const cwd = options.cwd ?? process.cwd();
const path = join(cwd, name);
if (existsSync(path)) {
await spawn({
cwd: path,
cmd: ["git", "pull"],
});
} else {
const url = `${options.repository}`;
await spawn({
cwd,
cmd: ["git", "clone", "--single-branch", "--depth", "1", url, name],
});
}
}
type SpawnOptions = {
cwd: string;
cmd: string[];
};
async function spawn({ cwd, cmd }: SpawnOptions) {
const { exited } = await Bun.spawn({
cwd,
cmd,
stdout: "inherit",
stderr: "inherit",
});
const exitCode = await exited;
if (exitCode !== 0) {
throw new Error(`"${cmd.join(" ")}" exited with ${exitCode}`);
}
}

View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "node",
"types": ["bun-types"],
"esModuleInterop": true,
"allowJs": true,
"strict": true,
"resolveJsonModule": true
},
"include": [
"src"
]
}

View File

@@ -46,10 +46,7 @@ export function objectPreviewToString(objectPreview: JSC.Runtime.ObjectPreview):
items = entries.map(entryPreviewToString).sort();
} else if (properties) {
if (isIndexed(subtype)) {
items = properties.map(indexedPropertyPreviewToString);
if (subtype !== "array") {
items.sort();
}
items = properties.map(indexedPropertyPreviewToString).sort();
} else {
items = properties.map(namedPropertyPreviewToString).sort();
}

Binary file not shown.

View File

@@ -174,26 +174,18 @@ declare module "bun:test" {
*
* @param table Array of Arrays with the arguments that are passed into the test fn for each row.
*/
each<T extends Readonly<[any, ...any[]]>>(
each<T extends ReadonlyArray<unknown>>(
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: [...T]) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
each<T extends Array<any>>(
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: Readonly<T>) => void | Promise<unknown>,
fn: (...args: T) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
each<T>(
table: Array<T>,
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: T[]) => void | Promise<unknown>,
fn: (arg: T) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
};
@@ -427,25 +419,18 @@ declare module "bun:test" {
*
* @param table Array of Arrays with the arguments that are passed into the test fn for each row.
*/
each<T extends Readonly<[any, ...any[]]>>(
each<T extends ReadonlyArray<unknown>>(
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: [...T]) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
each<T extends Array<any>>(
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: Readonly<T>) => void | Promise<unknown>,
fn: (...args: T) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
each<T>(
table: Array<T>,
table: ReadonlyArray<T>,
): (
label: string,
fn: (...args: T[]) => void | Promise<unknown>,
fn: (arg: T, done: (err?: unknown) => void) => void | Promise<unknown>,
options?: number | TestOptions,
) => void;
};

View File

@@ -70,19 +70,6 @@ declare module "bun" {
options?: { PATH?: string; cwd?: string },
): string | null;
interface TOML {
/**
* Parse a TOML string into a JavaScript object.
*
* @param {string} command The name of the executable or script
* @param {string} options.PATH Overrides the PATH environment variable
* @param {string} options.cwd Limits the search to a particular directory in which to searc
*
*/
parse(input: string): object;
}
export const TOML: TOML;
export type Serve<WebSocketDataType = undefined> =
| ServeOptions
| TLSServeOptions
@@ -163,10 +150,6 @@ declare module "bun" {
export function write(
destination: BunFile | PathLike,
input: Blob | TypedArray | ArrayBufferLike | string | BlobPart[],
options?: {
/** If writing to a PathLike, set the permissions of the file. */
mode?: number;
},
): Promise<number>;
/**
@@ -925,14 +908,6 @@ declare module "bun" {
* Minify whitespace and comments from the output.
*/
minifyWhitespace?: boolean;
/**
* **Experimental**
*
* Enabled by default, use this to disable dead code elimination.
*
* Some other transpiler options may still do some specific dead code elimination.
*/
deadCodeElimination?: boolean;
/**
* This does two things (and possibly more in the future):
@@ -2209,21 +2184,6 @@ declare module "bun" {
tls?: TLSOptions;
}
export interface SocketAddress {
/**
* The IP address of the client.
*/
address: string;
/**
* The port of the client.
*/
port: number;
/**
* The IP family ("IPv4" or "IPv6").
*/
family: "IPv4" | "IPv6";
}
/**
* HTTP & HTTPS Server
*
@@ -2263,7 +2223,7 @@ declare module "bun" {
* });
*
* // Update the server to return a different response
* server.reload({
* server.update({
* fetch(request) {
* return new Response("Hello World v2")
* }
@@ -2371,20 +2331,6 @@ declare module "bun" {
compress?: boolean,
): ServerWebSocketSendStatus;
/**
* Returns the client IP address and port of the given Request. If the request was closed or is a unix socket, returns null.
*
* @example
* ```js
* export default {
* async fetch(request, server) {
* return new Response(server.requestIP(request));
* }
* }
* ```
*/
requestIP(request: Request): SocketAddress | null;
/**
* How many requests are in-flight right now?
*/
@@ -3214,7 +3160,7 @@ declare module "bun" {
loader: Loader;
}
type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject | undefined;
type OnLoadResult = OnLoadResultSourceCode | OnLoadResultObject;
type OnLoadCallback = (
args: OnLoadArgs,
) => OnLoadResult | Promise<OnLoadResult>;
@@ -3306,37 +3252,6 @@ declare module "bun" {
* The config object passed to `Bun.build` as is. Can be mutated.
*/
config: BuildConfig & { plugins: BunPlugin[] };
/**
* Create a lazy-loaded virtual module that can be `import`ed or `require`d from other modules
*
* @param specifier The module specifier to register the callback for
* @param callback The function to run when the module is imported or required
*
* ### Example
* @example
* ```ts
* Bun.plugin({
* setup(builder) {
* builder.module("hello:world", () => {
* return { exports: { foo: "bar" }, loader: "object" };
* });
* },
* });
*
* // sometime later
* const { foo } = await import("hello:world");
* console.log(foo); // "bar"
*
* // or
* const { foo } = require("hello:world");
* console.log(foo); // "bar"
* ```
*/
module(
specifier: string,
callback: () => OnLoadResult | Promise<OnLoadResult>,
): void;
}
interface BunPlugin {
@@ -3900,7 +3815,7 @@ declare module "bun" {
: undefined;
type ReadableToSyncIO<X extends Readable> = X extends "pipe" | undefined
? Buffer
? Uint8Array
: undefined;
type WritableIO = FileSink | number | undefined;

View File

@@ -701,10 +701,10 @@ declare module "dns" {
* one of the `DNS error codes`.
* @since v0.1.16
*/
export function reverse(
ip: string,
callback: (err: ErrnoException | null, hostnames: string[]) => void,
): void;
// export function reverse(
// ip: string,
// callback: (err: ErrnoException | null, hostnames: string[]) => void,
// ): void;
/**
* Sets the IP address and port of servers to be used when performing DNS
* resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted
@@ -749,7 +749,7 @@ declare module "dns" {
* ```
* @since v0.11.3
*/
export function getServers(): string[];
// export function getServers(): string[];
/**
* Set the default value of `verbatim` in {@link lookup} and `dnsPromises.lookup()`. The value could be:
*
@@ -841,7 +841,7 @@ declare module "dns" {
* @since v8.3.0
*/
cancel(): void;
getServers: typeof getServers;
// getServers: typeof getServers;
resolve: typeof resolve;
resolve4: typeof resolve4;
resolve6: typeof resolve6;
@@ -854,7 +854,7 @@ declare module "dns" {
resolveSoa: typeof resolveSoa;
resolveSrv: typeof resolveSrv;
resolveTxt: typeof resolveTxt;
reverse: typeof reverse;
// reverse: typeof reverse;
/**
* The resolver instance will send its requests from the specified IP address.
* This allows programs to specify outbound interfaces when used on multi-homed

View File

@@ -681,7 +681,7 @@ interface Process {
*/
setSourceMapsEnabled(enabled: boolean): void;
kill(pid: number, signal?: string | number): true;
kill(pid: number, signal?: string | number): void;
on(event: "beforeExit", listener: BeforeExitListener): this;
// on(event: "disconnect", listener: DisconnectListener): this;
@@ -725,14 +725,6 @@ interface Process {
* @param listener The event handler function
*/
listenerCount(eventName: string | symbol, listener?: Function): number;
/**
* Get the constrained memory size for the process.
*
* On Linux, this is the memory limit for the process, accounting for cgroups 1 and 2.
* On other operating systems, this returns `undefined`.
*/
constrainedMemory(): number | undefined;
}
interface MemoryUsageObject {

View File

@@ -1,7 +1,6 @@
{
"name": "bun-types",
"repository": "https://github.com/oven-sh/bun",
"license": "MIT",
"devDependencies": {
"conditional-type-checks": "^1.0.6",
"prettier": "^2.4.1",
@@ -13,7 +12,7 @@
"prebuild": "echo $(pwd)",
"build": "rm -rf ./dist && bun run bundle && bun run fmt",
"bundle": "bun scripts/bundle.ts ./dist",
"test": "tsc",
"test": "tsd",
"fmt": "echo $(which prettier) && prettier --write './**/*.{ts,tsx,js,jsx}'"
},
"tsd": {

View File

@@ -41,6 +41,3 @@ import * as tsd from "tsd";
env: { ...process.env, dummy: "" },
});
}
{
Bun.TOML.parse("asdf = asdf");
}

View File

@@ -1,5 +0,0 @@
import * as dns from "node:dns";
dns.resolve("asdf", "A", () => {});
dns.reverse("asdf", () => {});
dns.getServers();

View File

@@ -63,69 +63,3 @@ describe("bun:test", () => {
expect(undefined).not.toBeDefined();
});
});
// inference should work when data is passed directly in
test.each([
["a", true, 5],
["b", false, 1234],
])("test.each", (a, b, c) => {
expectType<string>(a);
expectType<boolean>(b);
expectType<number | string>(c);
});
describe.each([
["a", true, 5],
["b", false, 5],
])("test.each", (a, b, c) => {
expectType<string>(a);
expectType<boolean>(b);
expectType<number | string>(c);
});
describe.each([
["a", true, 5],
["b", false, "asdf"],
])("test.each", (a, b, c) => {
expectType<string>(a);
expectType<boolean>(b);
expectType<number | string>(c);
});
describe.each([{ asdf: "asdf" }, { asdf: "asdf" }])("test.each", (a, b, c) => {
expectType<{ asdf: string }>(a);
expectType<{ asdf: string }>(c);
});
// no inference on data
const data = [
["a", true, 5],
["b", false, "asdf"],
];
test.each(data)("test.each", (...args) => {
expectType<string | number | boolean>(args[0]);
});
describe.each(data)("test.each", (a, b, c) => {
expectType<string | number | boolean>(a);
expectType<string | number | boolean>(b);
expectType<string | number | boolean>(c);
});
// as const
const dataAsConst = [
["a", true, 5],
["b", false, "asdf"],
] as const;
test.each(dataAsConst)("test.each", (...args) => {
expectType<string>(args[0]);
expectType<boolean>(args[1]);
expectType<string | number>(args[2]);
});
describe.each(dataAsConst)("test.each", (...args) => {
expectType<string>(args[0]);
expectType<boolean>(args[1]);
expectType<string | number>(args[2]);
});
describe.each(dataAsConst)("test.each", (a, b, c) => {
expectType<"a" | "b">(a);
expectType<boolean>(b);
expectType<5 | "asdf">(c);
});

View File

@@ -9,9 +9,7 @@
"allowSyntheticDefaultImports": true,
"disableSolutionSearching": true,
"noUnusedLocals": true,
"outDir": "build",
"noEmit": true,
"resolveJsonModule": true
"outDir": "build"
},
"exclude": [
"dist",

View File

@@ -665,39 +665,9 @@ int bsd_udp_packet_buffer_ecn(void *msgvec, int index) {
return 0; // no ecn defaults to 0
}
static int bsd_do_connect_raw(struct addrinfo *rp, int fd)
static int bsd_do_connect(struct addrinfo *result, int fd)
{
do {
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0 || errno == EINPROGRESS) {
return 0;
}
} while (errno == EINTR);
return LIBUS_SOCKET_ERROR;
}
static int bsd_do_connect(struct addrinfo *rp, int *fd)
{
while (rp != NULL) {
if (bsd_do_connect_raw(rp, *fd) == 0) {
return 0;
}
rp = rp->ai_next;
bsd_close_socket(*fd);
if (rp == NULL) {
return LIBUS_SOCKET_ERROR;
}
int resultFd = bsd_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (resultFd < 0) {
return LIBUS_SOCKET_ERROR;
}
*fd = resultFd;
}
return LIBUS_SOCKET_ERROR;
return connect(fd, result->ai_addr, (socklen_t) result->ai_addrlen);
}
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options) {
@@ -730,21 +700,18 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, co
return LIBUS_SOCKET_ERROR;
}
}
if (bsd_do_connect_raw(result, fd) != 0) {
}
do {
if (bsd_do_connect(result, fd) != 0 && errno != EINPROGRESS) {
bsd_close_socket(fd);
freeaddrinfo(result);
return LIBUS_SOCKET_ERROR;
}
} else {
if (bsd_do_connect(result, &fd) != 0) {
freeaddrinfo(result);
return LIBUS_SOCKET_ERROR;
}
}
} while (errno == EINTR);
freeaddrinfo(result);
return fd;
}

View File

@@ -30,7 +30,7 @@ void Bun__internal_dispatch_ready_poll(void* loop, void* poll);
#include <stdint.h>
#endif
void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void*);
void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs);
/* Pointer tags are used to indicate a Bun pointer versus a uSockets pointer */
#define UNSET_BITS_49_UNTIL_64 0x0000FFFFFFFFFFFF
@@ -174,20 +174,13 @@ void us_loop_run(struct us_loop_t *loop) {
}
}
void bun_on_tick_before(void* ctx);
void bun_on_tick_after(void* ctx);
void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void* tickCallbackContext) {
void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs) {
us_loop_integrate(loop);
if (loop->num_polls == 0)
return;
if (tickCallbackContext) {
bun_on_tick_before(tickCallbackContext);
}
/* Emit pre callback */
us_internal_loop_pre(loop);
@@ -209,10 +202,6 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void* tickC
}
#endif
if (tickCallbackContext) {
bun_on_tick_after(tickCallbackContext);
}
/* Iterate ready polls, dispatching them by type */
for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) {
struct us_poll_t *poll = GET_READY_POLL(loop, loop->current_ready_poll);
@@ -414,18 +403,14 @@ struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsi
#endif
#ifdef LIBUS_USE_EPOLL
void us_timer_close(struct us_timer_t *timer, int fallthrough) {
void us_timer_close(struct us_timer_t *timer) {
struct us_internal_callback_t *cb = (struct us_internal_callback_t *) timer;
us_poll_stop(&cb->p, cb->loop);
close(us_poll_fd(&cb->p));
/* (regular) sockets are the only polls which are not freed immediately */
if(fallthrough){
us_free(timer);
}else {
us_poll_free((struct us_poll_t *) timer, cb->loop);
}
/* (regular) sockets are the only polls which are not freed immediately */
us_poll_free((struct us_poll_t *) timer, cb->loop);
}
void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms, int repeat_ms) {
@@ -442,7 +427,7 @@ void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms
us_poll_start((struct us_poll_t *) t, internal_cb->loop, LIBUS_SOCKET_READABLE);
}
#else
void us_timer_close(struct us_timer_t *timer, int fallthrough) {
void us_timer_close(struct us_timer_t *timer) {
struct us_internal_callback_t *internal_cb = (struct us_internal_callback_t *) timer;
struct kevent64_s event;
@@ -450,11 +435,7 @@ void us_timer_close(struct us_timer_t *timer, int fallthrough) {
kevent64(internal_cb->loop->fd, &event, 1, NULL, 0, 0, NULL);
/* (regular) sockets are the only polls which are not freed immediately */
if(fallthrough){
us_free(timer);
}else {
us_poll_free((struct us_poll_t *) timer, internal_cb->loop);
}
us_poll_free((struct us_poll_t *) timer, internal_cb->loop);
}
void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms, int repeat_ms) {

View File

@@ -132,7 +132,7 @@ struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsi
void *us_timer_ext(struct us_timer_t *timer);
/* */
void us_timer_close(struct us_timer_t *timer, int fallthrough);
void us_timer_close(struct us_timer_t *timer);
/* Arm a timer with a delay from now and eventually a repeat delay.
* Specify 0 as repeat delay to disable repeating. Specify both 0 to disarm. */
@@ -391,7 +391,6 @@ struct us_socket_t *us_socket_wrap_with_tls(int ssl, struct us_socket_t *s, stru
int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more);
struct us_socket_t* us_socket_open(int ssl, struct us_socket_t * s, int is_client, char* ip, int ip_length);
int us_raw_root_certs(struct us_cert_string_t**out);
unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6);
#ifdef __cplusplus
}

View File

@@ -47,7 +47,7 @@ void us_internal_loop_data_free(struct us_loop_t *loop) {
free(loop->data.recv_buf);
us_timer_close(loop->data.sweep_timer, 0);
us_timer_close(loop->data.sweep_timer);
us_internal_async_close(loop->data.wakeup_async);
}

View File

@@ -280,25 +280,3 @@ int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int le
// non-TLS is always raw
return us_socket_write(ssl, s, data, length, msg_more);
}
unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6)
{
// This function is manual inlining + modification of
// us_socket_remote_address
// AsyncSocket::getRemoteAddress
// To get { ip, port, is_ipv6 } for Bun.serve().requestIP()
struct bsd_addr_t addr;
if (bsd_remote_addr(us_poll_fd(&s->p), &addr)) {
return 0;
}
int length = bsd_addr_get_ip_length(&addr);
if (!length) {
return 0;
}
memcpy(buf, bsd_addr_get_ip(&addr), length);
*port = bsd_addr_get_port(&addr);
return length;
}

View File

@@ -14,7 +14,7 @@ void uws_timer_close(struct us_timer_t *timer)
struct timer_handler_data *data;
memcpy(&data, us_timer_ext(t), sizeof(struct timer_handler_data *));
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
//Timer create helper
struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void *data), void *data)
@@ -47,7 +47,7 @@ struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void
if (!data->repeat)
{
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
},
ms, repeat_ms);

View File

@@ -19,7 +19,7 @@ void uws_timer_close(struct us_timer_t *timer)
struct timer_handler_data *data;
memcpy(&data, us_timer_ext(t), sizeof(struct timer_handler_data *));
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
//Timer create helper
struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void *data), void *data)
@@ -52,7 +52,7 @@ struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void
if (!data->repeat)
{
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
},
ms, repeat_ms);

View File

@@ -62,7 +62,7 @@ void uws_timer_close(struct us_timer_t *timer)
struct timer_handler_data *data;
memcpy(&data, us_timer_ext(t), sizeof(struct timer_handler_data *));
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
//Timer create helper
struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void *data), void *data)
@@ -95,7 +95,7 @@ struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void
if (!data->repeat)
{
free(data);
us_timer_close(t, 0);
us_timer_close(t);
}
},
ms, repeat_ms);

View File

@@ -205,7 +205,6 @@ extern "C"
DLL_EXPORT unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws);
DLL_EXPORT size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws, const char **dest);
DLL_EXPORT size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws, const char **dest);
DLL_EXPORT void uws_res_get_remote_address_info(uws_res_t *res, const char **dest, size_t *length, unsigned int *port);
//Response
DLL_EXPORT void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length, bool close_connection);

View File

@@ -90,7 +90,7 @@ int main() {
delete upgradeData;
us_timer_close(t, 0);
us_timer_close(t);
}, 5000, 0);
},

View File

@@ -439,24 +439,6 @@ public:
return {internalEnd(data, totalSize, true, true, closeConnection), hasResponded()};
}
/* Write the end of chunked encoded stream */
bool sendTerminatingChunk(bool closeConnection = false) {
writeStatus(HTTP_200_OK);
HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED)) {
/* Write mark on first call to write */
writeMark();
writeHeader("Transfer-Encoding", "chunked");
httpResponseData->state |= HttpResponseData<SSL>::HTTP_WRITE_CALLED;
}
/* Terminating 0 chunk */
Super::write("\r\n0\r\n\r\n", 7);
return internalEnd({nullptr, 0}, 0, false, false, closeConnection);
}
/* Write parts of the response in chunking fashion. Starts timeout if failed. */
bool write(std::string_view data) {
writeStatus(HTTP_200_OK);

View File

@@ -126,7 +126,7 @@ public:
LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this);
/* Stop and free dateTimer first */
us_timer_close(loopData->dateTimer, 1);
us_timer_close(loopData->dateTimer);
loopData->~LoopData();
/* uSockets will track whether this loop is owned by us or a borrowed alien loop */

View File

@@ -8,10 +8,8 @@
"mime-db": "^1.52.0"
},
"scripts": {
"run": "node hello.js",
"start": "hello.js",
"start:bun": "bun hello.js",
"start:bun:quotes": "bun run hello.js"
"run": "hello.js",
"start": "bun hello.js"
},
"trustedDependencies": [
"mime"

View File

@@ -28,6 +28,8 @@
.mtks { text-decoration: line-through; }
.mtks.mtku { text-decoration: underline line-through; text-underline-position: under; }
.bunlock {
display: flex;
flex-direction: row;
@@ -46,7 +48,6 @@
font-family: var(--vscode-editor-font-family);
background-color: var(--vscode-editor-background);
}
.lines > span {
margin-top: 1px;
margin-bottom: 1px;
@@ -66,4 +67,4 @@ code > span {
width: 100%;
margin-top: 1px;
margin-bottom: 1px;
}
}

View File

@@ -12,6 +12,7 @@ buildSync({
external: ["vscode"],
platform: "node",
format: "cjs",
// The following settings are required to allow for extension debugging
minify: false,
sourcemap: true,

View File

@@ -0,0 +1,35 @@
export function styleLockfile(preview: string) {
// Match all lines that don't start with a whitespace character
const lines = preview.split(/\n(?!\s)/);
return lines.map(styleSection).join("\n");
}
function styleSection(section: string) {
const lines = section.split(/\n/);
return lines.map(styleLine).join("\n");
}
function styleLine(line: string) {
if (line.startsWith("#")) {
return `<span class="mtk5">${line}</span>`;
}
const parts = line.trim().split(" ");
if (line.startsWith(" ")) {
return `<span><span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;${parts[0]}&nbsp;</span><span class="mtk16">${parts[1]}</span></span>`;
}
if (line.startsWith(" ")) {
const leftPart = `<span class="mtk6">&nbsp;&nbsp;${parts[0]}&nbsp;</span>`;
if (parts.length === 1) return `<span>${leftPart}</span>`;
if (parts[1].startsWith('"http://') || parts[1].startsWith('"https://'))
return `<span>${leftPart}<span class="mtk12 detected-link">${parts[1]}</span></span>`;
if (parts[1].startsWith('"')) return `<span>${leftPart}<span class="mtk16">${parts[1]}</span></span>`;
return `<span>${leftPart}<span class="mtk6">${parts[1]}</span></span>`;
}
return `<span class="mtk1">${line}&nbsp;</span>`;
}

View File

@@ -36,7 +36,7 @@ export class BunLockfileEditorProvider implements vscode.CustomReadonlyEditorPro
}
function renderLockfile({ webview }: vscode.WebviewPanel, preview: string, extensionUri: vscode.Uri): void {
const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, "assets", "vscode.css"));
const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, "media", "vscode.css"));
const lockfileContent = styleLockfile(preview);
const lineNumbers: string[] = [];
@@ -49,8 +49,11 @@ function renderLockfile({ webview }: vscode.WebviewPanel, preview: string, exten
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource};">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="${styleVSCodeUri}" rel="stylesheet" />
</head>
<body>
@@ -69,7 +72,7 @@ function previewLockfile(uri: vscode.Uri, token?: vscode.CancellationToken): Pro
const process = spawn("bun", [uri.fsPath], {
stdio: ["ignore", "pipe", "pipe"],
});
token?.onCancellationRequested(() => {
token.onCancellationRequested(() => {
process.kill();
});
let stdout = "";

View File

@@ -25,7 +25,7 @@ export async function providePackageJsonTasks(): Promise<BunTask[]> {
return Object.entries(scripts).map(([name, script]) => {
// Prefix script with bun if it doesn't already start with bun
const shellCommand = script.startsWith("bun run ") ? script : `bun run ${script}`;
const shellCommand = script.startsWith("bun") ? script : `bun ${script}`;
const task = new BunTask({
script,
@@ -55,12 +55,10 @@ function extractScriptsFromPackageJson(document: vscode.TextDocument) {
const range = new vscode.Range(document.positionAt(startIndex), document.positionAt(endIndex));
const scripts = matches[1].split(/,\s*/).map(script => {
const elements = script.match(/"([^"\\]|\\.|\\\n)*"/g);
if (elements?.length != 2) return null;
const [name, command] = elements;
const [name, command] = script.split(/s*:\s*/);
return {
name: name.replace('"', "").trim(),
command: command.replace(/(?<!\\)"/g, "").trim(),
name: name.replace(/"/g, "").trim(),
command: command.replace(/"/g, "").trim(),
range: new vscode.Range(
document.positionAt(startIndex + matches[0].indexOf(name)),
document.positionAt(startIndex + matches[0].indexOf(name) + name.length + command.length),
@@ -177,25 +175,23 @@ function registerHoverProvider(context: vscode.ExtensionContext) {
},
}),
vscode.commands.registerCommand("extension.bun.codelens.debug.task", async ({ script, name }: CommandArgs) => {
if (script.startsWith("bun run ")) script = script.slice(8);
if (script.startsWith("bun ")) script = script.slice(4);
debugCommand(script);
}),
vscode.commands.registerCommand("extension.bun.codelens.run.task", async ({ script, name }: CommandArgs) => {
if (script.startsWith("bun run ")) script = script.slice(8);
if (script.startsWith("bun ")) script = script.slice(4);
name = `Bun Task: ${name}`;
const terminals = getActiveTerminal(name);
if (terminals.length > 0) {
terminals[0].show();
terminals[0].sendText(`bun run ${script}`);
terminals[0].sendText(`bun ${script}`);
return;
}
const terminal = vscode.window.createTerminal({ name });
terminal.show();
terminal.sendText(`bun run ${script}`);
terminal.sendText(`bun ${script}`);
}),
);
}

1
src/api/schema.d.ts generated vendored
View File

@@ -719,7 +719,6 @@ export interface BunInstall {
global_bin_dir?: string;
frozen_lockfile?: boolean;
exact?: boolean;
use_github_api?: boolean;
}
export interface ClientServerModule {

10
src/api/schema.js generated
View File

@@ -3038,10 +3038,6 @@ function decodeBunInstall(bb) {
result["exact"] = !!bb.readByte();
break;
case 21:
result["use_github_api"] = !!bb.readByte();
break;
default:
throw new Error("Attempted to parse invalid message");
}
@@ -3174,12 +3170,6 @@ function encodeBunInstall(message, bb) {
bb.writeByte(20);
bb.writeByte(value);
}
var value = message["use_github_api"];
if (value != null) {
bb.writeByte(21);
bb.writeByte(value);
}
bb.writeByte(0);
}

View File

@@ -588,7 +588,6 @@ message BunInstall {
string global_bin_dir = 18;
bool frozen_lockfile = 19;
bool exact = 20;
bool use_github_api = 21;
}
struct ClientServerModule {

View File

@@ -2882,9 +2882,6 @@ pub const Api = struct {
/// exact
exact: ?bool = null,
/// use_github_api
use_github_api: ?bool = null,
pub fn decode(reader: anytype) anyerror!BunInstall {
var this = std.mem.zeroes(BunInstall);
@@ -2954,9 +2951,6 @@ pub const Api = struct {
20 => {
this.exact = try reader.readValue(bool);
},
21 => {
this.use_github_api = try reader.readValue(bool);
},
else => {
return error.InvalidMessage;
},
@@ -3046,10 +3040,6 @@ pub const Api = struct {
try writer.writeFieldID(20);
try writer.writeInt(@as(u8, @intFromBool(exact)));
}
if (this.use_github_api) |use_github_api| {
try writer.writeFieldID(21);
try writer.writeInt(@as(u8, @intFromBool(use_github_api)));
}
try writer.endMessage();
}
};

View File

@@ -1 +1 @@
5
3

View File

@@ -72,7 +72,6 @@ const TranspilerOptions = struct {
trim_unused_imports: ?bool = null,
inlining: bool = false,
dead_code_elimination: bool = true,
minify_whitespace: bool = false,
minify_identifiers: bool = false,
minify_syntax: bool = false,
@@ -542,10 +541,6 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std
transpiler.minify_whitespace = flag.toBoolean();
}
if (object.get(globalThis, "deadCodeElimination")) |flag| {
transpiler.dead_code_elimination = flag.toBoolean();
}
if (object.getTruthy(globalThis, "minify")) |hot| {
if (hot.isBoolean()) {
transpiler.minify_whitespace = hot.coerce(bool, globalThis);
@@ -805,7 +800,6 @@ pub fn constructor(
bundler.options.macro_remap = transpiler_options.macro_map;
}
bundler.options.dead_code_elimination = transpiler_options.dead_code_elimination;
bundler.options.minify_whitespace = transpiler_options.minify_whitespace;
// Keep defaults for these

Some files were not shown because too many files have changed in this diff Show More