Add test to recreate NativeCallContext.
This commit is contained in:
parent
296d5c054c
commit
204284f4f7
@ -227,7 +227,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline]
|
||||
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||
self.global.iter().flat_map(|&m| m.iter_imports())
|
||||
self.global.iter().flat_map(|&g| g.iter_imports())
|
||||
}
|
||||
/// Get an iterator over the current set of modules imported via `import` statements in reverse order.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
@ -236,7 +236,7 @@ impl<'a> NativeCallContext<'a> {
|
||||
pub(crate) fn iter_imports_raw(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&crate::ImmutableString, &Shared<Module>)> {
|
||||
self.global.iter().flat_map(|&m| m.iter_imports_raw())
|
||||
self.global.iter().flat_map(|&g| g.iter_imports_raw())
|
||||
}
|
||||
/// _(internals)_ The current [`GlobalRuntimeState`], if any.
|
||||
/// Exported under the `internals` feature only.
|
||||
@ -249,12 +249,12 @@ impl<'a> NativeCallContext<'a> {
|
||||
self.global
|
||||
}
|
||||
/// Get an iterator over the namespaces containing definitions of all script-defined functions
|
||||
/// in reverse order.
|
||||
/// in reverse order (i.e. parent namespaces are iterated after child namespaces).
|
||||
#[inline]
|
||||
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
|
||||
self.lib.iter().rev().copied()
|
||||
self.lib.iter().copied()
|
||||
}
|
||||
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
|
||||
/// _(internals)_ The current stack of namespaces containing definitions of all script-defined functions.
|
||||
/// Exported under the `internals` feature only.
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
|
@ -1960,9 +1960,6 @@ impl Module {
|
||||
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions to
|
||||
/// cross-call each other.
|
||||
///
|
||||
/// Functions in the global namespace, plus all functions defined in the [`Module`], are
|
||||
/// _merged_ into a _unified_ namespace. Therefore, all functions will be found.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
@ -1993,9 +1990,6 @@ impl Module {
|
||||
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions to
|
||||
/// cross-call each other.
|
||||
///
|
||||
/// Functions in the global namespace, plus all functions defined in the [`Module`], are
|
||||
/// _merged_ into a _unified_ namespace. Therefore, all functions will be found.
|
||||
///
|
||||
/// # WARNING - Low Level API
|
||||
///
|
||||
/// This function is very low level.
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![cfg(not(feature = "no_module"))]
|
||||
use rhai::{
|
||||
module_resolvers::{DummyModuleResolver, StaticModuleResolver},
|
||||
Dynamic, Engine, EvalAltResult, FnNamespace, ImmutableString, Module, ParseError,
|
||||
ParseErrorType, Scope, INT,
|
||||
Dynamic, Engine, EvalAltResult, FnNamespace, FnPtr, ImmutableString, Module, NativeCallContext,
|
||||
ParseError, ParseErrorType, Scope, Shared, INT,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@ -459,10 +459,10 @@ fn test_module_str() -> Result<(), Box<EvalAltResult>> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[test]
|
||||
fn test_module_ast_namespace() -> Result<(), Box<EvalAltResult>> {
|
||||
let script = r#"
|
||||
let script = "
|
||||
fn foo(x) { x + 1 }
|
||||
fn bar(x) { foo(x) }
|
||||
"#;
|
||||
";
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
@ -499,11 +499,11 @@ fn test_module_ast_namespace() -> Result<(), Box<EvalAltResult>> {
|
||||
fn test_module_ast_namespace2() -> Result<(), Box<EvalAltResult>> {
|
||||
use rhai::{Engine, Module, Scope};
|
||||
|
||||
const MODULE_TEXT: &str = r#"
|
||||
const MODULE_TEXT: &str = "
|
||||
fn run_function(function) {
|
||||
call(function)
|
||||
}
|
||||
"#;
|
||||
";
|
||||
|
||||
const SCRIPT: &str = r#"
|
||||
import "test_module" as test;
|
||||
@ -527,6 +527,76 @@ fn test_module_ast_namespace2() -> Result<(), Box<EvalAltResult>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(feature = "internals")]
|
||||
#[test]
|
||||
fn test_module_context() -> Result<(), Box<EvalAltResult>> {
|
||||
let script = "fn bar() { calc(|x| x + 1) }";
|
||||
|
||||
let mut engine = Engine::new();
|
||||
|
||||
let ast = engine.compile(script)?;
|
||||
|
||||
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
||||
|
||||
let mut resolver = StaticModuleResolver::new();
|
||||
resolver.insert("testing", module);
|
||||
engine.set_module_resolver(resolver);
|
||||
|
||||
engine.register_fn(
|
||||
"calc",
|
||||
|context: NativeCallContext, fp: FnPtr| -> Result<INT, Box<EvalAltResult>> {
|
||||
// Store fields for later use
|
||||
let engine = context.engine();
|
||||
let fn_name = context.fn_name().to_string();
|
||||
let source = context.source().map(|s| s.to_string());
|
||||
let global = context.global_runtime_state().unwrap().clone();
|
||||
let pos = context.position();
|
||||
let call_level = context.call_level();
|
||||
|
||||
// Store the paths of the stack of call modules up to this point
|
||||
let modules_list: Vec<String> = context
|
||||
.iter_namespaces()
|
||||
.map(|m| m.id().unwrap_or("testing"))
|
||||
.filter(|id| !id.is_empty())
|
||||
.map(|id| id.to_string())
|
||||
.collect();
|
||||
|
||||
// Recreate the 'NativeCallContext' - requires the 'internals' feature
|
||||
let mut libraries = Vec::<Shared<Module>>::new();
|
||||
|
||||
for path in modules_list {
|
||||
// Recreate the stack of call modules by resolving each path with
|
||||
// the module resolver.
|
||||
let module = engine.module_resolver().resolve(engine, None, &path, pos)?;
|
||||
|
||||
libraries.push(module);
|
||||
}
|
||||
|
||||
let lib: Vec<&Module> = libraries.iter().map(|m| m.as_ref()).collect();
|
||||
|
||||
let new_context = NativeCallContext::new_with_all_fields(
|
||||
engine,
|
||||
&fn_name,
|
||||
source.as_ref().map(|s| s.as_str()),
|
||||
&global,
|
||||
&lib,
|
||||
pos,
|
||||
call_level,
|
||||
);
|
||||
|
||||
fp.call_within_context(&new_context, (41 as INT,))
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
engine.eval::<INT>(r#"import "testing" as t; t::bar()"#)?,
|
||||
42
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_module_file() -> Result<(), Box<EvalAltResult>> {
|
||||
let engine = Engine::new();
|
||||
|
Loading…
Reference in New Issue
Block a user