Skip to content

Commit cfb6b7e

Browse files
committed
Fix step-over depth calculation consistency
1 parent 6128475 commit cfb6b7e

3 files changed

Lines changed: 28 additions & 6 deletions

File tree

luceedebug/src/main/java/luceedebug/coreinject/NativeDebuggerListener.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ private static class StepState {
240240
}
241241
}
242242

243+
/**
244+
* Cached reflection method for DebuggerFrame.getLine().
245+
* Initialized lazily on first use in getStackDepth().
246+
*/
247+
private static volatile java.lang.reflect.Method debuggerFrameGetLineMethod = null;
248+
243249
public static void setNativeMode(boolean enabled) {
244250
nativeMode = enabled;
245251
Log.info("Native mode: " + enabled);
@@ -604,12 +610,29 @@ public static void stopStepping(long threadId) {
604610
/**
605611
* Get the current stack depth for a PageContext.
606612
* Uses reflection to get debugger frames.
613+
* Only counts frames with line > 0 to match NativeDebugFrame.getNativeFrames() filtering.
607614
*/
608615
public static int getStackDepth(PageContext pc) {
609616
try {
610617
java.lang.reflect.Method getFrames = pc.getClass().getMethod("getDebuggerFrames");
611618
Object[] frames = (Object[]) getFrames.invoke(pc);
612-
return frames != null ? frames.length : 0;
619+
if (frames == null || frames.length == 0) return 0;
620+
621+
// Cache the getLine method on first use
622+
java.lang.reflect.Method getLine = debuggerFrameGetLineMethod;
623+
if (getLine == null) {
624+
getLine = frames[0].getClass().getMethod("getLine");
625+
debuggerFrameGetLineMethod = getLine;
626+
}
627+
628+
// Count only frames with line > 0 (matching getNativeFrames filtering)
629+
// Frames start with line=0 before first ExecutionLog.start() call
630+
int count = 0;
631+
for (Object frame : frames) {
632+
int line = (int) getLine.invoke(frame);
633+
if (line > 0) count++;
634+
}
635+
return count;
613636
} catch (Exception e) {
614637
// Log error - silent failure could cause incorrect step behavior
615638
Log.error("Error getting stack depth: " + e.getMessage());

luceedebug/src/main/java/luceedebug/coreinject/NativeLuceeVm.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,11 @@ public void stepOut(long threadID) {
336336

337337
/**
338338
* Get the current stack depth for a thread using native debugger frames.
339+
* Uses NativeDebuggerListener.getStackDepth() to count only real frames (not synthetic).
339340
*/
340341
private int getStackDepthForThread(long threadID) {
341-
IDebugFrame[] frames = getStackTrace(threadID);
342-
return frames != null ? frames.length : 0;
342+
PageContext pc = NativeDebuggerListener.getPageContext(threadID);
343+
return pc != null ? NativeDebuggerListener.getStackDepth(pc) : 0;
343344
}
344345

345346
// ========== Debug utilities ==========

test/cfml/SteppingTest.cfc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="dap" {
3535
teardownDap();
3636
} );
3737

38-
it( "validates line numbers in stepping-target", function() {
39-
if ( notSupportsBreakpointLocations() ) return skip();
40-
38+
it( title="validates line numbers in stepping-target", skip=notSupportsBreakpointLocations(), body=function() {
4139
var locations = dap.breakpointLocations( variables.targetFile, 1, 35 );
4240
var validLines = locations.body.breakpoints.map( function( bp ) { return bp.line; } );
4341

0 commit comments

Comments
 (0)