Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c570c17
perf(http): use pooled Hyper async hosts
fffonion Sep 19, 2026
0822742
fix(http): harden SSE stream framing and ABI
fffonion Sep 19, 2026
dfdf16d
docs(vmbc): update current-version wording
fffonion Sep 19, 2026
ffe2143
refactor(io): simplify async host lifecycles
fffonion Sep 19, 2026
6c6607d
fix(io): make process cleanup cancellation-safe
fffonion Sep 19, 2026
8b5a409
fix(io): reap process leader before cleanup error
fffonion Sep 19, 2026
62b6300
refactor(sqlite): use macro-owned async hosts
fffonion Sep 19, 2026
4184752
fix(sqlite): await adapter close on reset
fffonion Sep 19, 2026
daf6a67
fix(sqlite): harden deadlines and close retries
fffonion Sep 19, 2026
29c474a
fix(sqlite): bound persistent close retries
fffonion Sep 19, 2026
d913b7c
fix(integration): align async host feature gates and fingerprints
fffonion Sep 19, 2026
3671a8a
Remove legacy core compatibility paths
fffonion Sep 19, 2026
1673041
refactor(host): keep domain contracts current-only
fffonion Sep 19, 2026
0f1e81d
fix(build): gate sqlite catalog on wasm
fffonion Sep 19, 2026
3139278
fix(tests): complete pending async bridge stub
fffonion Sep 19, 2026
2994d7f
Enforce Tokio process runtime lease
fffonion Sep 19, 2026
5b01424
fix(vm): require async quiescence for bridge mutation
fffonion Sep 19, 2026
1c3ba70
fix(io): keep blocking process drop nonblocking
fffonion Sep 19, 2026
0dddf7d
fix(sqlite): enforce transaction deadline at commit
fffonion Sep 19, 2026
7796a82
test(sqlite): cover commit-hook deadline veto
fffonion Sep 19, 2026
332ab2c
docs: correct HTTP and async host contracts
fffonion Sep 20, 2026
fc4b95e
docs(host): remove historical SDK guidance
fffonion Sep 20, 2026
87d8c5d
docs: correct host SDK examples and HTTP defaults
fffonion Sep 20, 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
280 changes: 204 additions & 76 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 8 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,14 @@ runtime = []
async = ["runtime", "dep:tokio"]
http-client = [
"async",
"dep:futures-util",
"dep:http-body-util",
"dep:hyper",
"dep:hyper-rustls",
"dep:hyper-util",
"dep:rustls",
"dep:tokio-rustls",
"dep:tower-service",
"dep:url",
"dep:webpki-roots",
]
sqlite = ["runtime", "dep:rusqlite"]
sqlite = ["async", "dep:rusqlite", "dep:tokio-rusqlite"]
edge-abi = [
"dep:edge_abi",
"edge_abi/console",
Expand Down Expand Up @@ -89,7 +87,6 @@ cranelift-jit = { version = "0.129.1", optional = true }
cranelift-module = { version = "0.129.1", optional = true }
cranelift-native = { version = "0.129.1", optional = true }
pd-host-function = { path = "./pd-host-function", version = "0.1.0" }
rusqlite = { version = "0.32", default-features = false, features = ["bundled", "hooks", "limits"], optional = true }
edge_abi = { package = "pd-edge-abi", version = "0.1.1", default-features = false, optional = true }
futures-channel = "0.3"
paste = "1"
Expand All @@ -103,13 +100,13 @@ rustyline = { version = "14", optional = true }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
http-body-util = { version = "0.1", optional = true }
hyper = { version = "1", default-features = false, features = ["client", "http1"], optional = true }
hyper-util = { version = "0.1", default-features = false, features = ["tokio"], optional = true }
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"], optional = true }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"], optional = true }
hyper-rustls = { version = "0.27.7", default-features = false, features = ["http1", "ring", "tls12", "webpki-roots"], optional = true }
hyper-util = { version = "0.1", default-features = false, features = ["client-legacy", "http1", "tokio"], optional = true }
rusqlite = { version = "0.40.1", default-features = false, features = ["bundled", "hooks", "limits"], optional = true }
tokio-rusqlite = { version = "0.8", optional = true }
tower-service = { version = "0.3", optional = true }
url = { version = "2", optional = true }
futures-util = { version = "0.3", optional = true }
tokio = { version = "1", features = ["rt-multi-thread", "net", "time", "sync", "fs", "io-util", "process", "macros"], optional = true }
webpki-roots = { version = "1", optional = true }

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_System_Diagnostics_Debug", "Win32_System_Memory", "Win32_System_ProcessStatus", "Win32_System_Threading"] }
Expand Down
90 changes: 20 additions & 70 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,20 @@ fn main() {

// The SQLite namespace is optional: its builtin module links rusqlite,
// which is not available on every target or without the `sqlite` feature.
// When the feature is off (or the target is wasm32, where rusqlite's
// When the feature is off (or the target family is wasm, where rusqlite's
// bundled build is unsupported), drop the namespace and its static
// catalog IDs so the generated catalog, dispatch, and compiler namespace
// surface stay consistent and feature-clean.
let target_family = env::var("CARGO_CFG_TARGET_FAMILY").expect("missing target family");
let sqlite_enabled = env::var_os("CARGO_FEATURE_SQLITE").is_some()
&& env::var("CARGO_CFG_TARGET_ARCH").as_deref() != Ok("wasm32");
&& !target_family
.split(',')
.any(|family| family.trim() == "wasm");
if !sqlite_enabled {
namespaces.retain(|namespace| namespace.namespace != "sqlite");
catalog.retain(|entry| !entry.source_name.starts_with("sqlite::"));
}

let target_family = env::var("CARGO_CFG_TARGET_FAMILY").expect("missing target family");
let mut host_sources = vec![
SourceSpec {
path: "src/builtins/runtime/host.rs".to_string(),
Expand Down Expand Up @@ -206,8 +208,7 @@ fn main() {
});
}
let async_enabled = env::var_os("CARGO_FEATURE_ASYNC").is_some();
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("missing target architecture");
let builtin_sources = builtin_source_specs(&namespaces, async_enabled, &target_arch);
let builtin_sources = builtin_source_specs(&namespaces, async_enabled, &target_family);
let core_sources = [SourceSpec {
path: "src/builtins/runtime/core.rs".to_string(),
module: "core".to_string(),
Expand Down Expand Up @@ -279,8 +280,11 @@ fn write_generated_file(path: &Path, contents: &str) {
.unwrap_or_else(|err| panic!("failed to write {}: {err}", path.display()));
}

pub(crate) fn select_io_source_path(async_enabled: bool, target_arch: &str) -> &'static str {
if target_arch == "wasm32" {
pub(crate) fn select_io_source_path(async_enabled: bool, target_family: &str) -> &'static str {
if target_family
.split(',')
.any(|family| family.trim() == "wasm")
{
"src/builtins/runtime/io_wasm.rs"
} else if async_enabled {
"src/builtins/runtime/io/async_io.rs"
Expand All @@ -292,13 +296,13 @@ pub(crate) fn select_io_source_path(async_enabled: bool, target_arch: &str) -> &
fn builtin_source_specs(
namespaces: &[NamespaceDecl],
async_enabled: bool,
target_arch: &str,
target_family: &str,
) -> Vec<SourceSpec> {
namespaces
.iter()
.map(|namespace| {
let path = if namespace.module == "io" {
select_io_source_path(async_enabled, target_arch).to_string()
select_io_source_path(async_enabled, target_family).to_string()
} else {
format!("src/builtins/runtime/{}.rs", namespace.module)
};
Expand Down Expand Up @@ -2261,11 +2265,7 @@ fn find_matching_paren(source: &str) -> usize {

#[cfg(test)]
mod tests {
use super::{
HostExecutionKind, NamespaceDecl, SourceCategory, builtin_source_specs,
http_transport_enabled, parse_source_file, select_io_source_path,
};
use std::path::Path;
use super::{http_transport_enabled, select_io_source_path};

#[test]
fn http_transport_predicate_matches_source_and_catalog_boundary() {
Expand All @@ -2277,83 +2277,33 @@ mod tests {
assert!(!http_transport_enabled(false, "wasm"));
}

fn io_namespace() -> NamespaceDecl {
NamespaceDecl {
namespace: "io".to_string(),
module: "io".to_string(),
docs: "I/O".to_string(),
runtime_supported_on_wasm: false,
}
}

#[test]
fn io_source_selection_matches_runtime_module_cfg() {
assert_eq!(
select_io_source_path(false, "x86_64"),
select_io_source_path(false, "unix"),
"src/builtins/runtime/io/blocking.rs"
);
assert_eq!(
select_io_source_path(true, "x86_64"),
select_io_source_path(true, "unix"),
"src/builtins/runtime/io/async_io.rs"
);
assert_eq!(
select_io_source_path(false, "aarch64"),
select_io_source_path(false, "windows"),
"src/builtins/runtime/io/blocking.rs"
);
assert_eq!(
select_io_source_path(true, "aarch64"),
select_io_source_path(true, "windows"),
"src/builtins/runtime/io/async_io.rs"
);
assert_eq!(
select_io_source_path(false, "wasm32"),
select_io_source_path(false, "wasm"),
"src/builtins/runtime/io_wasm.rs"
);
assert_eq!(
select_io_source_path(true, "wasm32"),
select_io_source_path(true, "wasm"),
"src/builtins/runtime/io_wasm.rs"
);
}

#[test]
fn selected_io_source_drives_generated_metadata_input() {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let namespace = io_namespace();
for (async_enabled, target_arch) in [
(false, "x86_64"),
(true, "x86_64"),
(false, "wasm32"),
(true, "wasm32"),
] {
let specs =
builtin_source_specs(std::slice::from_ref(&namespace), async_enabled, target_arch);
let spec = specs
.iter()
.find(|spec| spec.category == SourceCategory::NamespacedBuiltin)
.expect("the IO namespace must produce a source spec");
assert_eq!(
spec.path,
select_io_source_path(async_enabled, target_arch),
"metadata must use the same source selected by the runtime module"
);
let source = std::fs::read_to_string(manifest_dir.join(&spec.path))
.expect("selected IO source must be readable");
let open_marker = if async_enabled && target_arch != "wasm32" {
"async fn builtin_io_open"
} else {
"fn builtin_io_open"
};
assert!(
source.contains(open_marker),
"selected source must provide the expected IO implementation"
);
let callables = parse_source_file(&manifest_dir.join(&spec.path), spec, 0);
let open = callables
.iter()
.find(|callable| callable.name == "io::open")
.expect("selected IO source must contain io::open");
assert_eq!(open.host_execution, HostExecutionKind::MaySuspend);
}
}
}

#[cfg(test)]
Expand Down
Loading
Loading