Skip to content

Add Watch Pane support for the notebook debugger#1282

Open
lionel- wants to merge 4 commits into
mainfrom
notebook/evaluate
Open

Add Watch Pane support for the notebook debugger#1282
lionel- wants to merge 4 commits into
mainfrom
notebook/evaluate

Conversation

@lionel-

@lionel- lionel- commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Addresses posit-dev/positron#13323

Screenshot 2026-06-23 at 09 31 46

The debugger support for notebooks and other Jupyter apps implemented in #1170 and #1171 was quite comprehensive except for one handler: evaluate, which powers the Watch Pane.

The reason it was delayed is that this handler was written for the Console path with an asynchronous approach. The handler needs to evaluate R code in the console and, by the time we get the Evaluate DAP request when the frontend refreshes the Wath Pane contents after R stops at a breakpoint (or browser() call), R might have resumed evaluation already. That could be either because the user typed n very fast or because they evaluated multiple top-level expresssions in one go and R stops at each of them. To support this case gracefully, the Evaluate handler is executed via an Idle task that only fires when R is no longer busy. Once it completes, a response is sent to the frontend with the result. This happens asynchronously: other DAP requests might come in and be handled while the Evaluate idle task is in flight.

This approach did not work out for the Jupyter layer because the handling happens on the Control socket (used for interrupts, shutdowns, and DAP messaging) and expects a quick response right away. While the protocol is silent on whether responses can be asynchronous, reference implementations assume serial handling, both on the frontend side (e.g. VS Code) and the backend side (ipykernel).

This PR solves this by adding a new "try-idle" R task that fires under 200ms if R becomes idle in that time frame, and use that in the Jupyter handler for Evaluate. In my initial implementation there was no timeout and the task would only succeed if the Console was parked in its event loop right at that moment. However that approach had two races that the timeout-waiting fixes:

  • If we get the evaluate request a bit too early, before the console has time to drop in the event loop, we'd spuriously treat R as busy.
  • If the event loop processes polled events right at that time (it does so every 50ms), we'd also miss the idleness.

I picked 200ms arbitrarily, it felt like the maximum amount of time that is reasonable to defer other important Control messages like interrupts or shut downs when R is truly busy and can't service our request.

@lionel- lionel- force-pushed the notebook/evaluate branch from ba17a11 to 87ea6f3 Compare June 23, 2026 07:17
@lionel- lionel- requested a review from thomasp85 June 23, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant