Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
On Jul 28, 2013, at 10:29 AM, James Greene james.m.gre...@gmail.com wrote: 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. NodeIterator already has an ability to only include text nodes. It appears to me that we can also add an ability to match a selector. e.g. var nodeIterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT, null, 'div a'); can find all text nodes under elements that match 'div a'. On Jul 27, 2013, at 1:04 PM, Ojan Vafai o...@chromium.org wrote: 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. 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. NodeIterator has nextNode() and previousNode() already. Why can't we add firstNode() and lastNode()? On Jul 27, 2013, at 11:25 AM, Ojan Vafai o...@chromium.org wrote: Realized this should probably be a new thread... On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote: I think these are good points of what is lost by using static NodeLists. I still feel pretty strongly though that these benefits don't outweigh the costs. If we want to give people most of the benefits of live NodeLists without the costs we could expose an iterator API: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list 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 gets the performance benefits of live NodeLists, I think meets the What happens when you remove the previous node during the iteration? - R. Niwa
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
[whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
Realized this should probably be a new thread... On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote: On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 7/24/13 10:42 PM, Jussi Kalliokoski wrote: Argh, I had forgotten about live NodeLists. OK, this is a reason that resonates with me and justifies calling these methods obsolete. Too bad these methods are so badly flawed Fwiw, I think the performance impact of live NodeLists is ... unclear. Their existence does mean that you have to deal with DOM mutations changing the lists, but them being live also means you can make the list getters much faster in cases when the caller doesn't actually want the entire list. And, as importantly, it also means that for multiple consecutive calls to get the list, say inside of a loop, can return the same result object. I.e. you don't have to re-walk the DOM for every iteration through the loop. I think these are good points of what is lost by using static NodeLists. I still feel pretty strongly though that these benefits don't outweigh the costs. If we want to give people most of the benefits of live NodeLists without the costs we could expose an iterator API: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list 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 gets the performance benefits of live NodeLists, I think meets the main use-cases of not wanting to walk the whole DOM, but doesn't require the browser to do a lot of metadata tracking as you go. Ojan
Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
Isn't that what the NodeIterator and TreeWalker APIs are for? Sincerely, James Greene On Jul 27, 2013 1:25 PM, Ojan Vafai o...@chromium.org wrote: Realized this should probably be a new thread... On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote: On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 7/24/13 10:42 PM, Jussi Kalliokoski wrote: Argh, I had forgotten about live NodeLists. OK, this is a reason that resonates with me and justifies calling these methods obsolete. Too bad these methods are so badly flawed Fwiw, I think the performance impact of live NodeLists is ... unclear. Their existence does mean that you have to deal with DOM mutations changing the lists, but them being live also means you can make the list getters much faster in cases when the caller doesn't actually want the entire list. And, as importantly, it also means that for multiple consecutive calls to get the list, say inside of a loop, can return the same result object. I.e. you don't have to re-walk the DOM for every iteration through the loop. I think these are good points of what is lost by using static NodeLists. I still feel pretty strongly though that these benefits don't outweigh the costs. If we want to give people most of the benefits of live NodeLists without the costs we could expose an iterator API: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list 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 gets the performance benefits of live NodeLists, I think meets the main use-cases of not wanting to walk the whole DOM, but doesn't require the browser to do a lot of metadata tracking as you go. Ojan
Re: [whatwg] iterators intead of live NodeLists WAS: Proposal: Adding methods like getElementById and getElementsByTagName to DocumentFragments
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. 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. On Sat, Jul 27, 2013 at 12:42 PM, James Greene james.m.gre...@gmail.comwrote: Isn't that what the NodeIterator and TreeWalker APIs are for? Sincerely, James Greene On Jul 27, 2013 1:25 PM, Ojan Vafai o...@chromium.org wrote: Realized this should probably be a new thread... On Sat, Jul 27, 2013 at 10:58 AM, Ojan Vafai o...@chromium.org wrote: On Thu, Jul 25, 2013 at 1:42 PM, Jonas Sicking jo...@sicking.cc wrote: On Thu, Jul 25, 2013 at 9:05 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 7/24/13 10:42 PM, Jussi Kalliokoski wrote: Argh, I had forgotten about live NodeLists. OK, this is a reason that resonates with me and justifies calling these methods obsolete. Too bad these methods are so badly flawed Fwiw, I think the performance impact of live NodeLists is ... unclear. Their existence does mean that you have to deal with DOM mutations changing the lists, but them being live also means you can make the list getters much faster in cases when the caller doesn't actually want the entire list. And, as importantly, it also means that for multiple consecutive calls to get the list, say inside of a loop, can return the same result object. I.e. you don't have to re-walk the DOM for every iteration through the loop. I think these are good points of what is lost by using static NodeLists. I still feel pretty strongly though that these benefits don't outweigh the costs. If we want to give people most of the benefits of live NodeLists without the costs we could expose an iterator API: var iterator = document.querySelectorAll('div').iterator(); --- does some magic to not precompute the whole list 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 gets the performance benefits of live NodeLists, I think meets the main use-cases of not wanting to walk the whole DOM, but doesn't require the browser to do a lot of metadata tracking as you go. Ojan