| Summary: | No-op textContent replacement could be short-circuited, like in Chrome | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | Ahmad Saleem <ahmad.saleem792> |
| Component: | DOM | Assignee: | Nobody <webkit-unassigned> |
| Status: | NEW --- | ||
| Severity: | Normal | CC: | annevk, ap, bfulgham, cdumez, cyb.ai.815, darin, heycam, karlcow, mmaxfield, rniwa, simon.fraser, webkit-bug-importer, zalan |
| Priority: | P2 | Keywords: | BrowserCompat, InRadar |
| Version: | WebKit Nightly Build | ||
| Hardware: | All | ||
| OS: | All | ||
| URL: | https://persistent.info/webkit/test-cases/selection-deletion.html | ||
| See Also: | https://bugs.webkit.org/show_bug.cgi?id=110682 | ||
|
Description
Ahmad Saleem
2022-08-30 15:57:07 PDT
The reason why this is happening in Safari and in Firefox is that the page replaces div.textContent every 100ms.
The reason why this doesn't happen in Chrome is that this operation is short-circuited there, the Node isn't replaced when the text isn't changing.
This optimization is not allowed per DOM Living Standard, but maybe the spec and WebKit can change if Chrome is getting away with it.
Easy to observe with a test like this:
<div id=div>aaa</div>
e = document.getElementById("div").firstChild
document.getElementById("div").textContent = "aaa";
e === document.getElementById("div").firstChild
# true in Chrome, false in other browsers.
> The textContent setter steps are to, if the given value is null, act as if it was the empty string instead, and then do as described below, switching on the interface this implements: > > … > > CharacterData > Replace data with node this, offset 0, count this’s length, and data the given value. in https://dom.spec.whatwg.org/#dom-node-textcontent and replace data in https://dom.spec.whatwg.org/#concept-cd-replace For the chrome optimization https://github.com/chromium/chromium/blob/924ec189cdfd33c8cee15d918f927afcb88d06db/third_party/blink/renderer/core/dom/node.cc#L2036-L2041 pointing to https://bugs.chromium.org/p/chromium/issues/detail?id=352836 as the source of the optimization. My steps in comment 1 aren't true to the original test case, which modifies document.querySelector("#dom").textContent. So this still seems like a Chrome bug per the spec? > Element > String replace all with the given value within this. yup, per spec. But I wonder if it could become an interesting optimization for all. Or if it has unintended consequences. Filed https://github.com/whatwg/dom/issues/1106 to discuss. Thanks for raising this Ahmad! One irony here is that in Safari’s early days we had a many "do less work because nothing changed" optimizations; part of "growing up" as a web browser engine was removing those because they harmed interoperability. I hope we do all agree to make this optimization a standard thing; given our shared WebKit roots I wonder when/why WebKit and Chromium diverged on this point. Should we mark this bug as MOVED while https://github.com/whatwg/dom/issues/1106 is being discussed? We usually don't do this. I don't think that it's beneficial to hide it in RESOLVED state when it's an observable compatibility issue. I am not sure whether it is same bug or not but I came across another such case: https://jsfiddle.net/2kEZ7/1/show Try to copy the numbers / result from rotated cube / square: getBoundingClientRect().width of div element is: xxxx <----- can't select this text. It happens in Chrome Canary 108, Safari 16 while Firefox Nightly 107 does allow you to copy it while clicking on the line and double clicking but not when you are trying to double click on the value. Just wanted to share. Thanks! |