Skip to content

Commit a3697ab

Browse files
committed
Add Debug::function method to get function running at a given level.
Close #607
1 parent 052740d commit a3697ab

File tree

2 files changed

+58
-17
lines changed

2 files changed

+58
-17
lines changed

src/debug.rs

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,32 @@ use std::os::raw::c_int;
33

44
use ffi::{lua_Debug, lua_State};
55

6+
use crate::function::Function;
67
use crate::state::RawLua;
7-
use crate::util::{linenumber_to_usize, ptr_to_lossy_str, ptr_to_str};
8+
use crate::util::{assert_stack, linenumber_to_usize, ptr_to_lossy_str, ptr_to_str, StackGuard};
89

910
/// Contains information about currently executing Lua code.
1011
///
11-
/// The `Debug` structure is provided as a parameter to the hook function set with
12-
/// [`Lua::set_hook`]. You may call the methods on this structure to retrieve information about the
13-
/// Lua code executing at the time that the hook function was called. Further information can be
14-
/// found in the Lua [documentation].
12+
/// You may call the methods on this structure to retrieve information about the Lua code executing
13+
/// at the specific level. Further information can be found in the Lua [documentation].
1514
///
1615
/// [documentation]: https://www.lua.org/manual/5.4/manual.html#lua_Debug
17-
/// [`Lua::set_hook`]: crate::Lua::set_hook
18-
pub struct Debug {
16+
pub struct Debug<'a> {
1917
state: *mut lua_State,
18+
lua: &'a RawLua,
2019
#[cfg_attr(not(feature = "luau"), allow(unused))]
2120
level: c_int,
2221
ar: *mut lua_Debug,
2322
}
2423

25-
impl Debug {
26-
pub(crate) fn new(lua: &RawLua, level: c_int, ar: *mut lua_Debug) -> Self {
27-
let state = lua.state();
28-
Debug { state, ar, level }
24+
impl<'a> Debug<'a> {
25+
pub(crate) fn new(lua: &'a RawLua, level: c_int, ar: *mut lua_Debug) -> Self {
26+
Debug {
27+
state: lua.state(),
28+
lua,
29+
ar,
30+
level,
31+
}
2932
}
3033

3134
/// Returns the specific event that triggered the hook.
@@ -49,7 +52,31 @@ impl Debug {
4952
}
5053
}
5154

52-
/// Corresponds to the `n` what mask.
55+
/// Returns the function that is running at the given level.
56+
///
57+
/// Corresponds to the `f` "what" mask.
58+
pub fn function(&self) -> Function {
59+
unsafe {
60+
let _sg = StackGuard::new(self.state);
61+
assert_stack(self.state, 1);
62+
63+
#[cfg(not(feature = "luau"))]
64+
mlua_assert!(
65+
ffi::lua_getinfo(self.state, cstr!("f"), self.ar) != 0,
66+
"lua_getinfo failed with `f`"
67+
);
68+
#[cfg(feature = "luau")]
69+
mlua_assert!(
70+
ffi::lua_getinfo(self.state, self.level, cstr!("f"), self.ar) != 0,
71+
"lua_getinfo failed with `f`"
72+
);
73+
74+
ffi::lua_xmove(self.state, self.lua.ref_thread(), 1);
75+
Function(self.lua.pop_ref_thread())
76+
}
77+
}
78+
79+
/// Corresponds to the `n` "what" mask.
5380
pub fn names(&self) -> DebugNames<'_> {
5481
unsafe {
5582
#[cfg(not(feature = "luau"))]
@@ -76,7 +103,7 @@ impl Debug {
76103
}
77104
}
78105

79-
/// Corresponds to the `S` what mask.
106+
/// Corresponds to the `S` "what" mask.
80107
pub fn source(&self) -> DebugSource<'_> {
81108
unsafe {
82109
#[cfg(not(feature = "luau"))]
@@ -106,7 +133,7 @@ impl Debug {
106133
}
107134
}
108135

109-
/// Corresponds to the `l` what mask. Returns the current line.
136+
/// Corresponds to the `l` "what" mask. Returns the current line.
110137
pub fn curr_line(&self) -> i32 {
111138
unsafe {
112139
#[cfg(not(feature = "luau"))]
@@ -124,8 +151,8 @@ impl Debug {
124151
}
125152
}
126153

127-
/// Corresponds to the `t` what mask. Returns true if the hook is in a function tail call, false
128-
/// otherwise.
154+
/// Corresponds to the `t` "what" mask. Returns true if the hook is in a function tail call,
155+
/// false otherwise.
129156
#[cfg(not(feature = "luau"))]
130157
#[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
131158
pub fn is_tail_call(&self) -> bool {
@@ -138,7 +165,7 @@ impl Debug {
138165
}
139166
}
140167

141-
/// Corresponds to the `u` what mask.
168+
/// Corresponds to the `u` "what" mask.
142169
pub fn stack(&self) -> DebugStack {
143170
unsafe {
144171
#[cfg(not(feature = "luau"))]

tests/tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,20 @@ fn test_inspect_stack() -> Result<()> {
13151315
)
13161316
.exec()?;
13171317

1318+
// Test retrieving currently running function
1319+
let running_function =
1320+
lua.create_function(|lua, ()| Ok(lua.inspect_stack(1, |debug| debug.function())))?;
1321+
lua.globals().set("running_function", running_function)?;
1322+
lua.load(
1323+
r#"
1324+
local function baz()
1325+
return running_function()
1326+
end
1327+
assert(baz() == baz)
1328+
"#,
1329+
)
1330+
.exec()?;
1331+
13181332
Ok(())
13191333
}
13201334

0 commit comments

Comments
 (0)