Skip to content

Send the final update for a plot page when the next page starts while the device is held - #1481

Merged
juliasilge merged 2 commits into
mainfrom
notebook-plot-deferred-page-update
Nov 14, 2026
Merged

juliasilge merged 2 commits into
mainfrom
notebook-plot-deferred-page-update

Conversation

@juliasilge

Copy link
Copy Markdown
Member

Addresses posit-dev/positron#17240

In notebook sessions, a plot page now keeps all of its layers when the same statement starts another page. Before this change, Quarto inline output showed the first page without the layers that were added last. For example, plot(gof_fit) from ergm showed the model page as a bare boxplot.

This base R example can be used to see the problem:

local({
  plot(1:10)
  points(5, 5, col = "red", pch = 16, cex = 4)
  plot(1:5)
  points(3, 3, col = "blue", pch = 16, cex = 4)
})

The first plot would not show the red point before this change. If you write the same calls as separate top-level statements, the red point always shows.

plot.default() and bxp() call dev.hold() before they call plot.new(), so when the second page starts, the before.plot.new hook records the first page with the red point. The device is on hold, though, so ark defers the notification and then the newPage callback gives the device a new plot ID. When the hold is released, ark sent the deferred notification for the new page only and the first page never got its final update.

Changes

  • ark now remembers when it defers a notification. If a new page starts while a notification is deferred, ark keeps the ID of the old page in a list of held pages.
  • When the hold is released, ark sends an update for each held page. In notebook mode, this update is update_display_data; in console mode, it is an update on the plot comm. The Plots pane already rendered the complete plot when it asked for one, but it now also gets the final image when the hold is released.
  • ark keeps a page only if the frontend already saw it. A page that the frontend never saw stays hidden, so dev.hold() still hides the pages between a hold and a flush.
  • If the user closes a plot, ark removes it from the held pages.

The frontend gets the new page before the update for the old page. To render the old page, ark replays its recording on another device. This change of device starts process_changes() again, and that call sends the new page first. Frontends match an update to its plot by display ID or comm ID, so the order doesn't have an effect. Positron's Quarto inline output (posit-dev/positron#17171) and .ipynb notebooks both replace the old output.

Tests

  • test_notebook_plot_layers_kept_when_next_page_starts_in_same_request in kernel_notebook.rs: the example above sends display_data for each page, then update_display_data for page 1 and for page 2. The image in the update for page 1 is different from the first image for page 1.
  • test_positron_held_layers_update_previous_page in plots.rs: in console mode, the same code sends an update event with a rendered image on the plot comm of page 1.
  • A new test helper, recv_iopub_update_display_data_content, returns the content of an update_display_data message.

Both new tests fail without the fix. The existing dev.hold() tests still pass. I also tested the ergm example from the issue:

Screenshot 2026-11-12 at 2 43 54 PM

Positron Release Notes

New Features

  • N/A

Bug Fixes

@juliasilge
juliasilge marked this pull request as ready for review November 13, 2026 01:12
@juliasilge
juliasilge requested a review from jmcphers November 13, 2026 01:12

@jmcphers jmcphers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is working great! Thank you!

@juliasilge
juliasilge merged commit 05159ce into main Nov 14, 2026
19 checks passed
@juliasilge
juliasilge deleted the notebook-plot-deferred-page-update branch November 14, 2026 02:26
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants