Class RemoteThread

java.lang.Object
org.eclipse.lsp4j.debug.Thread
io.quarkus.qute.debug.agent.RemoteThread

public class RemoteThread extends org.eclipse.lsp4j.debug.Thread
Represents a Qute debug thread that manages the execution flow of templates during debugging.

This class extends the Debug Adapter Protocol Thread to track the current state of execution, stack frames, and debugging actions like step over, step in, breakpoints, etc.

It is tightly integrated with DebuggeeAgent, which communicates with the debugging client.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final org.eclipse.lsp4j.debug.Thread[]
    Represents an empty array of threads.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a new RemoteThread instance.
  • Method Summary

    Modifier and Type
    Method
    Description
    Schedules a task to be executed within the render thread (the thread currently rendering the template) while it is suspended during debugging.
    void
    Marks the thread as exited and notifies the agent.
    getStackFrame(int frameId)
    Finds a specific stack frame by its ID.
    Returns the list of current stack frames.
    Returns the current debugger state of this thread.
    boolean
    Checks if the thread has been stopped.
    void
    Performs a "next" operation, stopping only on non-text nodes.
    void
    onAfterResolve(io.quarkus.qute.trace.ResolveEvent event)
    Called after a Qute template node has been resolved.
    void
    onBeforeResolve(io.quarkus.qute.trace.ResolveEvent event)
    Called before a Qute template node is resolved.
    void
    Pauses the thread at the next opportunity by setting the stop condition to always true.
    void
    Resumes execution of the thread after being suspended.
    void
    Marks the thread as started and clears its stack frames.
    void
    Performs a "step in" operation, stopping execution at the next node.
    void
    Performs a "step out" operation, resuming execution until the current function or template block returns.
    void
    Performs a "step over" operation, stopping only when the current frame size decreases, i.e., when the current step is completed.
    void
    Terminates the thread and notifies any waiting processes.

    Methods inherited from class org.eclipse.lsp4j.debug.Thread

    equals, getId, getName, hashCode, setId, setName, toString

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Field Details

    • EMPTY_THREAD

      public static final org.eclipse.lsp4j.debug.Thread[] EMPTY_THREAD
      Represents an empty array of threads.
  • Constructor Details

  • Method Details

    • getState

      public DebuggerState getState()
      Returns the current debugger state of this thread.
      Returns:
      the current DebuggerState
    • pause

      public void pause()
      Pauses the thread at the next opportunity by setting the stop condition to always true.
      Throws:
      DebuggerStoppedException - if the thread is already stopped
    • resume

      public void resume()
      Resumes execution of the thread after being suspended.
      Throws:
      DebuggerStoppedException - if the thread is already stopped
      IllegalStateException - if the thread is not currently suspended
    • isStopped

      public boolean isStopped()
      Checks if the thread has been stopped.
      Returns:
      true if stopped, false otherwise
    • onBeforeResolve

      public void onBeforeResolve(io.quarkus.qute.trace.ResolveEvent event)
      Called before a Qute template node is resolved.

      Updates the current stack frames and handles section frame groups for template sections (loops, conditionals, etc.).

      Sections include constructs like #for, #each, #if, and any other Qute section nodes. Each section has its own SectionFrameGroup which tracks the stack frames created while rendering that section.

      Parameters:
      event - the ResolveEvent representing the node resolution
    • onAfterResolve

      public void onAfterResolve(io.quarkus.qute.trace.ResolveEvent event)
      Called after a Qute template node has been resolved.

      Cleans up section frame groups if the resolved node was a section. This includes loops (#for / #each), conditionals (#if), or any other section nodes. Frames accumulated during the section are detached from the main thread stack when the section ends.

      Parameters:
      event - the ResolveEvent representing the node resolution
    • evaluateInRenderThread

      public CompletableFuture<Object> evaluateInRenderThread(Callable<CompletableFuture<Object>> action)
      Schedules a task to be executed within the render thread (the thread currently rendering the template) while it is suspended during debugging.

      This method is typically used by the debugger to evaluate Qute expressions or inspect the current template state. Since certain Qute features — such as expressions like uri:Todos.index — rely on contextual data bound to the HTTP request thread (e.g. @RequestScoped beans), these evaluations must occur in the same thread that is rendering the template. Executing such expressions in any other thread would lead to context-related errors such as:

         javax.enterprise.context.ContextNotActiveException: RequestScoped was not active
       

      The render thread periodically checks for scheduled evaluation tasks while suspended (see suspendAndWait(io.quarkus.qute.debug.StoppedEvent.StoppedReason)). When a task is detected, it is executed directly within that render thread to ensure full access to the active request and template context.

      Threading model:
      This method must be called from the debugger control thread (not the render thread itself). The provided callable will be executed synchronously within the render thread context, ensuring compatibility with request-bound state.

      Parameters:
      action - the task to execute within the render thread context. It should return a CompletableFuture representing the computation result.
      Returns:
      a CompletableFuture containing the result of the executed task
      Throws:
      IllegalStateException - if the thread is not currently suspended or if another evaluation task is already pending
    • terminate

      public void terminate()
      Terminates the thread and notifies any waiting processes.
    • stepIn

      public void stepIn()
      Performs a "step in" operation, stopping execution at the next node.
    • stepOut

      public void stepOut()
      Performs a "step out" operation, resuming execution until the current function or template block returns.
    • stepOver

      public void stepOver()
      Performs a "step over" operation, stopping only when the current frame size decreases, i.e., when the current step is completed.
    • next

      public void next()
      Performs a "next" operation, stopping only on non-text nodes.
    • getStackFrames

      public List<RemoteStackFrame> getStackFrames()
      Returns the list of current stack frames.
      Returns:
      a list of RemoteStackFrame
    • getStackFrame

      public RemoteStackFrame getStackFrame(int frameId)
      Finds a specific stack frame by its ID.
      Parameters:
      frameId - the frame ID
      Returns:
      the corresponding RemoteStackFrame, or null if not found
    • start

      public void start()
      Marks the thread as started and clears its stack frames.
    • exit

      public void exit()
      Marks the thread as exited and notifies the agent.