tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 103787e777fc70ef86037e6b57e2070f01adb6c0
parent a294a0259a9688103b19119365dc888f8dc37656
Author: Vincent Hilla <vhilla@mozilla.com>
Date:   Mon,  8 Dec 2025 14:59:54 +0000

Bug 2004155 - Make FlushAutoFocusCandidates robust to iterator position changes. r=dom-core,smaug

The code uses an nsTObserverArray to tolerate modifications during iteration.
But FlushPendingNotifications can desynchronize autoFocusElement from the
iterator's current position, resulting in removal at an unexpected or invalid
index.

Differential Revision: https://phabricator.services.mozilla.com/D275203

Diffstat:
Mdom/base/Document.cpp | 12+++++++-----
Mxpcom/ds/nsTObserverArray.h | 3++-
2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp @@ -13732,7 +13732,8 @@ void Document::FlushAutoFocusCandidates() { nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mAutoFocusCandidates); while (iter.HasMore()) { - nsCOMPtr<Element> autoFocusElement = do_QueryReferent(iter.GetNext()); + nsWeakPtr weakElement = iter.GetNext(); + nsCOMPtr<Element> autoFocusElement = do_QueryReferent(weakElement); if (!autoFocusElement) { continue; } @@ -13741,8 +13742,9 @@ void Document::FlushAutoFocusCandidates() { // to run which might affect the focusability of this element. autoFocusElementDoc->FlushPendingNotifications(FlushType::Frames); - // Above layout flush may cause the PresShell to disappear. - if (!mPresShell) { + // Above layout flush may cause the PresShell to disappear or autofocus to + // complete. The iterator position might have changed. + if (!mPresShell || mAutoFocusFired) { return; } @@ -13756,7 +13758,7 @@ void Document::FlushAutoFocusCandidates() { // If doc is not fully active, then remove element from candidates, and // continue. if (!autoFocusElementDoc->IsCurrentActiveDocument()) { - iter.Remove(); + mAutoFocusCandidates.RemoveElement(weakElement); continue; } @@ -13786,7 +13788,7 @@ void Document::FlushAutoFocusCandidates() { continue; } - iter.Remove(); + mAutoFocusCandidates.RemoveElement(weakElement); // Let inclusiveAncestorDocuments be a list consisting of doc, plus the // active documents of each of doc's browsing context's ancestor browsing diff --git a/xpcom/ds/nsTObserverArray.h b/xpcom/ds/nsTObserverArray.h @@ -333,7 +333,8 @@ class nsAutoTObserverArray : protected nsTObserverArray_base { } // Removes the element at the current iterator position. - // (the last element returned from |GetNext()|) + // This is the last element returned from |GetNext()|, unless + // the array was modified in the meantime. // This will not affect the next call to |GetNext()| void Remove() { return base_type::mArray.RemoveElementAt(base_type::mPosition - 1);