Giter VIP home page Giter VIP logo

oven-sh / bun Goto Github PK

View Code? Open in Web Editor NEW
69.2K 616.0 2.3K 155.5 MB

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one

Home Page: https://bun.sh

Zig 60.25% JavaScript 5.79% TypeScript 5.24% CSS 0.06% Makefile 0.32% C 3.28% C++ 23.91% HTML 0.01% Shell 0.35% Dockerfile 0.11% Rust 0.04% AMPL 0.01% Perl 0.12% Objective-C 0.13% CMake 0.19% PowerShell 0.13% Ruby 0.06%
bun bundler javascript javascriptcore jsx nodejs npm react transpiler typescript

bun's Introduction

Logo

Bun

stars Bun speed

Documentation   •   Discord   •   Issues   •   Roadmap

What is Bun?

Bun is under active development. Use it to speed up your development workflows or run simpler production code in resource-constrained environments like serverless functions. We're working on more complete Node.js compatibility and integration with existing frameworks. Join the Discord and watch the GitHub repository to keep tabs on future releases.

Bun is an all-in-one toolkit for JavaScript and TypeScript apps. It ships as a single executable called bun.

At its core is the Bun runtime, a fast JavaScript runtime designed as a drop-in replacement for Node.js. It's written in Zig and powered by JavaScriptCore under the hood, dramatically reducing startup times and memory usage.

bun run index.tsx             # TS and JSX supported out-of-the-box

The bun command-line tool also implements a test runner, script runner, and Node.js-compatible package manager. Instead of 1,000 node_modules for development, you only need bun. Bun's built-in tools are significantly faster than existing options and usable in existing Node.js projects with little to no changes.

bun test                      # run tests
bun run start                 # run the `start` script in `package.json`
bun install <pkg>             # install a package
bunx cowsay 'Hello, world!'   # execute a package

Install

Bun supports Linux (x64 & arm64) and macOS (x64 & Apple Silicon).

Linux users — Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1.

Windows users — Bun does not currently provide a native Windows build. We're working on this; progress can be tracked at this issue. In the meantime, use one of the installation methods below for Windows Subsystem for Linux.

# with install script (recommended)
curl -fsSL https://bun.sh/install | bash

# with npm
npm install -g bun

# with Homebrew
brew tap oven-sh/bun
brew install bun

# with Docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

Upgrade

To upgrade to the latest version of Bun, run:

bun upgrade

Bun automatically releases a canary build on every commit to main. To upgrade to the latest canary build, run:

bun upgrade --canary

View canary build

Quick links

Contributing

Refer to the Project > Contributing guide to start contributing to Bun.

License

Refer to the Project > License page for information about Bun's licensing.

bun's People

Contributors

alexkuz avatar alexlamsl avatar argosphil avatar cirospaciari avatar colinhacks avatar daleseo avatar dylan-conway avatar electroid avatar evanwashere avatar finnrg avatar gvilums avatar hanaasagi avatar hanford avatar huseeiin avatar jarred-sumner avatar jwhear avatar liz3 avatar michellbrito avatar nektro avatar nutlope avatar otgerrogla avatar paperdave avatar snazzah avatar sno2 avatar thatonebro avatar trnxdev avatar xhyrom avatar zackradisic avatar zhiyuang avatar zhuzilin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bun's Issues

Errors seen when environment exports functions

Errors seen when invoking bun from a bash environment with exported functions (e.g. as used by nvs / nvm):

To reproduce, simple package.json:

{
  "scripts": {
    "invoke-ls": "ls"
  }
}

Then in a bash instance:

# Define a function (details aren't important)
fn() { :; }
# The important bit: export the function
export -f fn

bun run invoke-ls

Error output seen:

$ ls
/usr/local/bin/bash: fn: line 1: syntax error: unexpected end of file
/usr/local/bin/bash: error importing function definition for `fn'
...followed by actual output of ls...

Allow build to output code that runs on Node.js

Bun does not emit code that runs in Node.js. It's very close to doing that, but does not yet.

Blockers:

  • require shouldn't import the bundler runtime
  • node:fs and other node:* prefixes need to be marked as external
  • Parallelize bun build for performance
  • Output as CommonJS?

The best approach might be a Node.js require and/or ESM loader hook. This would involve using NP-API and writing C bindings. This would make the filesystem watcher work in Node.

Configurable feature map

Right now, the bundler always transpiles effectively to ESNext. This should be configurable, and a limited amount of backwards-compatibility should be possible. Don't need to go as far back as ES6, but perhaps specifically last 2 versions for Safari.

Fix unicode interop between JSC <> Zig

This affects:

  • fetch()
  • Macros
  • console.log
  • Bun.readFileAsString
  • Bun.readFile

The fix is most likely auto-converting to UTF-8 when calling toZigString, but having some way of tracking memory. Perhaps doing this where it is garbage collected rather than manually managed.

Support import assertions

It should probably remove them from the output since browser support is scarce. A better plan, more broadly, is for decisions like this to be configurable instead of just me saying stuff.

documentation updates for react section to easily integrate with existing CRA

(I can put up a PR if you're welcoming PRs)

Requires react version >17 because of the react/jsx-dev-runtime dependency for the compiler

if working with an existing CRA, you need to update ./public/index.html to:

  1. remove %PUBLIC_URL%
  2. add a <script src="/src/index.js" async type="module"></script> to the document body.

I don't know if you have intentions to include support within bun to handle this out of the box.
I'd imagine if bun is going to be only for development workflows, then you wouldn't want to mess with the index.html file.

Copy source lines when generating error messages

Since we recycle source code buffers, if we don't immediately print error messages (most of the time we print later), the printed sourcecode is potentially garbage memory & often from the wrong file

While we're at it, we probably should implement the SourceLineTracker thing esbuild does to make generating the error location info faster

Allow spaces in paths

Currently Bun doesn't escape spaces in paths which result in a truncated path & is causing module not found errors.

Fix Catalina support

Need to set the minimum OS target in the build.zig file for macOS x64.

Shouldn't be any other code changes.

Filing an issue so I remember

Windows Support

The README and releases tab implies that Windows is not supported for this project.
Is this due to WebKit (JavaScriptCore) being exclusive to *nix platforms (Linux, macOS)?
Are there any plans to support Windows?

The project works great on linux btw 😀🚀

Finish implementing React Fast Refresh transforms

Exported components correctly register with react-refresh/runtime. But:

  • Non-exported components need to be registered
  • Hooks need to be registered
  • When building from websockets, the signature hashes need to be generated.

The current version may blow away state changes.

Fix calling #private() functions in classes

in:

class foo {
  #private() {
    this.#bar();
  }
  #bar() {}
}

current out:

❯ ./build/debug/macos-x86_64/esdev ./src/test/fixtures/nullish-coalesce.js


error: Unexpected private identifier. This is an internal error - not your fault.
}

src/test/fixtures/nullish-coalesce.js:6:2 62
thread 14325726 panic:

error: Unexpected private identifier. This is an internal error - not your fault.
}

src/test/fixtures/nullish-coalesce.js:6:2 62
/Users/jarred/Code/esdev/src/global.zig:343:28: 0x10ac5f8e0 in src.global.Global.panic (esdev)
            std.debug.panic(fmt, args);
                           ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:8992:25: 0x10aab30bb in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).panic (esdev)
            Global.panic("{s}", .{panic_buffer});
                        ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10361:28: 0x10a7b47e8 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExprInOut (esdev)
                    p.panic("Unexpected private identifier. This is an internal error - not your fault.", .{});
                           ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10179:20: 0x10a7ae0a2 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExpr (esdev)
            return @call(.{ .modifier = .always_inline }, P.visitExprInOut, .{ p, expr, ExprIn{} });
                   ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10862:47: 0x10a7b6871 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExprInOut (esdev)
                        e_.index = p.visitExpr(e_.index);
                                              ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:11216:49: 0x10a7b87ca in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExprInOut (esdev)
                    e_.target = p.visitExprInOut(e_.target, ExprIn{
                                                ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10179:20: 0x10a7ae0a2 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExpr (esdev)
            return @call(.{ .modifier = .always_inline }, P.visitExprInOut, .{ p, expr, ExprIn{} });
                   ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:12031:45: 0x10a7a76b0 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitAndAppendStmt (esdev)
                    data.value = p.visitExpr(data.value);
                                            ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:13238:41: 0x10a7a4e0f in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitStmts (esdev)
                try p.visitAndAppendStmt(list, stmt);
                                        ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10153:29: 0x10a7a441a in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitStmtsAndPrependTempRefs (esdev)
            try p.visitStmts(stmts, opts.kind);
                            ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10218:43: 0x10a7aca15 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitFunc (esdev)
            p.visitStmtsAndPrependTempRefs(&stmts, &temp_opts) catch unreachable;
                                          ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:11284:42: 0x10a7b8c54 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExprInOut (esdev)
                    e_.func = p.visitFunc(e_.func, expr.loc);
                                         ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:10179:20: 0x10a7ae0a2 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitExpr (esdev)
            return @call(.{ .modifier = .always_inline }, P.visitExprInOut, .{ p, expr, ExprIn{} });
                   ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:13127:53: 0x10a7ad278 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitClass (esdev)
                        property.value = p.visitExpr(val);
                                                    ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:12331:52: 0x10a7a8a18 in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitAndAppendStmt (esdev)
                    const shadow_ref = p.visitClass(stmt.loc, &data.class);
                                                   ^
/Users/jarred/Code/esdev/src/js_parser/js_parser.zig:13238:41: 0x10a7a4e0f in src.js_parser.js_parser.NewParser((struct src.js_parser.js_parser.ParserFeatures constant)).visitStmts (esdev)
                try p.visitAndAppendStmt(list, stmt);
                                        ^
^C

expected out:

class foo {
  #private() {
    this.#bar();
  }
  #bar() {}
}

Or transpile it using the WeakMap technique. Probably transpile it since Safari support isn't great for all the syntax.

error: Unterminated string literal

Bun 0.44 shows an error when parsing a long array of strings:

Error: SyntaxError

warn: Please run `bun bun` from a directory containing a package.json.

error: Unterminated string literal

Found with a small project:

yarn add faker

Create index.js:

require('faker');

This then errors:

bun bun ./index.js

Method calls on numeric literals

Error seen when hot reloading code in Chrome:

Uncaught SyntaxError: Invalid or unexpected token

Using bun dev using bun version 0.0.48. Code within an npm package included this expression:

parseFloat((0.0).toPrecision(precision) + '1')

The code hot-reloaded was:

parseFloat(0.toPrecision(precision) + '1')

It appears bun removed the parenthesis around the number, rendering the code syntactically invalid.

FWIW: adding a space would make it valid:

parseFloat(0 .toPrecision(precision) + '1')

Improve reliability of CommonJS <> ESM interop

Importing either CommonJS or ES Modules should work at least as well as it does on Node.js and/or Webpack.

While the common case often works fine, there are many edgecases to consider:

  • Why doesn't @mdx-js/runtime work correctly? Currently, it throws due to module.exports.default being marked read only. This is a symptom of a larger issue. One possible fix here is to change all assignments to module.exports to happen via Object.defineProperty instead of an assignment. This change should happen in the JS parser and not the printer.
  • Functions that recursively loop over the keys of an exported module/namespace eventually stack overflow. This happens because we currently set default to point to module.exports, i.e. module.exports.default === module.exports. This solves many issues with CommonJS interop, but ultimately is too fragile to keep. A better solution is wrapping in a require which checks for the existence of a Symbol marked as non-enumerable.

However, fixing one-off issues like these as they happen will not produce reliable software. These problems need to be fixed, but to ensure they stay fixed, an integration test suite that runs popular NPM packages and makes sure they successfully load/execute is a better plan. That should be run in an untrusted environment, like a GitHub actions runner and it should not have any permissions or secret keys. It should just have a bun binary preinstalled.

Fix `browser` map

  • Options.Platform.bun should import what browsers do
  • Options.Platform.browser should import what browsers do
  • Options.Platform.neutral should import what browsers do
  • Options.Platform.node should ignore it

These are good test cases:

import algoliasearch from 'algoliasearch/lite'
import { captureException, Severity } from '@sentry/nextjs'

Add a fast `npm install` to Bun's CLI

this is mostly stream of conscious

Why?

  1. npm install is too slow.
  2. Resolving node_modules is too slow. This affects bundlers and Node.js (bun as well)

How to make npm install faster

  • Tooling written in Zig launches much faster than Node.js-based tooling by default
  • binary lockfile format
  • Use a faster zlib library to go from .tar.gz -> .tar. cloudflare's zlib or https://github.com/ebiggers/libdeflate
  • On Linux, use io_uring for I/O
  • Parsing semver versions & ranges should not use regex and allocate as little memory as possible. No copying strings around

The disk cache is a question I'm still thinking about.

  • Probably wouldn't do caching via many small files on disk. Many small files == a lot of syscall overhead and npm clients are performance constrained by (1) network latency to resolve dependent package versions, (2) downloading files and (3) syscall overhead. The common case of running npm install on a package with a lockfile and no changes to dependencies is almost entirely constrained by syscall overhead.
  • A memory-mapped database such as LMDB could be fast, but I worry about reliability and remote filesystems. It could detect, warn & disable the cache if the filesystem is remote.
  • SQLite is a safe bet, but writes aren't very fast. It would be interesting to try storing blobs inside a "packages" table. Store package names, last updated, then a blob which is a semver sorted array of versions that are known to exist in the registry. Don't bother to cache any of the rest of the package.json, reparse it each time.

The purpose of this disk cache would solely be for preventing the extra network trip to the NPM registry to resolve package versions

Then, for storing the .tar.gz files, I would try just sticking them all in a big folder. The problem with large folders is reading the directory entries gets slower. To fix that, I'd try an index file which would be a binary file with a default name like index.cache that would effectively be a hash table stored on disk where the keys are filenames. I would test that this is faster in practice than just attempting to open the .tar.gz which may not exist and handling the error. I would also test if using LMDB is worthwhile for this too.

A lockfile format that makes other tooling faster

npm clients & bundlers both have to traverse node_modules. npm clients know the entire directory tree at package install time, but do not expose this information to other tooling.

Bun would do this differently.

A hypothetical bun install would persist a lockfile with the entire node_modules directory tree metadata in one binary lockfile and a subset of each package.json relevant to bundling (along with resolved versions and the resolution method, such as whether it was a .tar.gz file or a URL import). This would dramatically reduce the number of syscalls necessary to resolve imports. Instead of calling getdents() for nearly every directory in node_modules, bundlers could attempt to open file paths directly

URL imports could become "packages" via this lockfile as well.

The lockfile schema would be written using peechy, which would enable JavaScript and Go tooling to consume it as well.

For reviewability, this would be an executable file which on execution would print a human-readable version of the file (same as .bun files). Assumption: in practice, engineers largely don't review lockfiles by reading them. github bots are fundamentally better suited to surfacing changes in lockfiles for humans to review

Like with .bun files, the metadata would be numbers and pointers to byte offsets pointing to a single large combined string at the bottom of the file, which makes reading this potentially large file faster.

For symlinks and workspace packages, it wouldn't persist a directory tree. Those would quickly become outdated.

Fix ?? operator

in:

var hello = foo ?? "world";

current out:

var hello = foo;

expected out:

var hello = foo ?? "world";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.