Skip to main content

just_engine/runner/plugin/
resolver.rs

1//! Plugin resolver trait for lazy, dynamic resolution of super-global objects.
2//!
3//! Plugins implement `PluginResolver` to provide objects (like `Math`, `console`)
4//! that are available in the super-global scope. Objects are resolved lazily —
5//! only when JS code actually references them.
6
7use crate::runner::ds::error::JErrorType;
8use crate::runner::ds::value::JsValue;
9use crate::runner::plugin::types::EvalContext;
10
11/// A plugin resolver that can dynamically provide named objects and their methods.
12///
13/// Resolvers are queried in registration order when a name lookup reaches the
14/// super-global scope. The first resolver that claims a name wins.
15pub trait PluginResolver {
16    /// Does this resolver provide a binding with the given name?
17    ///
18    /// This should be a cheap check (e.g. a `HashSet::contains`).
19    /// It must NOT allocate or materialize the object.
20    fn has_binding(&self, name: &str) -> bool;
21
22    /// Materialize the object for the given name.
23    ///
24    /// Called only after `has_binding` returns `true`.
25    /// The returned `JsValue` is cached in the super-global environment
26    /// so this is called at most once per name per execution.
27    fn resolve(&self, name: &str, ctx: &mut EvalContext) -> Result<JsValue, JErrorType>;
28
29    /// Resolve a method on an object this resolver provides.
30    ///
31    /// For example, if this resolver provides `"Math"`, then
32    /// `resolve_method("Math", "abs", ctx, this, args)` should execute `Math.abs`.
33    ///
34    /// Returns `None` if the method is not found, allowing fallback to
35    /// property lookup on the materialized object.
36    fn call_method(
37        &self,
38        object_name: &str,
39        method_name: &str,
40        ctx: &mut EvalContext,
41        this: JsValue,
42        args: Vec<JsValue>,
43    ) -> Option<Result<JsValue, JErrorType>>;
44
45    /// Get a constructor for the given object name, if available.
46    ///
47    /// Returns `None` if this resolver doesn't provide a constructor for the name.
48    fn call_constructor(
49        &self,
50        _object_name: &str,
51        _ctx: &mut EvalContext,
52        _args: Vec<JsValue>,
53    ) -> Option<Result<JsValue, JErrorType>> {
54        None
55    }
56
57    /// Human-readable name for this resolver (for debugging/logging).
58    fn name(&self) -> &str;
59}