Skip to content

Commit ce3043a

Browse files
committed
Merge branch 'main' into yarn_to_npm
* main: (32 commits) Revert the addition of spacing between `icon` and `label` in `actionButton()` (#4248) Restrict `icon`/`label` separator spacing to `actionButton()` (#4247) Fix front-end action button label updating logic (#4242) Update news Properly handle undefined value for input subscribe callback (#4243) Start new version (#4241) v1.11.0 release candidate (#4232) Follow up to #3996: fix front-end checkbox label updating logic (#4238) feat(InputBinding): subscribe callback now supports event priority (#4211) Follow up to #3996 when label is unspecified (i.e., NULL), don't include it in the message (#4237) Run routine (#4234) chore: #4175 update jquery-ui to 1.14.1 (#4205) Update jQuery to 3.7.1 (#3969) Fix 404 in example 08_html (shiny.min.css) (#4221) Follow up to #3870: fix location of news item (#4233) Bugfix for error found in tests (#3870) Allow update input labels with HTML (#3996) Adds mirai to documentation (#4230) family->given for R Core authorship (#4222) fix(renderPlot): get interactive plotting working with ggplot2 v4.0 (#4228) ...
2 parents 1fc6afb + 460a93a commit ce3043a

File tree

105 files changed

+5173
-4987
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+5173
-4987
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@
3434
^.ignore$
3535
^\.browserslistrc$
3636
^\.eslintrc\.yml$
37+
^_dev$

DESCRIPTION

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: shiny
22
Type: Package
33
Title: Web Application Framework for R
4-
Version: 1.10.0.9000
4+
Version: 1.11.0.9000
55
Authors@R: c(
66
person("Winston", "Chang", role = c("aut", "cre"), email = "[email protected]", comment = c(ORCID = "0000-0002-1576-2126")),
77
person("Joe", "Cheng", role = "aut", email = "[email protected]"),
@@ -60,7 +60,7 @@ Authors@R: c(
6060
comment = "showdown.js library"),
6161
person("Ivan", "Sagalaev", role = c("ctb", "cph"),
6262
comment = "highlight.js library"),
63-
person(family = "R Core Team", role = c("ctb", "cph"),
63+
person(given = "R Core Team", role = c("ctb", "cph"),
6464
comment = "tar implementation from R")
6565
)
6666
Description: Makes it incredibly easy to build interactive web
@@ -107,11 +107,13 @@ Suggests:
107107
reactlog (>= 1.0.0),
108108
magrittr,
109109
yaml,
110+
mirai,
110111
future,
111112
dygraphs,
112113
ragg,
113114
showtext,
114-
sass
115+
sass,
116+
watcher
115117
URL: https://shiny.posit.co/,
116118
https://github.com/rstudio/shiny
117119
BugReports: https://github.com/rstudio/shiny/issues
@@ -200,6 +202,7 @@ Collate:
200202
'test.R'
201203
'update-input.R'
202204
'utils-lang.R'
205+
'utils-tags.R'
203206
'version_bs_date_picker.R'
204207
'version_ion_range_slider.R'
205208
'version_jquery.R'

NEWS.md

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,68 @@
11
# shiny (development version)
22

3-
## New features and improvements
3+
## New features
4+
5+
* The `icon` argument of `actionButton()`, `downloadButton()`, etc. now accepts values other than `shiny::icon()` (like `fontawesome::fa()` and `bsicons::bs_icon()`). (#4242)
6+
7+
## Improvements
8+
9+
* Padding is now provided between the `icon` and `label` of an `actionButton()`. (#4242)
10+
## Bug fixes
11+
12+
* Fixed a regression in v1.11.0 where `InputBinding` implementations that don't pass a value to their `subscribe` callback were no longer notifying Shiny of input changes. (#4243)
13+
14+
* `updateActionButton()` and `updateActionLink()` once again handle `label` updates correctly (which can now include HTML). (#4242)
15+
16+
# shiny 1.11.0
17+
18+
## Improvements
19+
20+
* When auto-reload is enabled, Shiny now reloads the entire app when support files, like Shiny modules, additional script files, or web assets, change. To enable auto-reload, call `devmode(TRUE)` to enable Shiny's developer mode, or set `options(shiny.autoreload = TRUE)` to specifically enable auto-reload. You can choose which files are watched for changes with the `shiny.autoreload.pattern` option. (#4184)
421

522
* When busy indicators are enabled (i.e., `useBusyIndicators()`), Shiny now:
623
* Shows a spinner on recalculating htmlwidgets that have previously rendered an error (including `req()` and `validate()`). (#4172)
724
* Shows a spinner on `tableOutput()`. (#4172)
825
* Places a minimum height on recalculating outputs so that the spinner is always visible. (#4172)
926

10-
* Shiny now uses `{cli}` instead of `{crayon}` for rich log messages. (@olivroy #4170)
27+
* Shiny now uses `{cli}` instead of `{crayon}` for rich log messages. (thanks @olivroy, #4170)
1128

12-
* Shiny's Typescript assets are now compiled to ES2021 instead of ES5. (#4066)
29+
* `renderPlot()` was updated to accommodate changes in ggplot2 v4.0.0. (#4226)
1330

14-
## Bug fixes
31+
* When adding the new tab via `insertTab()` or `bslib::nav_insert()`, the underlying JavaScript no longer renders content twice. (#4179)
32+
33+
## New features
34+
35+
* `textInput()`, `textAreaInput()`, `numericInput()` and `passwordInput()` all gain an `updateOn` option. `updateOn = "change"` is the default and previous behavior, where the input value updates immediately whenever the value changes. With `updateOn = "blur"`, the input value will update only when the text input loses focus or when the user presses Enter (or Cmd/Ctrl + Enter for `textAreaInput()`). (#4183)
36+
37+
* `textAreaInput()` gains a `autoresize` option, which automatically resizes the text area to fit its content. (#4210)
1538

16-
* Fixed a bug with modals where calling `removeModal()` too quickly after `showModal()` would fail to remove the modal if the remove modal message was received while the modal was in the process of being revealed. (#4173)
39+
* The family of `update*Input()` functions can now render HTML content passed to the `label` argument (e.g., `updateInputText(label = tags$b("New label"))`). (#3996)
40+
41+
* `ExtendedTask` now catches synchronous values and errors and returns them via `$result()`. Previously, the extended task function was required to always return a promise. This change makes it easier to use `ExtendedTask` with a function that may return early or do some synchronous work before returning a promise. (#4225)
42+
43+
* The `callback` argument of Shiny.js' `InputBinding.subscribe()` method gains support for a value of `"event"`. This makes it possible for an input binding to use event priority when updating the value (i.e., send immediately and always resend, even if the value hasn't changed). (#4211)
44+
45+
## Changes
46+
47+
* Shiny no longer suspends input changes when _any_ `<input type="submit">` or `<button type="submit">` is on the page. Instead, it now only suspends when a `submitButton()` is present. If you have reason for creating a submit button from custom HTML, add a CSS class of `shiny-submit-button` to the button. (#4209)
48+
49+
* Shiny's JavaScript assets are now compiled to ES2021 instead of ES5. (#4066)
50+
51+
* Upgraded jQuery from 3.6.0 to 3.7.1. (#3969)
52+
53+
* Updated jQuery UI from 1.13.2 to 1.14.1. (#4175)
54+
55+
## Bug fixes
1756

1857
* The Shiny Client Console (enabled with `shiny::devmode()`) no longer displays duplicate warning or error message. (#4177)
1958

20-
* Updated the JavaScript used when inserting a tab to avoid rendering dynamic UI elements twice when adding the new tab via `insertTab()` or `bslib::nav_insert()`. (#4179)
59+
* Synchronous errors that occur inside a `ExtendedTask` no longer stop the session. (#4225)
60+
61+
* Calling `removeModal()` immediately after `showModal()` no longer fails to remove the modal (this would sometimes happen if the remove message was received while the modal was in the process of being revealed). (#4173)
62+
63+
* `runExample("08_html")` now (correctly) requests to 'shiny.min.css', eliminating a network request failure. (#4220)
64+
65+
* `shiny::shinyAppTemplate()` no longer errors without a call to `library(shiny)`. (#3870)
2166

2267
# shiny 1.10.0
2368

@@ -178,7 +223,6 @@ In addition, various properties of the spinners and pulse can be customized with
178223

179224
* Fixed #3833: When `width` is provided to `textAreaInput()`, we now correctly set the width of the `<textarea>` element. (#3838)
180225

181-
182226
# shiny 1.7.4.1
183227

184228
## Full changelog
@@ -367,7 +411,7 @@ This release focuses on improvements in three main areas:
367411

368412
* Fixed #2951: screen readers correctly announce labels and date formats for `dateInput()` and `dateRangeInput()` widgets. (#2978)
369413

370-
* Closed #2847: `selectInput()` is reasonably accessible for screen readers even when `selectize` option is set to TRUE. To improve `selectize.js` accessibility, we have added [selectize-plugin-a11y](https://github.com/SLMNBJ/selectize-plugin-a11y) by default. (#2993)
414+
* Closed #2847: `selectInput()` is reasonably accessible for screen readers even when `selectize` option is set to TRUE. To improve `selectize.js` accessibility, we have added [selectize-plugin-a11y](https://github.com/SalmenBejaoui/selectize-plugin-a11y) by default. (#2993)
371415

372416
* Closed #612: Added `alt` argument to `renderPlot()` and `renderCachedPlot()` to specify descriptive texts for `plotOutput()` objects, which is essential for screen readers. By default, alt text is set to the static text, "Plot object," but even dynamic text can be made with reactive function. (#3006, thanks @trafficonese and @leonawicz for the original PR and discussion via #2494)
373417

R/bind-cache.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ utils::globalVariables(".GenericCallEnv", add = TRUE)
231231
#' promises, but rather objects provided by the
232232
#' \href{https://rstudio.github.io/promises/}{\pkg{promises}} package, which
233233
#' are similar to promises in JavaScript. (See [promises::promise()] for more
234-
#' information.) You can also use [future::future()] objects to run code in a
235-
#' separate process or even on a remote machine.
234+
#' information.) You can also use [mirai::mirai()] or [future::future()]
235+
#' objects to run code in a separate process or even on a remote machine.
236236
#'
237237
#' If the value returns a promise, then anything that consumes the cached
238238
#' reactive must expect it to return a promise.

R/conditions.R

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ getCallNames <- function(calls) {
7575
})
7676
}
7777

78+
# A stripped down version of getCallNames() that intentionally avoids deparsing expressions.
79+
# Instead, it leaves expressions to be directly `rlang::hash()` (for de-duplication), which
80+
# is much faster than deparsing then hashing.
81+
getCallNamesForHash <- function(calls) {
82+
lapply(calls, function(call) {
83+
name <- call[[1L]]
84+
if (is.function(name)) return("<Anonymous>")
85+
if (typeof(name) == "promise") return("<Promise>")
86+
name
87+
})
88+
}
89+
7890
getLocs <- function(calls) {
7991
vapply(calls, function(call) {
8092
srcref <- attr(call, "srcref", exact = TRUE)
@@ -144,7 +156,7 @@ getCallStackDigest <- function(callStack, warn = FALSE) {
144156
)
145157
}
146158

147-
rlang::hash(getCallNames(callStack))
159+
rlang::hash(getCallNamesForHash(callStack))
148160
}
149161

150162
saveCallStackDigest <- function(callStack) {

R/extended-task.R

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,15 @@
4141
#' is, a function that quickly returns a promise) and allows even that very
4242
#' session to immediately unblock and carry on with other user interactions.
4343
#'
44-
#' @examplesIf rlang::is_interactive() && rlang::is_installed("future")
45-
#'
44+
#' @examplesIf rlang::is_interactive() && rlang::is_installed("mirai")
4645
#' library(shiny)
4746
#' library(bslib)
48-
#' library(future)
49-
#' plan(multisession)
47+
#' library(mirai)
48+
#'
49+
#' # Set background processes for running tasks
50+
#' daemons(1)
51+
#' # Reset when the app is stopped
52+
#' onStop(function() daemons(0))
5053
#'
5154
#' ui <- page_fluid(
5255
#' titlePanel("Extended Task Demo"),
@@ -60,13 +63,12 @@
6063
#'
6164
#' server <- function(input, output) {
6265
#' rand_task <- ExtendedTask$new(function() {
63-
#' future(
66+
#' mirai(
6467
#' {
6568
#' # Slow operation goes here
6669
#' Sys.sleep(2)
6770
#' sample(1:100, 1)
68-
#' },
69-
#' seed = TRUE
71+
#' }
7072
#' )
7173
#' })
7274
#'
@@ -100,11 +102,12 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
100102
#' @param func The long-running operation to execute. This should be an
101103
#' asynchronous function, meaning, it should use the
102104
#' [\{promises\}](https://rstudio.github.io/promises/) package, most
103-
#' likely in conjuction with the
105+
#' likely in conjunction with the
106+
#' [\{mirai\}](https://mirai.r-lib.org) or
104107
#' [\{future\}](https://rstudio.github.io/promises/articles/promises_04_futures.html)
105108
#' package. (In short, the return value of `func` should be a
106-
#' [`Future`][future::future()] object, or a `promise`, or something else
107-
#' that [promises::as.promise()] understands.)
109+
#' [`mirai`][mirai::mirai()], [`Future`][future::future()], `promise`,
110+
#' or something else that [promises::as.promise()] understands.)
108111
#'
109112
#' It's also important that this logic does not read from any
110113
#' reactive inputs/sources, as inputs may change after the function is
@@ -130,14 +133,15 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
130133
#' arguments.
131134
invoke = function(...) {
132135
args <- rlang::dots_list(..., .ignore_empty = "none")
136+
call <- rlang::caller_call(n = 0)
133137

134138
if (
135139
isolate(private$rv_status()) == "running" ||
136140
private$invocation_queue$size() > 0
137141
) {
138-
private$invocation_queue$add(args)
142+
private$invocation_queue$add(list(args = args, call = call))
139143
} else {
140-
private$do_invoke(args)
144+
private$do_invoke(args, call = call)
141145
}
142146
invisible(NULL)
143147
},
@@ -204,44 +208,41 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
204208
rv_error = NULL,
205209
invocation_queue = NULL,
206210

207-
do_invoke = function(args) {
211+
do_invoke = function(args, call = NULL) {
208212
private$rv_status("running")
209213
private$rv_value(NULL)
210214
private$rv_error(NULL)
211215

212-
p <- NULL
213-
tryCatch({
214-
maskReactiveContext({
215-
# TODO: Bounce the do.call off of a promise_resolve(), so that the
216-
# call to invoke() always returns immediately?
217-
result <- do.call(private$func, args)
218-
p <- promises::as.promise(result)
219-
})
220-
}, error = function(e) {
221-
private$on_error(e)
222-
})
216+
p <- promises::promise_resolve(
217+
maskReactiveContext(do.call(private$func, args))
218+
)
223219

224-
promises::finally(
225-
promises::then(p,
226-
onFulfilled = function(value, .visible) {
227-
private$on_success(list(value=value, visible=.visible))
228-
},
229-
onRejected = function(error) {
230-
private$on_error(error)
231-
}
232-
),
233-
onFinally = function() {
234-
if (private$invocation_queue$size() > 0) {
235-
private$do_invoke(private$invocation_queue$remove())
236-
}
220+
p <- promises::then(
221+
p,
222+
onFulfilled = function(value, .visible) {
223+
private$on_success(list(value = value, visible = .visible))
224+
},
225+
onRejected = function(error) {
226+
private$on_error(error, call = call)
237227
}
238228
)
239229

230+
promises::finally(p, onFinally = function() {
231+
if (private$invocation_queue$size() > 0) {
232+
next_call <- private$invocation_queue$remove()
233+
private$do_invoke(next_call$args, next_call$call)
234+
}
235+
})
240236

241237
invisible(NULL)
242238
},
243239

244-
on_error = function(err) {
240+
on_error = function(err, call = NULL) {
241+
cli::cli_warn(
242+
"ERROR: An error occurred when invoking the ExtendedTask.",
243+
parent = err,
244+
call = call
245+
)
245246
private$rv_status("error")
246247
private$rv_error(err)
247248
},

0 commit comments

Comments
 (0)