Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
I strongly agree with the use-case, and think some feature for this would be very helpful. [Mixing up your emails for reply convenience.] On Sat, Jul 27, 2013 at 11:25 AM, Ojan Vafai o...@chromium.org wrote: On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list Can you describe this magic? It would be nice if this were somehow possible, but I'm not sure how it would be. There are many places where we expose SequenceNode or NodeList that can't easily be replaced with hand-rolled DOM walking (e.g. getNamedFlows). You could imagine NodeIterator taking a SequenceNode/NodeList as an argument to it's constructor instead of adding an iterator method, but I find the NodeIterator interface to be clunky and awkward. Yeah, having the ability to produce these iterators for any of the currently-static Node lists would be great. But again, not sure how the magic would work. :/ while (let current = iterator.next()) { ... } And next always does the walk from the current node. So, if you add a div before the current node, this specific iterator won't hit it, but if you add a div after it would. I'm not sure what should happen though if you remove the node that's the current node. I think I'm OK with the iterator just returning null for the next() call in that case. Thinking more on this, I think we could make next() still work in the case where you remove the node by pointing current at the previous node in the tree. Then you could do things like: while (let current = iterator.next()) { current.remove(); } This should be an ES iterator, rather than a custom DOM thing that looks almost exactly like an ES iterator. I think the methods we'd want here are next, previous, first and last. That way you can walk the iterator forward or backward. This doesn't overlap well with NodeIterator's current API. How useful is it to be able to walk an iterator in both directions at the same time? I suppose we can produce an iterator subclass that also has the additional methods we want. ~TJ
Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
I think it makes sense, too. That said, if the goal is to REPLACE the NodeIterator and TreeWalker APIs completely, it wouldn't be all that valuable for me as my most common use case has always been to get TEXT NODES from under a root node based on some CSS filtering of its ancestor nodes. If the proposed API used only CSS query selectors without also allowing the additional NodeType filtering provided whatToShow, then it could not not be used to directly gather text nodes. Might be OK to leave text nodes out... not sure how others use NIs/TWs. Sincerely, James Greene On Jul 28, 2013 11:24 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: I strongly agree with the use-case, and think some feature for this would be very helpful. [Mixing up your emails for reply convenience.] On Sat, Jul 27, 2013 at 11:25 AM, Ojan Vafai o...@chromium.org wrote: On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list Can you describe this magic? It would be nice if this were somehow possible, but I'm not sure how it would be. There are many places where we expose SequenceNode or NodeList that can't easily be replaced with hand-rolled DOM walking (e.g. getNamedFlows). You could imagine NodeIterator taking a SequenceNode/NodeList as an argument to it's constructor instead of adding an iterator method, but I find the NodeIterator interface to be clunky and awkward. Yeah, having the ability to produce these iterators for any of the currently-static Node lists would be great. But again, not sure how the magic would work. :/ while (let current = iterator.next()) { ... } And next always does the walk from the current node. So, if you add a div before the current node, this specific iterator won't hit it, but if you add a div after it would. I'm not sure what should happen though if you remove the node that's the current node. I think I'm OK with the iterator just returning null for the next() call in that case. Thinking more on this, I think we could make next() still work in the case where you remove the node by pointing current at the previous node in the tree. Then you could do things like: while (let current = iterator.next()) { current.remove(); } This should be an ES iterator, rather than a custom DOM thing that looks almost exactly like an ES iterator. I think the methods we'd want here are next, previous, first and last. That way you can walk the iterator forward or backward. This doesn't overlap well with NodeIterator's current API. How useful is it to be able to walk an iterator in both directions at the same time? I suppose we can produce an iterator subclass that also has the additional methods we want. ~TJ
Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
On 7/27/13 10:58 AM, Ojan Vafai wrote: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list Well, so... not precompute but make it some sort of live, or not precompute but represent a frozen set of nodes? What should happen with this situation: var list = document.querySelectorAll('div'); var iterator = list.iterator(); Should the list of nodes be precomputed in this case? Basically, the magic sounds like it's ... very magical. Magical enough that authors would have a tough time with this setup, even ignoring implementation concerns. -Boris
Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
On Sun, Jul 28, 2013 at 11:10 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 7/27/13 10:58 AM, Ojan Vafai wrote: var iterator = document.querySelectorAll('**div').iterator(); --- does some magic to not precompute the whole list Well, so... not precompute but make it some sort of live, or not precompute but represent a frozen set of nodes? What should happen with this situation: var list = document.querySelectorAll('**div'); var iterator = list.iterator(); Should the list of nodes be precomputed in this case? Basically, the magic sounds like it's ... very magical. Magical enough that authors would have a tough time with this setup, even ignoring implementation concerns. I was just picturing lazy computing the list. You don't need to compute the list until you query the length or index into the NodeList, at which point, if it's a static NodeList, you compute the whole thing in one go. If all you ever do is grab the iterator, then no need to compute the list. So, the example you give above would not precompute. Now that I put it in writing, the obvious problem with this is that it's a change in semantics. If you querySelectorAll and then modify the DOM before reading the length or an index, then you get a different list. :(
Re: [whatwg] Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
On Sun, Jul 28, 2013 at 1:59 PM, Ojan Vafai o...@chromium.org wrote: On Sun, Jul 28, 2013 at 11:10 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 7/27/13 10:58 AM, Ojan Vafai wrote: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list Well, so... not precompute but make it some sort of live, or not precompute but represent a frozen set of nodes? What should happen with this situation: var list = document.querySelectorAll('div'); var iterator = list.iterator(); Should the list of nodes be precomputed in this case? Basically, the magic sounds like it's ... very magical. Magical enough that authors would have a tough time with this setup, even ignoring implementation concerns. I was just picturing lazy computing the list. You don't need to compute the list until you query the length or index into the NodeList, at which point, if it's a static NodeList, you compute the whole thing in one go. If all you ever do is grab the iterator, then no need to compute the list. So, the example you give above would not precompute. Now that I put it in writing, the obvious problem with this is that it's a change in semantics. If you querySelectorAll and then modify the DOM before reading the length or an index, then you get a different list. :( It's not just a change in semantics, it's a change in behavior. To keep the same behavior you would have to make the static NodeList observe the DOM and precompute itself as soon as the DOM was modified. I.e. static NodeLists would incur the same performance problems that Ryosuke expressed concern about that live NodeLists have. So yeah, I don't think it's an option. In general, I'm not a big fan of anything that adds capabilities to all NodeLists. This has been brought up in the past when people suggested adding the ability to observe changes to all NodeLists. It's not at all obvious to me that in *all* situations where we use NodeLists that it is desired to be able to iterate the results lazily. Requiring that might force implementations to spend a lot of time implementing something that doesn't have use cases. We should think of NodeLists as simple Arrays. And it's clear that we don't want to force any function that returns an Array to be able to lazily compute that Array using an iterator. Keep in mind that the laziness is observable, so it's not a valid implementation strategy to only do the lazyness where there are clear performance benefits. / Jonas