@@ -236,11 +236,46 @@ getGlobalsAndPackages <- function(expr, envir = parent.frame(), tweak = tweakExp
236236 # # To please R CMD check
237237 a <- `future.call.arguments` <- NULL
238238 rm(list = c(" a" , " future.call.arguments" ))
239+
240+ # # If ...future.FUN() in globals, then ...
241+ if (" ...future.FUN" %in% names(globals )) {
242+ envFUN <- environment(globals [[" ...future.FUN" ]])
243+ # # Update environment of FUN(), unless it's a primitive function
244+ # # or a function in a namespace
245+ if (! is.null(envFUN ) && ! isNamespace(envFUN )) {
246+ expr <- substitute({
247+ " # future::getGlobalsAndPackages(): FUN() uses '...' internally "
248+ " # without having an '...' argument. This means '...' is treated"
249+ " # as a global variable. This may happen when FUN() is an "
250+ " # anonymous function. "
251+ " # "
252+ " # If an anonymous function, we will make sure to restore the "
253+ " # function environment of FUN() to the calling environment. "
254+ " # We assume FUN() an anonymous function if it lives in the "
255+ " # global environment, which is where globals are written. "
256+ penv <- env <- environment(... future.FUN )
257+ repeat {
258+ if (identical(env , globalenv()) || identical(env , emptyenv()))
259+ break
260+ penv <- env
261+ env <- parent.env(env )
262+ }
263+ if (identical(penv , globalenv())) {
264+ environment(... future.FUN ) <- environment()
265+ } else if (! identical(penv , emptyenv()) && ! is.null(penv ) && ! isNamespace(penv )) {
266+ parent.env(penv ) <- environment()
267+ }
268+ rm(list = c(" env" , " penv" ), inherits = FALSE )
269+ a
270+ }, list (a = expr ))
271+ }
272+ }
273+
239274 expr <- substitute({
240- # # covr: skip=1
241275 " # future::getGlobalsAndPackages(): wrapping the original future"
242276 " # expression in do.call(), because function called uses '...' "
243277 " # as a global variable "
278+ # # covr: skip=1
244279 do.call(function (... ) a , args = `future.call.arguments` )
245280 }, list (a = expr ))
246281 if (debug ) {
0 commit comments