-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: ParentNode.replaceAll() / ParentNode.replaceChildren() #478
Comments
Most of the time I just use I guess the value-add here would be for parent nodes that are not elements, so documents and document fragments. Do you often need to empty such nodes in your code? Could you give an example? |
@domenic, yes, an example comes to mind of re-populating |
IMHO, by using |
@jonathantneal your example could be replaced with @rianby64 The idea that the existing platform functionality "looks strange" is not a good justification for introducing a new feature into the web platform, with all the attendant implementation effort, testing effort, and speccing effort, not to mention the waiting that all web developers have to go through before it is available in all their target browsers. |
@domenic, I think the strangeness of |
OK. So there is no actual use case for this? Then my answer about how that's not a good justification remains. |
@domenic , it was my humble opinion about the @jonathantneal 's idea. For me is logic to expect something that empties the content of a tag. The name of Node.prototype.empty = function() {
this.innerHTML = '';
}; |
The justifications are to not use a loop ( If |
There's no such thing as "re-parsing an element". innerHTML = "" does the same thing as your proposed .empty(). I'll let @annevk make the call, but yes, I am pretty sure that is the preferred method for emptying an element. For documents, you've yet to present an example use case where you want to empty a document (as opposed to e.g. creating a new one using |
@domenic, understood. Thank you. You’ve indicated I do not have an example for emptying documents. I’ve only needed to empty iframe documents. iframe.contentDocument.empty() Being fully transparent, I only do this for creating “clean” shadow-dom-like fallbacks. And, admittedly, I see people using strings (via srcdoc) for this as well: https://codepen.io/chriscoyier/pen/rwvjVN Perhaps it’s old instincts, but I really thought |
You can also use |
We've had this proposed once before and the main argument then too was aesthetics. I guess it's worth considering, but it's also rather risky to add something like |
There are likely to be web compat issues here, since PrototypeJS defines the same name on |
@annevk great input. Out of curiosity what does happen to handlers on discarded nodes from |
@snuggs if there are no other references to the nodes or handlers, yes. |
Didn’t realize we’re still working around prototype. Sure, sure, I need no convincing. How about ... Are these performance statistics still relevant? If so, it definitely seems like this kind of functionality would still be helpful. |
I think the performance statistics are a good argument for filing a bug on various browsers. Please do so, if you can! |
If |
Other than being slightly clearer,
|
Thanks. Well, in PostCSS, it’s called
|
@annevk @domenic if I understand correctly the main argument for not adding method proposed here is "hey, we've got something like this already in the form of While I completely agree with this reasoning IMO the "ergonomics" should be seen in the broader context and not only number of characters to type. For me the main issue with lack of sth like I'm completely subscribing to the idea of keeping the platform APIs as simple and small as possible. But IMO the addition proposed here is valuable not because it will save few keystrokes - for me the main benefit would be a "platform-blessed" way of clearing children. This in turn could people less anxious about having too many choices and would ultimately make people happier :-) I guess tl'dr; is that I would like to add +1 for the proposal (whatever the final method name is). |
@domenic are you saying that people should file perf-related issues if different ways of clearing child nodes perform differently (ex. removeChild in a loop slower as compared to using innerText)? Or just file bugs if we have numbers that suggest removal being slow? I'm asking since in a test / benchark app I'm using removal of all (~1500) nodes take almost 1/2 time needed to create and attach those nodes in JS (~10ms to create nodes vs. ~4ms to delete them). It seems a lot but without having one "blessed" method of clearing children nodes and without knowing underlying implementation details it is hard to draw any conclussions that would justify opening issues on browsers side.... |
[...document.querySelectorAll('div')].forEach(node => document.body.appendChild(node)); I know there are many ways to do append/remove of NodeList, but with these functions implementers may choose the best way to perform |
We already have I recommended an alternative name, |
@pkozlowski-opensource |
The slowest way to empty a Node should be the fastest, therefore, we recommend the slowest way? I get it, sort of. Reality vs Theory. Does that close out this issue? Kudos to the people who have time to convince browser vendors to make innerHTML the fastest. Perhaps, if replace all is a concept, browsers can just expose some form of |
Slowest? Pointer? Per the link above |
Exposing "replace all" sounds interesting. |
fwiw setting textContent and setting innerHTML are not the same. It looks like Gecko has an optimization for innerHTML: and enumerates all the special cases for parsing: WebKit and Blink don't do that, but probably should. It still doesn't help in lots of cases though, for example it's disabled for tables which is a place where folks often clear all children to insert new rows. I do think a |
@jonathantneal are you interested in driving this? What remains here is a PR to the DOM Standard and a PR to WPT. |
I’ll do that. I may need help along the way. |
PR #755 has been made to add this functionality to the DOM spec (for those who just follow this conversation). This is my first pull request to this repository, so my instinct is that corrections will need to be made. I will do my best to address corrections promptly and be patient with reviews. As time permits, I will look into filing a remaining PR to WPT repository. |
WebKit team at Apple supports the addition of this API. WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=198578 |
@rniwa IIRC I believe the API is supposed to be |
Noticed when linked from description in whatwg#478 References: - https://github.com/whatwg/dom/blob/master/dom.bs#L2327 - https://github.com/whatwg/dom/blob/master/dom.bs#L2408 - https://github.com/whatwg/dom/blob/master/dom.bs#L2514 - https://github.com/whatwg/dom/blob/master/dom.bs#L3806 - https://github.com/whatwg/dom/blob/master/dom.bs#L5070 - https://github.com/whatwg/dom/blob/master/dom.bs#L5300 - https://github.com/whatwg/dom/blob/master/dom.bs#L5655
Tests: web-platform-tests/wpt#22524 Fixes #478. Closes #755 and closes #835.
Tests: web-platform-tests/wpt#22524 Fixes whatwg#478. Closes whatwg#755 and closes whatwg#835.
Just find replaceChildren() method. It is awesome! |
This isn't correct. They are both implemented using the exact same code paths in browsers, so any differences you are seeing are likely due to some other part of your setup. |
In theory, I think you're right.
Above code is usually used to setup, and |
If that's the only variable, I'd recommend filing a bug against Chrome. |
Is it just me, or is ParentNode.replaceChildren() problematic because of the choice to pass the children as a variable number of arguments? In practice, this limits the number of children you can append to ~120K on current Chrome before you get a |
@FergoTheGreat Is there a reason you're not using Canvas? An empty DOM element in Chrome requires around 1KB empty last I checked, and 120k of just those, without nested children, comes out to 0.1-0.2 GiB. If you need to constantly replace nodes like that, try Canvas 2D. That gives you an immediate mode API where you can just blank the screen ( Edit: you'll get far better performance this way as well. You may notice it suddenly gets buttery smooth with this. And you aren't the first one I had to advise to do this - once had another trying to use the DOM to manage a live SVG with 200k+ nodes and was starting to run into memory limitations around 250k nodes. |
In general we didn't optimize for appending numbers of elements that large because the overhead of creating the elements, computing the style, layout and paint ends up being so far outside what's reasonable for a frame duration on the main thread. To have reasonable web perf metrics you'd need to chunk the append way before the stack overflow. |
The ParentNode.replaceAll() or ParentNode.replaceChildren() method would remove all child nodes from the ParentNode while allowing the insertion of a new set of nodes. The best name is yet settled upon.
A “replace all” concept already exists in the spec.
Syntax
Example:
<select>
causes options to change in a corresponding Region<select>
:Rationale:
Like
append()
,prepend()
,before()
,after()
, andreplaceWith()
, we’re allowing developers to do something useful without a loop, e.g:Fallback Strategies
There are 2 common strategies to empty a ParentNode before inserting a new set of nodes (using
ParentNode.append
).The 1st strategy is to erase the innerHTML of a ParentNode. This is less meaningful and leads one to question the underlying implementation.
The 2nd strategy is to loop over and remove each child of the ParentNode. This is verbosE and leads one to wish for the same loop-free “sugar” provided to
append()
,prepend()
,before()
,after()
, andreplaceWith()
.Previous proposal (replaceAll)
Original Proposal (empty)
The ParentNode.empty() method would remove all child nodes from the parent node.
Syntax
Example:
In a filtering component, a change to one
<select>
swaps out the<option>
elements available to a second<select>
:Rationale:
Like
append()
,prepend()
,before()
,after()
, andreplaceWith()
, we’re allowing developers to do something useful without a loop, e.g:The text was updated successfully, but these errors were encountered: