bun-v0.0.83
版本发布时间: 2022-05-17 12:23:44
oven-sh/bun最新发布版本:bun-v1.1.20(2024-07-13 14:04:45)
To upgrade:
bun upgrade
Having trouble upgrading?
You can also try the install script.
curl https://bun.sh/install | bash
Thanks to:
- @kriszyp for tons of helpful feedback on how to improve Node-API support in bun
- @evanwashere for the idea & name for the
CFunction
abstraction - @adaptive for replacing
"wrangler@beta"
with"wrangler"
in the examples forbun add
- @littledivy for adding a couple missing packages to the build instructions
bun:sqlite
bun:sqlite
is a high-performance builtin SQLite module for bun.js.
It tends to be around 3x faster than the popular better-sqlite3
npm package
Note: in the benchmark I tweeted earlier, better-sqlite3
always returned arrays of arrays rather than arrays of objects, which was inconsistent with what bun:sqlite
& deno's x/sqlite were doing
Usage
import { Database } from "bun:sqlite";
const db = new Database("mydb.sqlite");
db.run(
"CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY AUTOINCREMENT, greeting TEXT)"
);
db.run("INSERT INTO foo (greeting) VALUES (?)", "Welcome to bun!");
db.run("INSERT INTO foo (greeting) VALUES (?)", "Hello World!");
// get the first row
db.query("SELECT * FROM foo").get();
// { id: 1, greeting: "Welcome to bun!" }
// get all rows
db.query("SELECT * FROM foo").all();
// [
// { id: 1, greeting: "Welcome to bun!" },
// { id: 2, greeting: "Hello World!" },
// ]
// get all rows matching a condition
db.query("SELECT * FROM foo WHERE greeting = ?").all("Welcome to bun!");
// [
// { id: 1, greeting: "Welcome to bun!" },
// ]
// get first row matching a named condition
db.query("SELECT * FROM foo WHERE greeting = $greeting").get({
$greeting: "Welcome to bun!",
});
// [
// { id: 1, greeting: "Welcome to bun!" },
// ]
There are more detailed docs in Bun's README
bun:sqlite
's API is loosely based on @joshuawise's better-sqlite3
New in bun:ffi
CFunction
lets you call native library functions from a function pointer.
It works like dlopen
but its for cases where you already have the function pointer so you don't need to open a library. This is useful for:
- callbacks passed from native libraries to JavaScript
- using Node-API and bun:ffi together
import {CFunction} from 'bun:ffi';
const myNativeLibraryGetVersion: number | bigint = /* Somehow you got this function pointer */
const getVersion = new CFunction({
returns: "cstring",
args: [],
// ptr is required
// this is where the function pointer goes!
ptr: myNativeLibraryGetVersion,
});
getVersion();
getVersion.close();
linkSymbols
is like CFunction
except for when there are multiple functions. It returns the same object as dlopen
except ptr
is required and there is no path
import { linkSymbols } from "bun:ffi";
const [majorPtr, minorPtr, patchPtr] = getVersionPtrs();
const lib = linkSymbols({
// Unlike with dlopen(), the names here can be whatever you want
getMajor: {
returns: "cstring",
args: [],
// Since this doesn't use dlsym(), you have to provide a valid ptr
// That ptr could be a number or a bigint
// An invalid pointer will crash your program.
ptr: majorPtr,
},
getMinor: {
returns: "cstring",
args: [],
ptr: minorPtr,
},
getPatch: {
returns: "cstring",
args: [],
ptr: patchPtr,
},
});
const [major, minor, patch] = [
lib.symbols.getMajor(),
lib.symbols.getMinor(),
lib.symbols.getPatch(),
];
new CString(ptr)
should be a little faster due to using a more optimized function for getting the length of a string.
require.resolve()
Running require.resolve("my-module")
in Bun.js will now resolve the path to the module. Previously, this was not supported.
In browsers, it becomes the absolute filepath at build-time. In node, it's left in without any changes.
Internally, Bun's JavaScript transpiler transforms it to:
// input:
require.resolve("my-module");
// output
import.meta.resolveSync("my-module");
You can see this for yourself by running bun build ./file.js --platform=bun
"node:module"
module polyfill
Node's "module"
module lets you create require functions from ESM modules.
Bun now has a polyfill that implements a subset of the "module"
module.
Normally require()
in bun transforms statically at build-time to an ESM import
statement. That doesn't work as well for Node-API (napi) modules because they cannot be statically analyzed by a JavaScript parser (since they're not JavaScript).
For napi modules, bun uses a dynamic require function and the "module"
module exports a way to create those using the same interface as in Node.js
import { createRequire } from "module";
// this also works:
//import {createRequire} from 'node:module';
var require = createRequire(import.meta.url);
require.resolve("my-module");
// dynamic require is supported for:
// - .json files
// - .node files (napi modules)
require("my-napi-module");
This is mostly intended for improving Node-API compatibility with modules loaded from ESM.
As an extra thing, you can also use require()
this way for .json files.
Bun.Transpiler – pass objects to macros
Bun.Transpiler
now supports passing objects to macros.
import { Transpiler } from "bun";
import { parseCookie } from "my-cookie-lib";
import { Database } from "bun:sqlite";
const transpiler = new Transpiler();
const db = new Database("mydb.sqlite");
export default {
fetch(req) {
const transpiled = transpiler.transformSync(
`
import {getUser} from 'macro:./get-user';
export function Hello({name}) {
return <div>Hello {name}</div>;
}
export const HelloCurrentUser = <Hello {...getUser()} />;
`,
// passing contextual data to Bun.Transpiler
{
userId: parseCookie(req.headers.get("Cookie")).userId,
db: db,
}
);
return new Response(transpiled, {
headers: { "Content-Type": "application/javascript" },
});
},
};
Then, in get-user.js
:
// db, userId is now accessible in macros
export function getUser(expr, { db, userId }) {
// we can use it to query the database while transpiling
return db.query("SELECT * FROM users WHERE id = ? LIMIT 1").get(userId);
}
That inlines the returned current user into the JavaScript source code, producing output equivalent to this:
export function Hello({ name }) {
return <div>Hello {name}</div>;
}
// notice that the current user is inlined rather than a function call
export const HelloCurrentUser = <Hello name="Jarred" />;
Bug fixes
-
Buffer.from(arrayBuffer, byteOffset, length)
now works as expected (thanks to @kriszyp for reporting)
Misc
- Receiving and sending strings to Node-API modules should be a little faster
1、 bun-darwin-aarch64.dSYM.tar.gz 15.26MB
2、 bun-darwin-aarch64.zip 11.72MB
3、 bun-darwin-x64.dSYM.tar.gz 16.6MB
4、 bun-darwin-x64.zip 13.96MB
5、 bun-linux-x64.zip 27.84MB