Compare commits

...

24 Commits

Author SHA1 Message Date
schloerke
06c0ce4065 yarn build (GitHub Actions) 2021-07-26 22:01:29 +00:00
schloerke
dcb29d211c sync package version (GitHub Actions) 2021-07-26 21:58:49 +00:00
Barret Schloerke
3bb441aa5b bump dev version 2021-07-26 17:51:51 -04:00
Barret Schloerke
2bb8dbfe3b Merge branch 'barret/quosure_expr_to_func' of https://github.com/rstudio/shiny into barret/quosure_expr_to_func 2021-07-26 17:44:51 -04:00
Barret Schloerke
476217c0c4 check fixes 2021-07-26 17:44:23 -04:00
schloerke
39ae0f5470 Document (GitHub Actions) 2021-07-26 21:35:41 +00:00
Barret Schloerke
17a53ea748 document 2021-07-26 17:32:56 -04:00
Barret Schloerke
10935f7316 handleEnvAndQuoted() -> sustainEnvAndQuoted() 2021-07-26 17:25:09 -04:00
Barret Schloerke
6abc2ea9d7 Revert test changes 2021-07-26 17:21:30 -04:00
Barret Schloerke
6281498ae3 Import rlang::quo_get_expr() 2021-07-26 17:20:12 -04:00
Barret Schloerke
6b078ffacd Remove proposed exprToFunction() and installExprFunction() as they do not consistently work 2021-07-26 10:39:06 -04:00
Barret Schloerke
f2977c0a06 Apply suggestions from code review
Co-authored-by: Winston Chang <winston@stdout.org>
2021-07-26 10:38:09 -04:00
schloerke
a75efaefd4 Document (GitHub Actions) 2021-07-23 20:05:58 +00:00
Barret Schloerke
b547e87250 Remove getQuosure() and getQuosure3()
Comment `handleEnvAndQuoted3Internal()` as it is currently not used
2021-07-23 15:55:40 -04:00
Barret Schloerke
38e4d5b5d6 document() 2021-07-23 15:39:29 -04:00
Barret Schloerke
254ae727b6 Fix broken tests. To review!! 2021-07-23 15:38:54 -04:00
Barret Schloerke
2a86c8cc49 white space 2021-07-23 15:38:40 -04:00
Barret Schloerke
0251559854 Make sure the environment of the quoToSimpleFunction is two levels deep to match test 2021-07-23 15:38:28 -04:00
Barret Schloerke
9cc2fee386 Fix missing logic flip change 2021-07-23 15:37:55 -04:00
Barret Schloerke
fe4a72492c Use new enquo0(), handleEnvAndQuotedInternal(), quoToFunction() cadence 2021-07-23 14:42:46 -04:00
Barret Schloerke
b9a2338aff add handleEnvAndQuoted() and handleEnvAndQuotedInternal() and handleEnvAndQuoted3Internal() 2021-07-23 14:41:50 -04:00
Barret Schloerke
aa39e8224a Add kitchen sink tests for quoToFunction and friends 2021-07-23 14:40:56 -04:00
Barret Schloerke
454c58173f clean up importFrom calls 2021-07-23 13:14:43 -04:00
Barret Schloerke
1012a0ea8c Allow for shinyDeprecated() to know of _superseded_ functions 2021-07-23 13:14:04 -04:00
33 changed files with 645 additions and 541 deletions

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.6.0.9021
Version: 1.6.0.9022
Authors@R: c(
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@rstudio.com", comment = c(ORCID = "0000-0002-1576-2126")),
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),

View File

@@ -119,7 +119,6 @@ export(getCurrentOutputInfo)
export(getCurrentTheme)
export(getDefaultReactiveDomain)
export(getQueryString)
export(getQuosure)
export(getShinyOption)
export(getUrlHash)
export(get_devmode_option)
@@ -274,6 +273,7 @@ export(stopApp)
export(strong)
export(submitButton)
export(suppressDependencies)
export(sustainEnvAndQuoted)
export(tabPanel)
export(tabPanelBody)
export(tableOutput)
@@ -379,6 +379,7 @@ importFrom(htmltools,tags)
importFrom(htmltools,validateCssUnit)
importFrom(htmltools,withTags)
importFrom(lifecycle,deprecated)
importFrom(lifecycle,is_present)
importFrom(promises,"%...!%")
importFrom(promises,"%...>%")
importFrom(promises,as.promise)
@@ -387,10 +388,13 @@ importFrom(promises,promise)
importFrom(promises,promise_reject)
importFrom(promises,promise_resolve)
importFrom(rlang,"%||%")
importFrom(rlang,"fn_body<-")
importFrom(rlang,"fn_fmls<-")
importFrom(rlang,as_function)
importFrom(rlang,as_quosure)
importFrom(rlang,enexpr)
importFrom(rlang,enquo)
importFrom(rlang,enquo0)
importFrom(rlang,enquos)
importFrom(rlang,enquos0)
importFrom(rlang,eval_tidy)
@@ -409,4 +413,8 @@ importFrom(rlang,new_function)
importFrom(rlang,new_quosure)
importFrom(rlang,pairlist2)
importFrom(rlang,quo)
importFrom(rlang,quo_get_expr)
importFrom(rlang,quo_is_missing)
importFrom(rlang,quo_set_env)
importFrom(rlang,quo_set_expr)
importFrom(rlang,zap_srcref)

View File

@@ -9,13 +9,19 @@
#' @param details Additional information to be added after a new line to the displayed message
#' @keywords internal
shinyDeprecated <- function(
version, what, with = NULL, details = NULL
version,
what,
with = NULL,
details = NULL,
type = c("deprecated", "superseded")
) {
if (is_false(getOption("shiny.deprecation.messages"))) {
return(invisible())
}
msg <- paste0("`", what, "` is deprecated as of shiny ", version, ".")
type <- match.arg(type)
msg <- paste0("`", what, "` is ", type, " as of shiny ", version, ".")
if (!is.null(with)) {
msg <- paste0(msg, "\n", "Please use `", with, "` instead.")
}
@@ -60,7 +66,7 @@ diskCache <- function(
logfile = NULL
) {
shinyDeprecated("1.6.0", "diskCache()", "cachem::cache_disk()")
if (lifecycle::is_present(exec_missing)) {
if (is_present(exec_missing)) {
shinyDeprecated("1.6.0", "diskCache(exec_missing =)")
}
@@ -93,7 +99,7 @@ memoryCache <- function(
logfile = NULL)
{
shinyDeprecated("1.6.0", "diskCache()", "cachem::cache_mem()")
if (lifecycle::is_present(exec_missing)) {
if (is_present(exec_missing)) {
shinyDeprecated("1.6.0", "diskCache(exec_missing =)")
}

View File

@@ -1,4 +1,3 @@
#' @importFrom fastmap fastmap
Map <- R6Class(
'Map',
portable = FALSE,

View File

@@ -945,12 +945,12 @@ Observable <- R6Class(
#' See the [Shiny tutorial](https://shiny.rstudio.com/tutorial/) for
#' more information about reactive expressions.
#'
#' @param x For `reactive`, an expression (quoted or unquoted). For
#' @param x TODO-barret docs; For `reactive`, an expression (quoted or unquoted). For
#' `is.reactive`, an object to test.
#' @param env The parent environment for the reactive expression. By default,
#' @param env TODO-barret docs; The parent environment for the reactive expression. By default,
#' this is the calling environment, the same as when defining an ordinary
#' non-reactive expression.
#' @param quoted Is the expression quoted? By default, this is `FALSE`.
#' @param quoted TODO-barret docs; Is the expression quoted? By default, this is `FALSE`.
#' This is useful when you want to use an expression that is stored in a
#' variable; to do so, it must be quoted with `quote()`.
#' @param label A label for the reactive expression, useful for debugging.
@@ -961,6 +961,7 @@ Observable <- R6Class(
#' @return a function, wrapped in a S3 class "reactive"
#'
#' @examples
#' # TODO-barret docs; with quosures, not env / quoted
#' values <- reactiveValues(A=1)
#'
#' reactiveB <- reactive({
@@ -979,7 +980,10 @@ Observable <- R6Class(
#' isolate(reactiveC())
#' isolate(reactiveD())
#' @export
reactive <- function(x, env = parent.frame(), quoted = FALSE,
reactive <- function(
x,
env = deprecated(),
quoted = deprecated(),
...,
label = NULL,
domain = getDefaultReactiveDomain(),
@@ -987,20 +991,19 @@ reactive <- function(x, env = parent.frame(), quoted = FALSE,
{
check_dots_empty()
x <- getQuosure(x, env, quoted)
fun <- as_function(x)
# as_function returns a function that takes `...`. We need one that takes no
# args.
formals(fun) <- list()
q <- enquo0(x)
q <- sustainEnvAndQuotedInternal(q, x, env, quoted)
fun <- quoToSimpleFunction(q)
# Attach a label and a reference to the original user source for debugging
label <- exprToLabel(get_expr(x), "reactive", label)
q_expr <- quo_get_expr(q)
label <- exprToLabel(q_expr, "reactive", label)
o <- Observable$new(fun, label, domain, ..stacktraceon = ..stacktraceon)
structure(
o$getValue,
observable = o,
cacheHint = list(userExpr = zap_srcref(get_expr(x))),
cacheHint = list(userExpr = zap_srcref(q_expr)),
class = c("reactiveExpr", "reactive", "function")
)
}
@@ -1325,10 +1328,10 @@ Observer <- R6Class(
#'
#' @param x An expression (quoted or unquoted). Any return value will be
#' ignored.
#' @param env The parent environment for the reactive expression. By default,
#' @param env TODO-barret docs; The parent environment for the reactive expression. By default,
#' this is the calling environment, the same as when defining an ordinary
#' non-reactive expression.
#' @param quoted Is the expression quoted? By default, this is `FALSE`.
#' @param quoted TODO-barret docs; Is the expression quoted? By default, this is `FALSE`.
#' This is useful when you want to use an expression that is stored in a
#' variable; to do so, it must be quoted with `quote()`.
#' @param label A label for the observer, useful for debugging.
@@ -1383,6 +1386,7 @@ Observer <- R6Class(
#' }
#'
#' @examples
#' # TODO-barret docs; examples are outdated
#' values <- reactiveValues(A=1)
#'
#' obsB <- observe({
@@ -1400,7 +1404,10 @@ Observer <- R6Class(
#' # are at the console, you can force a flush with flushReact()
#' shiny:::flushReact()
#' @export
observe <- function(x, env = parent.frame(), quoted = FALSE,
observe <- function(
x,
env = deprecated(),
quoted = deprecated(),
...,
label = NULL,
suspended = FALSE,
@@ -1411,14 +1418,12 @@ observe <- function(x, env = parent.frame(), quoted = FALSE,
{
check_dots_empty()
x <- getQuosure(x, env, quoted)
fun <- as_function(x)
# as_function returns a function that takes `...`. We need one that takes no
# args.
formals(fun) <- list()
q <- enquo0(x)
q <- sustainEnvAndQuotedInternal(q, x, env, quoted)
fun <- quoToSimpleFunction(q)
if (is.null(label)) {
label <- sprintf('observe(%s)', paste(deparse(get_expr(x)), collapse='\n'))
label <- sprintf('observe(%s)', paste(deparse(quo_get_expr(q)), collapse='\n'))
}
o <- Observer$new(
@@ -2146,17 +2151,17 @@ maskReactiveContext <- function(expr) {
#' scope.
#' @param event.env The parent environment for `eventExpr`. By default,
#' this is the calling environment.
#' @param event.quoted Is the `eventExpr` expression quoted? By default,
#' @param event.quoted TODO-barret docs; Is the `eventExpr` expression quoted? By default,
#' this is `FALSE`. This is useful when you want to use an expression
#' that is stored in a variable; to do so, it must be quoted with
#' `quote()`.
#' @param handler.env The parent environment for `handlerExpr`. By default,
#' @param handler.env TODO-barret docs; The parent environment for `handlerExpr`. By default,
#' this is the calling environment.
#' @param handler.quoted Is the `handlerExpr` expression quoted? By
#' @param handler.quoted TODO-barret docs; Is the `handlerExpr` expression quoted? By
#' default, this is `FALSE`. This is useful when you want to use an
#' expression that is stored in a variable; to do so, it must be quoted with
#' `quote()`.
#' @param value.env The parent environment for `valueExpr`. By default,
#' @param value.env TODO-barret docs; The parent environment for `valueExpr`. By default,
#' this is the calling environment.
#' @param value.quoted Is the `valueExpr` expression quoted? By default,
#' this is `FALSE`. This is useful when you want to use an expression
@@ -2265,8 +2270,8 @@ maskReactiveContext <- function(expr) {
#' }
#' @export
observeEvent <- function(eventExpr, handlerExpr,
event.env = parent.frame(), event.quoted = FALSE,
handler.env = parent.frame(), handler.quoted = FALSE,
event.env = deprecated(), event.quoted = deprecated(),
handler.env = deprecated(), handler.quoted = deprecated(),
...,
label = NULL, suspended = FALSE, priority = 0,
domain = getDefaultReactiveDomain(), autoDestroy = TRUE,
@@ -2274,15 +2279,17 @@ observeEvent <- function(eventExpr, handlerExpr,
{
check_dots_empty()
eventExpr <- getQuosure(eventExpr, event.env, event.quoted)
handlerExpr <- getQuosure(handlerExpr, handler.env, handler.quoted)
eventQ <- enquo0(eventExpr)
handlerQ <- enquo0(handlerExpr)
eventQ <- sustainEnvAndQuotedInternal(eventQ, eventExpr, event.env, event.quoted)
handlerQ <- sustainEnvAndQuotedInternal(handlerQ, handlerExpr, handler.env, handler.quoted)
if (is.null(label)) {
label <- sprintf('observeEvent(%s)', paste(deparse(get_expr(eventExpr)), collapse='\n'))
label <- sprintf('observeEvent(%s)', paste(deparse(get_expr(eventQ)), collapse='\n'))
}
handler <- inject(observe(
!!handlerExpr,
!!handlerQ,
label = label,
suspended = suspended,
priority = priority,
@@ -2296,7 +2303,7 @@ observeEvent <- function(eventExpr, handlerExpr,
ignoreInit = ignoreInit,
once = once,
label = label,
!!eventExpr,
!!eventQ,
x = handler
))
@@ -2306,27 +2313,29 @@ observeEvent <- function(eventExpr, handlerExpr,
#' @rdname observeEvent
#' @export
eventReactive <- function(eventExpr, valueExpr,
event.env = parent.frame(), event.quoted = FALSE,
value.env = parent.frame(), value.quoted = FALSE,
event.env = deprecated(), event.quoted = deprecated(),
value.env = deprecated(), value.quoted = deprecated(),
...,
label = NULL, domain = getDefaultReactiveDomain(),
ignoreNULL = TRUE, ignoreInit = FALSE)
{
check_dots_empty()
eventExpr <- getQuosure(eventExpr, event.env, event.quoted)
valueExpr <- getQuosure(valueExpr, value.env, value.quoted)
eventQ <- enquo0(eventExpr)
valueQ <- enquo0(valueExpr)
eventQ <- sustainEnvAndQuotedInternal(eventQ, eventExpr, event.env, event.quoted)
valueQ <- sustainEnvAndQuotedInternal(valueQ, valueExpr, value.env, value.quoted)
if (is.null(label)) {
label <- sprintf('eventReactive(%s)', paste(deparse(get_expr(eventExpr)), collapse='\n'))
label <- sprintf('eventReactive(%s)', paste(deparse(get_expr(eventQ)), collapse='\n'))
}
invisible(inject(bindEvent(
ignoreNULL = ignoreNULL,
ignoreInit = ignoreInit,
label = label,
!!eventExpr,
x = reactive(!!valueExpr, domain = domain, label = label)
!!eventQ,
x = reactive(!!valueQ, domain = domain, label = label)
)))
}

View File

@@ -46,8 +46,8 @@
#' decorative images.
#' @param ... Arguments to be passed through to [grDevices::png()].
#' These can be used to set the width, height, background color, etc.
#' @param env The environment in which to evaluate `expr`.
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
#' @param env TODO-barret docs; The environment in which to evaluate `expr`.
#' @param quoted TODO-barret docs; Is `expr` a quoted expression (with `quote()`)? This
#' is useful if you want to save an expression in a variable.
#' @param execOnResize If `FALSE` (the default), then when a plot is
#' resized, Shiny will *replay* the plot drawing commands with
@@ -61,14 +61,15 @@
#' @export
renderPlot <- function(expr, width = 'auto', height = 'auto', res = 72, ...,
alt = NA,
env = parent.frame(), quoted = FALSE,
env = deprecated(), quoted = deprecated(),
execOnResize = FALSE, outputArgs = list()
) {
expr <- getQuosure(expr, env, quoted)
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
# This ..stacktraceon is matched by a ..stacktraceoff.. when plotFunc
# is called
func <- quoToFunction(expr, "renderPlot", ..stacktraceon = TRUE)
func <- quoToFunction(q, "renderPlot", ..stacktraceon = TRUE)
args <- list(...)
@@ -186,7 +187,7 @@ renderPlot <- function(expr, width = 'auto', height = 'auto', res = 72, ...,
outputFunc,
renderFunc,
outputArgs,
cacheHint = list(userExpr = get_expr(expr), res = res)
cacheHint = list(userExpr = get_expr(q), res = res)
)
class(markedFunc) <- c("shiny.renderPlot", class(markedFunc))
markedFunc

View File

@@ -42,8 +42,8 @@
#' (i.e. they either evaluate to `NA` or `NaN`).
#' @param ... Arguments to be passed through to [xtable::xtable()]
#' and [xtable::print.xtable()].
#' @param env The environment in which to evaluate `expr`.
#' @param quoted Is `expr` a quoted expression (with `quote()`)?
#' @param env TODO-barret docs; The environment in which to evaluate `expr`.
#' @param quoted TODO-barret docs; Is `expr` a quoted expression (with `quote()`)?
#' This is useful if you want to save an expression in a variable.
#' @param outputArgs A list of arguments to be passed through to the
#' implicit call to [tableOutput()] when `renderTable` is
@@ -71,11 +71,12 @@ renderTable <- function(expr, striped = FALSE, hover = FALSE,
width = "auto", align = NULL,
rownames = FALSE, colnames = TRUE,
digits = NULL, na = "NA", ...,
env = parent.frame(), quoted = FALSE,
env = deprecated(), quoted = deprecated(),
outputArgs=list())
{
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderTable")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderTable")
if (!is.function(spacing)) spacing <- match.arg(spacing)

View File

@@ -2,7 +2,7 @@
## usethis namespace: start
## usethis namespace: end
#' @importFrom lifecycle deprecated
#' @importFrom lifecycle deprecated is_present
#' @importFrom grDevices dev.set dev.cur
#' @importFrom fastmap fastmap
#' @importFrom promises %...!%
@@ -11,11 +11,13 @@
#' promise promise_resolve promise_reject is.promising
#' as.promise
#' @importFrom rlang
#' quo enquo as_function get_expr get_env new_function enquos
#' quo enquo enquo0 as_function get_expr get_env new_function enquos
#' eval_tidy expr pairlist2 new_quosure enexpr as_quosure is_quosure inject
#' quo_set_env quo_set_expr quo_get_expr
#' enquos0 zap_srcref %||% is_na
#' is_false list2
#' missing_arg is_missing maybe_missing
#' quo_is_missing fn_fmls<- fn_body<-
#' @importFrom ellipsis
#' check_dots_empty check_dots_unnamed
#' @import htmltools

View File

@@ -160,13 +160,12 @@ print.shiny.render.function <- function(x, ...) {
#' @return An annotated render function, ready to be assigned to an
#' `output` slot.
#'
#' @seealso [getQuosure()], [quoToFunction()], [markRenderFunction()].
#' @seealso [quoToFunction()], [markRenderFunction()], [rlang::enquo()].
#'
#' @examples
#' # A very simple render function
#' renderTriple <- function(expr) {
#' expr <- getQuosure(expr)
#' func <- quoToFunction(expr)
#' func <- quoToFunction(rlang::enquo0(expr))
#'
#' createRenderFunction(
#' func,
@@ -321,8 +320,8 @@ markOutputAttrs <- function(renderFunc, snapshotExclude = NULL,
#' the output, see [plotPNG()].
#'
#' @param expr An expression that returns a list.
#' @param env The environment in which to evaluate `expr`.
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
#' @param env TODO-barret docs; The environment in which to evaluate `expr`.
#' @param quoted TODO-barret docs; Is `expr` a quoted expression (with `quote()`)? This
#' is useful if you want to save an expression in a variable.
#' @param deleteFile Should the file in `func()$src` be deleted after
#' it is sent to the client browser? Generally speaking, if the image is a
@@ -402,11 +401,12 @@ markOutputAttrs <- function(renderFunc, snapshotExclude = NULL,
#'
#' shinyApp(ui, server)
#' }
renderImage <- function(expr, env=parent.frame(), quoted=FALSE,
renderImage <- function(expr, env = deprecated(), quoted = deprecated(),
deleteFile, outputArgs=list())
{
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderImage")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderImage")
# missing() must be used directly within the function with the given arg
if (missing(deleteFile)) {
@@ -528,8 +528,8 @@ isTemp <- function(path, tempDir = tempdir(), mustExist) {
#' function return [invisible()].
#'
#' @param expr An expression to evaluate.
#' @param env The environment in which to evaluate `expr`. For expert use only.
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
#' @param env TODO-barret docs; The environment in which to evaluate `expr`. For expert use only.
#' @param quoted TODO-barret docs; Is `expr` a quoted expression (with `quote()`)? This
#' is useful if you want to save an expression in a variable.
#' @param width Width of printed output.
#' @param outputArgs A list of arguments to be passed through to the implicit
@@ -538,11 +538,12 @@ isTemp <- function(path, tempDir = tempdir(), mustExist) {
#'
#' @example res/text-example.R
#' @export
renderPrint <- function(expr, env = parent.frame(), quoted = FALSE,
renderPrint <- function(expr, env = deprecated(), quoted = deprecated(),
width = getOption('width'), outputArgs=list())
{
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderPrint")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderPrint")
# Set a promise domain that sets the console width
# and captures output
@@ -574,7 +575,7 @@ renderPrint <- function(expr, env = parent.frame(), quoted = FALSE,
outputArgs,
cacheHint = list(
label = "renderPrint",
origUserExpr = get_expr(expr)
origUserExpr = get_expr(q)
)
)
}
@@ -624,11 +625,12 @@ createRenderPrintPromiseDomain <- function(width) {
#' element.
#' @export
#' @rdname renderPrint
renderText <- function(expr, env=parent.frame(), quoted=FALSE,
renderText <- function(expr, env = deprecated(), quoted = deprecated(),
outputArgs=list(), sep=" ") {
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderText")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderText")
createRenderFunction(
func,
@@ -649,8 +651,8 @@ renderText <- function(expr, env=parent.frame(), quoted=FALSE,
#'
#' @param expr An expression that returns a Shiny tag object, [HTML()],
#' or a list of such objects.
#' @param env The environment in which to evaluate `expr`.
#' @param quoted Is `expr` a quoted expression (with `quote()`)? This
#' @param env TODO-barret docs; The environment in which to evaluate `expr`.
#' @param quoted TODO-barret docs; Is `expr` a quoted expression (with `quote()`)? This
#' is useful if you want to save an expression in a variable.
#' @param outputArgs A list of arguments to be passed through to the implicit
#' call to [uiOutput()] when `renderUI` is used in an
@@ -677,11 +679,12 @@ renderText <- function(expr, env=parent.frame(), quoted=FALSE,
#' shinyApp(ui, server)
#' }
#'
renderUI <- function(expr, env = parent.frame(), quoted = FALSE,
renderUI <- function(expr, env = deprecated(), quoted = deprecated(),
outputArgs = list())
{
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderUI")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderUI")
createRenderFunction(
func,
@@ -760,6 +763,8 @@ downloadHandler <- function(filename, content, contentType=NA, outputArgs=list()
#' Table output with the JavaScript DataTables library
#'
#' @description
#' `r lifecycle::badge("superseded")` Please use [`DT::renderDataTable()`]. (Shiny 0.11.1)
#'
#' Makes a reactive version of the given function that returns a data frame (or
#' matrix), which will be rendered with the [DataTables](https://datatables.net)
#' library. Paging, searching, filtering, and sorting can be done on the R side
@@ -823,7 +828,7 @@ downloadHandler <- function(filename, content, contentType=NA, outputArgs=list()
#' }
renderDataTable <- function(expr, options = NULL, searchDelay = 500,
callback = 'function(oTable) {}', escape = TRUE,
env = parent.frame(), quoted = FALSE,
env = deprecated(), quoted = deprecated(),
outputArgs=list())
{
@@ -834,8 +839,9 @@ renderDataTable <- function(expr, options = NULL, searchDelay = 500,
)
}
expr <- getQuosure(expr, env, quoted)
func <- quoToFunction(expr, "renderDataTable")
q <- enquo0(expr)
q <- sustainEnvAndQuotedInternal(q, expr, env, quoted)
func <- quoToFunction(q, "renderDataTable")
renderFunc <- function(shinysession, name, ...) {
if (is.function(options)) options <- options()

View File

@@ -68,21 +68,55 @@ formalsAndBody <- function(x) {
#'
#' @export
quoToFunction <- function(q,
label = deparse(sys.call(-1)[[1]]),
label = sys.call(-1)[[1]],
..stacktraceon = FALSE)
{
q <- as_quosure(q)
func <- as_function(q)
# as_function returns a function that takes `...`. We want one that takes no
func <- quoToSimpleFunction(q)
wrapFunctionLabel(func, updateFunctionLabel(label), ..stacktraceon = ..stacktraceon)
}
updateFunctionLabel <- function(label) {
# browser()
if (all(is.language(label))) {
# Prevent immediately invoked functions like as.language(a()())
if (is.language(label) && length(label) > 1) {
return("wrappedFunction")
}
label <- deparse(label, width.cutoff = 500L)
}
label <- as.character(label)
# Prevent function calls that are over one line; (Assignments are hard to perform)
# Prevent immediately invoked functions like "a()()"
if (length(label) > 1 || grepl("(", label, fixed = TRUE)) {
return("wrappedFunction")
}
if (label == "NULL") {
return("wrappedFunction")
}
label
}
quoToSimpleFunction <- function(q) {
# Should not use `new_function(list(), get_expr(q), get_env(q))` as extra logic
# is done by rlang to convert the quosure to a function within `as_function(q)`
fun <- as_function(q)
# If the quosure is empty, then the returned function can not be called.
# https://github.com/r-lib/rlang/issues/1244
if (quo_is_missing(q)) {
fn_body(fun) <- quote({})
return(fun)
}
# as_function returns a function that takes `...`. We need one that takes no
# args.
formals(func) <- list()
wrapFunctionLabel(func, label, ..stacktraceon = ..stacktraceon)
fn_fmls(fun) <- list()
fun
}
#' Convert expressions and quosures to functions
#'
#' `getQuosure()` and `quoToFunction()` are meant to be used together in a
#' `handleEnvAndQuoted()` and `quoToFunction()` are meant to be used together in a
#' `render` function, to capture user expressions or quosures and convert them
#' to functions. They are meant to replace the older functions
#' [installExprFunction()] and [exprToFunction()] (although those will continue
@@ -111,8 +145,7 @@ quoToFunction <- function(q,
#' # This is something that toolkit authors will do.
#' renderTriple <- function(expr) {
#' # Convert expr to a quosure, and then to a function
#' expr <- getQuosure(expr)
#' func <- quoToFunction(expr)
#' func <- quoToFunction(rlang::enquo0(expr))
#'
#' # Wrap up func, with another function which takes the value of func()
#' # and modifies it.
@@ -167,146 +200,157 @@ quoToFunction <- function(q,
#'
#' @rdname quoToFunction
#' @export
getQuosure <- function(x, env, quoted) {
if (!any(c("env", "quoted") %in% names(match.call()))) {
# This code path is used when `getQuosure(x)` is called.
#
# It duplicates some of the code in the `else` code path below, but this is
# actually clearer and simpler than setting up the logic go through a single
# code path.
x <- eval(substitute(substitute(x)), parent.frame())
# At this point, x can be a quosure if rlang::inject() is used, but the
# typical case is that x is not a quosure.
if (!is_quosure(x)) {
x <- new_quosure(x, env = parent.frame(2))
}
} else {
# This code path is used when `getQuosure(x, env, quoted)` is called.
#
# Much of the complexity is handling old-style metaprogramming cases. The
# code below is more complicated because it needs to look at unevaluated
# expressions in the _calling_ function. If this code were put directly in
# the calling function, it would look like this:
#
# if (!missing(env) || !missing(quoted)) {
# deprecatedEnvQuotedMessage()
# if (!quoted) x <- substitute(x)
# x <- new_quosure(x, env)
#
# } else {
# x <- substitute(x)
# if (!is_quosure(x)) {
# x <- new_quosure(x, env = parent.frame())
# }
# }
# TRUE if either the immediate caller (the renderXX function) or caller two
# frames back (the user's call to `renderXX()` passed in an environment.)
called_with_env <-
!missing(env) ||
!eval(substitute(missing(env)), parent.frame())
# Same as above, but with `quoted`
called_with_quoted <-
!missing(quoted) ||
!eval(substitute(missing(quoted)), parent.frame())
if (called_with_env || called_with_quoted) {
deprecatedEnvQuotedMessage()
if (!quoted) {
x <- eval(substitute(substitute(x)), parent.frame())
}
x <- new_quosure(x, env)
sustainEnvAndQuoted <- function(q, x, env, quoted) {
## To avoid possible boilerplate with `deprecated()`...
env_is_present <-
if (!is_present(env)) {
# If `env` is `deprecated()`, set to the parent frame of the caller
env <- parent.frame(2)
FALSE # env_is_present
} else {
x <- eval(substitute(substitute(x)), parent.frame())
# At this point, x can be a quosure if rlang::inject() is used, but the
# typical case is that x is not a quosure.
if (!is_quosure(x)) {
x <- new_quosure(x, env = parent.frame(2))
}
# check of parent frame had a missing _`env`_ param
eval(substitute(!missing(env)), parent.frame())
}
quoted_is_present <-
if (!is_present(quoted)) {
# If `quoted` is deprecated(), set to `FALSE`
quoted <- FALSE
}
FALSE # quoted_is_present
} else {
# check of parent frame had a missing _`quoted`_ param
eval(substitute(!missing(quoted)), parent.frame())
}
##
# This is TRUE when the user called `inject(renderFoo(!!q))`
x_is_quosure <- is_quosure(eval(substitute(substitute(x)), parent.frame()))
x
sustainEnvAndQuoted_(
q = q, env = env, quoted = quoted,
env_is_present = env_is_present,
quoted_is_present = quoted_is_present,
x_is_quosure = x_is_quosure,
verbose = TRUE
)
}
# `getQuosure()` is to be called from functions like `reactive()`, `observe()`,
# `sustainEnvAndQuotedInternal()` is to be called from functions like `reactive()`, `observe()`,
# and the various render functions. It handles the following cases:
# - The typical case where x is an unquoted expression, and `env` and `quoted`
# are not used.
# - New-style metaprogramming cases, where rlang::inject() is used to inline a
# quosure into the AST, as in `inject(reactive(!!x))`.
# - Old-style metaprogramming cases, where `env` and/or `quoted` are used.
# Same as `sustainEnvAndQuoted()`, but quiet
# Under assumption that `env = deprecated()` and `quoted = deprecated()`
sustainEnvAndQuotedInternal <- function(q, x, env, quoted) {
## Can leverage the fact that we know all `env` and `quoted` args are set to `deprecated()`
env_is_present <- is_present(env) # eval(substitute(!missing(env)), parent.frame())
quoted_is_present <- is_present(quoted) # eval(substitute(!missing(quoted)), parent.frame())
x_is_quosure <- is_quosure(eval(substitute(substitute(x)), parent.frame()))
if (!env_is_present) env <- parent.frame(2)
if (!quoted_is_present) quoted <- FALSE
sustainEnvAndQuoted_(
q = q,
env = env,
quoted = quoted,
env_is_present = env_is_present,
quoted_is_present = quoted_is_present,
x_is_quosure = x_is_quosure,
verbose = FALSE
)
}
# # Reaches up three calls to check if env / quoted were provided.
# # Can not leverage `is_present()` logic like in `sustainEnvAndQuotedInternal()`
# # This is similar to `sustainEnvAndQuotedInternal()`, but it is intended to be used only by
# # `installExprFunction()` and `exprToFunction()`. Whereas `sustainEnvAndQuotedInternal()` reaches
# # 2 calls back to find the expression passed in, this function reaches 3 calls
# # back, and it is only used internally within Shiny.
# sustainEnvAndQuoted3Internal <- function(q, x, env, quoted) {
# ## To avoid possible boilerplate with `deprecated()`...
# env_is_present <-
# if (!is_present(env)) {
# # If `env` is `deprecated()`, set to the parent frame of the caller
# env <- parent.frame(3)
# This is similar to `getQuosure()`, but it is intended to be used only by
# `installExprFunction()` and `exprToFunction()`. Whereas `getQuosure()` reaches
# 2 calls back to find the expression passed in, this function reaches 3 calls
# back, and it is only used internally within Shiny.
getQuosure3 <- function(x, env, quoted) {
if (!any(c("env", "quoted") %in% names(match.call(sys.function(-1), sys.call(-1))))) {
# This code path is used when `getQuosure(x)` is called.
# FALSE # env_is_present
# } else {
# # check of parent frame of the caller had a missing _`env`_ param
# eval(eval(substitute(substitute(!missing(env))), parent.frame()), parent.frame(2))
# }
# quoted_is_present <-
# if (!is_present(quoted)) {
# # If `quoted` is deprecated(), set to `FALSE`
# quoted <- FALSE
x <- eval(eval(substitute(substitute(substitute(x))), parent.frame()), parent.frame(2))
# FALSE # quoted_is_present
# } else {
# # check of parent frame had a missing _`quoted`_ param
# eval(eval(substitute(substitute(!missing(quoted))), parent.frame()), parent.frame(2))
# }
# ##
# x_is_quosure <- is_quosure(eval(eval(substitute(substitute(x)), parent.frame()), parent.frame(2)))
# At this point, x can be a quosure if rlang::inject() is used, but the
# typical case is that x is not a quosure.
if (!is_quosure(x)) {
x <- new_quosure(x, env = parent.frame(3))
# sustainEnvAndQuoted_(
# q = q, env = env, quoted = quoted,
# env_is_present = env_is_present,
# quoted_is_present = quoted_is_present,
# x_is_quosure = x_is_quosure,
# verbose = FALSE
# )
# }
sustainEnvAndQuoted_ <- function(
q, env, quoted,
env_is_present, quoted_is_present, x_is_quosure,
verbose = TRUE
) {
if (
env_is_present ||
quoted_is_present
) {
if (verbose) deprecatedEnvQuotedMessage()
# browser()
# Can't have x be a quosure and use env/quoted.
if (x_is_quosure) {
stop(
"Can not use a `quosure()` with either the `env` or `quoted` parameters.\n",
"Please alter your quosure before the shiny function call and ",
"do not supply any `env` or `quoted` parameters.\n",
"To use your `quosure()` object directly, use `inject()` mixed with `!!`.\n",
"Ex: `inject(renderText(!!q))`"
)
}
} else {
# This code path is used when `getQuosure3(x, env, quoted)` is
# called.
# TRUE if either the immediate caller (exprToFunction or
# installExprFunction) or caller two frames back (the user's call to
# `renderXX()` passed in an environment.)
called_with_env <-
!eval(substitute(missing(env)), parent.frame()) ||
!eval(eval(substitute(substitute(missing(env))), parent.frame()), parent.frame(2))
# Same as above, but with `quoted`
called_with_quoted <-
!eval(substitute(missing(quoted)), parent.frame()) ||
!eval(eval(substitute(substitute(missing(quoted))), parent.frame()), parent.frame(2))
if (called_with_env || called_with_quoted) {
deprecatedEnvQuotedMessage()
if (!quoted) {
x <- eval(eval(substitute(substitute(substitute(x))), parent.frame()), parent.frame(2))
}
x <- new_quosure(x, env)
} else {
x <- eval(eval(substitute(substitute(substitute(x))), parent.frame()), parent.frame(2))
# At this point, x can be a quosure if rlang::inject() is used, but the
# typical case is that x is not a quosure.
if (!is_quosure(x)) {
x <- new_quosure(x, env = parent.frame(3))
}
# In this code path, x is NOT a literal quosure object
if (isTRUE(quoted)) {
q <- quo_set_expr(q, eval_tidy(q))
}
if (env_is_present) {
q <- quo_set_env(q, env)
}
}
x
q
}
#' Convert an expression to a function
#'
#' This is to be called from another function, because it will attempt to get
#' an unquoted expression from two calls back. Note: as of Shiny 1.7.0, it is
#' recommended to use [getQuosure()] and [quoToFunction()] instead of
#' @description
#' `r lifecycle::badge("superseded")` Please see [`quoToFunction()`] for updated usage. (Shiny 1.7.0)
#'
#' Note: as of Shiny 1.7.0, it is
#' recommended to use [`quoToFunction()`] (and if necessary, [`sustainEnvAndQuoted()`]) instead of
#' `exprToFunction()` and `installExprFunction()`. See the examples for
#' information on how to migrate to `getQuosure()` and `quoToFunction()`.
#'
#' This is to be called from another function, because it will attempt to get
#' an unquoted expression from two calls back.
#'
#' For `exprToFunction()`:
#' If `expr` is a quoted expression, then this just converts it to a function.
#' If `expr` is a function, then this simply returns expr (and prints a
@@ -337,7 +381,7 @@ getQuosure3 <- function(x, env, quoted) {
#' # The old way of converting the expression to a quosure, with exprToFunction()
#' renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
#' # Convert expr to a function
#' func <- shiny::exprToFunction(expr, env, quoted)
#' func <- exprToFunction(expr, env, quoted)
#'
#' function() {
#' value <- func()
@@ -363,7 +407,8 @@ getQuosure3 <- function(x, env, quoted) {
#' # backward compatibility
#' renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
#' # Convert expr to a quosure, and then to a function
#' q <- getQuosure(expr, env, quoted)
#' q <- rlang::enquo0(expr)
#' q <- sustainEnvAndQuoted(q, expr, env, quoted)
#' func <- quoToFunction(q)
#'
#' function() {
@@ -378,8 +423,7 @@ getQuosure3 <- function(x, env, quoted) {
#' # it discards `env` and `quoted`, for simplicity.
#' renderTriple <- function(expr) {
#' # Convert expr to a quosure, and then to a function
#' q <- getQuosure(expr)
#' func <- quoToFunction(q)
#' func <- quoToFunction(rlang::enquo0(expr))
#'
#' function() {
#' value <- func()
@@ -407,8 +451,12 @@ getQuosure3 <- function(x, env, quoted) {
#' # "text, text, text"
#' @export
exprToFunction <- function(expr, env = parent.frame(), quoted = FALSE) {
expr <- getQuosure3(expr, env, quoted)
new_function(list(), get_expr(expr), get_env(expr))
if (!quoted) {
expr <- eval(substitute(substitute(expr)), parent.frame())
}
# expr is a quoted expression
new_function(list(), body = expr, env = env)
}
#' @rdname exprToFunction
@@ -425,20 +473,22 @@ exprToFunction <- function(expr, env = parent.frame(), quoted = FALSE) {
installExprFunction <- function(expr, name, eval.env = parent.frame(2),
quoted = FALSE,
assign.env = parent.frame(1),
label = deparse(sys.call(-1)[[1]]),
label = sys.call(-1)[[1]],
wrappedWithLabel = TRUE,
..stacktraceon = FALSE) {
if (!quoted) {
quoted <- TRUE
expr <- eval(substitute(substitute(expr)), parent.frame())
}
expr <- getQuosure3(expr, eval.env, quoted)
func <- new_function(list(), get_expr(expr), get_env(expr))
func <- exprToFunction(expr, eval.env, quoted)
if (length(label) > 1) {
# Just in case the deparsed code is more complicated than we imagine. If we
# have a label with length > 1 it causes warnings in wrapFunctionLabel.
label <- paste0(label, collapse = "\n")
}
if (wrappedWithLabel) {
func <- wrapFunctionLabel(func, label, ..stacktraceon = ..stacktraceon)
func <- wrapFunctionLabel(func, updateFunctionLabel(label), ..stacktraceon = ..stacktraceon)
} else {
registerDebugHook(name, assign.env, label)
}

View File

@@ -1,3 +1,3 @@
/*! shiny 1.6.0.9021 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function(){var t="ws:";window.location.protocol==="https:"&&(t="wss:");var o=window.location.pathname;/\/$/.test(o)||(o+="/");o+="autoreload/";var n=new WebSocket(t+"//"+window.location.host+o);n.onmessage=function(a){a.data==="autoreload"&&window.location.reload()};})();
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LWF1dG9yZWxvYWQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIGVzbGludC1kaXNhYmxlIHVuaWNvcm4vZmlsZW5hbWUtY2FzZSAqL1xudmFyIHByb3RvY29sID0gXCJ3czpcIjtcbmlmICh3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHByb3RvY29sID0gXCJ3c3M6XCI7XG52YXIgZGVmYXVsdFBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG5pZiAoIS9cXC8kLy50ZXN0KGRlZmF1bHRQYXRoKSkgZGVmYXVsdFBhdGggKz0gXCIvXCI7XG5kZWZhdWx0UGF0aCArPSBcImF1dG9yZWxvYWQvXCI7XG52YXIgd3MgPSBuZXcgV2ViU29ja2V0KHByb3RvY29sICsgXCIvL1wiICsgd2luZG93LmxvY2F0aW9uLmhvc3QgKyBkZWZhdWx0UGF0aCk7XG5cbndzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICBpZiAoZXZlbnQuZGF0YSA9PT0gXCJhdXRvcmVsb2FkXCIpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG4gIH1cbn07XG5cbmV4cG9ydCB7fTsiXSwKICAibWFwcGluZ3MiOiAiO1lBQ0EsR0FBSSxHQUFXLE1BQ2YsQUFBSSxPQUFPLFNBQVMsV0FBYSxVQUFVLEdBQVcsUUFDdEQsR0FBSSxHQUFjLE9BQU8sU0FBUyxTQUNsQyxBQUFLLE1BQU0sS0FBSyxJQUFjLElBQWUsS0FDN0MsR0FBZSxjQUNmLEdBQUksR0FBSyxHQUFJLFdBQVUsRUFBVyxLQUFPLE9BQU8sU0FBUyxLQUFPLEdBRWhFLEVBQUcsVUFBWSxTQUFVLEVBQU8sQ0FDOUIsQUFBSSxFQUFNLE9BQVMsY0FDakIsT0FBTyxTQUFTIiwKICAibmFtZXMiOiBbXQp9Cg==

View File

@@ -1,2 +1,2 @@
/*! shiny 1.6.0.9021 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
#showcase-well{border-radius:0}.shiny-code{background-color:#fff;margin-bottom:0}.shiny-code code{font-family:Menlo,Consolas,"Courier New",monospace}.shiny-code-container{margin-top:20px;clear:both}.shiny-code-container h3{display:inline;margin-right:15px}.showcase-header{font-size:16px;font-weight:normal}.showcase-code-link{text-align:right;padding:15px}#showcase-app-container{vertical-align:top}#showcase-code-tabs{margin-right:15px}#showcase-code-tabs pre{border:none;line-height:1em}#showcase-code-tabs .nav{margin-bottom:0}#showcase-code-tabs ul{margin-bottom:0}#showcase-code-tabs .tab-content{border-style:solid;border-color:#e5e5e5;border-width:0px 1px 1px 1px;overflow:auto;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#showcase-app-code{width:100%}#showcase-code-position-toggle{float:right}#showcase-sxs-code{padding-top:20px;vertical-align:top}.showcase-code-license{display:block;text-align:right}#showcase-code-content pre{background-color:#fff}

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
/*! shiny 1.6.0.9021 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function(){var a=eval;window.addEventListener("message",function(i){var e=i.data;e.code&&a(e.code)});})();
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvc3JjL3V0aWxzL2V2YWwudHMiLCAiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LXRlc3Rtb2RlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvL2VzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsXG4vL3RsL2RyO1xuLy8gKiBEaXJlY3QgdXNhZ2Ugb2YgYGV2YWwoXCJ4XCIpYCBpcyBiYWQgd2l0aCBidW5kbGVkIGNvZGUuXG4vLyAqIEluc3RlYWQsIHVzZSBpbmRpcmVjdCBjYWxscyB0byBgZXZhbGAgc3VjaCBhcyBgaW5kaXJlY3RFdmFsKFwieFwiKWBcbi8vICAgKiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuLy8gPiBUaGlzIGlzIGtub3duIGFzIFwiaW5kaXJlY3QgZXZhbFwiIGJlY2F1c2UgZXZhbCBpcyBub3QgYmVpbmcgY2FsbGVkIGRpcmVjdGx5LCBhbmQgc28gZG9lcyBub3QgdHJpZ2dlciB0aGUgZ3JhbW1hdGljYWwgc3BlY2lhbCBjYXNlIGZvciBkaXJlY3QgZXZhbCBpbiB0aGUgSmF2YVNjcmlwdCBWTS4gWW91IGNhbiBjYWxsIGluZGlyZWN0IGV2YWwgdXNpbmcgYW55IHN5bnRheCBhdCBhbGwgZXhjZXB0IGZvciBhbiBleHByZXNzaW9uIG9mIHRoZSBleGFjdCBmb3JtIGV2YWwoJ3gnKS4gRm9yIGV4YW1wbGUsIHZhciBldmFsMiA9IGV2YWw7IGV2YWwyKCd4JykgYW5kIFtldmFsXVswXSgneCcpIGFuZCB3aW5kb3cuZXZhbCgneCcpIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbi8vID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxudmFyIGluZGlyZWN0RXZhbCA9IGV2YWw7XG5leHBvcnQgeyBpbmRpcmVjdEV2YWwgfTsiLCAiLyogZXNsaW50LWRpc2FibGUgdW5pY29ybi9maWxlbmFtZS1jYXNlICovXG5pbXBvcnQgeyBpbmRpcmVjdEV2YWwgfSBmcm9tIFwiLi4vc3JjL3V0aWxzL2V2YWxcIjsgLy8gTGlzdGVuIGZvciBtZXNzYWdlcyBmcm9tIHBhcmVudCBmcmFtZS4gVGhpcyBmaWxlIGlzIG9ubHkgYWRkZWQgd2hlbiB0aGVcbi8vIHNoaW55LnRlc3Rtb2RlIG9wdGlvbiBpcyBUUlVFLlxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgdmFyIG1lc3NhZ2UgPSBlLmRhdGE7XG4gIGlmIChtZXNzYWdlLmNvZGUpIGluZGlyZWN0RXZhbChtZXNzYWdlLmNvZGUpO1xufSk7Il0sCiAgIm1hcHBpbmdzIjogIjtZQU9BLEdBQUksR0FBZSxLQ0huQixPQUFPLGlCQUFpQixVQUFXLFNBQVUsRUFBRyxDQUM5QyxHQUFJLEdBQVUsRUFBRSxLQUNoQixBQUFJLEVBQVEsTUFBTSxFQUFhLEVBQVEiLAogICJuYW1lcyI6IFtdCn0K

View File

@@ -1,4 +1,4 @@
/*! shiny 1.6.0.9021 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function() {
var __create = Object.create;
var __defProp = Object.defineProperty;
@@ -13263,7 +13263,7 @@
var windowShiny2;
function setShiny(windowShiny_) {
windowShiny2 = windowShiny_;
windowShiny2.version = "1.6.0.9021";
windowShiny2.version = "1.6.0.9022";
var _initInputBindings = initInputBindings(), inputBindings = _initInputBindings.inputBindings, fileInputBinding2 = _initInputBindings.fileInputBinding;
var _initOutputBindings = initOutputBindings(), outputBindings = _initOutputBindings.outputBindings;
setFileInputBinding(fileInputBinding2);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -68,8 +68,7 @@ for async computation via promises. It is recommended to use
\examples{
# A very simple render function
renderTriple <- function(expr) {
expr <- getQuosure(expr)
func <- quoToFunction(expr)
func <- quoToFunction(rlang::enquo0(expr))
createRenderFunction(
func,
@@ -88,5 +87,5 @@ r()
# [1] "20, 20, 20"
}
\seealso{
\code{\link[=getQuosure]{getQuosure()}}, \code{\link[=quoToFunction]{quoToFunction()}}, \code{\link[=markRenderFunction]{markRenderFunction()}}.
\code{\link[=quoToFunction]{quoToFunction()}}, \code{\link[=markRenderFunction]{markRenderFunction()}}, \code{\link[rlang:nse-defuse]{rlang::enquo()}}.
}

View File

@@ -13,7 +13,7 @@ installExprFunction(
eval.env = parent.frame(2),
quoted = FALSE,
assign.env = parent.frame(1),
label = deparse(sys.call(-1)[[1]]),
label = sys.call(-1)[[1]],
wrappedWithLabel = TRUE,
..stacktraceon = FALSE
)
@@ -40,13 +40,16 @@ the name of the calling function.}
\code{\link[=stacktrace]{stacktrace()}}.}
}
\description{
This is to be called from another function, because it will attempt to get
an unquoted expression from two calls back. Note: as of Shiny 1.7.0, it is
recommended to use \code{\link[=getQuosure]{getQuosure()}} and \code{\link[=quoToFunction]{quoToFunction()}} instead of
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} Please see \code{\link[=quoToFunction]{quoToFunction()}} for updated usage. (Shiny 1.7.0)
Note: as of Shiny 1.7.0, it is
recommended to use \code{\link[=quoToFunction]{quoToFunction()}} (and if necessary, \code{\link[=sustainEnvAndQuoted]{sustainEnvAndQuoted()}}) instead of
\code{exprToFunction()} and \code{installExprFunction()}. See the examples for
information on how to migrate to \code{getQuosure()} and \code{quoToFunction()}.
}
\details{
This is to be called from another function, because it will attempt to get
an unquoted expression from two calls back.
For \code{exprToFunction()}:
If \code{expr} is a quoted expression, then this just converts it to a function.
If \code{expr} is a function, then this simply returns expr (and prints a
@@ -71,7 +74,7 @@ function named \code{func} in the current environment.
# The old way of converting the expression to a quosure, with exprToFunction()
renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
# Convert expr to a function
func <- shiny::exprToFunction(expr, env, quoted)
func <- exprToFunction(expr, env, quoted)
function() {
value <- func()
@@ -97,7 +100,8 @@ renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
# backward compatibility
renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
# Convert expr to a quosure, and then to a function
q <- getQuosure(expr, env, quoted)
q <- rlang::enquo0(expr)
q <- sustainEnvAndQuoted(q, expr, env, quoted)
func <- quoToFunction(q)
function() {
@@ -112,8 +116,7 @@ renderTriple <- function(expr, env=parent.frame(), quoted=FALSE) {
# it discards `env` and `quoted`, for simplicity.
renderTriple <- function(expr) {
# Convert expr to a quosure, and then to a function
q <- getQuosure(expr)
func <- quoToFunction(q)
func <- quoToFunction(rlang::enquo0(expr))
function() {
value <- func()

View File

@@ -6,8 +6,8 @@
\usage{
observe(
x,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
...,
label = NULL,
suspended = FALSE,
@@ -21,11 +21,11 @@ observe(
\item{x}{An expression (quoted or unquoted). Any return value will be
ignored.}
\item{env}{The parent environment for the reactive expression. By default,
\item{env}{TODO-barret docs; The parent environment for the reactive expression. By default,
this is the calling environment, the same as when defining an ordinary
non-reactive expression.}
\item{quoted}{Is the expression quoted? By default, this is \code{FALSE}.
\item{quoted}{TODO-barret docs; Is the expression quoted? By default, this is \code{FALSE}.
This is useful when you want to use an expression that is stored in a
variable; to do so, it must be quoted with \code{quote()}.}
@@ -110,6 +110,7 @@ when the \link[=domains]{domain} that owns them ends (e.g. when a Shiny
session ends).
}
\examples{
# TODO-barret docs; examples are outdated
values <- reactiveValues(A=1)
obsB <- observe({

View File

@@ -8,10 +8,10 @@
observeEvent(
eventExpr,
handlerExpr,
event.env = parent.frame(),
event.quoted = FALSE,
handler.env = parent.frame(),
handler.quoted = FALSE,
event.env = deprecated(),
event.quoted = deprecated(),
handler.env = deprecated(),
handler.quoted = deprecated(),
...,
label = NULL,
suspended = FALSE,
@@ -26,10 +26,10 @@ observeEvent(
eventReactive(
eventExpr,
valueExpr,
event.env = parent.frame(),
event.quoted = FALSE,
value.env = parent.frame(),
value.quoted = FALSE,
event.env = deprecated(),
event.quoted = deprecated(),
value.env = deprecated(),
value.quoted = deprecated(),
...,
label = NULL,
domain = getDefaultReactiveDomain(),
@@ -51,15 +51,15 @@ scope.}
\item{event.env}{The parent environment for \code{eventExpr}. By default,
this is the calling environment.}
\item{event.quoted}{Is the \code{eventExpr} expression quoted? By default,
\item{event.quoted}{TODO-barret docs; Is the \code{eventExpr} expression quoted? By default,
this is \code{FALSE}. This is useful when you want to use an expression
that is stored in a variable; to do so, it must be quoted with
\code{quote()}.}
\item{handler.env}{The parent environment for \code{handlerExpr}. By default,
\item{handler.env}{TODO-barret docs; The parent environment for \code{handlerExpr}. By default,
this is the calling environment.}
\item{handler.quoted}{Is the \code{handlerExpr} expression quoted? By
\item{handler.quoted}{TODO-barret docs; Is the \code{handlerExpr} expression quoted? By
default, this is \code{FALSE}. This is useful when you want to use an
expression that is stored in a variable; to do so, it must be quoted with
\code{quote()}.}
@@ -99,7 +99,7 @@ happen once.}
\code{eventReactive}. It will be executed within an \code{\link[=isolate]{isolate()}}
scope.}
\item{value.env}{The parent environment for \code{valueExpr}. By default,
\item{value.env}{TODO-barret docs; The parent environment for \code{valueExpr}. By default,
this is the calling environment.}
\item{value.quoted}{Is the \code{valueExpr} expression quoted? By default,

View File

@@ -2,12 +2,12 @@
% Please edit documentation in R/utils-lang.R
\name{quoToFunction}
\alias{quoToFunction}
\alias{getQuosure}
\alias{sustainEnvAndQuoted}
\title{Convert a quosure to a function for a Shiny render function}
\usage{
quoToFunction(q, label = deparse(sys.call(-1)[[1]]), ..stacktraceon = FALSE)
quoToFunction(q, label = sys.call(-1)[[1]], ..stacktraceon = FALSE)
getQuosure(x, env, quoted)
sustainEnvAndQuoted(q, x, env, quoted)
}
\arguments{
\item{q}{A quosure.}
@@ -29,7 +29,7 @@ provided for backward compatibility.}
This takes a quosure and label, and wraps them into a function that should be
passed to \code{\link[=createRenderFunction]{createRenderFunction()}} or \code{\link[=markRenderFunction]{markRenderFunction()}}.
\code{getQuosure()} and \code{quoToFunction()} are meant to be used together in a
\code{handleEnvAndQuoted()} and \code{quoToFunction()} are meant to be used together in a
\code{render} function, to capture user expressions or quosures and convert them
to functions. They are meant to replace the older functions
\code{\link[=installExprFunction]{installExprFunction()}} and \code{\link[=exprToFunction]{exprToFunction()}} (although those will continue
@@ -60,8 +60,7 @@ for how to migrate them.
# This is something that toolkit authors will do.
renderTriple <- function(expr) {
# Convert expr to a quosure, and then to a function
expr <- getQuosure(expr)
func <- quoToFunction(expr)
func <- quoToFunction(rlang::enquo0(expr))
# Wrap up func, with another function which takes the value of func()
# and modifies it.

View File

@@ -7,8 +7,8 @@
\usage{
reactive(
x,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
...,
label = NULL,
domain = getDefaultReactiveDomain(),
@@ -18,14 +18,14 @@ reactive(
is.reactive(x)
}
\arguments{
\item{x}{For \code{reactive}, an expression (quoted or unquoted). For
\item{x}{TODO-barret docs; For \code{reactive}, an expression (quoted or unquoted). For
\code{is.reactive}, an object to test.}
\item{env}{The parent environment for the reactive expression. By default,
\item{env}{TODO-barret docs; The parent environment for the reactive expression. By default,
this is the calling environment, the same as when defining an ordinary
non-reactive expression.}
\item{quoted}{Is the expression quoted? By default, this is \code{FALSE}.
\item{quoted}{TODO-barret docs; Is the expression quoted? By default, this is \code{FALSE}.
This is useful when you want to use an expression that is stored in a
variable; to do so, it must be quoted with \code{quote()}.}
@@ -58,6 +58,7 @@ See the \href{https://shiny.rstudio.com/tutorial/}{Shiny tutorial} for
more information about reactive expressions.
}
\examples{
# TODO-barret docs; with quosures, not env / quoted
values <- reactiveValues(A=1)
reactiveB <- reactive({

View File

@@ -13,8 +13,8 @@ renderDataTable(
searchDelay = 500,
callback = "function(oTable) {}",
escape = TRUE,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
outputArgs = list()
)
}
@@ -48,9 +48,9 @@ indicate which columns to escape, e.g. \code{1:5} (the first 5 columns),
\code{c(1, 3, 4)}, or \code{c(-1, -3)} (all columns except the first and
third), or \code{c('Species', 'Sepal.Length')}.}
\item{env}{The environment in which to evaluate \code{expr}.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})?
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})?
This is useful if you want to save an expression in a variable.}
\item{outputArgs}{A list of arguments to be passed through to the implicit
@@ -58,6 +58,8 @@ call to \code{dataTableOutput()} when \code{renderDataTable()} is used
in an interactive R Markdown document.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} Please use \code{\link[DT:renderDataTable]{DT::renderDataTable()}}. (Shiny 0.11.1)
Makes a reactive version of the given function that returns a data frame (or
matrix), which will be rendered with the \href{https://datatables.net}{DataTables}
library. Paging, searching, filtering, and sorting can be done on the R side

View File

@@ -6,8 +6,8 @@
\usage{
renderImage(
expr,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
deleteFile,
outputArgs = list()
)
@@ -15,9 +15,9 @@ renderImage(
\arguments{
\item{expr}{An expression that returns a list.}
\item{env}{The environment in which to evaluate \code{expr}.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})? This
is useful if you want to save an expression in a variable.}
\item{deleteFile}{Should the file in \code{func()$src} be deleted after

View File

@@ -11,8 +11,8 @@ renderPlot(
res = 72,
...,
alt = NA,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
execOnResize = FALSE,
outputArgs = list()
)
@@ -50,9 +50,9 @@ ggplot objects; for other plots, \code{NA} results in alt text of "Plot object".
\code{NULL} or \code{""} is not recommended because those should be limited to
decorative images.}
\item{env}{The environment in which to evaluate \code{expr}.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})? This
is useful if you want to save an expression in a variable.}
\item{execOnResize}{If \code{FALSE} (the default), then when a plot is

View File

@@ -7,16 +7,16 @@
\usage{
renderPrint(
expr,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
width = getOption("width"),
outputArgs = list()
)
renderText(
expr,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
outputArgs = list(),
sep = " "
)
@@ -24,9 +24,9 @@ renderText(
\arguments{
\item{expr}{An expression to evaluate.}
\item{env}{The environment in which to evaluate \code{expr}. For expert use only.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}. For expert use only.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})? This
is useful if you want to save an expression in a variable.}
\item{width}{Width of printed output.}

View File

@@ -20,8 +20,8 @@ renderTable(
digits = NULL,
na = "NA",
...,
env = parent.frame(),
quoted = FALSE,
env = deprecated(),
quoted = deprecated(),
outputArgs = list()
)
}
@@ -71,9 +71,9 @@ columns will be displayed in scientific format with a precision of
\item{...}{Arguments to be passed through to \code{\link[xtable:xtable]{xtable::xtable()}}
and \code{\link[xtable:print.xtable]{xtable::print.xtable()}}.}
\item{env}{The environment in which to evaluate \code{expr}.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})?
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})?
This is useful if you want to save an expression in a variable.}
\item{outputArgs}{A list of arguments to be passed through to the

View File

@@ -4,15 +4,15 @@
\alias{renderUI}
\title{UI Output}
\usage{
renderUI(expr, env = parent.frame(), quoted = FALSE, outputArgs = list())
renderUI(expr, env = deprecated(), quoted = deprecated(), outputArgs = list())
}
\arguments{
\item{expr}{An expression that returns a Shiny tag object, \code{\link[=HTML]{HTML()}},
or a list of such objects.}
\item{env}{The environment in which to evaluate \code{expr}.}
\item{env}{TODO-barret docs; The environment in which to evaluate \code{expr}.}
\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
\item{quoted}{TODO-barret docs; Is \code{expr} a quoted expression (with \code{quote()})? This
is useful if you want to save an expression in a variable.}
\item{outputArgs}{A list of arguments to be passed through to the implicit

View File

@@ -4,7 +4,13 @@
\alias{shinyDeprecated}
\title{Print message for deprecated functions in Shiny}
\usage{
shinyDeprecated(version, what, with = NULL, details = NULL)
shinyDeprecated(
version,
what,
with = NULL,
details = NULL,
type = c("deprecated", "superseded")
)
}
\arguments{
\item{version}{Shiny version when the function was deprecated}

View File

@@ -3,7 +3,7 @@
"homepage": "https://shiny.rstudio.com",
"repository": "github:rstudio/shiny",
"name": "@types/rstudio-shiny",
"version": "1.6.0-alpha.9021",
"version": "1.6.0-alpha.9022",
"license": "GPL-3.0-only",
"main": "",
"browser": "",

View File

@@ -700,9 +700,9 @@ test_that("reactive() accepts injected quosures", {
y <- quo(a)
exp <- quo(!!y + 10)
a <- 2
f <- inject(reactive(!! exp ))
ff <- inject(reactive(!! exp ))
a <- 3
expect_identical(isolate(f()), 13)
expect_identical(isolate(ff()), 13)
})
test_that("observe() accepts injected quosures", {

View File

@@ -33,261 +33,272 @@ test_that("Render functions correctly handle quosures", {
expect_true(grepl("20\\.0", r2()))
})
test_that("Custom render functions with correctly handle quosures", {
# Many ways to create custom render functions:
# - exprToFunction(expr, env, quoted)
# - exprToFunction(expr, env, TRUE)
# - installExprFunction(expr, env, quoted)
# - installExprFunction(expr, env, TRUE)
# - quoToFunction(expr, env, quoted) <-- For backward compatbility
# - quoToFunction(expr, env, TRUE) <-- For backward compatbility
# - quoToFunction(expr) <-- Recommended way going forward
# ==============================================
# exprToFunction(expr, env, quoted)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
func <- shiny::exprToFunction(expr, env, quoted)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
test_that("functionLabel returns static value when the label can not be assigned to", {
getFunc <- function(exprF, envF = parent.frame(), quotedF = FALSE) {
quoToFunction(enquo0(exprF))
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# ==============================================
# exprToFunction(expr, env, TRUE)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
if (!quoted) expr <- substitute(expr)
func <- shiny::exprToFunction(expr, env, quoted = TRUE)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
expect_label <- function(func, labely) {
expect_equal(
as.character(body(func)[[2]][[1]]),
labely
)
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
expect_label(
getFunc({a + 1}),
"getFunc"
)
# ==============================================
# installExprFunction(expr, env, quoted)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
installExprFunction(expr, "func", env, quoted)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# ==============================================
# installExprFunction(expr, env, TRUE)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
if (!quoted) expr <- substitute(expr)
installExprFunction(expr, "func", env, quoted = TRUE)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# ==============================================
# quoToFunction(expr, env, quoted)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
q <- getQuosure(expr, env, quoted)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# For this particular version, also make sure that it works with `env` and
# `quoted`.
e <- new.env()
e$a <- 1
r2 <- renderDouble(quote({ a }), env = e, quoted = TRUE)
e$a <- 2
expect_identical(r2(), "2, 2")
# ==============================================
# quoToFunction(expr, env, TRUE)
renderDouble <- function(expr, env = parent.frame(), quoted = FALSE) {
if (!quoted) expr <- substitute(expr)
q <- getQuosure(expr, env, TRUE)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 2
r <- renderDouble(a + 1)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, quoted = FALSE)
expect_identical(r(), "2, 2")
r <- renderDouble(quote(a + 1), quoted = TRUE)
expect_identical(r(), "2, 2")
r <- renderDouble(a + 1, env = e)
expect_identical(r(), "3, 3")
r <- renderDouble(a + 1, env = e, quoted = FALSE)
expect_identical(r(), "3, 3")
r <- renderDouble(quote(a + 1), env = e, quoted = TRUE)
expect_identical(r(), "3, 3")
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# ==============================================
# quoToFunction(expr)
renderDouble <- function(expr) {
q <- getQuosure(expr)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
# Quosures
a <- 1
r1 <- inject(renderDouble({ !!a }))
r2 <- renderDouble({ eval_tidy(quo(!!a)) })
a <- 2
expect_identical(r1(), "1, 1")
expect_identical(r2(), "2, 2")
# multiline labels are not supported
expect_label(
(function(exprF) {
quoToFunction(enquo0(exprF))
})(),
"wrappedFunction"
)
# parents are not supported
expect_label(
(function(exprF) {quoToFunction(enquo0(exprF))})(),
"wrappedFunction"
)
})
for (info in list(
list(
name = "exprToFunction(expr, env, quoted)",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
func <- exprToFunction(exprF, envF, quotedF)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
},
can_not_test_quosures = TRUE
),
list(
name = "exprToFunction(expr, env, quoted = TRUE)",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
if (!quotedF) exprF <- substitute(exprF)
func <- exprToFunction(exprF, envF, quoted = TRUE)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
},
can_not_test_quosures = TRUE
),
list(
name = "installExprFunction(expr, \"func\", env, quoted)",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
a <- 1000
installExprFunction(exprF, "func", envF, quotedF)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
},
can_not_test_quosures = TRUE
),
list(
name = "installExprFunction(expr, \"func\", env, quoted = TRUE)",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
a <- 1000
if (!quotedF) exprF <- substitute(exprF)
installExprFunction(exprF, "func", envF, quoted = TRUE)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
},
can_not_test_quosures = TRUE
),
list(
name = "sustainEnvAndQuoted(); quoToFunction()",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
a <- 1000
q <- enquo0(exprF)
q <- sustainEnvAndQuoted(q, exprF, envF, quotedF)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
),
list(
name = "lower1 - sustainEnvAndQuoted(); quoToFunction()",
fn = function(exprF, envF = parent.frame(), quotedF = FALSE) {
a <- 1000
q <- enquo0(exprF)
q <- sustainEnvAndQuoted(q, exprF, envF, quotedF)
function() {
func <- quoToFunction(q)
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
),
list(
name = "old args - sustainEnvAndQuoted(),quoToFunction()",
fn = function(xF, envF = parent.frame(), quotedF = FALSE) {
a <- 1000
q <- enquo0(xF)
# Eventually can remove this, once users stop using env and quoted
q <- sustainEnvAndQuoted(q, xF, envF, quotedF)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
),
list(
name = "deprecated args - sustainEnvAndQuoted(),quoToFunction()",
fn = function(xF, envF = deprecated(), quotedF = deprecated()) {
a <- 1000
q <- enquo0(xF)
# Eventually can remove this, once users stop using env and quoted
q <- sustainEnvAndQuoted(q, xF, envF, quotedF)
func <- quoToFunction(q)
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
),
list(
name = "quoToFunction(enquo0(expr))",
fn = function(expr) {
func <- quoToFunction(enquo0(expr))
function() {
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
),
list(
name = "lower - quoToFunction(enquo0(expr))",
fn = function(expr) {
function() {
func <- quoToFunction(enquo0(expr))
value <- func()
paste(rep(value, 2), collapse=", ")
}
}
)
)) {
# Scope the local variables
local({
renderH <- info$fn %||% stop("`info$fn` not found")
messageVal <- info$messageVal %||% NA
# Different usages of env and quoted param
a <- 1
e <- new.env()
e$a <- 10
test_that(paste0("vanilla: ", info$name), {
expect_message({
val <- renderH({a + 1})()
}, messageVal)
expect_identical(val, "2, 2")
})
if (length(formals(renderH)) > 1) {
test_that(paste0("quoted = FALSE: ", info$name), {
r <- renderH(a + 1, quotedF = FALSE)
expect_identical(r(), "2, 2")
})
test_that(paste0("quoted = TRUE: ", info$name), {
r <- renderH(quote(a + 1), quotedF = TRUE)
expect_identical(r(), "2, 2")
})
test_that(paste0("env = e: ", info$name), {
r <- renderH(a + 1, envF = e)
expect_identical(r(), "11, 11")
})
test_that(paste0("env = e, quoted = FALSE: ", info$name), {
r <- renderH(a + 1, envF = e, quotedF = FALSE)
expect_identical(r(), "11, 11")
})
test_that(paste0("env = e, quoted = TRUE: ", info$name), {
r <- renderH(quote(a + 1), envF = e, quotedF = TRUE)
expect_identical(r(), "11, 11")
})
if (!isTRUE(info$can_not_test_quosures)) {
test_that(paste0("Works with injecting raw quosures: ", info$name), {
e <- list2env(list(a=10))
x <- new_quosure(quote({ a + 1 }) , env = e)
ans <- expect_message(
inject(renderH(!!x))(),
messageVal
)
expect_identical(ans, "11, 11")
# All below should always error
expect_error(inject(renderH(!!x, quotedF = F)), "alter your quosure")
expect_error(inject(renderH(!!x, quotedF = T)), "alter your quosure")
expect_error(inject(renderH(!!x, envF = e)), "alter your quosure")
expect_error(inject(renderH(!!x, envF = environment())), "alter your quosure")
})
}
}
test_that(paste0("Works with inject / !!: ", info$name), {
# Quosures
a <- 1
r1 <- inject(renderH({ !!a }))
r2 <- renderH({ eval_tidy(quo(!!a)) })
a <- 100
expect_identical(r1(), "1, 1")
expect_identical(r2(), "100, 100")
})
})
}
test_that("nested observe events work with exprToFunction", {
val <- 0
local({
t1 <- reactiveVal(0)
t2 <- reactiveVal(10)
observeEvent(
{
# message("outer observeEvent trigger")
val <<- val + 1
t1()
},
{
# message("outer observeEvent handler")
val <<- val + 2
observeEvent(
{
# message("inner observeEvent trigger")
val <<- val + 3
t2()
},
{
val <<- val + 4
# message("inner observeEvent handler")
}
)
}
)
})
expect_equal(val, 0)
flushReact()
expect_equal(val, 1 + 2 + 3 + 4)
})