Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
966645b
Remove picohttpparser from the build
claude Oct 27, 2026
f49bce4
Add bun_http1: response heads and chunked bodies in safe Rust
claude Oct 27, 2026
a62095b
Parse fetch and WebSocket responses with bun_http1
claude Oct 27, 2026
393931b
Update what still described picohttpparser as linked
claude Oct 27, 2026
7aaa18c
bun_http1: reject LF after a chunk size where it is seen
claude Oct 27, 2026
d101a6e
bun_http1: go from one chunk state to the next without a jump table
claude Oct 27, 2026
5ca2d69
Merge branch 'main-9b8347a2' into claude/picohttpparser-rust-replacem…
claude Oct 27, 2026
e0cd483
bun_http1: leave the decoder in picohttpparser's state after every error
claude Oct 27, 2026
6ad9c30
Test the response parser against results recorded from picohttpparser
claude Oct 27, 2026
b954bc2
http1-golden: fail instead of hanging, and keep the results that came…
claude Oct 27, 2026
82fc7ae
bun-types test: list http1_testing.bind.ts among the unpublished schemas
claude Oct 27, 2026
3120dcb
http1-golden: every byte value at every kind of position
claude Oct 27, 2026
42c689a
bun_http1: less work around the searches and the moves
claude Oct 27, 2026
84de2f6
bun_http1: tests that could not fail, and the missing ones
claude Oct 27, 2026
de2e587
bun_http1: a test for every bug in picohttpparser's history
claude Oct 27, 2026
b6c3809
bun_http1: carry picohttpparser's notice
claude Oct 27, 2026
2995f64
bun_http1: drop the end of the C comment from the notice
claude Oct 27, 2026
af762c9
Merge remote-tracking branch 'origin/main' into claude/picohttpparser…
claude Oct 28, 2026
d05dbc3
http1Internals.parseResponse: at most 65535 slots
claude Oct 28, 2026
b5dbacf
Merge remote-tracking branch 'origin/main' into claude/picohttpparser…
claude Oct 29, 2026
6107158
test/aot: an IR test that does not depend on the ids of the built-ins
claude Oct 29, 2026
633b353
bun_http1: record why its search is not a Highway kernel
claude Oct 29, 2026
4f191b1
Merge remote-tracking branch 'origin/main' into claude/picohttpparser…
claude Nov 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ codegen-for-zig-team.tar.gz
/src/deps/lol*html
/src/deps/ls*hpack
/src/deps/mimalloc
/src/deps/picohttpparser
/src/deps/tinycc
/src/deps/WebKit
/src/deps/zig
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The ke

#### Vendored Dependencies (`vendor/`)

Third-party native libraries are vendored locally and can be read from disk (not git submodules): boringssl (TLS/crypto), brotli, cares (async DNS), highway (SIMD), libdeflate, libuv (Windows event loop), lolhtml (HTML rewriter), lshpack (HTTP/2 HPACK), lsqpack + lsquic (HTTP/3), mimalloc (allocator), nodejs (headers), picohttpparser, rust-argon2 (argon2 for `Bun.password`, Rust), tinycc (FFI JIT, fork: oven-sh/tinycc), WebKit (JavaScriptCore), zlib (zlib-ng), zstd. Build configuration for these is in `scripts/build/deps/*.ts`.
Third-party native libraries are vendored locally and can be read from disk (not git submodules): boringssl (TLS/crypto), brotli, cares (async DNS), highway (SIMD), libdeflate, libuv (Windows event loop), lolhtml (HTML rewriter), lshpack (HTTP/2 HPACK), lsqpack + lsquic (HTTP/3), mimalloc (allocator), nodejs (headers), rust-argon2 (argon2 for `Bun.password`, Rust), tinycc (FFI JIT, fork: oven-sh/tinycc), WebKit (JavaScriptCore), zlib (zlib-ng), zstd. Build configuration for these is in `scripts/build/deps/*.ts`.

### JavaScript Class Implementation (C++)

Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"src/bundler",
"src/collections",
"src/css",
"src/errno",

Check warning on line 11 in Cargo.toml

View workflow job for this annotation

GitHub Actions / lol-html cargo test

