Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 13 additions & 6 deletions crates/perry-api-manifest/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,16 +461,23 @@ fn source_dts_tag(entry: &ApiEntry) -> &'static str {
}
}

/// Markdown anchor for a heading. mdbook lowercases and replaces
/// non-alphanum with `-`. Matches its slugifier closely enough for
/// the in-page TOC to land.
/// Markdown anchor for a heading, matching mdbook's `normalize_id`
/// (github-slugifier): keep alphanumerics + `_`/`-`, lowercase, turn
/// whitespace into `-`, and DROP every other punctuation character.
///
/// The distinction matters for module names with punctuation: mdbook
/// slugs `bun:ffi` → `bunffi` and `mysql2/promise` → `mysql2promise`
/// (the `:` / `/` are removed, NOT turned into `-`). The previous
/// "replace every non-alphanumeric with `-`" produced `bun-ffi` /
/// `mysql2-promise`, so the in-page TOC links jumped nowhere. (#6580)
fn anchor(s: &str) -> String {
s.chars()
.filter(|c| c.is_alphanumeric() || *c == '_' || *c == '-' || c.is_whitespace())
.map(|c| {
if c.is_ascii_alphanumeric() {
c.to_ascii_lowercase()
} else {
if c.is_whitespace() {
'-'
} else {
c.to_ascii_lowercase()
}
})
.collect()
Expand Down
5 changes: 5 additions & 0 deletions crates/perry-api-manifest/src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub const NATIVE_MODULES: &[&str] = &[
"sqlite",
"tursodb",
"iroh",
// #6562: Bun FFI (C-ABI). The `bun:` prefix is part of the specifier
// (unlike `node:`, which is stripped) — `import { dlopen } from "bun:ffi"`.
"bun:ffi",
"node-cron",
"nodemailer",
"http",
Expand Down Expand Up @@ -204,6 +207,8 @@ pub const RUNTIME_ONLY_MODULES: &[&str] = &[
"path/win32",
"os",
"buffer",
// #6562: bun:ffi is implemented entirely in perry-runtime.
"bun:ffi",
"assert",
"assert/strict",
"test",
Expand Down
29 changes: 29 additions & 0 deletions crates/perry-api-manifest/src/entries/part_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,35 @@ pub(crate) const API_MANIFEST_PART_1: &[ApiEntry] = &[
method("better-sqlite3", "pluck", true, None),
method("better-sqlite3", "columns", true, None),
method("better-sqlite3", "transaction", true, None),
// bun:ffi (#6562) — stage-1 surface. `FFIType` and `suffix` are
// constants; symbol-table call stubs live on the object `dlopen`
// returns, so the module surface itself is small. The stage-2/3
// exports (toArrayBuffer / JSCallback / linkSymbols / CFunction /
// viewSource / read / toBuffer) are declared and throw a descriptive
// ERR_NOT_IMPLEMENTED at runtime.
method("bun:ffi", "dlopen", false, None),
method("bun:ffi", "ptr", false, None),
method("bun:ffi", "CString", false, None),
property("bun:ffi", "FFIType"),
property("bun:ffi", "suffix"),
// Stage ≥2 surface: declared so feature-probes get a clear error rather
// than `undefined is not a function`, but NOT implemented yet — each
// throws at runtime. Marked `.stub_note` so the generated `.d.ts` /
// `reference.md` say so instead of reading as usable APIs (#6562).
method("bun:ffi", "toArrayBuffer", false, None)
.stub_note("stage 2 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "toBuffer", false, None)
.stub_note("stage 2 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "JSCallback", false, None)
.stub_note("stage 3 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "CFunction", false, None)
.stub_note("stage 3 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "linkSymbols", false, None)
.stub_note("stage ≥2 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "viewSource", false, None)
.stub_note("stage ≥2 — not yet implemented, throws at runtime (#6562)"),
method("bun:ffi", "read", false, None)
.stub_note("stage ≥2 — not yet implemented, throws at runtime (#6562)"),
class("sqlite", "DatabaseSync"),
class("sqlite", "Session"),
class("sqlite", "SQLTagStore"),
Expand Down
7 changes: 7 additions & 0 deletions crates/perry-api-manifest/tests/stub_inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ fn stub_inventory_matches_known_clusters() {
// event-loop refcount), mongodb.findOne (parsed document),
// exponential-backoff options (honored, incl. retry predicate).
("#4917", 9),
// #6562 (bun:ffi stage 1) — the stage-≥2 FFI surface is declared so
// feature probes get a clear error, but throws at runtime until the
// later stages land: toArrayBuffer, toBuffer, JSCallback, CFunction,
// linkSymbols, viewSource, read.
("#6562", 7),
];
let expected_map: BTreeMap<String, usize> =
expected.iter().map(|(k, v)| (k.to_string(), *v)).collect();
Expand All @@ -119,6 +124,8 @@ fn stubs_only_appear_in_allowlisted_modules() {
"exponential-backoff",
"inspector",
"repl",
// #6562: bun:ffi stage-≥2 exports are declared-but-throwing stubs.
"bun:ffi",
];
for e in iter_entries().filter(|e| e.stub) {
assert!(
Expand Down
4 changes: 4 additions & 0 deletions crates/perry-codegen/src/nm_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ pub(crate) fn nm_install_symbol(name: &str) -> Option<&'static str> {
"bigint" => Some("js_nm_install_bigint"),
"buffer" | "buffer.Buffer" => Some("js_nm_install_buffer"),
"bun" => Some("js_nm_install_bun"),
// #6562: bun:ffi keeps its scheme prefix (only `node:` is stripped
// above).
"bun:ffi" => Some("js_nm_install_bun_ffi"),
"child_process" => Some("js_nm_install_child_process"),
"cluster" => Some("js_nm_install_cluster"),
"console" => Some("js_nm_install_console"),
Expand Down Expand Up @@ -71,6 +74,7 @@ pub(crate) const NM_INSTALL_SYMBOLS: &[&str] = &[
"js_nm_install_bigint",
"js_nm_install_buffer",
"js_nm_install_bun",
"js_nm_install_bun_ffi",
"js_nm_install_child_process",
"js_nm_install_cluster",
"js_nm_install_console",
Expand Down
2 changes: 2 additions & 0 deletions crates/perry-codegen/src/runtime_decls/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ pub fn declare_phase_b_objects(module: &mut LlModule) {
module.declare_function("js_nm_install_bigint", VOID, &[]);
module.declare_function("js_nm_install_buffer", VOID, &[]);
module.declare_function("js_nm_install_bun", VOID, &[]);
// #6562: bun:ffi dispatch bucket.
module.declare_function("js_nm_install_bun_ffi", VOID, &[]);
module.declare_function("js_nm_install_child_process", VOID, &[]);
module.declare_function("js_nm_install_cluster", VOID, &[]);
module.declare_function("js_nm_install_console", VOID, &[]);
Expand Down
Loading
Loading