1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! Plugin architecture and super-global scope.
//!
//! This module implements the **super-global scope** - a key architectural feature
//! that provides lazy, dynamic resolution of built-in and plugin-provided objects.
//!
//! ## Super-Global Scope Concept
//!
//! The super-global scope sits outside the normal lexical environment chain and
//! provides objects that are available globally but resolved on-demand:
//!
//! ```text
//! Variable Lookup Order:
//! 1. Local scope (function/block)
//! 2. Outer scopes (lexical chain)
//! 3. Global scope
//! 4. Super-global scope ← Built-ins and plugins live here
//! ```
//!
//! ### Key Components
//!
//! - **[`PluginResolver`]**: Trait for providing objects and methods dynamically
//! - **[`SuperGlobalEnvironment`]**: Container holding multiple resolvers with caching
//! - **[`CorePluginResolver`]**: Adapter wrapping [`BuiltInRegistry`] as a resolver
//! - **[`EvalContext`](types::EvalContext)**: Execution context with super-global integration
//!
//! ### Resolution Flow
//!
//! When JavaScript code references a name (e.g., `Math`):
//!
//! 1. **Check cache**: Has this name been resolved before?
//! 2. **Query resolvers**: Ask each resolver in registration order
//! 3. **Cache result**: Store the resolved value for future lookups
//! 4. **Return value**: Provide the object to JavaScript code
//!
//! ### Method Calls
//!
//! Method calls (e.g., `Math.abs(-5)`) are handled specially:
//!
//! 1. **Direct dispatch**: Resolvers can handle method calls directly without
//! materializing the object
//! 2. **Fallback**: If no resolver handles it, fall back to property lookup
//!
//! This allows efficient built-in method calls without creating intermediate objects.
//!
//! ## Example: Custom Plugin
//!
//! ```
//! use just::runner::plugin::resolver::PluginResolver;
//! use just::runner::plugin::types::EvalContext;
//! use just::runner::ds::value::{JsValue, JsNumberType};
//! use just::runner::ds::error::JErrorType;
//!
//! struct UtilsPlugin;
//!
//! impl PluginResolver for UtilsPlugin {
//! fn has_binding(&self, name: &str) -> bool {
//! name == "Utils"
//! }
//!
//! fn resolve(&self, _name: &str, _ctx: &mut EvalContext) -> Result<JsValue, JErrorType> {
//! Ok(JsValue::Undefined) // Sentinel
//! }
//!
//! fn call_method(&self, obj: &str, method: &str, _ctx: &mut EvalContext,
//! _this: JsValue, args: Vec<JsValue>) -> Option<Result<JsValue, JErrorType>> {
//! if obj == "Utils" && method == "double" {
//! let n = match args.first() {
//! Some(JsValue::Number(JsNumberType::Integer(n))) => *n,
//! _ => 0,
//! };
//! Some(Ok(JsValue::Number(JsNumberType::Integer(n * 2))))
//! } else {
//! None
//! }
//! }
//!
//! fn name(&self) -> &str { "utils_plugin" }
//! }
//!
//! // Register the plugin
//! let mut ctx = EvalContext::new();
//! ctx.add_resolver(Box::new(UtilsPlugin));
//! // Now Utils.double(21) returns 42
//! ```
//!
//! ## Design Rationale
//!
//! ### Why Not Preload Everything?
//!
//! Traditional approach:
//! - Load all built-ins at startup
//! - High memory usage
//! - Slow startup time
//! - Hard to extend
//!
//! Super-global approach:
//! - Load on first use (lazy)
//! - Lower memory footprint
//! - Fast startup
//! - Easy to add plugins
//!
//! ### Why Not Use Global Scope?
//!
//! Keeping built-ins in a separate super-global scope:
//! - Prevents accidental mutation from JavaScript
//! - Allows local variables to shadow built-ins
//! - Maintains clean separation of concerns
//! - Enables efficient caching and dispatch
pub use ;
pub use BuiltInRegistry;
pub use PluginConfig;
pub use PluginResolver;
pub use CorePluginResolver;
pub use SuperGlobalEnvironment;