Consider avoiding synchronously focusing elements as it triggers sync style flush
Categories
(Firefox :: General, enhancement, P2)
Tracking
()
Performance Impact | low |
People
(Reporter: xidorn, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: perf, perf:responsiveness)
Comment 1•7 years ago
|
||
Reporter | ||
Comment 2•7 years ago
|
||
Updated•7 years ago
|
Comment 3•7 years ago
|
||
Updated•6 years ago
|
Updated•2 years ago
|
Comment 4•2 years ago
|
||
5 years later, and we do actually try to do this in a number of places, but AIUI it's generally difficult for frontend to predict what focus calls are likely to trigger a style flush (ie when the flush is 'free' because we know there's nothing to update, and when it's not).
We could add a flag to the focus manager to prevent it from flushing, e.g. for the URL bar focusing case or the browser focusing case that we do on tabswitch, because frontend knows that the element is present and can be focused... but I don't know how feasible this really is, and as a general problem I wonder about how this affects web content, and if there's not a way that we can avoid the flushing on the backend instead of forcing all the consumers to adapt or pass magical chromeonly flags.
Emilio, do you have any thoughts/advice here?
Updated•2 years ago
|
Comment 5•2 years ago
|
||
It's hard to not flush for content because we don't really want to expose the concept of flushing there...
Rather than passing a magic flag via the focus manager it could be more convenient to just add it in the FocusOptions
dictionary, but other than that I don't have any other specific thoughts here.
Comment 6•2 years ago
•
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #5)
It's hard to not flush for content because we don't really want to expose the concept of flushing there...
Sorry for under-specifying my question. Yeah, I didn't mean to suggest exposing the concept of flushing to web content.
Rather, I wonder if we could:
- use an extant frame for a node if one exists and use that to determine if it's focusable and to then focus it
- register a callback for when the next restyle/layout flush happens and doublecheck the node is still focusable at that point
- revert focus to where it was if the focusability of the node has changed inbetween these two points.
Perhaps even just doing (1) would be sufficient here?
As part of looking at this, I poked at chromium and our source code for a bit. It seems they also flush layout, except they avoid it in a few cases (old link from paul irish's overview).
Then I looked at our source code, and I was confused. In particular, it looks like in chrome documents we never skip focusing nodes:
https://searchfox.org/mozilla-central/rev/dd2fe65d792943365a03fa996cdf9766829575b6/dom/base/Element.cpp#458,465-471 + https://searchfox.org/mozilla-central/source/dom/base/nsFocusManager.cpp#5328
This seems bad, and per bug 1366517 is a leftover from XBL-ness. Maybe that means we can get rid of it now?
It also seems like there may be other cases where we might avoid flushing (though they look unlikely, off-hand, to significantly impact the issues outlined here).
Comment 7•2 years ago
|
||
(In reply to :Gijs (he/him) from comment #6)
(In reply to Emilio Cobos Álvarez (:emilio) from comment #5)
It's hard to not flush for content because we don't really want to expose the concept of flushing there...
Sorry for under-specifying my question. Yeah, I didn't mean to suggest exposing the concept of flushing to web content.
Rather, I wonder if we could:
- use an extant frame for a node if one exists and use that to determine if it's focusable and to then focus it
That by definition would expose the flushing to the web (because there might be a pending display: none
change for example).
- register a callback for when the next restyle/layout flush happens and doublecheck the node is still focusable at that point
- revert focus to where it was if the focusability of the node has changed inbetween these two points.
Focus is really weird because you can do that kind of circular :focus { display: none }
shenanigans. Also focusing itself changes style...
https://searchfox.org/mozilla-central/rev/dd2fe65d792943365a03fa996cdf9766829575b6/dom/base/Element.cpp#458,465-471 + https://searchfox.org/mozilla-central/source/dom/base/nsFocusManager.cpp#5328
This seems bad, and per bug 1366517 is a leftover from XBL-ness. Maybe that means we can get rid of it now?
Yeah, that special-case seems worth trying to remove nowadays.
It also seems like there may be other cases where we might avoid flushing (though they look unlikely, off-hand, to significantly impact the issues outlined here).
Agreed. In general we can avoid flushing if there's no pending restyle in that tree (we could do something similar to what we do for getComputedStyle
). Not quite sure if the complexity is worth it.
Description
•