bs_dependency_defer(func) memoises func against a shared cache keyed on formals(f) + body(f) + call args. Closures produced by a factory (the pattern from the "Dynamically themeable component" vignette) only differ in captured variables, so they all hash to the same key and every dependency after the first is served the first one's compiled output.
library(bslib)
mk_dep <- function(name, css) {
bs_dependency_defer(function(theme) {
if (!is_bs_theme(theme)) theme <- bs_theme(version = 5)
tmp <- tempfile(fileext = ".scss"); writeLines(css, tmp)
bs_dependency(input = sass::sass_file(tmp), theme = theme,
name = paste0("test-", name), version = "0.0.0")
})
}
mk_dep("red", ".x{color:red}")()$name
mk_dep("blue", ".x{color:blue}")()$name
#> [1] "test-red"
#> [1] "test-red" # expected "test-blue"
Today's viable workarounds are either memoise = FALSE or the one-liner in the docs suggestion below.
Suggested fixes:
- Code: add an optional cache_key to bs_dependency_defer() folded into the memoise key: bs_dependency_defer(func, memoise = TRUE, cache_key = NULL) . Callers pass a stable per-component id and the collision is gone. Happy to PR.
- Docs: update the "Dynamically themeable component" vignette + ?bs_dependency_defer to warn about the shared-cache collision when func is factory-built, and show the caller-side one-liner, give the sole theme formal a per-component default so formals(f) differs per component:
build <- function(theme) { ... }
formals(build)$theme <- "unique-per-component-id"
bs_dependency_defer(build)
Happy to PR either.
bs_dependency_defer(func)memoisesfuncagainst a shared cache keyed onformals(f)+body(f)+ call args. Closures produced by a factory (the pattern from the "Dynamically themeable component" vignette) only differ in captured variables, so they all hash to the same key and every dependency after the first is served the first one's compiled output.Today's viable workarounds are either memoise = FALSE or the one-liner in the docs suggestion below.
Suggested fixes:
Happy to PR either.