explicit `package.readme` can be inferred
"src/glob",
"src/http",
"src/install",
Expand Down Expand Up @@ -61,6 +61,7 @@
"src/exe_format",
"src/highway",
"src/histogram",
"src/http1",
"src/http_jsc",
"src/http_types",
"src/ini",
Expand Down Expand Up @@ -431,6 +432,7 @@
bun_exe_format = { path = "src/exe_format" }
bun_highway = { path = "src/highway" }
bun_histogram = { path = "src/histogram" }
bun_http1 = { path = "src/http1" }
bun_http_jsc = { path = "src/http_jsc" }
bun_http_types = { path = "src/http_types" }
bun_ini = { path = "src/ini" }
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Bun statically links these libraries:
| [`ls-qpack`](https://github.com/litespeedtech/ls-qpack) | MIT |
| [`lsquic`](https://github.com/litespeedtech/lsquic) | MIT (portions derived from [Chromium proto-quic](https://github.com/litespeedtech/lsquic/blob/master/LICENSE.chrome), BSD 3-Clause) |
| [`mimalloc`](https://github.com/microsoft/mimalloc) | MIT |
| [`picohttp`](https://github.com/h2o/picohttpparser) | dual-licensed under the Perl License or the MIT License |
| [`picohttp`](https://github.com/h2o/picohttpparser) (not linked: `src/http1` is derived from it) | [dual-licensed under the Perl License or the MIT License](src/http1/LICENSE) |
| [`zstd`](https://github.com/facebook/zstd) | dual-licensed under the BSD License or GPLv2 license |
| [`simdutf`](https://github.com/simdutf/simdutf) | Apache 2.0 |
| [`tinycc`](https://github.com/tinycc/tinycc) | LGPL v2.1 |
Expand Down
2 changes: 1 addition & 1 deletion docs/project/license.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Bun statically links these libraries:
| [`ls-qpack`](https://github.com/litespeedtech/ls-qpack) | MIT |
| [`lsquic`](https://github.com/litespeedtech/lsquic) | MIT (portions derived from Chromium proto-quic, BSD 3-Clause) |
| [`mimalloc`](https://github.com/microsoft/mimalloc) | MIT |
| [`picohttp`](https://github.com/h2o/picohttpparser) | dual-licensed under the Perl License or the MIT License |
| [`picohttp`](https://github.com/h2o/picohttpparser) (not linked: `src/http1` is derived from it) | dual-licensed under the Perl License or the MIT License |
| [`zstd`](https://github.com/facebook/zstd) | dual-licensed under the BSD License or GPLv2 license |
| [`simdutf`](https://github.com/simdutf/simdutf) | Apache 2.0 |
| [`tinycc`](https://github.com/tinycc/tinycc) | LGPL v2.1 |
Expand Down
55 changes: 0 additions & 55 deletions patches/picohttpparser/chunked-decoder.patch

This file was deleted.

40 changes: 12 additions & 28 deletions scripts/build/bun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,7 @@ export function emitBun(n: Ninja, cfg: Config, sources: Sources): BunOutput {
}
}

// Collect all dep lib paths, include dirs, output stamps, and directly-
// compiled source files (deps like picohttpparser that provide .c files
// instead of a .a — we compile those alongside bun's own sources).
// Collect all dep lib paths, include dirs and output stamps.
const depLibs: string[] = [];
const depObjects: string[] = [];
const depIncludes: string[] = [];
Expand Down Expand Up @@ -311,9 +309,6 @@ export function emitBun(n: Ninja, cfg: Config, sources: Sources): BunOutput {
noPchSources.add(rescleBinding);
}

// Deps with provides.sources compiled in the loop below so each dep's
// phony can point at its own .o files.

// Codegen .cpp files — compiled like regular sources.
cxxSources.push(...codegen.cppSources);

Expand Down Expand Up @@ -371,16 +366,15 @@ export function emitBun(n: Ninja, cfg: Config, sources: Sources): BunOutput {

// Compile all .c files. No PCH — dep signal applied directly.
const cObjects: string[] = [];
const compileC = (src: string): string => {
const obj = cc(n, cfg, src, {
flags: cFlagsFull,
implicitInputs: depHeaderSignal,
orderOnlyInputs: codegenOrderOnly,
});
cObjects.push(obj);
return obj;
};
for (const src of cSources) compileC(src);
for (const src of cSources) {
cObjects.push(
cc(n, cfg, src, {
flags: cFlagsFull,
implicitInputs: depHeaderSignal,
orderOnlyInputs: codegenOrderOnly,
}),
);
}

// InternalModuleRegistryConstants.S — `.incbin`s the bundled JS module sources
// so InternalModuleRegistry.cpp sees a tiny {offset, length} table instead of
Expand All @@ -395,16 +389,6 @@ export function emitBun(n: Ninja, cfg: Config, sources: Sources): BunOutput {
}),
);

// Deps that contribute source files for bun to compile directly (via
// provides.sources) instead of building a lib. Compile them here with
// bun's full flag set and give each a phony so `--target <name>` builds
// its .o files. libs.length === 0 guard: deps with a build step already
// got a phony in resolveDep — don't emit a duplicate.
for (const d of deps) {
if (d.sources.length === 0 || d.libs.length > 0) continue;
n.phony(d.name, d.sources.map(compileC));
}

// Dep objects (when !cfg.archiveDeps) are linked alongside bun's own
// objects, in the same response file. With cfg.archiveDeps they live in
// depLibs as .a files instead.
Expand Down Expand Up @@ -1021,12 +1005,12 @@ export function validateBunConfig(cfg: Config): void {
`--local-deps: ${name} is disabled for ${cfg.os}-${cfg.arch}${cfg.abi ? `-${cfg.abi}` : ""} in this configuration, so the checkout at ${path} would never be built`,
{ hint: `Drop ${name} from --local-deps, or build a target/config where its \`enabled\` predicate holds` },
);
// A dep the graph fetches but never reads (no build step, no sources, no
// A dep the graph fetches but never reads (no build step, no
// includes — lolhtml, which cargo consumes through the workspace
// Cargo.toml's `path = "vendor/lolhtml"`) can't be redirected from here.
const provides = dep.provides(cfg);
assert(
dep.build(cfg).kind !== "none" || (provides.sources ?? []).length > 0 || provides.includes.length > 0,
dep.build(cfg).kind !== "none" || provides.includes.length > 0,
`--local-deps: ${name} is only fetched by the build graph, never compiled or included by it, so redirecting it to ${path} would change nothing`,
{
hint: `Point ${name}'s real consumer at the checkout instead (for a cargo path dependency: the workspace Cargo.toml)`,
Expand Down
5 changes: 1 addition & 4 deletions scripts/build/deps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { lsqpack } from "./lsqpack.ts";
import { lsquic } from "./lsquic.ts";
import { mimalloc } from "./mimalloc.ts";
import { nodejsHeaders } from "./nodejs-headers.ts";
import { picohttpparser } from "./picohttpparser.ts";
import { rustArgon2 } from "./rust-argon2.ts";
import { sqlite } from "./sqlite.ts";
import { tinycc } from "./tinycc.ts";
Expand All @@ -42,8 +41,7 @@ import { zstd } from "./zstd.ts";
* boringssl near the end — many things depend on crypto/ssl symbols.
*/
export const allDeps: readonly Dependency[] = [
// Header-only / source-only first — no link order concerns.
picohttpparser,
// Header-only first — no link order concerns.
nodejsHeaders,

zlib,
Expand Down Expand Up @@ -91,7 +89,6 @@ export {
lsquic,
mimalloc,
nodejsHeaders,
picohttpparser,
rustArgon2,
sqlite,
tinycc,
Expand Down
40 changes: 0 additions & 40 deletions scripts/build/deps/picohttpparser.ts

This file was deleted.

1 change: 0 additions & 1 deletion scripts/build/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,6 @@ export function bunIncludes(cfg: Config): string[] {
join(cwd, "src/uws_sys"),
codegenDir,
vendorDir,
join(vendorDir, "picohttpparser"),
join(vendorDir, "zlib"),
// NODEJS_HEADERS_PATH comes from the nodejs dep; added separately
];
Expand Down
43 changes: 9 additions & 34 deletions scripts/build/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,16 +424,6 @@ export interface Provides {
includes: string[];
/** Preprocessor defines to add to bun's compilation. */
defines?: string[];
/**
* Source files (relative to the SOURCE dir) that bun compiles directly
* into its own binary — no nested build producing a `.a`. Declared as
* implicit outputs of the fetch rule so ninja knows where they come from;
* bun.ts adds them to its C/C++ source lists.
*
* Most deps provide `.a` files via `libs`. This is for the rare case of
* a single-file dep with no build system (picohttpparser: one .c file).
*/
sources?: string[];
}

/**
Expand All @@ -458,7 +448,6 @@ export type DepName =
| "lsquic"
| "mimalloc"
| "nodejs"
| "picohttpparser"
| "rust-argon2"
| "sqlite"
| "tinycc"
Expand Down Expand Up @@ -546,11 +535,6 @@ export interface ResolvedDep {
/** Absolute include paths for -I flags. */
includes: string[];
defines: string[];
/**
* Absolute paths to .c/.cpp files bun compiles directly (from
* Provides.sources). Empty for most deps — they provide .a files.
*/
sources: string[];
/**
* The final build output(s). Use these as implicit inputs on anything
* downstream that needs this dep built first.
Expand Down Expand Up @@ -833,15 +817,10 @@ export function resolveDep(
// we don't want patches changing between emitFetch and the hash check.
const patches = dep.patches === undefined ? [] : typeof dep.patches === "function" ? dep.patches(cfg) : dep.patches;

// Sources bun compiles directly (from Provides.sources). Resolved to
// absolute paths for (a) the ResolvedDep return and (b) declaring as
// implicit outputs of fetch so ninja knows where they come from.
const resolvedSources = (provides.sources ?? []).map(s => resolve(srcDir, s));

// DirectBuild sources are ALSO compiled in our ninja graph, so they need
// the same implicit-output-of-fetch treatment. Include the codegen tool
// source, its input, and any HeaderSubst templates — all read at build
// time from the fetched tree.
// DirectBuild sources are compiled in our ninja graph, so they are declared
// as implicit outputs of fetch: ninja then knows where they come from.
// Include the codegen tool source, its input, and any HeaderSubst
// templates — all read at build time from the fetched tree.
const directSources: string[] = [];
if (buildSpec.kind === "direct") {
for (const s of buildSpec.sources) {
Expand All @@ -865,7 +844,7 @@ export function resolveDep(
// (CMakeLists.txt) as the stamp. Editing it → reconfigure.
let sourceStamp: string | undefined;
if (source.kind === "github-archive") {
sourceStamp = emitFetch(n, cfg, dep.name, source, patches, [...resolvedSources, ...directSources]);
sourceStamp = emitFetch(n, cfg, dep.name, source, patches, directSources);
} else {
// Local/in-tree: no .ref to write. Use the build system's manifest file
// as the stamp — touching it triggers reconfigure/rebuild.
Expand Down Expand Up @@ -949,9 +928,7 @@ export function resolveDep(
// are link inputs, not include-order dependencies).
outputs = result.headerOutputs;
} else {
// No build step. The fetch stamp (if any) is the only output. For deps
// with provides.sources (picohttpparser), emitBun adds a phony pointing
// at the compiled .o files so `--target <name>` actually compiles them.
// No build step. The fetch stamp (if any) is the only output.
libs = [];
outputs = sourceStamp === undefined ? [] : [sourceStamp];
}
Expand All @@ -975,7 +952,6 @@ export function resolveDep(
objects,
includes,
defines: provides.defines ?? [],
sources: resolvedSources,
outputs,
checks,
};
Expand Down Expand Up @@ -1018,9 +994,9 @@ function emitFetch(

n.build({
outputs: [refStamp],
// Source files bun compiles directly (picohttpparser.c). Declaring
// them as outputs tells ninja "fetch creates these" — otherwise ninja
// errors "missing and no known rule to make it" on fresh checkouts.
// Source files our graph compiles. Declaring them as outputs tells ninja
// "fetch creates these" — otherwise ninja errors "missing and no known
// rule to make it" on fresh checkouts.
...(compiledSources.length > 0 && { implicitOutputs: compiledSources }),
rule: "dep_fetch",
inputs: [],
Expand Down Expand Up @@ -1107,7 +1083,6 @@ function emitPrebuilt(
checks: [],
includes,
defines: provides.defines ?? [],
sources: [],
outputs,
};
}
Expand Down
1 change: 1 addition & 0 deletions scripts/rust-miri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const MIRI_CRATES = [
"bun_sema",
"bun_ast",
"bun_paths",
"bun_http1",
"bun_hash",
"bun_base64",
"bun_bundler",
Expand Down
Loading
Loading