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