we (web engine): Experimental web browser project to understand the limits of Claude
at js-closures 87 lines 3.0 kB view raw
1//! JavaScript engine — lexer, parser, bytecode, register VM, GC, JIT (AArch64). 2 3pub mod ast; 4pub mod bytecode; 5pub mod compiler; 6pub mod gc; 7pub mod lexer; 8pub mod parser; 9pub mod vm; 10 11use std::fmt; 12 13/// An error produced by the JavaScript engine. 14#[derive(Debug)] 15pub enum JsError { 16 /// The engine does not yet support this feature or syntax. 17 NotImplemented, 18 /// A parse/syntax error in the source. 19 SyntaxError(String), 20 /// A runtime error during execution. 21 RuntimeError(String), 22} 23 24impl fmt::Display for JsError { 25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 26 match self { 27 JsError::NotImplemented => write!(f, "not implemented"), 28 JsError::SyntaxError(msg) => write!(f, "SyntaxError: {}", msg), 29 JsError::RuntimeError(msg) => write!(f, "RuntimeError: {}", msg), 30 } 31 } 32} 33 34/// Evaluate a JavaScript source string and return the completion value as a string. 35/// 36/// Parses the source, compiles to bytecode, and executes in the VM. 37pub fn evaluate(source: &str) -> Result<String, JsError> { 38 let program = parser::Parser::parse(source).map_err(|e| JsError::SyntaxError(e.to_string()))?; 39 let func = compiler::compile(&program)?; 40 let mut engine = vm::Vm::new(); 41 let result = engine 42 .execute(&func) 43 .map_err(|e| JsError::RuntimeError(e.to_string()))?; 44 Ok(result.to_js_string(&engine.gc)) 45} 46 47/// Evaluate a JavaScript source string with a preamble executed first in the 48/// same VM instance. Used by the Test262 harness to inject helpers like 49/// `assert`, `assert.sameValue`, and `Test262Error` before running tests. 50/// 51/// Returns `Ok(())` on success, or a `JsError` on parse/runtime failure. 52pub fn evaluate_with_preamble(preamble: &str, source: &str) -> Result<(), JsError> { 53 evaluate_with_preamble_limited(preamble, source, None) 54} 55 56/// Like [`evaluate_with_preamble`] but with an optional instruction limit to 57/// prevent infinite loops. Used by the Test262 harness. 58pub fn evaluate_with_preamble_limited( 59 preamble: &str, 60 source: &str, 61 instruction_limit: Option<u64>, 62) -> Result<(), JsError> { 63 let mut engine = vm::Vm::new(); 64 65 // Execute preamble to define harness functions. 66 let preamble_ast = 67 parser::Parser::parse(preamble).map_err(|e| JsError::SyntaxError(e.to_string()))?; 68 let preamble_func = compiler::compile(&preamble_ast)?; 69 engine 70 .execute(&preamble_func) 71 .map_err(|e| JsError::RuntimeError(e.to_string()))?; 72 73 // Set instruction limit for the test source (not the preamble). 74 if let Some(limit) = instruction_limit { 75 engine.set_instruction_limit(limit); 76 } 77 78 // Execute the test source. 79 let test_ast = 80 parser::Parser::parse(source).map_err(|e| JsError::SyntaxError(e.to_string()))?; 81 let test_func = compiler::compile(&test_ast)?; 82 engine 83 .execute(&test_func) 84 .map_err(|e| JsError::RuntimeError(e.to_string()))?; 85 86 Ok(()) 87}