Add DebuggingPackage.
This commit is contained in:
parent
0e5f62574d
commit
aee35e5f20
@ -9,6 +9,7 @@ New features
|
||||
|
||||
* A debugging interface is added.
|
||||
* A new bin tool, `rhai-dbg` (aka _The Rhai Debugger_), is added to showcase the debugging interface.
|
||||
* A new package, `DebuggingPackage`, is added which contains the `stack_trace` function to get the current call stack anywhere in a script.
|
||||
|
||||
|
||||
Version 1.4.2
|
||||
|
80
src/packages/debugging.rs
Normal file
80
src/packages/debugging.rs
Normal file
@ -0,0 +1,80 @@
|
||||
#![cfg(feature = "debugging")]
|
||||
|
||||
use crate::def_package;
|
||||
use crate::plugin::*;
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
use crate::{Dynamic, NativeCallContext, INT};
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::Array;
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
use crate::Map;
|
||||
|
||||
def_package! {
|
||||
/// Package of basic debugging utilities.
|
||||
crate::DebuggingPackage => |lib| {
|
||||
lib.standard = true;
|
||||
|
||||
combine_with_exported_module!(lib, "debugging", debugging_functions);
|
||||
}
|
||||
}
|
||||
|
||||
#[export_module]
|
||||
mod debugging_functions {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub fn stack_trace(ctx: NativeCallContext) -> Array {
|
||||
if let Some(global) = ctx.global_runtime_state() {
|
||||
global
|
||||
.debugger
|
||||
.call_stack()
|
||||
.iter()
|
||||
.rev()
|
||||
.map(
|
||||
|frame @ crate::debugger::CallStackFrame {
|
||||
fn_name,
|
||||
args,
|
||||
source,
|
||||
pos,
|
||||
}| {
|
||||
let call = frame.to_string();
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
{
|
||||
let mut map = Map::new();
|
||||
map.insert("call".into(), call.into());
|
||||
map.insert("fn_name".into(), fn_name.into());
|
||||
if !args.is_empty() {
|
||||
map.insert(
|
||||
"args".into(),
|
||||
Dynamic::from_array(args.clone().to_vec()),
|
||||
);
|
||||
}
|
||||
if !source.is_empty() {
|
||||
map.insert("source".into(), source.into());
|
||||
}
|
||||
if !pos.is_none() {
|
||||
map.insert("line".into(), (pos.line().unwrap() as INT).into());
|
||||
map.insert(
|
||||
"pos".into(),
|
||||
(pos.position().unwrap_or(0) as INT).into(),
|
||||
);
|
||||
}
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
#[cfg(feature = "no_object")]
|
||||
call.into()
|
||||
},
|
||||
)
|
||||
.collect()
|
||||
} else {
|
||||
Array::new()
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ pub(crate) mod arithmetic;
|
||||
pub(crate) mod array_basic;
|
||||
mod bit_field;
|
||||
pub(crate) mod blob_basic;
|
||||
mod debugging;
|
||||
mod fn_basic;
|
||||
mod iter_basic;
|
||||
mod lang_core;
|
||||
@ -24,6 +25,8 @@ pub use array_basic::BasicArrayPackage;
|
||||
pub use bit_field::BitFieldPackage;
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub use blob_basic::BasicBlobPackage;
|
||||
#[cfg(feature = "debugging")]
|
||||
pub use debugging::DebuggingPackage;
|
||||
pub use fn_basic::BasicFnPackage;
|
||||
pub use iter_basic::BasicIteratorPackage;
|
||||
pub use lang_core::LanguageCorePackage;
|
||||
|
@ -13,6 +13,7 @@ def_package! {
|
||||
/// * [`BasicStringPackage`][super::BasicStringPackage]
|
||||
/// * [`BasicIteratorPackage`][super::BasicIteratorPackage]
|
||||
/// * [`BasicFnPackage`][super::BasicFnPackage]
|
||||
/// * [`DebuggingPackage`][super::DebuggingPackage]
|
||||
crate::CorePackage => |lib| {
|
||||
lib.standard = true;
|
||||
|
||||
@ -21,5 +22,7 @@ def_package! {
|
||||
super::BasicStringPackage::init(lib);
|
||||
super::BasicIteratorPackage::init(lib);
|
||||
super::BasicFnPackage::init(lib);
|
||||
#[cfg(feature = "debugging")]
|
||||
super::DebuggingPackage::init(lib);
|
||||
}
|
||||
}
|
||||
|
34
tests/debugging.rs
Normal file
34
tests/debugging.rs
Normal file
@ -0,0 +1,34 @@
|
||||
#![cfg(feature = "debugging")]
|
||||
use rhai::{Engine, EvalAltResult, INT};
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use rhai::Array;
|
||||
|
||||
#[test]
|
||||
fn test_debugging() -> Result<(), Box<EvalAltResult>> {
|
||||
let engine = Engine::new();
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
{
|
||||
let r = engine.eval::<Array>(
|
||||
"
|
||||
fn foo(x) {
|
||||
if x >= 5 {
|
||||
stack_trace()
|
||||
} else {
|
||||
foo(x+1)
|
||||
}
|
||||
}
|
||||
|
||||
foo(0)
|
||||
",
|
||||
)?;
|
||||
|
||||
assert_eq!(r.len(), 6);
|
||||
|
||||
assert_eq!(engine.eval::<INT>("len(stack_trace())")?, 0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user