diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d9f3621..1881562f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * fix(rstudioapi): resolve emulation issues and viewer routing * fix(liveshare): resolve activation errors, file reading bugs, and add hooks for sess compatibility +* fix(workspace): fix code submission delays when the workspace contains many or large objects ### Features @@ -16,6 +17,9 @@ * feat(session): implement file-based reconnection and suppress verbose logs * feat(plot): new `r.plot.backend` enum setting for finer-grained control of the preferred plotting backend, including integration with the lightweight `jgd` graphics device (default if installed). `r.plot.useHttpgd` is still respected, but may be deprecated in a future release. * feat(term): new `r.rterm.preferredConsoles` enum setting enables for string-based R console selection (`"R"` (default), `"arf"`, and/or `"radian"`), automatically resolved against the user's `PATH`. `r.term.` is still respected (and prioritized) if provided. +* feat(dataview): keep one viewer per data name, refreshing the existing viewer on repeated `View()` calls +* feat(dataview): load data rows on demand while scrolling, with support for Arrow and Polars DataFrames +* feat(workspace): support recursive expansion of nested lists, environments, pairlists, S4 objects, and data frames ### Performance @@ -24,6 +28,7 @@ ### Other * Remove the unused `r.workspaceViewer.showObjectSize` setting and obsolete object-size tooltip support +* Remove obsolete `r.session.objectLengthLimit`, `r.session.objectTimeout`, and `r.session.levelOfObjectDetail` settings following the switch to on-demand workspace inspection ### Styling diff --git a/sess/R/handlers.R b/sess/R/handlers.R index 37418865..e0da8a44 100644 --- a/sess/R/handlers.R +++ b/sess/R/handlers.R @@ -17,9 +17,13 @@ try_capture_str <- function(object, max_level = 0L) { ) } +workspace_env_names <- function(env) { + ls(env, sorted = FALSE) +} + workspace_child_count <- function(object) { if (is.environment(object)) { - length(object) + length(workspace_env_names(object)) } else if (isS4(object)) { length(methods::slotNames(object)) } else if (typeof(object) %in% c("list", "pairlist")) { @@ -31,7 +35,7 @@ workspace_child_count <- function(object) { get_workspace_data <- function() { env <- .GlobalEnv - all_names <- ls(env, sorted = FALSE) + all_names <- workspace_env_names(env) objs <- lapply(all_names, function(name) { if (bindingIsActive(name, env)) { @@ -141,7 +145,7 @@ get_workspace_children <- function(name, path = list(), start = 1L) { } children <- if (is.environment(object)) { - child_names <- ls(object, sorted = FALSE)[seq.int(start, end)] + child_names <- workspace_env_names(object)[seq.int(start, end)] lapply(child_names, function(child_name) { if (bindingIsActive(child_name, object)) { list( diff --git a/sess/inst/tinytest/test-ipc.R b/sess/inst/tinytest/test-ipc.R index a20a05ed..1482e106 100644 --- a/sess/inst/tinytest/test-ipc.R +++ b/sess/inst/tinytest/test-ipc.R @@ -50,6 +50,22 @@ local({ expect_false(isTRUE(result)) }) +# Environment expansion must retain visible members when hidden bindings exist (R6). +local({ + name <- basename(tempfile("workspace_environment_")) + object <- new.env(parent = emptyenv()) + object$values <- list(first = 1L) + object$.hidden <- TRUE + assign(name, object, envir = .GlobalEnv) + on.exit(rm(list = name, envir = .GlobalEnv), add = TRUE) + + page <- sess:::get_workspace_children(name) + expect_equal( + lapply(page$children, function(child) child$selector), + list(list(kind = "name", value = "values")) + ) +}) + # dataview init/page/dispose lifecycle works local({ .sess_env <- sess:::.sess_env