Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to infer R is running in WebR? #414

Closed
HenrikBengtsson opened this issue Apr 17, 2024 · 7 comments · Fixed by #418
Closed

How to infer R is running in WebR? #414

HenrikBengtsson opened this issue Apr 17, 2024 · 7 comments · Fixed by #418
Labels
docs Improvements or additions to documentation feature New feature or request
Milestone

Comments

@HenrikBengtsson
Copy link

How can one check, programmatically, that we're running R via WebR?

A naive approach would be to use:

is_webr <- "webr" %in% loadedNamespaces()

but that assumes such a loaded package is WebR, but it could be another package with the same name, including the one on CRAN (Issue #165).

What other evidence can I look for conclude that we're running within WebR? I'm looking for something more robust, but also something that is sustainable. For example, looking for expected R options is not guaranteed. Neither is the attached webr_sham environment and its content.

@yutannihilation
Copy link
Contributor

I think .Platform$r_arch could be some meaningful value. Currently, it seems it's empty.

@georgestagg
Copy link
Member

There's some information in R.Version() that you can use:

> R.Version()
$platform
[1] "wasm32-unknown-emscripten"

$arch
[1] "wasm32"

$os
[1] "emscripten"

$system
[1] "wasm32, emscripten"
[...]

> version$os
[1] "emscripten"

We usually look for the "emscripten" string. This makes sense to me, Emscripten is like an alternative OS in many ways, and one day if R core supports building for wasm/Emscripten independently from webR your code will still work.

Checking for "wasm32" is an option, but one day we might migrate to "wasm64" when it is better supported in browsers.


This information should probably be documented somewhere in https://docs.r-wasm.org, I'll tag the issue as such.

@georgestagg georgestagg added docs Improvements or additions to documentation good first issue Good for newcomers labels Apr 18, 2024
@HenrikBengtsson
Copy link
Author

HenrikBengtsson commented Apr 18, 2024

Thanks. Though, strictly speaking, can't there be other alternative Wasm implementation for R showing up in the future that would show the same R.Version() information as WebR?

CLARIFICATION: I'm after detecting when running with WebR specifically.

@georgestagg
Copy link
Member

Yes, strictly speaking, that is true assuming the implementation also uses Emscripten as their Unix environment. A project compiling R for WASI/WASIX would likely have a different value there.

I guess we could possibly tweak $platform so that webr is part of the target triple in the vendor slot?

wasm32-webr-emscripten

@georgestagg georgestagg added feature New feature or request and removed good first issue Good for newcomers labels Apr 18, 2024
@georgestagg
Copy link
Member

CLARIFICATION: I'm after detecting when running with WebR specifically.

Part of the problem is that the WebAssembly R binary itself knows little about the surrounding webR JavaScript/TypeScript environment other than through the supporting webr R package, which talks to the outside world using Emscripten's C API.

Most of webR's functionality is exposed through a JavaScript Module object, but Emscripten provides a Unix-like API so that while JavaScript functions like Module.print() are eventually called, to the R Wasm binary it just looks like it's running under a Unix-like OS.

Thinking about it, I suppose the webR JavaScript environment is more akin to RStudio than an OS or platform detail and so the host_vendor is not really the right place for this.

Perhaps we could add an export to the webR support package to signal in some way that this is webR, and not the CRAN {webr} package? Maybe webr::is_webr() to always return TRUE, or a webr::version() function.

Alternatively, we could just set some environment variables, similar to RSTUDIO=1? We could set WEBR=1 and perhaps WEBR_VERSION=0.3.2. Of course, environment variables are not entirely robust either.


A hacky check that would work right now could be something like:

webr::eval_js("'webr' in Module")

which directly checks the JavaScript environment to see if the webr property has been defined on the module. This will return 1 when running under webR. Unfortunately, it relies on the webr support package to run the JavaScript check, which would only be available under webR in any case. So, possibly not that useful for you.

@HenrikBengtsson
Copy link
Author

HenrikBengtsson commented Apr 18, 2024

Part of the problem is that the WebAssembly R binary itself knows little about the surrounding webR JavaScript/TypeScript environment other than through the supporting webr R package, which talks to the outside world using Emscripten's C API.

Thanks for clarifying this - this is useful; my understanding how webR works is at best so-and-so right now.

Perhaps we could add an export to the webR support package to signal in some way that this is webR, and not the CRAN {webr} package? Maybe webr::is_webr() to always return TRUE, or a webr::version() function.

I think webr::is_webr() could work. Not sure if webr::version() would help? Are you thinking about something different that packageVersion("webr") here?

Alternatively, we could just set some environment variables, similar to RSTUDIO=1? We could set WEBR=1 and perhaps WEBR_VERSION=0.3.2. Of course, environment variables are not entirely robust either.

That would definitely work too.

The reason why I came to this is that I wanted to add a flag webr to startup::sysinfo() to indicate whether running in webR or not. I already detect other environments this way. Here's a summary of flags that I currently detect and how:

  • ess: Emacs Speaks Statistics (ESS): is.element("ESSR", search())
  • microsoftr: Microsoft R Open: exists("Revo.version", mode = "list", envir = baseenv(), inherits = FALSE)
  • pqr: A Pretty Quick Version of R (pqR): "pqR.base.version" %in% names(R.version)
  • radian: Radian: nzchar(Sys.getenv("RADIAN_VERSION"))
  • rstudio: RStudio Console: (Sys.getenv("RSTUDIO") == "1") && !nzchar(Sys.getenv("RSTUDIO_TERM"))
  • rstudioterm: RStudio Terminal: (Sys.getenv("RSTUDIO") == "1") && nzchar(Sys.getenv("RSTUDIO_TERM"))
  • wine: WineHQ: (.Platform$OS.type == "windows") && any(grepl("^WINE", names(Sys.getenv())))

A hacky check that would work right now could be something like:

webr::eval_js("'webr' in Module")

That works for my needs. I can do something like:

is_webr <- function() {
  if (!"webr" %in% loadedNamespaces()) return(FALSE)
  ns <- getNamespace("webr")
  if (!exists("eval_js", mode = "function", envir = ns)) return(FALSE)
  eval_js <- get("eval_js", mode = "function", envir = ns)
  eval_js("'webr' in Module") == 1L
}

BTW, is 'webR' how you want to refer to it? I've been using WebR thus far, but better to use the official notation.

@georgestagg
Copy link
Member

Thank you for sharing those other examples -- I think that's enough to convince me that an environment variable is indeed the right way to go. I'll try to get that in before next release.


BTW, is 'webR' how you want to refer to it? I've been using WebR thus far, but better to use the official notation.

I use "webR" unless it's at the start of a sentence, in which case I use "WebR". I don't mind how people refer to it, other than that it should never be "WEBR".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation feature New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants