pub mod aot;
pub mod aot_native;
pub mod ast;
pub mod banner;
pub mod builtins;
pub mod cache;
pub mod capture;
pub mod cli;
pub mod compiler;
pub mod dap;
pub mod host;
pub mod lexer;
pub mod lsp;
pub mod module;
pub mod parser;
pub mod proxy;
pub mod regexp;
pub mod repl;
pub mod rust_ffi;
pub mod slots;
pub mod stdlib;
pub mod tiers;
pub mod utf16;
pub use fusevm::Value;
pub const JS_STACK_SIZE: usize = 256 * 1024 * 1024;
pub fn run_on_js_stack(f: fn() -> std::process::ExitCode) -> std::process::ExitCode {
match std::thread::Builder::new()
.name("node-js".into())
.stack_size(JS_STACK_SIZE)
.spawn(f)
{
Ok(h) => h.join().unwrap_or_else(|p| std::panic::resume_unwind(p)),
Err(_) => f(),
}
}
pub fn compile(src: &str) -> Result<compiler::Program, String> {
let stmts = parser::parse(src)?;
compiler::compile(&stmts, false)
}
pub fn compile_completion(src: &str) -> Result<compiler::Program, String> {
let stmts = parser::parse(src)?;
compiler::compile_completion(&stmts, false)
}
pub fn compile_debug(src: &str) -> Result<compiler::Program, String> {
let stmts = parser::parse(src)?;
compiler::compile(&stmts, true)
}
pub fn load_merged(mut prog: compiler::Program) -> fusevm::Chunk {
let (func_off, try_off) = host::with_host(|h| h.program_offsets());
compiler::rebase_program(&mut prog, func_off, try_off);
let compiler::Program {
main,
functions,
tries,
} = prog;
let funcs: Vec<host::FuncDef> = functions.into_iter().map(|(_, f)| f).collect();
host::with_host(|h| h.load_program(funcs, tries));
main
}
pub fn run_compiled(prog: compiler::Program) -> Result<Value, String> {
host::run_main(load_merged(prog))
}
pub fn exit_code() -> Option<i32> {
host::with_host(|h| h.exit_code)
}
pub fn exit_code_after_failure() -> i32 {
host::with_host(|h| h.exit_code = Some(1));
let _ = stdlib::process::emit_exit_event(1);
host::with_host(|h| h.exit_code).unwrap_or(1)
}
pub fn eval_in_global_scope(src: &str) -> Result<Value, String> {
let prog = compile_completion(src)?;
let chunk = load_merged(prog);
host::run_chunk_in_global_scope(chunk)
}
pub fn compile_or_load(src: &str) -> Result<compiler::Program, String> {
if let Some(prog) = cache::load(src) {
if std::env::var_os("NODE_JS_TRACE").is_some() {
eprintln!(
"node-js: cache HIT ({} ops, {} functions) — skipped lex/parse/lower",
prog.main.ops.len(),
prog.functions.len()
);
}
return Ok(prog);
}
let prog = compile(src)?;
let _ = cache::store(src, &prog);
if std::env::var_os("NODE_JS_TRACE").is_some() {
eprintln!(
"node-js: cache MISS — compiled + stored ({} ops, {} functions)",
prog.main.ops.len(),
prog.functions.len()
);
}
Ok(prog)
}
pub fn eval_str(src: &str) -> Result<Value, String> {
eval_str_from(src, "[eval]")
}
pub fn eval_str_from(src: &str, origin: &str) -> Result<Value, String> {
host::reset_host();
if let Ok(cwd) = std::env::current_dir() {
module::set_entry_dir(cwd);
}
module::install_entry_globals(origin);
run_compiled(compile_or_load(src)?)
}
pub fn eval_str_print(src: &str, origin: &str) -> Result<(), String> {
host::reset_host();
if let Ok(cwd) = std::env::current_dir() {
module::set_entry_dir(cwd);
}
module::install_entry_globals(origin);
let value = run_compiled(compile_completion(src)?)?;
let line = stdlib::util::format(std::slice::from_ref(&value));
host::with_host(|h| h.write_out(&format!("{line}\n"), false));
Ok(())
}
pub fn eval_str_captured(src: &str, globals: &[(&str, &str)]) -> (Result<Value, String>, String) {
host::reset_host();
if let Ok(cwd) = std::env::current_dir() {
module::set_entry_dir(cwd);
}
host::with_host(|h| {
for (name, text) in globals {
let value = h.new_str(*text);
h.set_global(name, value);
}
h.begin_capture();
});
let result = compile_or_load(src).and_then(run_compiled);
let output = host::with_host(|h| h.end_capture());
(result, output)
}
pub fn eval_file(path: &str) -> Result<Value, String> {
let src = std::fs::read_to_string(path).map_err(|e| format!("cannot read {path}: {e}"))?;
host::reset_host();
let dir = std::path::Path::new(path)
.parent()
.filter(|p| !p.as_os_str().is_empty())
.map(std::path::Path::to_path_buf)
.or_else(|| std::env::current_dir().ok())
.unwrap_or_default();
let dir = std::fs::canonicalize(&dir).unwrap_or(dir);
module::set_entry_dir(dir);
let entry = std::fs::canonicalize(path)
.map(|p| p.to_string_lossy().into_owned())
.unwrap_or_else(|_| stdlib::path::resolve_one(path));
module::install_entry_globals(&entry);
run_compiled(compile_or_load(&src)?)
}
pub fn eval_file_debug(path: &str) -> Result<Value, String> {
let src = std::fs::read_to_string(path).map_err(|e| format!("cannot read {path}: {e}"))?;
let prog = compile_debug(&src)?;
host::reset_host();
host::set_debug_mode(true);
let r = run_compiled(prog);
host::set_debug_mode(false);
r
}