//! JavaScript engine — lexer, parser, bytecode, register VM, GC, JIT (AArch64). pub mod ast; pub mod builtins; pub mod bytecode; pub mod compiler; pub mod gc; pub mod lexer; pub mod parser; pub mod regex; pub mod vm; use std::fmt; /// An error produced by the JavaScript engine. #[derive(Debug)] pub enum JsError { /// The engine does not yet support this feature or syntax. NotImplemented, /// A parse/syntax error in the source. SyntaxError(String), /// A runtime error during execution. RuntimeError(String), } impl fmt::Display for JsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { JsError::NotImplemented => write!(f, "not implemented"), JsError::SyntaxError(msg) => write!(f, "SyntaxError: {}", msg), JsError::RuntimeError(msg) => write!(f, "RuntimeError: {}", msg), } } } /// Evaluate a JavaScript source string and return the completion value as a string. /// /// Parses the source, compiles to bytecode, and executes in the VM. pub fn evaluate(source: &str) -> Result { let program = parser::Parser::parse(source).map_err(|e| JsError::SyntaxError(e.to_string()))?; let func = compiler::compile(&program)?; let mut engine = vm::Vm::new(); let result = engine .execute(&func) .map_err(|e| JsError::RuntimeError(e.to_string()))?; Ok(result.to_js_string(&engine.gc)) } /// Evaluate a JavaScript source string with a preamble executed first in the /// same VM instance. Used by the Test262 harness to inject helpers like /// `assert`, `assert.sameValue`, and `Test262Error` before running tests. /// /// Returns `Ok(())` on success, or a `JsError` on parse/runtime failure. pub fn evaluate_with_preamble(preamble: &str, source: &str) -> Result<(), JsError> { evaluate_with_preamble_limited(preamble, source, None) } /// Like [`evaluate_with_preamble`] but with an optional instruction limit to /// prevent infinite loops. Used by the Test262 harness. pub fn evaluate_with_preamble_limited( preamble: &str, source: &str, instruction_limit: Option, ) -> Result<(), JsError> { let mut engine = vm::Vm::new(); // Execute preamble to define harness functions. let preamble_ast = parser::Parser::parse(preamble).map_err(|e| JsError::SyntaxError(e.to_string()))?; let preamble_func = compiler::compile(&preamble_ast)?; engine .execute(&preamble_func) .map_err(|e| JsError::RuntimeError(e.to_string()))?; // Set instruction limit for the test source (not the preamble). if let Some(limit) = instruction_limit { engine.set_instruction_limit(limit); } // Execute the test source. let test_ast = parser::Parser::parse(source).map_err(|e| JsError::SyntaxError(e.to_string()))?; let test_func = compiler::compile(&test_ast)?; engine .execute(&test_func) .map_err(|e| JsError::RuntimeError(e.to_string()))?; Ok(()) }