nodejs/aot.rs
1//! Ahead-of-time compilation (`node --build`).
2//!
3//! Precompiles the script to fusevm bytecode, warms the on-disk cache
4//! (`cache.rs`) so subsequent runs skip lex/parse/lower, and — via fusevm's `aot`
5//! feature (a native-object emitter linked against the node-js `staticlib`) —
6//! emits a standalone native executable that carries the node-js builtin dispatch
7//! and the fusevm AOT runtime. The report below is explicit user-requested
8//! output.
9
10/// Precompile `file` to a standalone native executable next to the source, and
11/// warm the bytecode cache. Returns a one-line report of what was built.
12pub fn build(file: &str) -> Result<String, String> {
13 let src = std::fs::read_to_string(file).map_err(|e| format!("cannot read {file}: {e}"))?;
14 let prog = crate::compile(&src)?;
15 let (nfns, nops) = (prog.functions.len(), prog.main.ops.len());
16 crate::cache::store(&src, &prog)?;
17
18 // Emit the native object + link a standalone executable. The output path is
19 // the source stem (`foo.js` -> `foo`).
20 let stem = std::path::Path::new(file)
21 .file_stem()
22 .map(|s| s.to_string_lossy().into_owned())
23 .unwrap_or_else(|| "a.out".into());
24 let out = std::path::Path::new(file)
25 .parent()
26 .unwrap_or_else(|| std::path::Path::new("."))
27 .join(&stem);
28 crate::aot_native::emit_executable(&prog, &out)?;
29
30 Ok(format!(
31 "built {file}: {nops} top-level ops, {nfns} functions -> {} (+ ~/.node-js/scripts.rkyv)",
32 out.display()
33 ))
34}