Skip to content

Commit 5e6bfa1

Browse files
authored
Fix command hang with { expressions when browser() is active (#1170)
1 parent d33d0eb commit 5e6bfa1

File tree

5 files changed

+51
-11
lines changed

5 files changed

+51
-11
lines changed

doc/newfeat.texi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
Changes and New Features in 19.04 (unreleased):
55
@itemize @bullet
66

7+
@item ESS[R]: @code{ess-command} now runs R code in a sandboxed environment.
8+
Use @code{.ess.environment()} to inspect the current environment.
9+
710
@item ESS[R]: Added support for new syntax in R 4.0 and R 4.1.
811
This concerns raw strings, lambda functions, and the pipe operator.
912

etc/ESSR/R/.basic.R

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ if(.ess.Rversion < "1.8")
222222

223223
writeLines(paste0(sentinel, "-START"))
224224

225+
.ess.environment.state$env <- parent.frame()
226+
on.exit(.ess.environment.state$env <- NULL, add = TRUE)
227+
228+
225229
## Don't interrupt `browser()` sessions (#1081)
226230
restart <- function(...) {
227231
if (!is.null(findRestart("browser")))
@@ -241,3 +245,9 @@ if(.ess.Rversion < "1.8")
241245
## Keep `.Last.value` stable
242246
invisible(.Last.value)
243247
}
248+
249+
.ess.environment.state <- new.env(parent = emptyenv())
250+
251+
.ess.environment <- function() {
252+
.ess.environment.state$env
253+
}

lisp/ess-r-mode.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ fill=TRUE); try(traceback(), silent=TRUE)})\n")
481481

482482
(defun ess-r-format-command (cmd &rest args)
483483
(let ((sentinel (alist-get 'output-delimiter args)))
484-
(format ".ess.command(%s, '%s')\n" cmd sentinel)))
484+
(format ".ess.command(local(%s), '%s')\n" cmd sentinel)))
485485

486486
(defvar ess-r-format-command-alist
487487
'((fun . ess-r-format-command)

test/ess-test-inf.el

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,19 @@
134134
:inf-result ""
135135
:eval (should (inferior-ess-available-p)))
136136

137+
(defun ess-test--browser ()
138+
(ess-send-string (ess-get-process) "{ browser(); NULL }\n")
139+
(ess-wait-for-process))
140+
141+
(defun ess-test--browser-cleanup ()
142+
(ess-debug-command-quit)
143+
(ess-wait-for-process)
144+
(etest-clear-inferior-buffer))
145+
137146
(etest-deftest-r ess--command-browser-timeout-test ()
138147
"`ess-command' fails with hanging command within browser (#1081)."
139-
:cleanup (progn
140-
(ess-debug-command-quit)
141-
(ess-wait-for-process)
142-
(etest-clear-inferior-buffer))
143-
:eval (progn
144-
(ess-send-string (ess-get-process) "{ browser(); NULL }\n")
145-
(ess-wait-for-process))
148+
:cleanup (ess-test--browser-cleanup)
149+
:eval (ess-test--browser)
146150
:inf-result "Called from: top level
147151
Browse[1]> debug at #1: NULL
148152
Browse[1]> "
@@ -160,6 +164,29 @@ Browse[1]> "
160164
:inf-result "NULL
161165
Browse[1]> ")
162166

167+
(etest-deftest-r ess-command-browser-curly-braces ()
168+
"`{` expressions when debugger is active do not interrupt command."
169+
:cleanup (ess-test--browser-cleanup)
170+
:eval (ess-test--browser)
171+
:inf-result "Called from: top level
172+
Browse[1]> debug at #1: NULL
173+
Browse[1]> "
174+
175+
:eval (should (string= (ess-string-command "{ 1; 2 }\n")
176+
"[1] 2"))
177+
:inf-result ""
178+
:eval (should (inferior-ess-available-p)))
179+
180+
(etest-deftest-r ess-command-environment ()
181+
"Can access current env with `.ess.environment()`"
182+
:cleanup (ess-test--browser-cleanup)
183+
:eval (progn
184+
(ess-send-string (ess-get-process)
185+
"local({ foo <- 1; browser(); NULL })\n")
186+
(ess-wait-for-process))
187+
:eval (should (string= (ess-string-command "ls(envir = .ess.environment())\n")
188+
"[1] \"foo\"")))
189+
163190
(etest-deftest-r ess-command-quit-test ()
164191
"`ess-command' does not leak output on quit (#794, #842).
165192
This is especially important within `while-no-input' used by

test/ess-test-r.el

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,10 +838,10 @@ https://github.com/emacs-ess/ESS/issues/725#issuecomment-431781558"
838838
:inf-cleanup
839839
(progn
840840
(kill-buffer ess-rdired-buffer)
841-
(ess-command "rm(my_rdired_variable)\n"))
842-
841+
(ess-command "rm(my_rdired_variable, envir = globalenv())\n"))
842+
843843
:eval
844-
((ess-command "my_rdired_variable <- TRUE\n")
844+
((ess-command "assign('my_rdired_variable', TRUE, envir = globalenv())\n")
845845
(save-window-excursion
846846
(ess-rdired))
847847
(with-current-buffer ess-rdired-buffer

0 commit comments

Comments
 (0)