Skip to content

bs_dependency_defer()  factory-built closures collide on the memoise cache #1330

Description

@AleKoure

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:

  1. 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.
  2. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority: MediumValid bug or well-defined request with moderate impact or a workaround.ai-triage:doneMarks an issue whose AI triage workflow is complete.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions