Skip to main content

just_engine/
lib.rs

1//! # just-engine - JavaScript Engine in Rust
2//!
3//! A ground-up implementation of an ES6 JavaScript engine featuring:
4//! - PEG parser with ESTree-compliant AST
5//! - Tree-walking interpreter
6//! - Stack-based and register-based bytecode VMs
7//! - Cranelift-powered native JIT compiler
8//! - Plugin architecture with lazy super-global scope resolution
9//!
10//! ## Quick Start
11//!
12//! ### Parsing JavaScript
13//!
14//! ```
15//! use just::parser::JsParser;
16//!
17//! let code = "var x = 5 + 3;";
18//! let ast = JsParser::parse_to_ast_from_str(code).unwrap();
19//! println!("Parsed {} statements", ast.body.len());
20//! ```
21//!
22//! ### Running JavaScript with the Interpreter
23//!
24//! ```
25//! use just_engine::parser::JsParser;
26//! use just_engine::runner::plugin::types::EvalContext;
27//! use just_engine::runner::plugin::registry::BuiltInRegistry;
28//! use just_engine::runner::eval::statement::execute_statement;
29//!
30//! // Parse the code
31//! let code = "var x = Math.abs(-42);";
32//! let ast = JsParser::parse_to_ast_from_str(code).unwrap();
33//!
34//! // Create evaluation context with built-ins
35//! let mut ctx = EvalContext::new();
36//! ctx.install_core_builtins(BuiltInRegistry::with_core());
37//!
38//! // Execute statements
39//! for stmt in &ast.body {
40//!     execute_statement(stmt, &mut ctx).unwrap();
41//! }
42//!
43//! // Get the result
44//! let x = ctx.get_binding("x").unwrap();
45//! println!("x = {:?}", x);
46//! ```
47//!
48//! ### Using the JIT Compiler
49//!
50//! ```
51//! use just_engine::parser::JsParser;
52//! use just_engine::runner::plugin::types::EvalContext;
53//! use just_engine::runner::plugin::registry::BuiltInRegistry;
54//! use just_engine::runner::jit;
55//!
56//! let code = "var sum = 0; for (var i = 0; i < 100; i++) { sum = sum + i; } sum";
57//! let ast = JsParser::parse_to_ast_from_str(code).unwrap();
58//!
59//! let mut ctx = EvalContext::new();
60//! ctx.install_core_builtins(BuiltInRegistry::with_core());
61//!
62//! let result = jit::execute(&ast, &mut ctx).unwrap();
63//! println!("Result: {:?}", result);
64//! ```
65//!
66//! ## Super-Global Scope Architecture
67//!
68//! One of the key architectural features of this engine is the **super-global scope**,
69//! which provides lazy, dynamic resolution of built-in and plugin-provided objects.
70//!
71//! ### How It Works
72//!
73//! Traditional JavaScript engines preload all built-in objects (Math, console, Array, etc.)
74//! into the global scope at startup. This engine uses a different approach:
75//!
76//! 1. **Lazy Resolution**: Built-in objects are resolved only when JavaScript code
77//!    actually references them, reducing startup time and memory usage.
78//!
79//! 2. **Plugin Architecture**: Objects are provided by "plugin resolvers" that implement
80//!    the [`runner::plugin::resolver::PluginResolver`] trait. Multiple resolvers can be
81//!    registered, and they're queried in order.
82//!
83//! 3. **Caching**: Once resolved, objects are cached in the super-global environment
84//!    to avoid repeated lookups.
85//!
86//! 4. **Immutable from JS**: JavaScript code cannot mutate the super-global scope itself,
87//!    though it can shadow super-global names with local variables.
88//!
89//! ### Example: Custom Plugin
90//!
91//! ```
92//! use just_engine::parser::JsParser;
93//! use just_engine::runner::plugin::types::EvalContext;
94//! use just_engine::runner::plugin::resolver::PluginResolver;
95//! use just_engine::runner::plugin::registry::BuiltInRegistry;
96//! use just_engine::runner::ds::value::{JsValue, JsNumberType};
97//! use just_engine::runner::ds::error::JErrorType;
98//! use just_engine::runner::eval::statement::execute_statement;
99//!
100//! // Define a custom plugin that provides a "MyMath" object
101//! struct MyMathPlugin;
102//!
103//! impl PluginResolver for MyMathPlugin {
104//!     fn has_binding(&self, name: &str) -> bool {
105//!         name == "MyMath"
106//!     }
107//!     
108//!     fn resolve(&self, _name: &str, _ctx: &mut EvalContext) -> Result<JsValue, JErrorType> {
109//!         Ok(JsValue::Undefined) // Sentinel value
110//!     }
111//!     
112//!     fn call_method(&self, obj: &str, method: &str, _ctx: &mut EvalContext,
113//!                    _this: JsValue, args: Vec<JsValue>) -> Option<Result<JsValue, JErrorType>> {
114//!         if obj == "MyMath" && method == "triple" {
115//!             let n = match args.first() {
116//!                 Some(JsValue::Number(JsNumberType::Integer(n))) => *n,
117//!                 _ => 0,
118//!             };
119//!             Some(Ok(JsValue::Number(JsNumberType::Integer(n * 3))))
120//!         } else {
121//!             None
122//!         }
123//!     }
124//!     
125//!     fn name(&self) -> &str { "my_math_plugin" }
126//! }
127//!
128//! // Use the plugin
129//! let mut ctx = EvalContext::new();
130//! ctx.install_core_builtins(BuiltInRegistry::with_core()); // Core built-ins
131//! ctx.add_resolver(Box::new(MyMathPlugin)); // Custom plugin
132//!
133//! let code = "var result = MyMath.triple(7);";
134//! let ast = JsParser::parse_to_ast_from_str(code).unwrap();
135//! for stmt in &ast.body {
136//!     execute_statement(stmt, &mut ctx).unwrap();
137//! }
138//!
139//! let result = ctx.get_binding("result").unwrap();
140//! // result is 21
141//! ```
142//!
143//! ### Benefits
144//!
145//! - **Extensibility**: Easy to add custom objects without modifying the engine core
146//! - **Performance**: Only pay for what you use - unused built-ins are never materialized
147//! - **Modularity**: Built-ins and plugins are cleanly separated
148//! - **Testing**: Easy to mock or replace built-ins for testing
149//!
150//! ## Architecture
151//!
152//! - **[`parser`]** - PEG parser and AST types
153//! - **[`runner`]** - Execution engines (interpreter, VMs, JIT)
154//!   - **[`runner::plugin`]** - Plugin system and super-global scope
155//!   - **[`runner::ds`]** - Data structures (values, objects, environments)
156//!   - **[`runner::eval`]** - Tree-walking interpreter
157//!   - **[`runner::jit`]** - Bytecode VMs and JIT compiler
158
159#[macro_use]
160extern crate lazy_static;
161
162pub mod parser;
163pub mod runner;