we (web engine): Experimental web browser project to understand the limits of Claude
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}