rstudio / rstudio/bslib

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

Open
#1,330 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ai-triage:done Priority: Medium
Dominant language
SCSS
Stars
569
Forks
72
Avg merge
1d 2h
Merged PRs (30d)
5

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the bs_dependency_defer() entry point and reproduce the collision with the provided R factory example. Inspect how the memoise key is built from the closure, then review ?bs_dependency_defer and the “Dynamically themeable component” vignette. Done means factory-built dependencies no longer return the first component’s result, or the documented workaround clearly prevents the collision.

Written by the indexing model from the issue text.

Assessment

Tech stack
r, sass
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.