Compare commits

...

60 Commits

Author SHA1 Message Date
Dylan Conway
acf4bb71a6 don't character diff emojis 2023-11-02 16:44:21 -07:00
Jarred Sumner
e646853d7a Fix assertion failure 2023-11-02 15:15:16 -07:00
Liz
3912f4d064 fix(build): add option and auto detect for arch linux (#6835)
* fix(build): add option and auto detect for arch linux

This adds a option and a automatic routine for decting arch linux,
where the path for libatomic is a bit special.

* fix: don't statically link if not needed
2023-10-31 23:21:45 -07:00
dave caruso
53d1acb0a5 chore: build system improvements (#6811)
* build system improvements

* public the secret download link

* typo

* i think i fixed it

* fix ci

* un-bump the cmake version
2023-10-31 17:25:13 -07:00
マルコメ
23d2c4c8e4 workflows(bun-mac-x64.yml): Fix typo "bun-obj-darwin-x6" (#6819) 2023-10-31 09:47:16 -07:00
Anton Golub
732650d6a4 fix: provide nodejs compat for dns methods wrapped with util.promisify (#6748)
* fix: add nodejs compat for dns methods wrapping with util.promisify

* fix: use single symbol for util.promisify.custom

* style: linting
2023-10-30 23:54:48 -07:00
Jarred Sumner
b29d68bbaf Fix memory leak in require (#6790)
* Fix memory leak in require() and add test

* Mark fixtures as generated code

* Add optimization for large files

* Fix small memory leak

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-30 23:54:02 -07:00
Kerem Kat
715be35764 Fix 6281 (#6809)
* throw an error when `Script` is called without new

fix https://github.com/oven-sh/bun/issues/6281

* fix typo in `File` without constructor error

fix https://github.com/oven-sh/bun/issues/6281
2023-10-30 23:05:32 -07:00
Dylan Conway
e259056bd8 peer dependency and semver prerelease bug fixes (#6814)
* `order` and `satisfy` prerelease numbers

* remove sorter

* use existing package for peer dep if possible

* fix test, remove loop

* count workspace versions, compare each part of prerelease

* other peer dependencies

* use existing packages if possible

* don't install peer more than once

* fix update tests
2023-10-30 23:04:47 -07:00
Kerem Kat
68146d0544 Fix minify-whitespace case undefined (#6808)
Print a space before `undefined` in `printUndefined`.

fix https://github.com/oven-sh/bun/issues/6750
2023-10-30 16:15:45 -07:00
Dylan Conway
7e09c7ca1e format 2023-10-30 16:09:34 -07:00
Ciro Spaciari
4d780837ac fix(fetch) (#6672)
* fix fetch

* oops

* revert

* fix checkServerIdentity

* check dns len

* use same checks on wsclient and fetch, fix tests

* more tests and more fixes

* fix node-http flask test

* orelse

* fix requestCert

* more fixes, but no data receiving

* fix pause on connect behavior on TLS

* WS Client + rejectUnauthorized progress

* move test to the right place

* more test

* oops

* oops 2

* fmt

* cleanup

* WIP: handle handshake properly on uWS

* handle rejectUnauthorized in uWS

* fmt

* duplicated test

* fix leak

* add rejectUnauthorized option in WS types

* fix merge

* fix merge2
2023-10-30 12:56:31 -07:00
IAS
cbc5ca770b fix: Macro segmentation faults (#6756)
* Fix for seg faults when using macros

* Update src/js_ast.zig to reflect review suggestions

Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>

* add test for checking non-zero exitcodes under macros. regression, issue 3830

---------

Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2023-10-30 12:36:38 -07:00
Jarred Sumner
2972cfadfb More resilient test for fetch body memory leak (#6794)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-30 12:35:55 -07:00
Jarred Sumner
6be17538e7 Fix flaky test 2023-10-30 02:01:29 -07:00
Liz
e5ccce1e89 feat(console): add printer for mapiterator (#6778)
* feat(console): add printer for mapiterator

MapIterator was not supported in printing, libraries like discordjs make big use of maps and
so i think supporting them would be a good idea.

* fix: snake case var

* fix: add tests for log and add setiterator printer
2023-10-30 01:29:25 -07:00
Rohit Kaushal
08fdbb3c7d [docs] fix ws/pubsub; closed ws don't publish to topic (#6739) 2023-10-30 00:07:50 -07:00
Hanaasagi
8880bf1026 fix(node:buffer): fix Buffer.readUintBE (#6770)
Close: #6759
2023-10-30 00:07:27 -07:00
Ross Martin
d7cb7884c3 Update contributing.md (#6787)
Adding ruby as a dev dependency to Arch list
2023-10-29 18:07:00 -07:00
Samuel Batista
bb19677ae4 docs(contributing) add ruby dependency (#6788)
Don't know why ruby is required to build bun, but without it `bun setup` fails.
2023-10-29 18:06:40 -07:00
Smoothieewastaken
a7a74b73f2 docs: spelling of necessarily (#6772) 2023-10-29 06:34:54 -07:00
perpetualsquid
e4394ef5cc Fixed broken link in deflatesync section (#6774)
* Fixed broken link in deflatesync section

* fixed link

* fixed link
2023-10-29 06:34:35 -07:00
Omar
e4e811d0a7 fix: remove extra parenthesis (#6775) 2023-10-29 06:34:19 -07:00
Jarred Sumner
6851a57ebd Update nodejs-apis.md 2023-10-28 20:17:20 -07:00
dave caruso
3b25c8637b dx: Fix setup script and contributing docs (#6752)
* Updated Dependencies Script

* demo

* fix submodule hell!!!

* lol

* attmept 2

* install nasm in ci

* setup sh 1

* yeah

* better zlib building

* codegen stuff

* attempt 2 at bun codegen ci

* o

* deps improvements

* generaet part of compile-cpp-only.ps1

* restore these

* good enough for Unix

* remove libuv submodule lol

* pass over docs
2023-10-28 04:46:56 -07:00
Jarred Sumner
d1244c8b1f Remove unnecessary DOMAttribute annotation
Preparation for https://github.com/WebKit/WebKit/pull/19606
2023-10-27 22:00:29 -07:00
Rohan Mayya
d1a7bb4a69 add cache and main (#6679) 2023-10-27 11:26:59 -07:00
Darshan Sen
a0bd8365da docs: fix setup.sh path in contributing.md (#6745)
It was added in https://github.com/oven-sh/bun/pull/4410. The `src`
directory is not supposed to be a part of the path.

Signed-off-by: Darshan Sen <raisinten@gmail.com>
2023-10-27 04:08:37 -07:00
Jarred Sumner
16a0801058 Format cmakelists + increase stack size 2023-10-27 04:01:06 -07:00
Jarred Sumner
c4156376d9 Fix debug log 2023-10-27 04:01:05 -07:00
dave caruso
4ff54139b7 fix(ci): typo 2023-10-27 03:20:44 -07:00
Jarred Sumner
8d2e0725e7 Fix fallback to copyfile 2023-10-27 02:36:10 -07:00
Jarred Sumner
700f932ddf Fix warning 2023-10-27 02:20:51 -07:00
Jarred Sumner
7485c7c7cb feat: Windows + CMake Build System (#4410)
* Prepare for windows event loop

* More progress

* Update libuv.zig

* wip

* Make compiling each dependency a shell script

* Bump mimalloc

* Add the build scripts

* Update settings.json

* Fix a bunch of compiler warnings

* Remove more warnings

* more warnings

* cmake works

* Update JSSQLStatement.h

* put it in the zig file

* Fix usockets warnings

* Fixup

* Fix one of the compiler errors

* chunk

* draw the rest of the owl

* theres more

* Rename Process -> BunProcess

Works around a Windows issue

* Add musl polyfill for memmem on Windows

* More

* 12 mb

* Fix getenvZ

* fix variosu issues

* Add fast-ish path for bun install on Windows

* Update windows.zig

* Update windows.zig

* Fix build issue

* it works

* hmmm

* Rename file

* Fixups

* Update wtf-bindings.cpp

* Update src/bun.js/bindings/headers-handwritten.h

Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>

* further!

* more

* Update .gitignore

* hm

* quite a lot of fixes

* Update CMakeLists.txt

* zig fmt

* Many more things are starting to work.

* reb

* regenaret

* Update JSSink.h

* fixup

* fetch works

* Bun.serve() and much of the event loop works now

* Make require() work

* bun install progress

* more things work

* use less std.os

* Fixes

* small fixes

* Bump

* Bummp

* Undo that change

* We have to bump the version of Debian because libarchive has a higher minimum requirement

* ok

* some clenaup

* windows

* Update bun.zig

* fixup

* avoid duplicate symbols

* avoid undefined symbols

* bump

* Remove issue template for install

It's not used, and use the bug issue instead.

* Add types for cp and cpSync

* Add types for watchFile and unwatchFile

* Add bun-types to 'bun fmt' script

* Update nodejs compat docs cp/cpSync/watchFile/unwatchFile (#4525)

* feat(fetch) rejectUnauthorized and checkServerIdentity (#4514)

* enable root certs on fetch

* rebase

* fix lookup

* some fixes and improvements

* fmt

* more fixes

* more fixes

* check detached onHandshake

* fix promise case

* fix cert non-Native

* add fetch tls tests

* more one test

* churn

* Update feature_flags.zig

* Update response.zig

* Revert "avoid undefined symbols"

This reverts commit ca835b726f.

* Revert "avoid duplicate symbols"

This reverts commit 4ac6ca8700.

* Update feature_flags.zig

* Set permissions

* more

* Update mimalloc

* Fix sqlite test failures

* Fix some test failures

* Make sure we remove libusockets is removed

* hm

* [dave]: fix webcrypto crash

* bump

* Update index.ts

* windows zig compiles

* cmake on mac works

* progress

* yay

* bun run build

* fix

* ok

* oops

* asdfasfdafdsafda

* fghjkl

* git ignore

* wow

* Process -> BunProcess

* hmm

* blah

* finalize merge

* now it only has linker errors on mac

* sdfadsf

* g

* getting farther

* sxdcvbnmk,

* adfhjskfjdhkas

* a

* fgh

* update build dot zig

* asdfg

* theoretical -DCANARY flag we can use

* asdf

* cool

* okay

* colorterm

* New build workflow

* Fix script

* Use sudo

* More sudo

* Tweak dependencies

* Another sudo attempt

* Tweak script

* 16.0 -> 16

* Tweak script

* Tweak script

* Tweak script

* Tweak script

* Tweak script

* bun install

* ssh into github actions

* add more to ssh

* Fix postinstal

* Skip llvm

* New dockerfile

* Build

* More changes to Dockerfile

* chaos chaos chaos

* okay

* a

* more cmake nonsense

* add unified sources code (does not work)

* stuff

* prepare for CI builds

* ok

* yay

* yeah

* make this more stable simply by trying again if it fails, 5 times, then lose. it fixes the stability issue i was running into L O L

* messing with ci

* x

* a

* clean dependencies before build

* oops

* this is not going to work but its closer

* not gonna work either

* a

* a

* did i do it

* a

* a

* work around weird fs+Bun.build issues

* properly pass debug flag correctly

* idk im sorry

* lose

* maybe

* run the tests please

* a

* fix zlib script

* a

* hi

* prevent stupid ci issue

* i totally didnt leave in a syntax error on cmakelists

* a

* lol

* relax

* 😭

* a

* SO SILLY

* 😡 one line mistake

* one character diff

* fix linking symbols missing

* work on dependency scripts

* does this work now?

* fix mac build

* a

* bump!

* woops

* add macos baseline build

* .

* fix sqlite and also enable $assert/$debug support in builtin functions

* okay

* oops

* zig upgrade lol

* Merge

* Fix spawn test issue

* Set a timeout

* yeah

* etc

* mi

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
Co-authored-by: Ashcon Partovi <ashcon@partovi.net>
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: dave caruso <me@paperdave.net>
2023-10-27 01:51:56 -07:00
Jarred Sumner
46a337cbc8 Fix running Bun.spawn on Vercel and GCP (#6724)
* Fix running `Bun.spawn` on Vercel and GCP

* Update subprocess.zig

* Deflake test

* Update spawn-streaming-stdout.test.ts

* Fix tests + cleanup

* Fix hang

* Handle edgecase

* Update subprocess.zig

* Update subprocess.zig

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-27 00:03:03 -07:00
Colin McDonnell
58d9a0d770 Add EdgeDB guide 2023-10-26 17:28:57 -07:00
Liz
8f42d8c2dd fix: emit close on stdin stream end (#6720)
* fix: emit close on stdin stream end

We where not emitting the `close` event when done reading stdin data.
It took me way too long to find this but i kept searching in zig/cpp code of the stream implementations...

Fixes: https://github.com/oven-sh/bun/issues/6713

* fix: don't emit close twice
2023-10-26 17:00:37 -07:00
Hanaasagi
b5fb980145 fix(requestIP): fix type cast from binary to text format for IPv4. (#6725)
* fix(requestIP): fix type cast from binary to text format for IPv4.
Close: #6668

* use ares_inet_ntop
2023-10-26 12:31:53 -03:00
Jarred Sumner
2b8aae05d1 Add test for custom thenables in AsyncLocalStorage and fix flaky test and make expect(fn).toThrow drain unhandled promise rejections (#6701)
* Copy Node.js test for async-local-storage thenables

* Fix flaky test

* Make expect(fn).toThrow() more reliable

* Fix setImmediate order

* Support restoring mocked modules with spyOn

* Fix vm test

* Fix more tests

* alright

* Upgrade WebKit

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-25 22:35:14 -07:00
Susheel Thapa
2327737b14 docs: fixed typo in guides, install and runtime folder (#6718) 2023-10-25 18:27:05 -07:00
Pierre CM
58ce044607 fix cli create from local template (#6670)
* fix #4766

* fix cli create command for local folders

* zig fmt

* rm comment
2023-10-25 16:54:36 -07:00
Jasper Kelder
85bde43c2f fix bun add drizzle to bun add drizzle-orm (#6703) 2023-10-25 12:55:16 -07:00
Colin McDonnell
4fb5ab0ca8 Update drizzle guide 2023-10-25 12:52:15 -07:00
Colin McDonnell
c275cecfd1 Updates to drizzle 2023-10-25 12:16:59 -07:00
Jarred Sumner
6a2768f247 Implement mock.module in bun:test (#6685)
* Implement Module Mocks

* Update javascript.zig

* Add test for spyOn + ESM namespace

* Bump WebKit

* Bump WebKit

* Drain microtasks at end of test executions

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-25 02:59:47 -07:00
Jarred Sumner
7bcf60324a Fix setTimeout(() => {}, 0) and align setImmediate behavior with Node.js (#6674)
* Fix setTimeout(() => {}, 0)

* Align `setImmediate` with Node.js

* Update event_loop.zig

* Update test

* use Bun.sleep

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-25 02:59:29 -07:00
dave caruso
c700a70872 fix(runtime): remove env variable limit (#6697)
* fix env limit

* test
2023-10-24 20:11:06 -07:00
Colin McDonnell
ce4e1894f6 Remove unnecessary line 2023-10-24 18:48:07 -07:00
Colin McDonnell
f60167c015 Add Drizzle guide (#6698)
* Add drizzle guide

* Add Drizzle guide

* Tweak
2023-10-24 18:28:39 -07:00
Dylan Conway
042a6cdbce Update worker_threads.test.ts 2023-10-24 17:07:48 -07:00
Jérôme Benoit
85a0d71c52 fix(worker_threads): off by one on threadId (#6671)
* fix(worker_threads): off by one on threadId

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: refine worker_threads threadId consistency test

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: improve worker_threads tests

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: fix worker_threads threadId consistency test

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: simplify worker_threads threadId consistency test

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: refine worker_threads threadId consistency test

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>

* refactor: cleanup import on worker_threads tests

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: switch worker_threads worker to TS

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: revert wrong refactoring

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: format

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: port worker_threads worker to ESM

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: cleanup worker_threads test

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>

* test: improve worker_threads coverage

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>

---------

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2023-10-24 17:05:22 -07:00
Dylan Conway
fa1bbec023 Update bun-install.test.ts 2023-10-24 13:18:51 -07:00
nxzq
1496681297 Update workspaces.md (#6673) 2023-10-23 23:16:42 -07:00
Liz
3906d17165 add new repo (#6676) 2023-10-23 23:16:13 -07:00
Yam Borodetsky
f297b95436 docs: fix react.md typos (#6656)
* docs: fix react.md typos

* docs: fix one more typo
2023-10-23 13:48:45 -07:00
Jarred Sumner
fafd9368f5 Backport uWS & usockets changes (#6649)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-10-22 13:44:08 -07:00
Ai Hoshino
1836ecd2ed fix(node:buffer): fix Buffer.write stuck (#6651) 2023-10-22 13:42:05 -07:00
Jarred Sumner
4cdaabd433 Dump as json 2023-10-21 16:27:11 -07:00
Jarred Sumner
4a74a46780 Add require builtins snippet 2023-10-21 16:18:18 -07:00
Dylan Conway
b62c010e95 fix bun link in workspace package (#6631)
* link workspace package

* add test

* more complete test
2023-10-20 22:38:46 -07:00
515 changed files with 23096 additions and 61563 deletions

View File

@@ -1,17 +1,15 @@
node_modules
**/node_modules
src/bun.js/WebKit/LayoutTests
zig-out
zig-build
**/*.o
**/*.a
examples
**/*.o
**/.next
.git
src/bun.js/WebKit
**/CMakeCache.txt
**/node_modules
.git
examples
node_modules
packages/**/bun
packages/**/bun-profile
src/bun.js/WebKit
src/bun.js/WebKit/LayoutTests
zig-build
zig-cache
zig-out

2
.gitattributes vendored
View File

@@ -27,6 +27,8 @@ src/bun.js/bindings/sqlite/sqlite3_local.h linguist-vendored
src/bun.js/bindings/simdutf.cpp linguist-vendored
src/bun.js/bindings/simdutf.h linguist-vendored
*-fixture* linguist-generated
src/js/out/WebCoreJSBuiltins.cpp linguist-generated
src/js/out/WebCoreJSBuiltins.h linguist-generated
src/js/out/WebCoreJSBuiltins.d.ts linguist-generated

View File

@@ -4,11 +4,6 @@ concurrency:
group: bun-linux-aarch64-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: bun-test'
on:
push:
branches:
@@ -38,10 +33,7 @@ jobs:
arch: aarch64
build_arch: arm64
runner: linux-arm64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-linux-arm64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-arm64-lto"
build_machine_arch: aarch64
steps:
- uses: actions/checkout@v3
with:
@@ -73,9 +65,7 @@ jobs:
BUILDARCH=${{matrix.build_arch}}
BUILD_MACHINE_ARCH=${{matrix.build_machine_arch}}
CPU_TARGET=${{matrix.cpu}}
WEBKIT_URL=${{matrix.webkit_url}}
GIT_SHA=${{github.sha}}
WEBKIT_BASENAME=${{matrix.webkit_basename}}
platforms: linux/${{matrix.build_arch}}
target: artifact
outputs: type=local,dest=${{runner.temp}}/release
@@ -111,14 +101,6 @@ jobs:
with:
name: bun-${{matrix.tag}}
path: ${{runner.temp}}/release/bun-${{matrix.tag}}.zip
- uses: actions/upload-artifact@v3
with:
name: bun-obj-${{matrix.tag}}
path: ${{runner.temp}}/release/bun-obj
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}-dependencies
path: ${{runner.temp}}/release/bun-dependencies
- name: Release
id: release
uses: ncipollo/release-action@v1

View File

@@ -4,11 +4,6 @@ concurrency:
group: bun-linux-build-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: bun-test'
on:
push:
branches:
@@ -49,16 +44,12 @@ jobs:
arch: x86_64
build_arch: amd64
runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
- cpu: nehalem
tag: linux-x64-baseline
arch: x86_64
build_arch: amd64
runner: big-ubuntu
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-linux-amd64-lto.tar.gz"
webkit_basename: "bun-webkit-linux-amd64-lto"
build_machine_arch: x86_64
steps:
@@ -92,9 +83,14 @@ jobs:
BUILDARCH=${{matrix.build_arch}}
BUILD_MACHINE_ARCH=${{matrix.build_machine_arch}}
CPU_TARGET=${{matrix.cpu}}
WEBKIT_URL=${{matrix.webkit_url}}
GIT_SHA=${{github.sha}}
WEBKIT_BASENAME=${{matrix.webkit_basename}}
SCCACHE_BUCKET=bun
SCCACHE_REGION=auto
SCCACHE_S3_USE_SSL=true
SCCACHE_ENDPOINT=${{ secrets.CACHE_S3_ENDPOINT }}
AWS_ACCESS_KEY_ID=${{ secrets.CACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }}
platforms: linux/${{matrix.build_arch}}
target: artifact
outputs: type=local,dest=${{runner.temp}}/release

View File

@@ -5,9 +5,8 @@ concurrency:
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: bun-test'
LLVM_VERSION: 16
BUN_DOWNLOAD_URL_BASE: https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest
on:
push:
@@ -32,79 +31,134 @@ on:
workflow_dispatch:
jobs:
macos-object-files:
name: macOS Object
macOS-zig:
name: macOS Zig Object
runs-on: med-ubuntu
if: github.repository_owner == 'oven-sh'
strategy:
matrix:
include:
# - cpu: nehalem
# arch: x86_64
# tag: bun-obj-darwin-x64-baseline
# - cpu: haswell
# arch: x86_64
# tag: bun-obj-darwin-x64
- cpu: native
arch: aarch64
tag: bun-obj-darwin-aarch64
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: docker/setup-buildx-action@v2
- uses: actions/checkout@v4
# - name: Checkout submodules
# run: git submodule update --init --recursive --depth=1 --progress --force
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true
- name: Run
run: |
rm -rf ${{runner.temp}}/release
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
- name: Compile Zig Object
uses: docker/build-push-action@v3
if: runner.arch == 'X64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
# This doesnt seem to work
# cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
build-args: |
BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }}
ARCH=${{ matrix.arch }}
BUILDARCH=amd64
BUILD_MACHINE_ARCH=x86_64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/amd64
TRIPLET=${{ matrix.arch }}-macos-none
GIT_SHA=${{ github.sha }}
platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- name: Build and push
uses: docker/build-push-action@v3
if: runner.arch == 'ARM64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
build-args: |
ARCH=${{ matrix.arch }}
BUILDARCH=arm64
BUILD_MACHINE_ARCH=aarch64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/arm64
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- uses: actions/upload-artifact@v3
- name: Upload Zig Object
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}
path: ${{runner.temp}}/release/bun.o
path: ${{runner.temp}}/release/bun-zig.o
macOS-dependencies:
name: macOS Dependencies
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
timeout-minutes: 15
strategy:
matrix:
include:
- cpu: native
arch: aarch64
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
artifact: bun-obj-darwin-aarch64
runner: macos-arm64
steps:
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
run: |
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
- name: Hash submodule versions
run: |
print_data() {
git submodule | grep -v WebKit
llvm-config --version
rustc --version
cat $(echo scripts/build*.sh scripts/all-dependencies.sh | tr " " "\n" | sort)
}
echo "sha=$(print_data | sha1sum | cut -c 1-10)" >> $GITHUB_OUTPUT
id: submodule-versions
- name: Cache submodule dependencies
id: cache-deps-restore
uses: actions/cache/restore@v3
with:
path: ${{runner.temp}}/bun-deps
key: bun-deps-${{ matrix.tag }}-${{ steps.submodule-versions.outputs.sha }}
- name: Compile submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
env:
CPU_TARGET: ${{ matrix.cpu }}
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
mkdir -p $BUN_DEPS_OUT_DIR
bash ./scripts/clean-dependencies.sh
bash ./scripts/all-dependencies.sh
- name: Cache submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
id: cache-deps-save
uses: actions/cache/save@v3
with:
path: ${{runner.temp}}/bun-deps
key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }}
- name: Upload submodule dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
macOS-cpp:
name: macOS C++
runs-on: ${{ matrix.runner }}
@@ -113,257 +167,141 @@ jobs:
strategy:
matrix:
include:
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: native
arch: aarch64
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-2/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
dependencies: true
compile_obj: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
# TODO: replace with sccache
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}
- name: Download WebKit
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
- name: Compile dependencies
if: matrix.dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $BUN_DEPS_OUT_DIR
make vendor-without-check
- name: Compile C++
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
SOURCE_DIR: ${{ github.workspace }}
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $OBJ_DIR $BUN_DEPS_OUT_DIR
make clean-bindings
make -j $(sysctl -n hw.ncpu) release-bindings
mkdir -p $OBJ_DIR
cd $OBJ_DIR
cmake -S $SOURCE_DIR -B $OBJ_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_CPP_ONLY=1 \
-DNO_CONFIGURE_DEPENDS=1
bash compile-cpp-only.sh -v
- name: Upload C++
if: matrix.compile_obj
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Upload Dependencies
if: matrix.dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
macOS:
path: ${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a
macOS-link:
name: macOS Link
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
needs: [macOS-cpp, macos-object-files]
timeout-minutes: 90
needs: [macOS-zig, macOS-cpp, macOS-dependencies]
timeout-minutes: 60
permissions: write-all
strategy:
matrix:
include:
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# obj: bun-obj-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# obj: bun-obj-darwin-x64
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: native
arch: aarch64
tag: bun-darwin-aarch64
obj: bun-obj-darwin-aarch64
package: bun-darwin-aarch64
artifact: bun-obj-darwin-aarch64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-macos-arm64-lto.tar.gz"
runner: macos-arm64
steps:
- uses: actions/checkout@v3
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install ccache llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv openssl@1.1 ninja --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
- name: Download WebKit
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-${{matrix.arch}}.zip"
unzip bun-darwin-${{matrix.arch}}.zip
mkdir -p ${{ runner.temp }}/.bun/bin
mv bun-darwin-${{matrix.arch}}/bun ${{ runner.temp }}/.bun/bin/bun
chmod +x ${{ runner.temp }}/.bun/bin/bun
echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH
- name: Download C++
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Download Dependencies
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{ runner.temp }}/bun-deps
- name: Download Object
- name: Download Zig Object
uses: actions/download-artifact@v3
with:
name: ${{ matrix.obj }}
path: ${{ runner.temp }}/release
- name: Downloaded submodule dependencies
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
- name: Link
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf packages/${{ matrix.package }}
mkdir -p packages/${{ matrix.package }}
mv ${{ runner.temp }}/release/* packages/${{ matrix.package }}/
make bun-link-lld-release copy-to-bun-release-dir-bin
SRC_DIR=$PWD
mkdir ${{runner.temp}}/link-build
cd ${{runner.temp}}/link-build
cmake $SRC_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_LINK_ONLY=1 \
-DBUN_ZIG_OBJ="${{ runner.temp }}/release/bun-zig.o" \
-DBUN_CPP_ARCHIVE="${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a" \
-DBUN_DEPS_OUT_DIR="${{runner.temp}}/bun-deps" \
-DNO_CONFIGURE_DEPENDS=1
ninja -v
- name: Zip
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
cd ${{runner.temp}}/release
cd ${{runner.temp}}/link-build
chmod +x bun-profile bun
mkdir ${{matrix.tag}}-profile
mkdir ${{matrix.tag}}
/usr/bin/strip -S bun
mkdir -p ${{matrix.tag}}-profile/ ${{matrix.tag}}/
mv bun-profile ${{matrix.tag}}-profile/bun-profile
mv bun ${{matrix.tag}}/bun
@@ -373,11 +311,11 @@ jobs:
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}-profile
path: ${{runner.temp}}/release/${{matrix.tag}}-profile.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release/${{matrix.tag}}.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}.zip
- name: Release
id: release
uses: ncipollo/release-action@v1
@@ -394,7 +332,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
artifacts: "${{runner.temp}}/link-build/${{matrix.tag}}.zip,${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
@@ -417,7 +355,7 @@ jobs:
macOS-test:
name: Tests ${{matrix.tag}}
runs-on: ${{ matrix.runner }}
needs: [macOS]
needs: [macOS-link]
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
permissions:
pull-requests: write

View File

@@ -5,9 +5,8 @@ concurrency:
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: bun-test'
LLVM_VERSION: 16
BUN_DOWNLOAD_URL_BASE: https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest
on:
push:
@@ -49,62 +48,129 @@ jobs:
# arch: aarch64
# tag: bun-obj-darwin-aarch64
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: docker/setup-buildx-action@v2
- uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true
- name: Run
run: |
rm -rf ${{runner.temp}}/release
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
- name: Compile Zig Object
uses: docker/build-push-action@v3
if: runner.arch == 'X64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
# This doesnt seem to work
# cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# This was used before, but also does not really work
cache-from: type=local,src=/tmp/.buildx-cache-${{matrix.tag}}
cache-to: type=local,dest=/tmp/.buildx-cache-${{matrix.tag}}
build-args: |
BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }}
ARCH=${{ matrix.arch }}
BUILDARCH=amd64
BUILD_MACHINE_ARCH=x86_64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/amd64
TRIPLET=${{ matrix.arch }}-macos-none
GIT_SHA=${{ github.sha }}
SCCACHE_BUCKET=bun
SCCACHE_REGION=auto
SCCACHE_S3_USE_SSL=true
SCCACHE_ENDPOINT=${{ secrets.CACHE_S3_ENDPOINT }}
AWS_ACCESS_KEY_ID=${{ secrets.CACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }}
platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- name: Build and push
uses: docker/build-push-action@v3
if: runner.arch == 'ARM64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
build-args: |
ARCH=${{ matrix.arch }}
BUILDARCH=arm64
BUILD_MACHINE_ARCH=aarch64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/arm64
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- uses: actions/upload-artifact@v3
- name: Upload Zig Object
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}
path: ${{runner.temp}}/release/bun.o
path: ${{runner.temp}}/release/bun-zig.o
macOS-dependencies:
name: macOS Dependencies
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
timeout-minutes: 15
strategy:
matrix:
include:
- cpu: nehalem
arch: x86_64
tag: bun-darwin-x64-baseline
obj: bun-obj-darwin-x64-baseline
runner: macos-12
artifact: bun-obj-darwin-x64-baseline
steps:
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
run: |
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
- name: Hash submodule versions
run: |
print_data() {
git submodule | grep -v WebKit
llvm-config --version
rustc --version
cat $(echo scripts/build*.sh scripts/all-dependencies.sh | tr " " "\n" | sort)
}
echo "sha=$(print_data | sha1sum | cut -c 1-10)" >> $GITHUB_OUTPUT
id: submodule-versions
- name: Cache submodule dependencies
id: cache-deps-restore
uses: actions/cache/restore@v3
with:
path: ${{runner.temp}}/bun-deps
key: bun-deps-${{ matrix.tag }}-${{ steps.submodule-versions.outputs.sha }}
- name: Compile submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
env:
CPU_TARGET: ${{ matrix.cpu }}
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
mkdir -p $BUN_DEPS_OUT_DIR
bash ./scripts/clean-dependencies.sh
bash ./scripts/all-dependencies.sh
- name: Cache submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
id: cache-deps-save
uses: actions/cache/save@v3
with:
path: ${{runner.temp}}/bun-deps
key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }}
- name: Upload submodule dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
macOS-cpp:
name: macOS C++
runs-on: ${{ matrix.runner }}
@@ -119,136 +185,66 @@ 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-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: nehalem
arch: x86_64
tag: bun-darwin-x64-baseline
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-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
# - cpu: native
# arch: aarch64
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
- name: ccache (dependencies)
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip"
unzip bun-darwin-x64.zip
mkdir -p ${{ runner.temp }}/.bun/bin
mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun
chmod +x ${{ runner.temp }}/.bun/bin/bun
echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH
# TODO: replace with sccache
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
if: matrix.dependencies
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-dependencies
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-dependencies
- name: ccache (c++)
uses: hendrikmuhs/ccache-action@v1.2
if: matrix.compile_obj
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-obj
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-obj
- name: Download WebKit
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
- name: Compile dependencies
if: matrix.dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $OBJ_DIR $BUN_DEPS_OUT_DIR
make vendor-without-check
key: ${{ runner.os }}-ccache-${{ matrix.tag }}
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}
- name: Compile C++
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
SOURCE_DIR: ${{ github.workspace }}
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $OBJ_DIR $BUN_DEPS_OUT_DIR
make -j $(sysctl -n hw.ncpu) release-bindings
mkdir -p $OBJ_DIR
cd $OBJ_DIR
cmake -S $SOURCE_DIR -B $OBJ_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_CPP_ONLY=1 \
-DNO_CONFIGURE_DEPENDS=1
bash compile-cpp-only.sh -v
- name: Upload C++
if: matrix.compile_obj
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Upload Dependencies
if: matrix.dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
path: ${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a
macOS:
name: macOS Link
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
needs: [macOS-cpp, macos-object-files]
needs: [macOS-cpp, macos-object-files, macOS-dependencies]
timeout-minutes: 90
permissions: write-all
strategy:
@@ -261,113 +257,70 @@ 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: haswell
# arch: x86_64
# tag: bun-darwin-x64
# obj: bun-obj-darwin-x64
# package: bun-darwin-x64
# runner: macos-12
# artifact: bun-obj-darwin-x64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-macos-amd64-lto.tar.gz"
# runner: macos-arm64
steps:
- uses: actions/checkout@v3
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install ccache llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv openssl@1.1 ninja --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
- name: ccache (link)
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
- name: Download WebKit
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip"
unzip bun-darwin-x64.zip
mkdir -p ${{ runner.temp }}/.bun/bin
mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun
chmod +x ${{ runner.temp }}/.bun/bin/bun
echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH
- name: Download C++
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Download Dependencies
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{ runner.temp }}/bun-deps
- name: Download Object
- name: Download Zig Object
uses: actions/download-artifact@v3
with:
name: ${{ matrix.obj }}
path: ${{ runner.temp }}/release
- name: Downloaded submodule dependencies
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
- name: Link
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf packages/${{ matrix.package }}
mkdir -p packages/${{ matrix.package }}
mv ${{ runner.temp }}/release/* packages/${{ matrix.package }}/
make bun-link-lld-release copy-to-bun-release-dir-bin
SRC_DIR=$PWD
mkdir ${{runner.temp}}/link-build
cd ${{runner.temp}}/link-build
cmake $SRC_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_LINK_ONLY=1 \
-DBUN_ZIG_OBJ="${{ runner.temp }}/release/bun-zig.o" \
-DBUN_CPP_ARCHIVE="${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a" \
-DBUN_DEPS_OUT_DIR="${{runner.temp}}/bun-deps" \
-DNO_CONFIGURE_DEPENDS=1
ninja -v
- name: Zip
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
cd ${{runner.temp}}/release
cd ${{runner.temp}}/link-build
chmod +x bun-profile bun
mkdir ${{matrix.tag}}-profile
mkdir ${{matrix.tag}}
/usr/bin/strip -S bun
mkdir -p ${{matrix.tag}}-profile/ ${{matrix.tag}}/
mv bun-profile ${{matrix.tag}}-profile/bun-profile
mv bun ${{matrix.tag}}/bun
@@ -377,11 +330,11 @@ jobs:
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}-profile
path: ${{runner.temp}}/release/${{matrix.tag}}-profile.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release/${{matrix.tag}}.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}.zip
- name: Release
id: release
uses: ncipollo/release-action@v1
@@ -398,7 +351,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
artifacts: "${{runner.temp}}/link-build/${{matrix.tag}}.zip,${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:
@@ -419,7 +372,7 @@ jobs:
[Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
macOS-test:
name: Tests ${{matrix.tag}}
name: macOS Test
runs-on: ${{ matrix.runner }}
needs: [macOS]
if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'

View File

@@ -5,9 +5,8 @@ concurrency:
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
TEST_TAG: bun-test'
LLVM_VERSION: 16
BUN_DOWNLOAD_URL_BASE: https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest
on:
push:
@@ -32,8 +31,8 @@ on:
workflow_dispatch:
jobs:
macos-object-files:
name: macOS Object
macOS-zig:
name: macOS Zig Object
runs-on: med-ubuntu
if: github.repository_owner == 'oven-sh'
strategy:
@@ -45,66 +44,131 @@ jobs:
- cpu: haswell
arch: x86_64
tag: bun-obj-darwin-x64
# - cpu: native
# arch: aarch64
# tag: bun-obj-darwin-aarch64
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- uses: docker/setup-buildx-action@v2
- uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true
- name: Run
run: |
rm -rf ${{runner.temp}}/release
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
- name: Compile Zig Object
uses: docker/build-push-action@v3
if: runner.arch == 'X64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
# This doesnt seem to work
# cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# This was used before, but also does not really work
cache-from: type=local,src=/tmp/.buildx-cache-${{matrix.tag}}
cache-to: type=local,dest=/tmp/.buildx-cache-${{matrix.tag}}
build-args: |
BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }}
ARCH=${{ matrix.arch }}
BUILDARCH=amd64
BUILD_MACHINE_ARCH=x86_64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/amd64
TRIPLET=${{ matrix.arch }}-macos-none
GIT_SHA=${{ github.sha }}
SCCACHE_BUCKET=bun
SCCACHE_REGION=auto
SCCACHE_S3_USE_SSL=true
SCCACHE_ENDPOINT=${{ secrets.CACHE_S3_ENDPOINT }}
AWS_ACCESS_KEY_ID=${{ secrets.CACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }}
platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- name: Build and push
uses: docker/build-push-action@v3
if: runner.arch == 'ARM64'
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=min
build-args: |
ARCH=${{ matrix.arch }}
BUILDARCH=arm64
BUILD_MACHINE_ARCH=aarch64
CPU_TARGET=${{ matrix.cpu }}
TRIPLET=${{matrix.arch}}-macos-none
GIT_SHA=${{github.sha}}
platforms: linux/arm64
target: build_release_obj
outputs: type=local,dest=${{runner.temp}}/release
- uses: actions/upload-artifact@v3
- name: Upload Zig Object
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}
path: ${{runner.temp}}/release/bun.o
path: ${{runner.temp}}/release/bun-zig.o
macOS-dependencies:
name: macOS Dependencies
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
timeout-minutes: 15
strategy:
matrix:
include:
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
obj: bun-obj-darwin-x64
runner: macos-12
artifact: bun-obj-darwin-x64
steps:
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
run: |
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
- name: Hash submodule versions
run: |
print_data() {
git submodule | grep -v WebKit
llvm-config --version
rustc --version
cat $(echo scripts/build*.sh scripts/all-dependencies.sh | tr " " "\n" | sort)
}
echo "sha=$(print_data | sha1sum | cut -c 1-10)" >> $GITHUB_OUTPUT
id: submodule-versions
- name: Cache submodule dependencies
id: cache-deps-restore
uses: actions/cache/restore@v3
with:
path: ${{runner.temp}}/bun-deps
key: bun-deps-${{ matrix.tag }}-${{ steps.submodule-versions.outputs.sha }}
- name: Compile submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
env:
CPU_TARGET: ${{ matrix.cpu }}
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
mkdir -p $BUN_DEPS_OUT_DIR
bash ./scripts/clean-dependencies.sh
bash ./scripts/all-dependencies.sh
- name: Cache submodule dependencies
if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
id: cache-deps-save
uses: actions/cache/save@v3
with:
path: ${{runner.temp}}/bun-deps
key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }}
- name: Upload submodule dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
macOS-cpp:
name: macOS C++
runs-on: ${{ matrix.runner }}
@@ -113,157 +177,77 @@ jobs:
strategy:
matrix:
include:
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: true
# compile_obj: false
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
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-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: true
compile_obj: false
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# dependencies: false
# compile_obj: true
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
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-2/bun-webkit-macos-amd64-lto.tar.gz"
dependencies: false
compile_obj: true
# - cpu: native
# arch: aarch64
# 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-2/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
# dependencies: true
# compile_obj: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
- name: Download WebKit
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
- name: ccache (dependencies)
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip"
unzip bun-darwin-x64.zip
mkdir -p ${{ runner.temp }}/.bun/bin
mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun
chmod +x ${{ runner.temp }}/.bun/bin/bun
echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH
# TODO: replace with sccache
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
if: matrix.dependencies
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-dependencies
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-dependencies
- name: ccache (c++)
uses: hendrikmuhs/ccache-action@v1.2
if: matrix.compile_obj
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-obj
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-obj
- name: Compile dependencies
if: matrix.dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $OBJ_DIR $BUN_DEPS_OUT_DIR
make vendor-without-check
key: ${{ runner.os }}-ccache-${{ matrix.tag }}
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}
- name: Compile C++
if: matrix.compile_obj
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
SOURCE_DIR: ${{ github.workspace }}
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
mkdir -p $OBJ_DIR $BUN_DEPS_OUT_DIR
make -j $(sysctl -n hw.ncpu) release-bindings
mkdir -p $OBJ_DIR
cd $OBJ_DIR
cmake -S $SOURCE_DIR -B $OBJ_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_CPP_ONLY=1 \
-DNO_CONFIGURE_DEPENDS=1
bash compile-cpp-only.sh -v
- name: Upload C++
if: matrix.compile_obj
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Upload Dependencies
if: matrix.dependencies
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
path: ${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a
macOS:
name: macOS Link
runs-on: ${{ matrix.runner }}
if: github.repository_owner == 'oven-sh'
needs: [macOS-cpp, macos-object-files]
needs: [macOS-cpp, macOS-zig, macOS-dependencies]
timeout-minutes: 90
permissions: write-all
strategy:
matrix:
include:
# - cpu: nehalem
# arch: x86_64
# tag: bun-darwin-x64-baseline
# obj: bun-obj-darwin-x64-baseline
# 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-2/bun-webkit-macos-amd64-lto.tar.gz"
- cpu: haswell
arch: x86_64
tag: bun-darwin-x64
@@ -271,105 +255,71 @@ 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-2/bun-webkit-macos-amd64-lto.tar.gz"
# - cpu: native
# arch: aarch64
# tag: bun-darwin-aarch64
# obj: bun-obj-darwin-aarch64
# package: bun-darwin-aarch64
# artifact: bun-obj-darwin-aarch64
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-2/bun-webkit-macos-arm64-lto.tar.gz"
# runner: macos-arm64
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/2023-oct3-4/bun-webkit-macos-amd64-lto.tar.gz"
steps:
- uses: actions/checkout@v3
- name: Checkout submodules
run: git submodule update --init --recursive --depth=1 --progress -j $(sysctl -n hw.ncpu) --force
- name: Install dependencies
run: git submodule update --init --recursive --depth=1 --progress --force
- name: Install system dependencies
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
run: |
brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force
brew install ccache llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv openssl@1.1 ninja --force
echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@16
- name: Download WebKit
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf $JSC_BASE_DIR
mkdir -p $JSC_BASE_DIR
curl -L ${{ matrix.webkit_url }} | tar -xz -C $JSC_BASE_DIR --strip-components=1
echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
brew link --overwrite llvm@$LLVM_VERSION
curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip"
unzip bun-darwin-x64.zip
mkdir -p ${{ runner.temp }}/.bun/bin
mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun
chmod +x ${{ runner.temp }}/.bun/bin/bun
echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH
- name: Download C++
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-cpp
path: ${{ runner.temp }}/bun-cpp-obj
- name: Download Dependencies
uses: actions/download-artifact@v3
with:
name: ${{ matrix.tag }}-deps
path: ${{ runner.temp }}/bun-deps
- name: Download Object
- name: Download Zig Object
uses: actions/download-artifact@v3
with:
name: ${{ matrix.obj }}
path: ${{ runner.temp }}/release
- name: ccache (link)
uses: hendrikmuhs/ccache-action@v1.2
- name: Downloaded submodule dependencies
uses: actions/download-artifact@v3
with:
key: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}-link
name: ${{ matrix.tag }}-deps
path: ${{runner.temp}}/bun-deps
- name: Link
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
rm -rf packages/${{ matrix.package }}
mkdir -p packages/${{ matrix.package }}
mv ${{ runner.temp }}/release/* packages/${{ matrix.package }}/
make bun-link-lld-release copy-to-bun-release-dir-bin
SRC_DIR=$PWD
mkdir ${{runner.temp}}/link-build
cd ${{runner.temp}}/link-build
cmake $SRC_DIR \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_LINK_ONLY=1 \
-DBUN_ZIG_OBJ="${{ runner.temp }}/release/bun-zig.o" \
-DBUN_CPP_ARCHIVE="${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a" \
-DBUN_DEPS_OUT_DIR="${{runner.temp}}/bun-deps" \
-DNO_CONFIGURE_DEPENDS=1
ninja -v
- name: Zip
env:
CPU_TARGET: ${{ matrix.cpu }}
JSC_BASE_DIR: ${{ runner.temp }}/bun-webkit
JSC_LIB: ${{ runner.temp }}/bun-webkit/lib
BUN_DEPLOY_DIR: ${{ runner.temp }}/release/bun
OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
BUN_RELEASE_DIR: ${{ runner.temp }}/release
WEBKIT_RELEASE_DIR: ${{ runner.temp }}/bun-webkit
WEBKIT_RELEASE_DIR_LTO: ${{ runner.temp }}/bun-webkit
run: |
cd ${{runner.temp}}/release
cd ${{runner.temp}}/link-build
chmod +x bun-profile bun
mkdir ${{matrix.tag}}-profile
mkdir ${{matrix.tag}}
/usr/bin/strip -S bun
mkdir -p ${{matrix.tag}}-profile/ ${{matrix.tag}}/
mv bun-profile ${{matrix.tag}}-profile/bun-profile
mv bun ${{matrix.tag}}/bun
@@ -379,11 +329,11 @@ jobs:
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}-profile
path: ${{runner.temp}}/release/${{matrix.tag}}-profile.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip
- uses: actions/upload-artifact@v3
with:
name: ${{matrix.tag}}
path: ${{runner.temp}}/release/${{matrix.tag}}.zip
path: ${{runner.temp}}/link-build/${{matrix.tag}}.zip
- name: Release
id: release
uses: ncipollo/release-action@v1
@@ -400,7 +350,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
name: "Canary (${{github.sha}})"
tag: "canary"
artifacts: "${{runner.temp}}/release/${{matrix.tag}}.zip,${{runner.temp}}/release/${{matrix.tag}}-profile.zip"
artifacts: "${{runner.temp}}/link-build/${{matrix.tag}}.zip,${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip"
- uses: sarisia/actions-status-discord@v1
if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
with:

View File

@@ -152,7 +152,7 @@ jobs:
matrix:
include:
- variant: debian
suffix: ''
suffix: ""
- variant: debian
suffix: -debian
- variant: slim

159
.github/workflows/bun-windows-x64.yml vendored Normal file
View File

@@ -0,0 +1,159 @@
# TODO(@paperdave)
# this workflow is a work in progress
name: bun-windows-x64
concurrency:
group: bun-windows-x64-${{ github.ref }}
cancel-in-progress: true
on:
# push:
# branches: [main]
# paths:
# - "src/**/*"
# - "test/**/*"
# - "packages/bun-usockets/src/**/*"
# - "build.zig"
# - "Makefile"
# - "Dockerfile"
# pull_request:
# branches: [main]
# paths:
# - "src/**/*"
# - "test/**/*"
# - "packages/bun-usockets/src/**/*"
# - "build.zig"
# - "Makefile"
# - "Dockerfile"
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
# windows-zig:
# name: Windows Zig Object
# runs-on: med-ubuntu
# if: github.repository_owner == 'oven-sh'
# strategy:
# matrix:
# include:
# - cpu: native
# arch: x86_64
# tag: bun-windows-x64
# steps:
# - uses: actions/checkout@v4
# - name: Setup Docker Buildx
# uses: docker/setup-buildx-action@v2
# id: buildx
# with:
# install: true
# - name: Login to GitHub Container Registry
# uses: docker/login-action@v2
# with:
# registry: ghcr.io
# username: ${{ github.actor }}
# password: ${{ secrets.GITHUB_TOKEN }}
# - name: Compile Zig Object
# uses: docker/build-push-action@v3
# if: runner.arch == 'X64'
# with:
# context: .
# push: false
# # This doesnt seem to work
# # cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# # cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
# build-args: |
# BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
# BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }}
# ARCH=${{ matrix.arch }}
# CPU_TARGET=${{ matrix.cpu }}
# TRIPLET=${{ matrix.arch }}-windows-msvc
# GIT_SHA=${{ github.sha }}
# platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
# target: build_release_obj
# outputs: type=local,dest=${{runner.temp}}/release
# - name: Upload Zig Object
# uses: actions/upload-artifact@v3
# with:
# name: ${{ matrix.tag }}-zig
# path: ${{runner.temp}}/release/bun-zig.o
# windows-dependencies:
# strategy:
# matrix:
# include:
# - runner: windows-latest
# arch: amd64
# tag: bun-windows-x64
# runs-on: windows-latest
# timeout-minutes: 90
# steps:
# - uses: actions/checkout@v4
# - uses: ilammy/msvc-dev-cmd@7315a94840631165970262a99c72cfb48a65d25d
# with:
# arch: ${{ matrix.arch }}
# - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e
# with:
# version: 16.0.6
# - run: choco install -y ninja
# - name: Build Dependencies
# run: |
# git submodule update --init --recursive --progress --depth=1 --checkout
# Invoke-WebRequest -Uri "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip" -OutFile nasm.zip
# Expand-Archive nasm.zip (mkdir -Force "nasm")
# $Nasm = (Get-ChildItem "nasm")
# $env:Path += ";${Nasm}"
# $env:BUN_DEPS_OUT_DIR = (mkdir -Force "./bun-deps")
# ./scripts/all-dependencies.ps1
# - uses: actions/upload-artifact@v3
# with:
# name: bun-deps/
# path: bun-windows-x64-deps
windows-codegen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
curl -fsSL ${{ secrets.BUN_DOWNLOAD_URL_BASE }}/bun-linux-x64.zip > bun.zip
unzip bun.zip
export PATH="$PWD/bun-linux-x64:$PATH"
./scripts/cross-compile-codegen.sh win32 x64
- uses: actions/upload-artifact@v3
with:
name: bun-windows-x64-codegen
path: build-codegen-win32-x64/
windows-dependencies:
strategy:
matrix:
include:
- runner: windows-latest
arch: amd64
tag: bun-windows-x64
runs-on: windows-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@7315a94840631165970262a99c72cfb48a65d25d
with:
arch: ${{ matrix.arch }}
- uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e
with:
version: 16.0.6
- run: choco install -y ninja
- uses: actions/download-artifact@v2
with:
name: bun-windows-x64-codegen
path: build
- name: Build Dependencies
run: |
git submodule update --init --recursive --progress --depth=1 --checkout
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DNO_CODEGEN=1 -DNO_CONFIGURE_DEPENDS=1
- uses: actions/upload-artifact@v3
with:
name: bun-deps/
path: bun-windows-x64-deps

View File

@@ -1,7 +1,7 @@
name: zig-fmt
env:
ZIG_VERSION: 0.12.0-dev.899+027aabf49
ZIG_VERSION: 0.12.0-dev.1297+a9e66ed73
on:
pull_request:

23
.gitignore vendored
View File

@@ -110,7 +110,7 @@ misctools/machbench
*.big
.eslintcache
bun-webkit
/bun-webkit
src/deps/c-ares/build
src/bun.js/bindings-obj
@@ -135,3 +135,24 @@ make-dev-stats.csv
.uuid
tsconfig.tsbuildinfo
*.lib
*.pdb
CMakeFiles
build.ninja
.ninja_deps
.ninja_log
CMakeCache.txt
cmake_install.cmake
compile_commands.json
*.lib
x64
**/*.vcxproj*
**/*.sln*
**/*.dir
**/*.pdb
/.webkit-cache
/src/deps/libuv
/build-*/

42
.gitmodules vendored
View File

@@ -1,10 +1,3 @@
[submodule "src/deps/picohttpparser"]
path = src/deps/picohttpparser
url = https://github.com/h2o/picohttpparser.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false
[submodule "src/javascript/jsc/WebKit"]
path = src/bun.js/WebKit
url = https://github.com/oven-sh/WebKit.git
@@ -13,6 +6,13 @@ depth = 1
update = none
shallow = true
fetchRecurseSubmodules = false
[submodule "src/deps/picohttpparser"]
path = src/deps/picohttpparser
url = https://github.com/h2o/picohttpparser.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false
[submodule "src/deps/mimalloc"]
path = src/deps/mimalloc
url = https://github.com/Jarred-Sumner/mimalloc.git
@@ -56,15 +56,23 @@ depth = 1
shallow = true
fetchRecurseSubmodules = false
[submodule "src/deps/c-ares"]
path = src/deps/c-ares
url = https://github.com/c-ares/c-ares.git
path = src/deps/c-ares
url = https://github.com/c-ares/c-ares.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false
[submodule "src/deps/zstd"]
path = src/deps/zstd
url = https://github.com/facebook/zstd.git
ignore = dirty
path = src/deps/zstd
url = https://github.com/facebook/zstd.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false
[submodule "src/deps/base64"]
path = src/deps/base64
url = https://github.com/aklomp/base64.git
ignore = dirty
depth = 1
shallow = true
path = src/deps/base64
url = https://github.com/aklomp/base64.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false

View File

@@ -1,21 +0,0 @@
// I would have made this a bash script but there isn't an easy way to track
// time in bash sub-second cross platform.
import fs from "fs";
const start = Date.now() + 5;
const result = Bun.spawnSync(process.argv.slice(2), {
stdio: ["inherit", "inherit", "inherit"],
});
const end = Date.now();
const diff = (Math.max(Math.round(end - start), 0) / 1000).toFixed(3);
const success = result.exitCode === 0;
try {
const line = `${new Date().toISOString()}, ${success ? "success" : "fail"}, ${diff}\n`;
if (fs.existsSync(".scripts/make-dev-stats.csv")) {
fs.appendFileSync(".scripts/make-dev-stats.csv", line);
} else {
fs.writeFileSync(".scripts/make-dev-stats.csv", line);
}
} catch {
// Ignore
}
process.exit(result.exitCode);

View File

@@ -1,13 +0,0 @@
#!/bin/bash
set -euxo pipefail
# if bun-webkit node_modules directory exists
if [ -d ./node_modules/bun-webkit ] || [ -d ./node_modules/bun-webkit-debug ]; then
rm -f bun-webkit
# get the first matching bun-webkit-* directory name
ln -s ./node_modules/$(ls ./node_modules | grep bun-webkit- | grep -v bun-webkit-debug | head -n 1) ./bun-webkit
fi
# sets up vscode C++ intellisense
rm -f .vscode/clang++
ln -s $(which clang++-16 || which clang++) .vscode/clang++ 2>/dev/null

View File

@@ -1,23 +1,17 @@
{
"configurations": [
{
"name": "Mac",
"name": "Debug",
"forcedInclude": ["${workspaceFolder}/src/bun.js/bindings/root.h"],
"includePath": [
"${workspaceFolder}/../webkit-build/include/",
"${workspaceFolder}/bun-webkit/include/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/bmalloc/Headers/",
"${workspaceFolder}/build/bun-webkit/include",
"${workspaceFolder}/build/codegen",
"${workspaceFolder}/src/bun.js/bindings/",
"${workspaceFolder}/src/bun.js/bindings/webcore/",
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
"${workspaceFolder}/src/bun.js/modules/",
"${workspaceFolder}/src/js/builtins/",
"${workspaceFolder}/src/js/out",
"${workspaceFolder}/src/deps/boringssl/include/",
"${workspaceFolder}/src/deps",
"${workspaceFolder}/src/napi/*",
@@ -26,27 +20,16 @@
],
"browse": {
"path": [
"${workspaceFolder}/../webkit-build/include/",
"${workspaceFolder}/bun-webkit/include/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/ICU/Headers/",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/JavaScriptCore/PrivateHeaders/**",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/WTF/Headers/**",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Debug/bmalloc/Headers/**",
"${workspaceFolder}/src/bun.js/bindings/*",
"${workspaceFolder}/src/bun.js/bindings/*",
"${workspaceFolder}/build/bun-webkit/include",
"${workspaceFolder}/src/bun.js/bindings",
"${workspaceFolder}/src/napi/*",
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
"${workspaceFolder}/src/bun.js/bindings/webcore/",
"${workspaceFolder}/src/js/builtins/*",
"${workspaceFolder}/src/js/out/*",
"${workspaceFolder}/src/bun.js/modules/*",
"${workspaceFolder}/src/deps",
"${workspaceFolder}/src/deps/boringssl/include/",
"${workspaceFolder}/packages/bun-usockets/",
"${workspaceFolder}/packages/bun-uws/",
"${workspaceFolder}/src/napi"
"${workspaceFolder}/src/deps/*",
"${workspaceFolder}/src/deps/boringssl/include/*",
"${workspaceFolder}/packages/bun-usockets/*",
"${workspaceFolder}/packages/bun-uws/*",
"${workspaceFolder}/src/napi/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ".vscode/cppdb"

6
.vscode/launch.json generated vendored
View File

@@ -307,11 +307,9 @@
"name": "bun install",
"program": "bun-debug",
"args": ["install"],
"cwd": "${fileDirname}",
"cwd": "/Users/jarred/Build/worky",
"console": "internalConsole",
"env": {
"BUN_DEBUG_ALL": "1"
}
"env": {}
},
{
"type": "lldb",

89
.vscode/settings.json vendored
View File

@@ -8,43 +8,35 @@
"search.useIgnoreFiles": true,
"zig.buildOnSave": false,
"zig.formattingProvider": "zls",
"zig.buildArgs": ["obj", "-Dfor-editor"],
"zig.buildOption": "build",
"zig.buildFilePath": "${workspaceFolder}/build.zig",
"zig.initialSetupDone": true,
"editor.formatOnSave": true,
"[zig]": {
"editor.tabSize": 4,
"editor.useTabStops": false,
"editor.defaultFormatter": "ziglang.vscode-zig",
"editor.formatOnSave": true
"editor.defaultFormatter": "ziglang.vscode-zig"
},
"[ts]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[js]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"zig.zls.enableInlayHints": false,
"zig.zls.enabled": true,
"git.ignoreSubmodules": true,
"[jsx]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[tsx]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[yaml]": {
"editor.formatOnSave": true
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[yaml]": {},
"[markdown]": {
"editor.unicodeHighlight.ambiguousCharacters": false,
"editor.unicodeHighlight.invisibleCharacters": false,
"diffEditor.ignoreTrimWhitespace": false,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.wordWrap": "on",
"editor.quickSuggestions": {
"comments": "off",
@@ -64,8 +56,6 @@
"**/*.xcscheme": true,
"**/*.pem": true,
"**/*.xcodeproj": true,
"test/snapshots": true,
"test/snapshots-no-hmr": true,
"src/bun.js/WebKit": true,
"src/deps/libarchive": true,
"src/deps/mimalloc": true,
@@ -77,30 +67,25 @@
"src/deps/lol-html": true,
"src/deps/c-ares": true,
"src/deps/tinycc": true,
"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/deps/zstd": true
},
"C_Cpp.files.exclude": {
"**/.vscode": true,
"src/bun.js/WebKit/JSTests": true,
"src/bun.js/WebKit/Tools": true,
"src/bun.js/WebKit/WebDriverTests": true,
"src/bun.js/WebKit/WebKit.xcworkspace": true,
"src/bun.js/WebKit/WebKitLibraries": true,
"src/bun.js/WebKit/Websites": true,
"src/bun.js/WebKit/resources": true,
"src/bun.js/WebKit/LayoutTests": true,
"src/bun.js/WebKit/ManualTests": true,
"src/bun.js/WebKit/PerformanceTests": true,
"src/bun.js/WebKit/WebKitLegacy": true,
"src/bun.js/WebKit/WebCore": true,
"src/bun.js/WebKit/WebDriver": true,
"src/bun.js/WebKit/WebKitBuild": true,
"src/bun.js/WebKit/WebInspectorUI": true
"WebKit/JSTests": true,
"WebKit/Tools": true,
"WebKit/WebDriverTests": true,
"WebKit/WebKit.xcworkspace": true,
"WebKit/WebKitLibraries": true,
"WebKit/Websites": true,
"WebKit/resources": true,
"WebKit/LayoutTests": true,
"WebKit/ManualTests": true,
"WebKit/PerformanceTests": true,
"WebKit/WebKitLegacy": true,
"WebKit/WebCore": true,
"WebKit/WebDriver": true,
"WebKit/WebKitBuild": true,
"WebKit/WebInspectorUI": true
},
"[cpp]": {
"editor.defaultFormatter": "xaver.clang-format"
@@ -191,20 +176,12 @@
"set": "cpp",
"__memory": "cpp",
"memory_resource": "cpp",
"resource.h": "c",
"sysinfo.h": "c",
"*.tcc": "cpp",
"list": "cpp",
"shared_mutex": "cpp",
"cinttypes": "cpp",
"variant": "cpp",
"sysctl.h": "c",
"interface_adresses.h": "c",
"interface_addresses.h": "c",
"ctype.h": "c",
"ethernet.h": "c",
"inet.h": "c",
"packet.h": "c",
"queue": "cpp",
"compare": "cpp",
"concepts": "cpp",
@@ -220,7 +197,23 @@
"regex": "cpp",
"span": "cpp",
"valarray": "cpp",
"codecvt": "cpp"
"codecvt": "cpp",
"xtr1common": "cpp",
"stop_token": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstring": "cpp",
"xtree": "cpp",
"xutility": "cpp"
},
"C_Cpp.errorSquiggles": "enabled",
"eslint.workingDirectories": ["packages/bun-types"],

1189
CMakeLists.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,11 @@
# This Dockerfile is used by CI workflows to build Bun. It is not intended as a development
# environment, or to be used as a base image for other projects.
#
# You likely want this image instead: https://hub.docker.com/r/oven/bun
#
# TODO: move this file to reduce confusion
ARG DEBIAN_FRONTEND=noninteractive
ARG GITHUB_WORKSPACE=/build
ARG ZIG_PATH=${GITHUB_WORKSPACE}/zig
ARG WEBKIT_DIR=${GITHUB_WORKSPACE}/bun-webkit
ARG BUN_RELEASE_DIR=${GITHUB_WORKSPACE}/bun-release
ARG BUN_DEPS_OUT_DIR=${GITHUB_WORKSPACE}/bun-deps
@@ -8,123 +13,140 @@ ARG BUN_DIR=${GITHUB_WORKSPACE}/bun
ARG CPU_TARGET=native
ARG ARCH=x86_64
ARG BUILD_MACHINE_ARCH=x86_64
ARG TRIPLET=${ARCH}-linux-gnu
ARG BUILDARCH=amd64
ARG WEBKIT_TAG=2023-oct3-2
ARG ZIG_TAG=jul1
ARG ZIG_VERSION="0.12.0-dev.899+027aabf49"
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
ARG TRIPLET=${ARCH}-linux-gnu
ARG GIT_SHA="unknown"
ARG BUN_DOWNLOAD_URL_BASE="https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest"
ARG ZIG_FOLDERNAME=zig-linux-${BUILD_MACHINE_ARCH}-${ZIG_VERSION}
ARG ZIG_FILENAME=${ZIG_FOLDERNAME}.tar.xz
ARG WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/$WEBKIT_TAG/${WEBKIT_BASENAME}.tar.gz"
ARG ZIG_URL="https://ziglang.org/builds/${ZIG_FILENAME}"
ARG GIT_SHA=""
ARG BUN_BASE_VERSION=1.0
ARG BUN_VERSION="1.0.7"
ARG NODE_VERSION="20"
ARG LLVM_VERSION="16"
ARG ZIG_VERSION="0.12.0-dev.1297+a9e66ed73"
ARG SCCACHE_BUCKET
ARG SCCACHE_REGION
ARG SCCACHE_S3_USE_SSL
ARG SCCACHE_ENDPOINT
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
FROM bitnami/minideb:bullseye as bun-base
RUN install_packages ca-certificates curl wget lsb-release software-properties-common gnupg gnupg1 gnupg2 && \
echo "deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-16 main" > /etc/apt/sources.list.d/llvm.list && \
echo "deb-src https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-16 main" >> /etc/apt/sources.list.d/llvm.list && \
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
install_packages \
cmake \
file \
git \
gnupg \
libc-dev \
libxml2 \
libxml2-dev \
make \
ninja-build \
perl \
python3 \
rsync \
ruby \
unzip \
clang-16 \
lld-16 \
lldb-16 \
clangd-16 \
xz-utils \
bash tar gzip ccache nodejs && \
npm install -g esbuild
ARG BUN_DOWNLOAD_URL_BASE
ARG DEBIAN_FRONTEND
ARG BUN_VERSION
ARG NODE_VERSION
ARG LLVM_VERSION
ARG BUILD_MACHINE_ARCH
ARG BUN_DIR
ARG BUN_DEPS_OUT_DIR
ENV CI 1
ENV BUILDARCH=${BUILDARCH}
ENV BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR}
ENV CXX=clang++-16
ENV CC=clang-16
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG BUILDARCH
ARG ZIG_PATH
ARG WEBKIT_URL
ARG ZIG_URL
ARG ZIG_FOLDERNAME
ARG ZIG_FILENAME
ENV WEBKIT_OUT_DIR=${WEBKIT_DIR}
ENV BUILDARCH=${BUILDARCH}
ENV AR=/usr/bin/llvm-ar-16
ENV ZIG "${ZIG_PATH}/zig"
ENV PATH="$ZIG/bin:$PATH"
ENV LD=lld-16
RUN mkdir -p $BUN_DIR $BUN_DEPS_OUT_DIR
ENV SCCACHE_BUCKET=${SCCACHE_BUCKET}
ENV SCCACHE_REGION=${SCCACHE_REGION}
ENV SCCACHE_S3_USE_SSL=${SCCACHE_S3_USE_SSL}
ENV SCCACHE_ENDPOINT=${SCCACHE_ENDPOINT}
ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
FROM bun-base as bun-base-with-zig-and-webkit
RUN apt-get update -y \
&& install_packages \
ca-certificates \
curl \
gnupg \
&& echo "deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-${LLVM_VERSION} main" > /etc/apt/sources.list.d/llvm.list \
&& echo "deb-src https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-${LLVM_VERSION} main" >> /etc/apt/sources.list.d/llvm.list \
&& curl -fsSL "https://apt.llvm.org/llvm-snapshot.gpg.key" | apt-key add - \
&& echo "deb https://deb.nodesource.com/node_${NODE_VERSION}.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
&& curl -fsSL "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" | apt-key add - \
&& echo "deb https://apt.kitware.com/ubuntu/ focal main" > /etc/apt/sources.list.d/kitware.list \
&& curl -fsSL "https://apt.kitware.com/keys/kitware-archive-latest.asc" | apt-key add - \
&& install_packages \
wget \
bash \
software-properties-common \
build-essential \
autoconf \
automake \
libtool \
pkg-config \
clang-${LLVM_VERSION} \
lld-${LLVM_VERSION} \
lldb-${LLVM_VERSION} \
clangd-${LLVM_VERSION} \
make \
cmake \
ninja-build \
file \
libc-dev \
libxml2 \
libxml2-dev \
xz-utils \
git \
tar \
rsync \
gzip \
unzip \
perl \
python3 \
ruby \
golang \
nodejs \
&& ln -s /usr/bin/clang-${LLVM_VERSION} /usr/bin/clang \
&& ln -s /usr/bin/clang++-${LLVM_VERSION} /usr/bin/clang++ \
&& ln -s /usr/bin/lld-${LLVM_VERSION} /usr/bin/lld \
&& ln -s /usr/bin/lldb-${LLVM_VERSION} /usr/bin/lldb \
&& ln -s /usr/bin/clangd-${LLVM_VERSION} /usr/bin/clangd \
&& ln -s /usr/bin/llvm-ar-${LLVM_VERSION} /usr/bin/llvm-ar \
&& arch="$(dpkg --print-architecture)" \
&& case "${arch##*-}" in \
amd64) variant="x64";; \
arm64) variant="aarch64";; \
*) echo "error: unsupported architecture: $arch"; exit 1 ;; \
esac \
&& wget "${BUN_DOWNLOAD_URL_BASE}/bun-linux-${variant}.zip" \
&& unzip bun-linux-${variant}.zip \
&& mv bun-linux-${variant}/bun /usr/bin/bun \
&& ln -s /usr/bin/bun /usr/bin/bunx \
&& rm -rf bun-linux-${variant} bun-linux-${variant}.zip \
&& mkdir -p ${BUN_DIR} ${BUN_DEPS_OUT_DIR}
# && if [ -n "${SCCACHE_BUCKET}" ]; then \
# echo "Setting up sccache" \
# && wget https://github.com/mozilla/sccache/releases/download/v0.5.4/sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl.tar.gz \
# && tar xf sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl.tar.gz \
# && mv sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl/sccache /usr/bin/sccache \
# && rm -rf sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl.tar.gz sccache-v0.5.4-${BUILD_MACHINE_ARCH}-unknown-linux-musl \
FROM bun-base as bun-base-with-zig
ARG ZIG_VERSION
ARG BUILD_MACHINE_ARCH
ARG ZIG_FOLDERNAME=zig-linux-${BUILD_MACHINE_ARCH}-${ZIG_VERSION}
ARG ZIG_FILENAME=${ZIG_FOLDERNAME}.tar.xz
ARG ZIG_URL="https://ziglang.org/builds/${ZIG_FILENAME}"
WORKDIR $GITHUB_WORKSPACE
ADD $ZIG_URL .
RUN tar xf ${ZIG_FILENAME} && \
rm ${ZIG_FILENAME} && mv ${ZIG_FOLDERNAME} zig;
WORKDIR $GITHUB_WORKSPACE
ARG GITHUB_WORKSPACE
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG BUILDARCH
ARG ZIG_PATH
ARG WEBKIT_URL
ARG ZIG_URL
ARG WEBKIT_BASENAME
ADD ${WEBKIT_URL} .
RUN mkdir -p ${WEBKIT_DIR} && cd ${GITHUB_WORKSPACE} && \
gunzip ${WEBKIT_BASENAME}.tar.gz && tar -xf ${WEBKIT_BASENAME}.tar && \
cat ${WEBKIT_DIR}/include/cmakeconfig.h > /dev/null
LABEL org.opencontainers.image.title="bun base image with zig & webkit ${BUILDARCH} (glibc)"
LABEL org.opencontainers.image.source=https://github.com/oven-sh/bun
RUN tar xf ${ZIG_FILENAME} \
&& mv ${ZIG_FOLDERNAME}/lib /usr/lib/zig \
&& mv ${ZIG_FOLDERNAME}/zig /usr/bin/zig \
&& rm -rf ${ZIG_FILENAME} ${ZIG_FOLDERNAME}
FROM bun-base as c-ares
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ENV CCACHE_DIR=/ccache
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
COPY Makefile ${BUN_DIR}/Makefile
COPY src/deps/c-ares ${BUN_DIR}/src/deps/c-ares
@@ -133,20 +155,11 @@ WORKDIR $BUN_DIR
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && make c-ares && rm -rf ${BUN_DIR}/src/deps/c-ares ${BUN_DIR}/Makefile
FROM bun-base as lolhtml
RUN install_packages build-essential && curl https://sh.rustup.rs -sSf | sh -s -- -y
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
@@ -155,88 +168,57 @@ COPY src/deps/lol-html ${BUN_DIR}/src/deps/lol-html
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache export PATH=$PATH:$HOME/.cargo/bin && export CC=$(which clang-16) && cd ${BUN_DIR} && \
make lolhtml && rm -rf src/deps/lol-html Makefile
RUN --mount=type=cache,target=/ccache export PATH=$PATH:$HOME/.cargo/bin && cd ${BUN_DIR} && \
make lolhtml && rm -rf src/deps/lol-html Makefile
FROM bun-base as mimalloc
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
COPY src/deps/mimalloc ${BUN_DIR}/src/deps/mimalloc
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache cd ${BUN_DIR} && \
make mimalloc && rm -rf src/deps/mimalloc Makefile
make mimalloc && rm -rf src/deps/mimalloc Makefile
FROM bun-base as zlib
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ENV CCACHE_DIR=/ccache
COPY Makefile ${BUN_DIR}/Makefile
COPY src/deps/zlib ${BUN_DIR}/src/deps/zlib
WORKDIR $BUN_DIR
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && \
make zlib && rm -rf src/deps/zlib Makefile
make zlib && rm -rf src/deps/zlib Makefile
FROM bun-base as libarchive
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ENV CCACHE_DIR=/ccache
RUN install_packages autoconf automake libtool pkg-config
COPY Makefile ${BUN_DIR}/Makefile
COPY src/deps/libarchive ${BUN_DIR}/src/deps/libarchive
ENV CCACHE_DIR=/ccache
WORKDIR $BUN_DIR
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && \
make libarchive && rm -rf src/deps/libarchive Makefile
make libarchive && rm -rf src/deps/libarchive Makefile
FROM bun-base as tinycc
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
@@ -248,13 +230,6 @@ FROM bun-base as boringssl
RUN install_packages golang
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
@@ -268,42 +243,8 @@ ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache cd ${BUN_DIR} && make boringssl && rm -rf src/deps/boringssl Makefile
FROM bun-base as uws
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
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
WORKDIR $BUN_DIR
RUN cd $BUN_DIR && \
make uws && rm -rf packages/bun-uws Makefile
FROM bun-base as base64
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
@@ -314,225 +255,10 @@ COPY src/deps/base64 ${BUN_DIR}/src/deps/base64
WORKDIR $BUN_DIR
RUN cd $BUN_DIR && \
make base64 && rm -rf src/deps/base64 Makefile
FROM bun-base as picohttp
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
COPY src/deps/picohttpparser ${BUN_DIR}/src/deps/picohttpparser
COPY src/deps/*.c ${BUN_DIR}/src/deps/
COPY src/deps/*.h ${BUN_DIR}/src/deps/
WORKDIR $BUN_DIR
RUN cd $BUN_DIR && \
make picohttp
FROM bun-base-with-zig-and-webkit as identifier_cache
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
WORKDIR $BUN_DIR
COPY Makefile ${BUN_DIR}/Makefile
COPY src/js_lexer/identifier_data.zig ${BUN_DIR}/src/js_lexer/identifier_data.zig
COPY src/js_lexer/identifier_cache.zig ${BUN_DIR}/src/js_lexer/identifier_cache.zig
RUN cd $BUN_DIR && \
make identifier-cache && rm -rf zig-cache Makefile
FROM bun-base-with-zig-and-webkit as node_fallbacks
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
WORKDIR $BUN_DIR
COPY Makefile ${BUN_DIR}/Makefile
COPY src/node-fallbacks ${BUN_DIR}/src/node-fallbacks
RUN cd $BUN_DIR && \
make node-fallbacks && rm -rf src/node-fallbacks/node_modules Makefile
FROM bun-base-with-zig-and-webkit as prepare_release
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
WORKDIR $BUN_DIR
COPY ./root.zig ${BUN_DIR}/root.zig
COPY ./src ${BUN_DIR}/src
COPY ./build.zig ${BUN_DIR}/build.zig
COPY ./completions ${BUN_DIR}/completions
COPY ./packages ${BUN_DIR}/packages
COPY ./src/build-id ${BUN_DIR}/src/build-id
COPY ./package.json ${BUN_DIR}/package.json
COPY ./misctools ${BUN_DIR}/misctools
COPY Makefile ${BUN_DIR}/Makefile
FROM prepare_release as compile_release_obj
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
COPY .prettierrc.cjs ${BUN_DIR}/.prettierrc.cjs
WORKDIR $BUN_DIR
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
ARG ARCH
ARG TRIPLET
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ARG GIT_SHA
ARG BUN_BASE_VERSION
ENV BUN_BASE_VERSION=${BUN_BASE_VERSION}
ENV GIT_SHA=${GIT_SHA}
COPY --from=identifier_cache ${BUN_DIR}/src/js_lexer/*.blob ${BUN_DIR}/src/js_lexer/
COPY --from=node_fallbacks ${BUN_DIR}/src/node-fallbacks/out ${BUN_DIR}/src/node-fallbacks/out
COPY ./src/build-id ${BUN_DIR}/src/build-id
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && mkdir -p src/bun.js/bindings-obj && rm -rf $HOME/.cache zig-cache && make prerelease && \
mkdir -p $BUN_RELEASE_DIR && \
OUTPUT_DIR=/tmp/bun-${TRIPLET}-${GIT_SHA} $ZIG_PATH/zig build obj -Doutput-dir=/tmp/bun-${TRIPLET}-${GIT_SHA} -Doptimize=ReleaseFast -Dtarget="${TRIPLET}" -Dcpu="${CPU_TARGET}" && \
cp /tmp/bun-${TRIPLET}-${GIT_SHA}/bun.o /tmp/bun-${TRIPLET}-${GIT_SHA}/bun-${BUN_BASE_VERSION}.$(cat ${BUN_DIR}/src/build-id).o && cd / && rm -rf $BUN_DIR
FROM scratch as build_release_obj
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG GIT_SHA
ARG TRIPLET
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY --from=compile_release_obj /tmp/bun-${TRIPLET}-${GIT_SHA}/*.o /
FROM prepare_release as compile_cpp
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
COPY .prettierrc.cjs ${BUN_DIR}/.prettierrc.cjs
WORKDIR $BUN_DIR
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
# Required for webcrypto bindings
COPY src/deps/boringssl/include ${BUN_DIR}/src/deps/boringssl/include
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && mkdir -p src/bun.js/bindings-obj && rm -rf $HOME/.cache zig-cache && mkdir -p $BUN_RELEASE_DIR && \
make release-bindings -j10 && mv src/bun.js/bindings-obj/* /tmp
FROM bun-base as sqlite
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
ENV CCACHE_DIR=/ccache
COPY Makefile ${BUN_DIR}/Makefile
COPY src/bun.js/bindings/sqlite ${BUN_DIR}/src/bun.js/bindings/sqlite
COPY .prettierrc.cjs ${BUN_DIR}/.prettierrc.cjs
WORKDIR $BUN_DIR
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && make sqlite
make base64 && rm -rf src/deps/base64 Makefile
FROM bun-base as zstd
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
ARG CPU_TARGET
@@ -546,140 +272,167 @@ COPY .prettierrc.cjs ${BUN_DIR}/.prettierrc.cjs
WORKDIR $BUN_DIR
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
RUN --mount=type=cache,target=/ccache cd $BUN_DIR && make zstd
FROM scratch as build_release_cpp
COPY --from=compile_cpp /tmp/*.o /
FROM prepare_release as build_release
FROM bun-base-with-zig as bun-identifier-cache
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG CPU_TARGET
ARG BUN_DIR
ENV CPU_TARGET=${CPU_TARGET}
WORKDIR $BUN_DIR
COPY src/js_lexer/identifier_data.zig ${BUN_DIR}/src/js_lexer/identifier_data.zig
COPY src/js_lexer/identifier_cache.zig ${BUN_DIR}/src/js_lexer/identifier_cache.zig
RUN cd $BUN_DIR \
&& zig run src/js_lexer/identifier_data.zig \
&& rm -rf zig-cache
FROM bun-base as bun-node-fallbacks
ARG BUN_DIR
WORKDIR $BUN_DIR
COPY src/node-fallbacks ${BUN_DIR}/src/node-fallbacks
RUN cd $BUN_DIR/src/node-fallbacks \
&& bun install --frozen-lockfile \
&& bun run build \
&& rm -rf src/node-fallbacks/node_modules
FROM bun-base as bun-webkit
ARG BUILDARCH
COPY CMakeLists.txt ${BUN_DIR}/CMakeLists.txt
RUN mkdir ${BUN_DIR}/bun-webkit \
&& WEBKIT_TAG=$(grep 'set(WEBKIT_TAG' "${BUN_DIR}/CMakeLists.txt" | awk '{print $2}' | cut -f 1 -d ')') \
&& WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/autobuild-${WEBKIT_TAG}/bun-webkit-linux-${BUILDARCH}-lto.tar.gz" \
&& echo "Downloading ${WEBKIT_URL}" \
&& curl -fsSL "${WEBKIT_URL}" | tar -xz -C ${BUN_DIR}/bun-webkit --strip-components=1
FROM bun-base as bun-cpp-objects
COPY --from=bun-webkit ${BUN_DIR}/bun-webkit ${BUN_DIR}/bun-webkit
COPY packages ${BUN_DIR}/packages
COPY src ${BUN_DIR}/src
COPY CMakeLists.txt ${BUN_DIR}/CMakeLists.txt
COPY src/deps/boringssl/include ${BUN_DIR}/src/deps/boringssl/include
ENV CCACHE_DIR=/ccache
RUN --mount=type=cache,target=/ccache mkdir ${BUN_DIR}/build \
&& cd ${BUN_DIR}/build \
&& mkdir -p tmp_modules tmp_functions js codegen \
&& cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUN_CPP_ONLY=1 -DWEBKIT_DIR=/build/bun/bun-webkit \
&& bash compile-cpp-only.sh
FROM bun-base-with-zig as bun-codegen-for-zig
COPY package.json bun.lockb Makefile .gitmodules .prettierrc.cjs ${BUN_DIR}/
COPY src/runtime ${BUN_DIR}/src/runtime
COPY src/runtime.js src/runtime.footer*.js src/react-refresh.js ${BUN_DIR}/src/
COPY packages/bun-error ${BUN_DIR}/packages/bun-error
COPY src/fallback.ts ${BUN_DIR}/src/fallback.ts
COPY src/api ${BUN_DIR}/src/api
WORKDIR $BUN_DIR
# TODO: move away from Makefile entirely
RUN bun install --frozen-lockfile \
&& make runtime_js fallback_decoder bun_error \
&& rm -rf src/runtime src/fallback.ts node_modules bun.lockb package.json Makefile
FROM bun-base-with-zig as bun-compile-zig-obj
ARG ZIG_PATH
ARG TRIPLET
ARG GIT_SHA
ARG CPU_TARGET
COPY *.zig package.json CMakeLists.txt ${BUN_DIR}/
COPY completions ${BUN_DIR}/completions
COPY packages ${BUN_DIR}/packages
COPY src ${BUN_DIR}/src
COPY --from=bun-identifier-cache ${BUN_DIR}/src/js_lexer/*.blob ${BUN_DIR}/src/js_lexer/
COPY --from=bun-node-fallbacks ${BUN_DIR}/src/node-fallbacks/out ${BUN_DIR}/src/node-fallbacks/out
COPY --from=bun-codegen-for-zig ${BUN_DIR}/src/*.out.js ${BUN_DIR}/src/*.out.refresh.js ${BUN_DIR}/src/
COPY --from=bun-codegen-for-zig ${BUN_DIR}/packages/bun-error/dist ${BUN_DIR}/packages/bun-error/dist
WORKDIR $BUN_DIR
RUN mkdir -p build \
&& bun run $BUN_DIR/src/codegen/bundle-modules-fast.ts $BUN_DIR/build \
&& cd build \
&& cmake .. \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCPU_TARGET="${CPU_TARGET}" \
-DZIG_TARGET="${TRIPLET}" \
-DWEBKIT_DIR="omit" \
-DNO_CONFIGURE_DEPENDS=1 \
-DNO_CODEGEN=1 \
-DBUN_ZIG_OBJ="/tmp/bun-zig.o" \
&& ONLY_ZIG=1 ninja "/tmp/bun-zig.o" \
&& echo "-> /tmp/bun-zig.o"
FROM scratch as build_release_obj
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
COPY Makefile ${BUN_DIR}/Makefile
COPY .prettierrc.cjs ${BUN_DIR}/.prettierrc.cjs
COPY --from=bun-compile-zig-obj /tmp/bun-zig.o /
FROM bun-base as bun-link
ARG CPU_TARGET
ENV CPU_TARGET=${CPU_TARGET}
WORKDIR $BUN_DIR
ENV JSC_BASE_DIR=${WEBKIT_DIR}
ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib
RUN mkdir -p build bun-webkit
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=base64 ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=mimalloc ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
COPY --from=picohttp ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
COPY --from=sqlite ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
COPY --from=zstd ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/
COPY --from=c-ares ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/
# lol
COPY src/bun.js/bindings/sqlite/sqlite3.c ${BUN_DIR}/src/bun.js/bindings/sqlite/sqlite3.c
COPY --from=build_release_obj /*.o /tmp
COPY --from=build_release_cpp /*.o ${BUN_DIR}/src/bun.js/bindings-obj/
COPY --from=build_release_cpp /*.a ${BUN_DEPS_OUT_DIR}/
COPY src/symbols.dyn src/linker.lds ${BUN_DIR}/src/
RUN cd $BUN_DIR && mkdir -p ${BUN_RELEASE_DIR} && make bun-relink copy-to-bun-release-dir && \
rm -rf $HOME/.cache zig-cache misctools package.json build-id completions build.zig $(BUN_DIR)/packages
COPY CMakeLists.txt ${BUN_DIR}/CMakeLists.txt
COPY --from=zlib ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=base64 ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=mimalloc ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=zstd ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=c-ares ${BUN_DEPS_OUT_DIR}/* ${BUN_DEPS_OUT_DIR}/
COPY --from=bun-compile-zig-obj /tmp/bun-zig.o ${BUN_DIR}/build/bun-zig.o
COPY --from=bun-cpp-objects ${BUN_DIR}/build/bun-cpp-objects.a ${BUN_DIR}/build/bun-cpp-objects.a
COPY --from=bun-cpp-objects ${BUN_DIR}/bun-webkit/lib ${BUN_DIR}/bun-webkit/lib
WORKDIR $BUN_DIR/build
RUN cmake .. \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_LINK_ONLY=1 \
-DBUN_ZIG_OBJ="${BUN_DIR}/build/bun-zig.o" \
-DBUN_CPP_ARCHIVE="${BUN_DIR}/build/bun-cpp-objects.a" \
-DWEBKIT_DIR="${BUN_DIR}/bun-webkit" \
-DBUN_DEPS_OUT_DIR="${BUN_DEPS_OUT_DIR}" \
&& ninja \
&& mkdir -p /build/out \
&& mv bun bun-profile /build/out \
&& rm -rf ${BUN_DIR} ${BUN_DEPS_OUT_DIR}
FROM scratch as artifact
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
COPY --from=build_release ${BUN_RELEASE_DIR}/bun /bun
COPY --from=build_release ${BUN_RELEASE_DIR}/bun-profile /bun-profile
COPY --from=build_release ${BUN_DEPS_OUT_DIR}/* /bun-dependencies
COPY --from=build_release_obj /*.o /bun-obj
FROM prepare_release as build_unit
ARG DEBIAN_FRONTEND
ARG GITHUB_WORKSPACE
ARG ZIG_PATH
# Directory extracts to "bun-webkit"
ARG WEBKIT_DIR
ARG BUN_RELEASE_DIR
ARG BUN_DEPS_OUT_DIR
ARG BUN_DIR
WORKDIR $BUN_DIR
ENV PATH "$ZIG_PATH:$PATH"
ENV LIB_ICU_PATH "${WEBKIT_DIR}/lib"
CMD make headers \
api \
analytics \
bun_error \
fallback_decoder \
bindings -j10 && \
make \
run-all-unit-tests
# FROM bun-test-base as test_base
# ARG DEBIAN_FRONTEND=noninteractive
# ARG GITHUB_WORKSPACE=/build
# ARG ZIG_PATH=${GITHUB_WORKSPACE}/zig
# # Directory extracts to "bun-webkit"
# ARG WEBKIT_DIR=${GITHUB_WORKSPACE}/bun-webkit
# ARG BUN_RELEASE_DIR=${GITHUB_WORKSPACE}/bun-release
# ARG BUN_DEPS_OUT_DIR=${GITHUB_WORKSPACE}/bun-deps
# ARG BUN_DIR=${GITHUB_WORKSPACE}/bun
# ARG BUILDARCH=amd64
# RUN groupadd -r chromium && useradd -d ${BUN_DIR} -M -r -g chromium -G audio,video chromium \
# && mkdir -p /home/chromium/Downloads && chown -R chromium:chromium /home/chromium
# USER chromium
# WORKDIR $BUN_DIR
# ENV NPM_CLIENT bun
# ENV PATH "${BUN_DIR}/packages/bun-linux-x64:${BUN_DIR}/packages/bun-linux-aarch64:$PATH"
# ENV CI 1
# ENV BROWSER_EXECUTABLE /usr/bin/chromium
# COPY ./test ${BUN_DIR}/test
# COPY Makefile ${BUN_DIR}/Makefile
# COPY package.json ${BUN_DIR}/package.json
# COPY .docker/run-test.sh ${BUN_DIR}/run-test.sh
# COPY ./bun.lockb ${BUN_DIR}/bun.lockb
# # # We don't want to worry about architecture differences in this image
# COPY --from=release /opt/bun/bin/bun ${BUN_DIR}/packages/bun-linux-aarch64/bun
# COPY --from=release /opt/bun/bin/bun ${BUN_DIR}/packages/bun-linux-x64/bun
# USER root
# RUN chgrp -R chromium ${BUN_DIR} && chmod g+rwx ${BUN_DIR} && chown -R chromium:chromium ${BUN_DIR}
# USER chromium
# CMD [ "bash", "run-test.sh" ]
# FROM release
COPY --from=bun-link /build/out /

View File

@@ -39,7 +39,6 @@ endif
MIN_MACOS_VERSION ?= $(DEFAULT_MIN_MACOS_VERSION)
BUN_BASE_VERSION = 1.0
CI ?= false
AR=
@@ -66,7 +65,7 @@ PACKAGE_JSON_VERSION = $(BUN_BASE_VERSION).$(BUILD_ID)
BUN_BUILD_TAG = bun-v$(PACKAGE_JSON_VERSION)
BUN_RELEASE_BIN = $(PACKAGE_DIR)/bun
PRETTIER ?= $(shell which prettier 2>/dev/null || echo "./node_modules/.bin/prettier")
ESBUILD = $(shell which esbuild 2>/dev/null || echo "./node_modules/.bin/esbuild")
ESBUILD = "$(shell which esbuild 2>/dev/null || echo "./node_modules/.bin/esbuild")"
DSYMUTIL ?= $(shell which dsymutil 2>/dev/null || which dsymutil-15 2>/dev/null)
WEBKIT_DIR ?= $(realpath src/bun.js/WebKit)
WEBKIT_RELEASE_DIR ?= $(WEBKIT_DIR)/WebKitBuild/Release
@@ -74,7 +73,7 @@ WEBKIT_DEBUG_DIR ?= $(WEBKIT_DIR)/WebKitBuild/Debug
WEBKIT_RELEASE_DIR_LTO ?= $(WEBKIT_DIR)/WebKitBuild/ReleaseLTO
NPM_CLIENT ?= $(shell which bun 2>/dev/null || which npm 2>/dev/null)
NPM_CLIENT = "$(shell which bun 2>/dev/null || which npm 2>/dev/null)"
ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make sure zig is in PATH. Or set ZIG=/path/to-zig-executable")
# We must use the same compiler version for the JavaScriptCore bindings and JavaScriptCore
@@ -187,11 +186,6 @@ BUN_CFLAGS = $(MACOS_MIN_FLAG) $(MARCH_NATIVE) $(OPTIMIZATION_LEVEL) -fno-excep
BUN_TMP_DIR := /tmp/make-bun
CFLAGS=$(CFLAGS_WITHOUT_MARCH) $(MARCH_NATIVE)
DEFAULT_USE_BMALLOC := 1
USE_BMALLOC ?= DEFAULT_USE_BMALLOC
# Set via postinstall
ifeq (,$(realpath $(JSC_BASE_DIR)))
JSC_BASE_DIR = $(realpath $(firstword $(wildcard bun-webkit)))
@@ -380,9 +374,7 @@ ICU_FLAGS ?=
# Ideally, we could just look up the linker search paths
ifeq ($(OS_NAME),linux)
LIB_ICU_PATH ?= $(JSC_LIB)
ICU_FLAGS += $(LIB_ICU_PATH)/libicuuc.a $(LIB_ICU_PATH)/libicudata.a $(LIB_ICU_PATH)/libicui18n.a
else
LIB_ICU_PATH ?= $(BUN_DEPS_DIR)
ICU_FLAGS += $(LIB_ICU_PATH)/libicuuc.a $(LIB_ICU_PATH)/libicudata.a $(LIB_ICU_PATH)/libicui18n.a
endif
ifeq ($(OS_NAME),darwin)
@@ -764,7 +756,7 @@ USOCKETS_DIR = $(BUN_DIR)/packages/bun-usockets
USOCKETS_SRC_DIR = $(USOCKETS_DIR)/src
usockets:
rm -rf $(USOCKETS_DIR)/*.i $(USOCKETS_DIR)/*.bc $(USOCKETS_DIR)/*.o $(USOCKETS_DIR)/*.s $(USOCKETS_DIR)/*.ii $(USOCKETS_DIR)/*.s
rm -rf $(USOCKETS_DIR)/*.i $(USOCKETS_DIR)/*.bc $(USOCKETS_DIR)/*.o $(USOCKETS_DIR)/*.s $(USOCKETS_DIR)/*.ii $(USOCKETS_DIR)/*.s $(BUN_DEPS_OUT_DIR)/libusockets.a
cd $(USOCKETS_DIR) && $(CC_WITH_CCACHE) -I$(USOCKETS_SRC_DIR) -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc $(EMIT_LLVM_FOR_RELEASE) $(MACOS_MIN_FLAG) -fPIC $(CFLAGS) $(UWS_CC_FLAGS) -save-temps -I$(BUN_DEPS_DIR)/uws/uSockets/src $(UWS_LDFLAGS) -g $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) $(OPTIMIZATION_LEVEL) -c $(wildcard $(USOCKETS_SRC_DIR)/*.c) $(wildcard $(USOCKETS_SRC_DIR)/**/*.c)
cd $(USOCKETS_DIR) && $(CXX_WITH_CCACHE) -I$(USOCKETS_SRC_DIR) -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc $(EMIT_LLVM_FOR_RELEASE) $(MACOS_MIN_FLAG) -fPIC $(CXXFLAGS) $(UWS_CXX_FLAGS) -save-temps -I$(BUN_DEPS_DIR)/uws/uSockets/src $(UWS_LDFLAGS) -g $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) $(OPTIMIZATION_LEVEL) -c $(wildcard $(USOCKETS_SRC_DIR)/*.cpp) $(wildcard $(USOCKETS_SRC_DIR)/**/*.cpp)
cd $(USOCKETS_DIR) && $(AR) rcvs $(BUN_DEPS_OUT_DIR)/libusockets.a $(USOCKETS_DIR)/*.{o,bc}
@@ -833,10 +825,10 @@ fallback_decoder:
.PHONY: runtime_js
runtime_js:
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV=\"production\" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV=\"production\" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV=\"production\" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV=\"production\" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
.PHONY: runtime_js_dev
runtime_js_dev:
@@ -937,6 +929,9 @@ clone-submodules:
.PHONY: headers
headers:
echo please don't run the headers generator anymore. i don't think it works.
echo if you really need it, run make headers2
headers2:
rm -f /tmp/build-jsc-headers src/bun.js/bindings/headers.zig
touch src/bun.js/bindings/headers.zig
$(ZIG) build headers-obj
@@ -1326,7 +1321,7 @@ release-bindings: $(OBJ_DIR) $(OBJ_FILES) $(WEBCORE_OBJ_FILES) $(SQLITE_OBJ_FILE
# Do not add $(DEBUG_DIR) to this list
# It will break caching, causing you to have to wait for every .cpp file to rebuild.
.PHONY: bindings
bindings: $(DEBUG_OBJ_DIR) $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_NODE_OS_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES) $(DEBUG_IO_FILES) $(DEBUG_MODULES_OBJ_FILES) $(DEBUG_WEBCRYPTO_OBJ_FILES)
bindings-real: $(DEBUG_OBJ_DIR) $(DEBUG_OBJ_FILES) $(DEBUG_WEBCORE_OBJ_FILES) $(DEBUG_SQLITE_OBJ_FILES) $(DEBUG_NODE_OS_OBJ_FILES) $(DEBUG_BUILTINS_OBJ_FILES) $(DEBUG_IO_FILES) $(DEBUG_MODULES_OBJ_FILES) $(DEBUG_WEBCRYPTO_OBJ_FILES)
.PHONY: jsc-bindings-mac
jsc-bindings-mac: bindings
@@ -1485,12 +1480,12 @@ wasm-return1:
$(ZIG) build-lib -OReleaseSmall test/bun.js/wasm-return-1-test.zig -femit-bin=test/bun.js/wasm-return-1-test.wasm -target wasm32-freestanding
generate-classes:
bun src/bun.js/scripts/generate-classes.ts
bun src/codegen/generate-classes.ts
$(ZIG) fmt src/bun.js/bindings/generated_classes.zig
$(CLANG_FORMAT) -i src/bun.js/bindings/ZigGeneratedClasses.h src/bun.js/bindings/ZigGeneratedClasses.cpp
generate-sink:
bun src/bun.js/scripts/generate-jssink.js
bun src/codegen/generate-jssink.js
$(CLANG_FORMAT) -i src/bun.js/bindings/JSSink.cpp src/bun.js/bindings/JSSink.h
./src/bun.js/scripts/create_hash_table src/bun.js/bindings/JSSink.cpp > src/bun.js/bindings/JSSinkLookupTable.h
$(SED) -i -e 's/#include "Lookup.h"//' src/bun.js/bindings/JSSinkLookupTable.h
@@ -1913,46 +1908,30 @@ vendor: assert-deps submodule vendor-without-check
vendor-dev: assert-deps submodule npm-install-dev vendor-without-npm
.PHONY: bun
bun: vendor identifier-cache build-obj bun-link-lld-release bun-codesign-release-local
bun:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: static-hash-table
static-hash-table:
bun src/js/_codegen/static-hash-tables.ts
cpp:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: cpp
cpp: ## compile src/js/builtins + all c++ code then link
@make clean-bindings js
@make static-hash-table
@make bindings -j$(CPU_COUNT)
@make link
zig:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: cpp
cpp-no-link:
@make clean-bindings js
@make bindings -j$(CPU_COUNT)
dev:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: zig
zig: ## compile zig code then link
@make mkdir-dev dev-obj link
setup:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: zig-no-link
zig-no-link:
@make mkdir-dev dev-obj
bindings:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'
.PHONY: dev
dev: # combo of `make cpp` and `make zig`
@make cpp-no-link zig-no-link -j2
@make link
.PHONY: setup
setup: vendor-dev identifier-cache clean-bindings
make jsc-check dev
@echo ""
@echo "First build complete!"
@echo "\"bun-debug\" is available at $(DEBUG_BIN)/bun-debug"
@echo ""
.PHONY: help
help: ## to print this help
@echo "For detailed build instructions, see https://bun.sh/docs/project/contributing"
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {gsub("\\\\n",sprintf("\n%22c",""), $$2);printf "\033[36m%-20s\033[0m \t\t%s\n", $$1, $$2}' $(MAKEFILE_LIST)
help:
echo makefile is deprecated - use `cmake` / `bun run build`
echo 'See https://bun.sh/docs/project/contributing for more details'

View File

@@ -6,23 +6,30 @@ bench("await 1", async function () {
return await 1;
});
function callnextTick(resolve) {
process.nextTick(resolve);
}
if (typeof process !== "undefined") {
bench("process.nextTick x 100", async function () {
var remaining = 100;
var cb, promise;
promise = new Promise(resolve => {
cb = resolve;
});
function awaitNextTick() {
return new Promise(callnextTick);
}
for (let i = 0; i < 100; i++) {
process.nextTick(() => {
if (--remaining === 0) cb();
});
}
bench("promise.nextTick", async function () {
return awaitNextTick();
});
return promise;
});
bench("await 1 x 100", async function () {
for (let i = 0; i < 100; i++) await 1;
});
}
bench("await new Promise(resolve => resolve())", async function () {
await new Promise(resolve => resolve());
});
bench("Promise.all(Array.from({length: 100}, () => new Promise((resolve) => resolve())))", async function () {
return Promise.all(Array.from({ length: 100 }, () => Promise.resolve(1)));
});
await run();

View File

@@ -0,0 +1,25 @@
import { bench, run } from "./runner.mjs";
import { builtinModules } from "node:module";
import { writeFile } from "node:fs/promises";
import { spawnSync } from "child_process";
for (let builtin of builtinModules) {
const path = `/tmp/require.${builtin.replaceAll("/", "_")}.cjs`;
await writeFile(
path,
`
const builtin = ${JSON.stringify(builtin)};
const now = require("perf_hooks").performance.now();
require(builtin);
const end = require("perf_hooks").performance.now();
process.stdout.write(JSON.stringify({builtin, time: end - now}) + "\\n");
`,
);
const result = spawnSync(typeof Bun !== "undefined" ? "bun" : "node", [path], {
stdio: ["inherit", "inherit", "inherit"],
env: {
...process.env,
NODE_NO_WARNINGS: "1",
},
});
}

134
build.zig
View File

@@ -1,6 +1,7 @@
const required_zig_version = "0.12.0-dev.899+027aabf49";
const recommended_zig_version = "0.12.0-dev.1297+a9e66ed73";
const zig_version = @import("builtin").zig_version;
const std = @import("std");
const pathRel = std.fs.path.relative;
const Wyhash = @import("./src/wyhash.zig").Wyhash;
var is_debug_build = false;
@@ -13,6 +14,11 @@ fn moduleSource(comptime out: []const u8) FileSource {
}
}
fn exists(path: []const u8) bool {
_ = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false;
return true;
}
const color_map = std.ComptimeStringMap([]const u8, .{
&.{ "black", "30m" },
&.{ "blue", "34m" },
@@ -48,11 +54,37 @@ fn addInternalPackages(b: *Build, step: *CompileStep, _: std.mem.Allocator, _: [
};
step.addModule("async_io", io);
step.addModule("zlib-internal", brk: {
if (target.isWindows()) {
break :brk b.createModule(.{ .source_file = FileSource.relative("src/deps/zlib.win32.zig") });
}
break :brk b.createModule(.{ .source_file = FileSource.relative("src/deps/zlib.posix.zig") });
});
var async_: *Module = brk: {
if (target.isDarwin() or target.isLinux() or target.isFreeBSD()) {
break :brk b.createModule(.{
.source_file = FileSource.relative("src/async/posix_event_loop.zig"),
});
} else if (target.isWindows()) {
break :brk b.createModule(.{
.source_file = FileSource.relative("src/async/windows_event_loop.zig"),
});
}
break :brk b.createModule(.{
.source_file = FileSource.relative("src/async/stub_event_loop.zig"),
});
};
step.addModule("async", async_);
}
const BunBuildOptions = struct {
canary: bool = false,
sha: [:0]const u8 = "",
version: []const u8 = "",
baseline: bool = false,
bindgen: bool = false,
sizegen: bool = false,
@@ -61,6 +93,8 @@ const BunBuildOptions = struct {
runtime_js_version: u64 = 0,
fallback_html_version: u64 = 0,
tinycc: bool = true,
pub fn updateRuntime(this: *BunBuildOptions) anyerror!void {
if (std.fs.cwd().openFile("src/runtime.out.js", .{ .mode = .read_only })) |file| {
defer file.close();
@@ -92,6 +126,11 @@ const BunBuildOptions = struct {
pub fn step(this: BunBuildOptions, b: anytype) *std.build.OptionsStep {
var opts = b.addOptions();
opts.addOption(@TypeOf(this.canary), "is_canary", this.canary);
opts.addOption(
std.SemanticVersion,
"version",
std.SemanticVersion.parse(this.version) catch @panic(b.fmt("Invalid version: {s}", .{this.version})),
);
opts.addOption(@TypeOf(this.sha), "sha", this.sha);
opts.addOption(@TypeOf(this.baseline), "baseline", this.baseline);
opts.addOption(@TypeOf(this.bindgen), "bindgen", this.bindgen);
@@ -99,6 +138,7 @@ const BunBuildOptions = struct {
opts.addOption(@TypeOf(this.base_path), "base_path", this.base_path);
opts.addOption(@TypeOf(this.runtime_js_version), "runtime_js_version", this.runtime_js_version);
opts.addOption(@TypeOf(this.fallback_html_version), "fallback_html_version", this.fallback_html_version);
opts.addOption(@TypeOf(this.tinycc), "tinycc", this.tinycc);
return opts;
}
};
@@ -148,18 +188,24 @@ pub fn build(b: *Build) !void {
}
pub fn build_(b: *Build) !void {
if (!std.mem.eql(u8, @import("builtin").zig_version_string, required_zig_version)) {
const colors = std.io.getStdErr().supportsAnsiEscapeCodes();
std.debug.print(
"{s}WARNING:\nBun requires zig version '{s}', but found '{s}', build may fail...\nMake sure you installed the right version as per https://bun.sh/docs/project/development#install-zig\n{s}You can update to the right version using 'zigup {s}'\n\n",
.{
if (colors) "\x1b[1;33m" else "",
required_zig_version,
@import("builtin").zig_version_string,
if (colors) "\x1b[0m" else "",
required_zig_version,
},
);
switch (comptime zig_version.order(std.SemanticVersion.parse(recommended_zig_version) catch unreachable)) {
.eq => {},
.lt => {
@compileError("The minimum version of Zig required to compile Bun is " ++ recommended_zig_version ++ ", found " ++ @import("builtin").zig_version_string);
},
.gt => {
const colors = std.io.getStdErr().supportsAnsiEscapeCodes();
std.debug.print(
"{s}WARNING:\nBun recommends Zig version '{s}', but found '{s}', build may fail...\nMake sure you installed the right version as per https://bun.sh/docs/project/contributing#install-zig\n{s}You can update to the right version using 'zigup {s}'\n\n",
.{
if (colors) "\x1b[1;33m" else "",
recommended_zig_version,
@import("builtin").zig_version_string,
if (colors) "\x1b[0m" else "",
recommended_zig_version,
},
);
},
}
// Standard target options allows the person running `zig build` to choose
@@ -171,6 +217,8 @@ pub fn build_(b: *Build) !void {
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
optimize = b.standardOptimizeOption(.{});
const generated_code_directory = b.option([]const u8, "generated-code", "Set the generated code directory") orelse "./build";
var output_dir_buf = std.mem.zeroes([4096]u8);
var bin_label = if (optimize == std.builtin.OptimizeMode.Debug) "packages/debug-bun-" else "packages/bun-";
@@ -203,15 +251,17 @@ pub fn build_(b: *Build) !void {
var triplet = triplet_buf[0 .. osname.len + cpuArchName.len + 1];
if (b.option([]const u8, "output-dir", "target to install to") orelse std.os.getenv("OUTPUT_DIR")) |output_dir_| {
output_dir = try pathRel(b.allocator, b.install_prefix, output_dir_);
const outfile_maybe = b.option([]const u8, "output-file", "target to install to");
if (outfile_maybe) |outfile| {
output_dir = try pathRel(b.allocator, b.install_prefix, std.fs.path.dirname(outfile) orelse "");
} else {
const output_dir_base = try std.fmt.bufPrint(&output_dir_buf, "{s}{s}", .{ bin_label, triplet });
output_dir = try pathRel(b.allocator, b.install_prefix, output_dir_base);
}
is_debug_build = optimize == OptimizeMode.Debug;
const bun_executable_name = if (optimize == std.builtin.OptimizeMode.Debug) "bun-debug" else "bun";
const bun_executable_name = if (outfile_maybe) |outfile| std.fs.path.basename(outfile[0 .. outfile.len - std.fs.path.extension(outfile).len]) else if (is_debug_build) "bun-debug" else "bun";
const root_src = if (target.getOsTag() == std.Target.Os.Tag.freestanding)
"root_wasm.zig"
else
@@ -236,7 +286,28 @@ pub fn build_(b: *Build) !void {
.main_mod_path = .{ .cwd_relative = b.pathFromRoot(".") },
});
b.reference_trace = 16;
if (!exists(b.pathFromRoot(try std.fs.path.join(b.allocator, &.{
"src",
"js_lexer",
"id_continue_bitset.blob",
})))) {
const identifier_data = b.pathFromRoot(try std.fs.path.join(b.allocator, &.{ "src", "js_lexer", "identifier_data.zig" }));
var run_step = b.addSystemCommand(&.{
b.zig_exe,
"run",
identifier_data,
});
run_step.has_side_effects = true;
obj.step.dependOn(&run_step.step);
}
b.reference_trace = if (b.option(u32, "reference-trace", "Set the reference trace")) |trace|
if (trace == 0)
null
else
trace
else
16;
var default_build_options: BunBuildOptions = brk: {
const is_baseline = arch.isX86() and (target.cpu_model == .baseline or
@@ -247,7 +318,7 @@ pub fn build_(b: *Build) !void {
git_sha = b.allocator.dupeZ(u8, sha) catch unreachable;
} else {
sha: {
const result = std.ChildProcess.exec(.{
const result = std.ChildProcess.run(.{
.allocator = b.allocator,
.argv = &.{
"git",
@@ -262,9 +333,12 @@ pub fn build_(b: *Build) !void {
}
}
const is_canary = (std.os.getenvZ("BUN_CANARY") orelse "0")[0] == '1';
const is_canary =
b.option(bool, "canary", "Treat this as a canary build") orelse
((b.env_map.get("BUN_CANARY") orelse "0")[0] == '1');
break :brk .{
.canary = is_canary,
.version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0",
.sha = git_sha,
.baseline = is_baseline,
.bindgen = false,
@@ -299,8 +373,9 @@ pub fn build_(b: *Build) !void {
min_version,
max_version,
obj.target.getCpuModel().name,
}) catch unreachable;
std.io.getStdErr().writer().print("Output: {s}/{s}\n\n", .{ output_dir, bun_executable_name }) catch unreachable;
}) catch {};
std.io.getStdErr().writer().print("Zig {s}\n", .{@import("builtin").zig_version_string}) catch {};
// std.io.getStdErr().writer().print("Output: {s}/{s}\n\n", .{ output_dir, bun_executable_name }) catch unreachable;
defer obj_step.dependOn(&obj.step);
@@ -319,13 +394,22 @@ pub fn build_(b: *Build) !void {
obj.addOptions("build_options", actual_build_options.step(b));
obj.linkLibC();
// Generated Code
// TODO: exit with a better error early if these files do not exist. it is an indication someone ran `zig build` directly without the code generators.
obj.addModule("generated/ZigGeneratedClasses.zig", b.createModule(.{
.source_file = .{ .path = b.fmt("{s}/ZigGeneratedClasses.zig", .{generated_code_directory}) },
}));
obj.addModule("generated/ResolvedSourceTag.zig", b.createModule(.{
.source_file = .{ .path = b.fmt("{s}/ResolvedSourceTag.zig", .{generated_code_directory}) },
}));
obj.linkLibC();
obj.dll_export_fns = true;
obj.strip = false;
obj.bundle_compiler_rt = false;
obj.omit_frame_pointer = optimize != .Debug;
obj.subsystem = .Console;
// Disable stack probing on x86 so we don't need to include compiler_rt
if (target.getCpuArch().isX86()) obj.disable_stack_probing = true;
if (target.getCpuArch().isX86() or target.isWindows()) obj.disable_stack_probing = true;
if (b.option(bool, "for-editor", "Do not emit bin, just check for errors") orelse false) {
// obj.emit_bin = .no_emit;

BIN
bun.lockb

Binary file not shown.

View File

@@ -398,7 +398,7 @@ buf; // => Uint8Array(25)
compressed; // => Uint8Array(10)
```
The second argument supports the same set of configuration options as [`Bun.gzipSync`](#bun.gzipSync).
The second argument supports the same set of configuration options as [`Bun.gzipSync`](#bungzipsync).
## `Bun.inflateSync()`

View File

@@ -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");
ws.publish("the-group-chat", msg);
server.publish("the-group-chat", msg);
},
},
});

View File

@@ -207,7 +207,7 @@ After cloning a template, `bun create` will automatically remove the `"bun-creat
---
- `GITHUB_API_TOKEN`
- `GITHUB_ACCESS_TOKEN`
- This lets `bun create` work with private repositories or if you get rate-limited
{% /table %}

View File

@@ -0,0 +1,185 @@
---
name: Use Drizzle ORM with Bun
---
Drizzle is an ORM that supports both a SQL-like "query builder" API and an ORM-like [Queries API](https://orm.drizzle.team/docs/rqb). It supports the `bun:sqlite` built-in module.
---
Let's get started by creating a fresh project with `bun init` and installing Drizzle.
```sh
$ bun init -y
$ bun add drizzle-orm
$ bun add -D drizzle-kit
```
---
Then we'll connect to a SQLite database using the `bun:sqlite` module and create the Drizzle database instance.
```ts#db.ts
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Database } from "bun:sqlite";
const sqlite = new Database("sqlite.db");
export const db = drizzle(sqlite);
```
---
To see the database in action, add these lines to `index.ts`.
```ts#index.ts
import { db } from "./db";
import { sql } from "drizzle-orm";
const query = sql`select "hello world" as text`;
const result = db.get<{ text: string }>(query);
console.log(result);
```
---
Then run `index.ts` with Bun. Bun will automatically create `sqlite.db` and execute the query.
```sh
$ bun run index.ts
{
text: "hello world"
}
```
---
Lets give our database a proper schema. Create a `schema.ts` file and define a `movies` table.
```ts#schema.ts
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const movies = sqliteTable("movies", {
id: integer("id").primaryKey(),
title: text("name"),
releaseYear: integer("release_year"),
});
```
---
We can use the `drizzle-kit` CLI to generate an initial SQL migration.
```sh
$ bunx drizzle-kit generate:sqlite --schema ./schema.ts
```
---
This creates a new `drizzle` directory containing a `.sql` migration file and `meta` directory.
```txt
drizzle
├── 0000_ordinary_beyonder.sql
└── meta
├── 0000_snapshot.json
└── _journal.json
```
---
We can execute these migrations with a simple `migrate.ts` script.
This script creates a new connection to a SQLite database that writes to `sqlite.db`, then executes all unexecuted migrations in the `drizzle` directory.
```ts#migrate.ts
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Database } from "bun:sqlite";
const sqlite = new Database("sqlite.db");
const db = drizzle(sqlite);
await migrate(db, { migrationsFolder: "./drizzle" });
```
---
We can run this script with `bun` to execute the migration.
```sh
$ bun run migrate.ts
```
---
Now that we have a database, let's add some data to it. Create a `seed.ts` file with the following contents.
```ts#seed.ts
import { db } from "./db";
import * as schema from "./schema";
await db.insert(schema.movies).values([
{
title: "The Matrix",
releaseYear: 1999,
},
{
title: "The Matrix Reloaded",
releaseYear: 2003,
},
{
title: "The Matrix Revolutions",
releaseYear: 2003,
},
]);
console.log(`Seeding complete.`);
```
---
Then run this file.
```sh
$ bun run seed.ts
Seeding complete.
```
---
We finally have a database with a schema and some sample data. Let's use Drizzle to query it. Replace the contents of `index.ts` with the following.
```ts#index.ts
import * as schema from "./schema";
import { db } from "./db";
const result = await db.select().from(schema.movies);
console.log(result);
```
---
Then run the file. You should see the three movies we inserted.
```sh
$ bun run index.ts
bun run index.ts
[
{
id: 1,
title: "The Matrix",
releaseYear: 1999
}, {
id: 2,
title: "The Matrix Reloaded",
releaseYear: 2003
}, {
id: 3,
title: "The Matrix Revolutions",
releaseYear: 2003
}
]
```
---
Refer to the [Drizzle website](https://orm.drizzle.team/docs/overview) for complete documentation.

View File

@@ -0,0 +1,227 @@
---
name: Use EdgeDB with Bun
---
EdgeDB is a graph-relational database powered by Postgres under the hood. It provides a declarative schema language, migrations system, and object-oriented query language, in addition to supporting raw SQL queries. It solves the object-relational mapping problem at the database layer, eliminating the for an ORM library in your application code.
---
First, [install EdgeDB](https://www.edgedb.com/install) if you haven't already.
{% codetabs %}
```sh#Linux/macOS
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
```
```sh#Windows
$ iwr https://ps1.edgedb.com -useb | iex
```
{% /codetabs %}
---
Use `bun init` to create a fresh project.
```sh
$ mkdir my-edgedb-app
$ cd my-edgedb-app
$ bun init -y
```
---
We'll use the EdgeDB CLI to initialize an EdgeDB instance for our project. This creates an `edgedb.toml` file in our project root.
```sh
$ edgedb project init
No `edgedb.toml` found in `/Users/colinmcd94/Documents/bun/fun/examples/my-edgedb-app` or above
Do you want to initialize a new project? [Y/n]
> Y
Specify the name of EdgeDB instance to use with this project [default: my_edgedb_app]:
> my_edgedb_app
Checking EdgeDB versions...
Specify the version of EdgeDB to use with this project [default: x.y]:
> x.y
┌─────────────────────┬────────────────────────────────────────────────────────────────────────┐
│ Project directory │ /Users/colinmcd94/Documents/bun/fun/examples/my-edgedb-app │
│ Project config │ /Users/colinmcd94/Documents/bun/fun/examples/my-edgedb-app/edgedb.toml │
│ Schema dir (empty) │ /Users/colinmcd94/Documents/bun/fun/examples/my-edgedb-app/dbschema │
│ Installation method │ portable package │
│ Version │ x.y+6d5921b │
│ Instance name │ my_edgedb_app │
└─────────────────────┴────────────────────────────────────────────────────────────────────────┘
Version x.y+6d5921b is already downloaded
Initializing EdgeDB instance...
Applying migrations...
Everything is up to date. Revision initial
Project initialized.
To connect to my_edgedb_app, run `edgedb`
```
---
To see if the database is running, let's open a REPL and run a simple query.
Then run `\quit` to exit the REPL.
```sh
$ edgedb
edgedb> select 1 + 1;
2
edgedb> \quit
```
---
With the project initialized, we can define a schema. The `edgedb project init` command already created a `dbschema/default.esdl` file to contain our schema.
```txt
dbschema
├── default.esdl
└── migrations
```
---
Open that file and paste the following contents.
```txt
module default {
type Movie {
title: str;
releaseYear: int64;
}
};
```
---
Then generate and apply an initial migration.
```sh
$ edgedb migration create
Created /Users/colinmcd94/Documents/bun/fun/examples/my-edgedb-app/dbschema/migrations/00001.edgeql, id: m1uwekrn4ni4qs7ul7hfar4xemm5kkxlpswolcoyqj3xdhweomwjrq
$ edgedb migrate
Applied m1uwekrn4ni4qs7ul7hfar4xemm5kkxlpswolcoyqj3xdhweomwjrq (00001.edgeql)
```
---
With out schema applied, let's execute some queries using EdgeDB's JavaScript client library. We'll install the client library and EdgeDB's codegen CLI, and create a `seed.ts`.file.
```sh
$ bun add edgedb
$ bun add -D @edgedb/generate
$ touch seed.ts
```
---
Paste the following code into `seed.ts`.
The client auto-connects to the database. We insert a couple movies using the `.execute()` method.
```ts
import { createClient } from "edgedb";
const client = createClient();
const INSERT_MOVIE = `
insert Movie {
title := <str>$title,
releaseYear := <int64>$year,
}
`;
const movies = [
{ title: "The Matrix", year: 1999 },
{ title: "The Matrix Reloaded", year: 2003 },
{ title: "The Matrix Revolutions", year: 2003 },
];
for (const movie of movies) {
await client.execute(INSERT_MOVIE, movie);
}
console.log(`Seeding complete.`);
process.exit();
```
---
Then run this file with Bun.
```sh
$ bun run seed.ts
Seeding complete.
```
---
EdgeDB implements a number of code generation tools for TypeScript. To query our newly seeded database in a typesafe way, we'll use `@edgedb/generate` to code-generate the EdgeQL query builder.
```sh
$ bunx @edgedb/generate edgeql-js
Generating query builder...
Detected tsconfig.json, generating TypeScript files.
To override this, use the --target flag.
Run `npx @edgedb/generate --help` for full options.
Introspecting database schema...
Writing files to ./dbschema/edgeql-js
Generation complete! 🤘
Checking the generated query builder into version control
is not recommended. Would you like to update .gitignore to ignore
the query builder directory? The following line will be added:
dbschema/edgeql-js
[y/n] (leave blank for "y")
> y
```
---
In `index.ts`, we can import the generated query builder from `./dbschema/edgeql-js` and write a simple select query.
```ts
import { createClient } from "edgedb";
import e from "./dbschema/edgeql-js";
const client = createClient();
const query = e.select(e.Movie, () => ({
title: true,
releaseYear: true,
}));
const results = await query.run(client);
console.log(results);
results; // { title: string, releaseYear: number | null }[]
```
---
Running the file with Bun, we can see the list of movies we inserted.
```sh
$ bun run index.ts
[
{
title: "The Matrix",
releaseYear: 1999
}, {
title: "The Matrix Reloaded",
releaseYear: 2003
}, {
title: "The Matrix Revolutions",
releaseYear: 2003
}
]
```
---
For complete documentation, refer to the [EdgeDB docs](https://www.edgedb.com/docs).

View File

@@ -1,5 +1,5 @@
---
name: Get started using Prisma
name: Use Prisma with Bun
---
{% callout %}

View File

@@ -4,7 +4,7 @@ name: Use React and JSX
React just works with Bun. Bun supports `.jsx` and `.tsx` files out of the box.
Remember that JSX is just a special syntax for including HTML-like syntax in JavaScript files. It's commonReact uses JSX syntax, as do other React alternatives like [Preact](https://preactjs.com/) and [Solid](https://www.solidjs.com/). Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
Remember that JSX is just a special syntax for including HTML-like syntax in JavaScript files. React uses JSX syntax, as do alternatives like [Preact](https://preactjs.com/) and [Solid](https://www.solidjs.com/). Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
---
@@ -27,7 +27,7 @@ const element = jsx("h1", { children: "Hello, world!" });
---
This code requires `react` to run, so make sure you you've installed React.
This code requires `react` to run, so make sure you've installed React.
```bash
$ bun install react

View File

@@ -20,7 +20,7 @@ test("party like it's 1999", () => {
---
The `setSystemTime` function is commonly used on conjunction with [Lifecycle Hooks](/docs/test/lifecycle) to configure a testing environment with a determinstic "fake clock".
The `setSystemTime` function is commonly used on conjunction with [Lifecycle Hooks](/docs/test/lifecycle) to configure a testing environment with a deterministic "fake clock".
```ts
import { test, expect, beforeAll, setSystemTime } from "bun:test";

View File

@@ -2,7 +2,7 @@
name: Get the file name of the current file
---
Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.file` to retreive the name of the current file.
Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.file` to retrieve the name of the current file.
```ts#/a/b/c.ts
import.meta.file; // => "c.ts"

View File

@@ -2,7 +2,7 @@
name: Get the absolute path of the current file
---
Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.path` to retreive the absolute path of the current file.
Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.path` to retrieve the absolute path of the current file.
```ts#/a/b/c.ts
import.meta.path; // => "/a/b/c.ts"

View File

@@ -28,7 +28,7 @@ const server = Bun.serve<{ username: string }>({
},
close(ws) {
const msg = `${ws.data.username} has left the chat`;
ws.publish("the-group-chat", msg);
server.publish("the-group-chat", msg);
ws.unsubscribe("the-group-chat");
},
},

View File

@@ -32,7 +32,7 @@ node_modules
└── bar@4.5.6
```
But what if a security vulnerability was introduced in `bar@4.5.6`? We may want a way to pin `bar` to an older version that doesn't have the vulerability. This is where `"overrides"`/`"resolutions"` come in.
But what if a security vulnerability was introduced in `bar@4.5.6`? We may want a way to pin `bar` to an older version that doesn't have the vulnerability. This is where `"overrides"`/`"resolutions"` come in.
## `"overrides"`

View File

@@ -24,7 +24,7 @@ tree
   └── 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`.
In the root `package.json`, the `"workspaces"` key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It's conventional to place all the workspace in a directory called `packages`.
```json
{

View File

@@ -0,0 +1,61 @@
## Prerequisites
### System Dependencies
- [Visual Studio](https://visualstudio.microsoft.com) with the "Desktop development with C++" workload. You should install Git and CMake from here, if not already installed.
- Ninja
- Go
- Rust
- NASM
- Perl
- Do not use Strawberry Perl, it includes tools from MSys2 which will break your build.
- Ruby
### Zig
Bun pins a version of Zig. As the compiler is still in development, breaking changes happen often that will break the build. It is recommended to use [Zigup](https://github.com/marler8997/zigup/releases) as it can quickly switch to any version by name, but you can also [manually download Zig](https://ziglang.org/download/).
```bash
$ zigup 0.12.0-dev.1297+a9e66ed73
```
{% callout %}
We last updated Zig on **October 26th, 2023**
{% /callout %}
### Codegen
On Unix platforms, we depend on an existing build of Bun to generate code for itself. Since the Windows branch is not stable enough for this to pass, you currently need to generate the code.
On a system with Bun installed, run:
```bash
$ bash ./scripts/cross-compile-codegen.sh win32 x64
# -> build-codegen-win32-x64
```
Copy the contents of this to the Windows machine into a folder named `build`
TODO: Use WSL to automatically run codegen without a separate machine.
## Building
```ps1
npm install
.\scripts\env.ps1
.\scripts\update-submodules.ps1
.\scripts\all-dependencies.ps1
cd build # this was created by the codegen script in the prerequisites
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug
ninja
```
If this was successful, you should have a `bun-debug.exe` in the `build` folder.
```ps1
.\bun-debug.exe --version
```

View File

@@ -2,7 +2,7 @@ Configuring a development environment for Bun can take 10-30 minutes depending o
If you are using Windows, you must use a WSL environment as Bun does not yet compile on Windows natively.
Before starting, you will need to already have a release build of Bun installed, as we use our bundler to transpile and minify our code.
Before starting, you will need to already have a release build of Bun installed, as we use our bundler to transpile and minify our code, as well as for code generation scripts.
{% codetabs %}
@@ -72,16 +72,11 @@ If not, run this to manually link it:
```bash#macOS (Homebrew)
# use fish_add_path if you're using fish
$ export PATH="$PATH:$(brew --prefix llvm@16)/bin"
$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@16)/lib"
$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@16)/include"
```
```bash#Arch
# use fish_add_path if you're using fish
$ export PATH="$PATH:/usr/lib/llvm16/bin"
$ export LDFLAGS="$LDFLAGS -L/usr/lib/llvm16/lib"
$ export CPPFLAGS="$CPPFLAGS -I/usr/lib/llvm16/include"
```
{% /codetabs %}
@@ -93,225 +88,79 @@ Using your system's package manager, install the rest of Bun's dependencies:
{% codetabs %}
```bash#macOS (Homebrew)
$ brew install automake ccache cmake coreutils esbuild gnu-sed go libiconv libtool ninja pkg-config rust
$ brew install automake ccache cmake coreutils gnu-sed go libiconv libtool ninja pkg-config rust
```
```bash#Ubuntu/Debian
$ sudo apt install cargo ccache cmake git golang libtool ninja-build pkg-config rustc esbuild
$ sudo apt install cargo ccache cmake git golang libtool ninja-build pkg-config rustc ruby-full
```
```bash#Arch
$ sudo pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
$ sudo pacman -S base-devel ccache cmake git go libiconv libtool make ninja pkg-config python rust sed unzip ruby
```
```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
$ sudo dnf install cargo ccache cmake git golang libtool ninja-build pkg-config rustc libatomic-static libstdc++-static sed unzip
```
{% /codetabs %}
{% details summary="Ubuntu — Unable to locate package esbuild" %}
The `apt install esbuild` command may fail with an `Unable to locate package` error if you are using a Ubuntu mirror that does not contain an exact copy of the original Ubuntu server. Note that the same error may occur if you are not using any mirror but have the Ubuntu Universe enabled in the `sources.list`. In this case, you can install esbuild manually:
```bash
$ curl -fsSL https://esbuild.github.io/dl/latest | sh
$ chmod +x ./esbuild
$ sudo mv ./esbuild /usr/local/bin
```
{% /details %}
In addition to this, you will need an npm package manager (`bun`, `npm`, etc) to install the `package.json` dependencies.
## Install Zig
Zig can be installed either with our npm package [`@oven/zig`](https://www.npmjs.com/package/@oven/zig), or by using [zigup](https://github.com/marler8997/zigup).
```bash
$ bun install -g @oven/zig
$ zigup 0.12.0-dev.899+027aabf49
$ zigup 0.12.0-dev.1297+a9e66ed73
```
{% callout %}
We last updated Zig on **October 12th, 2023**
We last updated Zig on **October 26th, 2023**
{% /callout %}
## First Build
## Building Bun
After cloning the repository, run the following command to run the first build. This may take a while as it will clone submodules and build dependencies.
```bash
$ make setup
$ bun setup
```
The binary will be located at `packages/debug-bun-{platform}-{arch}/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, let's print the version number on the development build of Bun.
The binary will be located at `./build/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, let's print the version number on the development build of Bun.
```bash
$ packages/debug-bun-*/bun-debug --version
bun 1.x.y__dev
$ build/bun-debug --version
x.y.z_debug
```
Note: `make setup` is just an alias for the following:
To rebuild, you can invoke `bun run build`
```bash
$ make assert-deps submodule npm-install-dev node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml sqlite usockets uws tinycc c-ares zstd base64 cpp zig link
$ bun run build
```
## Rebuilding
These two scripts, `setup` and `build`, are aliases to do roughly the following:
Bun uses a series of make commands to rebuild parts of the codebase. The general rule for rebuilding is there is `make link` to rerun the linker, and then different make targets for different parts of the codebase. Do not pass `-j` to make as these scripts will break if run out of order, and multiple cores will be used when possible during the builds.
```bash
$ ./scripts/setup.sh
$ cmake -S . -G Ninja -B build -DCMAKE_BUILD_TYPE=Debug
$ ninja -C build # 'bun run build' runs just this
```
{% table %}
- What changed
- Run this command
---
- Zig Code
- `make zig`
---
- C++ Code
- `make cpp`
---
- Zig + C++ Code
- `make dev` (combination of the above two)
---
- JS/TS Code in `src/js`
- `make js` (in bun-debug, js is loaded from disk without a recompile). If you change the names of any file or add/remove anything, you must also run `make dev`.
---
- `*.classes.ts`
- `make generate-classes dev`
---
- JSSink
- `make generate-sink cpp`
---
- `src/node_fallbacks/*`
- `make node-fallbacks zig`
---
- `identifier_data.zig`
- `make identifier-cache zig`
---
- Code using `cppFn`/`JSC.markBinding`
- `make headers` (TODO: explain what this is used for and why it's useful)
{% /table %}
`make setup` cloned a bunch of submodules and built the subprojects. When a submodule is out of date, run `make submodule` to quickly reset/update all your submodules, then you can rebuild individual submodules with their respective command.
{% table %}
- Dependency
- Run this command
---
- WebKit
- `bun install` (it is a prebuilt package)
---
- uWebSockets
- `make uws`
---
- Mimalloc
- `make mimalloc`
---
- PicoHTTPParser
- `make picohttp`
---
- zlib
- `make zlib`
---
- BoringSSL
- `make boringssl`
---
- libarchive
- `make libarchive`
---
- lolhtml
- `make lolhtml`
---
- sqlite
- `make sqlite`
---
- TinyCC
- `make tinycc`
---
- c-ares
- `make c-ares`
---
- zstd
- `make zstd`
---
- Base64
- `make base64`
{% /table %}
The above will probably also need Zig and/or C++ code rebuilt.
Advanced uses can pass CMake flags to customize the build.
## VSCode
VSCode is the recommended IDE for working on Bun, as it has been configured. Once opening, you can run `Extensions: Show Recommended Extensions` to install the recommended extensions for Zig and C++. ZLS is automatically configured.
## JavaScript builtins
When you change anything in `src/js/builtins/*` or switch branches, run this:
```bash
$ make js cpp
```
That inlines the TypeScript code into C++ headers.
## Code generation scripts
{% callout %}
Make sure you have `ccache` installed, otherwise regeneration will take much longer than it should.
**Note**: This section is outdated. The code generators are run automatically by ninja, instead of by `make`.
{% /callout %}
For more information on how `src/js` works, see `src/js/README.md` in the codebase.
## Code generation scripts
Bun leverages a lot of code generation scripts.
The [./src/bun.js/bindings/headers.h](https://github.com/oven-sh/bun/blob/main/src/bun.js/bindings/headers.h) file has bindings to & from Zig <> C++ code. This file is generated by running the following:
@@ -344,26 +193,17 @@ You probably won't need to run that one much.
## Modifying ESM modules
Certain modules like `node:fs`, `node:stream`, `bun:sqlite`, and `ws` are implemented in JavaScript. These live in `src/js/{node,bun,thirdparty}` files and are pre-bundled using Bun. The bundled code is committed so CI builds can run without needing a copy of Bun.
When these are changed, run:
```
$ make js
```
In debug builds, Bun automatically loads these from the filesystem, wherever it was compiled, so no need to re-run `make dev`.
Certain modules like `node:fs`, `node:stream`, `bun:sqlite`, and `ws` are implemented in JavaScript. These live in `src/js/{node,bun,thirdparty}` files and are pre-bundled using Bun. In debug builds, Bun automatically loads these from the filesystem, wherever it was compiled, so no need to re-run `make dev`.
## Release build
To build a release build of Bun, run:
```bash
$ make release-bindings -j12
$ make release
$ bun run build:release
```
The binary will be located at `packages/bun-{platform}-{arch}/bun`.
The binary will be located at `./build-release/bun` and `./build-release/bun-profile`.
## Valgrind
@@ -383,17 +223,14 @@ You'll need a very recent version of Valgrind due to DWARF 5 debug symbols. You
$ 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.
```bash
$ bun install
$ make cpp
```
## Building WebKit locally + Debug mode of JSC
{% callout %}
**TODO**: This is out of date. TLDR is pass `-DUSE_DEBUG_JSC=1` or `-DWEBKIT_DIR=...` to CMake. it will probably need more fiddling. ask @paperdave if you need this.
{% /callout %}
WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:
```bash
@@ -455,29 +292,6 @@ If you see an error when compiling `libarchive`, run this:
$ brew install pkg-config
```
### missing files on `zig build obj`
If you see an error about missing files on `zig build obj`, make sure you built the headers.
```bash
$ make headers
```
### cmakeconfig.h not found
If you see an error about `cmakeconfig.h` not being found, this is because the precompiled WebKit did not install properly.
```bash
$ bun install
```
Check to see the command installed webkit, and you can manually look for `node_modules/bun-webkit-{platform}-{arch}`:
```bash
# this should reveal two directories. if not, something went wrong
$ echo node_modules/bun-webkit*
```
### macOS `library not found for -lSystem`
If you see this error when compiling, run:
@@ -494,4 +308,4 @@ Bun requires `libatomic` to be statically linked. On Arch Linux, it is only give
$ sudo ln -s /lib/libatomic.so /lib/libatomic.a
```
The built version of bun may not work on other systems if compiled this way.
The built version of Bun may not work on other systems if compiled this way.

View File

@@ -0,0 +1,75 @@
There are four parts to the CI build:
- Dependencies: should be cached across builds as much as possible, it depends on git submodule hashes
- Zig Object: depends on \*.zig and potentially src/js
- C++ Object: depends on \*.cpp and src/js
- Linking: depends on the above three
Utilizing multiple GitHub Action runners allows us to do a lot of work in parallel.
## Dependencies
```sh
BUN_DEPS_OUT_DIR="/optional/out/dir" bash ./scripts/all-dependencies.sh
```
## Zig Object
This does not have a dependency on WebKit or any of the dependencies at all. It can be compiled without checking out submodules, but you will need to have bun install run. It can be very easily cross compiled.
```sh
BUN_REPO=/path/to/oven-sh/bun
cd tmp1
cmake $BUN_REPO \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCPU_TARGET="native" \
-DZIG_TARGET="native" \
-DBUN_ZIG_OBJ="./bun-zig.o"
ninja ./bun-zig.o
# -> bun-zig.o
```
## C++ Object
Note: if WEBKIT_DIR is not passed, it is automatically downloaded from GitHub releases. This depends on the headers from submodules but not necessarily the build copies of them, .a files, etc.
```sh
cd tmp2
cmake $BUN_REPO \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_CPP_ONLY=1 \
bash compile-cpp-only.sh
# -> bun-cpp-objects.a
```
## Linking
The goal is you run both stages from above on different machines, so that they can build in parallel. Zig build is slow, and MacOS build runners are slower on average than the linux ones. With both artifacts from above, you can link them together:
```sh
cd tmp3
cmake $BUN_REPO \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUN_LINK_ONLY=1 \
-DBUN_ZIG_OBJ="/path/to/bun-zig.o" \
-DBUN_CPP_ARCHIVE="/path/to/bun-cpp-objects.a"
ninja
# optiona:
# -DBUN_DEPS_OUT_DIR=... custom deps dir, use this to cache the built deps between rebuilds
# -DWEBKIT_DIR=... same thing, but it's probably fast enough to pull from github releases
# -> bun
# -> bun-profile
# -> bun.dSYM/
```

View File

@@ -156,7 +156,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 experimental VM ES modules are not implemented, including `vm.Module`, `vm.SourceTextModule`, `vm.SyntheticModule`,`importModuleDynamically`, and `vm.measureMemory`. Options like `timeout`, `breakOnSigint`, `cachedData` are not implemented yet. There is a bug with `this` value for contextified options not having the correct prototype.
### [`node:wasi`](https://nodejs.org/api/wasi.html)

View File

@@ -221,7 +221,7 @@ console.log(mySvelteComponent.render());
{% 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`.
This feature is currently only available at runtime with `Bun.plugin` and not yet supported in the bundler, but you can mimic the behavior using `onResolve` and `onLoad`.
{% /note %}

View File

@@ -27,7 +27,7 @@ pub fn main() anyerror!void {
var args = std.mem.bytesAsSlice([]u8, try std.process.argsAlloc(allocator));
const to_resolve = args[args.len - 1];
const cwd = try std.process.getCwdAlloc(allocator);
const cwd = try bun.getcwdAlloc(allocator);
var path: []u8 = undefined;
var out_buffer: [bun.MAX_PATH_BYTES]u8 = undefined;

View File

@@ -47,7 +47,7 @@ pub fn main() anyerror!void {
bun.asByteSlice(args[args.len - 1]),
};
const tarball_path = path_handler.joinAbsStringBuf(try std.process.getCwdAlloc(std.heap.c_allocator), &tarball_path_buf, &parts, .auto);
const tarball_path = path_handler.joinAbsStringBuf(try bun.getcwdAlloc(std.heap.c_allocator), &tarball_path_buf, &parts, .auto);
Output.prettyErrorln("Tarball Path: {s}", .{tarball_path});
var folder = basename;

View File

@@ -15,9 +15,9 @@
},
"private": true,
"scripts": {
"build-runtime": "esbuild --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js",
"build-fallback": "esbuild --target=esnext --bundle src/fallback.ts --format=iife --platform=browser --minify > src/fallback.out.js",
"postinstall": "bash .scripts/postinstall.sh",
"setup": "./scripts/setup.sh",
"build": "if [ ! -e build ]; then bun setup; fi && ninja -C build",
"build:release": "cmake . -DCMAKE_BUILD_TYPE=Release -GNinja -Bbuild-release && ninja -Cbuild-release",
"typecheck": "tsc --noEmit && cd test && bun run typecheck",
"fmt": "prettier --write --cache './{src,test,bench,packages/{bun-types,bun-inspector-*,bun-vscode,bun-debug-adapter-protocol}}/**/*.{mjs,ts,tsx,js,jsx}'",
"lint": "eslint './**/*.d.ts' --cache",
@@ -26,8 +26,7 @@
"devDependencies": {
"@types/react": "^18.0.25",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
"bun-webkit": "0.0.1-1a49a1f94bf42ab4f8c6b11d7bbbb21e491d2d62"
"@typescript-eslint/parser": "^5.31.0"
},
"version": "0.0.0",
"prettier": "./.prettierrc.cjs"

View File

@@ -27,6 +27,38 @@ declare module "bun:test" {
export const mock: {
<T extends AnyFunction>(Function: T): Mock<T>;
/**
* Replace the module `id` with the return value of `factory`.
*
* This is useful for mocking modules.
*
* @param id module ID to mock
* @param factory a function returning an object that will be used as the exports of the mocked module
*
* @example
* ## Example
* ```ts
* import { mock } from "bun:test";
*
* mock.module("fs/promises", () => {
* return {
* readFile: () => Promise.resolve("hello world"),
* };
* });
*
* import { readFile } from "fs/promises";
*
* console.log(await readFile("hello.txt", "utf8")); // hello world
* ```
*
* ## More notes
*
* If the module is already loaded, exports are overwritten with the return
* value of `factory`. If the export didn't exist before, it will not be
* added to existing import statements. This is due to how ESM works.
*/
module(id: string, factory: () => any): void | Promise<void>;
};
/**

View File

@@ -4077,7 +4077,7 @@ declare module "bun" {
* Spawn a new process
*
* ```js
* const {stdout} = Bun.spawn(["echo", "hello"]));
* const {stdout} = Bun.spawn(["echo", "hello"]);
* const text = await readableStreamToText(stdout);
* console.log(text); // "hello\n"
* ```
@@ -4139,7 +4139,7 @@ declare module "bun" {
* Synchronously spawn a new process
*
* ```js
* const {stdout} = Bun.spawnSync(["echo", "hello"]));
* const {stdout} = Bun.spawnSync(["echo", "hello"]);
* console.log(stdout.toString()); // "hello\n"
* ```
*

View File

@@ -235,7 +235,10 @@ declare namespace NodeJS {
interface Require {
(id: string): any;
resolve: RequireResolve;
cache: Record<string, NodeModule>;
main: NodeModule | undefined;
}
interface ProcessEnv {}
type Signals =
| "SIGABRT"
@@ -2394,6 +2397,12 @@ declare var WebSocket: {
* Sets the sub-protocols the client is willing to accept.
*/
protocols?: string[];
/**
* Override the default TLS options
*/
tls?: {
rejectUnauthorized?: boolean | undefined; // Defaults to true
};
},
): WebSocket;

View File

@@ -397,6 +397,32 @@ int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
return recv(fd, buf, length, flags);
}
#if !defined(_WIN32)
#include <sys/uio.h>
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
struct iovec chunks[2];
chunks[0].iov_base = (char *)header;
chunks[0].iov_len = header_length;
chunks[1].iov_base = (char *)payload;
chunks[1].iov_len = payload_length;
return writev(fd, chunks, 2);
}
#else
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
int written = bsd_send(fd, header, header_length, 0);
if (written == header_length) {
int second_write = bsd_send(fd, payload, payload_length, 0);
if (second_write > 0) {
written += second_write;
}
}
return written;
}
#endif
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more) {
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)

View File

@@ -566,10 +566,10 @@ void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) {
}
void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_context_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data) {
void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data) {
#ifndef LIBUS_NO_SSL
if (ssl) {
us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data))on_handshake, custom_data);
us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, (us_internal_on_handshake_t)on_handshake, custom_data);
return;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
// MSVC doesn't support C11 stdatomic.h propertly yet.
// so we use C++ std::atomic instead.
#include "./internal/internal.h"
#include "./root_certs.h"
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <atomic>
static const int root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]);
static X509* root_cert_instances[sizeof(root_certs) / sizeof(root_certs[0])] = {NULL};
static std::atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT;
static std::atomic_bool root_cert_instances_initialized = 0;
// This callback is used to avoid the default passphrase callback in OpenSSL
// which will typically prompt for the passphrase. The prompting is designed
// for the OpenSSL CLI, but works poorly for this case because it involves
// synchronous interaction with the controlling terminal, something we never
// want, and use this function to avoid it.
int us_no_password_callback(char* buf, int size, int rwflag, void* u) {
return 0;
}
static X509 * us_ssl_ctx_get_X509_without_callback_from(struct us_cert_string_t content) {
X509 *x = NULL;
BIO *in;
ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()
in = BIO_new_mem_buf(content.str, content.len);
if (in == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
goto end;
}
x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL);
if (x == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
goto end;
}
return x;
end:
X509_free(x);
BIO_free(in);
return NULL;
}
static void us_internal_init_root_certs() {
if(std::atomic_load(&root_cert_instances_initialized) == 1) return;
while(atomic_flag_test_and_set_explicit(&root_cert_instances_lock, std::memory_order_acquire));
if(!atomic_exchange(&root_cert_instances_initialized, 1)) {
for (size_t i = 0; i < root_certs_size; i++) {
root_cert_instances[i] = us_ssl_ctx_get_X509_without_callback_from(root_certs[i]);
}
}
atomic_flag_clear_explicit(&root_cert_instances_lock, std::memory_order_release);
}
extern "C" int us_internal_raw_root_certs(struct us_cert_string_t** out) {
*out = root_certs;
return root_certs_size;
}
extern "C" X509_STORE* us_get_default_ca_store() {
X509_STORE *store = X509_STORE_new();
if (store == NULL) {
return NULL;
}
if (!X509_STORE_set_default_paths(store)) {
X509_STORE_free(store);
return NULL;
}
us_internal_init_root_certs();
// load all root_cert_instances on the default ca store
for (size_t i = 0; i < root_certs_size; i++) {
X509* cert = root_cert_instances[i];
if(cert == NULL) continue;
X509_up_ref(cert);
X509_STORE_add_cert(store, cert);
}
return store;
}

View File

@@ -35,8 +35,8 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void*);
/* Pointer tags are used to indicate a Bun pointer versus a uSockets pointer */
#define UNSET_BITS_49_UNTIL_64 0x0000FFFFFFFFFFFF
#define CLEAR_POINTER_TAG(p) ((void *) ((uintptr_t) (p) & UNSET_BITS_49_UNTIL_64))
#define LIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 1)
#define UNLIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 0)
#define LIKELY(cond) __builtin_expect((_Bool)(cond), 1)
#define UNLIKELY(cond) __builtin_expect((_Bool)(cond), 0)
#ifdef LIBUS_USE_EPOLL
#define GET_READY_POLL(loop, index) (struct us_poll_t *) loop->ready_polls[index].data.ptr

View File

@@ -0,0 +1,330 @@
/*
* Authored by Alex Hultman, 2018-2021.
* Intellectual property of third-party.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "internal/internal.h"
#include "libusockets.h"
#include <stdlib.h>
#ifdef LIBUS_USE_LIBUV
/* uv_poll_t->data always (except for most times after calling us_poll_stop)
* points to the us_poll_t */
static void poll_cb(uv_poll_t *p, int status, int events) {
us_internal_dispatch_ready_poll((struct us_poll_t *)p->data, status < 0,
events);
}
static void prepare_cb(uv_prepare_t *p) {
struct us_loop_t *loop = p->data;
us_internal_loop_pre(loop);
}
/* Note: libuv timers execute AFTER the post callback */
static void check_cb(uv_check_t *p) {
struct us_loop_t *loop = p->data;
us_internal_loop_post(loop);
}
/* Not used for polls, since polls need two frees */
static void close_cb_free(uv_handle_t *h) { free(h->data); }
/* This one is different for polls, since we need two frees here */
static void close_cb_free_poll(uv_handle_t *h) {
/* It is only in case we called us_poll_stop then quickly us_poll_free that we
* enter this. Most of the time, actual freeing is done by us_poll_free. */
if (h->data) {
free(h->data);
free(h);
}
}
static void timer_cb(uv_timer_t *t) {
struct us_internal_callback_t *cb = t->data;
cb->cb(cb);
}
static void async_cb(uv_async_t *a) {
struct us_internal_callback_t *cb = a->data;
// internal asyncs give their loop, not themselves
cb->cb((struct us_internal_callback_t *)cb->loop);
}
// poll
void us_poll_init(struct us_poll_t *p, LIBUS_SOCKET_DESCRIPTOR fd,
int poll_type) {
p->poll_type = poll_type;
p->fd = fd;
}
void us_poll_free(struct us_poll_t *p, struct us_loop_t *loop) {
/* The idea here is like so; in us_poll_stop we call uv_close after setting
* data of uv-poll to 0. This means that in close_cb_free we call free on 0
* with does nothing, since us_poll_stop should not really free the poll.
* HOWEVER, if we then call us_poll_free while still closing the uv-poll, we
* simply change back the data to point to our structure so that we actually
* do free it like we should. */
if (uv_is_closing((uv_handle_t *)p->uv_p)) {
p->uv_p->data = p;
} else {
free(p->uv_p);
free(p);
}
}
void us_poll_start(struct us_poll_t *p, struct us_loop_t *loop, int events) {
p->poll_type = us_internal_poll_type(p) |
((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) |
((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
uv_poll_init_socket(loop->uv_loop, p->uv_p, p->fd);
uv_poll_start(p->uv_p, events, poll_cb);
}
void us_poll_change(struct us_poll_t *p, struct us_loop_t *loop, int events) {
if (us_poll_events(p) != events) {
p->poll_type =
us_internal_poll_type(p) |
((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0) |
((events & LIBUS_SOCKET_WRITABLE) ? POLL_TYPE_POLLING_OUT : 0);
uv_poll_start(p->uv_p, events, poll_cb);
}
}
void us_poll_stop(struct us_poll_t *p, struct us_loop_t *loop) {
uv_poll_stop(p->uv_p);
/* We normally only want to close the poll here, not free it. But if we stop
* it, then quickly "free" it with us_poll_free, we postpone the actual
* freeing to close_cb_free_poll whenever it triggers. That's why we set data
* to null here, so that us_poll_free can reset it if needed */
p->uv_p->data = 0;
uv_close((uv_handle_t *)p->uv_p, close_cb_free_poll);
}
int us_poll_events(struct us_poll_t *p) {
return ((p->poll_type & POLL_TYPE_POLLING_IN) ? LIBUS_SOCKET_READABLE : 0) |
((p->poll_type & POLL_TYPE_POLLING_OUT) ? LIBUS_SOCKET_WRITABLE : 0);
}
unsigned int us_internal_accept_poll_event(struct us_poll_t *p) { return 0; }
int us_internal_poll_type(struct us_poll_t *p) { return p->poll_type & 3; }
void us_internal_poll_set_type(struct us_poll_t *p, int poll_type) {
p->poll_type = poll_type | (p->poll_type & 12);
}
LIBUS_SOCKET_DESCRIPTOR us_poll_fd(struct us_poll_t *p) { return p->fd; }
void us_loop_pump(struct us_loop_t *loop) {
uv_run(loop->uv_loop, UV_RUN_NOWAIT);
}
struct us_loop_t *us_create_loop(void *hint,
void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop),
void (*post_cb)(struct us_loop_t *loop),
unsigned int ext_size) {
struct us_loop_t *loop =
(struct us_loop_t *)malloc(sizeof(struct us_loop_t) + ext_size);
loop->uv_loop = hint ? hint : uv_loop_new();
loop->is_default = hint != 0;
loop->uv_pre = malloc(sizeof(uv_prepare_t));
uv_prepare_init(loop->uv_loop, loop->uv_pre);
uv_prepare_start(loop->uv_pre, prepare_cb);
uv_unref((uv_handle_t *)loop->uv_pre);
loop->uv_pre->data = loop;
loop->uv_check = malloc(sizeof(uv_check_t));
uv_check_init(loop->uv_loop, loop->uv_check);
uv_unref((uv_handle_t *)loop->uv_check);
uv_check_start(loop->uv_check, check_cb);
loop->uv_check->data = loop;
// here we create two unreffed handles - timer and async
us_internal_loop_data_init(loop, wakeup_cb, pre_cb, post_cb);
// if we do not own this loop, we need to integrate and set up timer
if (hint) {
us_loop_integrate(loop);
}
return loop;
}
// based on if this was default loop or not
void us_loop_free(struct us_loop_t *loop) {
// ref and close down prepare and check
uv_ref((uv_handle_t *)loop->uv_pre);
uv_prepare_stop(loop->uv_pre);
loop->uv_pre->data = loop->uv_pre;
uv_close((uv_handle_t *)loop->uv_pre, close_cb_free);
uv_ref((uv_handle_t *)loop->uv_check);
uv_check_stop(loop->uv_check);
loop->uv_check->data = loop->uv_check;
uv_close((uv_handle_t *)loop->uv_check, close_cb_free);
us_internal_loop_data_free(loop);
// we need to run the loop one last round to call all close callbacks
// we cannot do this if we do not own the loop, default
if (!loop->is_default) {
uv_run(loop->uv_loop, UV_RUN_NOWAIT);
uv_loop_delete(loop->uv_loop);
}
// now we can free our part
free(loop);
}
void us_loop_run(struct us_loop_t *loop) {
us_loop_integrate(loop);
uv_run(loop->uv_loop, UV_RUN_NOWAIT);
}
struct us_poll_t *us_create_poll(struct us_loop_t *loop, int fallthrough,
unsigned int ext_size) {
struct us_poll_t *p =
(struct us_poll_t *)malloc(sizeof(struct us_poll_t) + ext_size);
p->uv_p = malloc(sizeof(uv_poll_t));
p->uv_p->data = p;
return p;
}
/* If we update our block position we have to updarte the uv_poll data to point
* to us */
struct us_poll_t *us_poll_resize(struct us_poll_t *p, struct us_loop_t *loop,
unsigned int ext_size) {
struct us_poll_t *new_p = realloc(p, sizeof(struct us_poll_t) + ext_size);
new_p->uv_p->data = new_p;
return new_p;
}
// timer
struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough,
unsigned int ext_size) {
struct us_internal_callback_t *cb = malloc(
sizeof(struct us_internal_callback_t) + sizeof(uv_timer_t) + ext_size);
cb->loop = loop;
cb->cb_expects_the_loop = 0; // never read?
cb->leave_poll_ready = 0; // never read?
uv_timer_t *uv_timer = (uv_timer_t *)(cb + 1);
uv_timer_init(loop->uv_loop, uv_timer);
uv_timer->data = cb;
if (fallthrough) {
uv_unref((uv_handle_t *)uv_timer);
}
return (struct us_timer_t *)cb;
}
void *us_timer_ext(struct us_timer_t *timer) {
return ((char *)timer) + sizeof(struct us_internal_callback_t) +
sizeof(uv_timer_t);
}
void us_timer_close(struct us_timer_t *t) {
struct us_internal_callback_t *cb = (struct us_internal_callback_t *)t;
uv_timer_t *uv_timer = (uv_timer_t *)(cb + 1);
// always ref the timer before closing it
uv_ref((uv_handle_t *)uv_timer);
uv_timer_stop(uv_timer);
uv_timer->data = cb;
uv_close((uv_handle_t *)uv_timer, close_cb_free);
}
void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t),
int ms, int repeat_ms) {
struct us_internal_callback_t *internal_cb =
(struct us_internal_callback_t *)t;
internal_cb->cb = (void (*)(struct us_internal_callback_t *))cb;
uv_timer_t *uv_timer = (uv_timer_t *)(internal_cb + 1);
if (!ms) {
uv_timer_stop(uv_timer);
} else {
uv_timer_start(uv_timer, timer_cb, ms, repeat_ms);
}
}
struct us_loop_t *us_timer_loop(struct us_timer_t *t) {
struct us_internal_callback_t *internal_cb =
(struct us_internal_callback_t *)t;
return internal_cb->loop;
}
// async (internal only)
struct us_internal_async *us_internal_create_async(struct us_loop_t *loop,
int fallthrough,
unsigned int ext_size) {
struct us_internal_callback_t *cb = malloc(
sizeof(struct us_internal_callback_t) + sizeof(uv_async_t) + ext_size);
cb->loop = loop;
return (struct us_internal_async *)cb;
}
void us_internal_async_close(struct us_internal_async *a) {
struct us_internal_callback_t *cb = (struct us_internal_callback_t *)a;
uv_async_t *uv_async = (uv_async_t *)(cb + 1);
// always ref the async before closing it
uv_ref((uv_handle_t *)uv_async);
uv_async->data = cb;
uv_close((uv_handle_t *)uv_async, close_cb_free);
}
void us_internal_async_set(struct us_internal_async *a,
void (*cb)(struct us_internal_async *)) {
struct us_internal_callback_t *internal_cb =
(struct us_internal_callback_t *)a;
internal_cb->cb = (void (*)(struct us_internal_callback_t *))cb;
uv_async_t *uv_async = (uv_async_t *)(internal_cb + 1);
uv_async_init(internal_cb->loop->uv_loop, uv_async, async_cb);
uv_unref((uv_handle_t *)uv_async);
uv_async->data = internal_cb;
}
void us_internal_async_wakeup(struct us_internal_async *a) {
struct us_internal_callback_t *internal_cb =
(struct us_internal_callback_t *)a;
uv_async_t *uv_async = (uv_async_t *)(internal_cb + 1);
uv_async_send(uv_async);
}
#endif

View File

@@ -0,0 +1,47 @@
/*
* Authored by Alex Hultman, 2018-2019.
* Intellectual property of third-party.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBUV_H
#define LIBUV_H
#include "internal/loop_data.h"
#include <uv.h>
#define LIBUS_SOCKET_READABLE UV_READABLE
#define LIBUS_SOCKET_WRITABLE UV_WRITABLE
struct us_loop_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_internal_loop_data_t data;
uv_loop_t *uv_loop;
int is_default;
uv_prepare_t *uv_pre;
uv_check_t *uv_check;
};
// it is no longer valid to cast a pointer to us_poll_t to a pointer of
// uv_poll_t
struct us_poll_t {
/* We need to hold a pointer to this uv_poll_t since we need to be able to
* resize our block */
uv_poll_t *uv_p;
LIBUS_SOCKET_DESCRIPTOR fd;
unsigned char poll_type;
};
#endif // LIBUV_H

View File

@@ -18,9 +18,10 @@
#ifndef INTERNAL_H
#define INTERNAL_H
#if defined(_MSC_VER)
#ifndef __cplusplus
#define alignas(x) __declspec(align(x))
#endif
#else
#include <stdalign.h>
#endif
@@ -32,7 +33,11 @@
#if defined(LIBUS_USE_EPOLL) || defined(LIBUS_USE_KQUEUE)
#define LIBUS_MAX_READY_POLLS 1024
void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop, struct us_poll_t *old_poll, struct us_poll_t *new_poll, int old_events, int new_events);
void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop,
struct us_poll_t *old_poll,
struct us_poll_t *new_poll,
int old_events,
int new_events);
#endif
/* We only have one networking implementation so far */
@@ -43,35 +48,47 @@ void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop, struct
#include "internal/eventing/epoll_kqueue.h"
#endif
#ifdef LIBUS_USE_LIBUV
#include "internal/eventing/libuv.h"
#endif
/* Poll type and what it polls for */
enum {
/* Two first bits */
POLL_TYPE_SOCKET = 0,
POLL_TYPE_SOCKET_SHUT_DOWN = 1,
POLL_TYPE_SEMI_SOCKET = 2,
POLL_TYPE_CALLBACK = 3,
/* Two first bits */
POLL_TYPE_SOCKET = 0,
POLL_TYPE_SOCKET_SHUT_DOWN = 1,
POLL_TYPE_SEMI_SOCKET = 2,
POLL_TYPE_CALLBACK = 3,
/* Two last bits */
POLL_TYPE_POLLING_OUT = 4,
POLL_TYPE_POLLING_IN = 8
/* Two last bits */
POLL_TYPE_POLLING_OUT = 4,
POLL_TYPE_POLLING_IN = 8
};
/* Loop related */
void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events);
void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error,
int events);
void us_internal_timer_sweep(struct us_loop_t *loop);
void us_internal_free_closed_sockets(struct us_loop_t *loop);
void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context);
void us_internal_loop_unlink(struct us_loop_t *loop, struct us_socket_context_t *context);
void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop));
void us_internal_loop_link(struct us_loop_t *loop,
struct us_socket_context_t *context);
void us_internal_loop_unlink(struct us_loop_t *loop,
struct us_socket_context_t *context);
void us_internal_loop_data_init(struct us_loop_t *loop,
void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop),
void (*post_cb)(struct us_loop_t *loop));
void us_internal_loop_data_free(struct us_loop_t *loop);
void us_internal_loop_pre(struct us_loop_t *loop);
void us_internal_loop_post(struct us_loop_t *loop);
/* Asyncs (old) */
struct us_internal_async *us_internal_create_async(struct us_loop_t *loop, int fallthrough, unsigned int ext_size);
struct us_internal_async *us_internal_create_async(struct us_loop_t *loop,
int fallthrough,
unsigned int ext_size);
void us_internal_async_close(struct us_internal_async *a);
void us_internal_async_set(struct us_internal_async *a, void (*cb)(struct us_internal_async *));
void us_internal_async_set(struct us_internal_async *a,
void (*cb)(struct us_internal_async *));
void us_internal_async_wakeup(struct us_internal_async *a);
/* Eventing related */
@@ -84,78 +101,94 @@ void us_internal_init_loop_ssl_data(struct us_loop_t *loop);
void us_internal_free_loop_ssl_data(struct us_loop_t *loop);
/* Socket context related */
void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s);
void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s);
void us_internal_socket_context_link_socket(struct us_socket_context_t *context,
struct us_socket_t *s);
void us_internal_socket_context_unlink_socket(
struct us_socket_context_t *context, struct us_socket_t *s);
/* Sockets are polls */
struct us_socket_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p; // 4 bytes
unsigned char timeout; // 1 byte
unsigned char long_timeout; // 1 byte
unsigned short low_prio_state; /* 0 = not in low-prio queue, 1 = is in low-prio queue, 2 = was in low-prio queue in this iteration */
struct us_socket_context_t *context;
struct us_socket_t *prev, *next;
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p; // 4 bytes
unsigned char timeout; // 1 byte
unsigned char long_timeout; // 1 byte
unsigned short
low_prio_state; /* 0 = not in low-prio queue, 1 = is in low-prio queue, 2
= was in low-prio queue in this iteration */
struct us_socket_context_t *context;
struct us_socket_t *prev, *next;
};
struct us_wrapped_socket_context_t {
struct us_socket_events_t events;
struct us_socket_events_t old_events;
struct us_socket_events_t events;
struct us_socket_events_t old_events;
};
#if defined(LIBUS_USE_KQUEUE)
/* Internal callback types are polls just like sockets */
struct us_internal_callback_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
struct us_loop_t *loop;
int cb_expects_the_loop;
int leave_poll_ready;
void (*cb)(struct us_internal_callback_t *cb);
mach_port_t port;
void* machport_buf;
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
struct us_loop_t *loop;
int cb_expects_the_loop;
int leave_poll_ready;
void (*cb)(struct us_internal_callback_t *cb);
mach_port_t port;
void *machport_buf;
};
#else
struct us_internal_callback_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
struct us_loop_t *loop;
int cb_expects_the_loop;
int leave_poll_ready;
void (*cb)(struct us_internal_callback_t *cb);
alignas(LIBUS_EXT_ALIGNMENT) struct us_poll_t p;
struct us_loop_t *loop;
int cb_expects_the_loop;
int leave_poll_ready;
void (*cb)(struct us_internal_callback_t *cb);
};
#endif
#if __cplusplus
extern "C" {
#endif
int us_internal_raw_root_certs(struct us_cert_string_t **out);
#if __cplusplus
}
#endif
/* Listen sockets are sockets */
struct us_listen_socket_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_socket_t s;
unsigned int socket_ext_size;
alignas(LIBUS_EXT_ALIGNMENT) struct us_socket_t s;
unsigned int socket_ext_size;
};
/* Listen sockets are keps in their own list */
void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *s);
void us_internal_socket_context_unlink_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *s);
void us_internal_socket_context_link_listen_socket(
struct us_socket_context_t *context, struct us_listen_socket_t *s);
void us_internal_socket_context_unlink_listen_socket(
struct us_socket_context_t *context, struct us_listen_socket_t *s);
struct us_socket_context_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_loop_t *loop;
uint32_t global_tick;
unsigned char timestamp;
unsigned char long_timestamp;
struct us_socket_t *head_sockets;
struct us_listen_socket_t *head_listen_sockets;
struct us_socket_t *iterator;
struct us_socket_context_t *prev, *next;
alignas(LIBUS_EXT_ALIGNMENT) struct us_loop_t *loop;
uint32_t global_tick;
unsigned char timestamp;
unsigned char long_timestamp;
struct us_socket_t *head_sockets;
struct us_listen_socket_t *head_listen_sockets;
struct us_socket_t *iterator;
struct us_socket_context_t *prev, *next;
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length);
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
struct us_socket_t *(*on_writable)(struct us_socket_t *);
struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
//void (*on_timeout)(struct us_socket_context *);
struct us_socket_t *(*on_socket_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_socket_long_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_end)(struct us_socket_t *);
struct us_socket_t *(*on_connect_error)(struct us_socket_t *, int code);
int (*is_low_prio)(struct us_socket_t *);
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip,
int ip_length);
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
struct us_socket_t *(*on_writable)(struct us_socket_t *);
struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
// void (*on_timeout)(struct us_socket_context *);
struct us_socket_t *(*on_socket_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_socket_long_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_end)(struct us_socket_t *);
struct us_socket_t *(*on_connect_error)(struct us_socket_t *, int code);
int (*is_low_prio)(struct us_socket_t *);
};
/* Internal SSL interface */
@@ -163,83 +196,142 @@ struct us_socket_context_t {
struct us_internal_ssl_socket_context_t;
struct us_internal_ssl_socket_t;
typedef void (*us_internal_on_handshake_t)(
struct us_internal_ssl_socket_t *, int success,
struct us_bun_verify_error_t verify_error, void *custom_data);
/* SNI functions */
void us_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user);
void us_bun_internal_ssl_socket_context_add_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern, struct us_bun_socket_context_options_t options, void *user);
void us_internal_ssl_socket_context_remove_server_name(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern);
void us_internal_ssl_socket_context_on_server_name(struct us_internal_ssl_socket_context_t *context, void (*cb)(struct us_internal_ssl_socket_context_t *, const char *));
void *us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_context_find_server_name_userdata(struct us_internal_ssl_socket_context_t *context, const char *hostname_pattern);
void us_internal_ssl_socket_context_add_server_name(
struct us_internal_ssl_socket_context_t *context,
const char *hostname_pattern, struct us_socket_context_options_t options,
void *user);
void us_bun_internal_ssl_socket_context_add_server_name(
struct us_internal_ssl_socket_context_t *context,
const char *hostname_pattern,
struct us_bun_socket_context_options_t options, void *user);
void us_internal_ssl_socket_context_remove_server_name(
struct us_internal_ssl_socket_context_t *context,
const char *hostname_pattern);
void us_internal_ssl_socket_context_on_server_name(
struct us_internal_ssl_socket_context_t *context,
void (*cb)(struct us_internal_ssl_socket_context_t *, const char *));
void *
us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_context_find_server_name_userdata(
struct us_internal_ssl_socket_context_t *context,
const char *hostname_pattern);
void *us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_context_get_native_handle(struct us_internal_ssl_socket_context_t *context);
struct us_bun_verify_error_t us_internal_verify_error(struct us_internal_ssl_socket_t *s);
struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(struct us_loop_t *loop,
int context_ext_size, struct us_socket_context_options_t options);
struct us_internal_ssl_socket_context_t *us_internal_bun_create_ssl_socket_context(struct us_loop_t *loop,
int context_ext_size, struct us_bun_socket_context_options_t options);
void *
us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_context_get_native_handle(
struct us_internal_ssl_socket_context_t *context);
struct us_bun_verify_error_t
us_internal_verify_error(struct us_internal_ssl_socket_t *s);
struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
struct us_loop_t *loop, int context_ext_size,
struct us_socket_context_options_t options);
struct us_internal_ssl_socket_context_t *
us_internal_bun_create_ssl_socket_context(
struct us_loop_t *loop, int context_ext_size,
struct us_bun_socket_context_options_t options);
void us_internal_ssl_socket_context_free(struct us_internal_ssl_socket_context_t *context);
void us_internal_ssl_socket_context_on_open(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_open)(struct us_internal_ssl_socket_t *s, int is_client, char *ip, int ip_length));
void us_internal_ssl_socket_context_free(
struct us_internal_ssl_socket_context_t *context);
void us_internal_ssl_socket_context_on_open(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_open)(
struct us_internal_ssl_socket_t *s, int is_client, char *ip,
int ip_length));
void us_internal_ssl_socket_context_on_close(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_close)(struct us_internal_ssl_socket_t *s, int code, void *reason));
void us_internal_ssl_socket_context_on_close(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_close)(
struct us_internal_ssl_socket_t *s, int code, void *reason));
void us_internal_ssl_socket_context_on_data(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_data)(struct us_internal_ssl_socket_t *s, char *data, int length));
void us_internal_ssl_socket_context_on_data(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_data)(
struct us_internal_ssl_socket_t *s, char *data, int length));
void us_internal_ssl_handshake(struct us_internal_ssl_socket_t *s, void (*on_handshake)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
void us_internal_on_ssl_handshake(struct us_internal_ssl_socket_context_t * context, void (*on_handshake)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
void us_internal_ssl_handshake(struct us_internal_ssl_socket_t *s);
void us_internal_on_ssl_handshake(
struct us_internal_ssl_socket_context_t *context,
us_internal_on_handshake_t onhandshake, void *custom_data);
void us_internal_ssl_socket_context_on_writable(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_writable)(struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_writable(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_writable)(
struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_timeout(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_timeout)(struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_timeout(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_timeout)(
struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_long_timeout(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_timeout)(struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_long_timeout(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_timeout)(
struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_end(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_end)(struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_end(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_end)(
struct us_internal_ssl_socket_t *s));
void us_internal_ssl_socket_context_on_connect_error(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_connect_error)(struct us_internal_ssl_socket_t *s, int code));
void us_internal_ssl_socket_context_on_connect_error(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *(*on_connect_error)(
struct us_internal_ssl_socket_t *s, int code));
struct us_listen_socket_t *us_internal_ssl_socket_context_listen(struct us_internal_ssl_socket_context_t *context,
const char *host, int port, int options, int socket_ext_size);
struct us_listen_socket_t *us_internal_ssl_socket_context_listen(
struct us_internal_ssl_socket_context_t *context, const char *host,
int port, int options, int socket_ext_size);
struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(struct us_internal_ssl_socket_context_t *context,
const char *path, int options, int socket_ext_size);
struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
struct us_internal_ssl_socket_context_t *context, const char *path,
int options, int socket_ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect(struct us_internal_ssl_socket_context_t *context,
const char *host, int port, const char *source_host, int options, int socket_ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect(
struct us_internal_ssl_socket_context_t *context, const char *host,
int port, const char *source_host, int options, int socket_ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(struct us_internal_ssl_socket_context_t *context,
const char *server_path, int options, int socket_ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
struct us_internal_ssl_socket_context_t *context, const char *server_path,
int options, int socket_ext_size);
int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s, const char *data, int length, int msg_more);
int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s, const char *data, int length, int msg_more);
int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,
const char *data, int length, int msg_more);
int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
const char *data, int length,
int msg_more);
void us_internal_ssl_socket_timeout(struct us_internal_ssl_socket_t *s, unsigned int seconds);
void *us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t *s);
struct us_internal_ssl_socket_context_t *us_internal_ssl_socket_get_context(struct us_internal_ssl_socket_t *s);
void us_internal_ssl_socket_timeout(struct us_internal_ssl_socket_t *s,
unsigned int seconds);
void *
us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t *s);
struct us_internal_ssl_socket_context_t *
us_internal_ssl_socket_get_context(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_ext(struct us_internal_ssl_socket_t *s);
int us_internal_ssl_socket_is_shut_down(struct us_internal_ssl_socket_t *s);
void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t *s);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *s, int ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(struct us_socket_t *s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size);
struct us_internal_ssl_socket_context_t *us_internal_create_child_ssl_socket_context(struct us_internal_ssl_socket_context_t *context, int context_ext_size);
struct us_loop_t *us_internal_ssl_socket_context_loop(struct us_internal_ssl_socket_context_t *context);
struct us_internal_ssl_socket_t* us_internal_ssl_socket_open(struct us_internal_ssl_socket_t * s, int is_client, char* ip, int ip_length);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
struct us_socket_t *s, struct us_bun_socket_context_options_t options,
struct us_socket_events_t events, int socket_ext_size);
struct us_internal_ssl_socket_context_t *
us_internal_create_child_ssl_socket_context(
struct us_internal_ssl_socket_context_t *context, int context_ext_size);
struct us_loop_t *us_internal_ssl_socket_context_loop(
struct us_internal_ssl_socket_context_t *context);
struct us_internal_ssl_socket_t *
us_internal_ssl_socket_open(struct us_internal_ssl_socket_t *s, int is_client,
char *ip, int ip_length);
int us_raw_root_certs(struct us_cert_string_t**out);
int us_raw_root_certs(struct us_cert_string_t **out);
#endif
#endif // INTERNAL_H

View File

@@ -90,6 +90,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd
int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
int bsd_would_block();
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket

View File

@@ -153,6 +153,12 @@ struct us_socket_context_options_t {
int ssl_prefer_low_memory_usage; /* Todo: rename to prefer_low_memory_usage and apply for TCP as well */
};
struct us_bun_verify_error_t {
long error;
const char* code;
const char* reason;
};
struct us_socket_events_t {
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length);
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
@@ -166,11 +172,6 @@ struct us_socket_events_t {
void (*on_handshake)(struct us_socket_t*, int success, struct us_bun_verify_error_t verify_error, void* custom_data);
};
struct us_bun_verify_error_t {
long error;
const char* code;
const char* reason;
};
struct us_bun_socket_context_options_t {
const char *key_file_name;
@@ -231,7 +232,7 @@ void us_socket_context_on_long_timeout(int ssl, struct us_socket_context_t *cont
void us_socket_context_on_connect_error(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_connect_error)(struct us_socket_t *s, int code));
void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_context_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
/* Emitted when a socket has been half-closed */
void us_socket_context_on_end(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_end)(struct us_socket_t *s));
@@ -344,6 +345,9 @@ void *us_socket_get_native_handle(int ssl, struct us_socket_t *s);
* Set hint msg_more if you have more immediate data to write. */
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more);
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length);
/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
* at any given point in time. Will remove any such pre set timer */
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds);

View File

@@ -18,7 +18,9 @@
#include "libusockets.h"
#include "internal/internal.h"
#include <stdlib.h>
#ifndef WIN32
#include <sys/ioctl.h>
#endif
/* The loop has 2 fallthrough polls */
void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop),

View File

@@ -150,22 +150,90 @@ struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, vo
return s;
}
// This function is the same as us_socket_close but:
// - does not emit on_close event
// - does not close
struct us_socket_t *us_socket_detach(int ssl, struct us_socket_t *s) {
if (!us_socket_is_closed(0, s)) {
if (s->low_prio_state == 1) {
/* Unlink this socket from the low-priority queue */
if (!s->prev) s->context->loop->data.low_prio_head = s->next;
else s->prev->next = s->next;
if (s->next) s->next->prev = s->prev;
s->prev = 0;
s->next = 0;
s->low_prio_state = 0;
} else {
us_internal_socket_context_unlink_socket(s->context, s);
}
us_poll_stop((struct us_poll_t *) s, s->context->loop);
/* Link this socket to the close-list and let it be deleted after this iteration */
s->next = s->context->loop->data.closed_head;
s->context->loop->data.closed_head = s;
/* Any socket with prev = context is marked as closed */
s->prev = (struct us_socket_t *) s->context;
return s;
}
return s;
}
// This function is used for moving a socket between two different event loops
struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size) {
struct us_poll_t *accepted_p = us_create_poll(ctx->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size);
us_poll_init(accepted_p, client_fd, POLL_TYPE_SOCKET);
us_poll_start(accepted_p, ctx->loop, flags);
struct us_socket_t *s = (struct us_socket_t *) accepted_p;
s->context = ctx;
s->timeout = 0;
s->low_prio_state = 0;
/* We always use nodelay */
bsd_socket_nodelay(client_fd, 1);
us_internal_socket_context_link_socket(ctx, s);
if (ctx->on_open) ctx->on_open(s, 0, 0, 0);
return s;
}
struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds) {
#ifdef LIBUS_USE_LIBUV
#if defined(LIBUS_USE_LIBUV) || defined(WIN32)
return 0;
#endif
#else
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0) {
return 0;
}
return us_socket_from_fd(ctx, socket_ext_size, fds[0]);
#endif
}
/* This is not available for SSL sockets as it makes no sense. */
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length) {
if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
return 0;
}
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
if (written != header_length + payload_length) {
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}
return written < 0 ? 0 : written;
}
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd) {
#ifdef LIBUS_USE_LIBUV
#if defined(LIBUS_USE_LIBUV) || defined(WIN32)
return 0;
#endif
#else
struct us_poll_t *p1 = us_create_poll(ctx->loop, 0, sizeof(struct us_socket_t) + socket_ext_size);
us_poll_init(p1, fd, POLL_TYPE_SOCKET);
us_poll_start(p1, ctx->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
@@ -186,6 +254,7 @@ struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socke
}
return s;
#endif
}

