Compare commits

...

5 Commits

Author SHA1 Message Date
George Stagg
6b76647503 Bump version number for webR package fork 2024-05-30 21:34:13 -04:00
George Stagg
bf62d3c3d1 Add GHA to build shiny webR image 2024-05-30 21:33:00 -04:00
George Stagg
a052a624fb Unsafe changes to further reduce stack use
The internal function `.addCondHands` is used in place of
`withConditionHandlers` to avoid adding a call to the stack. This
generates a warning during `R CMD check`.

The `captureStackTraces` function is removed from `hybrid_chain`.
Instead stack traces are captured and annotated by a `captureStackTraces`
invoked by `runApp` higher up the call stack.
2024-05-30 21:33:00 -04:00
George Stagg
c219fe9ca1 Update tests for changed hybrid_chain call stack 2024-05-30 21:32:59 -04:00
George Stagg
78f3f1180e Reduce amount of call stack used in hybrid_chain
Replaces `tryCatch` in `hybrid_chain` with `withCallingHandlers`. This improves
Shiny on webR on Safari < 16.4 by reducing the amount of call stack used during
deep nested calls to `hybrid_chain`.

A `delayedAssign` is used so that if the error condition handler is invoked,
the condition is handled or re-thrown in the context of `hybrid_chain`, rather
than the context of the inner function deeper in the stack.

The `finally` argument is reimplemented with an `on.exit()`.
2024-05-30 21:32:56 -04:00
5 changed files with 100 additions and 46 deletions

1
.github/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.html

View File

@@ -0,0 +1,19 @@
# Workflow derived from https://github.com/r-wasm/actions/tree/v1/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
release:
# Must republish release to update assets
types: [ published ]
name: Build and deploy wasm R package image
jobs:
release-file-system-image:
uses: r-wasm/actions/.github/workflows/release-file-system-image.yml@v1
permissions:
# For publishing artifact files to the release
contents: write
# To download GitHub Packages within action
repository-projects: read
with:
strip: "demo, doc, examples, help, html, include, tests, vignette"

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.8.1.9001
Version: 1.8.1.9991
Authors@R: c(
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@posit.co", comment = c(ORCID = "0000-0002-1576-2126")),
person("Joe", "Cheng", role = "aut", email = "joe@posit.co"),
@@ -213,3 +213,36 @@ RdMacros: lifecycle
Config/testthat/edition: 3
Config/Needs/check:
shinytest2
Config/Needs/wasm:
R6,
Rcpp,
base64enc,
bslib,
cachem,
cli,
codetools,
commonmark,
crayon,
digest,
ellipsis,
fastmap,
fontawesome,
fs,
glue,
htmltools,
httpuv,
jquerylib,
jsonlite,
later,
lifecycle,
magrittr,
memoise,
mime,
promises,
rappdirs,
renv,
rlang,
sass,
sourcetools,
withr,
xtable

View File

@@ -1515,41 +1515,44 @@ hybrid_chain <- function(expr, ..., catch = NULL, finally = NULL,
do <- function() {
runFinally <- TRUE
tryCatch(
{
captureStackTraces({
result <- withVisible(force(expr))
if (promises::is.promising(result$value)) {
# Purposefully NOT including domain (nor replace), as we're already in
# the domain at this point
p <- promise_chain(valueWithVisible(result), ..., catch = catch, finally = finally)
runFinally <- FALSE
p
} else {
result <- Reduce(
function(v, func) {
if (v$visible) {
withVisible(func(v$value))
} else {
withVisible(func(invisible(v$value)))
}
},
list(...),
result
)
on.exit({ if (runFinally && !is.null(finally)) finally() })
valueWithVisible(result)
}
})
},
error = function(e) {
if (!is.null(catch))
catch(e)
else
stop(e)
},
finally = if (runFinally && !is.null(finally)) finally()
catch_e <- NULL
delayedAssign("do_catch",
if (!is.null(catch)) {
catch(catch_e)
return()
} else {
stop(catch_e)
}
)
handlers <- list(error = function(e) { catch_e <<- e; do_catch })
classes <- names(handlers)
.Internal(.addCondHands(classes, handlers, parent.frame(), NULL, TRUE))
result <- withVisible(force(expr))
if (promises::is.promising(result$value)) {
# Purposefully NOT including domain (nor replace), as we're already in
# the domain at this point
p <- promise_chain(valueWithVisible(result), ..., catch = catch, finally = finally)
runFinally <- FALSE
p
} else {
result <- Reduce(
function(v, func) {
if (v$visible) {
withVisible(func(v$value))
} else {
withVisible(func(invisible(v$value)))
}
},
list(...),
result
)
valueWithVisible(result)
}
}
if (!is.null(domain)) {

View File

@@ -129,7 +129,7 @@ test_that("integration tests", {
df <- causeError(full = FALSE)
# dumpTests(df)
expect_equal(df$num, c(56L, 55L, 54L, 38L, 37L, 36L, 35L, 34L, 33L))
expect_equal(df$num, c(53L, 52L, 51L, 35L, 34L, 33L, 32L, 31L, 30L))
expect_equal(df$call, c("A", "B", "<reactive:C>", "C", "renderTable",
"func", "force", "withVisible", "withCallingHandlers"))
expect_equal(nzchar(df$loc), c(TRUE, TRUE, TRUE, FALSE, TRUE,
@@ -138,12 +138,11 @@ test_that("integration tests", {
df <- causeError(full = TRUE)
# dumpTests(df)
expect_equal(df$num, c(59L, 58L, 57L, 56L, 55L, 54L, 53L,
52L, 51L, 50L, 49L, 48L, 47L, 46L, 45L, 44L, 43L, 42L, 41L,
40L, 39L, 38L, 37L, 36L, 35L, 34L, 33L, 32L, 31L, 30L, 29L,
28L, 27L, 26L, 25L, 24L, 23L, 22L, 21L, 20L, 19L, 18L, 17L,
16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L,
3L, 2L, 1L))
expect_equal(df$num, c(56L, 55L, 54L, 53L, 52L, 51L, 50L, 49L,
48L, 47L, 46L, 45L, 44L, 43L, 42L, 41L, 40L, 39L, 38L, 37L,
36L, 35L, 34L, 33L, 32L, 31L, 30L, 29L, 28L, 27L, 26L, 25L,
24L, 23L, 22L, 21L, 20L, 19L, 18L, 17L, 16L, 15L, 14L, 13L,
12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L))
expect_equal(df$call, c("h", ".handleSimpleError", "stop",
"A", "B", "<reactive:C>", "..stacktraceon..", ".func", "withVisible",
"withCallingHandlers", "contextFunc", "env$runWith", "force",
@@ -152,8 +151,8 @@ test_that("integration tests", {
"ctx$run", "self$.updateValue", "..stacktraceoff..", "C",
"renderTable", "func", "force", "withVisible", "withCallingHandlers",
"domain$wrapSync", "promises::with_promise_domain",
"captureStackTraces", "doTryCatch", "tryCatchOne", "tryCatchList",
"tryCatch", "do", "hybrid_chain", "renderFunc", "renderTable({ C() }, server = FALSE)",
"captureStackTraces", "withCallingHandlers", "do", "hybrid_chain",
"renderFunc", "renderTable({ C() }, server = FALSE)",
"..stacktraceon..", "contextFunc", "env$runWith", "force",
"domain$wrapSync", "promises::with_promise_domain",
"withReactiveDomain", "domain$wrapSync", "promises::with_promise_domain",
@@ -165,10 +164,9 @@ test_that("integration tests", {
TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
FALSE))
FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE))
})
test_that("shiny.error", {