Closed Bug 1356034 Opened 7 years ago Closed 7 years ago

Investigate why a sync reflow is guaranteed when doing focus();

Categories

(Core :: DOM: UI Events & Focus Handling, enhancement, P1)

enhancement

Tracking

()

RESOLVED DUPLICATE of bug 1369140
mozilla55
Iteration:
55.7 - Jun 12

People

(Reporter: mconley, Unassigned)

References

(Blocks 1 open bug)

Details

Element.focus() appears to be one of those things that, without fail, causes a sync reflow.

Example:

http://searchfox.org/mozilla-central/rev/944f87c575e8a0bcefc1ed8efff10b34cf7a5169/toolkit/content/widgets/textbox.xml#228-237

Here, the textbox binding is calling focus() on the inputField on a mousedown event handler. It's possible that there are other mousedown event handlers that will fire in this same tick, but we're going to jank those in order to do what might be a full layout recalculation.

Hey Enn, out of curiosity, do you know why it is necessary to flush layout on focus?
Flags: needinfo?(enndeakin)
Flags: qe-verify?
Priority: -- → P2
Whiteboard: [photon-performance]
It probably wasn't necessary in some/most cases, but removing the flush entirely will cause many test failures and quite likely many compatibility regressions.

The page at https://gist.github.com/paulirish/5d52fb081b3570c81e3a suggests that Chrome does multiple flushes when focus() is called.

You might consider whether the specific case of calling focus() from script can be changed, but I suspect that removing it will cause some subtle issues.

For reference, the flush was added by bug 305840.
Flags: needinfo?(enndeakin)
If removing the flush isn't possible, could we make the flush lazy instead? (eg. do it when some code calls the document.activeElement getter?)
The flush occurs when determining whether the element is focusable or not.

For example, a page that redirects focus to a just created element on mousedown. I suspect there is some editing tool that does this.

The other bug (792297) removed one of the flushes but smaug didn't think it was worth it; perhaps that at least could be revisited.
(In reply to Neil Deakin from comment #4)
> The flush occurs when determining whether the element is focusable or not.

Can we skip this test for some common cases? Eg. focusing the location bar should always be possible, especially when it has just been clicked. Focusing a tab is probably always possible too. Or am I missing something?
Why doesn't https://bugzilla.mozilla.org/show_bug.cgi?id=792297#c11 still apply?


Curious, could we move the JS calling .focus() to happen in an animation frame callback? We're going to flush right after that anyhow, so the flush might not be so bad, if it makes the flush happening afterwards no-op.
(In reply to Olli Pettay [:smaug] from comment #6)
> Why doesn't https://bugzilla.mozilla.org/show_bug.cgi?id=792297#c11 still
> apply?
> 
> 
> Curious, could we move the JS calling .focus() to happen in an animation
> frame callback?

Possibly. We filed this bug and started this discussion because in bug 1349211 comment 4 I observed that some of the time we spend when opening tabs is sync flushes when moving the focus at least twice.

Before we started digging into that code to ensure we set the focus only once (which we should probably do anyway for that case), we wanted to check if there was something that could be done on the platform side to make .focus() calls cheap enough that we wouldn't need to care if the focus is moved more than once by JS code.

The specific case of setting the focus twice may not be the only place where we have this problem, so if possible it would be nicer to fix the whole category of problems rather than just one specific occurrence.
Blocks: 1356858
Depends on: 1358727
Depends on: 1358728
Blocks: 1358727, 1358728
No longer depends on: 1358727, 1358728
Blocks: 1358813
(In reply to Neil Deakin from comment #4)
> The flush occurs when determining whether the element is focusable or not.

Why do we need to flush layout for that and not frames?
Blocks: 1359765
Blocks: 1360043
Blocks: 1360078
Only a few failures for flushing frames instead; could be possible to fix them up:

https://treeherder.mozilla.org/#/jobs?repo=try&revision=5f870b525670f96b23aaee869d05bf622beb4b63
Blocks: 1362808
Blocks: 1365605
Flags: qe-verify? → qe-verify-
(In reply to Mike Conley (:mconley) from comment #10)
> Bug 1369140 is on inbound, and has landed the approach that causes us to
> flush _frames_ (and not styles or layout!) when switching focus.

frames and style is the same, I believe. See http://searchfox.org/mozilla-central/rev/1a0d9545b9805f50a70de703a3c04fc0d22e3839/dom/base/FlushType.h#28-29
(In reply to Dão Gottwald [::dao] from comment #11)
> (In reply to Mike Conley (:mconley) from comment #10)
> > Bug 1369140 is on inbound, and has landed the approach that causes us to
> > flush _frames_ (and not styles or layout!) when switching focus.
> 
> frames and style is the same, I believe. See
> http://searchfox.org/mozilla-central/rev/
> 1a0d9545b9805f50a70de703a3c04fc0d22e3839/dom/base/FlushType.h#28-29

Ah, TIL. Thank you. I'll mark my comment as obsolete.
In bug 1369140, ehsan made focus switching only flush styles, and not layout.

I'm going to work my way through the dependencies here, but I'm pretty certain these are all fixed now.
Apparently not all are fixed. I'll file a new bug for them, transfer dependencies, and close this one out.
Rewiring remaining bugs, and marking them blocking bug 1371371. We no longer guarantee a layout flush during focus switches, so I think this bug is done.
No longer blocks: 1356862, 1358695, 1358813
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
Iteration: --- → 55.7 - Jun 12
Priority: P2 → P1
Resolution: FIXED → DUPLICATE
Whiteboard: [photon-performance]
Component: Event Handling → User events and focus handling
You need to log in before you can comment on or make changes to this bug.