This was the product of a long discussion between @wch, @alandipert, @bborgesr
and myself. The conflation of immediate (no throttle/debounce) and non-dedupe
in a single "immediate" flag was deemed unacceptable, because UI controls often
want immediacy but also dedupe. Introducing a second "dedupe" flag would work
but {immediate: false, dedupe: false} doesn't make much sense, and dedupe not
only implies that InputNoResendDecorator should behave differently but also
InputBatchSender (i.e. no deduplication AND no coalescing).
We decided to remove the "immediate" boolean option and replace it with a
string option that would have three possibilities at this time. The only con
to this approach is if anyone is calling onInputChange with immediate:true
today, and I can't imagine anyone is. The immediate flag only has any effect
if the input id that's being set has been put in debounce/throttle mode, and
I don't even think that is documented today, and I'm not even sure it's
possible to do it from custom JS (that's not part of a custom input binding).
Without this change, async handlers won't return any
value for getDefaultReactiveDomain().
library(shiny)
library(promises)
ui <- fluidPage(
p("This app tests if async handlers have reactive domains. You'll get a yes/no answer below."),
h3(
"Does it work?",
textOutput("answer", inline = TRUE)
)
)
server <- function(input, output, session) {
output$answer <- renderText({
promise_resolve(TRUE) %...>% {
if (!is.null(getDefaultReactiveDomain()))
"Yes!"
else
"No :("
}
})
}
shinyApp(ui, server)
* Fix#2008: Allow eventReactive and observeEvent eventExprs to be async
This makes it possible to monitor e.g. async reactives.
In the process of fixing this, also discovered that observers don't
filter out shiny.silent.error (i.e. req(FALSE)) when they come back
from async operations. For example, this will kill the current
Shiny session instead of being ignored:
observe({
promise_resolve(TRUE) %...>%
{req(FALSE)}
})
This issue is also fixed in this commit.
* Enable deep stack trace by default, now that it's fast
We already had an `immediate` input option, which was used to override client side rate
limiting mechanisms (debounce/throttle). This commit extends the semantics of that option
to also mean that duplicate values should not be ignored on the client side.
Previous to this commit, circumventing the client side dedupe logic was not enough. The
server side ReactiveValues object was also subject to deduping. With this commit, the
low-level ReactiveValues class's constructor now has a `dedupe` option, which defaults
to TRUE; the ReactiveValues used for a session's input has it turned to FALSE. I figure
if I had to work this hard to get the client to stop sending duplicates, and the input
values are only expected to ever be updated by the client, then there's really no reason
for server side deduping to be performed for this particular ReactiveValues object.
It would make sense as a future feature to also make deduping optional for user-created
reactiveValues and reactiveVal objects.
- Adds functions we will need for tracking ..stacktraceon/off..
across deep stacks
- Adds functions we will need for pruning according to lobstr::cst
logic
These functions are not yet integrated, that will occur in a
separate commit.
With deep stack traces enabled, whenever then() is called, we need
to grab the current stack, just in case a downstream callback throws
an error and we need to form a deep stack trace.
Previously, we were calling formatStackTrace at the time that we
grab the current stack (i.e. no error has happened yet) because I
wasn't sure whether holding a reference to sys.calls() for a long
time was a good idea from a garbage collection perspective; would it
prevent the stack frame environments from being collected? But the
answer is no, sys.calls() is just calls, which can be confirmed with
.Internal(inspect(sys.calls()).
By deferring the formatStackTrace call to when we actually need to
print the stack trace, we save ourselves a ton of work--it turns out
it's quite expensive to format the stack traces, much more expensive
than sys.calls() alone.
* A copy of yihui's PR for rmarkdown (https://github.com/rstudio/rmarkdown/pull/1171/) to avoid to error "Error in normalizePath: path[1]="": No such file or directory" when running any tutorial
* first try
* limited the scope of the `tryCatch` wrapper to the one important line that needed it; added news item