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