Nothing
#' @details `extractStackTrace` takes a list of calls (e.g. as returned
#' from `conditionStackTrace(cond)`) and returns a data frame with one
#' row for each stack frame and the columns `num` (stack frame number),
#' `call` (a function name or similar), and `loc` (source file path
#' and line number, if available). It was deprecated after shiny 1.0.5 because
#' it doesn't support deep stack traces.
#' @rdname stacktrace
#' @export
extractStackTrace <- function(calls,
full = get_devmode_option("shiny.fullstacktrace", FALSE),
offset = getOption("shiny.stacktraceoffset", TRUE)) {
srcrefs <- getSrcRefs(calls)
if (offset) {
# Offset calls vs. srcrefs by 1 to make them more intuitive.
# E.g. for "foo [bar.R:10]", line 10 of bar.R will be part of
# the definition of foo().
srcrefs <- c(utils::tail(srcrefs, -1), list(NULL))
}
calls <- setSrcRefs(calls, srcrefs)
callnames <- getCallNames(calls)
# Hide and show parts of the callstack based on ..stacktrace(on|off)..
if (full) {
toShow <- rep.int(TRUE, length(calls))
} else {
# Remove stop(), .handleSimpleError(), and h() calls from the end of
# the calls--they don't add any helpful information. But only remove
# the last *contiguous* block of them, and then, only if they are the
# last thing in the calls list.
hideable <- callnames %in% c("stop", ".handleSimpleError", "h")
# What's the last that *didn't* match stop/.handleSimpleError/h?
lastGoodCall <- max(which(!hideable))
toRemove <- length(calls) - lastGoodCall
# But don't remove more than 5 levels--that's an indication we might
# have gotten it wrong, I guess
if (toRemove > 0 && toRemove < 5) {
calls <- utils::head(calls, -toRemove)
callnames <- utils::head(callnames, -toRemove)
}
toShow <- stripStackTraces(list(callnames))[[1]]
toShow <-
toShow &
# doTryCatch, tryCatchOne, and tryCatchList are not informative--they're
# just internals for tryCatch
!(callnames %in% c("doTryCatch", "tryCatchOne", "tryCatchList")) &
# doWithOneRestart and withOneRestart are not informative--they're
# just internals for withRestarts
!(callnames %in% c("withOneRestart", "doWithOneRestart"))
}
calls <- calls[toShow]
calls <- rev(calls) # Show in traceback() order
index <- rev(which(toShow))
width <- floor(log10(max(index))) + 1
data.frame(
num = index,
call = getCallNames(calls),
loc = getLocs(calls),
# category = getCallCategories(calls),
stringsAsFactors = FALSE
)
}
cleanLocs <- function(locs) {
locs[!grepl("test-stacks\\.R", locs, perl = TRUE)] <- ""
# sub("^.*#", "", locs)
locs
}
dumpTests <- function(df) {
print(bquote({
expect_equal(df$num, .(df$num))
expect_equal(df$call, .(df$call))
expect_equal(nzchar(df$loc), .(nzchar(df$loc)))
}))
}
# Helper: run a render function whose body throws an error, capture the
# stack trace, apply fence-based filtering, and return the filtered data
# frame. The render function body should call a function that calls stop().
# `needs_session` indicates whether the render function requires
# shinysession/name parameters (TRUE for markRenderFunction-based renders
# like renderPlot and renderPrint, FALSE for createRenderFunction-based
# renders like renderText/renderTable/renderUI/renderImage which can be
# called with no args).
captureFilteredRenderTrace <- function(render_fn, needs_session = TRUE) {
session <- MockShinySession$new()
on.exit(if (!session$isClosed()) session$close())
res <- try({
captureStackTraces({
isolate({
withReactiveDomain(session, {
if (needs_session) {
render_fn(shinysession = session, name = "testoutput")
} else {
render_fn()
}
})
})
})
},
silent = TRUE)
cond <- attr(res, "condition", exact = TRUE)
stopifnot(!is.null(cond))
stopifnot(!is.null(conditionStackTrace(cond)))
suppressMessages(
extractStackTrace(conditionStackTrace(cond), full = FALSE)
)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.