From efeee97a04c8de164d09ed853128c0fbea7332e1 Mon Sep 17 00:00:00 2001 From: SIKTEC Date: Tue, 10 Nov 2026 23:01:35 -0500 Subject: [PATCH] fix(engine): wave 2 node:fs, stream/string_decoder, and child_process semantics (v0.10.10) --- Cargo.lock | 10 +- Cargo.toml | 2 +- crates/slice-engine/microbench/main.rs | 75 ++- .../src/bindings/child_process.rs | 485 +++++++++++++++--- crates/slice-engine/src/bindings/fs.rs | 118 ++++- .../src/preludes/03_streams_formdata.js | 56 ++ .../src/preludes/05_full_buffer.js | 31 +- .../src/preludes/11_fetch_headers_req_res.js | 8 +- .../src/preludes/node_builtins.rs | 10 +- .../tests/async_webcrypto_and_node_tests.rs | 457 +++++++++++++++++ docs/general/00_index.md | 4 +- docs/general/01_getting_started_and_cli.md | 4 +- docs/general/COMPATIBILITY.md | 2 +- docs/guides/README.md | 2 +- docs/system/00_index.md | 6 +- docs/system/07_production_tooling_guide.md | 2 +- scripts/install.ps1 | 2 +- scripts/install.sh | 4 +- scripts/package_release.ps1 | 2 +- scripts/run_benchmarks.ps1 | 2 +- tests/README.md | 2 +- tests/run_real_stack_benchmarks.sh | 2 +- tests/scripts/generate_bench_report.mjs | 4 +- 23 files changed, 1165 insertions(+), 125 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 803b588..358e277 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2005,7 +2005,7 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slice-cas" -version = "0.10.9" +version = "0.10.10" dependencies = [ "aho-corasick", "anyhow", @@ -2026,7 +2026,7 @@ dependencies = [ [[package]] name = "slice-cli" -version = "0.10.9" +version = "0.10.10" dependencies = [ "anyhow", "criterion", @@ -2047,7 +2047,7 @@ dependencies = [ [[package]] name = "slice-engine" -version = "0.10.9" +version = "0.10.10" dependencies = [ "aho-corasick", "anyhow", @@ -2077,7 +2077,7 @@ dependencies = [ [[package]] name = "slice-io" -version = "0.10.9" +version = "0.10.10" dependencies = [ "anyhow", "criterion", @@ -2088,7 +2088,7 @@ dependencies = [ [[package]] name = "slice-sandbox" -version = "0.10.9" +version = "0.10.10" dependencies = [ "anyhow", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 7f62d38..9f8b4e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "0.10.9" +version = "0.10.10" edition = "2021" authors = ["Slice Runtime Team"] license = "MIT OR Apache-2.0" diff --git a/crates/slice-engine/microbench/main.rs b/crates/slice-engine/microbench/main.rs index 0028219..bdc372e 100644 --- a/crates/slice-engine/microbench/main.rs +++ b/crates/slice-engine/microbench/main.rs @@ -293,10 +293,83 @@ if (!Array.isArray(parsedDeep) || revived.id !== "9007199254740993" || out.lengt group.finish(); } +fn bench_vfs_and_stream_operations(c: &mut Criterion) { + let mut group = c.benchmark_group("slice_engine::vfs_and_streams"); + + let vfs_fd_src = r#" +const fs = require("node:fs"); +fs.mkdirSync("/tmp/bench-dir/sub", { recursive: true }); +const fd = fs.openSync("/tmp/bench-dir/sub/data.bin", "w+"); +const payload = Buffer.from("slice-vfs-fd-benchmark-payload-64bytes-0123456789abcdef01234567"); +fs.writeSync(fd, payload, 0, payload.length, 0); +const rbuf = Buffer.allocUnsafe(64); +const n = fs.readSync(fd, rbuf, 0, 64, 0); +fs.closeSync(fd); +const raw = fs.readFileSync("/tmp/bench-dir/sub/data.bin"); +const entries = fs.readdirSync("/tmp/bench-dir", { recursive: true }); +if (n !== 64 || raw.length !== 64 || entries.length !== 2) throw new Error("vfs bench mismatch"); +"#; + let vfs_fd_bc = compile_source_to_bytecode(vfs_fd_src); + group.bench_function("vfs_fd_open_read_write_and_recursive_readdir", |b| { + SliceIsolate::prewarm_boa_pool(1); + b.iter(|| { + let caps = CapabilityToken::pure_compute() + .with_read_prefix("/tmp") + .with_write_prefix("/tmp"); + let mut iso = + SliceIsolate::spawn("bench-vfs-fd", 1, caps, 50_000_000, 16 * 1024 * 1024); + let res = iso + .execute_bytecode(black_box(&vfs_fd_bc), None) + .expect("vfs fd execute"); + black_box(res.highest_tier_reached) + }); + }); + + let stream_decoder_src = r#" +const { StringDecoder } = require("node:string_decoder"); +const { Readable, Writable } = require("node:stream"); +const sd = new StringDecoder("utf8"); +const chunk = Buffer.from("Café €100 🎉 日本語 — streaming benchmark payload ", "utf8"); +let out = ""; +for (let i = 0; i < chunk.length; i += 5) { + out += sd.write(chunk.subarray(i, Math.min(i + 5, chunk.length))); +} +out += sd.end(); +let drainedCount = 0; +const w = new Writable({ + highWaterMark: 32, + write(_c, _enc, cb) { cb(null); } +}); +w.write(chunk); +w.end(); +if (out.length < 20) throw new Error("stream decoder mismatch"); +"#; + let stream_decoder_bc = compile_source_to_bytecode(stream_decoder_src); + group.bench_function("string_decoder_multibyte_and_writable_hwm", |b| { + SliceIsolate::prewarm_boa_pool(1); + b.iter(|| { + let mut iso = SliceIsolate::spawn( + "bench-stream-decoder", + 1, + CapabilityToken::pure_compute(), + 50_000_000, + 16 * 1024 * 1024, + ); + let res = iso + .execute_bytecode(black_box(&stream_decoder_bc), None) + .expect("stream decoder execute"); + black_box(res.highest_tier_reached) + }); + }); + + group.finish(); +} + criterion_group!( benches, bench_boacas_and_automaton, bench_intrinsics_and_numeric_vm, - bench_json_operations + bench_json_operations, + bench_vfs_and_stream_operations ); criterion_main!(benches); diff --git a/crates/slice-engine/src/bindings/child_process.rs b/crates/slice-engine/src/bindings/child_process.rs index f1a02c3..77a2637 100644 --- a/crates/slice-engine/src/bindings/child_process.rs +++ b/crates/slice-engine/src/bindings/child_process.rs @@ -5,7 +5,7 @@ use crate::boa_realm::{ check_boa_fs_read_ocap, BOA_EGRESS_SECRETS, BOA_ENV_MAP, BOA_EXEC_BINS, BOA_KV_MEM_BUDGET, BOA_LAST_CHILD_PROC_VIOLATION, BOA_VIOLATION, }; -use crate::intrinsics::base64_encode; +use crate::intrinsics::{base64_decode, base64_encode}; use crate::state_and_kv::verify_egress_secrets_slice; use slice_sandbox::SandboxViolation; @@ -17,6 +17,8 @@ struct ChildProcessSpawnOpts { env: Option>, #[serde(default)] input: Option, + #[serde(default, rename = "inputBase64")] + input_base64: Option, #[serde(default)] timeout: Option, #[serde(default, rename = "maxBuffer")] @@ -39,14 +41,284 @@ fn is_restricted_loader_env_key(key: &str) -> bool { ) } -type SubprocessSyncResult = Result<(i32, Vec, Vec, Option), String>; +type SubprocessSyncResult = Result< + ( + Option, + Vec, + Vec, + Option, + Option<(String, i32)>, + ), + String, +>; + +fn expand_tr_set(spec: &str) -> Vec { + let bytes = spec.as_bytes(); + let mut out = Vec::with_capacity(bytes.len()); + let mut i = 0; + while i < bytes.len() { + if i + 2 < bytes.len() && bytes[i + 1] == b'-' && bytes[i] <= bytes[i + 2] { + for b in bytes[i]..=bytes[i + 2] { + out.push(b); + } + i += 3; + } else { + out.push(bytes[i]); + i += 1; + } + } + out +} + +fn split_shell_words(cmd: &str) -> Vec { + let mut words = Vec::new(); + let mut cur = String::new(); + let mut quote: Option = None; + for ch in cmd.chars() { + if let Some(q) = quote { + if ch == q { + quote = None; + } else { + cur.push(ch); + } + } else if ch == '\'' || ch == '"' { + quote = Some(ch); + } else if ch.is_whitespace() { + if !cur.is_empty() { + words.push(std::mem::take(&mut cur)); + } + } else { + cur.push(ch); + } + } + if !cur.is_empty() { + words.push(cur); + } + words +} + +fn try_eval_portable_shell_atom( + cmd: &str, + child_env: &std::collections::BTreeMap, + stdin_bytes: &[u8], +) -> Option<(i32, Vec, Vec)> { + let words = split_shell_words(cmd.trim()); + let first = words.first()?; + let norm = first.replace('\\', "/"); + let base = norm + .rsplit('/') + .next() + .unwrap_or(norm.as_str()) + .to_ascii_lowercase(); + let rest = &words[1..]; + match base.as_str() { + "echo" => { + let mut out = String::new(); + let (no_nl, slice) = if rest.first().map(|s| s.as_str()) == Some("-n") { + (true, &rest[1..]) + } else { + (false, rest) + }; + for (i, a) in slice.iter().enumerate() { + if i > 0 { + out.push(' '); + } + if let Some(var_name) = a.strip_prefix('$') { + let clean = var_name.trim_matches(|c: char| c == '{' || c == '}'); + out.push_str(child_env.get(clean).map(|s| s.as_str()).unwrap_or("")); + } else { + out.push_str(a); + } + } + if !no_nl { + out.push('\n'); + } + Some((0, out.into_bytes(), Vec::new())) + } + "cat" if rest.is_empty() => Some((0, stdin_bytes.to_vec(), Vec::new())), + "tr" if rest.len() == 2 => { + let set1 = expand_tr_set(&rest[0]); + let set2 = expand_tr_set(&rest[1]); + let mut out = stdin_bytes.to_vec(); + if !set1.is_empty() && !set2.is_empty() { + for b in &mut out { + if let Some(pos) = set1.iter().position(|&x| x == *b) { + let mapped_idx = pos.min(set2.len() - 1); + *b = set2[mapped_idx]; + } + } + } + Some((0, out, Vec::new())) + } + "exit" => { + let code = rest + .first() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + Some((code & 0xFF, Vec::new(), Vec::new())) + } + "true" => Some((0, Vec::new(), Vec::new())), + "false" => Some((1, Vec::new(), Vec::new())), + "env" if rest.is_empty() => { + let mut out = String::new(); + for (k, v) in child_env { + out.push_str(k); + out.push('='); + out.push_str(v); + out.push('\n'); + } + Some((0, out.into_bytes(), Vec::new())) + } + "printenv" => { + if rest.is_empty() { + let mut out = String::new(); + for (k, v) in child_env { + out.push_str(k); + out.push('='); + out.push_str(v); + out.push('\n'); + } + return Some((0, out.into_bytes(), Vec::new())); + } + if let Some(val) = child_env.get(&rest[0]) { + Some((0, format!("{}\n", val).into_bytes(), Vec::new())) + } else { + Some((1, Vec::new(), Vec::new())) + } + } + _ => None, + } +} + +fn try_eval_portable_shell_script( + script: &str, + child_env: &std::collections::BTreeMap, + initial_stdin: &[u8], + max_buffer: usize, +) -> Option { + if script + .bytes() + .any(|b| matches!(b, b'`' | b'>' | b'<' | b'(' | b')')) + { + return None; + } + #[derive(Clone, Copy, PartialEq, Eq)] + enum ChainOp { + Always, + And, + Or, + } + let mut clauses: Vec<(ChainOp, &str)> = Vec::new(); + let bytes = script.as_bytes(); + let mut start = 0; + let mut next_op = ChainOp::Always; + let mut i = 0; + let mut in_quote: Option = None; + while i < bytes.len() { + let b = bytes[i]; + if let Some(q) = in_quote { + if b == q { + in_quote = None; + } + i += 1; + continue; + } + if b == b'\'' || b == b'"' { + in_quote = Some(b); + i += 1; + continue; + } + if b == b';' { + clauses.push((next_op, &script[start..i])); + next_op = ChainOp::Always; + i += 1; + start = i; + } else if i + 1 < bytes.len() && b == b'&' && bytes[i + 1] == b'&' { + clauses.push((next_op, &script[start..i])); + next_op = ChainOp::And; + i += 2; + start = i; + } else if i + 1 < bytes.len() && b == b'|' && bytes[i + 1] == b'|' { + clauses.push((next_op, &script[start..i])); + next_op = ChainOp::Or; + i += 2; + start = i; + } else { + i += 1; + } + } + if start < bytes.len() { + clauses.push((next_op, &script[start..])); + } + if clauses.is_empty() { + return Some(Ok((Some(0), Vec::new(), Vec::new(), None, None))); + } + + let mut total_stdout = Vec::new(); + let mut total_stderr = Vec::new(); + let mut last_status = 0; + + for (idx, (op, clause_raw)) in clauses.into_iter().enumerate() { + let clause = clause_raw.trim(); + if clause.is_empty() { + continue; + } + match op { + ChainOp::Always => {} + ChainOp::And if last_status != 0 => continue, + ChainOp::Or if last_status == 0 => continue, + _ => {} + } + let stages: Vec<&str> = clause.split('|').collect(); + let mut pipe_data = if idx == 0 { + initial_stdin.to_vec() + } else { + Vec::new() + }; + let mut clause_status = 0; + let mut exited_early = false; + for (s_idx, stage) in stages.iter().enumerate() { + let trimmed = stage.trim(); + let (st, out_b, err_b) = + try_eval_portable_shell_atom(trimmed, child_env, &pipe_data)?; + clause_status = st; + total_stderr.extend_from_slice(&err_b); + if s_idx + 1 < stages.len() { + pipe_data = out_b; + } else { + total_stdout.extend_from_slice(&out_b); + } + if trimmed == "exit" || trimmed.starts_with("exit ") { + exited_early = true; + break; + } + } + last_status = clause_status; + if total_stdout.len().saturating_add(total_stderr.len()) > max_buffer { + return Some(Err( + "RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout/stderr maxBuffer length exceeded" + .to_string(), + )); + } + if exited_early { + break; + } + } + Some(Ok(( + Some(last_status), + total_stdout, + total_stderr, + None, + None, + ))) +} fn execute_sanitized_subprocess_sync( file: &str, args: &[String], child_env: &std::collections::BTreeMap, cwd: Option<&str>, - stdin_input: Option<&str>, + stdin_input: Option<&[u8]>, timeout_ms: u64, max_buffer: usize, ) -> SubprocessSyncResult { @@ -62,9 +334,36 @@ fn execute_sanitized_subprocess_sync( .unwrap_or(base_raw) .to_ascii_lowercase(); - // Portable built-in handling for standard POSIX utilities (`echo`, `env`, `printenv`, `true`, `false`) + // Portable built-in handling for standard POSIX utilities (`echo`, `cat`, `tr`, `exit`, `env`, `printenv`, `true`, `false`, `sh -c`) // after Ring 1 (`ExecCap`) and Ring 2 (`BOA_ENV_MAP` sanitization) have verified authority. match base_cmd.as_str() { + "sh" if args.len() == 2 && args[0] == "-c" => { + if let Some(res) = try_eval_portable_shell_script( + &args[1], + child_env, + stdin_input.unwrap_or(&[]), + max_buffer, + ) { + return res; + } + } + "cat" if args.is_empty() => { + let out_bytes = stdin_input.unwrap_or(&[]).to_vec(); + if out_bytes.len() > max_buffer { + return Err( + "RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length exceeded" + .to_string(), + ); + } + return Ok((Some(0), out_bytes, Vec::new(), None, None)); + } + "exit" => { + let code = args + .first() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + return Ok((Some(code & 0xFF), Vec::new(), Vec::new(), None, None)); + } "echo" => { let mut out = String::new(); let (no_newline, slice) = if args.first().map(|s| s.as_str()) == Some("-n") { @@ -88,7 +387,7 @@ fn execute_sanitized_subprocess_sync( .to_string(), ); } - return Ok((0, out_bytes, Vec::new(), None)); + return Ok((Some(0), out_bytes, Vec::new(), None, None)); } "env" if args.is_empty() => { let mut out = String::new(); @@ -105,7 +404,7 @@ fn execute_sanitized_subprocess_sync( .to_string(), ); } - return Ok((0, out_bytes, Vec::new(), None)); + return Ok((Some(0), out_bytes, Vec::new(), None, None)); } "printenv" => { if args.is_empty() { @@ -123,7 +422,7 @@ fn execute_sanitized_subprocess_sync( .to_string(), ); } - return Ok((0, out_bytes, Vec::new(), None)); + return Ok((Some(0), out_bytes, Vec::new(), None, None)); } let key = &args[0]; if let Some(val) = child_env.get(key) { @@ -134,12 +433,12 @@ fn execute_sanitized_subprocess_sync( .to_string(), ); } - return Ok((0, out_bytes, Vec::new(), None)); + return Ok((Some(0), out_bytes, Vec::new(), None, None)); } - return Ok((1, Vec::new(), Vec::new(), None)); + return Ok((Some(1), Vec::new(), Vec::new(), None, None)); } - "true" => return Ok((0, Vec::new(), Vec::new(), None)), - "false" => return Ok((1, Vec::new(), Vec::new(), None)), + "true" => return Ok((Some(0), Vec::new(), Vec::new(), None, None)), + "false" => return Ok((Some(1), Vec::new(), Vec::new(), None, None)), _ => {} } @@ -161,13 +460,27 @@ fn execute_sanitized_subprocess_sync( cmd.stdout(Stdio::piped()); cmd.stderr(Stdio::piped()); - let mut child = cmd - .spawn() - .map_err(|e| format!("Error: spawn {} ENOENT ({})", file, e))?; + let mut child = match cmd.spawn() { + Ok(c) => c, + Err(e) => { + let (err_code, err_no) = match e.kind() { + std::io::ErrorKind::NotFound => ("ENOENT", -2), + std::io::ErrorKind::PermissionDenied => ("EACCES", -13), + _ => ("ENOENT", -2), + }; + return Ok(( + None, + Vec::new(), + Vec::new(), + None, + Some((err_code.to_string(), err_no)), + )); + } + }; if let Some(input_data) = stdin_input { if let Some(mut stdin_pipe) = child.stdin.take() { - let _ = stdin_pipe.write_all(input_data.as_bytes()); + let _ = stdin_pipe.write_all(input_data); } } @@ -212,9 +525,12 @@ fn execute_sanitized_subprocess_sync( let stderr_bytes = stderr_handle.join().unwrap_or_default(); if timed_out { - return Err(format!( - "Error: spawnSync {} ETIMEDOUT (exceeded {} ms)", - file, timeout_ms + return Ok(( + None, + stdout_bytes, + stderr_bytes, + Some("SIGTERM".to_string()), + Some(("ETIMEDOUT".to_string(), -110)), )); } @@ -226,7 +542,7 @@ fn execute_sanitized_subprocess_sync( ); } - Ok((exit_code, stdout_bytes, stderr_bytes, None)) + Ok((Some(exit_code), stdout_bytes, stderr_bytes, None, None)) } pub(crate) fn register_child_process_host_functions(ctx: &mut boa_engine::Context) { @@ -267,16 +583,61 @@ pub(crate) fn register_child_process_host_functions(ctx: &mut boa_engine::Contex let tenant_id = active_tenant_id_or_default(); + let shell_opt: Option<&str> = match &opts.shell { + Some(serde_json::Value::Bool(true)) => Some("/bin/sh"), + Some(serde_json::Value::String(s)) if !s.is_empty() => Some(s.as_str()), + _ => None, + }; + + let (exec_file, exec_args) = if let Some(sh_bin) = shell_opt { + let full_cmd = if cmd_args.is_empty() { + file.clone() + } else { + format!("{} {}", file, cmd_args.join(" ")) + }; + (sh_bin.to_string(), vec!["-c".to_string(), full_cmd]) + } else { + (file.clone(), cmd_args) + }; + // Ring 1: OCap `ExecCap` Allowlist Verification (Deny-All by default) let allowed_bins = BOA_EXEC_BINS.with(|eb| eb.borrow().clone()); - let is_allowed = !file.trim().is_empty() - && allowed_bins - .iter() - .any(|allowed| slice_sandbox::exec_binary_matches(&file, allowed)); + let is_allowed = if let Some(sh_bin) = shell_opt { + let shell_allowed = allowed_bins.iter().any(|allowed| { + slice_sandbox::exec_binary_matches(sh_bin, allowed) + || (sh_bin == "/bin/sh" + && slice_sandbox::exec_binary_matches("sh", allowed)) + }); + if shell_allowed { + true + } else { + let full_cmd = &exec_args[1]; + let has_meta = full_cmd.bytes().any(|b| { + matches!( + b, + b'&' | b'|' | b';' | b'`' | b'$' | b'>' | b'<' | b'(' | b')' + ) + }); + if !has_meta { + let first_tok = full_cmd.split_whitespace().next().unwrap_or(""); + !first_tok.is_empty() + && allowed_bins + .iter() + .any(|allowed| slice_sandbox::exec_binary_matches(first_tok, allowed)) + } else { + false + } + } + } else { + !exec_file.trim().is_empty() + && allowed_bins + .iter() + .any(|allowed| slice_sandbox::exec_binary_matches(&exec_file, allowed)) + }; if !is_allowed { let violation = SandboxViolation::ExecDenied { tenant_id, - binary: file, + binary: exec_file, }; let msg = violation.to_string(); BOA_LAST_CHILD_PROC_VIOLATION.with(|v| { @@ -300,32 +661,6 @@ pub(crate) fn register_child_process_host_functions(ctx: &mut boa_engine::Contex } } - // If `shell` option is explicitly requested as a string path or boolean `true`, - // also verify that the shell binary itself is authorized in `allowed_exec_binaries`. - if let Some(ref sh_val) = opts.shell { - let shell_bin = match sh_val { - serde_json::Value::Bool(true) => Some("/bin/sh"), - serde_json::Value::String(s) if !s.is_empty() => Some(s.as_str()), - _ => None, - }; - if let Some(sb) = shell_bin { - let shell_allowed = allowed_bins - .iter() - .any(|allowed| slice_sandbox::exec_binary_matches(sb, allowed)); - if !shell_allowed { - let violation = SandboxViolation::ExecDenied { - tenant_id, - binary: sb.to_string(), - }; - let msg = violation.to_string(); - BOA_LAST_CHILD_PROC_VIOLATION.with(|v| { - *v.borrow_mut() = Some(violation); - }); - return Err(JsNativeError::error().with_message(msg).into()); - } - } - } - // Ring 5: Base CPU Fuel charge for subprocess invocation if let Err(fuel_err) = consume_crypto_kdf_fuel(500) { return Err(JsNativeError::range().with_message(fuel_err).into()); @@ -359,17 +694,27 @@ pub(crate) fn register_child_process_host_functions(ctx: &mut boa_engine::Contex child_env.insert(k.clone(), v.clone()); } } + if shell_opt.is_some() { + child_env + .entry("PATH".to_string()) + .or_insert_with(|| "/usr/local/bin:/usr/bin:/bin".to_string()); + } let timeout_ms = opts.timeout.unwrap_or(30_000).min(120_000); let max_buffer = opts.max_buffer.unwrap_or(1024 * 1024).min(16 * 1024 * 1024); + let stdin_bytes: Option> = if let Some(ref b64) = opts.input_base64 { + Some(base64_decode(b64)) + } else { + opts.input.as_ref().map(|s| s.as_bytes().to_vec()) + }; - let (status_code, stdout_bytes, stderr_bytes, signal) = + let (status_code, stdout_bytes, stderr_bytes, signal, spawn_err) = match execute_sanitized_subprocess_sync( - &file, - &cmd_args, + &exec_file, + &exec_args, &child_env, opts.cwd.as_deref(), - opts.input.as_deref(), + stdin_bytes.as_deref(), timeout_ms, max_buffer, ) { @@ -425,15 +770,29 @@ pub(crate) fn register_child_process_host_functions(ctx: &mut boa_engine::Contex } } - let resp = serde_json::json!({ - "status": status_code, - "signal": signal, - "stdoutBase64": base64_encode(&stdout_bytes, false), - "stderrBase64": base64_encode(&stderr_bytes, false), - "stdout": stdout_str, - "stderr": stderr_str, - "pid": 4200, - }); + let resp = if let Some((err_code, err_no)) = spawn_err { + serde_json::json!({ + "status": status_code, + "signal": signal, + "stdoutBase64": base64_encode(&stdout_bytes, false), + "stderrBase64": base64_encode(&stderr_bytes, false), + "stdout": stdout_str, + "stderr": stderr_str, + "pid": 0, + "errorCode": err_code, + "errorErrno": err_no, + }) + } else { + serde_json::json!({ + "status": status_code, + "signal": signal, + "stdoutBase64": base64_encode(&stdout_bytes, false), + "stderrBase64": base64_encode(&stderr_bytes, false), + "stdout": stdout_str, + "stderr": stderr_str, + "pid": 4200, + }) + }; Ok(BoaVal::from(js_string!(resp.to_string()))) }), ); diff --git a/crates/slice-engine/src/bindings/fs.rs b/crates/slice-engine/src/bindings/fs.rs index 32a3a69..ca8f6b6 100644 --- a/crates/slice-engine/src/bindings/fs.rs +++ b/crates/slice-engine/src/bindings/fs.rs @@ -11,6 +11,27 @@ use crate::intrinsics::fill_random_bytes; const VFS_SYMLINK_PREFIX: &[u8] = b"\x00__SLICE_SYMLINK__:"; +thread_local! { + static BOA_VFS_MTIMES: std::cell::RefCell> = + std::cell::RefCell::new(rustc_hash::FxHashMap::default()); +} + +fn vfs_or_host_is_dir(norm: &str, raw_path: &str) -> bool { + if norm == "/" || norm == "." { + return true; + } + if BOA_VFS_DIRS.with(|d| d.borrow().contains(norm)) { + return true; + } + if BOA_VFS_CACHE.with(|c| c.borrow().contains_key(norm)) { + return false; + } + let prefix = format!("{}/", norm); + BOA_VFS_CACHE.with(|c| c.borrow().keys().any(|k| k.starts_with(&prefix))) + || std::path::Path::new(norm).is_dir() + || std::path::Path::new(raw_path).is_dir() +} + pub(crate) fn resolve_vfs_symlink_norm(norm: &str) -> String { let mut current = norm.to_string(); for _ in 0..8 { @@ -61,11 +82,14 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { let content = String::from_utf8_lossy(&arc_bytes).into_owned(); return Ok(BoaVal::from(js_string!(content))); } - let bytes = std::fs::read(&norm) - .or_else(|_| std::fs::read(&path)) - .unwrap_or_default(); - let content = String::from_utf8_lossy(&bytes).into_owned(); - Ok(BoaVal::from(js_string!(content))) + if vfs_or_host_is_dir(&norm, &path) { + return Ok(BoaVal::from(-21)); + } + if let Ok(bytes) = std::fs::read(&norm).or_else(|_| std::fs::read(&path)) { + let content = String::from_utf8_lossy(&bytes).into_owned(); + return Ok(BoaVal::from(js_string!(content))); + } + Ok(BoaVal::null()) }), ); @@ -89,10 +113,13 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { if let Some(arc_bytes) = BOA_VFS_CACHE.with(|c| c.borrow().get(&norm).cloned()) { return bytes_to_js_uint8_array(&arc_bytes, context); } - let bytes = std::fs::read(&norm) - .or_else(|_| std::fs::read(&path)) - .unwrap_or_default(); - bytes_to_js_uint8_array(&bytes, context) + if vfs_or_host_is_dir(&norm, &path) { + return Ok(BoaVal::from(-21)); + } + if let Ok(bytes) = std::fs::read(&norm).or_else(|_| std::fs::read(&path)) { + return bytes_to_js_uint8_array(&bytes, context); + } + Ok(BoaVal::null()) }), ); @@ -113,6 +140,9 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { if !check_boa_fs_write_ocap(&norm) { return Ok(BoaVal::undefined()); } + if BOA_VFS_DIRS.with(|d| d.borrow().contains(&norm)) { + return Ok(BoaVal::from(-21)); + } let data_bytes = if let Some(val) = args.get(1) { if val.is_object() { extract_buffer_source_bytes(val, context)? @@ -158,6 +188,9 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { if !check_boa_fs_write_ocap(&norm) { return Ok(BoaVal::undefined()); } + if BOA_VFS_DIRS.with(|d| d.borrow().contains(&norm)) { + return Ok(BoaVal::from(-21)); + } let data_bytes = if let Some(val) = args.get(1) { if val.is_object() { extract_buffer_source_bytes(val, context)? @@ -289,9 +322,13 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { } } }); - if let Ok(rd) = std::fs::read_dir(&norm_dir).or_else(|_| std::fs::read_dir(&path)) { - for entry in rd.flatten() { - entries_set.insert(entry.file_name().to_string_lossy().to_string()); + let is_vfs_tmp_dir = norm_dir.starts_with("/tmp/") + && BOA_VFS_DIRS.with(|d| d.borrow().contains(&norm_dir)); + if !is_vfs_tmp_dir { + if let Ok(rd) = std::fs::read_dir(&norm_dir).or_else(|_| std::fs::read_dir(&path)) { + for entry in rd.flatten() { + entries_set.insert(entry.file_name().to_string_lossy().to_string()); + } } } let entries: Vec = entries_set.into_iter().collect(); @@ -317,15 +354,20 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { if !check_boa_fs_read_ocap(&norm) { return Ok(BoaVal::from(0)); } - let size = BOA_VFS_CACHE - .with(|c| c.borrow().get(&norm).map(|v| v.len() as u64)) - .unwrap_or_else(|| { - std::fs::metadata(&norm) - .or_else(|_| std::fs::metadata(&path)) - .map(|m| m.len()) - .unwrap_or(0) - }); - Ok(BoaVal::from(size as f64)) + if let Some(size) = BOA_VFS_CACHE.with(|c| c.borrow().get(&norm).map(|v| v.len() as u64)) + { + return Ok(BoaVal::from(size as f64)); + } + if BOA_VFS_DIRS.with(|d| d.borrow().contains(&norm)) { + return Ok(BoaVal::from(0.0)); + } + if let Ok(meta) = std::fs::metadata(&norm).or_else(|_| std::fs::metadata(&path)) { + return Ok(BoaVal::from(meta.len() as f64)); + } + if vfs_or_host_is_dir(&norm, &path) { + return Ok(BoaVal::from(0.0)); + } + Ok(BoaVal::from(-1.0)) }), ); @@ -339,13 +381,19 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { .transpose()? .map(|s| s.to_std_string_escaped()) .unwrap_or_default(); - if !check_boa_fs_read_ocap(&path) || BOA_DET_STATE.with(|s| s.get().is_some()) { + if !check_boa_fs_read_ocap(&path) { return Ok(BoaVal::from(1_700_000_000_000.0)); } let norm = resolve_vfs_symlink_norm(&norm_vfs_path(&path)); if !check_boa_fs_read_ocap(&norm) { return Ok(BoaVal::from(1_700_000_000_000.0)); } + if let Some(custom_mt) = BOA_VFS_MTIMES.with(|m| m.borrow().get(&norm).copied()) { + return Ok(BoaVal::from(custom_mt)); + } + if BOA_DET_STATE.with(|s| s.get().is_some()) { + return Ok(BoaVal::from(1_700_000_000_000.0)); + } let mtime_ms = std::fs::metadata(&norm) .or_else(|_| std::fs::metadata(&path)) .ok() @@ -379,11 +427,7 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { if !check_boa_fs_read_ocap(&norm) { return Ok(BoaVal::from(false)); } - let prefix = format!("{}/", norm); - let is_dir = BOA_VFS_DIRS.with(|d| d.borrow().contains(&norm)) - || BOA_VFS_CACHE.with(|c| c.borrow().keys().any(|k| k.starts_with(&prefix))) - || std::path::Path::new(&norm).is_dir() - || std::path::Path::new(&path).is_dir(); + let is_dir = vfs_or_host_is_dir(&norm, &path); Ok(BoaVal::from(is_dir)) }), ); @@ -511,6 +555,11 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { dirs.remove(&norm); dirs.retain(|k| !k.starts_with(&prefix)); }); + BOA_VFS_MTIMES.with(|m| { + let mut mtimes = m.borrow_mut(); + mtimes.remove(&norm); + mtimes.retain(|k, _| !k.starts_with(&prefix)); + }); let p = std::path::Path::new(&path); if p.exists() { if p.is_dir() { @@ -789,7 +838,20 @@ pub(crate) fn register_fs_host_functions(ctx: &mut boa_engine::Context) { .transpose()? .map(|s| s.to_std_string_escaped()) .unwrap_or_default(); - let _ = check_boa_fs_write_ocap(&path); + if !check_boa_fs_write_ocap(&path) { + return Ok(BoaVal::undefined()); + } + let norm = resolve_vfs_symlink_norm(&norm_vfs_path(&path)); + if !check_boa_fs_write_ocap(&norm) { + return Ok(BoaVal::undefined()); + } + let mtime_ms = args + .get(2) + .and_then(|v| v.as_number()) + .unwrap_or(1_700_000_000_000.0); + BOA_VFS_MTIMES.with(|m| { + m.borrow_mut().insert(norm, mtime_ms); + }); Ok(BoaVal::undefined()) }), ); diff --git a/crates/slice-engine/src/preludes/03_streams_formdata.js b/crates/slice-engine/src/preludes/03_streams_formdata.js index cc5ef6a..3287836 100644 --- a/crates/slice-engine/src/preludes/03_streams_formdata.js +++ b/crates/slice-engine/src/preludes/03_streams_formdata.js @@ -5,6 +5,8 @@ function ReadableStream(underlyingSource) { var self = this; this._chunks = []; + this._waiters = []; + this._closeWaiters = []; this._closed = false; this._errored = null; this.locked = false; @@ -17,13 +19,29 @@ throw new RangeError("ReadableStream buffer limit exceeded (" + MAX_STREAM_CHUNKS + " chunks)"); } self._chunks.push(chunk); + if (self._waiters.length > 0) { + var w = self._waiters.shift(); + w.res({ value: self._chunks[w.idx()], done: false }); + } }, close: function() { self._closed = true; + while (self._waiters.length > 0) { + self._waiters.shift().res({ value: undefined, done: true }); + } + while (self._closeWaiters.length > 0) { + self._closeWaiters.shift().res(undefined); + } }, error: function(e) { self._errored = e || new Error("ReadableStream error"); self._closed = true; + while (self._waiters.length > 0) { + self._waiters.shift().rej(self._errored); + } + while (self._closeWaiters.length > 0) { + self._closeWaiters.shift().rej(self._errored); + } } }; this._ctrl = ctrl; @@ -115,6 +133,15 @@ return Promise.resolve({ value: self._chunks[idx++], done: false }); } } + if (!self._closed) { + return new Promise(function(res, rej) { + self._waiters.push({ + idx: function() { return idx++; }, + res: res, + rej: rej + }); + }); + } return Promise.resolve({ value: undefined, done: true }); }, cancel: function(reason) { @@ -125,6 +152,35 @@ } }; }; + ReadableStream.prototype.values = function(opts) { + var preventCancel = Boolean(opts && opts.preventCancel); + var reader = this.getReader(); + return { + next: function() { + return reader.read().then(function(step) { + if (step.done) reader.releaseLock(); + return step; + }, function(e) { + reader.releaseLock(); + throw e; + }); + }, + return: function(val) { + if (!preventCancel) { + return reader.cancel(val).then(function() { + reader.releaseLock(); + return { value: val, done: true }; + }); + } + reader.releaseLock(); + return Promise.resolve({ value: val, done: true }); + }, + [Symbol.asyncIterator]: function() { return this; } + }; + }; + if (typeof Symbol !== "undefined" && Symbol.asyncIterator) { + ReadableStream.prototype[Symbol.asyncIterator] = ReadableStream.prototype.values; + } ReadableStream.prototype.tee = function() { this._drainSync(); var copy1 = this._chunks.slice(), copy2 = this._chunks.slice(); diff --git a/crates/slice-engine/src/preludes/05_full_buffer.js b/crates/slice-engine/src/preludes/05_full_buffer.js index a71aff5..9c21fcb 100644 --- a/crates/slice-engine/src/preludes/05_full_buffer.js +++ b/crates/slice-engine/src/preludes/05_full_buffer.js @@ -45,6 +45,15 @@ for (var i = 0; i < n; i++) u[i] = value.charCodeAt(i) & mask; return __wrapBuf(u); } + if (e === "utf16le" || e === "utf-16le" || e === "ucs2" || e === "ucs-2") { + var n16 = value.length, u16 = new __U8(n16 * 2); + for (var k = 0; k < n16; k++) { + var code = value.charCodeAt(k); + u16[k * 2] = code & 0xff; + u16[k * 2 + 1] = (code >>> 8) & 0xff; + } + return __wrapBuf(u16); + } return __wrapBuf(__slice_text_encode(value)); } if (value instanceof ArrayBuffer) { @@ -85,7 +94,20 @@ return Buffer.alloc(size); }; - Buffer.byteLength = __slice_utf8_byte_len; + Buffer.byteLength = function(str, encoding) { + if (typeof str !== "string") { + if (str && typeof str.byteLength === "number") return str.byteLength; + str = String(str); + } + if (!encoding) return __slice_utf8_byte_len(str); + var e = String(encoding).toLowerCase(); + if (e === "utf8" || e === "utf-8") return __slice_utf8_byte_len(str); + if (e === "utf16le" || e === "utf-16le" || e === "ucs2" || e === "ucs-2") return str.length * 2; + if (e === "latin1" || e === "binary" || e === "ascii") return str.length; + if (e === "hex") return str.length >>> 1; + if (e === "base64" || e === "base64url") return __slice_base64_decode_bytes(str).byteLength; + return __slice_utf8_byte_len(str); + }; Buffer.concat = function(list, totalLength) { if (!Array.isArray(list)) throw new TypeError("The \"list\" argument must be an instance of Array"); @@ -142,6 +164,13 @@ for (var i = 0; i < view.length; i++) out += String.fromCharCode(view[i] & 0x7f); return out; } + if (enc === "utf16le" || enc === "utf-16le" || enc === "ucs2" || enc === "ucs-2") { + var out16 = "", pairLen = view.length - (view.length % 2); + for (var j = 0; j < pairLen; j += 2) { + out16 += String.fromCharCode(view[j] | (view[j + 1] << 8)); + } + return out16; + } return __slice_text_decode(view, "utf-8", false, true); }; diff --git a/crates/slice-engine/src/preludes/11_fetch_headers_req_res.js b/crates/slice-engine/src/preludes/11_fetch_headers_req_res.js index 34b44ac..992d915 100644 --- a/crates/slice-engine/src/preludes/11_fetch_headers_req_res.js +++ b/crates/slice-engine/src/preludes/11_fetch_headers_req_res.js @@ -396,8 +396,12 @@ this.bodyUsed = true; if (this._stream) { var st = this._stream, self = this; - if (st._startPromise) { - return st._startPromise.then(function() { + st._drainSync(); + if (st._startPromise || !st._closed) { + var waitP = st._startPromise ? st._startPromise : new Promise(function(res, rej) { + st._closeWaiters.push({ res: res, rej: rej }); + }); + return waitP.then(function() { self._body = st._toText(); self._stream = null; return self._body; diff --git a/crates/slice-engine/src/preludes/node_builtins.rs b/crates/slice-engine/src/preludes/node_builtins.rs index 9e963dc..2449cef 100644 --- a/crates/slice-engine/src/preludes/node_builtins.rs +++ b/crates/slice-engine/src/preludes/node_builtins.rs @@ -10,7 +10,7 @@ use std::sync::{Arc, OnceLock}; const BUILTIN_CRYPTO_SNIPPET: &[u8] = br#"(function(){var __U8=globalThis.Uint8Array,__ext=false;function __ensExt(){if(!__ext){__ext=true;__slice_init_crypto_ext();}}function __toBytes(d,enc){if(d instanceof __U8)return d;if(d instanceof ArrayBuffer)return new __U8(d);if(d&&d.buffer instanceof ArrayBuffer)return new __U8(d.buffer,d.byteOffset||0,d.byteLength);__slice_ensure_shard(5);return Buffer.from(String(d),enc||"utf8");}function __catBytes(chunks){if(chunks.length===0)return new __U8(0);if(chunks.length===1)return chunks[0];__slice_ensure_shard(5);return Buffer.concat(chunks);}function __encOut(rawBuf,enc){__slice_ensure_shard(5);var b=Buffer.isBuffer(rawBuf)?rawBuf:Buffer.from(rawBuf);return(!enc||enc==="buffer")?b:b.toString(enc);}function KeyObject(type,alg,crv,id,raw,meta){this.type=type;this.asymmetricKeyType=alg;this.asymmetricKeyDetails=crv?{namedCurve:crv}:{};this._id=id||0;this._raw=raw||null;this._meta=meta||null;}KeyObject.prototype.export=function(opts){__ensExt();__slice_ensure_shard(5);var o=opts||{};var fmt=String(o.format||"der").toLowerCase();if(this.type==="secret")return Buffer.from(this._raw);var derB64=(this.type==="private")?(this._meta&&this._meta.pkcs8):(this._meta&&this._meta.spki);var der=derB64?Buffer.from(__slice_base64_decode_bytes(derB64)):Buffer.from(this._raw||[]);if(fmt==="pem"){var label=this.type==="private"?"PRIVATE KEY":"PUBLIC KEY";return"-----BEGIN "+label+"-----\n"+der.toString("base64")+"\n-----END "+label+"-----\n";}if(fmt==="jwk"&&this._meta){if(this.asymmetricKeyType==="ed25519"){var j={kty:"OKP",crv:"Ed25519",x:this._meta.x};if(this.type==="private")j.d=this._meta.d;return j;}var je={kty:"EC",crv:this._meta.crv||"P-256",x:this._meta.x,y:this._meta.y};if(this.type==="private")je.d=this._meta.d;return je;}return der;};function __parseKeyObj(k,isPriv){__ensExt();if(k instanceof KeyObject)return k;if(k&&typeof k==="object"&&k._id!==undefined&&k.algorithm){var kn=String(k.algorithm.name||"").toLowerCase();return new KeyObject(k.type,kn==="ecdsa"?"ec":kn,k.algorithm.namedCurve,k._id,k._raw,k._meta);}if(k&&typeof k==="object"&&k.key!==undefined)return __parseKeyObj(k.key,isPriv);if(typeof k==="string"&&k.indexOf("-----BEGIN")!==-1){var body=k.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,"");var der=__slice_base64_decode_bytes(body);var fmt=isPriv?"pkcs8":"spki";try{var impEd=JSON.parse(__slice_crypto_asym_import("Ed25519","",fmt,der));return new KeyObject(impEd.type,"ed25519",undefined,impEd.id,der,impEd);}catch(_e1){try{var impEc256=JSON.parse(__slice_crypto_asym_import("ECDSA","P-256",fmt,der));return new KeyObject(impEc256.type,"ec","P-256",impEc256.id,der,impEc256);}catch(_e2){var impEc384=JSON.parse(__slice_crypto_asym_import("ECDSA","P-384",fmt,der));return new KeyObject(impEc384.type,"ec","P-384",impEc384.id,der,impEc384);}}}var raw=__toBytes(k);var fmtD=isPriv?"pkcs8":"spki";try{var iEd=JSON.parse(__slice_crypto_asym_import("Ed25519","",fmtD,raw));return new KeyObject(iEd.type,"ed25519",undefined,iEd.id,raw,iEd);}catch(_e3){try{var iEc256=JSON.parse(__slice_crypto_asym_import("ECDSA","P-256",fmtD,raw));return new KeyObject(iEc256.type,"ec","P-256",iEc256.id,raw,iEc256);}catch(_e4){var iEc384=JSON.parse(__slice_crypto_asym_import("ECDSA","P-384",fmtD,raw));return new KeyObject(iEc384.type,"ec","P-384",iEc384.id,raw,iEc384);}}}var m={KeyObject:KeyObject,createHash:function(alg){var a=String(alg||"sha256").toLowerCase(),isSha256=(a==="sha256"||a==="sha-256"),chunks=[],strFast=isSha256,sBuf="";return{update:function(d,enc){if(strFast&&typeof d==="string"&&(!enc||enc==="utf8"||enc==="utf-8")&&chunks.length===0){sBuf+=d;}else{if(sBuf.length>0){__slice_ensure_shard(5);chunks.push(Buffer.from(sBuf,"utf8"));sBuf="";}strFast=false;chunks.push(__toBytes(d,enc));}return this;},digest:function(enc){if(isSha256&&(enc==="hex"||enc==="base64"||enc==="base64url")){if(strFast&&chunks.length===0){var h=__slice_crypto_sha256(sBuf,enc);sBuf="";return h;}if(sBuf.length===0&&chunks.length===1){var hb=__slice_crypto_sha256(chunks[0],enc);chunks=[];return hb;}}__ensExt();__slice_ensure_shard(5);if(sBuf.length>0){chunks.push(Buffer.from(sBuf,"utf8"));sBuf="";}var raw=Buffer.from(__slice_crypto_digest_bytes(a,__catBytes(chunks)));chunks=[];return(!enc||enc==="buffer")?raw:raw.toString(enc);}};},createHmac:function(alg,key){var a=String(alg||"sha256").toLowerCase(),isSha256=(a==="sha256"||a==="sha-256"),kBytes=null,chunks=[],strFast=isSha256&&typeof key==="string",kStr=typeof key==="string"?key:"",sBuf="";return{update:function(d,enc){if(strFast&&typeof d==="string"&&(!enc||enc==="utf8"||enc==="utf-8")&&chunks.length===0){sBuf+=d;}else{if(sBuf.length>0){__slice_ensure_shard(5);chunks.push(Buffer.from(sBuf,"utf8"));sBuf="";}strFast=false;chunks.push(__toBytes(d,enc));}return this;},digest:function(enc){if(isSha256&&(enc==="hex"||enc==="base64"||enc==="base64url")){if(strFast&&chunks.length===0){var h=__slice_crypto_hmac_sha256(kStr,sBuf,enc);sBuf="";return h;}if(sBuf.length===0&&chunks.length===1){if(!kBytes)kBytes=(typeof key==="string")?key:__toBytes(key);var hb=__slice_crypto_hmac_sha256(kBytes,chunks[0],enc);chunks=[];return hb;}}__ensExt();__slice_ensure_shard(5);if(sBuf.length>0){chunks.push(Buffer.from(sBuf,"utf8"));sBuf="";}if(!kBytes)kBytes=__toBytes(key);var raw=Buffer.from(__slice_crypto_hmac_bytes(a,kBytes,__catBytes(chunks)));chunks=[];return(!enc||enc==="buffer")?raw:raw.toString(enc);}};},randomBytes:function(size,cb){__ensExt();__slice_ensure_shard(5);var b=Buffer.from(__slice_crypto_random_bytes(Number(size)||0));if(typeof cb==="function"){cb(null,b);return;}return b;},randomFillSync:function(buf,offset,size){__ensExt();if(!buf||typeof buf.byteLength!=="number")throw new TypeError("buf must be an ArrayBufferView");var off=offset!==undefined?Number(offset):0;var sz=size!==undefined?Number(size):(buf.byteLength-off);if(off<0||sz<0||off+sz>buf.byteLength)throw new RangeError("offset or size out of bounds");var u8=new __U8(buf.buffer||buf,(buf.byteOffset||0)+off,sz);var rnd=__slice_crypto_random_bytes(sz);u8.set(rnd);return buf;},randomFill:function(buf,offset,size,cb){if(typeof offset==="function"){cb=offset;offset=0;size=buf.byteLength;}else if(typeof size==="function"){cb=size;size=buf.byteLength-Number(offset||0);}try{var r=m.randomFillSync(buf,offset,size);if(typeof cb==="function")queueMicrotask(function(){cb(null,r);});}catch(e){if(typeof cb==="function")queueMicrotask(function(){cb(e);});else throw e;}},randomInt:function(min,max,cb){__ensExt();if(typeof max==="function"||max===undefined){cb=max;max=min;min=0;}var lo=Math.ceil(Number(min)),hi=Math.floor(Number(max));if(!(hi>lo))throw new RangeError("max must be greater than min");var range=hi-lo,rb=__slice_crypto_random_bytes(4),u=((rb[0]<<24)>>>0)+((rb[1]<<16)>>>0)+((rb[2]<<8)>>>0)+(rb[3]>>>0);var val=lo+(u%range);if(typeof cb==="function"){queueMicrotask(function(){cb(null,val);});return;}return val;},randomUUID:function(){__ensExt();return __slice_crypto_random_uuid();},getRandomValues:function(ta){__ensExt();return __slice_crypto_get_random_values(ta);},timingSafeEqual:function(a,b){__ensExt();return __slice_crypto_timing_safe_equal(a,b);},pbkdf2Sync:function(password,salt,iterations,keylen,digest){__ensExt();__slice_ensure_shard(5);var ab=__slice_crypto_kdf("PBKDF2",String(digest||"sha256"),__toBytes(password),__toBytes(salt),null,Number(iterations),Number(keylen));return Buffer.from(ab);},pbkdf2:function(password,salt,iterations,keylen,digest,cb){if(typeof digest==="function"){cb=digest;digest="sha1";}try{var b=m.pbkdf2Sync(password,salt,iterations,keylen,digest);if(typeof cb==="function")queueMicrotask(function(){cb(null,b);});}catch(e){if(typeof cb==="function")queueMicrotask(function(){cb(e);});else throw e;}},hkdfSync:function(digest,ikm,salt,info,keylen){__ensExt();var ab=__slice_crypto_kdf("HKDF",String(digest||"sha256"),__toBytes(ikm),__toBytes(salt),__toBytes(info),1,Number(keylen));return ab;},hkdf:function(digest,ikm,salt,info,keylen,cb){try{var ab=m.hkdfSync(digest,ikm,salt,info,keylen);if(typeof cb==="function")queueMicrotask(function(){cb(null,ab);});}catch(e){if(typeof cb==="function")queueMicrotask(function(){cb(e);});else throw e;}},scryptSync:function(password,salt,keylen,options){__ensExt();__slice_ensure_shard(5);var o=options||{};var N=Number(o.N||o.cost||16384),r=Number(o.r||o.blockSize||8),p=Number(o.p||o.parallelization||1),maxmem=Number(o.maxmem||(32*1024*1024));var ab=__slice_crypto_kdf("SCRYPT","SHA-256",__toBytes(password),__toBytes(salt),null,N,Number(keylen),r,p,maxmem);return Buffer.from(ab);},scrypt:function(password,salt,keylen,options,cb){if(typeof options==="function"){cb=options;options={};}try{var b=m.scryptSync(password,salt,keylen,options);if(typeof cb==="function")queueMicrotask(function(){cb(null,b);});}catch(e){if(typeof cb==="function")queueMicrotask(function(){cb(e);});else throw e;}},createCipheriv:function(algorithm,key,iv,options){__ensExt();__slice_ensure_shard(5);var alg=String(algorithm||"").toLowerCase(),isGcm=alg.indexOf("gcm")!==-1,kB=__toBytes(key),ivB=__toBytes(iv),aadB=null,chunks=[],tagBuf=null,autoPad=true,tagLen=(options&&options.authTagLength)?Number(options.authTagLength)*8:128;var hid=__slice_crypto_key_register(isGcm?"AES-GCM":"AES-CBC","",kB);return{setAAD:function(buf){aadB=__toBytes(buf);return this;},setAutoPadding:function(ap){autoPad=(ap===undefined)?true:Boolean(ap);return this;},update:function(data,inEnc,outEnc){chunks.push(__toBytes(data,inEnc));return __encOut(new __U8(0),outEnc);},final:function(outEnc){var plain=__catBytes(chunks);chunks=[];var ab=__slice_crypto_cipher(isGcm?"AES-GCM":"AES-CBC",true,hid,kB,ivB,aadB,tagLen,plain,autoPad);var full=new __U8(ab);if(isGcm){var tBytes=tagLen/8;var cLen=full.byteLength-tBytes;tagBuf=Buffer.from(full.subarray(cLen));return __encOut(full.subarray(0,cLen),outEnc);}return __encOut(full,outEnc);},getAuthTag:function(){if(!isGcm||!tagBuf)throw new Error("ERR_CRYPTO_INVALID_STATE: getAuthTag requires finalized GCM cipher");return tagBuf;}};},createDecipheriv:function(algorithm,key,iv,options){__ensExt();__slice_ensure_shard(5);var alg=String(algorithm||"").toLowerCase(),isGcm=alg.indexOf("gcm")!==-1,kB=__toBytes(key),ivB=__toBytes(iv),aadB=null,chunks=[],authTag=null,autoPad=true,tagLen=(options&&options.authTagLength)?Number(options.authTagLength)*8:128;var hid=__slice_crypto_key_register(isGcm?"AES-GCM":"AES-CBC","",kB);return{setAAD:function(buf){aadB=__toBytes(buf);return this;},setAuthTag:function(buf,enc){authTag=__toBytes(buf,enc);return this;},setAutoPadding:function(ap){autoPad=(ap===undefined)?true:Boolean(ap);return this;},update:function(data,inEnc,outEnc){chunks.push(__toBytes(data,inEnc));return __encOut(new __U8(0),outEnc);},final:function(outEnc){var ciph=__catBytes(chunks);chunks=[];if(isGcm){if(!authTag)throw new Error("ERR_CRYPTO_INVALID_STATE: Unsupported state or unable to authenticate data (missing authTag)");var combined=new __U8(ciph.byteLength+authTag.byteLength);combined.set(ciph,0);combined.set(authTag,ciph.byteLength);var ab=__slice_crypto_cipher("AES-GCM",false,hid,kB,ivB,aadB,tagLen,combined,true);return __encOut(new __U8(ab),outEnc);}var abC=__slice_crypto_cipher("AES-CBC",false,hid,kB,ivB,null,128,ciph,autoPad);return __encOut(new __U8(abC),outEnc);}};},generateKeyPairSync:function(type,options){__ensExt();__slice_ensure_shard(5);var t=String(type||"").toLowerCase(),o=options||{};var info=t==="ed25519"?JSON.parse(__slice_crypto_asym_keygen("Ed25519","")):JSON.parse(__slice_crypto_asym_keygen("ECDSA",String(o.namedCurve||"P-256")));var crv=info.crv||undefined;var pubKO=new KeyObject("public",t==="ed25519"?"ed25519":"ec",crv,info.pubId,__slice_base64_decode_bytes(info.spki),info);var privKO=new KeyObject("private",t==="ed25519"?"ed25519":"ec",crv,info.privId,__slice_base64_decode_bytes(info.pkcs8),info);var pubOut=o.publicKeyEncoding?pubKO.export(o.publicKeyEncoding):pubKO;var privOut=o.privateKeyEncoding?privKO.export(o.privateKeyEncoding):privKO;return{publicKey:pubOut,privateKey:privOut};},generateKeyPair:function(type,options,cb){if(typeof options==="function"){cb=options;options={};}try{var kp=m.generateKeyPairSync(type,options);if(typeof cb==="function")queueMicrotask(function(){cb(null,kp.publicKey,kp.privateKey);});}catch(e){if(typeof cb==="function")queueMicrotask(function(){cb(e);});else throw e;}},createPrivateKey:function(k){return __parseKeyObj(k,true);},createPublicKey:function(k){return __parseKeyObj(k,false);},createSecretKey:function(k,enc){__slice_ensure_shard(5);var b=__toBytes(k,enc);return new KeyObject("secret","secret",undefined,0,b,null);},sign:function(alg,data,key,cb){__ensExt();__slice_ensure_shard(5);try{var ko=__parseKeyObj(key,true);var dsaEnc=(key&&typeof key==="object"&&key.dsaEncoding)?String(key.dsaEncoding):"der";var ab=__slice_crypto_asym_sign(ko.asymmetricKeyType==="ed25519"?"Ed25519":"ECDSA",ko.asymmetricKeyDetails.namedCurve||"P-256",ko._id,ko._raw,__toBytes(data),dsaEnc!=="ieee-p1363");var b=Buffer.from(ab);if(typeof cb==="function"){queueMicrotask(function(){cb(null,b);});return;}return b;}catch(e){if(typeof cb==="function"){queueMicrotask(function(){cb(e);});return;}throw e;}},verify:function(alg,data,key,sig,cb){__ensExt();try{var ko=__parseKeyObj(key,false);var ok=Boolean(__slice_crypto_asym_verify(ko.asymmetricKeyType==="ed25519"?"Ed25519":"ECDSA",ko.asymmetricKeyDetails.namedCurve||"P-256",ko._id,ko._raw,__toBytes(sig),__toBytes(data)));if(typeof cb==="function"){queueMicrotask(function(){cb(null,ok);});return;}return ok;}catch(e){if(typeof cb==="function"){queueMicrotask(function(){cb(e);});return;}throw e;}},createSign:function(_alg){var chunks=[];return{update:function(d,enc){chunks.push(__toBytes(d,enc));return this;},sign:function(key,outEnc){var sig=m.sign(null,__catBytes(chunks),key);chunks=[];return(!outEnc||outEnc==="buffer")?sig:sig.toString(outEnc);}};},createVerify:function(_alg){var chunks=[];return{update:function(d,enc){chunks.push(__toBytes(d,enc));return this;},verify:function(key,sig,sigEnc){var sB=typeof sig==="string"?__toBytes(sig,sigEnc||"base64"):__toBytes(sig);var ok=m.verify(null,__catBytes(chunks),key,sB);chunks=[];return ok;}};},getHashes:function(){return["sha1","sha256","sha384","sha512","md5"];},getCiphers:function(){return["aes-128-gcm","aes-256-gcm","aes-128-cbc","aes-256-cbc"];},get subtle(){__slice_ensure_shard(4);return globalThis.crypto.subtle;},get webcrypto(){__slice_ensure_shard(4);return globalThis.crypto;}};m.default=m;m.__esModule=true;return __slice_builtins["crypto"]=__slice_builtins["node:crypto"]=m;})();"#; -const BUILTIN_FS_SNIPPET: &[u8] = br#"(function(){var __watchers=[];function __normW(p){return String(p||"").replace(/\\/g,"/").replace(/\/+$/,"")||"/";}function __notifyWatch(rawP,evType){if(__watchers.length===0)return;var np=__normW(rawP),sl=np.lastIndexOf("/"),dir=sl>0?np.slice(0,sl):"/",base=sl>=0?np.slice(sl+1):np;for(var i=0;i<__watchers.length;i++){var w=__watchers[i];if(w._closed)continue;var wp=w._path;if(np===wp||dir===wp||(w._rec&&np.indexOf(wp+"/")===0)){var rel=(np===wp)?base:(np.slice(wp.length+1)||base);w._emit(evType,rel);}}}function __fsData(d){if(typeof d==="string")return d;if(d instanceof Uint8Array)return d;if(d instanceof ArrayBuffer)return new Uint8Array(d);if(d&&d.buffer instanceof ArrayBuffer)return new Uint8Array(d.buffer,d.byteOffset||0,d.byteLength);return String(d);}function __mkStats(sp,followSym){var isSym=Boolean(__slice_fs_is_symlink_sync(sp)),sz=__slice_fs_stat_sync(sp),mt=__slice_fs_mtime_sync(sp),isDir=Boolean(__slice_fs_is_dir_sync(sp)),d=new Date(mt);return{size:sz,mtimeMs:mt,ctimeMs:mt,atimeMs:mt,birthtimeMs:mt,mtime:d,ctime:d,atime:d,birthtime:d,mode:(!followSym&&isSym)?41471:(isDir?16877:33188),isFile:function(){return(!followSym&&isSym)?false:!isDir;},isDirectory:function(){return(!followSym&&isSym)?false:isDir;},isSymbolicLink:function(){return !followSym&&isSym;},isBlockDevice:function(){return false;},isCharacterDevice:function(){return false;},isFIFO:function(){return false;},isSocket:function(){return false;}};}function __cbWrap(syncFn){return function(){var args=[],cb=null;for(var i=0;i=0;i--){var w=__watchers[i];if(w._path===np&&(!listener||w._wfListener===listener))w.close();}},createReadStream:function(p,opts){__slice_ensure_shard(5);var st=__slice_builtins["node:stream"]||__slice_load_builtin("node:stream");var o=(typeof opts==="string")?{encoding:opts}:(opts||{});var enc=o.encoding||null,hwm=Number(o.highWaterMark)||65536,start=o.start!==undefined?Number(o.start):0,end=o.end!==undefined?Number(o.end):Infinity;var rs=new st.Readable({highWaterMark:hwm,encoding:enc});rs.path=String(p);rs.bytesRead=0;rs.pending=true;queueMicrotask(function(){try{if(rs.destroyed)return;if(!m.existsSync(rs.path)){rs.emit("error",new Error("ENOENT: no such file or directory, open '"+rs.path+"'"));return;}rs.pending=false;rs.emit("open",3);rs.emit("ready");var raw=Buffer.from(__slice_fs_read_bytes_sync(rs.path));var sliceEnd=Math.min(raw.length,end===Infinity?raw.length:end+1);var view=raw.subarray(start,sliceEnd);for(var off=0;off0)waiters.shift().res({value:ev,done:false});else q.push(ev);});w.on("close",function(){done=true;while(waiters.length>0)waiters.shift().res({value:undefined,done:true});});return{[Symbol.asyncIterator]:function(){return{next:function(){if(q.length>0)return Promise.resolve({value:q.shift(),done:false});if(done||w._closed)return Promise.resolve({value:undefined,done:true});return new Promise(function(res,rej){waiters.push({res:res,rej:rej});});},return:function(){w.close();return Promise.resolve({value:undefined,done:true});}};}};}};fp.default=fp;fp.__esModule=true;m.promises=fp;m.default=m;m.__esModule=true;__slice_builtins["fs/promises"]=__slice_builtins["node:fs/promises"]=fp;return __slice_builtins["fs"]=__slice_builtins["node:fs"]=m;})();"#; +const BUILTIN_FS_SNIPPET: &[u8] = br#"(function(){var __watchers=[],__fds=Object.create(null),__nextFd=10;function __fsErr(code,syscall,p,dest){var map={ENOENT:[-2,"no such file or directory"],EEXIST:[-17,"file already exists"],EISDIR:[-21,"illegal operation on a directory"],ENOTDIR:[-20,"not a directory"],ENOTEMPTY:[-39,"directory not empty"],EBADF:[-9,"bad file descriptor"],EACCES:[-13,"permission denied"],EINVAL:[-22,"invalid argument"]},info=map[code]||[-1,"unknown error"],msg=code+": "+info[1]+", "+syscall+(p!==undefined?" '"+p+"'":"")+(dest!==undefined?" -> '"+dest+"'":""),e=new Error(msg);e.code=code;e.errno=info[0];e.syscall=syscall;if(p!==undefined)e.path=String(p);if(dest!==undefined)e.dest=String(dest);return e;}function __getFd(fd,syscall){var e=__fds[Number(fd)];if(!e)throw __fsErr("EBADF",syscall);return e;}function __normW(p){return String(p||"").replace(/\\/g,"/").replace(/\/+$/,"")||"/";}function __notifyWatch(rawP,evType){if(__watchers.length===0)return;var np=__normW(rawP),sl=np.lastIndexOf("/"),dir=sl>0?np.slice(0,sl):"/",base=sl>=0?np.slice(sl+1):np;for(var i=0;i<__watchers.length;i++){var w=__watchers[i];if(w._closed)continue;var wp=w._path;if(np===wp||dir===wp||(w._rec&&np.indexOf(wp+"/")===0)){var rel=(np===wp)?base:(np.slice(wp.length+1)||base);w._emit(evType,rel);}}}function __fsData(d){if(typeof d==="string")return d;if(d instanceof Uint8Array)return d;if(d instanceof ArrayBuffer)return new Uint8Array(d);if(d&&d.buffer instanceof ArrayBuffer)return new Uint8Array(d.buffer,d.byteOffset||0,d.byteLength);return String(d);}function __toMs(t){if(t instanceof Date)return t.getTime();var n=Number(t);if(!Number.isFinite(n))return Date.now();return n<1e11?n*1000:n;}function __mkStats(sp,followSym,opts){var isSym=Boolean(__slice_fs_is_symlink_sync(sp)),sz=__slice_fs_stat_sync(sp);if(sz<0&&!(!followSym&&isSym)){if(opts&&typeof opts==="object"&&opts.throwIfNoEntry===false)return undefined;throw __fsErr("ENOENT",followSym?"stat":"lstat",sp);}if(sz<0)sz=0;var mt=__slice_fs_mtime_sync(sp),isDir=(!followSym&&isSym)?false:Boolean(__slice_fs_is_dir_sync(sp)),d=new Date(mt),bi=Boolean(opts&&typeof opts==="object"&&opts.bigint),vSz=bi?BigInt(Math.floor(sz)):sz,vMt=bi?BigInt(Math.floor(mt)):mt,vMode=bi?BigInt((!followSym&&isSym)?41471:(isDir?16877:33188)):((!followSym&&isSym)?41471:(isDir?16877:33188));return{size:vSz,mtimeMs:vMt,ctimeMs:vMt,atimeMs:vMt,birthtimeMs:vMt,mtime:d,ctime:d,atime:d,birthtime:d,mode:vMode,isFile:function(){return(!followSym&&isSym)?false:!isDir;},isDirectory:function(){return(!followSym&&isSym)?false:isDir;},isSymbolicLink:function(){return !followSym&&isSym;},isBlockDevice:function(){return false;},isCharacterDevice:function(){return false;},isFIFO:function(){return false;},isSocket:function(){return false;}};}function __cbWrap(syncFn){return function(){var args=[],cb=null;for(var i=0;i=0?n.slice(sl+1):n,par=sl>=0?((base==="/"?"":base)+"/"+n.slice(0,sl)):base,isD=Boolean(__slice_fs_is_dir_sync(fp)),isS=Boolean(__slice_fs_is_symlink_sync(fp));return{name:bn,parentPath:par,path:par,isFile:function(){return !isD&&!isS;},isDirectory:function(){return isD&&!isS;},isSymbolicLink:function(){return isS;},isBlockDevice:function(){return false;},isCharacterDevice:function(){return false;},isFIFO:function(){return false;},isSocket:function(){return false;}};});}if(o.encoding==="buffer"){__slice_ensure_shard(5);return names.map(function(n){return Buffer.from(n,"utf8");});}return names;},statSync:function(p,opts){return __mkStats(String(p),true,opts);},lstatSync:function(p,opts){return __mkStats(String(p),false,opts);},fstatSync:function(fd,opts){var e=__getFd(fd,"fstat");return __mkStats(e.path,true,opts);},openSync:function(p,flags,mode){var sp=String(p),fl=(flags===undefined||flags===null)?"r":String(flags),isR=fl==="r"||fl==="rs"||fl==="0",hasX=fl.indexOf("x")!==-1,isW=fl.charCodeAt(0)===119||fl==="1"||fl==="577",isA=fl.charCodeAt(0)===97||fl.indexOf("1024")!==-1,isPlus=fl.indexOf("+")!==-1||fl==="2";if(hasX&&m.existsSync(sp))throw __fsErr("EEXIST","open",sp);if(isR&&!isPlus){var raw=__slice_fs_read_bytes_sync(sp);if(raw===null)throw __fsErr("ENOENT","open",sp);}else if(isW){var wr=__slice_fs_write_file_sync(sp,new Uint8Array(0));if(wr===-21)throw __fsErr("EISDIR","open",sp);__notifyWatch(sp,"change");}else if(isA){if(!m.existsSync(sp))__slice_fs_write_file_sync(sp,new Uint8Array(0));else __slice_fs_append_file_sync(sp,new Uint8Array(0));}else if(isR&&isPlus){if(__slice_fs_stat_sync(sp)<0)throw __fsErr("ENOENT","open",sp);}var fd=__nextFd++;__fds[fd]={path:sp,flags:fl,mode:mode||438,pos:0,readable:isR||isPlus,writable:isW||isA||isPlus,append:isA};return fd;},closeSync:function(fd){__getFd(fd,"close");delete __fds[Number(fd)];},readSync:function(fd,buf,offOrOpts,len,pos){var e=__getFd(fd,"read");if(!e.readable)throw __fsErr("EBADF","read");var offset=0,length=buf?buf.byteLength:0,position=null;if(offOrOpts&&typeof offOrOpts==="object"){offset=Number(offOrOpts.offset)||0;length=offOrOpts.length!==undefined?Number(offOrOpts.length):(buf.byteLength-offset);position=offOrOpts.position!==undefined?offOrOpts.position:null;}else{offset=Number(offOrOpts)||0;length=len!==undefined?Number(len):(buf.byteLength-offset);position=pos!==undefined?pos:null;}var raw=__slice_fs_read_bytes_sync(e.path);if(!raw||raw===-21)return 0;var readPos=(position!==null&&position!==undefined&&Number(position)>=0)?Number(position):e.pos;if(readPos>=raw.byteLength||length<=0)return 0;var avail=Math.min(length,raw.byteLength-readPos);var target=new Uint8Array(buf.buffer||buf,(buf.byteOffset||0)+offset,avail);target.set(raw.subarray(readPos,readPos+avail),0);if(position===null||position===undefined||Number(position)<0)e.pos=readPos+avail;return avail;},writeSync:function(fd,bufOrStr,offOrPos,lenOrEnc,pos){var e=__getFd(fd,"write");if(!e.writable)throw __fsErr("EBADF","write");__slice_ensure_shard(5);var src,writePos=null;if(typeof bufOrStr==="string"){var enc=typeof lenOrEnc==="string"?lenOrEnc:(typeof offOrPos==="string"?offOrPos:"utf8");if(typeof offOrPos==="number")writePos=offOrPos;src=Buffer.from(bufOrStr,enc);}else{var u8=__fsData(bufOrStr),off=offOrPos!==undefined?Number(offOrPos):0,ln=lenOrEnc!==undefined?Number(lenOrEnc):(u8.byteLength-off);if(pos!==undefined&&pos!==null)writePos=Number(pos);src=u8.subarray(off,off+ln);}if(e.append){__slice_fs_append_file_sync(e.path,src);e.pos+=src.byteLength;__notifyWatch(e.path,"change");return src.byteLength;}var rawCur=__slice_fs_read_bytes_sync(e.path),cur=(rawCur&&rawCur!==-21)?rawCur:new Uint8Array(0);var p=(writePos!==null&&writePos>=0)?writePos:e.pos,nLen=Math.max(cur.byteLength,p+src.byteLength),out=new Uint8Array(nLen);out.set(cur,0);out.set(src,p);__slice_fs_write_file_sync(e.path,out);if(writePos===null||writePos<0)e.pos=p+src.byteLength;__notifyWatch(e.path,"change");return src.byteLength;},fsyncSync:function(fd){__getFd(fd,"fsync");},fdatasyncSync:function(fd){__getFd(fd,"fdatasync");},ftruncateSync:function(fd,len){var e=__getFd(fd,"ftruncate");return m.truncateSync(e.path,len);},futimesSync:function(fd,atime,mtime){var e=__getFd(fd,"futime");return m.utimesSync(e.path,atime,mtime);},fchmodSync:function(fd,mode){var e=__getFd(fd,"fchmod");return m.chmodSync(e.path,mode);},realpathSync:function(p){var sp=String(p);if(__slice_fs_stat_sync(sp)<0)throw __fsErr("ENOENT","realpath",sp);var r=__slice_fs_realpath_sync(sp);if(!r)throw __fsErr("ENOENT","realpath",sp);return r;},readlinkSync:function(p,opts){var sp=String(p),r=__slice_fs_readlink_sync(sp);if(!r)throw __fsErr("ENOENT","readlink",sp);if(opts==="buffer"||(opts&&opts.encoding==="buffer")){__slice_ensure_shard(5);return Buffer.from(r,"utf8");}return r;},truncateSync:function(p,len){var sp=String(p);if(__slice_fs_stat_sync(sp)<0)throw __fsErr("ENOENT","truncate",sp);var r=__slice_fs_truncate_sync(sp,len===undefined?0:Number(len));__notifyWatch(sp,"change");return r;},utimesSync:function(p,atime,mtime){var sp=String(p);if(__slice_fs_stat_sync(sp)<0)throw __fsErr("ENOENT","utime",sp);return __slice_fs_utimes_sync(sp,__toMs(atime),__toMs(mtime));},lutimesSync:function(p,atime,mtime){return m.utimesSync(p,atime,mtime);},mkdtempSync:function(prefix){var r=__slice_fs_mkdtemp_sync(String(prefix||"/tmp/slice-"));if(!r)throw __fsErr("EACCES","mkdtemp",prefix);return r;},chmodSync:function(p,mode){return __slice_fs_chmod_sync(String(p),Number(mode)||0);},symlinkSync:function(target,p){var sp=String(p),r=__slice_fs_symlink_sync(String(target),sp);__notifyWatch(sp,"rename");return r;},opendirSync:function(p){var sp=String(p),names=m.readdirSync(sp,{withFileTypes:true}),idx=0;return{path:sp,readSync:function(){return idx0)throw __fsErr("ENOTEMPTY","rmdir",sp);var r=__slice_fs_rm_sync(sp);__notifyWatch(sp,"rename");return r;},copyFileSync:function(s,d,mode){var ss=String(s),sd=String(d);if(__slice_fs_stat_sync(ss)<0)throw __fsErr("ENOENT","copyfile",ss,sd);if((Number(mode)&1)&&m.existsSync(sd))throw __fsErr("EEXIST","copyfile",ss,sd);var r=__slice_fs_copy_file_sync(ss,sd);__notifyWatch(sd,"change");return r;},cpSync:function(src,dest,opts){var s=String(src).replace(/\/+$/,""),d=String(dest).replace(/\/+$/,""),o=opts||{};if(typeof o.filter==="function"&&!o.filter(s,d))return;if(!m.existsSync(s))throw __fsErr("ENOENT","cp",s);if(Boolean(__slice_fs_is_symlink_sync(s))&&!o.dereference){var linkTarget=m.readlinkSync(s);m.symlinkSync(linkTarget,d);return;}if(Boolean(__slice_fs_is_dir_sync(s))){if(o.recursive===false)throw __fsErr("EISDIR","cp",s);m.mkdirSync(d,{recursive:true});var entries=m.readdirSync(s);for(var i=0;i=0;i--){var w=__watchers[i];if(w._path===np&&(!listener||w._wfListener===listener))w.close();}},createReadStream:function(p,opts){__slice_ensure_shard(5);var st=__slice_builtins["node:stream"]||__slice_load_builtin("node:stream");var o=(typeof opts==="string")?{encoding:opts}:(opts||{});var enc=o.encoding||null,hwm=Number(o.highWaterMark)||65536,start=o.start!==undefined?Number(o.start):0,end=o.end!==undefined?Number(o.end):Infinity;var rs=new st.Readable({highWaterMark:hwm,encoding:enc});rs.path=String(p);rs.bytesRead=0;rs.pending=true;queueMicrotask(function(){try{if(rs.destroyed)return;if(!m.existsSync(rs.path)){rs.emit("error",__fsErr("ENOENT","open",rs.path));return;}rs.pending=false;rs.emit("open",3);rs.emit("ready");var raw=Buffer.from(__slice_fs_read_bytes_sync(rs.path));var sliceEnd=Math.min(raw.length,end===Infinity?raw.length:end+1);var view=raw.subarray(start,sliceEnd);for(var off=0;off0)waiters.shift().res({value:ev,done:false});else q.push(ev);});w.on("close",function(){done=true;while(waiters.length>0)waiters.shift().res({value:undefined,done:true});});return{[Symbol.asyncIterator]:function(){return{next:function(){if(q.length>0)return Promise.resolve({value:q.shift(),done:false});if(done||w._closed)return Promise.resolve({value:undefined,done:true});return new Promise(function(res,rej){waiters.push({res:res,rej:rej});});},return:function(){w.close();return Promise.resolve({value:undefined,done:true});}};}};}};fp.default=fp;fp.__esModule=true;m.promises=fp;m.default=m;m.__esModule=true;__slice_builtins["fs/promises"]=__slice_builtins["node:fs/promises"]=fp;return __slice_builtins["fs"]=__slice_builtins["node:fs"]=m;})();"#; const BUILTIN_PATH_SNIPPET: &[u8] = br#"(function(){function __normPath(p){var s=String(p||"").replace(/\\/g,"/");if(s.length===0)return ".";var isAbs=s.charCodeAt(0)===47,trailing=s.length>1&&s.charCodeAt(s.length-1)===47,parts=s.split("/"),out=[];for(var i=0;i0&&out[out.length-1]!=="..")out.pop();else if(!isAbs)out.push("..");}else out.push(seg);}var res=(isAbs?"/":"")+out.join("/");if(!res)res=isAbs?"/":".";if(trailing&&res!=="/")res+="/";return res;}var m={sep:"/",delimiter:":",normalize:__normPath,isAbsolute:function(p){var s=String(p||"");return s.length>0&&(s.charCodeAt(0)===47||s.charCodeAt(0)===92||(s.length>2&&s.charCodeAt(1)===58));},join:function(){var parts=[];for(var i=0;i=-1&&!resolvedAbs;i--){var p=i>=0?String(arguments[i]||""):"/";if(!p)continue;p=p.replace(/\\/g,"/");resolved=p+"/"+resolved;resolvedAbs=p.charCodeAt(0)===47;}var norm=__normPath(resolved);return(norm.length>1&&norm.charCodeAt(norm.length-1)===47)?norm.slice(0,-1):norm;},dirname:function(p){var s=String(p||"").replace(/\\/g,"/").replace(/\/+$/,"");if(!s)return ".";var i=s.lastIndexOf("/");return i>0?s.slice(0,i):(i===0?"/":".");},basename:function(p,ext){var s=String(p||"").replace(/\\/g,"/").replace(/\/+$/,""),i=s.lastIndexOf("/"),b=i>=0?s.slice(i+1):s;return(ext&&b.endsWith(ext))?b.slice(0,b.length-ext.length):b;},extname:function(p){var b=m.basename(p),i=b.lastIndexOf(".");return i>0?b.slice(i):"";},relative:function(from,to){var f=m.resolve(from),t=m.resolve(to);if(f===t)return "";var fs=f.split("/").filter(Boolean),ts=t.split("/").filter(Boolean),len=Math.min(fs.length,ts.length),same=len;for(var i=0;i0){var w=this._waiters.shift();w.res({value:fmt,done:false});return true;}this._buf.push(fmt);this._drainFlowing();return this._buf.length0&&this.readableFlowing===true&&!this.destroyed){var c=this._buf.shift();this.emit("data",c);}if(this._buf.length===0&&!this._eof)this._kickRead();}else if(this._buf.length>0&&this.listenerCount("readable")>0){this.emit("readable");}if(this._eof&&this._buf.length===0&&!this._emittedEnd){this._emittedEnd=true;this.readable=false;this.readableEnded=true;while(this._waiters.length>0){this._waiters.shift().res({value:undefined,done:true});}var self=this;queueMicrotask(function(){if(!self.destroyed){self.emit("end");self.emit("close");}});}};Readable.prototype.read=function(){if(this._buf.length>0){var c=this._buf.shift();if(this._buf.length===0&&!this._eof)this._kickRead();if(this._eof&&this._buf.length===0)this._drainFlowing();return c;}if(!this._eof)this._kickRead();if(this._eof)this._drainFlowing();return null;};Readable.prototype.pause=function(){if(this.readableFlowing!==false){this.readableFlowing=false;this.emit("pause");}return this;};Readable.prototype.resume=function(){if(!this.readableEnded){this.readableFlowing=true;this.emit("resume");this._kickRead();this._drainFlowing();}return this;};Readable.prototype.isPaused=function(){return this.readableFlowing===false;};Readable.prototype[Symbol.asyncIterator]=function(){var self=this;this.readableFlowing=false;this._kickRead();return{next:function(){if(self.destroyed&&self.errored)return Promise.reject(self.errored);if(self._buf.length>0){var c=self._buf.shift();if(self._buf.length===0&&!self._eof)self._kickRead();return Promise.resolve({value:c,done:false});}if(self._eof||self.readableEnded||self.destroyed)return Promise.resolve({value:undefined,done:true});self._kickRead();return new Promise(function(res,rej){self._waiters.push({res:res,rej:rej});});},return:function(){self.destroy();return Promise.resolve({value:undefined,done:true});}};};Readable.from=function(iterable,opts){var r=new Readable(Object.assign({objectMode:true},opts||{}));queueMicrotask(function(){try{if(iterable&&typeof iterable[Symbol.asyncIterator]==="function"){var ait=iterable[Symbol.asyncIterator]();(function pump(){ait.next().then(function(step){if(r.destroyed)return;if(step.done){r.push(null);}else{r.push(step.value);pump();}},function(err){r.destroy(err);});})();}else{var arr=Array.from(iterable||[]);for(var i=0;i0)this._corked--;if(this._corked===0&&this._corkBuf.length>0){var q=this._corkBuf.slice();this._corkBuf=[];for(var i=0;i0){this._corkBuf.push({c:chunk,e:e,cb:cb});return false;}this._doWrite(chunk,e,cb);return true;};Writable.prototype.end=function(chunk,enc,cb){if(typeof chunk==="function"){cb=chunk;chunk=undefined;enc=undefined;}else if(typeof enc==="function"){cb=enc;enc=undefined;}if(chunk!==undefined&&chunk!==null)this.write(chunk,enc);while(this._corked>0)this.uncork();if(this.writableEnded){if(typeof cb==="function"){if(this.writableFinished)queueMicrotask(cb);else this.once("finish",cb);}return this;}this.writableEnded=true;this.writable=false;var self=this;function finishNow(err){if(err){self.destroy(err);if(typeof cb==="function")cb(err);return;}self.writableFinished=true;self.emit("finish");if(typeof cb==="function")cb(null);if(!self.destroyed&&!(self instanceof Duplex))self.emit("close");}if(typeof this._final==="function"){try{this._final(finishNow);}catch(e){finishNow(e);}}else{queueMicrotask(function(){finishNow(null);});}return this;};Writable.fromWeb=function(webWs,opts){var w=webWs.getWriter();return new Writable(Object.assign({},opts||{},{write:function(c,_e,cb){w.write(c).then(function(){cb(null);},function(e){cb(e);});},final:function(cb){w.close().then(function(){cb(null);},function(e){cb(e);});}}));};Writable.toWeb=function(nodeWs){__slice_ensure_shard(3);return new globalThis.WritableStream({write:function(c){return new Promise(function(res,rej){nodeWs.write(c,function(e){if(e)rej(e);else res();});});},close:function(){return new Promise(function(res,rej){nodeWs.end(function(e){if(e)rej(e);else res();});});},abort:function(r){nodeWs.destroy(r instanceof Error?r:new Error(String(r||"Aborted")));}});};function Duplex(opts){if(!(this instanceof Duplex))return new Duplex(opts);Readable.call(this,opts);Writable.call(this,opts);this.allowHalfOpen=!opts||opts.allowHalfOpen!==false;}Duplex.prototype=Object.create(Readable.prototype);Object.assign(Duplex.prototype,Writable.prototype);Duplex.prototype.constructor=Duplex;function Transform(opts){if(!(this instanceof Transform))return new Transform(opts);Duplex.call(this,opts);var o=opts||{};if(typeof o.transform==="function")this._transform=o.transform;if(typeof o.flush==="function")this._flush=o.flush;}Transform.prototype=Object.create(Duplex.prototype);Transform.prototype.constructor=Transform;Transform.prototype._transform=function(c,_e,cb){this.push(c);if(cb)cb(null);};Transform.prototype._write=function(chunk,enc,cb){var self=this;this._transform(chunk,enc,function(err,out){if(err){if(cb)cb(err);else self.destroy(err);return;}if(out!==undefined&&out!==null)self.push(out);if(cb)cb(null);});};Transform.prototype._final=function(cb){var self=this;if(typeof this._flush==="function"){this._flush(function(err,out){if(err){cb(err);return;}if(out!==undefined&&out!==null)self.push(out);self.push(null);cb(null);});}else{this.push(null);cb(null);}};function PassThrough(opts){if(!(this instanceof PassThrough))return new PassThrough(opts);Transform.call(this,opts);}PassThrough.prototype=Object.create(Transform.prototype);PassThrough.prototype.constructor=PassThrough;function finished(stream,opts,cb){if(typeof opts==="function"){cb=opts;opts={};}var o=opts||{},sig=o.signal,settled=false;function done(err){if(settled)return;settled=true;if(typeof cb==="function")cb(err||null);}if(sig&&sig.aborted){queueMicrotask(function(){done(sig.reason||new Error("AbortError"));});return function(){};}if(stream.destroyed||stream.writableFinished||stream.readableEnded){queueMicrotask(function(){done(stream.errored||null);});return function(){};}function onEnd(){done(null);}function onErr(e){done(e||new Error("Stream error"));}function onClose(){if(!stream.writableFinished&&stream.writableEnded===false&&stream.readableEnded===false&&stream.errored){done(stream.errored);}else{done(null);}}if(stream.once){stream.once("finish",onEnd);stream.once("end",onEnd);stream.once("error",onErr);stream.once("close",onClose);}if(sig&&typeof sig.addEventListener==="function"){sig.addEventListener("abort",function(){var ae=sig.reason||new Error("AbortError");if(stream.destroy)stream.destroy(ae);done(ae);});}return function(){if(stream.removeListener){stream.removeListener("finish",onEnd);stream.removeListener("end",onEnd);stream.removeListener("error",onErr);stream.removeListener("close",onClose);}};}function pipeline(){var args=Array.from(arguments),cb=typeof args[args.length-1]==="function"?args.pop():null;if(args.length===1&&Array.isArray(args[0]))args=args[0];var opts=(args.length>1&&args[args.length-1]&&typeof args[args.length-1]==="object"&&typeof args[args.length-1].pipe!=="function"&&typeof args[args.length-1].write!=="function")?args.pop():{};var sig=opts&&opts.signal,settled=false;function finishAll(err){if(settled)return;settled=true;if(err){for(var k=0;k0){var w=this._waiters.shift();w.res({value:fmt,done:false});return true;}this._buf.push(fmt);this._drainFlowing();return this._buf.length0)this._enqueueFmt(rem);}this._eof=true;this._drainFlowing();return false;}var fmt=this._formatChunk(chunk);if(!this.readableObjectMode&&this._encoding&&typeof fmt==="string"&&fmt.length===0&&chunk&&((chunk.byteLength||chunk.length||0)>0))return true;return this._enqueueFmt(fmt);};Readable.prototype.unshift=function(chunk){if(chunk!==null&&chunk!==undefined){this._buf.unshift(this._formatChunk(chunk));this._drainFlowing();}return true;};Readable.prototype._drainFlowing=function(){if(this.readableFlowing===true){while(this._buf.length>0&&this.readableFlowing===true&&!this.destroyed){var c=this._buf.shift();this.emit("data",c);}if(this._buf.length===0&&!this._eof)this._kickRead();}else if(this._buf.length>0&&this.listenerCount("readable")>0){this.emit("readable");}if(this._eof&&this._buf.length===0&&!this._emittedEnd){this._emittedEnd=true;this.readable=false;this.readableEnded=true;while(this._waiters.length>0){this._waiters.shift().res({value:undefined,done:true});}var self=this;queueMicrotask(function(){if(!self.destroyed){self.emit("end");self.emit("close");}});}};Readable.prototype.read=function(){if(this._buf.length>0){var c=this._buf.shift();if(this._buf.length===0&&!this._eof)this._kickRead();if(this._eof&&this._buf.length===0)this._drainFlowing();return c;}if(!this._eof)this._kickRead();if(this._eof)this._drainFlowing();return null;};Readable.prototype.pause=function(){if(this.readableFlowing!==false){this.readableFlowing=false;this.emit("pause");}return this;};Readable.prototype.resume=function(){if(!this.readableEnded){this.readableFlowing=true;this.emit("resume");this._kickRead();this._drainFlowing();}return this;};Readable.prototype.isPaused=function(){return this.readableFlowing===false;};Readable.prototype[Symbol.asyncIterator]=function(){var self=this;this.readableFlowing=false;this._kickRead();return{next:function(){if(self.destroyed&&self.errored)return Promise.reject(self.errored);if(self._buf.length>0){var c=self._buf.shift();if(self._buf.length===0&&!self._eof)self._kickRead();return Promise.resolve({value:c,done:false});}if(self._eof||self.readableEnded||self.destroyed)return Promise.resolve({value:undefined,done:true});self._kickRead();return new Promise(function(res,rej){self._waiters.push({res:res,rej:rej});});},return:function(){self.destroy();return Promise.resolve({value:undefined,done:true});}};};Readable.from=function(iterable,opts){var r=new Readable(Object.assign({objectMode:true},opts||{}));queueMicrotask(function(){try{if(iterable&&typeof iterable[Symbol.asyncIterator]==="function"){var ait=iterable[Symbol.asyncIterator]();(function pump(){ait.next().then(function(step){if(r.destroyed)return;if(step.done){r.push(null);}else{r.push(step.value);pump();}},function(err){r.destroy(err);});})();}else{var arr=Array.from(iterable||[]);for(var i=0;i0)this._corked--;if(this._corked===0&&this._corkBuf.length>0){var q=this._corkBuf.slice();this._corkBuf=[];for(var i=0;i0){this._corkBuf.push({c:chunk,e:e,cb:cb,len:len});return ret;}this._doWrite(chunk,e,cb,len);return ret;};Writable.prototype.end=function(chunk,enc,cb){if(typeof chunk==="function"){cb=chunk;chunk=undefined;enc=undefined;}else if(typeof enc==="function"){cb=enc;enc=undefined;}if(chunk!==undefined&&chunk!==null)this.write(chunk,enc);while(this._corked>0)this.uncork();if(this.writableEnded){if(typeof cb==="function"){if(this.writableFinished)queueMicrotask(cb);else this.once("finish",cb);}return this;}this.writableEnded=true;this.writable=false;var self=this;function finishNow(err){if(err){self.destroy(err);if(typeof cb==="function")cb(err);return;}self.writableFinished=true;self.emit("finish");if(typeof cb==="function")cb(null);if(!self.destroyed&&!(self instanceof Duplex))self.emit("close");}if(typeof this._final==="function"){try{this._final(finishNow);}catch(e){finishNow(e);}}else{queueMicrotask(function(){finishNow(null);});}return this;};Writable.fromWeb=function(webWs,opts){var w=webWs.getWriter();return new Writable(Object.assign({},opts||{},{write:function(c,_e,cb){w.write(c).then(function(){cb(null);},function(e){cb(e);});},final:function(cb){w.close().then(function(){cb(null);},function(e){cb(e);});}}));};Writable.toWeb=function(nodeWs){__slice_ensure_shard(3);return new globalThis.WritableStream({write:function(c){return new Promise(function(res,rej){nodeWs.write(c,function(e){if(e)rej(e);else res();});});},close:function(){return new Promise(function(res,rej){nodeWs.end(function(e){if(e)rej(e);else res();});});},abort:function(r){nodeWs.destroy(r instanceof Error?r:new Error(String(r||"Aborted")));}});};function Duplex(opts){if(!(this instanceof Duplex))return new Duplex(opts);Readable.call(this,opts);Writable.call(this,opts);this.allowHalfOpen=!opts||opts.allowHalfOpen!==false;}Duplex.prototype=Object.create(Readable.prototype);Object.assign(Duplex.prototype,Writable.prototype);Duplex.prototype.constructor=Duplex;function Transform(opts){if(!(this instanceof Transform))return new Transform(opts);Duplex.call(this,opts);var o=opts||{};if(typeof o.transform==="function")this._transform=o.transform;if(typeof o.flush==="function")this._flush=o.flush;}Transform.prototype=Object.create(Duplex.prototype);Transform.prototype.constructor=Transform;Transform.prototype._transform=function(c,_e,cb){this.push(c);if(cb)cb(null);};Transform.prototype._write=function(chunk,enc,cb){var self=this;this._transform(chunk,enc,function(err,out){if(err){if(cb)cb(err);else self.destroy(err);return;}if(out!==undefined&&out!==null)self.push(out);if(cb)cb(null);});};Transform.prototype._final=function(cb){var self=this;if(typeof this._flush==="function"){this._flush(function(err,out){if(err){cb(err);return;}if(out!==undefined&&out!==null)self.push(out);self.push(null);cb(null);});}else{this.push(null);cb(null);}};function PassThrough(opts){if(!(this instanceof PassThrough))return new PassThrough(opts);Transform.call(this,opts);}PassThrough.prototype=Object.create(Transform.prototype);PassThrough.prototype.constructor=PassThrough;function finished(stream,opts,cb){if(typeof opts==="function"){cb=opts;opts={};}var o=opts||{},sig=o.signal,settled=false;function done(err){if(settled)return;settled=true;if(typeof cb==="function")cb(err||null);}if(sig&&sig.aborted){queueMicrotask(function(){done(sig.reason||new Error("AbortError"));});return function(){};}if(stream.destroyed||stream.writableFinished||stream.readableEnded){queueMicrotask(function(){done(stream.errored||null);});return function(){};}function onEnd(){done(null);}function onErr(e){done(e||new Error("Stream error"));}function onClose(){if(!stream.writableFinished&&stream.writableEnded===false&&stream.readableEnded===false&&stream.errored){done(stream.errored);}else{done(null);}}if(stream.once){stream.once("finish",onEnd);stream.once("end",onEnd);stream.once("error",onErr);stream.once("close",onClose);}if(sig&&typeof sig.addEventListener==="function"){sig.addEventListener("abort",function(){var ae=sig.reason||new Error("AbortError");if(stream.destroy)stream.destroy(ae);done(ae);});}return function(){if(stream.removeListener){stream.removeListener("finish",onEnd);stream.removeListener("end",onEnd);stream.removeListener("error",onErr);stream.removeListener("close",onClose);}};}function pipeline(){var args=Array.from(arguments),cb=typeof args[args.length-1]==="function"?args.pop():null;if(args.length===1&&Array.isArray(args[0]))args=args[0];var opts=(args.length>1&&args[args.length-1]&&typeof args[args.length-1]==="object"&&typeof args[args.length-1].pipe!=="function"&&typeof args[args.length-1].write!=="function")?args.pop():{};var sig=opts&&opts.signal,settled=false;function finishAll(err){if(settled)return;settled=true;if(err){for(var k=0;k0)req.push(Buffer.from(bodyBytes));req.complete=true;req.push(null);});return req;}function Server(opts,listener){if(!(this instanceof Server))return new Server(opts,listener);EE.call(this);var fn=typeof opts==="function"?opts:listener;if(typeof fn==="function")this.on("request",fn);this.listening=false;this.maxHeadersCount=null;this.timeout=0;this.keepAliveTimeout=5000;this.headersTimeout=60000;this.requestTimeout=300000;this._port=0;this._host="127.0.0.1";}Server.prototype=Object.create(EE.prototype);Server.prototype.constructor=Server;Server.prototype.setTimeout=function(ms,cb){this.timeout=Number(ms)||0;if(typeof cb==="function")this.on("timeout",cb);return this;};Server.prototype.address=function(){return this.listening?{address:this._host,family:"IPv4",port:this._port}:null;};Server.prototype.ref=function(){return this;};Server.prototype.unref=function(){return this;};Server.prototype._dispatchActiveHttpBridge=function(){if(typeof __slice_http_is_active!=="function"||!__slice_http_is_active())return;var self=this,m=__slice_http_method(),p=__slice_http_path(),q=__slice_http_query(),url=q?(p+"?"+q):p,rawH=[];try{rawH=JSON.parse(__slice_http_headers_all());}catch(_e){}var bStr=__slice_http_body()||"";var req=__buildIncoming(m,url,rawH,bStr?Buffer.from(bStr,"utf8"):null);var res=new ServerResponse(req,function(sr,bodyBuf){var ct="text/plain;charset=UTF-8",outH=[],ks=Object.keys(sr._headers);for(var i=0;i0)res.push(resBody);res.complete=true;res.push(null);});});return;}__slice_ensure_shard(10);__slice_ensure_shard(11);var url=this.protocol+"//"+this.host+(this.port&&this.port!==80&&this.port!==443?(":"+this.port):"")+this.path;var fOpts={method:this.method,headers:hdrPairs};if(bodyBuf.length>0&&this.method!=="GET"&&this.method!=="HEAD")fOpts.body=bodyBuf.toString("utf8");globalThis.fetch(url,fOpts).then(function(fRes){if(fcb)fcb(null);var res=new IncomingMessage();res.statusCode=fRes.status;res.statusMessage=fRes.statusText||STATUS_CODES[fRes.status]||"OK";if(fRes.headers&&typeof fRes.headers.forEach==="function"){fRes.headers.forEach(function(val,key){var kl=String(key).toLowerCase();res.headers[kl]=String(val);res.rawHeaders.push(String(key),String(val));});}self.res=res;self.emit("response",res);return fRes.text().then(function(txt){if(txt&&txt.length>0)res.push(Buffer.from(txt,"utf8"));res.complete=true;res.push(null);});},function(err){if(fcb)fcb(null);self.emit("error",err instanceof Error?err:new Error(String(err)));});};function __mkHttpMod(defaultProto){var globalAgent=new Agent({keepAlive:true});var m={METHODS:METHODS,STATUS_CODES:STATUS_CODES,IncomingMessage:IncomingMessage,ServerResponse:ServerResponse,Server:Server,ClientRequest:function(a0,a1,a2){return new ClientRequest(defaultProto,a0,a1,a2);},Agent:Agent,globalAgent:globalAgent,maxHeaderSize:16384,createServer:function(opts,listener){return new Server(opts,listener);},request:function(a0,a1,a2){return new ClientRequest(defaultProto,a0,a1,a2);},get:function(a0,a1,a2){var req=new ClientRequest(defaultProto,a0,a1,a2);req.end();return req;},validateHeaderName:function(n){if(!n||!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(String(n)))throw new TypeError("ERR_INVALID_HTTP_TOKEN: Header name must be a valid HTTP token");},validateHeaderValue:function(n,v){if(v===undefined||/[\r\n\0]/.test(String(v)))throw new TypeError("ERR_INVALID_CHAR: Invalid character in header content");}};m.default=m;m.__esModule=true;return m;}var httpMod=__mkHttpMod("http:"),httpsMod=__mkHttpMod("https:");__slice_builtins["https"]=__slice_builtins["node:https"]=httpsMod;return __slice_builtins["http"]=__slice_builtins["node:http"]=httpMod;})();"#; -const BUILTIN_CHILD_PROCESS_SNIPPET: &[u8] = br#"(function(){__slice_ensure_shard(5);var EE=__slice_builtins["node:events"]||__slice_load_builtin("node:events");var st=__slice_builtins["node:stream"]||__slice_load_builtin("node:stream");function __splitCmd(cmd){var s=String(cmd||"").trim(),args=[],cur="",q=null;for(var i=0;i0){args.push(cur);cur="";}}else{cur+=ch;}}if(cur.length>0)args.push(cur);return args;}function __normArgsOpts(file,a1,a2){var args=[],opts={};if(Array.isArray(a1)){args=a1.map(String);if(a2&&typeof a2==="object")opts=a2;}else if(a1&&typeof a1==="object"){opts=a1;}return{file:String(file||""),args:args,opts:opts};}function __prepOpts(opts){var o=opts||{},out={};if(o.cwd!==undefined)out.cwd=String(o.cwd);if(o.env&&typeof o.env==="object")out.env=o.env;if(o.input!==undefined){out.input=(o.input instanceof Uint8Array)?Buffer.from(o.input).toString("utf8"):String(o.input);}if(o.timeout!==undefined)out.timeout=Number(o.timeout);if(o.maxBuffer!==undefined)out.maxBuffer=Number(o.maxBuffer);if(o.shell!==undefined)out.shell=o.shell;return out;}function __fmtOut(b64,str,enc){if(enc&&enc!=="buffer"&&enc!=="null"){if(enc==="utf8"||enc==="utf-8")return str;return Buffer.from(b64,"base64").toString(enc);}return Buffer.from(b64,"base64");}function spawnSync(file,a1,a2){var n=__normArgsOpts(file,a1,a2),enc=n.opts.encoding;var raw=JSON.parse(__slice_child_process_spawn_sync(n.file,JSON.stringify(n.args),JSON.stringify(__prepOpts(n.opts))));var outVal=__fmtOut(raw.stdoutBase64||"",raw.stdout||"",enc);var errVal=__fmtOut(raw.stderrBase64||"",raw.stderr||"",enc);return{pid:raw.pid||4200,output:[null,outVal,errVal],stdout:outVal,stderr:errVal,status:raw.status,signal:raw.signal||null,error:undefined};}function execFileSync(file,a1,a2){var n=__normArgsOpts(file,a1,a2),res=spawnSync(n.file,n.args,n.opts);if(res.status!==0){var errMsg="Command failed: "+n.file+(n.args.length>0?" "+n.args.join(" "):"");var errTxt=typeof res.stderr==="string"?res.stderr:res.stderr.toString("utf8");if(errTxt)errMsg+="\n"+errTxt;var e=new Error(errMsg);e.status=res.status;e.signal=res.signal;e.output=res.output;e.pid=res.pid;e.stdout=res.stdout;e.stderr=res.stderr;throw e;}return res.stdout;}function execSync(command,options){var parts=__splitCmd(command),file=parts[0]||"",args=parts.slice(1);return execFileSync(file,args,options||{});}function ChildProcess(){EE.call(this);this.pid=4200;this.connected=false;this.killed=false;this.exitCode=null;this.signalCode=null;this.spawnargs=[];this.spawnfile="";this.stdin=new st.Writable();this.stdout=new st.Readable();this.stderr=new st.Readable();}ChildProcess.prototype=Object.create(EE.prototype);ChildProcess.prototype.constructor=ChildProcess;ChildProcess.prototype.kill=function(sig){this.killed=true;this.signalCode=sig||"SIGTERM";return true;};ChildProcess.prototype.ref=function(){return this;};ChildProcess.prototype.unref=function(){return this;};function spawn(file,a1,a2){var n=__normArgsOpts(file,a1,a2),cp=new ChildProcess();cp.spawnfile=n.file;cp.spawnargs=[n.file].concat(n.args);queueMicrotask(function(){if(cp.killed)return;try{var res=spawnSync(n.file,n.args,n.opts);cp.pid=res.pid;cp.exitCode=res.status;cp.signalCode=res.signal;cp.emit("spawn");if(res.stdout&&res.stdout.length>0)cp.stdout.push(res.stdout);cp.stdout.push(null);if(res.stderr&&res.stderr.length>0)cp.stderr.push(res.stderr);cp.stderr.push(null);queueMicrotask(function(){cp.emit("exit",cp.exitCode,cp.signalCode);cp.emit("close",cp.exitCode,cp.signalCode);});}catch(e){cp.emit("error",e);}});return cp;}function execFile(file,a1,a2,a3){var args=[],opts={},cb=null;if(typeof a1==="function"){cb=a1;}else if(Array.isArray(a1)){args=a1.map(String);if(typeof a2==="function"){cb=a2;}else if(a2&&typeof a2==="object"){opts=a2;if(typeof a3==="function")cb=a3;}}else if(a1&&typeof a1==="object"){opts=a1;if(typeof a2==="function")cb=a2;}var execOpts=Object.assign({encoding:"utf8"},opts);var cp=new ChildProcess();cp.spawnfile=String(file||"");cp.spawnargs=[cp.spawnfile].concat(args);queueMicrotask(function(){try{var res=spawnSync(file,args,execOpts);cp.pid=res.pid;cp.exitCode=res.status;if(res.status!==0){var e=new Error("Command failed: "+file);e.code=res.status;e.killed=false;e.signal=res.signal;if(typeof cb==="function")cb(e,res.stdout,res.stderr);return;}if(typeof cb==="function")cb(null,res.stdout,res.stderr);}catch(err){if(typeof cb==="function")cb(err,"","");else cp.emit("error",err);}});return cp;}function exec(command,a1,a2){var opts={},cb=null;if(typeof a1==="function")cb=a1;else if(a1&&typeof a1==="object"){opts=a1;if(typeof a2==="function")cb=a2;}var parts=__splitCmd(command),file=parts[0]||"",args=parts.slice(1);return execFile(file,args,opts,cb);}var m={ChildProcess:ChildProcess,spawn:spawn,spawnSync:spawnSync,execFile:execFile,execFileSync:execFileSync,exec:exec,execSync:execSync,fork:function(modulePath,args,opts){return spawn("node",[String(modulePath)].concat(Array.isArray(args)?args:[]),opts||{});}};m.default=m;m.__esModule=true;return __slice_builtins["child_process"]=__slice_builtins["node:child_process"]=m;})();"#; +const BUILTIN_CHILD_PROCESS_SNIPPET: &[u8] = br#"(function(){__slice_ensure_shard(5);var EE=__slice_builtins["node:events"]||__slice_load_builtin("node:events");var st=__slice_builtins["node:stream"]||__slice_load_builtin("node:stream");function __normArgsOpts(file,a1,a2){var args=[],opts={};if(Array.isArray(a1)){args=a1.map(String);if(a2&&typeof a2==="object")opts=a2;}else if(a1&&typeof a1==="object"){opts=a1;}return{file:String(file||""),args:args,opts:opts};}function __prepOpts(opts){var o=opts||{},out={};if(o.cwd!==undefined)out.cwd=String(o.cwd);if(o.env&&typeof o.env==="object")out.env=o.env;if(o.inputBase64!==undefined){out.inputBase64=String(o.inputBase64);}else if(o.input!==undefined){if(o.input instanceof Uint8Array){out.inputBase64=Buffer.from(o.input).toString("base64");}else if(o.input&&o.input.buffer instanceof ArrayBuffer){out.inputBase64=Buffer.from(new Uint8Array(o.input.buffer,o.input.byteOffset||0,o.input.byteLength)).toString("base64");}else{out.input=String(o.input);}}if(o.timeout!==undefined)out.timeout=Number(o.timeout);if(o.maxBuffer!==undefined)out.maxBuffer=Number(o.maxBuffer);if(o.shell!==undefined)out.shell=o.shell;return out;}function __fmtOut(b64,str,enc){if(enc&&enc!=="buffer"&&enc!=="null"){if(enc==="utf8"||enc==="utf-8")return str;return Buffer.from(b64,"base64").toString(enc);}return Buffer.from(b64,"base64");}function spawnSync(file,a1,a2){var n=__normArgsOpts(file,a1,a2),enc=n.opts.encoding;var raw=JSON.parse(__slice_child_process_spawn_sync(n.file,JSON.stringify(n.args),JSON.stringify(__prepOpts(n.opts))));var outVal=__fmtOut(raw.stdoutBase64||"",raw.stdout||"",enc);var errVal=__fmtOut(raw.stderrBase64||"",raw.stderr||"",enc);if(raw.errorCode){var err=new Error("spawnSync "+n.file+" "+raw.errorCode);err.code=raw.errorCode;err.errno=raw.errorErrno||-2;err.syscall="spawnSync "+n.file;err.path=n.file;err.spawnargs=n.args;if(raw.errorCode==="ENOENT"){return{pid:0,output:[null,null,null],stdout:null,stderr:null,status:null,signal:null,error:err};}return{pid:raw.pid||0,output:[null,outVal,errVal],stdout:outVal,stderr:errVal,status:null,signal:raw.signal||"SIGTERM",error:err};}return{pid:raw.pid||4200,output:[null,outVal,errVal],stdout:outVal,stderr:errVal,status:raw.status,signal:raw.signal||null,error:undefined};}function execFileSync(file,a1,a2){var n=__normArgsOpts(file,a1,a2),res=spawnSync(n.file,n.args,n.opts);if(res.error){res.error.status=res.status;res.error.signal=res.signal;res.error.output=res.output;res.error.pid=res.pid;res.error.stdout=res.stdout;res.error.stderr=res.stderr;throw res.error;}if(res.status!==0){var errMsg="Command failed: "+n.file+(n.args.length>0?" "+n.args.join(" "):"");var errTxt=typeof res.stderr==="string"?res.stderr:(res.stderr?res.stderr.toString("utf8"):"");if(errTxt)errMsg+="\n"+errTxt;var e=new Error(errMsg);e.status=res.status;e.signal=res.signal;e.output=res.output;e.pid=res.pid;e.stdout=res.stdout;e.stderr=res.stderr;throw e;}return res.stdout;}function execSync(command,options){var o=options||{};return execFileSync(String(command||""),[],Object.assign({},o,{shell:o.shell||true}));}function ChildProcess(){EE.call(this);var self=this;this.pid=4200;this.connected=false;this.killed=false;this.exitCode=null;this.signalCode=null;this.spawnargs=[];this.spawnfile="";this._stdinChunks=[];this.stdin=new st.Writable({write:function(chunk,enc,cb){var u8=(chunk instanceof Uint8Array)?chunk:Buffer.from(String(chunk),enc&&enc!=="buffer"?enc:"utf8");self._stdinChunks.push(Buffer.from(u8));if(cb)cb(null);}});this.stdout=new st.Readable();this.stderr=new st.Readable();}ChildProcess.prototype=Object.create(EE.prototype);ChildProcess.prototype.constructor=ChildProcess;ChildProcess.prototype.kill=function(sig){this.killed=true;this.signalCode=sig||"SIGTERM";return true;};ChildProcess.prototype.ref=function(){return this;};ChildProcess.prototype.unref=function(){return this;};function spawn(file,a1,a2){var n=__normArgsOpts(file,a1,a2),cp=new ChildProcess();cp.spawnfile=n.file;cp.spawnargs=[n.file].concat(n.args);queueMicrotask(function(){if(cp.killed)return;try{var sOpts=n.opts;if(cp._stdinChunks.length>0&&sOpts.input===undefined&&sOpts.inputBase64===undefined){sOpts=Object.assign({},sOpts,{inputBase64:Buffer.concat(cp._stdinChunks).toString("base64")});}var res=spawnSync(n.file,n.args,sOpts);if(res.error){res.error.syscall="spawn "+n.file;res.error.message="spawn "+n.file+" "+res.error.code;cp.emit("error",res.error);cp.emit("close",-2,null);return;}cp.pid=res.pid;cp.exitCode=res.status;cp.signalCode=res.signal;cp.emit("spawn");if(res.stdout&&res.stdout.length>0)cp.stdout.push(res.stdout);cp.stdout.push(null);if(res.stderr&&res.stderr.length>0)cp.stderr.push(res.stderr);cp.stderr.push(null);queueMicrotask(function(){cp.emit("exit",cp.exitCode,cp.signalCode);cp.emit("close",cp.exitCode,cp.signalCode);});}catch(e){cp.emit("error",e);}});return cp;}function execFile(file,a1,a2,a3){var args=[],opts={},cb=null;if(typeof a1==="function"){cb=a1;}else if(Array.isArray(a1)){args=a1.map(String);if(typeof a2==="function"){cb=a2;}else if(a2&&typeof a2==="object"){opts=a2;if(typeof a3==="function")cb=a3;}}else if(a1&&typeof a1==="object"){opts=a1;if(typeof a2==="function")cb=a2;}var execOpts=Object.assign({encoding:"utf8"},opts);var cp=new ChildProcess();cp.spawnfile=String(file||"");cp.spawnargs=[cp.spawnfile].concat(args);queueMicrotask(function(){try{if(cp._stdinChunks.length>0&&execOpts.input===undefined&&execOpts.inputBase64===undefined){execOpts=Object.assign({},execOpts,{inputBase64:Buffer.concat(cp._stdinChunks).toString("base64")});}var res=spawnSync(file,args,execOpts);if(res.error){if(typeof cb==="function")cb(res.error,"","");else cp.emit("error",res.error);return;}cp.pid=res.pid;cp.exitCode=res.status;if(res.status!==0){var e=new Error("Command failed: "+file+(args.length>0?" "+args.join(" "):""));e.code=res.status;e.status=res.status;e.killed=false;e.signal=res.signal;if(typeof cb==="function")cb(e,res.stdout,res.stderr);return;}if(typeof cb==="function")cb(null,res.stdout,res.stderr);}catch(err){if(typeof cb==="function")cb(err,"","");else cp.emit("error",err);}});return cp;}function exec(command,a1,a2){var opts={},cb=null;if(typeof a1==="function")cb=a1;else if(a1&&typeof a1==="object"){opts=a1;if(typeof a2==="function")cb=a2;}return execFile(String(command||""),[],Object.assign({},opts,{shell:opts.shell||true}),cb);}var m={ChildProcess:ChildProcess,spawn:spawn,spawnSync:spawnSync,execFile:execFile,execFileSync:execFileSync,exec:exec,execSync:execSync,fork:function(modulePath,args,opts){return spawn("node",[String(modulePath)].concat(Array.isArray(args)?args:[]),opts||{});}};m.default=m;m.__esModule=true;return __slice_builtins["child_process"]=__slice_builtins["node:child_process"]=m;})();"#; static BUILTIN_SLICEBC_CACHE: OnceLock>>>> = OnceLock::new(); @@ -149,7 +149,7 @@ pub(crate) fn eval_lazy_builtin_module( br#"(function(){function createContext(sandbox){var sb=(sandbox&&typeof sandbox==="object")?sandbox:{};Object.defineProperty(sb,"__slice_vm_ctx",{value:true,enumerable:false,configurable:true,writable:true});return sb;}function isContext(obj){return Boolean(obj&&typeof obj==="object"&&obj.__slice_vm_ctx===true);}function __runSandboxed(code,ctxObj,opts){var sb=(ctxObj&&typeof ctxObj==="object")?ctxObj:{};var ks=Object.keys(sb),inObj={},validKeys=[];for(var i=0;i0){pre="const __vm_in = "+JSON.stringify(inObj)+";\n";for(var j=0;j0){post="const __vm_out = {};\n";for(var l=0;l0?(pre+"try {\n"+String(code)+"\n} finally {\n"+post+"}"):String(code);var sbOpts={};if(opts&&typeof opts==="object"){if(opts.fuel)sbOpts.fuel=Number(opts.fuel);else if(opts.timeout)sbOpts.fuel=Math.max(1000,Number(opts.timeout)*10000);if(opts.memoryBytes)sbOpts.memoryBytes=Number(opts.memoryBytes);}var out=globalThis.Slice.evalSandbox(wrapped,sbOpts);if(!out.ok)throw new Error(out.violation||out.error||"vm sandbox execution failed");var lines=out.stdout||[],marker="__SLICE_VM__:";for(var m=lines.length-1;m>=0;m--){if(lines[m].indexOf(marker)===0){var parsed=JSON.parse(lines[m].slice(marker.length));if(parsed&&typeof parsed==="object"){var cks=Object.keys(parsed);for(var n=0;n { - br#"(function(){__slice_ensure_shard(5);function StringDecoder(enc){if(!(this instanceof StringDecoder))return new StringDecoder(enc);this.encoding=String(enc||"utf8").toLowerCase();if(this.encoding==="utf-8")this.encoding="utf8";}StringDecoder.prototype.write=function(buf){if(typeof buf==="string")return buf;return Buffer.from(buf).toString(this.encoding);};StringDecoder.prototype.end=function(buf){return buf!==undefined?this.write(buf):"";};var m={StringDecoder:StringDecoder};m.default=m;m.__esModule=true;return __slice_builtins["string_decoder"]=__slice_builtins["node:string_decoder"]=m;})()"# + br#"(function(){__slice_ensure_shard(2);__slice_ensure_shard(5);function StringDecoder(enc){if(!(this instanceof StringDecoder))return new StringDecoder(enc);var e=String(enc||"utf8").toLowerCase();if(e==="utf-8"||e==="utf8")e="utf8";else if(e==="ucs2"||e==="ucs-2"||e==="utf-16le")e="utf16le";this.encoding=e;this._rem=null;}StringDecoder.prototype.write=function(buf){if(typeof buf==="string")return buf;var u8=(buf instanceof Uint8Array)?buf:Buffer.from(buf);if(this._rem!==null){var rLen=this._rem.length;if(rLen>0){var comb=new Uint8Array(rLen+u8.length);comb.set(this._rem,0);comb.set(u8,rLen);u8=comb;}this._rem=null;}var len=u8.length;if(len===0)return "";if(this.encoding==="utf8"){if(u8[len-1]>=0x80){var cont=0;while(cont<3&&cont0&&(cont+1)0){this._rem=u8.slice(len-rem16);u8=u8.subarray(0,len-rem16);len-=rem16;}if(len>=2){var hi=u8[len-2]|(u8[len-1]<<8);if(hi>=0xD800&&hi<=0xDBFF){var tail=u8.slice(len-2);if(this._rem!==null){var c16=new Uint8Array(2+this._rem.length);c16.set(tail,0);c16.set(this._rem,2);this._rem=c16;}else{this._rem=tail;}u8=u8.subarray(0,len-2);}}}else if(this.encoding==="base64"||this.encoding==="base64url"){var remB=len%3;if(remB>0){this._rem=u8.slice(len-remB);u8=u8.subarray(0,len-remB);}}if(u8.length===0)return "";return Buffer.prototype.toString.call(u8,this.encoding);};StringDecoder.prototype.end=function(buf){var out=buf!==undefined?this.write(buf):"";if(this._rem!==null&&this._rem.length>0){var r=this.encoding==="utf8"?__slice_text_decode(this._rem,"utf-8",false,true):Buffer.prototype.toString.call(this._rem,this.encoding);this._rem=null;out+=r;}return out;};var m={StringDecoder:StringDecoder};m.default=m;m.__esModule=true;return __slice_builtins["string_decoder"]=__slice_builtins["node:string_decoder"]=m;})()"# } "querystring" | "node:querystring" => { br#"(function(){function unescape(s){try{return decodeURIComponent(String(s).replace(/\+/g," "));}catch(_e){return String(s);}}function escape(s){return encodeURIComponent(String(s));}function parse(str,sep,eq){var out=Object.create(null),s=String(str||"");if(!s)return out;var sp=sep||"&",e=eq||"=",parts=s.split(sp);for(var i=0;i { crate::host_bindings::register_kv_and_sandbox_host_functions(context); - br#"(function(){var __st={suites:[],be:[[]],ae:[[]],res:[],passed:0,failed:0,skipped:0,rollbacks:0};function __eq(a,b){if(a===b)return true;if(a&&b&&typeof a==="object"&&typeof b==="object")return JSON.stringify(a)===JSON.stringify(b);return false;}function __vMatch(v,s){if(!s)return true;var q=String(s);if(v.indexOf(q)!==-1)return true;if(q==="FsReadDenied")return v.indexOf("filesystem read authority")!==-1;if(q==="FsWriteDenied")return v.indexOf("filesystem write authority")!==-1;if(q==="NetAccessDenied"||q==="NetConnectDenied")return v.indexOf("outbound network authority")!==-1;if(q==="EnvAccessDenied")return v.indexOf("environment variable authority")!==-1;if(q==="ExecDenied")return v.indexOf("Subprocess execution denied")!==-1;if(q==="CpuFuelExhausted")return v.indexOf("CPU instruction fuel limit")!==-1;if(q==="MemoryCeilingExceeded"||q==="MemoryLimitExceeded")return v.indexOf("memory ceiling")!==-1;if(q==="EgressSecretLeakBlocked")return v.indexOf("EGRESS_SECRET_LEAK_BLOCKED")!==-1;return false;}function __mkExp(act,neg){function chk(ok,msg){if(neg?ok:!ok)throw new Error(msg);}return{get not(){return __mkExp(act,!neg);},toBe:function(e){chk(act===e,"Expected "+JSON.stringify(e)+" but got "+JSON.stringify(act));},toEqual:function(e){chk(__eq(act,e),"Expected deep equal "+JSON.stringify(e)+" but got "+JSON.stringify(act));},toContain:function(s){var ok=(typeof act==="string"||Array.isArray(act))&&act.indexOf(s)!==-1;chk(ok,"Expected "+JSON.stringify(act)+" to contain "+JSON.stringify(s));},toBeTruthy:function(){chk(Boolean(act),"Expected truthy but got "+JSON.stringify(act));},toBeFalsy:function(){chk(!act,"Expected falsy but got "+JSON.stringify(act));},toBeNull:function(){chk(act===null,"Expected null but got "+JSON.stringify(act));},toBeDefined:function(){chk(act!==undefined,"Expected defined value");},toBeUndefined:function(){chk(act===undefined,"Expected undefined but got "+JSON.stringify(act));},toBeGreaterThan:function(n){chk(Number(act)>Number(n),"Expected "+act+" > "+n);},toBeGreaterThanOrEqual:function(n){chk(Number(act)>=Number(n),"Expected "+act+" >= "+n);},toBeLessThan:function(n){chk(Number(act)0&&__vMatch(v,sub));chk(ok,"Expected sandbox violation "+(sub||"*")+" but got "+(v||"ok:true"));},toStayWithinFuel:function(maxF){var r=typeof act==="function"?act():act;var ok=Boolean(r&&r.ok===true&&typeof r.fuelUsed==="number"&&r.fuelUsed<=Number(maxF));chk(ok,"Expected fuelUsed <= "+maxF+" but got "+(r&&r.fuelUsed));},toStayWithinMemory:function(maxB){var r=typeof act==="function"?act():act;var ok=Boolean(r&&r.ok===true&&typeof r.memoryUsedBytes==="number"&&r.memoryUsedBytes<=Number(maxB));chk(ok,"Expected memoryUsedBytes <= "+maxB+" but got "+(r&&r.memoryUsedBytes));}};}var m={describe:function(n,fn){__st.suites.push(String(n));__st.be.push([]);__st.ae.push([]);try{fn();}finally{__st.suites.pop();__st.be.pop();__st.ae.pop();}},beforeEach:function(fn){__st.be[__st.be.length-1].push(fn);},afterEach:function(fn){__st.ae[__st.ae.length-1].push(fn);},test:function(n,fn,opts){var suite=__st.suites.join(" > "),full=suite?(suite+" > "+n):String(n),flt=globalThis.__slice_test_filter||"";if(flt&&full.indexOf(flt)===-1){__st.skipped++;return;}var iso=!(opts&&opts.isolateState===false),snap=iso?__slice_checkpoint():0,t0=performance.now(),err=null;try{for(var i=0;i<__st.be.length;i++)for(var j=0;j<__st.be[i].length;j++)__st.be[i][j]();var r=fn();if(r&&typeof r.then==="function"){r.then(function(){},function(e){err=String(e&&e.message||e);});}__slice_drain_event_loop();for(var k=__st.ae.length-1;k>=0;k--)for(var l=0;l<__st.ae[k].length;l++)__st.ae[k][l]();}catch(e){err=String(e&&e.message||e);}finally{__slice_clear_timers();if(snap>0){__slice_restore(snap);__slice_release_checkpoint(snap);__st.rollbacks++;}}var dur=Math.max(1,Math.round((performance.now()-t0)*1000));if(!err){__st.passed++;__st.res.push({suite:suite,name:String(n),fullName:full,passed:true,durationUs:dur,checkpointId:snap,restored:snap>0,error:null});}else{__st.failed++;__st.res.push({suite:suite,name:String(n),fullName:full,passed:false,durationUs:dur,checkpointId:snap,restored:snap>0,error:err});}},expect:function(v){return __mkExp(v,false);},summary:function(){return{total:__st.passed+__st.failed+__st.skipped,passed:__st.passed,failed:__st.failed,skipped:__st.skipped,checkpointsRestored:__st.rollbacks,results:__st.res.slice()};},reset:function(){__st.suites=[];__st.be=[[]],__st.ae=[[]];__st.res=[];__st.passed=0;__st.failed=0;__st.skipped=0;__st.rollbacks=0;}};m.it=m.test;m.default=m;m.__esModule=true;return __slice_builtins["slice:test"]=__slice_builtins["node:test"]=__slice_builtins["bun:test"]=__slice_builtins["test"]=m;})()"# + br#"(function(){var __st={suites:[],be:[[]],ae:[[]],res:[],passed:0,failed:0,skipped:0,rollbacks:0};function __eq(a,b){if(a===b)return true;if(a&&b&&typeof a==="object"&&typeof b==="object")return JSON.stringify(a)===JSON.stringify(b);return false;}function __vMatch(v,s){if(!s)return true;var q=String(s);if(v.indexOf(q)!==-1)return true;if(q==="FsReadDenied")return v.indexOf("filesystem read authority")!==-1;if(q==="FsWriteDenied")return v.indexOf("filesystem write authority")!==-1;if(q==="NetAccessDenied"||q==="NetConnectDenied")return v.indexOf("outbound network authority")!==-1;if(q==="EnvAccessDenied")return v.indexOf("environment variable authority")!==-1;if(q==="ExecDenied")return v.indexOf("Subprocess execution denied")!==-1;if(q==="CpuFuelExhausted")return v.indexOf("CPU instruction fuel limit")!==-1;if(q==="MemoryCeilingExceeded"||q==="MemoryLimitExceeded")return v.indexOf("memory ceiling")!==-1;if(q==="EgressSecretLeakBlocked")return v.indexOf("EGRESS_SECRET_LEAK_BLOCKED")!==-1;return false;}function __mkExp(act,neg){function chk(ok,msg){if(neg?ok:!ok)throw new Error(msg);}return{get not(){return __mkExp(act,!neg);},toBe:function(e){chk(act===e||(act&&act._isBuffer&&typeof e==="string"&&act.toString("utf8")===e),"Expected "+JSON.stringify(e)+" but got "+JSON.stringify(act));},toEqual:function(e){chk(__eq(act,e),"Expected deep equal "+JSON.stringify(e)+" but got "+JSON.stringify(act));},toContain:function(s){var ok=(typeof act==="string"||Array.isArray(act))&&act.indexOf(s)!==-1;chk(ok,"Expected "+JSON.stringify(act)+" to contain "+JSON.stringify(s));},toBeTruthy:function(){chk(Boolean(act),"Expected truthy but got "+JSON.stringify(act));},toBeFalsy:function(){chk(!act,"Expected falsy but got "+JSON.stringify(act));},toBeNull:function(){chk(act===null,"Expected null but got "+JSON.stringify(act));},toBeDefined:function(){chk(act!==undefined,"Expected defined value");},toBeUndefined:function(){chk(act===undefined,"Expected undefined but got "+JSON.stringify(act));},toBeGreaterThan:function(n){chk(Number(act)>Number(n),"Expected "+act+" > "+n);},toBeGreaterThanOrEqual:function(n){chk(Number(act)>=Number(n),"Expected "+act+" >= "+n);},toBeLessThan:function(n){chk(Number(act)0&&__vMatch(v,sub));chk(ok,"Expected sandbox violation "+(sub||"*")+" but got "+(v||"ok:true"));},toStayWithinFuel:function(maxF){var r=typeof act==="function"?act():act;var ok=Boolean(r&&r.ok===true&&typeof r.fuelUsed==="number"&&r.fuelUsed<=Number(maxF));chk(ok,"Expected fuelUsed <= "+maxF+" but got "+(r&&r.fuelUsed));},toStayWithinMemory:function(maxB){var r=typeof act==="function"?act():act;var ok=Boolean(r&&r.ok===true&&typeof r.memoryUsedBytes==="number"&&r.memoryUsedBytes<=Number(maxB));chk(ok,"Expected memoryUsedBytes <= "+maxB+" but got "+(r&&r.memoryUsedBytes));}};}var m={describe:function(n,fn){__st.suites.push(String(n));__st.be.push([]);__st.ae.push([]);try{fn();}finally{__st.suites.pop();__st.be.pop();__st.ae.pop();}},beforeEach:function(fn){__st.be[__st.be.length-1].push(fn);},afterEach:function(fn){__st.ae[__st.ae.length-1].push(fn);},test:function(n,fn,opts){var suite=__st.suites.join(" > "),full=suite?(suite+" > "+n):String(n),flt=globalThis.__slice_test_filter||"";if(flt&&full.indexOf(flt)===-1){__st.skipped++;return;}var iso=!(opts&&opts.isolateState===false),snap=iso?__slice_checkpoint():0,t0=performance.now(),err=null;try{for(var i=0;i<__st.be.length;i++)for(var j=0;j<__st.be[i].length;j++)__st.be[i][j]();var r=fn();if(r&&typeof r.then==="function"){r.then(function(){},function(e){err=String(e&&e.message||e);});}__slice_drain_event_loop();for(var k=__st.ae.length-1;k>=0;k--)for(var l=0;l<__st.ae[k].length;l++)__st.ae[k][l]();}catch(e){err=String(e&&e.message||e);}finally{__slice_clear_timers();if(snap>0){__slice_restore(snap);__slice_release_checkpoint(snap);__st.rollbacks++;}}var dur=Math.max(1,Math.round((performance.now()-t0)*1000));if(!err){__st.passed++;__st.res.push({suite:suite,name:String(n),fullName:full,passed:true,durationUs:dur,checkpointId:snap,restored:snap>0,error:null});}else{__st.failed++;__st.res.push({suite:suite,name:String(n),fullName:full,passed:false,durationUs:dur,checkpointId:snap,restored:snap>0,error:err});}},expect:function(v){return __mkExp(v,false);},summary:function(){return{total:__st.passed+__st.failed+__st.skipped,passed:__st.passed,failed:__st.failed,skipped:__st.skipped,checkpointsRestored:__st.rollbacks,results:__st.res.slice()};},reset:function(){__st.suites=[];__st.be=[[]],__st.ae=[[]];__st.res=[];__st.passed=0;__st.failed=0;__st.skipped=0;__st.rollbacks=0;}};m.it=m.test;m.default=m;m.__esModule=true;return __slice_builtins["slice:test"]=__slice_builtins["node:test"]=__slice_builtins["bun:test"]=__slice_builtins["test"]=m;})()"# } _ => return Ok(BoaVal::undefined()), }; diff --git a/crates/slice-engine/tests/async_webcrypto_and_node_tests.rs b/crates/slice-engine/tests/async_webcrypto_and_node_tests.rs index 037284a..d83e562 100644 --- a/crates/slice-engine/tests/async_webcrypto_and_node_tests.rs +++ b/crates/slice-engine/tests/async_webcrypto_and_node_tests.rs @@ -2547,3 +2547,460 @@ fn test_phase5_conformance_scorecard_ecmascript_wintertc_and_node() { assert_eq!(res["node_builtins_loaded"], 31); assert_eq!(res["node_builtins_total"], 31); } + +#[test] +fn test_wave2_node_fs_and_fs_promises_error_codes_descriptors_and_semantics() { + let script = r#" +import fs from "node:fs"; +import fsp from "node:fs/promises"; + +async function run() { + const out: Record = {}; + + // 1. ENOENT error codes across sync and promises APIs + const syncEnoentOps: Array<[string, () => any]> = [ + ["readFileSync", () => fs.readFileSync("/tmp/wave2-no-such-file.txt")], + ["statSync", () => fs.statSync("/tmp/wave2-no-such-file.txt")], + ["lstatSync", () => fs.lstatSync("/tmp/wave2-no-such-file.txt")], + ["unlinkSync", () => fs.unlinkSync("/tmp/wave2-no-such-file.txt")], + ["rmdirSync", () => fs.rmdirSync("/tmp/wave2-no-such-dir")], + ["readdirSync", () => fs.readdirSync("/tmp/wave2-no-such-dir")], + ["renameSync", () => fs.renameSync("/tmp/wave2-no-src", "/tmp/wave2-no-dst")], + ["copyFileSync", () => fs.copyFileSync("/tmp/wave2-no-src", "/tmp/wave2-no-dst")], + ["openSync", () => fs.openSync("/tmp/wave2-no-such-file.txt", "r")] + ]; + out.syncEnoentAllMatch = syncEnoentOps.every(([name, fn]) => { + try { + fn(); + return false; + } catch (e: any) { + return e && e.code === "ENOENT" && e.errno === -2 && typeof e.syscall === "string"; + } + }); + + try { + await fsp.readFile("/tmp/wave2-no-such-async.txt"); + out.asyncEnoent = false; + } catch (e: any) { + out.asyncEnoent = e && e.code === "ENOENT"; + } + + // 2. statSync / lstatSync with { throwIfNoEntry: false } + out.statNoThrow = fs.statSync("/tmp/wave2-no-such-file.txt", { throwIfNoEntry: false }) === undefined; + out.lstatNoThrow = fs.lstatSync("/tmp/wave2-no-such-file.txt", { throwIfNoEntry: false }) === undefined; + + // 3. EEXIST, EISDIR, ENOTDIR, ENOTEMPTY + fs.mkdirSync("/tmp/wave2-dir", { recursive: true }); + try { + fs.mkdirSync("/tmp/wave2-dir"); + out.mkdirEexist = false; + } catch (e: any) { + out.mkdirEexist = e && e.code === "EEXIST"; + } + out.mkdirRecursiveOk = fs.mkdirSync("/tmp/wave2-dir", { recursive: true }) === undefined || true; + + try { + fs.readFileSync("/tmp/wave2-dir"); + out.readDirEisdir = false; + } catch (e: any) { + out.readDirEisdir = e && e.code === "EISDIR"; + } + + fs.writeFileSync("/tmp/wave2-dir/child.txt", "hello"); + try { + fs.readdirSync("/tmp/wave2-dir/child.txt"); + out.readdirFileEnotdir = false; + } catch (e: any) { + out.readdirFileEnotdir = e && e.code === "ENOTDIR"; + } + + try { + fs.rmdirSync("/tmp/wave2-dir"); + out.rmdirNonEmpty = false; + } catch (e: any) { + out.rmdirNonEmpty = e && e.code === "ENOTEMPTY"; + } + + try { + fs.writeFileSync("/tmp/wave2-dir/child.txt", "dup", { flag: "wx" }); + out.wxEexist = false; + } catch (e: any) { + out.wxEexist = e && e.code === "EEXIST"; + } + + // 4. Default Buffer return vs string encoding on readFileSync / fsp.readFile + const rawBytes = new Uint8Array([0x00, 0xff, 0xfe, 0x41, 0x42, 0x80]); + fs.writeFileSync("/tmp/wave2-bin.dat", rawBytes); + const readBuf = fs.readFileSync("/tmp/wave2-bin.dat"); + const readAsyncBuf = await fsp.readFile("/tmp/wave2-bin.dat"); + out.readBufIsBuffer = Buffer.isBuffer(readBuf); + out.readAsyncBufIsBuffer = Buffer.isBuffer(readAsyncBuf); + out.readBufExact = readBuf.length === 6 && readBuf[0] === 0x00 && readBuf[1] === 0xff && readBuf[2] === 0xfe && readBuf[5] === 0x80; + + // 5. writeFileSync & fsp.writeFile with { flag: "a" } + fs.writeFileSync("/tmp/wave2-append.txt", "part1"); + fs.writeFileSync("/tmp/wave2-append.txt", "-part2", { flag: "a" }); + await fsp.writeFile("/tmp/wave2-append.txt", "-part3", { flag: "a" }); + out.appendResult = fs.readFileSync("/tmp/wave2-append.txt", "utf8"); + + // 6. utimesSync & mtime persistence + const targetMtimeSec = 1700000123; + fs.utimesSync("/tmp/wave2-append.txt", targetMtimeSec, targetMtimeSec); + const stAfterUtimes = fs.statSync("/tmp/wave2-append.txt"); + out.utimesMtimeMs = stAfterUtimes.mtimeMs; + out.utimesDateMatch = stAfterUtimes.mtime.getTime() === targetMtimeSec * 1000; + + // 7. readdirSync with { recursive: true } and { withFileTypes: true } + fs.mkdirSync("/tmp/wave2-tree/a/b", { recursive: true }); + fs.writeFileSync("/tmp/wave2-tree/root.txt", "r"); + fs.writeFileSync("/tmp/wave2-tree/a/mid.txt", "m"); + fs.writeFileSync("/tmp/wave2-tree/a/b/leaf.txt", "l"); + const recNames = fs.readdirSync("/tmp/wave2-tree", { recursive: true }).sort(); + const recDirents = fs.readdirSync("/tmp/wave2-tree", { recursive: true, withFileTypes: true }); + out.recNames = recNames; + out.recDirentsCount = recDirents.length; + out.recHasLeafFile = recDirents.some((d: any) => d.name === "leaf.txt" && d.parentPath === "/tmp/wave2-tree/a/b" && d.isFile() && !d.isDirectory()); + out.recHasSubDir = recDirents.some((d: any) => d.name === "b" && d.parentPath === "/tmp/wave2-tree/a" && d.isDirectory()); + + // 8. File descriptor table: openSync, writeSync, readSync, fstatSync, ftruncateSync, closeSync, fsp.open + const fd = fs.openSync("/tmp/wave2-fd.txt", "w+"); + const written1 = fs.writeSync(fd, Buffer.from("Hello FD World")); + const fst1 = fs.fstatSync(fd); + fs.ftruncateSync(fd, 8); + const fst2 = fs.fstatSync(fd); + const rbuf = Buffer.alloc(8); + const bytesRead = fs.readSync(fd, rbuf, 0, 8, 0); + fs.closeSync(fd); + let closedEbadf = false; + try { + fs.readSync(fd, rbuf, 0, 4, 0); + } catch (e: any) { + closedEbadf = e && e.code === "EBADF"; + } + + const fh = await fsp.open("/tmp/wave2-fd.txt", "r+"); + await fh.write("!", 8, "utf8"); + const fhBuf = Buffer.alloc(9); + const fhRead = await fh.read(fhBuf, 0, 9, 0); + await fh.close(); + + out.fdWritten1 = written1; + out.fdSizeBeforeTrunc = fst1.size; + out.fdSizeAfterTrunc = fst2.size; + out.fdReadStr = rbuf.toString("utf8", 0, bytesRead); + out.closedEbadf = closedEbadf; + out.fhReadStr = fhBuf.toString("utf8", 0, fhRead.bytesRead); + + console.log(JSON.stringify(out)); +} +run(); +"#; + + let bundled = slice_cas::strip_typescript_and_normalize(script, true); + let bc = compile_source_to_bytecode(&bundled); + let caps = CapabilityToken::pure_compute() + .with_read_prefix("/tmp") + .with_write_prefix("/tmp"); + let mut iso = SliceIsolate::spawn("wave2-fs-semantics", 1, caps, 10_000_000, 16 * 1024 * 1024); + let m = iso.execute_bytecode(&bc, None).unwrap(); + let out: serde_json::Value = serde_json::from_str(&m.stdout[0]).unwrap(); + + assert_eq!(out["syncEnoentAllMatch"], true); + assert_eq!(out["asyncEnoent"], true); + assert_eq!(out["statNoThrow"], true); + assert_eq!(out["lstatNoThrow"], true); + assert_eq!(out["mkdirEexist"], true); + assert_eq!(out["mkdirRecursiveOk"], true); + assert_eq!(out["readDirEisdir"], true); + assert_eq!(out["readdirFileEnotdir"], true); + assert_eq!(out["rmdirNonEmpty"], true); + assert_eq!(out["wxEexist"], true); + assert_eq!(out["readBufIsBuffer"], true); + assert_eq!(out["readAsyncBufIsBuffer"], true); + assert_eq!(out["readBufExact"], true); + assert_eq!(out["appendResult"], "part1-part2-part3"); + assert_eq!(out["utimesMtimeMs"], 1_700_000_123_000.0); + assert_eq!(out["utimesDateMatch"], true); + assert_eq!( + out["recNames"], + serde_json::json!(["a", "a/b", "a/b/leaf.txt", "a/mid.txt", "root.txt"]) + ); + assert_eq!(out["recDirentsCount"], 5); + assert_eq!(out["recHasLeafFile"], true); + assert_eq!(out["recHasSubDir"], true); + assert_eq!(out["fdWritten1"], 14); + assert_eq!(out["fdSizeBeforeTrunc"], 14); + assert_eq!(out["fdSizeAfterTrunc"], 8); + assert_eq!(out["fdReadStr"], "Hello FD"); + assert_eq!(out["closedEbadf"], true); + assert_eq!(out["fhReadStr"], "Hello FD!"); + + // Verify OCap FsReadDenied still traps cleanly even if guest code wraps readFileSync in try/catch + let ocap_bypass_attempt = r#" +import fs from "node:fs"; +try { + fs.readFileSync("/etc/passwd"); +} catch (_e) {} +"#; + let ocap_bc = compile_source_to_bytecode(&slice_cas::strip_typescript_and_normalize( + ocap_bypass_attempt, + true, + )); + let mut iso_no_fs = SliceIsolate::spawn( + "wave2-fs-ocap-guard", + 1, + CapabilityToken::pure_compute().with_read_prefix("/tmp"), + 5_000_000, + 8 * 1024 * 1024, + ); + let err = iso_no_fs.execute_bytecode(&ocap_bc, None).unwrap_err(); + assert!( + matches!(err, SandboxViolation::FsReadDenied { .. }), + "Expected FsReadDenied, got {:?}", + err + ); +} + +#[test] +fn test_wave2_streams_string_decoder_backpressure_and_web_async_iteration() { + let script = r#" +import { StringDecoder } from "node:string_decoder"; +import { Readable, Writable } from "node:stream"; + +async function run() { + const out: Record = {}; + + // 1. StringDecoder multi-byte UTF-8 (1-byte and 2-byte splits across 2/3/4-byte codepoints) + const fullUtf8Text = "Café €100 🎉 日本語"; + const utf8Bytes = Buffer.from(fullUtf8Text, "utf8"); + const sd1 = new StringDecoder("utf8"); + let decoded1By1 = ""; + for (let i = 0; i < utf8Bytes.length; i++) { + decoded1By1 += sd1.write(utf8Bytes.subarray(i, i + 1)); + } + decoded1By1 += sd1.end(); + out.utf8ByteByByteMatch = decoded1By1 === fullUtf8Text; + + // 2. StringDecoder UTF-16LE odd-byte and surrogate splits + const utf16Bytes = Buffer.from("Hi 🎉!", "utf16le"); + const sd16 = new StringDecoder("utf16le"); + let decoded16 = ""; + for (let i = 0; i < utf16Bytes.length; i++) { + decoded16 += sd16.write(utf16Bytes.subarray(i, i + 1)); + } + decoded16 += sd16.end(); + out.utf16ByteByByteMatch = decoded16 === "Hi 🎉!"; + + // 3. StringDecoder Base64 chunked streaming + const b64Input = Buffer.from("slice-stream-base64-payload"); + const sdB64 = new StringDecoder("base64"); + let b64Out = ""; + for (let i = 0; i < b64Input.length; i += 2) { + b64Out += sdB64.write(b64Input.subarray(i, Math.min(i + 2, b64Input.length))); + } + b64Out += sdB64.end(); + out.b64Match = b64Out === b64Input.toString("base64"); + + // 4. Readable with setEncoding("utf8") receiving split multi-byte buffers + const emojiBuf = Buffer.from("🎉🚀", "utf8"); // 8 bytes + const rEncoded = new Readable({ + read() { + this.push(emojiBuf.subarray(0, 2)); + this.push(emojiBuf.subarray(2, 5)); + this.push(emojiBuf.subarray(5, 8)); + this.push(null); + } + }); + rEncoded.setEncoding("utf8"); + let rEncodedStr = ""; + for await (const chunk of rEncoded) { + rEncodedStr += chunk; + } + out.readableSetEncodingMatch = rEncodedStr === "🎉🚀"; + + // 5. Writable highWaterMark backpressure and 'drain' event + const pendingCallbacks: Array<() => void> = []; + const wBackpressure = new Writable({ + highWaterMark: 4, + write(_chunk, _enc, cb) { + pendingCallbacks.push(() => cb(null)); + } + }); + const w1 = wBackpressure.write("abcd"); // 4 bytes >= hwm(4) -> false + let drained = false; + wBackpressure.on("drain", () => { + drained = true; + }); + while (pendingCallbacks.length > 0) { + const fn = pendingCallbacks.shift()!; + fn(); + } + out.backpressureReturnedFalse = w1 === false; + out.drainEventFired = drained === true; + + // 6. ReadableStream async iteration (`for await...of` and `.values()`) + const asyncRs = new ReadableStream({ + start(ctrl) { + setTimeout(() => { + ctrl.enqueue("chunk-1"); + ctrl.enqueue("chunk-2"); + ctrl.close(); + }, 1); + } + }); + const rsIterated: string[] = []; + for await (const item of asyncRs) { + rsIterated.push(String(item)); + } + out.rsAsyncIterator = rsIterated; + + // 7. Readable.toWeb(Readable.from(...)) -> new Response(webStream).text() + const nodeReadable = Readable.from([Buffer.from("hello "), Buffer.from("web "), Buffer.from("response")]); + const webConverted = Readable.toWeb(nodeReadable); + const respText = await new Response(webConverted).text(); + out.toWebResponseText = respText; + + console.log(JSON.stringify(out)); +} +run(); +"#; + + let bundled = slice_cas::strip_typescript_and_normalize(script, true); + let bc = compile_source_to_bytecode(&bundled); + let mut iso = SliceIsolate::spawn( + "wave2-streams-decoder", + 1, + CapabilityToken::pure_compute(), + 10_000_000, + 16 * 1024 * 1024, + ); + let m = iso.execute_bytecode(&bc, None).unwrap(); + let out: serde_json::Value = serde_json::from_str(&m.stdout[0]).unwrap(); + + assert_eq!(out["utf8ByteByByteMatch"], true); + assert_eq!(out["utf16ByteByByteMatch"], true); + assert_eq!(out["b64Match"], true); + assert_eq!(out["readableSetEncodingMatch"], true); + assert_eq!(out["backpressureReturnedFalse"], true); + assert_eq!(out["drainEventFired"], true); + assert_eq!( + out["rsAsyncIterator"], + serde_json::json!(["chunk-1", "chunk-2"]) + ); + assert_eq!(out["toWebResponseText"], "hello web response"); +} + +#[test] +fn test_wave2_child_process_shell_pipelines_stdin_and_enoent() { + let script = r#" +import cp from "node:child_process"; + +async function run() { + const out: Record = {}; + + // 1. execSync with shell operators (&&, ||, ;) and pipeline (|) + out.chainAnd = cp.execSync("echo alpha && echo beta").toString().trim().replace(/\r\n/g, "\n"); + out.chainOr = cp.execSync("false || echo fallback-ok").toString().trim(); + out.pipelineUpper = cp.execSync("echo hello world | tr a-z A-Z").toString().trim(); + + // 2. execSync non-zero exit code attaches err.status + try { + cp.execSync("exit 42"); + out.exit42Status = 0; + } catch (e: any) { + out.exit42Status = e.status; + } + + // 3. async exec with shell pipeline + out.asyncExecPipe = await new Promise((resolve, reject) => { + cp.exec("echo async-pipe | tr a-z A-Z", (err: any, stdout: any) => { + if (err) reject(err); + else resolve(String(stdout).trim()); + }); + }); + + // 4. spawn with stdin.write() + stdin.end() piped to child stdout + out.spawnStdinCat = await new Promise((resolve, reject) => { + const child = cp.spawn("cat", []); + let collected = ""; + child.stdout.on("data", (d: any) => { + collected += Buffer.isBuffer(d) ? d.toString("utf8") : String(d); + }); + child.on("error", reject); + child.on("close", () => resolve(collected)); + child.stdin.write("piped-line-1\n"); + child.stdin.write(Buffer.from("piped-line-2")); + child.stdin.end(); + }); + + // 5. spawnSync & spawn ENOENT handling for non-existent binary + const missingSync = cp.spawnSync("/nonexistent_slice_binary_xyz"); + out.spawnSyncEnoentCode = missingSync.error ? missingSync.error.code : null; + out.spawnSyncStatusNull = missingSync.status === null; + + out.spawnAsyncEnoentCode = await new Promise((resolve) => { + const badChild = cp.spawn("/nonexistent_slice_binary_xyz"); + badChild.on("error", (err: any) => { + resolve(String(err.code)); + }); + }); + + console.log(JSON.stringify(out)); +} +run(); +"#; + + let bundled = slice_cas::strip_typescript_and_normalize(script, true); + let bc = compile_source_to_bytecode(&bundled); + let caps = CapabilityToken::pure_compute() + .with_exec_binary("/bin/sh") + .with_exec_binary("sh") + .with_exec_binary("echo") + .with_exec_binary("tr") + .with_exec_binary("cat") + .with_exec_binary("false") + .with_exec_binary("/nonexistent_slice_binary_xyz"); + let mut iso = SliceIsolate::spawn( + "wave2-child-process", + 1, + caps, + 10_000_000, + 16 * 1024 * 1024, + ); + let m = iso.execute_bytecode(&bc, None).unwrap(); + let out: serde_json::Value = serde_json::from_str(&m.stdout[0]).unwrap(); + + assert_eq!(out["chainAnd"], "alpha\nbeta"); + assert_eq!(out["chainOr"], "fallback-ok"); + assert_eq!(out["pipelineUpper"], "HELLO WORLD"); + assert_eq!(out["exit42Status"], 42); + assert_eq!(out["asyncExecPipe"], "ASYNC-PIPE"); + assert_eq!(out["spawnStdinCat"], "piped-line-1\npiped-line-2"); + assert_eq!(out["spawnSyncEnoentCode"], "ENOENT"); + assert_eq!(out["spawnSyncStatusNull"], true); + assert_eq!(out["spawnAsyncEnoentCode"], "ENOENT"); + + // Verify OCap ExecDenied when shell/binary is not permitted + let unauthorized_exec = r#" +import cp from "node:child_process"; +cp.execSync("echo hi && echo bye"); +"#; + let unauth_bc = compile_source_to_bytecode(&slice_cas::strip_typescript_and_normalize( + unauthorized_exec, + true, + )); + let mut iso_no_exec = SliceIsolate::spawn( + "wave2-exec-ocap-guard", + 1, + CapabilityToken::pure_compute(), + 5_000_000, + 8 * 1024 * 1024, + ); + let err = iso_no_exec.execute_bytecode(&unauth_bc, None).unwrap_err(); + assert!( + matches!(err, SandboxViolation::ExecDenied { .. }), + "Expected ExecDenied, got {:?}", + err + ); +} + diff --git a/docs/general/00_index.md b/docs/general/00_index.md index afdf74c..6c48708 100644 --- a/docs/general/00_index.md +++ b/docs/general/00_index.md @@ -1,6 +1,6 @@ -# The Slice (Nexus-JS) Developer Handbook (`v0.10.9`) +# The Slice (Nexus-JS) Developer Handbook (`v0.10.10`) -Welcome to the complete developer handbook for **Slice (Nexus-JS)** (`v0.10.9`) — a microVM-grade JavaScript and TypeScript runtime, compiler, HTTP server, and AI sandbox engineered in Rust. +Welcome to the complete developer handbook for **Slice (Nexus-JS)** (`v0.10.10`) — a microVM-grade JavaScript and TypeScript runtime, compiler, HTTP server, and AI sandbox engineered in Rust. Whether you are building a high-throughput full-stack web service, packaging a CLI tool into a single zero-dependency executable, running 1,000 untrusted customer plugins on a single machine, or executing LLM-generated TypeScript inside an AI coding agent, this handbook walks you through every feature, CLI command, API, security capability, and migration pattern from the perspective of an application developer. diff --git a/docs/general/01_getting_started_and_cli.md b/docs/general/01_getting_started_and_cli.md index 2faa162..5507bd5 100644 --- a/docs/general/01_getting_started_and_cli.md +++ b/docs/general/01_getting_started_and_cli.md @@ -1,6 +1,6 @@ # Chapter 01: Installation, Upgrading, Quickstart, `slice.toml` & Complete CLI Reference -This chapter is your complete day-one guide to installing, upgrading, configuring, and operating **Slice (Nexus-JS)** (`v0.10.9`). By the end of this chapter, you will know how to install and update Slice on any operating system, scaffold a new TypeScript project, configure your `slice.toml` manifest and `.env` vault, run live development with `< 3 ms` `--watch` reloads, use the interactive `slice repl` shell, and master all 13 CLI commands. +This chapter is your complete day-one guide to installing, upgrading, configuring, and operating **Slice (Nexus-JS)** (`v0.10.10`). By the end of this chapter, you will know how to install and update Slice on any operating system, scaffold a new TypeScript project, configure your `slice.toml` manifest and `.env` vault, run live development with `< 3 ms` `--watch` reloads, use the interactive `slice repl` shell, and master all 13 CLI commands. --- @@ -545,7 +545,7 @@ Launches an interactive **SES-Locked TypeScript/JavaScript Compartment Shell** w **Example REPL Session:** ```text $ slice repl -Slice (Nexus-JS) v0.10.9 Interactive SES-Locked Compartment Shell +Slice (Nexus-JS) v0.10.10 Interactive SES-Locked Compartment Shell Commands: :help, :metrics, :caps, :vars, :reset, :quit slice(ses)> const price: number = 250 * 4; => 1000 diff --git a/docs/general/COMPATIBILITY.md b/docs/general/COMPATIBILITY.md index 61c835a..2f4840a 100644 --- a/docs/general/COMPATIBILITY.md +++ b/docs/general/COMPATIBILITY.md @@ -26,7 +26,7 @@ All WinterTC globals are available in every isolate out of the box. Under the ho | **Events & Signals** | `Event`, `CustomEvent`, `EventTarget`, `AbortController`, `AbortSignal` | **100% Supported** | Listener registration (`once`, `passive`, `signal`), `AbortSignal.abort()`, `AbortSignal.timeout(ms)`, `AbortSignal.any(signals)`, and `DOMException`. | | **Timers & Microtasks** | `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval`, `setImmediate`, `clearImmediate`, `queueMicrotask`, `process.nextTick` | **100% Supported** | $O(1)$ Slab-Allocated Hierarchical Timer Wheel with strict priority ordering (`sync -> process.nextTick -> Promise.then / queueMicrotask -> setImmediate -> setTimeout(0)`), deterministic virtual time-warp (`0 ns` wall-clock wait during cassette tests), and real non-blocking concurrency on live sockets. | | **Cloning & Diagnostics** | `structuredClone`, `performance.now()`, `console.*` (`log`, `info`, `warn`, `error`, `debug`, `table`, `time`, `timeLog`, `timeEnd`, `group`, `groupCollapsed`, `groupEnd`, `dir`, `dirxml`, `count`, `countReset`, `assert`, `trace`, `clear`) | **100% Supported** | Graph-preserving cyclic `structuredClone` (`Map`, `Set`, `Date`, `RegExp`, `ArrayBuffer`, `Uint8Array`, `Error`, `transfer` list) and full WHATWG `console.*` specification routed through the Outbound Egress Secret DLP Firewall (with deterministic elapsed timing under `--deterministic`). | -| **Internationalization & WinterTC Globals** | `Intl` (`DateTimeFormat`, `NumberFormat`, `Collator`, `PluralRules`, `Segmenter`, `getCanonicalLocales`, `supportedValuesOf`), `navigator`, `location` | **100% Supported** | Zero-ICU-bloat deterministic `Intl` fast-path shard (`18_intl.js`) supporting `Date.prototype.toLocale*`, `Number.prototype.toLocaleString` (`decimal`, `currency`, `percent`, `unit`, `formatToParts`), `String.prototype.localeCompare`, `PluralRules` (`cardinal`, `ordinal`), `Segmenter` (`grapheme`, `word`, `sentence`), plus WinterTC `navigator` (`userAgent: "Slice-NexusJS/0.10.9"`, `hardwareConcurrency`, `language`, `languages`) and `location`. | +| **Internationalization & WinterTC Globals** | `Intl` (`DateTimeFormat`, `NumberFormat`, `Collator`, `PluralRules`, `Segmenter`, `getCanonicalLocales`, `supportedValuesOf`), `navigator`, `location` | **100% Supported** | Zero-ICU-bloat deterministic `Intl` fast-path shard (`18_intl.js`) supporting `Date.prototype.toLocale*`, `Number.prototype.toLocaleString` (`decimal`, `currency`, `percent`, `unit`, `formatToParts`), `String.prototype.localeCompare`, `PluralRules` (`cardinal`, `ordinal`), `Segmenter` (`grapheme`, `word`, `sentence`), plus WinterTC `navigator` (`userAgent: "Slice-NexusJS/0.10.10"`, `hardwareConcurrency`, `language`, `languages`) and `location`. | | **JSX / TSX & Edge SSR** | Native `.tsx` / `.jsx` compilation + `slice:jsx` (`react/jsx-runtime`, `preact/jsx-runtime`, `hono/jsx`) | **100% Supported** | Native Rust Oxc JSX/TSX compiler (`runtime: automatic`) paired with a built-in zero-dependency SSR engine (`renderToString`, `jsx`, `jsxs`, `jsxDEV`, `Fragment`, `createElement`/`h`, `raw`) featuring automatic HTML & attribute XSS escaping, void tag handling, and camelCase `style` object serialization. | --- diff --git a/docs/guides/README.md b/docs/guides/README.md index 5596cab..7c63928 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -1,6 +1,6 @@ # Slice (Nexus-JS) — Developer How-To Guides (`docs/guides/`) -This directory contains practical step-by-step developer guides, production deployment how-tos, and ecosystem integration recipes for Slice (`v0.10.9`): +This directory contains practical step-by-step developer guides, production deployment how-tos, and ecosystem integration recipes for Slice (`v0.10.10`): ## Available Guides diff --git a/docs/system/00_index.md b/docs/system/00_index.md index 2468eff..5a7b304 100644 --- a/docs/system/00_index.md +++ b/docs/system/00_index.md @@ -1,4 +1,4 @@ -# Slice (Nexus-JS): System Architecture & Internal Specification Index (`v0.10.9`) +# Slice (Nexus-JS): System Architecture & Internal Specification Index (`v0.10.10`) Welcome to the **Slice (Nexus-JS)** System Architecture and Internal Specification (`docs/system/`). Engineered in pure Rust (`edition = 2021`, `opt-level = 3`, `lto = "fat"`, `codegen-units = 1`, `panic = "abort"`), Slice replaces the legacy POSIX + monolithic V8/JSC assumptions of Node.js, Deno, and Bun with four orthogonal, tightly integrated Rust crates: @@ -21,7 +21,7 @@ Welcome to the **Slice (Nexus-JS)** System Architecture and Internal Specificati | **[`05_wasm_workers_and_kernel_io.md`](./05_wasm_workers_and_kernel_io.md)** | Pure-Rust WebAssembly (`wasmi` `v2.0.0`, `GLOBAL_WASM_MODULE_CACHE`, 5-Ring WASM Cage), Capability-Attenuated MicroVM Web Workers & `node:worker_threads` (`IDLE_WORKER_POOL`), Direct Kernel Completion Rings (`io_uring` & `IOCP`), & OS-Native `notify` File Watcher | `crates/slice-engine/src/{wasm,workers}.rs`, `crates/slice-io/src/lib.rs`, `crates/slice-cli/src/config_and_watch.rs` | | **[`06_edge_kv_ai_sandbox_and_mcp.md`](./06_edge_kv_ai_sandbox_and_mcp.md)** | 16-Way Sharded `Slice.kv` (`EDGE_KV_SLAB`), Multi-Tenant `--tenant-dir` Atomic Hot-Swap, SplitMix64 `--deterministic` Replay, AI Agent "Code Mode" (`Slice.evalSandbox`, `< 5 us` `Slice.checkpoint`/`restore`), Time-Travel `slice test`, & Built-In MCP Server (`slice mcp`) | `crates/slice-engine/src/state_and_kv.rs`, `crates/slice-cli/src/{test_runner,mcp_and_repl}.rs` | | **[`07_production_tooling_guide.md`](./07_production_tooling_guide.md)** | Production CLI Reference, Unified 4-Layer Configuration System (`slice.toml`, Inline `// @slice-...`, `SLICE_*` Env Vars, CLI Flags), Docker & Kubernetes Deployment Patterns, and Multi-Tenant Operations | `crates/slice-cli/src/{main,config_and_watch}.rs`, `crates/slice-sandbox/src/lib.rs` | -| **[`08_benchmarks_and_comparisons.md`](./08_benchmarks_and_comparisons.md)** | Complete 4-Runtime Empirical Benchmark Suite (Slice `v0.10.9` vs Node.js `v25.8.1`, Deno `v2.7.5`, and Bun `v1.3.10`) Across All 31 Applications, Framework Suites & Case Studies | `benches/`, `tests/apps/`, `tests/frameworks/`, `tests/case_studies/` | +| **[`08_benchmarks_and_comparisons.md`](./08_benchmarks_and_comparisons.md)** | Complete 4-Runtime Empirical Benchmark Suite (Slice `v0.10.10` vs Node.js `v25.8.1`, Deno `v2.7.5`, and Bun `v1.3.10`) Across All 31 Applications, Framework Suites & Case Studies | `benches/`, `tests/apps/`, `tests/frameworks/`, `tests/case_studies/` | | **[`09_research_deep_dive.md`](./09_research_deep_dive.md)** | Foundational Systems Research Paper: Breaking the JS/TS Cold-Start, Memory Density, and Multi-Tenant Security Wall | Architectural Research Blueprint | | **[`vendor/boa_engine/SLICE_PATCH.md`](../../vendor/boa_engine/SLICE_PATCH.md)** | `SLICEBC1` Precompiled `CodeBlock` Binary Serializer/Deserializer & Deferred Function Span Architecture | `vendor/boa_engine/src/{slice_precompile.rs,lib.rs,vm/opcode/call/mod.rs}` | @@ -31,7 +31,7 @@ Welcome to the **Slice (Nexus-JS)** System Architecture and Internal Specificati ``` +---------------------------------------------------------------------------------------------------+ -| Slice (Nexus-JS) v0.10.9 Host | +| Slice (Nexus-JS) v0.10.10 Host | | | | +---------------------------------------------------------------------------------------------+ | | | slice-sandbox: Zero-Trust OCap, SES & Hardware Boundary | | diff --git a/docs/system/07_production_tooling_guide.md b/docs/system/07_production_tooling_guide.md index ae71604..bdc8e11 100644 --- a/docs/system/07_production_tooling_guide.md +++ b/docs/system/07_production_tooling_guide.md @@ -2,7 +2,7 @@ ## 1. Overview of the Production Toolchain -Slice `v0.10.9` provides a complete developer and production deployment workflow packaged inside a single self-contained native Rust executable (`slice`, embedding the **Oxc** TypeScript compiler, transitive `node_modules` bundler, **Boa** ES2024+ VM, and **Slice** Zero-Stat CAS + Tier-0/Tier-2 engine): +Slice `v0.10.10` provides a complete developer and production deployment workflow packaged inside a single self-contained native Rust executable (`slice`, embedding the **Oxc** TypeScript compiler, transitive `node_modules` bundler, **Boa** ES2024+ VM, and **Slice** Zero-Stat CAS + Tier-0/Tier-2 engine): 1. **Project Initialization & Policy Configuration (`slice init` & `slice.toml`)** 2. **Zero-Stat Content-Addressed Packaging (`slice pack` for single files or full `package.json` + `node_modules` folders)** diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 915e5c1..ba7a1d1 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -16,6 +16,6 @@ if (-not (Test-Path $ReleaseExe)) { $DestExe = Join-Path $InstallDir "slice.exe" Copy-Item -Force $ReleaseExe $DestExe -Write-Host "Installed Slice v0.10.9 to $DestExe" +Write-Host "Installed Slice v0.10.10 to $DestExe" & $DestExe info diff --git a/scripts/install.sh b/scripts/install.sh index 1c4d6a3..818aa72 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -9,13 +9,13 @@ INSTALL_DIR="${HOME}/.slice/bin" mkdir -p "$INSTALL_DIR" if [ ! -f "$ROOT_DIR/target/release/slice" ]; then - echo "Compiling Slice v0.10.9 release binary..." + echo "Compiling Slice v0.10.10 release binary..." cargo build --release fi cp -f "$ROOT_DIR/target/release/slice" "$INSTALL_DIR/slice" chmod +x "$INSTALL_DIR/slice" -echo "Installed Slice v0.10.9 to $INSTALL_DIR/slice" +echo "Installed Slice v0.10.10 to $INSTALL_DIR/slice" "$INSTALL_DIR/slice" info diff --git a/scripts/package_release.ps1 b/scripts/package_release.ps1 index 39b7221..2ad74f3 100644 --- a/scripts/package_release.ps1 +++ b/scripts/package_release.ps1 @@ -6,7 +6,7 @@ $ErrorActionPreference = "Stop" $RootDir = Split-Path -Parent $PSScriptRoot Set-Location $RootDir -Write-Host "[1/4] Building Slice v0.10.9 Release Binary (LTO=fat, opt-level=3)..." +Write-Host "[1/4] Building Slice v0.10.10 Release Binary (LTO=fat, opt-level=3)..." cargo build --release $DistDir = Join-Path $RootDir "dist" diff --git a/scripts/run_benchmarks.ps1 b/scripts/run_benchmarks.ps1 index 0b5e9f7..ead3140 100644 --- a/scripts/run_benchmarks.ps1 +++ b/scripts/run_benchmarks.ps1 @@ -15,7 +15,7 @@ $CargoToml = Get-Content (Join-Path $RootDir "Cargo.toml") -Raw if ($CargoToml -match '(?m)^\[workspace\.package\]\s*\r?\nversion\s*=\s*"([^"]+)"') { $Version = $Matches[1] } else { - $Version = "0.10.9" + $Version = "0.10.10" } try { diff --git a/tests/README.md b/tests/README.md index 0d0512b..933056d 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,7 +6,7 @@ This directory (`tests/`) contains a reproducible Linux `x86_64` Docker benchmar ## Latest Runtimes Installed in Docker ([`tests/Dockerfile`](./Dockerfile)) -- **Slice (`v0.10.9` — `SLICEBC\x01` Precompiled `CodeBlock` CAS Default):** Hybrid architecture combining **Oxc** (`v0.154.0` production Rust TypeScript compiler + AST ESM-to-CJS module bundler with deferred function module spans (`0x11` tag) + `.wasm` zero-stat module bundler + full `package.json` `"exports"` resolver + static barrel tree-shaker), **Boa (`boa_engine` v0.22 + [`vendor/boa_engine/SLICE_PATCH.md`](../vendor/boa_engine/SLICE_PATCH.md))** full ECMAScript VM with default `SLICEBC\x01` precompiled `Gc` + global `Scope` binary payloads (zero runtime `boa_parser` / `ByteCompiler` overhead) and pre-fused `node:*` built-in shards, thread-local pre-warmed context pool (`BOA_CONTEXT_POOL`), pure-Rust **WebAssembly (`wasmi` v2.0.0)** engine with `GLOBAL_WASM_MODULE_CACHE` and 5-Ring CPU fuel & linear memory cages, native Rust fast-path intrinsics (`SemVer`, `SHA-256`/`SHA-384`/`SHA-512`, `HMAC-SHA256`/`HMAC-SHA512`, `Base64URL`, in-memory `VFS` slab cache, WinterTC `URL`/`URLPattern`/`URLSearchParams`/`Headers`/`Request`/`Response`/`ReadableStream`/`TransformStream`/`CompressionStream`/`DecompressionStream`/`TextEncoder`/`TextDecoder`/`crypto.subtle`/`Blob`/`File`/`FormData`/`structuredClone`/`EventTarget`/`AbortSignal`/`WebAssembly`, real `Uint8Array`-backed `Buffer`, `node:*` Core Tier-1 modules including `node:async_hooks` and `node:zlib`, `Slice.streamSSE` / `Response.sse`, OCap-guarded outbound HTTP/1.1 & HTTPS TLS 1.3 `fetch()` with Keep-Alive pooling, hop-by-hop redirect guard, Cloud Metadata SSRF Shield, and Egress DLP, built-in Time-Travel `slice test` runner, OS-native `notify` (`v8.2`) `< 5 ms` `--watch`, and Auto-DLP `.env`), and **Slice Zero-Stat CAS + `--static` BLAKE3 `ETag` Static Server + Tier-0/Tier-2 fast paths**. +- **Slice (`v0.10.10` — `SLICEBC\x01` Precompiled `CodeBlock` CAS Default):** Hybrid architecture combining **Oxc** (`v0.154.0` production Rust TypeScript compiler + AST ESM-to-CJS module bundler with deferred function module spans (`0x11` tag) + `.wasm` zero-stat module bundler + full `package.json` `"exports"` resolver + static barrel tree-shaker), **Boa (`boa_engine` v0.22 + [`vendor/boa_engine/SLICE_PATCH.md`](../vendor/boa_engine/SLICE_PATCH.md))** full ECMAScript VM with default `SLICEBC\x01` precompiled `Gc` + global `Scope` binary payloads (zero runtime `boa_parser` / `ByteCompiler` overhead) and pre-fused `node:*` built-in shards, thread-local pre-warmed context pool (`BOA_CONTEXT_POOL`), pure-Rust **WebAssembly (`wasmi` v2.0.0)** engine with `GLOBAL_WASM_MODULE_CACHE` and 5-Ring CPU fuel & linear memory cages, native Rust fast-path intrinsics (`SemVer`, `SHA-256`/`SHA-384`/`SHA-512`, `HMAC-SHA256`/`HMAC-SHA512`, `Base64URL`, in-memory `VFS` slab cache, WinterTC `URL`/`URLPattern`/`URLSearchParams`/`Headers`/`Request`/`Response`/`ReadableStream`/`TransformStream`/`CompressionStream`/`DecompressionStream`/`TextEncoder`/`TextDecoder`/`crypto.subtle`/`Blob`/`File`/`FormData`/`structuredClone`/`EventTarget`/`AbortSignal`/`WebAssembly`, real `Uint8Array`-backed `Buffer`, `node:*` Core Tier-1 modules including `node:async_hooks` and `node:zlib`, `Slice.streamSSE` / `Response.sse`, OCap-guarded outbound HTTP/1.1 & HTTPS TLS 1.3 `fetch()` with Keep-Alive pooling, hop-by-hop redirect guard, Cloud Metadata SSRF Shield, and Egress DLP, built-in Time-Travel `slice test` runner, OS-native `notify` (`v8.2`) `< 5 ms` `--watch`, and Auto-DLP `.env`), and **Slice Zero-Stat CAS + `--static` BLAKE3 `ETag` Static Server + Tier-0/Tier-2 fast paths**. - **Node.js (`v27.0.0-alpha` — Absolute Latest Release):** Dynamically resolved at container build time from `https://nodejs.org/dist/index.json` (`.[0].version`). - **Bun (`v1.4.4` — Absolute Latest Release):** Installed via official `https://bun.sh/install`. - **Deno (`v2.9.8` — Absolute Latest Release):** Installed via official `https://deno.land/install.sh`. diff --git a/tests/run_real_stack_benchmarks.sh b/tests/run_real_stack_benchmarks.sh index be44b4d..2810e29 100644 --- a/tests/run_real_stack_benchmarks.sh +++ b/tests/run_real_stack_benchmarks.sh @@ -44,7 +44,7 @@ BENCH_TAGS="${1:-${SLICE_BENCH_TAGS:-all}}" METRICS_JSONL="${SLICE_BENCH_JSONL:-/tmp/slice_bench_metrics.jsonl}" rm -f "$METRICS_JSONL" -SLICE_VERSION="${SLICE_VERSION:-0.10.9}" +SLICE_VERSION="${SLICE_VERSION:-0.10.10}" SLICE_GIT_COMMIT="${SLICE_GIT_COMMIT:-$(git -C "$ROOT_DIR" rev-parse --short HEAD 2>/dev/null || echo "abdbf89")}" SLICE_BENCH_TS_UTC="${SLICE_BENCH_TS_UTC:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")}" CURRENT_APP_IDX="" diff --git a/tests/scripts/generate_bench_report.mjs b/tests/scripts/generate_bench_report.mjs index a74780a..f6ab75d 100644 --- a/tests/scripts/generate_bench_report.mjs +++ b/tests/scripts/generate_bench_report.mjs @@ -330,12 +330,12 @@ function parseJsonlMetrics(jsonlPath, previousReport) { return { metadata: { - version: metaRec.version || previousReport?.metadata?.version || "0.10.9", + version: metaRec.version || previousReport?.metadata?.version || "0.10.10", commit: metaRec.commit || previousReport?.metadata?.commit || "abdbf89", timestampUtc: metaRec.timestampUtc || new Date().toISOString(), environment: metaRec.environment || previousReport?.metadata?.environment || "Linux x86_64 Docker (io_uring SQPOLL + WRPKRU)", runtimes: { - slice: `v${metaRec.version || "0.10.9"}`, + slice: `v${metaRec.version || "0.10.10"}`, bun: metaRec.bunVersion || previousReport?.metadata?.runtimes?.bun || "v1.4.4", deno: metaRec.denoVersion || previousReport?.metadata?.runtimes?.deno || "v2.9.8", node: metaRec.nodeVersion || previousReport?.metadata?.runtimes?.node || "v27.0.0-alpha"