Conversation
|
This only fixes selection.selectChildren, but does not fix other cases where you pass a “live” HTMLCollection to d3.selectAll or return an HTMLCollection from the function in selection.selectAll. Both of those cases allow an HTMLCollection to be considered an array here: Lines 1 to 5 in 464cb9a I think there are two ways we could go here. One would be for the array function to test for HTMLCollection more explicitly and force the conversion to a non-live array. The other (and it’s not exclusive) would be for selection.remove to run in reverse order, so that the last element is removed first, and thus selection.remove will remove all the elements even if the collection is live. My inclination is that we should do the first, and that if we do the first, we don’t really need to do the second. D3 selections are intended to be immutable (at least with respect to the elements they contain—obviously the elements themselves are mutable). That said, I’m not sure how best to detect HTMLCollection yet. We could do an instanceof check, but that might be overly precise. |
|
Oops, apparently NodeList can be live too, e.g. d3.selectAll(document.body.childNodes). So, copying an HTMLCollection into an Array solves only some of the problem, and there’s no (practical) way to distinguish between a NodeList that is live (e.g., element.childNodes) and a NodeList this is static (e.g., document.querySelectorAll). That said, we could still have a special path that avoids a copy for the common case of selection.selectAll(selector). |
fixes #275