rstudio / htmltools

Tools for HTML generation and output
https://rstudio.github.io/htmltools/
214 stars 67 forks source link

tagQuery remove method raises an error #346

Closed federiva closed 1 year ago

federiva commented 1 year ago

The problem

When trying to remove a tag using the remove method I'm getting the following error. This error is not being raised when I'm trying to remove other tags from the same object.

Error in child$envKey : object of type 'closure' is not subsettable

Steps to reproduce - Trying to remove the label from the selectInput widget

# get the selectInput
html <- selectInput("select_id", "label", letters)
# Remove the label
tagQuery(html)$
    find("label")$
    remove()

More info

My attempt at debugging

I found that when the error is raised the selectedWalkIRev function is calling func(els, fn) in its body. The error is raised when within this function we are trying to get the envKey attribute therefore raising the aforementioned error.

The cause when this is happening is that we are passing a function in the els list which I suppose is being brought from before, upper in the call stack. (See the third element below)

els
[[1]]
<!-- shiny.tag.env --> 
<label class="control-label" id="select_id-label" for="select_id">label</label>

[[2]]
<!-- shiny.tag.env --> 
<div>
  <select id="select_id"><option value="a" selected>a</option>
<option value="b">b</option>
# cutting the output here...

[[3]]
function () 
{
    if (is_shiny_app()) {
        shiny::registerThemeDependency(func)
        return(mfunc(get_current_theme()))
    }
    mfunc(bs_global_get())
}
<bytecode: 0x5641e4c32168>
<environment: 0x5641e7ac49e8>
attr(,"class")
[1] "shiny.tag.function"

R version and package version

R version 4.2.1 htmltools 0.5.3

Traceback

9: .f(.x[[i]], i, ...)
8: func(els, fn)
7: selectedWalkIRev(elParent$children, function(child, childPos) {
       if (!isTagEnv(el)) 
           return()
       childKey <- child$envKey
       if (elKey == childKey) {
           func(elParent, el, childPos)
           asTagEnv(elParent)
       }
   })
6: .f(.x[[i]], ...)
5: func(els, fn)
4: tagQueryWalk(els, function(el) {
       if (!isTagEnv(el)) 
           return()
       elKey <- el$envKey
       elParent <- el$parent
       selectedWalkIRev(elParent$children, function(child, childPos) {
           if (!isTagEnv(el)) 
               return()
           childKey <- child$envKey
           if (elKey == childKey) {
               func(elParent, el, childPos)
               asTagEnv(elParent)
           }
       })
   })
3: tagQueryMatchChildRev(els, function(elParent, el, childPos) {
       el$parent <- NULL
       elParent$children[[childPos]] <- NULL
   })
2: tagQuerySiblingRemove(selected_)
1: tagQuery(html)$find("label")$remove()
schloerke commented 1 year ago

Thank you for the reprex!