View File

@@ -124,6 +124,12 @@ public:
getLoopData()->corkedSocketIsSSL = SSL;
}
void uncorkWithoutSending() {
if (isCorked()) {
getLoopData()->corkedSocket = nullptr;
}
}
/* Cork this socket. Only one socket may ever be corked per-loop at any given time */
void cork() {
/* Extra check for invalid corking of others */
@@ -213,9 +219,9 @@ public:
unsigned char *b = (unsigned char *) binary.data();
if (binary.length() == 4) {
ipLength = sprintf(buf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
ipLength = snprintf(buf, sizeof(buf), "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
} else {
ipLength = sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ipLength = snprintf(buf, sizeof(buf), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11],
b[12], b[13], b[14], b[15]);
}

View File

@@ -64,6 +64,33 @@ private:
/* Init the HttpContext by registering libusockets event handlers */
HttpContext<SSL> *init() {
if(SSL) {
// if we are SSL we need to handle the handshake properly
us_socket_context_on_handshake(SSL, getSocketContext(), [](us_socket_t *s, int success, struct us_bun_verify_error_t verify_error, void* custom_data) {
// if we are closing or already closed, we don't need to do anything
if (!us_socket_is_closed(SSL, s) && !us_socket_is_shut_down(SSL, s)) {
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
if(httpContextData->rejectUnauthorized) {
if(!success || verify_error.error != 0) {
// we failed to handshake, close the socket
us_socket_close(SSL, s, 0, nullptr);
return;
}
}
/* Any connected socket should timeout until it has a request */
us_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S);
/* Call filter */
for (auto &f : httpContextData->filterHandlers) {
f((HttpResponse<SSL> *) s, 1);
}
}
}, nullptr);
}
/* Handle socket connections */
us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int /*is_client*/, char */*ip*/, int /*ip_length*/) {
/* Any connected socket should timeout until it has a request */
@@ -72,10 +99,12 @@ private:
/* Init socket ext */
new (us_socket_ext(SSL, s)) HttpResponseData<SSL>;
/* Call filter */
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
for (auto &f : httpContextData->filterHandlers) {
f((HttpResponse<SSL> *) s, 1);
if(!SSL) {
/* Call filter */
HttpContextData<SSL> *httpContextData = getSocketContextDataS(s);
for (auto &f : httpContextData->filterHandlers) {
f((HttpResponse<SSL> *) s, 1);
}
}
return s;
@@ -396,9 +425,13 @@ public:
if (!httpContext) {
return nullptr;
}
// for servers this is only valid when request cert is enabled
/* Init socket context data */
new ((HttpContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData<SSL>();
auto* httpContextData = new ((HttpContextData<SSL> *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData<SSL>();
if(options.request_cert && options.reject_unauthorized) {
httpContextData->rejectUnauthorized = true;
}
return httpContext->init();
}

View File

@@ -49,6 +49,7 @@ private:
HttpRouter<RouterData> router;
void *upgradedWebSocket = nullptr;
bool isParsingHttp = false;
bool rejectUnauthorized = false;
};
}

View File

@@ -245,9 +245,14 @@ struct InflationStream {
}
#endif
/* Save off the bytes we're about to overwrite */
char* tailLocation = (char*)compressed.data() + compressed.length();
char preTailBytes[4];
memcpy(preTailBytes, tailLocation, 4);
/* Append tail to chunk */
unsigned char tail[4] = {0x00, 0x00, 0xff, 0xff};
memcpy((char *)compressed.data() + compressed.length(), tail, 4);
memcpy(tailLocation, tail, 4);
compressed = {compressed.data(), compressed.length() + 4};
/* We clear this one here, could be done better */
@@ -275,6 +280,9 @@ struct InflationStream {
inflateReset(&inflationStream);
}
/* Restore the bytes we used for the tail */
memcpy(tailLocation, preTailBytes, 4);
if ((err != Z_BUF_ERROR && err != Z_OK) || zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) {
return std::nullopt;
}

View File

@@ -105,48 +105,73 @@ public:
/* If we are subscribers and have messages to drain we need to drain them here to stay synced */
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
if (webSocketData->subscriber) {
/* This will call back into us, send. */
webSocketContextData->topicTree->drain(webSocketData->subscriber);
}
/* Transform the message to compressed domain if requested */
if (compress) {
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
/* Check and correct the compress hint. It is never valid to compress 0 bytes */
if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
LoopData *loopData = Super::getLoopData();
/* Compress using either shared or dedicated deflationStream */
if (webSocketData->deflationStream) {
message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false);
/* Special path for long sends of non-compressed, non-SSL messages */
if (message.length() >= 16 * 1024 && !compress && !SSL && !webSocketData->subscriber && getBufferedAmount() == 0 && Super::getLoopData()->corkOffset == 0) {
char header[10];
int header_length = (int) protocol::formatMessage<isServer>(header, nullptr, 0, opCode, message.length(), compress, fin);
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length());
if (written != header_length + (int) message.length()) {
/* Buffer up backpressure */
if (written > header_length) {
webSocketData->buffer.append(message.data() + written - header_length, message.length() - (size_t) (written - header_length));
} else {
message = loopData->deflationStream->deflate(loopData->zlibContext, message, true);
webSocketData->buffer.append(header + written, (size_t) header_length - (size_t) written);
webSocketData->buffer.append(message.data(), message.length());
}
} else {
compress = false;
}
}
/* Get size, allocate size, write if needed */
size_t messageFrameSize = protocol::messageFrameSize(message.length());
auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize);
protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress, fin);
/* Depending on size of message we have different paths */
if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) {
/* This is a drain */
auto[written, failed] = Super::write(nullptr, 0);
if (failed) {
/* Return false for failure, skipping to reset the timeout below */
/* We cannot still be corked if we have backpressure.
* We also cannot uncork normally since it will re-write the already buffered
* up backpressure again. */
Super::uncorkWithoutSending();
return BACKPRESSURE;
}
} else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) {
/* Uncork if we came here uncorked */
auto [written, failed] = Super::uncork();
if (failed) {
return BACKPRESSURE;
} else {
if (webSocketData->subscriber) {
/* This will call back into us, send. */
webSocketContextData->topicTree->drain(webSocketData->subscriber);
}
/* Transform the message to compressed domain if requested */
if (compress) {
WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData();
/* Check and correct the compress hint. It is never valid to compress 0 bytes */
if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) {
LoopData *loopData = Super::getLoopData();
/* Compress using either shared or dedicated deflationStream */
if (webSocketData->deflationStream) {
message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false);
} else {
message = loopData->deflationStream->deflate(loopData->zlibContext, message, true);
}
} else {
compress = false;
}
}
/* Get size, allocate size, write if needed */
size_t messageFrameSize = protocol::messageFrameSize(message.length());
auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize);
protocol::formatMessage<isServer>(sendBuffer, message.data(), message.length(), opCode, message.length(), compress, fin);
/* Depending on size of message we have different paths */
if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) {
/* This is a drain */
auto[written, failed] = Super::write(nullptr, 0);
if (failed) {
/* Return false for failure, skipping to reset the timeout below */
return BACKPRESSURE;
}
} else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) {
/* Uncork if we came here uncorked */
auto [written, failed] = Super::uncork();
if (failed) {
return BACKPRESSURE;
}
}
}
/* Every successful send resets the timeout */
@@ -221,6 +246,8 @@ public:
/* There is no timeout when failing to uncork for WebSockets,
* as that is handled by idleTimeout */
auto [written, failed] = Super::uncork();
(void)written;
(void)failed;
} else {
/* We are already corked, or can't cork so let's just call the handler */
handler();
@@ -349,4 +376,4 @@ public:
}
#endif // UWS_WEBSOCKET_H
#endif // UWS_WEBSOCKET_H

View File

@@ -0,0 +1,83 @@
param(
[Alias("f")][switch]$Force = $false
)
$ErrorActionPreference = 'Stop'
$DidAnything = $false;
$BUN_BASE_DIR = if ($env:BUN_BASE_DIR) { $env:BUN_BASE_DIR } else { Join-Path $PSScriptRoot '..' }
$BUN_DEPS_DIR = if ($env:BUN_DEPS_DIR) { $env:BUN_DEPS_DIR } else { Join-Path $BUN_BASE_DIR 'src\deps' }
$BUN_DEPS_OUT_DIR = if ($env:BUN_DEPS_OUT_DIR) { $env:BUN_DEPS_OUT_DIR } else { $BUN_DEPS_DIR }
function Build-Dependency {
param(
$Script,
[string[]]$Outputs
)
$ScriptPath = Join-Path $PSScriptRoot "build-$Script.ps1"
if (!$Force) {
foreach ($Output in $Outputs) {
$OutputPath = Join-Path $BUN_DEPS_OUT_DIR $Output
if (Test-Path $OutputPath) {
Write-Host "$Script - already built"
return
}
}
}
else {
Remove-Item $Outputs -ErrorAction SilentlyContinue
}
Write-Host "$Script - Building"
Push-Location $PSScriptRoot
try {
& $ScriptPath
}
catch {
Write-Host "Failed to build $Script"
throw $_
}
finally {
Pop-Location
}
$Script:DidAnything = $true
}
Build-Dependency `
-Script "base64" `
-Outputs @("base64.lib")
Build-Dependency `
-Script "boringssl" `
-Outputs @("crypto.lib", "ssl.lib", "decrepit.lib")
Build-Dependency `
-Script "cares" `
-Outputs @("cares.lib")
Build-Dependency `
-Script "libarchive" `
-Outputs @("archive.lib")
Build-Dependency `
-Script "lolhtml" `
-Outputs @("lolhtml.lib")
Build-Dependency `
-Script "mimalloc" `
-Outputs @("mimalloc.lib")
# Build-Dependency `
# -Script "tinycc" `
# -Outputs @("tcc.lib")
Build-Dependency `
-Script "zlib" `
-Outputs @("zlib.lib")
Build-Dependency `
-Script "zstd" `
-Outputs @("zstd.lib")
Build-Dependency `
-Script "libuv" `
-Outputs @("libuv.lib")
if (!($Script:DidAnything)) {
Write-Host "(run with -Force to rebuild all)"
}

67
scripts/all-dependencies.sh Executable file
View File

@@ -0,0 +1,67 @@
set -euo pipefail
source "$(dirname -- "${BASH_SOURCE[0]}")/env.sh"
FORCE=
while getopts "f" opt; do
case ${opt} in
f )
FORCE=1
;;
\? )
echo "Usage: all-dependencies.sh [-h] [-f]"
echo "Options:"
echo " h Print this help message"
echo " f Set force to 1"
exit 1
;;
esac
done
BUILT_ANY=0
dep() {
local script="$1"
if [ -z "$FORCE" ]; then
HAS_ALL_DEPS=1
shift
for lib in "$@"; do
if [ ! -f "$BUN_DEPS_OUT_DIR/$lib" ]; then
HAS_ALL_DEPS=0
break
fi
done
if [ "$HAS_ALL_DEPS" == "1" ]; then
printf "%s - already built\n" "$script"
return
fi
fi
printf "building %s\n" "$script"
set +e
bash "$SCRIPT_DIR/build-$script.sh"
EXIT=$?
if [ "$EXIT" -ne 0 ]; then
printf "Failed to build %s\n" "$script"
exit "$EXIT"
fi
set -e
BUILT_ANY=1
}
dep base64 libbase64.a
dep boringssl libcrypto.a libssl.a libdecrepit.a
dep cares libcares.a
dep libarchive libarchive.a
dep lolhtml liblolhtml.a
dep mimalloc-debug libmimalloc-debug.a libmimalloc-debug.o
dep mimalloc libmimalloc.a libmimalloc.o
dep tinycc libtcc.a
dep zlib libz.a
dep zstd libzstd.a
if [ "$BUILT_ANY" -eq 0 ]; then
printf "(run with -f to rebuild)\n"
fi

