withr
                                
                                 withr copied to clipboard
                                
                                    withr copied to clipboard
                            
                            
                            
                        local_pdf (and probably other similar functions as well) does not restore device
Because the devices are in a circular ring, not in a stack (!!!).
f <- function() { withr::local_pdf(tempfile()) }
png("2.png")
png("3.png")
dev.cur()
#> png 
#>   4
f()
dev.cur()
#> png 
#>   2
Created on 2020-06-17 by the reprex package (v0.3.0)
(Without reprex, the first dev.cur() returns 3, probably reprex or knitr / evaluate are also messing with the devices.)
Yeah, I guess the tests never try opening multiple devices so don't run into this, definitely a bug.
While I agree it is very confusing, this behavior is consistent with what would happen if you open and close the devices manually, so I am not sure we should change it...
f <- function() {
  png("1.png")
  dev.off()
  invisible()
}
png("2.png")
png("3.png")
dev.cur()
#> quartz_off_screen 
#>                 4
f()
dev.cur()
#> quartz_off_screen 
#>                 2
Created on 2020-09-02 by the reprex package (v0.3.0)
this behavior is consistent with what would happen if you open and close the devices manually
I am not sure withr needs to follow that. I think withr's contract is more like "create a temporary context, and then clean up side effects". I.e. a withr::with*(...) block should not have any side effect.