Compare commits

..

3 Commits

Author SHA1 Message Date
Joe Cheng
9444bf82ee Try fixing GHA failure by busting the cache 2023-02-13 12:31:56 -08:00
Joe Cheng
70114125ba Code review feedback 2023-02-13 09:16:05 -08:00
Joe Cheng
02ea53c5e9 Ensure logged-in user matches when handling session-specific routes 2023-01-12 16:50:00 -08:00
69 changed files with 7086 additions and 11219 deletions

View File

@@ -21,3 +21,5 @@ jobs:
node-version: "14.x"
R-CMD-check:
uses: rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1
with:
cache-version: "2.1"

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.7.4.9002
Version: 1.7.4.9001
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"),
@@ -87,7 +87,7 @@ Imports:
tools,
crayon,
rlang (>= 0.4.10),
fastmap (>= 1.1.1),
fastmap (>= 1.1.0),
withr,
commonmark (>= 1.7),
glue (>= 1.3.2),

11
NEWS.md
View File

@@ -1,4 +1,4 @@
# shiny 1.7.4.9002
# shiny 1.7.4.9001
## Full changelog
@@ -8,15 +8,8 @@
* Closed #789: `<script>` loaded from dynamic UI are no longer loaded using synchronous `XMLHttpRequest` (via jQuery). (#3666)
* For `reactiveValues()` objects, whenever the `$names()` or `$values()` methods are called, the keys are now returned in the order that they were inserted. (#3774)
* `Map` objects are now initialized at load time instead of build time. This avoids potential problems that could arise from storing `fastmap` objects into the built Shiny package. (#3775)
* Closed #3635: `window.Shiny.outputBindings` and `window.Shiny.inputBindings` gain a `onRegister()` method, to register callbacks that execute whenever a new binding is registered. Internally, Shiny uses this to check whether it should re-bind to the DOM when a binding has been registered. (#3638)
### Bug fixes
* Fixed #3771: Sometimes the error `ion.rangeSlider.min.js: i.stopPropagation is not a function` would appear in the JavaScript console. (#3772)
# shiny 1.7.4
@@ -30,7 +23,7 @@
### New features and improvements
* `plotOutput()`, `imageOutput()`, and `uiOutput()` gain a `fill` argument. If `TRUE` (the default for `plotOutput()`), the output container is allowed to grow/shrink to fit a fill container (created via `htmltools::bindFillRole()`) with an opinionated height. This means `plotOutput()` will grow/shrink by default [inside of `bslib::card_body_fill()`](https://rstudio.github.io/bslib/articles/cards.html#responsive-sizing), but `imageOutput()` and `uiOutput()` will have to opt-in to similar behavior with `fill = TRUE`. (#3715)
* `plotOutput()`, `imageOutput()`, and `uiOutput()` gain a `fill` argument. If `TRUE` (the default for `plotOutput()`), the output container is allowed to grow/shrink to fit a fill container (created via `htmltools::bindFillRole()`) with an opinionated height. This means `plotOutput()` will grow/shrink by default [inside of `bslib::card_body_fill()`](https://rstudio.github.io/bslib/articles/cards.html#responsive-sizing), but `imageOutput()` and `uiOutput()` will have to opt-in to similar behavior with `fill = TRUE`. (#3715)
* Closed #3687: Updated jQuery-UI to v1.13.2. (#3697)

View File

@@ -452,10 +452,8 @@ RestoreInputSet <- R6Class("RestoreInputSet",
)
)
# This is a fastmap::faststack(); value is assigned in .onLoad().
restoreCtxStack <- NULL
on_load({
restoreCtxStack <- fastmap::faststack()
})
withRestoreContext <- function(ctx, expr) {
restoreCtxStack$push(ctx)

View File

@@ -190,10 +190,8 @@ devmode_inform <- function(
registered_devmode_options <- NULL
on_load({
registered_devmode_options <- Map$new()
})
#' @include map.R
registered_devmode_options <- Map$new()
#' @describeIn devmode Registers a Shiny Developer Mode option with an updated
#' value and Developer message. This registration method allows package
@@ -342,22 +340,21 @@ get_devmode_option <- function(
}
on_load({
register_devmode_option(
"shiny.autoreload",
"Turning on shiny autoreload. To disable, call `options(shiny.autoreload = FALSE)`",
TRUE
)
register_devmode_option(
"shiny.minified",
"Using full shiny javascript file. To use the minified version, call `options(shiny.minified = TRUE)`",
FALSE
)
register_devmode_option(
"shiny.autoreload",
"Turning on shiny autoreload. To disable, call `options(shiny.autoreload = FALSE)`",
TRUE
)
register_devmode_option(
"shiny.fullstacktrace",
"Turning on full stack trace. To disable, call `options(shiny.fullstacktrace = FALSE)`",
TRUE
)
})
register_devmode_option(
"shiny.minified",
"Using full shiny javascript file. To use the minified version, call `options(shiny.minified = TRUE)`",
FALSE
)
register_devmode_option(
"shiny.fullstacktrace",
"Turning on full stack trace. To disable, call `options(shiny.fullstacktrace = FALSE)`",
TRUE
)

View File

@@ -7,9 +7,9 @@
# the private seed during load.
withPrivateSeed(set.seed(NULL))
for (expr in on_load_exprs) {
eval(expr, envir = environment(.onLoad))
}
# Create this at the top level, but since the object is from a different
# package, we don't want to bake it into the built binary package.
restoreCtxStack <<- fastmap::faststack()
# Make sure these methods are available to knitr if shiny is loaded but not
# attached.
@@ -23,11 +23,3 @@
# https://github.com/rstudio/shiny/issues/2630
register_upgrade_message("htmlwidgets", 1.5)
}
on_load_exprs <- list()
# Register an expression to be evaluated when the package is loaded (in the
# .onLoad function).
on_load <- function(expr) {
on_load_exprs[[length(on_load_exprs) + 1]] <<- substitute(expr)
}

View File

@@ -559,6 +559,4 @@ MessageLogger = R6Class(
)
)
on_load({
rLog <- RLog$new("shiny.reactlog", "shiny.reactlog.console")
})
rLog <- RLog$new("shiny.reactlog", "shiny.reactlog.console")

View File

@@ -182,8 +182,8 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL,
# $ xmax : num 3.78
# $ ymin : num 17.1
# $ ymax : num 20.4
# $ panelvar1: chr "6"
# $ panelvar2: chr "0
# $ panelvar1: int 6
# $ panelvar2: int 0
# $ coords_css:List of 4
# ..$ xmin: int 260
# ..$ xmax: int 298
@@ -367,8 +367,8 @@ nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL,
# $ img_css_ratio:List of 2
# ..$ x: num 1.25
# ..$ y: num 1.25
# $ panelvar1 : chr "6"
# $ panelvar2 : chr "0"
# $ panelvar1 : int 6
# $ panelvar2 : int 0
# $ mapping :List of 4
# ..$ x : chr "wt"
# ..$ y : chr "mpg"

View File

@@ -1,6 +1,6 @@
#' Insert and remove UI objects
#'
#' These functions allow you to dynamically add and remove arbitrary UI
#' These functions allow you to dynamically add and remove arbirary UI
#' into your app, whenever you want, as many times as you want.
#' Unlike [renderUI()], the UI generated with `insertUI()` is persistent:
#' once it's created, it stays there until removed by `removeUI()`. Each
@@ -11,7 +11,7 @@
#' function.
#'
#' It's particularly useful to pair `removeUI` with `insertUI()`, but there is
#' no restriction on what you can use it on. Any element that can be selected
#' no restriction on what you can use on. Any element that can be selected
#' through a jQuery selector can be removed through this function.
#'
#' @param selector A string that is accepted by jQuery's selector

View File

@@ -326,9 +326,6 @@ ReactiveValues <- R6Class(
.dedupe = logical(0),
# Key, asList(), or names() have been retrieved
.hasRetrieved = list(),
# All names, in insertion order. The names are also stored in the .values
# object, but it does not preserve order.
.nameOrder = character(0),
initialize = function(
@@ -406,11 +403,6 @@ ReactiveValues <- R6Class(
return(invisible())
}
# If it's new, append key to the name order
if (!key_exists) {
.nameOrder[length(.nameOrder) + 1] <<- key
}
# set the value for better logging
.values$set(key, value)
@@ -452,13 +444,14 @@ ReactiveValues <- R6Class(
},
names = function() {
nameValues <- .values$keys()
if (!isTRUE(.hasRetrieved$names)) {
domain <- getDefaultReactiveDomain()
rLog$defineNames(.reactId, .nameOrder, .label, domain)
rLog$defineNames(.reactId, nameValues, .label, domain)
.hasRetrieved$names <<- TRUE
}
.namesDeps$register()
return(.nameOrder)
return(nameValues)
},
# Get a metadata value. Does not trigger reactivity.
@@ -506,7 +499,7 @@ ReactiveValues <- R6Class(
},
toList = function(all.names=FALSE) {
listValue <- .values$mget(.nameOrder)
listValue <- .values$values()
if (!all.names) {
listValue <- listValue[!grepl("^\\.", base::names(listValue))]
}

View File

@@ -1,9 +1,5 @@
# Create a Map object for input handlers and register the defaults.
# This is assigned in .onLoad time.
inputHandlers <- NULL
on_load({
inputHandlers <- Map$new()
})
# Create a map for input handlers and register the defaults.
inputHandlers <- Map$new()
#' Register an Input Handler
#'
@@ -129,117 +125,115 @@ applyInputHandlers <- function(inputs, shinysession = getDefaultReactiveDomain()
inputs
}
on_load({
# Takes a list-of-lists and returns a matrix. The lists
# must all be the same length. NULL is replaced by NA.
registerInputHandler("shiny.matrix", function(data, ...) {
if (length(data) == 0)
return(matrix(nrow=0, ncol=0))
m <- matrix(unlist(lapply(data, function(x) {
sapply(x, function(y) {
ifelse(is.null(y), NA, y)
})
})), nrow = length(data[[1]]), ncol = length(data))
return(m)
})
# Takes a list-of-lists and returns a matrix. The lists
# must all be the same length. NULL is replaced by NA.
registerInputHandler("shiny.matrix", function(data, ...) {
if (length(data) == 0)
return(matrix(nrow=0, ncol=0))
registerInputHandler("shiny.number", function(val, ...){
ifelse(is.null(val), NA, val)
})
registerInputHandler("shiny.password", function(val, shinysession, name) {
# Mark passwords as not serializable
setSerializer(name, serializerUnserializable)
val
})
registerInputHandler("shiny.date", function(val, ...){
# First replace NULLs with NA, then convert to Date vector
datelist <- ifelse(lapply(val, is.null), NA, val)
res <- NULL
tryCatch({
res <- as.Date(unlist(datelist))
},
error = function(e) {
# It's possible for client to send a string like "99999-01-01", which
# as.Date can't handle.
warning(e$message)
res <<- as.Date(rep(NA, length(datelist)))
}
)
res
})
registerInputHandler("shiny.datetime", function(val, ...){
# First replace NULLs with NA, then convert to POSIXct vector
times <- lapply(val, function(x) {
if (is.null(x)) NA
else x
m <- matrix(unlist(lapply(data, function(x) {
sapply(x, function(y) {
ifelse(is.null(y), NA, y)
})
as.POSIXct(unlist(times), origin = "1970-01-01", tz = "UTC")
})
registerInputHandler("shiny.action", function(val, shinysession, name) {
# mark up the action button value with a special class so we can recognize it later
class(val) <- c("shinyActionButtonValue", class(val))
val
})
registerInputHandler("shiny.file", function(val, shinysession, name) {
# This function is only used when restoring a Shiny fileInput. When a file is
# uploaded the usual way, it takes a different code path and won't hit this
# function.
if (is.null(val))
return(NULL)
# The data will be a named list of lists; convert to a data frame.
val <- as.data.frame(lapply(val, unlist), stringsAsFactors = FALSE)
# `val$datapath` should be a filename without a path, for security reasons.
if (basename(val$datapath) != val$datapath) {
stop("Invalid '/' found in file input path.")
}
# Prepend the persistent dir
oldfile <- file.path(getCurrentRestoreContext()$dir, val$datapath)
# Copy the original file to a new temp dir, so that a restored session can't
# modify the original.
newdir <- file.path(tempdir(), createUniqueId(12))
dir.create(newdir)
val$datapath <- file.path(newdir, val$datapath)
file.copy(oldfile, val$datapath)
# Need to mark this input value with the correct serializer. When a file is
# uploaded the usual way (instead of being restored), this occurs in
# session$`@uploadEnd`.
setSerializer(name, serializerFileInput)
snapshotPreprocessInput(name, snapshotPreprocessorFileInput)
val
})
# to be used with !!!answer
registerInputHandler("shiny.symbolList", function(val, ...) {
if (is.null(val)) {
list()
} else {
lapply(val, as.symbol)
}
})
# to be used with !!answer
registerInputHandler("shiny.symbol", function(val, ...) {
if (is.null(val) || identical(val, "")) {
NULL
} else {
as.symbol(val)
}
})
})), nrow = length(data[[1]]), ncol = length(data))
return(m)
})
registerInputHandler("shiny.number", function(val, ...){
ifelse(is.null(val), NA, val)
})
registerInputHandler("shiny.password", function(val, shinysession, name) {
# Mark passwords as not serializable
setSerializer(name, serializerUnserializable)
val
})
registerInputHandler("shiny.date", function(val, ...){
# First replace NULLs with NA, then convert to Date vector
datelist <- ifelse(lapply(val, is.null), NA, val)
res <- NULL
tryCatch({
res <- as.Date(unlist(datelist))
},
error = function(e) {
# It's possible for client to send a string like "99999-01-01", which
# as.Date can't handle.
warning(e$message)
res <<- as.Date(rep(NA, length(datelist)))
}
)
res
})
registerInputHandler("shiny.datetime", function(val, ...){
# First replace NULLs with NA, then convert to POSIXct vector
times <- lapply(val, function(x) {
if (is.null(x)) NA
else x
})
as.POSIXct(unlist(times), origin = "1970-01-01", tz = "UTC")
})
registerInputHandler("shiny.action", function(val, shinysession, name) {
# mark up the action button value with a special class so we can recognize it later
class(val) <- c("shinyActionButtonValue", class(val))
val
})
registerInputHandler("shiny.file", function(val, shinysession, name) {
# This function is only used when restoring a Shiny fileInput. When a file is
# uploaded the usual way, it takes a different code path and won't hit this
# function.
if (is.null(val))
return(NULL)
# The data will be a named list of lists; convert to a data frame.
val <- as.data.frame(lapply(val, unlist), stringsAsFactors = FALSE)
# `val$datapath` should be a filename without a path, for security reasons.
if (basename(val$datapath) != val$datapath) {
stop("Invalid '/' found in file input path.")
}
# Prepend the persistent dir
oldfile <- file.path(getCurrentRestoreContext()$dir, val$datapath)
# Copy the original file to a new temp dir, so that a restored session can't
# modify the original.
newdir <- file.path(tempdir(), createUniqueId(12))
dir.create(newdir)
val$datapath <- file.path(newdir, val$datapath)
file.copy(oldfile, val$datapath)
# Need to mark this input value with the correct serializer. When a file is
# uploaded the usual way (instead of being restored), this occurs in
# session$`@uploadEnd`.
setSerializer(name, serializerFileInput)
snapshotPreprocessInput(name, snapshotPreprocessorFileInput)
val
})
# to be used with !!!answer
registerInputHandler("shiny.symbolList", function(val, ...) {
if (is.null(val)) {
list()
} else {
lapply(val, as.symbol)
}
})
# to be used with !!answer
registerInputHandler("shiny.symbol", function(val, ...) {
if (is.null(val) || identical(val, "")) {
NULL
} else {
as.symbol(val)
}
})

View File

@@ -1,12 +1,7 @@
#' @include server-input-handlers.R
appsByToken <- NULL
appsNeedingFlush <- NULL
on_load({
appsByToken <- Map$new()
appsNeedingFlush <- Map$new()
})
appsByToken <- Map$new()
appsNeedingFlush <- Map$new()
# Provide a character representation of the WS that can be used
# as a key in a Map.
@@ -127,10 +122,7 @@ decodeMessage <- function(data) {
return(mainMessage)
}
autoReloadCallbacks <- NULL
on_load({
autoReloadCallbacks <- Callbacks$new()
})
autoReloadCallbacks <- Callbacks$new()
createAppHandlers <- function(httpHandlers, serverFuncSource) {
appvars <- new.env()

View File

@@ -1876,6 +1876,26 @@ ShinySession <- R6Class(
# Provides a mechanism for handling direct HTTP requests that are posted
# to the session (rather than going through the websocket)
handleRequest = function(req) {
if (!is.null(self$user)) {
if (is.null(req$HTTP_SHINY_SERVER_CREDENTIALS)) {
# Session owner is logged in, but this requester is not
return(NULL)
}
requestUser <- NULL
try(
{
creds <- safeFromJSON(req$HTTP_SHINY_SERVER_CREDENTIALS)
requestUser <- creds$user
},
silent = TRUE
)
if (!identical(self$user, requestUser)) {
# This requester is not the same user as session owner
return(NULL)
}
}
# TODO: Turn off caching for the response
subpath <- req$PATH_INFO

View File

@@ -753,7 +753,7 @@
x = $handle.offset().left;
x += ($handle.width() / 2) - 1;
this.pointerClick("single", {preventDefault: function () {}, stopPropagation: function () {}, pageX: x});
this.pointerClick("single", {preventDefault: function () {}, pageX: x});
}
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
/*! shiny 1.7.4.9002 | (c) 2012-2023 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.7.4.9001 | (c) 2012-2023 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:400}.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,#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

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
/*! shiny 1.7.4.9002 | (c) 2012-2023 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.7.4.9001 | (c) 2012-2023 RStudio, PBC. | License: GPL-3 | file LICENSE */
"use strict";(function(){var a=eval;window.addEventListener("message",function(i){var e=i.data;e.code&&a(e.code)});})();
//# sourceMappingURL=shiny-testmode.js.map

View File

@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../../../srcts/src/utils/eval.ts", "../../../srcts/extras/shiny-testmode.ts"],
"sourcesContent": ["//esbuild.github.io/content-types/#direct-eval\n//tl/dr;\n// * Direct usage of `eval(\"x\")` is bad with bundled code.\n// * Instead, use indirect calls to `eval` such as `indirectEval(\"x\")`\n// * Even just renaming the function works well enough.\n// > This is known as \"indirect eval\" because eval is not being called directly, and so does not trigger the grammatical special case for direct eval in the JavaScript VM. You can call indirect eval using any syntax at all except for an expression of the exact form eval('x'). For example, var eval2 = eval; eval2('x') and [eval][0]('x') and window.eval('x') are all indirect eval calls.\n// > When you use indirect eval, the code is evaluated in the global scope instead of in the inline scope of the caller.\n\nvar indirectEval = eval;\nexport { indirectEval };", "/* eslint-disable unicorn/filename-case */\nimport { indirectEval } from \"../src/utils/eval\";\n\n// Listen for messages from parent frame. This file is only added when the\n// shiny.testmode option is TRUE.\nwindow.addEventListener(\"message\", function (e) {\n var message = e.data;\n if (message.code) indirectEval(message.code);\n});"],
"mappings": ";yBAQA,IAAIA,EAAe,KCHnB,OAAO,iBAAiB,UAAW,SAAUC,EAAG,CAC9C,IAAIC,EAAUD,EAAE,KACZC,EAAQ,MAAMC,EAAaD,EAAQ,IAAI,CAC7C,CAAC",
"sourcesContent": ["//esbuild.github.io/content-types/#direct-eval\n//tl/dr;\n// * Direct usage of `eval(\"x\")` is bad with bundled code.\n// * Instead, use indirect calls to `eval` such as `indirectEval(\"x\")`\n// * Even just renaming the function works well enough.\n// > This is known as \"indirect eval\" because eval is not being called directly, and so does not trigger the grammatical special case for direct eval in the JavaScript VM. You can call indirect eval using any syntax at all except for an expression of the exact form eval('x'). For example, var eval2 = eval; eval2('x') and [eval][0]('x') and window.eval('x') are all indirect eval calls.\n// > When you use indirect eval, the code is evaluated in the global scope instead of in the inline scope of the caller.\nvar indirectEval = eval;\nexport { indirectEval };", "/* eslint-disable unicorn/filename-case */\nimport { indirectEval } from \"../src/utils/eval\"; // Listen for messages from parent frame. This file is only added when the\n// shiny.testmode option is TRUE.\n\nwindow.addEventListener(\"message\", function (e) {\n var message = e.data;\n if (message.code) indirectEval(message.code);\n});"],
"mappings": ";yBAOA,IAAIA,EAAe,KCHnB,OAAO,iBAAiB,UAAW,SAAUC,EAAG,CAC9C,IAAIC,EAAUD,EAAE,KACZC,EAAQ,MAAMC,EAAaD,EAAQ,IAAI,CAC7C,CAAC",
"names": ["indirectEval", "e", "message", "indirectEval"]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -64,7 +64,7 @@ updated and all observers have been run (default).}
\item{session}{The shiny session. Advanced use only.}
}
\description{
These functions allow you to dynamically add and remove arbitrary UI
These functions allow you to dynamically add and remove arbirary UI
into your app, whenever you want, as many times as you want.
Unlike \code{\link[=renderUI]{renderUI()}}, the UI generated with \code{insertUI()} is persistent:
once it's created, it stays there until removed by \code{removeUI()}. Each
@@ -76,7 +76,7 @@ function.
}
\details{
It's particularly useful to pair \code{removeUI} with \code{insertUI()}, but there is
no restriction on what you can use it on. Any element that can be selected
no restriction on what you can use on. Any element that can be selected
through a jQuery selector can be removed through this function.
}
\examples{

View File

@@ -17,7 +17,7 @@ memoryCache(
\arguments{
\item{max_size}{Maximum size of the cache, in bytes. If the cache exceeds
this size, cached objects will be removed according to the value of the
\code{evict}. Use \code{Inf} for no size limit. The default is 512 megabytes.}
\code{evict}. Use \code{Inf} for no size limit. The default is 1 gigabyte.}
\item{max_age}{Maximum age of files in cache before they are evicted, in
seconds. Use \code{Inf} for no age limit.}

View File

@@ -3,7 +3,7 @@
"homepage": "https://shiny.rstudio.com",
"repository": "github:rstudio/shiny",
"name": "@types/rstudio-shiny",
"version": "1.7.4-alpha.9002",
"version": "1.7.4-alpha.9001",
"license": "GPL-3.0-only",
"main": "",
"browser": "",
@@ -40,11 +40,12 @@
"@types/jest": "^26.0.23",
"@types/jqueryui": "1.12.16",
"@types/lodash": "^4.14.170",
"@types/node": "^18.14.2",
"@types/node": "^15.6.1",
"@types/showdown": "^1.9.3",
"@typescript-eslint/eslint-plugin": "^5.38.1",
"@typescript-eslint/parser": "^5.38.1",
"autoprefixer": "^10.2.6",
"bootstrap-datepicker": "1.9.0",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001312",
"core-js": "^3.13.0",
@@ -59,8 +60,9 @@
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-unicorn": "^43.0.2",
"fs-readdir-recursive": "^1.1.0",
"ion-rangeslider": "2.3.1",
"jest": "^26.6.3",
"jquery": "^3.6.0",
"jquery": "3.6.0",
"lodash": "^4.17.21",
"madge": "^4.0.2",
"node-gyp": "^8.1.0",
@@ -69,6 +71,8 @@
"prettier": "^2.7.1",
"readcontrol": "^1.0.0",
"replace": "^1.2.1",
"selectize": "0.12.4",
"strftime": "0.9.2",
"ts-jest": "^26",
"ts-node": "^10.9.1",
"type-coverage": "^2.22.0",

View File

@@ -1,5 +1,4 @@
import { mergeSort } from "../utils";
import { Callbacks } from "../utils/callbacks";
interface BindingBase {
name: string;
@@ -15,7 +14,6 @@ class BindingRegistry<Binding extends BindingBase> {
name!: string;
bindings: Array<BindingObj<Binding>> = [];
bindingNames: { [key: string]: BindingObj<Binding> } = {};
registerCallbacks: Callbacks = new Callbacks();
register(binding: Binding, bindingName: string, priority = 0): void {
const bindingObj = { binding, priority };
@@ -25,12 +23,6 @@ class BindingRegistry<Binding extends BindingBase> {
this.bindingNames[bindingName] = bindingObj;
binding.name = bindingName;
}
this.registerCallbacks.invoke();
}
onRegister(fn: () => void, once = true): void {
this.registerCallbacks.register(fn, once);
}
setPriority(bindingName: string, priority: number): void {

View File

@@ -58,7 +58,6 @@ type BrushOpts = {
type Brush = {
reset: () => void;
hasOldBrush: () => boolean;
importOldBrush: () => void;
isInsideBrush: (offsetCss: Offset) => boolean;
isInResizeArea: (offsetCss: Offset) => boolean;
@@ -174,15 +173,10 @@ function createBrush(
if ($div) $div.remove();
}
function hasOldBrush(): boolean {
const oldDiv = $el.find("#" + el.id + "_brush");
return oldDiv.length > 0;
}
// If there's an existing brush div, use that div to set the new brush's
// settings, provided that the x, y, and panel variables have the same names,
// and there's a panel with matching panel variable values.
function importOldBrush(): void {
function importOldBrush() {
const oldDiv = $el.find("#" + el.id + "_brush");
if (oldDiv.length === 0) return;
@@ -623,7 +617,6 @@ function createBrush(
return {
reset: reset,
hasOldBrush,
importOldBrush: importOldBrush,
isInsideBrush: isInsideBrush,
isInResizeArea: isInResizeArea,

View File

@@ -57,9 +57,6 @@ function createClickHandler(
): CreateHandler {
const clickInfoSender = coordmap.mouseCoordinateSender(inputId, clip);
// Send initial (null) value on creation.
clickInfoSender(null);
return {
mousedown: function (e) {
// Listen for left mouse button only
@@ -93,9 +90,6 @@ function createHoverHandler(
hoverInfoSender = new Throttler(null, sendHoverInfo, delay);
else hoverInfoSender = new Debouncer(null, sendHoverInfo, delay);
// Send initial (null) value on creation.
hoverInfoSender.immediateCall(null);
// What to do when mouse exits the image
let mouseout: () => void;
@@ -239,11 +233,6 @@ function createBrushHandler(
brushInfoSender = new Debouncer(null, sendBrushInfo, opts.brushDelay);
}
// Send initial (null) value on creation.
if (!brush.hasOldBrush()) {
brushInfoSender.immediateCall();
}
function mousedown(e: JQuery.MouseDownEvent) {
// This can happen when mousedown inside the graphic, then mouseup
// outside, then mousedown inside. Just ignore the second

View File

@@ -150,24 +150,6 @@ function initShiny(windowShiny: Shiny): void {
(x) => x.value
);
// When future bindings are registered, rebind to the DOM once the current
// event loop is done. This is necessary since the binding might be registered
// after Shiny has already bound to the DOM (#3635)
let enqueuedCount = 0;
const enqueueRebind = () => {
enqueuedCount++;
windowShiny.shinyapp?.actionQueue.enqueue(() => {
enqueuedCount--;
// If this function is scheduled more than once in the queue, don't do anything.
// Only do the bindAll when we get to the last instance of this function in the queue.
if (enqueuedCount === 0) {
windowShiny.bindAll?.(document.documentElement);
}
});
};
inputBindings.onRegister(enqueueRebind, false);
outputBindings.onRegister(enqueueRebind, false);
// The server needs to know the size of each image and plot output element,
// in case it is auto-sizing
$(".shiny-image-output, .shiny-plot-output, .shiny-report-size").each(

View File

@@ -1,45 +0,0 @@
type Cb = {
once: boolean;
fn: () => void;
};
type Cbs = {
[key: string]: Cb;
};
class Callbacks {
callbacks: Cbs = {};
id = 0;
register(fn: () => void, once = true): () => void {
this.id += 1;
const id = this.id;
this.callbacks[id] = { fn, once };
return () => {
delete this.callbacks[id];
};
}
invoke(): void {
for (const id in this.callbacks) {
const cb = this.callbacks[id];
try {
cb.fn();
} finally {
if (cb.once) delete this.callbacks[id];
}
}
}
clear(): void {
this.callbacks = {};
}
count(): number {
return Object.keys(this.callbacks).length;
}
}
export { Callbacks };

View File

@@ -1,5 +1,5 @@
import { InputBinding } from "./inputBinding";
type ActionButtonReceiveMessageData = {
declare type ActionButtonReceiveMessageData = {
label?: string;
icon?: string | [];
};

View File

@@ -1,7 +1,7 @@
import { InputBinding } from "./inputBinding";
type CheckedHTMLElement = HTMLInputElement;
type CheckboxChecked = CheckedHTMLElement["checked"];
type CheckboxReceiveMessageData = {
declare type CheckedHTMLElement = HTMLInputElement;
declare type CheckboxChecked = CheckedHTMLElement["checked"];
declare type CheckboxReceiveMessageData = {
value?: CheckboxChecked;
label?: string;
};

View File

@@ -1,16 +1,16 @@
import { InputBinding } from "./inputBinding";
import type { CheckedHTMLElement } from "./checkbox";
type CheckboxGroupHTMLElement = CheckedHTMLElement;
type ValueLabelObject = {
declare type CheckboxGroupHTMLElement = CheckedHTMLElement;
declare type ValueLabelObject = {
value: HTMLInputElement["value"];
label: string;
};
type CheckboxGroupReceiveMessageData = {
declare type CheckboxGroupReceiveMessageData = {
options?: string;
value?: Parameters<CheckboxGroupInputBinding["setValue"]>[1];
label: string;
};
type CheckboxGroupValue = CheckboxGroupHTMLElement["value"];
declare type CheckboxGroupValue = CheckboxGroupHTMLElement["value"];
declare class CheckboxGroupInputBinding extends InputBinding {
find(scope: HTMLElement): JQuery<HTMLElement>;
getValue(el: CheckboxGroupHTMLElement): CheckboxGroupValue[];

View File

@@ -9,7 +9,7 @@ declare global {
bsDatepicker(methodName: string, params: Date | null): void;
}
}
type DateReceiveMessageData = {
declare type DateReceiveMessageData = {
label: string;
min?: Date | null;
max?: Date | null;

View File

@@ -1,6 +1,6 @@
import { formatDateUTC } from "../../utils";
import { DateInputBindingBase } from "./date";
type DateRangeReceiveMessageData = {
declare type DateRangeReceiveMessageData = {
label: string;
min?: Date;
max?: Date;

View File

@@ -1,7 +1,7 @@
import { BindingRegistry } from "../registry";
import { InputBinding } from "./inputBinding";
import { FileInputBinding } from "./fileinput";
type InitInputBindings = {
declare type InitInputBindings = {
inputBindings: BindingRegistry<InputBinding>;
fileInputBinding: FileInputBinding;
};

View File

@@ -1,6 +1,6 @@
import { TextInputBindingBase } from "./text";
type NumberHTMLElement = HTMLInputElement;
type NumberReceiveMessageData = {
declare type NumberHTMLElement = HTMLInputElement;
declare type NumberReceiveMessageData = {
label: string;
value?: string | null;
min?: string | null;

View File

@@ -1,10 +1,10 @@
import { InputBinding } from "./inputBinding";
type RadioHTMLElement = HTMLInputElement;
type ValueLabelObject = {
declare type RadioHTMLElement = HTMLInputElement;
declare type ValueLabelObject = {
value: HTMLInputElement["value"];
label: string;
};
type RadioReceiveMessageData = {
declare type RadioReceiveMessageData = {
value?: string | [];
options?: ValueLabelObject[];
label: string;

View File

@@ -1,18 +1,18 @@
/// <reference types="selectize" />
import { InputBinding } from "./inputBinding";
import type { NotUndefined } from "../../utils/extraTypes";
type SelectHTMLElement = HTMLSelectElement & {
declare type SelectHTMLElement = HTMLSelectElement & {
nonempty: boolean;
};
type SelectInputReceiveMessageData = {
declare type SelectInputReceiveMessageData = {
label: string;
options?: string;
config?: string;
url?: string;
value?: string;
};
type SelectizeOptions = Selectize.IOptions<string, unknown>;
type SelectizeInfo = Selectize.IApi<string, unknown> & {
declare type SelectizeOptions = Selectize.IOptions<string, unknown>;
declare type SelectizeInfo = Selectize.IApi<string, unknown> & {
settings: SelectizeOptions;
};
declare class SelectInputBinding extends InputBinding {

View File

@@ -1,7 +1,7 @@
import type { TextHTMLElement } from "./text";
import { TextInputBindingBase } from "./text";
type TimeFormatter = (fmt: string, dt: Date) => string;
type SliderReceiveMessageData = {
declare type TimeFormatter = (fmt: string, dt: Date) => string;
declare type SliderReceiveMessageData = {
label: string;
value?: Array<number | string> | number | string;
min?: number;

View File

@@ -1,5 +1,5 @@
import { InputBinding } from "./inputBinding";
type TabInputReceiveMessageData = {
declare type TabInputReceiveMessageData = {
value?: string;
};
declare class BootstrapTabInputBinding extends InputBinding {

View File

@@ -1,6 +1,6 @@
import { InputBinding } from "./inputBinding";
type TextHTMLElement = HTMLInputElement;
type TextReceiveMessageData = {
declare type TextHTMLElement = HTMLInputElement;
declare type TextReceiveMessageData = {
label: string;
value?: TextHTMLElement["value"];
placeholder?: TextHTMLElement["placeholder"];

View File

@@ -1,6 +1,6 @@
import { BindingRegistry } from "../registry";
import { OutputBinding } from "./outputBinding";
type InitOutputBindings = {
declare type InitOutputBindings = {
outputBindings: BindingRegistry<OutputBinding>;
};
declare function initOutputBindings(): InitOutputBindings;

View File

@@ -1,4 +1,3 @@
import { Callbacks } from "../utils/callbacks";
interface BindingBase {
name: string;
}
@@ -13,9 +12,7 @@ declare class BindingRegistry<Binding extends BindingBase> {
bindingNames: {
[key: string]: BindingObj<Binding>;
};
registerCallbacks: Callbacks;
register(binding: Binding, bindingName: string, priority?: number): void;
onRegister(fn: () => void, once?: boolean): void;
setPriority(bindingName: string, priority: number): void;
getPriority(bindingName: string): number | false;
getBindings(): Array<BindingObj<Binding>>;

View File

@@ -1,7 +1,7 @@
import type { JQueryEventHandlerBase } from "bootstrap";
import "jquery";
type EvtPrefix<T extends string> = `${T}.${string}`;
type EvtFn<T extends JQuery.Event> = ((evt: T) => void) | null | undefined;
declare type EvtPrefix<T extends string> = `${T}.${string}`;
declare type EvtFn<T extends JQuery.Event> = ((evt: T) => void) | null | undefined;
declare global {
interface JQuery {
on(events: EvtPrefix<"change">, handler: EvtFn<JQuery.DragEvent>): this;

View File

@@ -1,11 +1,11 @@
import type { ShinyApp } from "../shiny/shinyapp";
type JobId = string;
type UploadUrl = string;
type UploadInitValue = {
declare type JobId = string;
declare type UploadUrl = string;
declare type UploadInitValue = {
jobId: JobId;
uploadUrl: UploadUrl;
};
type UploadEndValue = never;
declare type UploadEndValue = never;
declare class FileProcessor {
files: File[];
fileIndex: number;

View File

@@ -1,15 +1,15 @@
import type { Coordmap } from "./initCoordmap";
import type { Panel } from "./initPanelScales";
import type { Offset } from "./findbox";
type Bounds = {
declare type Bounds = {
xmin: number;
xmax: number;
ymin: number;
ymax: number;
};
type BoundsCss = Bounds;
type BoundsData = Bounds;
type ImageState = {
declare type BoundsCss = Bounds;
declare type BoundsData = Bounds;
declare type ImageState = {
brushing: boolean;
dragging: boolean;
resizing: boolean;
@@ -26,7 +26,7 @@ type ImageState = {
panel: Panel | null;
changeStartBounds: Bounds;
};
type BrushOpts = {
declare type BrushOpts = {
brushDirection: "x" | "xy" | "y";
brushClip: boolean;
brushFill: string;
@@ -36,9 +36,8 @@ type BrushOpts = {
brushDelay?: number;
brushResetOnNew?: boolean;
};
type Brush = {
declare type Brush = {
reset: () => void;
hasOldBrush: () => boolean;
importOldBrush: () => void;
isInsideBrush: (offsetCss: Offset) => boolean;
isInResizeArea: (offsetCss: Offset) => boolean;

View File

@@ -3,14 +3,14 @@ import type { BoundsCss, Bounds, BrushOpts } from "./createBrush";
import type { Offset } from "./findbox";
import type { Coordmap } from "./initCoordmap";
import type { Panel } from "./initPanelScales";
type CreateHandler = {
declare type CreateHandler = {
mousemove?: (e: JQuery.MouseMoveEvent) => void;
mouseout?: (e: JQuery.MouseOutEvent) => void;
mousedown?: (e: JQuery.MouseDownEvent) => void;
onResetImg: () => void;
onResize: ((e: JQuery.ResizeEvent) => void) | null;
};
type BrushInfo = {
declare type BrushInfo = {
xmin: number;
xmax: number;
ymin: number;
@@ -28,9 +28,9 @@ type BrushInfo = {
brushId?: string;
outputId?: string;
};
type InputId = Parameters<Coordmap["mouseCoordinateSender"]>[0];
type Clip = Parameters<Coordmap["mouseCoordinateSender"]>[1];
type NullOutside = Parameters<Coordmap["mouseCoordinateSender"]>[2];
declare type InputId = Parameters<Coordmap["mouseCoordinateSender"]>[0];
declare type Clip = Parameters<Coordmap["mouseCoordinateSender"]>[1];
declare type NullOutside = Parameters<Coordmap["mouseCoordinateSender"]>[2];
declare function createClickHandler(inputId: InputId, clip: Clip, coordmap: Coordmap): CreateHandler;
declare function createHoverHandler(inputId: InputId, delay: number, delayType: string | "throttle", clip: Clip, nullOutside: NullOutside, coordmap: Coordmap): CreateHandler;
declare function createBrushHandler(inputId: InputId, $el: JQuery<HTMLElement>, opts: BrushOpts, coordmap: Coordmap, outputId: BrushInfo["outputId"]): CreateHandler;

View File

@@ -1,5 +1,5 @@
import type { Bounds } from "./createBrush";
type Offset = {
declare type Offset = {
x: number;
y: number;
};

View File

@@ -3,13 +3,13 @@ import type { Offset } from "./findbox";
import type { Bounds } from "./createBrush";
import type { Panel, PanelInit } from "./initPanelScales";
declare function findOrigin($el: JQuery<HTMLElement>): Offset;
type OffsetCss = {
declare type OffsetCss = {
[key: string]: number;
};
type OffsetImg = {
declare type OffsetImg = {
[key: string]: number;
};
type CoordmapInit = {
declare type CoordmapInit = {
panels: PanelInit[];
dims: {
height: number;
@@ -19,7 +19,7 @@ type CoordmapInit = {
width: null;
};
};
type Coordmap = {
declare type Coordmap = {
panels: Panel[];
dims: {
height: number;

View File

@@ -1,6 +1,6 @@
import type { Offset } from "./findbox";
import type { Bounds } from "./createBrush";
type PanelInit = {
declare type PanelInit = {
domain: {
top: number;
bottom: number;
@@ -24,7 +24,7 @@ type PanelInit = {
[key: string]: number | string;
};
};
type Panel = PanelInit & {
declare type Panel = PanelInit & {
scaleDataToImg: {
(val: Bounds, clip?: boolean): Bounds;
};

View File

@@ -1,5 +1,5 @@
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
type LastSentValues = {
declare type LastSentValues = {
[key: string]: {
[key: string]: string;
};

View File

@@ -1,6 +1,6 @@
import type { InputBinding } from "../bindings";
type EventPriority = "deferred" | "event" | "immediate";
type InputPolicyOpts = {
declare type EventPriority = "deferred" | "event" | "immediate";
declare type InputPolicyOpts = {
priority: EventPriority;
el?: HTMLElement;
binding?: InputBinding;

View File

@@ -1,6 +1,6 @@
import type { InputPolicy, InputPolicyOpts } from "./inputPolicy";
import type { InputRatePolicy } from "./inputRatePolicy";
type RatePolicyModes = "debounce" | "direct" | "throttle";
declare type RatePolicyModes = "debounce" | "direct" | "throttle";
declare class InputRateDecorator implements InputPolicy {
target: InputPolicy;
inputRatePolicies: {

View File

@@ -1,8 +1,8 @@
import type { InputBinding, OutputBinding } from "../bindings";
import type { BindingRegistry } from "../bindings/registry";
import type { InputRateDecorator, InputValidateDecorator } from "../inputPolicies";
type BindScope = HTMLElement | JQuery<HTMLElement>;
type BindInputsCtx = {
declare type BindScope = HTMLElement | JQuery<HTMLElement>;
declare type BindInputsCtx = {
inputs: InputValidateDecorator;
inputsRate: InputRateDecorator;
inputBindings: BindingRegistry<InputBinding>;

View File

@@ -13,27 +13,27 @@ declare function renderHtmlAsync(html: string, el: BindScope, dependencies: Html
declare function renderHtml(html: string, el: BindScope, dependencies: HtmlDep[], where?: WherePosition): ReturnType<typeof singletonsRenderHtml>;
declare function renderDependenciesAsync(dependencies: HtmlDep[] | null): Promise<void>;
declare function renderDependencies(dependencies: HtmlDep[] | null): void;
type HtmlDepVersion = string;
type MetaItem = {
declare type HtmlDepVersion = string;
declare type MetaItem = {
name: string;
content: string;
[x: string]: string;
};
type StylesheetItem = {
declare type StylesheetItem = {
href: string;
rel?: string;
type?: string;
};
type ScriptItem = {
declare type ScriptItem = {
src: string;
[x: string]: string;
};
type AttachmentItem = {
declare type AttachmentItem = {
key: string;
href: string;
[x: string]: string;
};
type HtmlDep = {
declare type HtmlDep = {
name: string;
version: HtmlDepVersion;
restyle?: boolean;

View File

@@ -1,22 +1,22 @@
import type { OutputBindingAdapter } from "../bindings/outputAdapter";
import type { UploadInitValue, UploadEndValue } from "../file/fileProcessor";
import { AsyncQueue } from "../utils/asyncQueue";
type ResponseValue = UploadEndValue | UploadInitValue;
type Handler = (message: any) => Promise<void> | void;
type ShinyWebSocket = WebSocket & {
declare type ResponseValue = UploadEndValue | UploadInitValue;
declare type Handler = (message: any) => Promise<void> | void;
declare type ShinyWebSocket = WebSocket & {
allowReconnect?: boolean;
};
type ErrorsMessageValue = {
declare type ErrorsMessageValue = {
message: string;
call: string[];
type?: string[];
};
type OnSuccessRequest = (value: ResponseValue) => void;
type OnErrorRequest = (err: string) => void;
type InputValues = {
declare type OnSuccessRequest = (value: ResponseValue) => void;
declare type OnErrorRequest = (err: string) => void;
declare type InputValues = {
[key: string]: unknown;
};
type MessageValue = Parameters<WebSocket["send"]>[0];
declare type MessageValue = Parameters<WebSocket["send"]>[0];
declare function addCustomMessageHandler(type: string, handler: Handler): void;
declare class ShinyApp {
$socket: ShinyWebSocket | null;

View File

@@ -2,7 +2,7 @@ import type { BindScope } from "./bind";
declare const knownSingletons: {
[key: string]: boolean;
};
type WherePosition = "afterBegin" | "afterEnd" | "beforeBegin" | "beforeEnd" | "replace";
declare type WherePosition = "afterBegin" | "afterEnd" | "beforeBegin" | "beforeEnd" | "replace";
declare function renderHtml(html: string, el: BindScope, where: WherePosition): ReturnType<typeof processHtml>;
declare function registerNames(s: string[] | string): void;
declare function processHtml(val: string): {

View File

@@ -1,16 +0,0 @@
type Cb = {
once: boolean;
fn: () => void;
};
type Cbs = {
[key: string]: Cb;
};
declare class Callbacks {
callbacks: Cbs;
id: number;
register(fn: () => void, once?: boolean): () => void;
invoke(): void;
clear(): void;
count(): number;
}
export { Callbacks };

View File

@@ -1,11 +1,11 @@
type AnyFunction = (...args: any[]) => any;
type AnyVoidFunction = (...args: any[]) => void;
type MapValuesUnion<T> = T[keyof T];
type MapWithResult<X, R> = {
declare type AnyFunction = (...args: any[]) => any;
declare type AnyVoidFunction = (...args: any[]) => void;
declare type MapValuesUnion<T> = T[keyof T];
declare type MapWithResult<X, R> = {
[Property in keyof X]: R;
};
/**
* Exclude undefined from T
*/
type NotUndefined<T> = T extends undefined ? never : T;
declare type NotUndefined<T> = T extends undefined ? never : T;
export type { AnyFunction, AnyVoidFunction, MapValuesUnion, MapWithResult, NotUndefined, };

View File

@@ -1,4 +1,4 @@
type UserAgent = typeof window.navigator.userAgent;
declare type UserAgent = typeof window.navigator.userAgent;
declare let userAgent: UserAgent;
declare function setUserAgent(userAgent_: UserAgent): void;
export type { UserAgent };

View File

@@ -126,23 +126,6 @@ test_that("ReactiveValues", {
expect_error(values$a <- 1)
})
test_that("reactiveValues keys are sorted", {
values <- reactiveValues(b=2, a=0)
values$C <- 13
values$A <- 0
values$c <- 3
values$B <- 12
# Setting an existing value shouldn't change order
values$a <- 1
values$A <- 11
expect_identical(isolate(names(values)), c("b", "a", "C", "A", "c", "B"))
expect_identical(
isolate(reactiveValuesToList(values)),
list(b=2, a=1, C=13, A=11, c=3, B=12)
)
})
test_that("reactiveValues() has useful print method", {
verify_output(test_path("print-reactiveValues.txt"), {
x <- reactiveValues(x = 1, y = 2, z = 3)

View File

@@ -2,15 +2,6 @@ diff --git a/inst/www/shared/ionrangeslider/js/ion.rangeSlider.js b/inst/www/sha
index 2fe2c8d..89d204e 100644
--- a/inst/www/shared/ionrangeslider/js/ion.rangeSlider.js
+++ b/inst/www/shared/ionrangeslider/js/ion.rangeSlider.js
@@ -753,7 +753,7 @@
x = $handle.offset().left;
x += ($handle.width() / 2) - 1;
- this.pointerClick("single", {preventDefault: function () {}, pageX: x});
+ this.pointerClick("single", {preventDefault: function () {}, stopPropagation: function () {}, pageX: x});
}
},
@@ -816,6 +816,7 @@
*/
pointerDown: function (target, e) {

4528
yarn.lock

File diff suppressed because it is too large Load Diff