16
scripts/build-base64.ps1 Normal file
View File

@@ -0,0 +1,16 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'base64')
try {
Set-Location (mkdir -Force build)
Run cmake @CMAKE_FLAGS -DBASE64_WERROR=0 ..
Run cmake --build . --clean-first --config Release
Copy-Item base64.lib $BUN_DEPS_OUT_DIR
Write-Host "-> base64.lib"
}
finally {
Pop-Location
}

14
scripts/build-base64.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
cd $BUN_DEPS_DIR/base64
rm -rf build
mkdir -p build
cd build
cmake "${CMAKE_FLAGS[@]}" .. -GNinja -B .
ninja
cp libbase64.a $BUN_DEPS_OUT_DIR/libbase64.a

View File

@@ -0,0 +1,15 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'boringssl')
try {
Set-Location (mkdir -Force build)
Run cmake @CMAKE_FLAGS ..
Run cmake --build . --target crypto --target ssl --target decrepit --clean-first --config Release
Copy-Item crypto/crypto.lib $BUN_DEPS_OUT_DIR
Copy-Item ssl/ssl.lib $BUN_DEPS_OUT_DIR
Copy-Item decrepit/decrepit.lib $BUN_DEPS_OUT_DIR
Write-Host "-> crypto.lib, ssl.lib, decrepit.lib"
} finally { Pop-Location }

14
scripts/build-boringssl.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
cd $BUN_DEPS_DIR/boringssl
mkdir -p build
cd build
cmake "${CMAKE_FLAGS[@]}" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -GNinja ..
ninja libcrypto.a libssl.a libdecrepit.a
cp **/libcrypto.a $BUN_DEPS_OUT_DIR/libcrypto.a
cp **/libssl.a $BUN_DEPS_OUT_DIR/libssl.a
cp **/libdecrepit.a $BUN_DEPS_OUT_DIR/libdecrepit.a

16
scripts/build-cares.ps1 Normal file
View File

@@ -0,0 +1,16 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'c-ares')
try {
Set-Location (mkdir -Force build)
Run cmake @CMAKE_FLAGS -DCARES_STATIC=ON -DCARES_SHARED=OFF ..
Run cmake --build . --clean-first --config Release
Copy-Item lib\cares.lib $BUN_DEPS_OUT_DIR
Write-Host "-> cares.lib"
}
finally {
Pop-Location
}

21
scripts/build-cares.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
cd $BUN_DEPS_DIR/c-ares
rm -rf build
mkdir -p build
cd build
cmake "${CMAKE_FLAGS[@]}" .. \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCARES_STATIC=ON \
-DCARES_STATIC_PIC=ON \
-DCARES_SHARED=OFF \
-G "Ninja"
ninja
cp lib/libcares.a $BUN_DEPS_OUT_DIR/libcares.a

View File

@@ -0,0 +1,16 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'libarchive')
try {
Set-Location (mkdir -Force build)
Run cmake @CMAKE_FLAGS -DBUILD_SHARED_LIBS=OFF -DENABLE_TEST=OFF -DENABLE_INSTALL=OFF -DENABLE_WERROR=0 ..
Run cmake --build . --clean-first --config Release
Copy-Item libarchive\archive.lib $BUN_DEPS_OUT_DIR
Write-Host "-> libarchive.lib"
}
finally {
Pop-Location
}

13
scripts/build-libarchive.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
mkdir -p $BUN_DEPS_OUT_DIR
cd $BUN_DEPS_DIR/libarchive
make clean || echo ""
./build/clean.sh || echo ""
./build/autogen.sh
./configure --disable-shared --enable-static --with-pic --disable-bsdtar --disable-bsdcat --disable-rpath --enable-posix-regex-lib --without-xml2 --without-expat --without-openssl --without-iconv --without-zlib
make -j$CPUS
cp ./.libs/libarchive.a $BUN_DEPS_OUT_DIR/libarchive.a

40
scripts/build-libuv.ps1 Normal file
View File

@@ -0,0 +1,40 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
$CWD = Get-Location
$Source = (Join-Path $PSScriptRoot "../src/deps/libuv")
$Commit = "da527d8d2a908b824def74382761566371439003"
if (!(Test-Path -PathType Container $Source)) {
Write-Host "Cloning libuv: $Commit"
New-Item -ItemType Directory -Force -Path $Source
Push-Location $Source
try {
Run git init
Run git remote add origin "https://github.com/libuv/libuv"
Run git fetch --depth 1 origin $Commit
Run git checkout FETCH_HEAD
} finally { Pop-Location }
} else {
Push-Location $Source
try {
$CurrentCommit = git rev-parse HEAD
if ($CurrentCommit -ne $Commit) {
Write-Host "Updating libuv: $Commit"
Run git fetch --depth 1 origin $Commit
Run git checkout FETCH_HEAD
}
} finally { Pop-Location }
}
Push-Location $Source
try {
$null = mkdir build -ErrorAction SilentlyContinue
Set-Location build
Run cmake .. @CMAKE_FLAGS "-DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS -Wno-int-conversion"
Run cmake --build . --clean-first --config Release
Copy-Item libuv.lib $BUN_DEPS_OUT_DIR
Write-Host "-> libuv.lib"
} finally { Pop-Location }

11
scripts/build-lolhtml.ps1 Normal file
View File

@@ -0,0 +1,11 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'lol-html/c-api')
try {
Run cargo build --release --target x86_64-pc-windows-msvc
Copy-Item target/x86_64-pc-windows-msvc/release/lolhtml.lib $BUN_DEPS_OUT_DIR
Copy-Item target/x86_64-pc-windows-msvc/release/lolhtml.pdb $BUN_DEPS_OUT_DIR
Write-Host "-> lolhtml.lib"
} finally { Pop-Location }

7
scripts/build-lolhtml.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
cd $BUN_DEPS_DIR/lol-html/c-api
cargo build --release
cp target/release/liblolhtml.a $BUN_DEPS_OUT_DIR/liblolhtml.a

30
scripts/build-mimalloc-debug.sh Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euxo pipefail
source "$(dirname -- "${BASH_SOURCE[0]}")/env.sh"
MIMALLOC_OVERRIDE_FLAG=${MIMALLOC_OVERRIDE_FLAG:-}
MIMALLOC_VALGRIND_ENABLED_FLAG=${MIMALLOC_VALGRIND_ENABLED_FLAG:-}
cd $BUN_DEPS_DIR/mimalloc
rm -rf CMakeCache* CMakeFiles
cmake "${CMAKE_FLAGS[@]}" . \
-DCMAKE_BUILD_TYPE=Debug \
-DMI_DEBUG=1 \
-DMI_SKIP_COLLECT_ON_EXIT=1 \
-DMI_BUILD_SHARED=OFF \
-DMI_BUILD_STATIC=ON \
-DMI_BUILD_TESTS=OFF \
-DMI_OSX_ZONE=OFF \
-DMI_OSX_INTERPOSE=OFF \
-DMI_BUILD_OBJECT=ON \
-DMI_USE_CXX=ON \
-DMI_OVERRIDE=OFF \
-DMI_OSX_ZONE=OFF \
-GNinja
ninja
cp libmimalloc-debug.a $BUN_DEPS_OUT_DIR/libmimalloc-debug.a
cp CMakeFiles/mimalloc-obj.dir/src/static.c.o $BUN_DEPS_OUT_DIR/libmimalloc-debug.o

View File

@@ -0,0 +1,25 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'mimalloc')
try {
Set-Location (mkdir -Force build)
Run cmake .. @CMAKE_FLAGS `
-DMI_SKIP_COLLECT_ON_EXIT=1 `
-DMI_BUILD_SHARED=OFF `
-DMI_BUILD_STATIC=ON `
-DMI_BUILD_TESTS=OFF `
-DMI_OSX_ZONE=OFF `
-DMI_OSX_INTERPOSE=OFF `
-DMI_BUILD_OBJECT=ON `
-DMI_USE_CXX=ON `
-DMI_OVERRIDE=OFF `
-DMI_OSX_ZONE=OFF
Run cmake --build . --clean-first --config Release
Copy-Item mimalloc-static.lib $BUN_DEPS_OUT_DIR/mimalloc.lib
Write-Host "-> mimalloc.lib"
} finally { Pop-Location }

29
scripts/build-mimalloc.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euxo pipefail
source "$(dirname -- "${BASH_SOURCE[0]}")/env.sh"
MIMALLOC_OVERRIDE_FLAG=${MIMALLOC_OVERRIDE_FLAG:-}
MIMALLOC_VALGRIND_ENABLED_FLAG=${MIMALLOC_VALGRIND_ENABLED_FLAG:-}
cd $BUN_DEPS_DIR/mimalloc
rm -rf CMakeCache* CMakeFiles
cmake "${CMAKE_FLAGS[@]}" . \
-DCMAKE_BUILD_TYPE=Release \
-DMI_SKIP_COLLECT_ON_EXIT=1 \
-DMI_BUILD_SHARED=OFF \
-DMI_BUILD_STATIC=ON \
-DMI_BUILD_TESTS=OFF \
-DMI_OSX_ZONE=OFF \
-DMI_OSX_INTERPOSE=OFF \
-DMI_BUILD_OBJECT=ON \
-DMI_USE_CXX=ON \
-DMI_OVERRIDE=OFF \
-DMI_OSX_ZONE=OFF \
-GNinja
ninja
cp libmimalloc.a $BUN_DEPS_OUT_DIR/libmimalloc.a
cp CMakeFiles/mimalloc-obj.dir/src/static.c.o $BUN_DEPS_OUT_DIR/libmimalloc.o

11
scripts/build-tinycc.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
mkdir -p $BUN_DEPS_OUT_DIR
cd $BUN_DEPS_DIR/tinycc
make clean
CFLAGS="${CFLAGS} -DTCC_LIBTCC1=\\\"\0\\\"" ./configure --enable-static --cc="$CC" --ar="$AR" --config-predefs=yes
make libtcc.a -j$CPUS
cp libtcc.a $BUN_DEPS_OUT_DIR

29
scripts/build-zlib.ps1 Normal file
View File

@@ -0,0 +1,29 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'zlib')
try {
Run git reset --hard
# TODO: make a patch upstream to change the line
# `#ifdef _MSC_VER`
# to account for clang-cl, which implements `__builtin_ctzl` and `__builtin_expect`
$textToReplace = [regex]::Escape("int __inline __builtin_ctzl(unsigned long mask)") + "[^}]*}"
$fileContent = Get-Content "deflate.h" -Raw
if ($fileContent -match $textToReplace) {
Set-Content -Path "deflate.h" -Value ($fileContent -replace $textToReplace, "")
}
else {
throw "Failed to patch deflate.h"
}
Set-Location (mkdir -Force build)
Run cmake .. @CMAKE_FLAGS
Run cmake --build . --clean-first --config Release
Copy-Item zlib.lib $BUN_DEPS_OUT_DIR
Write-Host "-> zlib.lib"
}
finally { Pop-Location }

13
scripts/build-zlib.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
mkdir -p $BUN_DEPS_OUT_DIR
cd $BUN_DEPS_DIR/zlib
export CFLAGS="-O3"
if [[ $(uname -s) == 'Darwin' ]]; then
export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
fi
CFLAGS="${CFLAGS}" ./configure --static
make -j${CPUS}
cp ./libz.a $BUN_DEPS_OUT_DIR/libz.a

13
scripts/build-zstd.ps1 Normal file
View File

@@ -0,0 +1,13 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
Push-Location (Join-Path $BUN_DEPS_DIR 'zstd')
try {
Remove-Item CMakeCache.txt -ErrorAction SilentlyContinue
Run cmake -S "build/cmake" @CMAKE_FLAGS -DZSTD_BUILD_STATIC=ON
Run cmake --build . --clean-first --config Release
Copy-Item lib/zstd_static.lib $BUN_DEPS_OUT_DIR/zstd.lib
Write-Host "-> zstd.lib"
} finally { Pop-Location }

11
scripts/build-zstd.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euxo pipefail
source $(dirname -- "${BASH_SOURCE[0]}")/env.sh
mkdir -p $BUN_DEPS_OUT_DIR
cd $BUN_DEPS_DIR/zstd
rm -rf Release CMakeCache.txt CMakeFiles
cmake "${CMAKE_FLAGS[@]}" -DZSTD_BUILD_STATIC=ON -B Release -S build/cmake -G Ninja
ninja -C Release
cp Release/lib/libzstd.a $BUN_DEPS_OUT_DIR/libzstd.a

View File

@@ -0,0 +1,29 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
. (Join-Path $PSScriptRoot "env.ps1")
function Reset-Submodule {
param (
$Repository
)
Push-Location $Repository
try {
Run git reset --hard
Run git clean -fdx
}
finally {
Pop-Location
}
}
$Deps = Join-Path $PSScriptRoot "../src/deps"
Reset-Submodule $Deps/base64
Reset-Submodule $Deps/boringssl
Reset-Submodule $Deps/c-ares
Reset-Submodule $Deps/libarchive
Reset-Submodule $Deps/lol-html
Reset-Submodule $Deps/mimalloc
Reset-Submodule $Deps/picohttpparser
Reset-Submodule $Deps/tinycc
Reset-Submodule $Deps/zlib
Reset-Submodule $Deps/zstd

26
scripts/clean-dependencies.sh Executable file
View File

@@ -0,0 +1,26 @@
FORCE=
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
BUN_BASE_DIR=${BUN_BASE_DIR:-$(cd $SCRIPT_DIR && cd .. && pwd)}
BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR:-$BUN_BASE_DIR/src/deps/}
BUN_DEPS_DIR=${BUN_DEPS_DIR:-$BUN_BASE_DIR/src/deps/}
rm -f $BUN_DEPS_OUT_DIR/*.a
git_reset() {
dir=$(pwd)
cd $1
git reset --hard
git clean -fdx
cd $dir
}
git_reset $BUN_DEPS_DIR/boringssl
git_reset $BUN_DEPS_DIR/c-ares
git_reset $BUN_DEPS_DIR/libarchive
git_reset $BUN_DEPS_DIR/lol-html
git_reset $BUN_DEPS_DIR/mimalloc
git_reset $BUN_DEPS_DIR/picohttpparser
git_reset $BUN_DEPS_DIR/tinycc
git_reset $BUN_DEPS_DIR/zlib
git_reset $BUN_DEPS_DIR/zstd

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -e
export TARGET_PLATFORM=${1:-win32}
export TARGET_ARCH=${2:-x64}
cd "$(dirname "${BASH_SOURCE[0]}")/../"
OUT=$(realpath build-codegen-${TARGET_PLATFORM}-${TARGET_ARCH})
rm -rf "$OUT"
mkdir -p "$OUT"
bun ./src/codegen/bundle-functions.ts --debug=OFF "$OUT" &
bun ./src/codegen/bundle-modules.ts --debug=OFF "$OUT" &
rm -rf "$OUT/tmp_functions"
rm -rf "$OUT/tmp_modules"
CLASSES=(
./src/bun.js/*.classes.ts
./src/bun.js/api/*.classes.ts
./src/bun.js/test/*.classes.ts
./src/bun.js/webcore/*.classes.ts
./src/bun.js/node/*.classes.ts
)
bun "./src/codegen/generate-classes.ts" ${CLASSES[@]} "$OUT/codegen" &
LUTS=(
./src/bun.js/bindings/BunObject.cpp
./src/bun.js/bindings/ZigGlobalObject.lut.txt
./src/bun.js/bindings/JSBuffer.cpp
./src/bun.js/bindings/BunProcess.cpp
./src/bun.js/bindings/ProcessBindingConstants.cpp
./src/bun.js/bindings/ProcessBindingNatives.cpp
)
for lut in ${LUTS[@]}; do
result=$(basename $lut | sed 's/.lut.txt/.cpp/' | sed 's/.cpp/.h/')
echo bun "./src/codegen/create-hash-table.ts" "$lut" "$OUT/codegen/$result"
done
wait
rm -rf "$OUT/tmp"*
echo "-> `basename "$OUT"`"

View File

@@ -0,0 +1,42 @@
param (
[Parameter(Mandatory)]
[string]$OutDir,
[Parameter(Mandatory)][string]$Tag,
[Parameter(Mandatory)][string]$PackageName
)
$ErrorActionPreference = "Stop"
$Url = "https://github.com/oven-sh/WebKit/releases/download/autobuild-$Tag/$PackageName.tar.gz"
$CacheDir = (mkdir -Force (Join-Path $PSScriptRoot "../.webkit-cache"))
$TarPath = Join-Path $CacheDir "$PackageName-$Tag.tar.gz"
if (Test-Path $OutDir\.tag) {
$CurrentTag = Get-Content -Path (Join-Path $OutDir ".tag")
if ($CurrentTag -eq $Tag) {
return
}
}
Remove-Item $OutDir -ErrorAction SilentlyContinue -Recurse
$null = mkdir -Force $OutDir
try {
Write-Host "-- Downloading WebKit"
if (!(Test-Path $TarPath)) {
try {
Invoke-WebRequest $Url -OutFile $TarPath
} catch {
Write-Error "Failed to fetch WebKit from: $Url"
throw $_
}
}
Push-Location $CacheDir
tar.exe "-xzf" "$PackageName-$Tag.tar.gz" -C (Resolve-Path -Relative $OutDir\..\).replace('\', '/')
Pop-Location
Set-Content -Path (Join-Path $OutDir ".tag") -Value "$Tag"
} catch {
Remove-Item -Force -ErrorAction SilentlyContinue $OutDir
throw $_
}

View File

@@ -0,0 +1,57 @@
#!/bin/bash
set -e
OUTDIR="$1"
TAG="$2"
PKG="$3"
if [ -z "$OUTDIR" ]; then
echo "Missing outdir"
exit 1
fi
if [ -z "$TAG" ]; then
echo "Missing tag"
exit 1
fi
if [ -z "$PKG" ]; then
echo "Missing package"
exit 1
fi
mkdir -p "$OUTDIR"
url="https://github.com/oven-sh/WebKit/releases/download/autobuild-$TAG/$PKG.tar.gz"
tar_dir="$(dirname "$0")/../.webkit-cache"
tar="$tar_dir/$PKG-$TAG.tar.gz"
mkdir -p "$tar_dir"
# TODO: Remove this block, future builds may not include a package.json
if [ -f "$OUTDIR/package.json" ]; then
read_version=$(grep -o '"version": "[^"]*"' "$OUTDIR/package.json" | sed 's/"version": "\(.*\)"/\1/' 2>/dev/null)
if [ "$read_version" == "0.0.1-$TAG" ]; then
echo "$TAG" > "$OUTDIR/.tag"
exit 0
fi
fi
if [ -f "$OUTDIR/.tag" ]; then
read_tag="$(cat "$OUTDIR/.tag")"
if [ "$read_tag" == "$TAG" ]; then
exit 0
fi
fi
rm -rf "$OUTDIR"
if [ ! -f "$tar" ]; then
echo "-- Downloading WebKit"
if ! curl -o "$tar" -L "$url"; then
echo "Failed to download $url"
exit 1
fi
fi
tar -xzf "$tar" -C "$(dirname "$OUTDIR")"
echo "$TAG" > "$OUTDIR/.tag"

73
scripts/env.ps1 Normal file
View File

@@ -0,0 +1,73 @@
$ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash
# this is the environment script for building bun's dependencies
# it sets c compiler and flags
$ScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
if ($env:VSINSTALLDIR -eq $null) {
Write-Host "Loading Visual Studio environment, this may take a second..."
$vsDir = Get-ChildItem -Path "C:\Program Files\Microsoft Visual Studio\2022" -Directory
if ($vsDir -eq $null) {
throw "Visual Studio directory not found."
}
Push-Location $vsDir
try {
. (Join-Path -Path $vsDir.FullName -ChildPath "Common7\Tools\Launch-VsDevShell.ps1") -Arch amd64 -HostArch amd64
} finally { Pop-Location }
}
if($Env:VSCMD_ARG_TGT_ARCH -eq "x86") {
# Please do not try to compile Bun for 32 bit. It will not work. I promise.
throw "Visual Studio environment is targetting 32 bit. This configuration is definetly a mistake."
}
$BUN_BASE_DIR = if ($env:BUN_BASE_DIR) { $env:BUN_BASE_DIR } else { Join-Path $ScriptDir '..' }
$BUN_DEPS_DIR = if ($env:BUN_DEPS_DIR) { $env:BUN_DEPS_DIR } else { Join-Path $BUN_BASE_DIR 'src\deps' }
$BUN_DEPS_OUT_DIR = if ($env:BUN_DEPS_OUT_DIR) { $env:BUN_DEPS_OUT_DIR } else { $BUN_DEPS_DIR }
$CPUS = if ($env:CPUS) { $env:CPUS } else { (Get-WmiObject -Class Win32_Processor).NumberOfCores }
$CC = "clang-cl"
$CXX = "clang-cl"
$CFLAGS = '/O2'
$CXXFLAGS = '/O2'
$CMAKE_FLAGS = @(
"-GNinja",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_C_COMPILER=$CC",
"-DCMAKE_CXX_COMPILER=$CXX",
"-DCMAKE_C_FLAGS=`"$CFLAGS`"",
"-DCMAKE_CXX_FLAGS=`"$CXXFLAGS`""
)
$env:CC = "clang-cl"
$env:CXX = "clang-cl"
$env:CFLAGS = $CFLAGS
$env:CXXFLAGS = $CXXFLAGS
$env:CPUS = $CPUS
$null = New-Item -ItemType Directory -Force -Path $BUN_DEPS_OUT_DIR
function Run() {
# A handy way to run a command, and automatically throw an error if the
# exit code is non-zero.
if ($args.Count -eq 0) {
throw "Must supply some arguments."
}
$command = $args[0]
$commandArgs = @()
if ($args.Count -gt 1) {
$commandArgs = $args[1..($args.Count - 1)]
}
& $command $commandArgs
$result = $LASTEXITCODE
if ($result -ne 0) {
throw "$command $commandArgs exited with code $result."
}
}

45
scripts/env.sh Executable file
View File

@@ -0,0 +1,45 @@
# this is the environment script for building bun's dependencies
# it sets c compiler and flags
export SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
export BUN_BASE_DIR=${BUN_BASE_DIR:-$(cd $SCRIPT_DIR && cd .. && pwd)}
export BUN_DEPS_DIR=${BUN_DEPS_DIR:-$BUN_BASE_DIR/src/deps/}
export BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR:-$BUN_BASE_DIR/src/deps/}
# this compiler detection could be better
export CC=${CC:-$(which clang-16 || which clang || which cc)}
export CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)}
export AR=${AR:-$(which llvm-ar || which ar)}
export CPUS=${CPUS:-$(nproc || sysctl -n hw.ncpu || echo 1)}
export CMAKE_CXX_COMPILER=${CXX}
export CMAKE_C_COMPILER=${CC}
export CFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden'
export CXXFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden'
export CMAKE_FLAGS=(
-DCMAKE_C_COMPILER="${CC}"
-DCMAKE_CXX_COMPILER="${CXX}"
-DCMAKE_C_FLAGS="$CFLAGS"
-DCMAKE_CXX_FLAGS="$CXXFLAGS"
-DCMAKE_BUILD_TYPE=Release
)
if [[ $(uname -s) == 'Darwin' ]]; then
if ! [[ $(uname -m) == 'arm64' ]]; then
export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-10.14}
else
export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-11.0}
fi
CMAKE_FLAGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET})
export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
export CXXFLAGS="$CXXFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}"
fi
mkdir -p $BUN_DEPS_OUT_DIR
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "C Compiler: ${CC}"
echo "C++ Compiler: ${CXX}"
fi

97
scripts/setup.sh Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -e
C_BOLD="\e[1;1m"
C_GREEN="\e[32m"
C_RED="\e[31m"
C_BLUE="\e[34m"
C_RESET="\e[0m"
has_exec() {
which "$1" >/dev/null 2>&1 || return 1
}
fail() {
printf "${C_RED}setup error${C_RESET}: %s\n" "$@"
exit 1
}
LLVM_VERSION=16
# this compiler detection could be better
# it is copy pasted from ./env.sh
CC=${CC:-$(which clang-16 || which clang || which cc)}
CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)}
test -n "$CC" || fail "missing LLVM $LLVM_VERSION (could not find clang)"
test -n "$CXX" || fail "missing LLVM $LLVM_VERSION (could not find clang++)"
for type in CC CXX; do
compiler="${!type}"
$(
"$compiler" --version | grep "clang version ${LLVM_VERSION}." >/dev/null 2>&1
) || fail "LLVM ${LLVM_VERSION} is required. Detected $type as '$compiler'"
done
has_exec "bun" || fail "you need an existing copy of 'bun' in your path to build bun"
has_exec "cmake" || fail "'cmake' is missing"
has_exec "ninja" || fail "'ninja' is missing"
$(
has_exec "rustc" \
&& (test $(cargo --version | awk '{print $2}' | cut -d. -f2) -gt 57) \
&& has_exec "cargo"
) || fail "Rust and Cargo version must be installed (minimum version 1.57)"
has_exec "go" || fail "'go' is missing"
has_exec "pkg-config" || fail "'pkg-config' is missing"
has_exec "automake" || fail "'automake' is missing"
has_exec "perl" || fail "'perl' is missing"
has_exec "ruby" || fail "'ruby' is missing"
rm -f .vscode/clang++
ln -s "$CXX" .vscode/clang++
printf "All system dependencies OK\n"
printf "C Compiler for dependencies: ${CC}\n"
printf "C++ Compiler for dependencies: ${CXX}\n"
cd "$(dirname "${BASH_SOURCE[0]}")"
bash ./update-submodules.sh
bash ./all-dependencies.sh
cd ../
bun i
# TODO(@paperdave): do not use the Makefile please
make runtime_js fallback_decoder bun_error node-fallbacks
mkdir -p build
rm -f build/CMakeCache.txt
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -G Ninja -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX"
ninja -C build
printf "Checking if built bun functions\n"
BUN_VERSION=$(BUN_DEBUG_QUIET_LOGS=1 ./build/bun-debug --version)
printf "\n"
printf "🎉 ${C_GREEN}${C_BOLD}Development environment setup complete!${C_RESET}\n"
printf "${C_BLUE}bun v${BUN_VERSION} is located at ./build/bun-debug${C_RESET}\n"
if has_exec bun-debug; then
bun_is_at=$(which bun-debug)
if [ "$(realpath "$bun_is_at")" != "$(realpath "./build/bun-debug")" ]; then
printf "\n"
printf "${C_RED}"'Your $PATH is not configured correctly!\n'"${C_RESET}"
printf "\n"
printf "which bun-debug --> %s\n" "${bun_is_at}"
printf "\n"
printf "You should remove this binary and switch it to ./build:\n"
printf ' export PATH="$PATH:%s"\n' $(realpath "$PWD/build")
fi
else
printf "\n"
printf "You should add ./build to your path:\n"
printf ' export PATH="$PATH:%s"\n' $(realpath "$PWD/build")
fi
printf "\n"
printf "To rebuild bun, run '${C_GREEN}bun run build${C_RESET}'\n\n"

12
scripts/update-submodules.sh Executable file
View File

@@ -0,0 +1,12 @@
cd -- "$(dirname -- "${BASH_SOURCE[0]}")"
cd ..
NAMES=$(cat .gitmodules | grep 'path = ' | awk '{print $3}')
# we will exclude webkit unless you explicity clone it yourself (a huge download)
if [ ! -e "src/bun.js/WebKit/.git" ]; then
NAMES=$(echo "$NAMES" | grep -v 'WebKit')
fi
set -euxo pipefail
git submodule update --init --recursive --progress --depth=1 --checkout $NAMES

View File

@@ -7,18 +7,7 @@ const StringTypes = @import("./string_types.zig");
const Mimalloc = @import("root").bun.Mimalloc;
const bun = @import("root").bun;
pub const build_id = std.fmt.parseInt(u64, std.mem.trim(u8, @embedFile("./build-id"), "\n \r\t"), 10) catch unreachable;
pub const version: if (Environment.isWasm)
std.SemanticVersion
else
@import("./install/semver.zig").Version = .{
.major = 1,
.minor = 0,
.patch = build_id,
};
const version_string = std.fmt.comptimePrint("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
const version_string = Environment.version_string;
pub const package_json_version = if (Environment.isDebug)
version_string ++ "_debug"
@@ -79,7 +68,7 @@ pub fn setThreadName(name: StringTypes.stringZ) void {
/// Flushes stdout and stderr and exits with the given code.
pub fn exit(code: u8) noreturn {
Output.flush();
std.os.exit(code);
std.c._exit(code);
}
pub const AllocatorConfiguration = struct {

View File

@@ -332,7 +332,7 @@ pub const GenerateHeader = struct {
"IOPlatformExpertDevice",
};
const result = try std.ChildProcess.exec(.{
const result = try std.ChildProcess.run(.{
.allocator = default_allocator,
.cwd = Fs.FileSystem.instance.top_level_dir,
.argv = std.mem.span(&cmds),

View File

@@ -0,0 +1,852 @@
const bun = @import("root").bun;
const Output = bun.Output;
const JSC = bun.JSC;
const uws = bun.uws;
const Environment = bun.Environment;
const std = @import("std");
pub const Loop = uws.Loop;
/// Track if an object whose file descriptor is being watched should keep the event loop alive.
/// This is not reference counted. It only tracks active or inactive.
pub const KeepAlive = struct {
status: Status = .inactive,
const log = Output.scoped(.KeepAlive, false);
const Status = enum { active, inactive, done };
pub inline fn isActive(this: KeepAlive) bool {
return this.status == .active;
}
/// Make calling ref() on this poll into a no-op.
pub fn disable(this: *KeepAlive) void {
this.unref(JSC.VirtualMachine.get());
this.status = .done;
}
/// Only intended to be used from EventLoop.Pollable
pub fn deactivate(this: *KeepAlive, loop: *Loop) void {
if (this.status != .active)
return;
this.status = .inactive;
loop.num_polls -= 1;
loop.active -|= 1;
}
/// Only intended to be used from EventLoop.Pollable
pub fn activate(this: *KeepAlive, loop: *Loop) void {
if (this.status != .inactive)
return;
this.status = .active;
loop.num_polls += 1;
loop.active += 1;
}
pub fn init() KeepAlive {
return .{};
}
/// Prevent a poll from keeping the process alive.
pub fn unref(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .active)
return;
this.status = .inactive;
vm.event_loop_handle.?.unref();
}
/// From another thread, Prevent a poll from keeping the process alive.
pub fn unrefConcurrently(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .active)
return;
this.status = .inactive;
vm.event_loop_handle.?.unrefConcurrently();
}
/// Prevent a poll from keeping the process alive on the next tick.
pub fn unrefOnNextTick(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .active)
return;
this.status = .inactive;
vm.pending_unref_counter +|= 1;
}
/// From another thread, prevent a poll from keeping the process alive on the next tick.
pub fn unrefOnNextTickConcurrently(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .active)
return;
this.status = .inactive;
_ = @atomicRmw(@TypeOf(vm.pending_unref_counter), &vm.pending_unref_counter, .Add, 1, .Monotonic);
}
/// Allow a poll to keep the process alive.
pub fn ref(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .inactive)
return;
this.status = .active;
vm.event_loop_handle.?.ref();
}
/// Allow a poll to keep the process alive.
pub fn refConcurrently(this: *KeepAlive, vm: *JSC.VirtualMachine) void {
if (this.status != .inactive)
return;
this.status = .active;
vm.event_loop_handle.?.refConcurrently();
}
pub fn refConcurrentlyFromEventLoop(this: *KeepAlive, loop: *JSC.EventLoop) void {
this.refConcurrently(loop.virtual_machine);
}
pub fn unrefConcurrentlyFromEventLoop(this: *KeepAlive, loop: *JSC.EventLoop) void {
this.unrefConcurrently(loop.virtual_machine);
}
};
const KQueueGenerationNumber = if (Environment.isMac and Environment.allow_assert) usize else u0;
pub const FilePoll = struct {
var max_generation_number: KQueueGenerationNumber = 0;
fd: bun.UFileDescriptor = invalid_fd,
flags: Flags.Set = Flags.Set{},
owner: Owner = undefined,
/// We re-use FilePoll objects to avoid allocating new ones.
///
/// That means we might run into situations where the event is stale.
/// on macOS kevent64 has an extra pointer field so we use it for that
/// linux doesn't have a field like that
generation_number: KQueueGenerationNumber = 0,
next_to_free: ?*FilePoll = null,
const FileReader = JSC.WebCore.FileReader;
const FileSink = JSC.WebCore.FileSink;
const FIFO = JSC.WebCore.FIFO;
const Subprocess = JSC.Subprocess;
const BufferedInput = Subprocess.BufferedInput;
const BufferedOutput = Subprocess.BufferedOutput;
const DNSResolver = JSC.DNS.DNSResolver;
const GetAddrInfoRequest = JSC.DNS.GetAddrInfoRequest;
const Deactivated = opaque {
pub var owner: Owner = Owner.init(@as(*Deactivated, @ptrFromInt(@as(usize, 0xDEADBEEF))));
};
pub const Owner = bun.TaggedPointerUnion(.{
FileReader,
FileSink,
Subprocess,
BufferedInput,
FIFO,
Deactivated,
DNSResolver,
GetAddrInfoRequest,
});
fn updateFlags(poll: *FilePoll, updated: Flags.Set) void {
var flags = poll.flags;
flags.remove(.readable);
flags.remove(.writable);
flags.remove(.process);
flags.remove(.machport);
flags.remove(.eof);
flags.remove(.hup);
flags.setUnion(updated);
poll.flags = flags;
}
pub fn onKQueueEvent(poll: *FilePoll, loop: *Loop, kqueue_event: *const std.os.system.kevent64_s) void {
if (KQueueGenerationNumber != u0)
std.debug.assert(poll.generation_number == kqueue_event.ext[0]);
poll.updateFlags(Flags.fromKQueueEvent(kqueue_event.*));
poll.onUpdate(loop, kqueue_event.data);
}
pub fn onEpollEvent(poll: *FilePoll, loop: *Loop, epoll_event: *std.os.linux.epoll_event) void {
poll.updateFlags(Flags.fromEpollEvent(epoll_event.*));
poll.onUpdate(loop, 0);
}
pub fn clearEvent(poll: *FilePoll, flag: Flags) void {
poll.flags.remove(flag);
}
pub fn isReadable(this: *FilePoll) bool {
const readable = this.flags.contains(.readable);
this.flags.remove(.readable);
return readable;
}
pub fn isHUP(this: *FilePoll) bool {
const readable = this.flags.contains(.hup);
this.flags.remove(.hup);
return readable;
}
pub fn isEOF(this: *FilePoll) bool {
const readable = this.flags.contains(.eof);
this.flags.remove(.eof);
return readable;
}
pub fn isWritable(this: *FilePoll) bool {
const readable = this.flags.contains(.writable);
this.flags.remove(.writable);
return readable;
}
pub fn deinit(this: *FilePoll) void {
var vm = JSC.VirtualMachine.get();
var loop = vm.event_loop_handle.?;
this.deinitPossiblyDefer(vm, loop, vm.rareData().filePolls(vm), false);
}
pub fn deinitForceUnregister(this: *FilePoll) void {
var vm = JSC.VirtualMachine.get();
var loop = vm.event_loop_handle.?;
this.deinitPossiblyDefer(vm, loop, vm.rareData().filePolls(vm), true);
}
fn deinitPossiblyDefer(this: *FilePoll, vm: *JSC.VirtualMachine, loop: *Loop, polls: *FilePoll.Store, force_unregister: bool) void {
if (this.isRegistered()) {
_ = this.unregister(loop, force_unregister);
}
this.owner = Deactivated.owner;
const was_ever_registered = this.flags.contains(.was_ever_registered);
this.flags = Flags.Set{};
this.fd = invalid_fd;
polls.put(this, vm, was_ever_registered);
}
pub fn deinitWithVM(this: *FilePoll, vm: *JSC.VirtualMachine) void {
var loop = vm.event_loop_handle.?;
this.deinitPossiblyDefer(vm, loop, vm.rareData().filePolls(vm), false);
}
pub fn isRegistered(this: *const FilePoll) bool {
return this.flags.contains(.poll_writable) or this.flags.contains(.poll_readable) or this.flags.contains(.poll_process) or this.flags.contains(.poll_machport);
}
const kqueue_or_epoll = if (Environment.isMac) "kevent" else "epoll";
pub fn onUpdate(poll: *FilePoll, loop: *Loop, size_or_offset: i64) void {
if (poll.flags.contains(.one_shot) and !poll.flags.contains(.needs_rearm)) {
if (poll.flags.contains(.has_incremented_poll_count)) poll.deactivate(loop);
poll.flags.insert(.needs_rearm);
}
var ptr = poll.owner;
switch (ptr.tag()) {
@field(Owner.Tag, "FIFO") => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) FIFO", .{poll.fd});
ptr.as(FIFO).ready(size_or_offset, poll.flags.contains(.hup));
},
@field(Owner.Tag, "Subprocess") => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) Subprocess", .{poll.fd});
var loader = ptr.as(JSC.Subprocess);
loader.onExitNotificationTask();
},
@field(Owner.Tag, "FileSink") => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) FileSink", .{poll.fd});
var loader = ptr.as(JSC.WebCore.FileSink);
loader.onPoll(size_or_offset, 0);
},
@field(Owner.Tag, "DNSResolver") => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) DNSResolver", .{poll.fd});
var loader: *DNSResolver = ptr.as(DNSResolver);
loader.onDNSPoll(poll);
},
@field(Owner.Tag, "GetAddrInfoRequest") => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) GetAddrInfoRequest", .{poll.fd});
var loader: *GetAddrInfoRequest = ptr.as(GetAddrInfoRequest);
loader.onMachportChange();
},
else => {
log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) disconnected?", .{poll.fd});
},
}
}
pub const Flags = enum {
// What are we asking the event loop about?
/// Poll for readable events
poll_readable,
/// Poll for writable events
poll_writable,
/// Poll for process-related events
poll_process,
/// Poll for machport events
poll_machport,
// What did the event loop tell us?
readable,
writable,
process,
eof,
hup,
machport,
// What is the type of file descriptor?
fifo,
tty,
one_shot,
needs_rearm,
has_incremented_poll_count,
disable,
nonblocking,
was_ever_registered,
ignore_updates,
pub fn poll(this: Flags) Flags {
return switch (this) {
.readable => .poll_readable,
.writable => .poll_writable,
.process => .poll_process,
.machport => .poll_machport,
else => this,
};
}
pub const Set = std.EnumSet(Flags);
pub const Struct = std.enums.EnumFieldStruct(Flags, bool, false);
pub fn fromKQueueEvent(kqueue_event: std.os.system.kevent64_s) Flags.Set {
var flags = Flags.Set{};
if (kqueue_event.filter == std.os.system.EVFILT_READ) {
flags.insert(Flags.readable);
log("readable", .{});
if (kqueue_event.flags & std.os.system.EV_EOF != 0) {
flags.insert(Flags.hup);
log("hup", .{});
}
} else if (kqueue_event.filter == std.os.system.EVFILT_WRITE) {
flags.insert(Flags.writable);
log("writable", .{});
if (kqueue_event.flags & std.os.system.EV_EOF != 0) {
flags.insert(Flags.hup);
log("hup", .{});
}
} else if (kqueue_event.filter == std.os.system.EVFILT_PROC) {
log("proc", .{});
flags.insert(Flags.process);
} else if (kqueue_event.filter == std.os.system.EVFILT_MACHPORT) {
log("machport", .{});
flags.insert(Flags.machport);
}
return flags;
}
pub fn fromEpollEvent(epoll: std.os.linux.epoll_event) Flags.Set {
var flags = Flags.Set{};
if (epoll.events & std.os.linux.EPOLL.IN != 0) {
flags.insert(Flags.readable);
log("readable", .{});
}
if (epoll.events & std.os.linux.EPOLL.OUT != 0) {
flags.insert(Flags.writable);
log("writable", .{});
}
if (epoll.events & std.os.linux.EPOLL.ERR != 0) {
flags.insert(Flags.eof);
log("eof", .{});
}
if (epoll.events & std.os.linux.EPOLL.HUP != 0) {
flags.insert(Flags.hup);
log("hup", .{});
}
return flags;
}
};
const HiveArray = bun.HiveArray(FilePoll, 128).Fallback;
// We defer freeing FilePoll until the end of the next event loop iteration
// This ensures that we don't free a FilePoll before the next callback is called
pub const Store = struct {
hive: HiveArray,
pending_free_head: ?*FilePoll = null,
pending_free_tail: ?*FilePoll = null,
const log = Output.scoped(.FilePoll, false);
pub fn init(allocator: std.mem.Allocator) Store {
return .{
.hive = HiveArray.init(allocator),
};
}
pub fn get(this: *Store) *FilePoll {
return this.hive.get();
}
pub fn processDeferredFrees(this: *Store) void {
var next = this.pending_free_head;
while (next) |current| {
next = current.next_to_free;
current.next_to_free = null;
this.hive.put(current);
}
this.pending_free_head = null;
this.pending_free_tail = null;
}
pub fn put(this: *Store, poll: *FilePoll, vm: *JSC.VirtualMachine, ever_registered: bool) void {
if (!ever_registered) {
this.hive.put(poll);
return;
}
std.debug.assert(poll.next_to_free == null);
if (this.pending_free_tail) |tail| {
std.debug.assert(this.pending_free_head != null);
std.debug.assert(tail.next_to_free == null);
tail.next_to_free = poll;
}
if (this.pending_free_head == null) {
this.pending_free_head = poll;
std.debug.assert(this.pending_free_tail == null);
}
poll.flags.insert(.ignore_updates);
this.pending_free_tail = poll;
std.debug.assert(vm.after_event_loop_callback == null or vm.after_event_loop_callback == @as(?JSC.OpaqueCallback, @ptrCast(&processDeferredFrees)));
vm.after_event_loop_callback = @ptrCast(&processDeferredFrees);
vm.after_event_loop_callback_ctx = this;
}
};
const log = Output.scoped(.FilePoll, false);
pub inline fn isActive(this: *const FilePoll) bool {
return this.flags.contains(.has_incremented_poll_count);
}
pub inline fn isWatching(this: *const FilePoll) bool {
return !this.flags.contains(.needs_rearm) and (this.flags.contains(.poll_readable) or this.flags.contains(.poll_writable) or this.flags.contains(.poll_process));
}
pub inline fn isKeepingProcessAlive(this: *const FilePoll) bool {
return !this.flags.contains(.disable) and this.isActive();
}
/// Make calling ref() on this poll into a no-op.
pub fn disableKeepingProcessAlive(this: *FilePoll, vm: *JSC.VirtualMachine) void {
if (this.flags.contains(.disable))
return;
this.flags.insert(.disable);
vm.event_loop_handle.?.active -= @as(u32, @intFromBool(this.flags.contains(.has_incremented_poll_count)));
}
pub fn enableKeepingProcessAlive(this: *FilePoll, vm: *JSC.VirtualMachine) void {
if (!this.flags.contains(.disable))
return;
this.flags.remove(.disable);
vm.event_loop_handle.?.active += @as(u32, @intFromBool(this.flags.contains(.has_incremented_poll_count)));
}
pub fn canActivate(this: *const FilePoll) bool {
return !this.flags.contains(.has_incremented_poll_count);
}
/// Only intended to be used from EventLoop.Pollable
pub fn deactivate(this: *FilePoll, loop: *Loop) void {
std.debug.assert(this.flags.contains(.has_incremented_poll_count));
loop.num_polls -= @as(i32, @intFromBool(this.flags.contains(.has_incremented_poll_count)));
loop.active -|= @as(u32, @intFromBool(!this.flags.contains(.disable) and this.flags.contains(.has_incremented_poll_count)));
this.flags.remove(.has_incremented_poll_count);
}
/// Only intended to be used from EventLoop.Pollable
pub fn activate(this: *FilePoll, loop: *Loop) void {
loop.num_polls += @as(i32, @intFromBool(!this.flags.contains(.has_incremented_poll_count)));
loop.active += @as(u32, @intFromBool(!this.flags.contains(.disable) and !this.flags.contains(.has_incremented_poll_count)));
this.flags.insert(.has_incremented_poll_count);
}
pub fn init(vm: *JSC.VirtualMachine, fd: bun.FileDescriptor, flags: Flags.Struct, comptime Type: type, owner: *Type) *FilePoll {
return initWithOwner(vm, fd, flags, Owner.init(owner));
}
pub fn initWithOwner(vm: *JSC.VirtualMachine, fd: bun.FileDescriptor, flags: Flags.Struct, owner: Owner) *FilePoll {
var poll = vm.rareData().filePolls(vm).get();
poll.fd = @intCast(fd);
poll.flags = Flags.Set.init(flags);
poll.owner = owner;
poll.next_to_free = null;
if (KQueueGenerationNumber != u0) {
max_generation_number +%= 1;
poll.generation_number = max_generation_number;
}
return poll;
}
pub inline fn canRef(this: *const FilePoll) bool {
if (this.flags.contains(.disable))
return false;
return !this.flags.contains(.has_incremented_poll_count);
}
pub inline fn canUnref(this: *const FilePoll) bool {
return this.flags.contains(.has_incremented_poll_count);
}
/// Prevent a poll from keeping the process alive.
pub fn unref(this: *FilePoll, vm: *JSC.VirtualMachine) void {
if (!this.canUnref())
return;
log("unref", .{});
this.deactivate(vm.event_loop_handle.?);
}
/// Allow a poll to keep the process alive.
pub fn ref(this: *FilePoll, vm: *JSC.VirtualMachine) void {
if (this.canRef())
return;
log("ref", .{});
this.activate(vm.event_loop_handle.?);
}
pub fn onTick(loop: *Loop, tagged_pointer: ?*anyopaque) callconv(.C) void {
var tag = Pollable.from(tagged_pointer);
if (tag.tag() != @field(Pollable.Tag, "FilePoll"))
return;
var file_poll: *FilePoll = tag.as(FilePoll);
if (file_poll.flags.contains(.ignore_updates)) {
return;
}
if (comptime Environment.isMac)
onKQueueEvent(file_poll, loop, &loop.ready_polls[@as(usize, @intCast(loop.current_ready_poll))])
else if (comptime Environment.isLinux)
onEpollEvent(file_poll, loop, &loop.ready_polls[@as(usize, @intCast(loop.current_ready_poll))]);
}
const Pollable = bun.TaggedPointerUnion(
.{
FilePoll,
Deactivated,
},
);
comptime {
@export(onTick, .{ .name = "Bun__internal_dispatch_ready_poll" });
}
const timeout = std.mem.zeroes(std.os.timespec);
const kevent = std.c.kevent;
const linux = std.os.linux;
pub fn register(this: *FilePoll, loop: *Loop, flag: Flags, one_shot: bool) JSC.Maybe(void) {
return registerWithFd(this, loop, flag, one_shot, this.fd);
}
pub fn registerWithFd(this: *FilePoll, loop: *Loop, flag: Flags, one_shot: bool, fd: u64) JSC.Maybe(void) {
const watcher_fd = loop.fd;
log("register: {s} ({d})", .{ @tagName(flag), fd });
std.debug.assert(fd != invalid_fd);
if (one_shot) {
this.flags.insert(.one_shot);
}
if (comptime Environment.isLinux) {
const one_shot_flag: u32 = if (!this.flags.contains(.one_shot)) 0 else linux.EPOLL.ONESHOT;
const flags: u32 = switch (flag) {
.process,
.readable,
=> linux.EPOLL.IN | linux.EPOLL.HUP | one_shot_flag,
.writable => linux.EPOLL.OUT | linux.EPOLL.HUP | linux.EPOLL.ERR | one_shot_flag,
else => unreachable,
};
var event = linux.epoll_event{ .events = flags, .data = .{ .u64 = @intFromPtr(Pollable.init(this).ptr()) } };
var op: u32 = if (this.isRegistered() or this.flags.contains(.needs_rearm)) linux.EPOLL.CTL_MOD else linux.EPOLL.CTL_ADD;
const ctl = linux.epoll_ctl(
watcher_fd,
op,
@intCast(fd),
&event,
);
this.flags.insert(.was_ever_registered);
if (JSC.Maybe(void).errnoSys(ctl, .epoll_ctl)) |errno| {
return errno;
}
} else if (comptime Environment.isMac) {
var changelist = std.mem.zeroes([2]std.os.system.kevent64_s);
const one_shot_flag: u16 = if (!this.flags.contains(.one_shot)) 0 else std.c.EV_ONESHOT;
changelist[0] = switch (flag) {
.readable => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_READ,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_ADD | one_shot_flag,
.ext = .{ this.generation_number, 0 },
},
.writable => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_WRITE,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_ADD | one_shot_flag,
.ext = .{ this.generation_number, 0 },
},
.process => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_PROC,
.data = 0,
.fflags = std.c.NOTE_EXIT,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_ADD | one_shot_flag,
.ext = .{ this.generation_number, 0 },
},
.machport => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_MACHPORT,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_ADD | one_shot_flag,
.ext = .{ this.generation_number, 0 },
},
else => unreachable,
};
// output events only include change errors
const KEVENT_FLAG_ERROR_EVENTS = 0x000002;
// The kevent() system call returns the number of events placed in
// the eventlist, up to the value given by nevents. If the time
// limit expires, then kevent() returns 0.
const rc = rc: {
while (true) {
const rc = std.os.system.kevent64(
watcher_fd,
&changelist,
1,
// The same array may be used for the changelist and eventlist.
&changelist,
// we set 0 here so that if we get an error on
// registration, it becomes errno
0,
KEVENT_FLAG_ERROR_EVENTS,
&timeout,
);
if (std.c.getErrno(rc) == .INTR) continue;
break :rc rc;
}
};
this.flags.insert(.was_ever_registered);
// If an error occurs while
// processing an element of the changelist and there is enough room
// in the eventlist, then the event will be placed in the eventlist
// with EV_ERROR set in flags and the system error in data.
if (changelist[0].flags == std.c.EV_ERROR and changelist[0].data != 0) {
return JSC.Maybe(void).errnoSys(changelist[0].data, .kevent).?;
// Otherwise, -1 will be returned, and errno will be set to
// indicate the error condition.
}
const errno = std.c.getErrno(rc);
if (errno != .SUCCESS) {
return JSC.Maybe(void){
.err = bun.sys.Error.fromCode(errno, .kqueue),
};
}
} else {
bun.todo(@src(), {});
}
if (this.canActivate())
this.activate(loop);
this.flags.insert(switch (flag) {
.readable => .poll_readable,
.process => if (comptime Environment.isLinux) .poll_readable else .poll_process,
.writable => .poll_writable,
.machport => .poll_machport,
else => unreachable,
});
this.flags.remove(.needs_rearm);
return JSC.Maybe(void).success;
}
const invalid_fd = bun.invalid_fd;
pub fn unregister(this: *FilePoll, loop: *Loop, force_unregister: bool) JSC.Maybe(void) {
return this.unregisterWithFd(loop, this.fd, force_unregister);
}
pub fn unregisterWithFd(this: *FilePoll, loop: *Loop, fd: bun.UFileDescriptor, force_unregister: bool) JSC.Maybe(void) {
if (!(this.flags.contains(.poll_readable) or this.flags.contains(.poll_writable) or this.flags.contains(.poll_process) or this.flags.contains(.poll_machport))) {
// no-op
return JSC.Maybe(void).success;
}
std.debug.assert(fd != invalid_fd);
const watcher_fd = loop.fd;
const flag: Flags = brk: {
if (this.flags.contains(.poll_readable))
break :brk .readable;
if (this.flags.contains(.poll_writable))
break :brk .writable;
if (this.flags.contains(.poll_process))
break :brk .process;
if (this.flags.contains(.poll_machport))
break :brk .machport;
return JSC.Maybe(void).success;
};
if (this.flags.contains(.needs_rearm) and !force_unregister) {
log("unregister: {s} ({d}) skipped due to needs_rearm", .{ @tagName(flag), fd });
this.flags.remove(.poll_process);
this.flags.remove(.poll_readable);
this.flags.remove(.poll_process);
this.flags.remove(.poll_machport);
return JSC.Maybe(void).success;
}
log("unregister: {s} ({d})", .{ @tagName(flag), fd });
if (comptime Environment.isLinux) {
const ctl = linux.epoll_ctl(
watcher_fd,
linux.EPOLL.CTL_DEL,
@intCast(fd),
null,
);
if (JSC.Maybe(void).errnoSys(ctl, .epoll_ctl)) |errno| {
return errno;
}
} else if (comptime Environment.isMac) {
var changelist = std.mem.zeroes([2]std.os.system.kevent64_s);
changelist[0] = switch (flag) {
.readable => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_READ,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_DELETE,
.ext = .{ 0, 0 },
},
.machport => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_MACHPORT,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_DELETE,
.ext = .{ 0, 0 },
},
.writable => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_WRITE,
.data = 0,
.fflags = 0,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_DELETE,
.ext = .{ 0, 0 },
},
.process => .{
.ident = @as(u64, @intCast(fd)),
.filter = std.os.system.EVFILT_PROC,
.data = 0,
.fflags = std.c.NOTE_EXIT,
.udata = @intFromPtr(Pollable.init(this).ptr()),
.flags = std.c.EV_DELETE,
.ext = .{ 0, 0 },
},
else => unreachable,
};
// output events only include change errors
const KEVENT_FLAG_ERROR_EVENTS = 0x000002;
// The kevent() system call returns the number of events placed in
// the eventlist, up to the value given by nevents. If the time
// limit expires, then kevent() returns 0.
const rc = std.os.system.kevent64(
watcher_fd,
&changelist,
1,
// The same array may be used for the changelist and eventlist.
&changelist,
1,
KEVENT_FLAG_ERROR_EVENTS,
&timeout,
);
// If an error occurs while
// processing an element of the changelist and there is enough room
// in the eventlist, then the event will be placed in the eventlist
// with EV_ERROR set in flags and the system error in data.
if (changelist[0].flags == std.c.EV_ERROR) {
return JSC.Maybe(void).errnoSys(changelist[0].data, .kevent).?;
// Otherwise, -1 will be returned, and errno will be set to
// indicate the error condition.
}
const errno = std.c.getErrno(rc);
switch (rc) {
std.math.minInt(@TypeOf(rc))...-1 => return JSC.Maybe(void).errnoSys(@intFromEnum(errno), .kevent).?,
else => {},
}
} else {
bun.todo(@src(), {});
}
this.flags.remove(.needs_rearm);
this.flags.remove(.one_shot);
// we don't support both right now
std.debug.assert(!(this.flags.contains(.poll_readable) and this.flags.contains(.poll_writable)));
this.flags.remove(.poll_readable);
this.flags.remove(.poll_writable);
this.flags.remove(.poll_process);
this.flags.remove(.poll_machport);
if (this.isActive())
this.deactivate(loop);
return JSC.Maybe(void).success;
}
};
pub const Waker = @import("io").Waker;

View File

@@ -0,0 +1,3 @@
pub const Loop = opaque {};
pub const KeepAlive = opaque {};
pub const FilePoll = opaque {};

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