Backed out 7 changesets (bug 1444491, bug 1801761) for causing failures on autofocus-attribute.svg. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Wed, 15 Feb 2023 19:03:59 +0200
changeset 653227 7c9d11c84ac7a77507e4f8b7d136da56227e7ca3
parent 653226 f82668f37d71b7c49f7e22ddb33c77c012b6ddfd
child 653228 c7e12c1b792ac21216b2c23b95e9ca4b26b35192
push id40635
push usersmolnar@mozilla.com
push dateThu, 16 Feb 2023 04:35:37 +0000
treeherdermozilla-central@b2d97b936206 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1444491, 1801761
milestone112.0a1
backs out1cee414009cb12b0850d7ae0ce2aa1b7dc51c24d
30f786b7919124f57eb76fb27cacf7c5313fdceb
ce06375518a7e73510070b1ed39dbe61a8c08db8
64c8bb293e5c86a53f82cdc2b253139dd9db589d
94aa0ce630f21da9aeedb591947327a66098118f
80010eabc0c10e4535c56f7724b4ce945bda13b2
7d8da1f44177d2ad95c070b0dbce30b57904a19d
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 7 changesets (bug 1444491, bug 1801761) for causing failures on autofocus-attribute.svg. CLOSED TREE Backed out changeset 1cee414009cb (bug 1444491) Backed out changeset 30f786b79191 (bug 1444491) Backed out changeset ce06375518a7 (bug 1801761) Backed out changeset 64c8bb293e5c (bug 1444491) Backed out changeset 94aa0ce630f2 (bug 1444491) Backed out changeset 80010eabc0c1 (bug 1444491) Backed out changeset 7d8da1f44177 (bug 1444491)
dom/base/Document.cpp
dom/base/Document.h
dom/base/nsContentSink.h
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsStyledElement.cpp
dom/html/nsHTMLContentSink.cpp
dom/html/reftests/autofocus/autofocus-after-load-ref.html
dom/tests/browser/browser_autofocus_background.js
layout/base/PresShell.cpp
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
parser/html/nsHtml5TreeOpExecutor.h
parser/htmlparser/nsIContentSink.h
parser/htmlparser/nsIHTMLContentSink.h
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-in-not-fully-active-document.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-on-stable-document.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-reconnected.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-when-later-but-before.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-when-later.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/focusable-area-in-top-document.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-autofocus-on-changing-input-type.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-cross-origin-autofocus.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-sandboxed-automatic-features.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/not-on-first-task.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/queue-non-focusable.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/same-origin-autofocus.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-another-top-level-browsing-context.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-non-focusable.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-not-fully-active.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/supported-elements.html.ini
testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/update-the-rendering.html.ini
testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html
testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-valid.html
testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/resources/frame-with-a.html
testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/resources/utils.js
testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -376,17 +376,16 @@
 #include "nsIURIMutator.h"
 #include "nsIVariant.h"
 #include "nsIWeakReference.h"
 #include "nsIWebNavigation.h"
 #include "nsIWidget.h"
 #include "nsIX509Cert.h"
 #include "nsIX509CertValidity.h"
 #include "nsIXMLContentSink.h"
-#include "nsIHTMLContentSink.h"
 #include "nsIXULRuntime.h"
 #include "nsImageLoadingContent.h"
 #include "nsImportModule.h"
 #include "nsLanguageAtomService.h"
 #include "nsLayoutUtils.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsNodeInfoManager.h"
@@ -6838,19 +6837,16 @@ already_AddRefed<PresShell> Document::Cr
   UpdateFrameRequestCallbackSchedulingState();
 
   if (mDocumentL10n) {
     // In case we already accumulated mutations,
     // we'll trigger the refresh driver now.
     mDocumentL10n->OnCreatePresShell();
   }
 
-  if (HasAutoFocusCandidates()) {
-    ScheduleFlushAutoFocusCandidates();
-  }
   // Now that we have a shell, we might have @font-face rules (the presence of a
   // shell may change which rules apply to us). We don't need to do anything
   // like EnsureStyleFlush or such, there's nothing to update yet and when stuff
   // is ready to update we'll flush the font set.
   MarkUserFontSetDirty();
 
   // Take the author style disabled state from the top browsing cvontext.
   // (PageStyleChild.jsm ensures this is up to date.)
@@ -6947,17 +6943,16 @@ bool Document::ShouldThrottleFrameReques
       DOMIntersectionObserver::Intersect(input, *el);
   return !output.Intersects();
 }
 
 void Document::DeletePresShell() {
   mExternalResourceMap.HideViewers();
   if (nsPresContext* presContext = mPresShell->GetPresContext()) {
     presContext->RefreshDriver()->CancelPendingFullscreenEvents(this);
-    presContext->RefreshDriver()->CancelFlushAutoFocus(this);
   }
 
   // When our shell goes away, request that all our images be immediately
   // discarded, so we don't carry around decoded image data for a document we
   // no longer intend to paint.
   ImageTracker()->RequestDiscardAll();
 
   // Now that we no longer have a shell, we need to forget about any FontFace
@@ -12625,264 +12620,131 @@ Document* Document::GetTemplateContentsO
     // Set |mTemplateContentsOwner| as the template contents owner of itself so
     // that it is the template contents owner of nested template elements.
     mTemplateContentsOwner->mTemplateContentsOwner = mTemplateContentsOwner;
   }
 
   return mTemplateContentsOwner;
 }
 
-// https://html.spec.whatwg.org/#the-autofocus-attribute
-void Document::ElementWithAutoFocusInserted(Element* aAutoFocusCandidate) {
-  BrowsingContext* bc = GetBrowsingContext();
-  if (!bc) {
-    return;
-  }
-
-  // If target is not fully active, then return.
-  if (!IsCurrentActiveDocument()) {
-    return;
-  }
-
-  // If target's active sandboxing flag set has the sandboxed automatic features
-  // browsing context flag, then return.
-  if (GetSandboxFlags() & SANDBOXED_AUTOMATIC_FEATURES) {
-    return;
-  }
-
-  // For each ancestorBC of target's browsing context's ancestor browsing
-  // contexts: if ancestorBC's active document's origin is not same origin with
-  // target's origin, then return.
-  while (bc) {
-    BrowsingContext* parent = bc->GetParent();
-    if (!parent) {
-      break;
-    }
-    // AncestorBC is not the same site
-    if (!parent->IsInProcess()) {
-      return;
-    }
-
-    Document* currentDocument = bc->GetDocument();
-    if (!currentDocument) {
-      return;
-    }
-
-    Document* parentDocument = parent->GetDocument();
-    if (!parentDocument) {
-      return;
-    }
-
-    // Not same origin
-    if (!currentDocument->NodePrincipal()->Equals(
-            parentDocument->NodePrincipal())) {
-      return;
-    }
-
-    bc = parent;
-  }
-  MOZ_ASSERT(bc->IsTop());
-
-  Document* topDocument = bc->GetDocument();
-  MOZ_ASSERT(topDocument);
-  topDocument->AppendAutoFocusCandidateToTopDocument(aAutoFocusCandidate);
-}
-
-void Document::ScheduleFlushAutoFocusCandidates() {
-  MOZ_ASSERT(mPresShell && mPresShell->DidInitialize());
-  MOZ_ASSERT(GetBrowsingContext()->IsTop());
-  if (nsRefreshDriver* rd = mPresShell->GetRefreshDriver()) {
-    rd->ScheduleAutoFocusFlush(this);
-  }
-}
-
-void Document::AppendAutoFocusCandidateToTopDocument(
-    Element* aAutoFocusCandidate) {
-  MOZ_ASSERT(GetBrowsingContext()->IsTop());
-  if (mAutoFocusFired) {
-    return;
-  }
-
-  if (!HasAutoFocusCandidates()) {
-    // PresShell may be initialized later
-    if (mPresShell && mPresShell->DidInitialize()) {
-      ScheduleFlushAutoFocusCandidates();
-    }
-  }
-
-  nsWeakPtr element = do_GetWeakReference(aAutoFocusCandidate);
-  mAutoFocusCandidates.RemoveElement(element);
-  mAutoFocusCandidates.AppendElement(element);
-}
-
-void Document::SetAutoFocusFired() {
-  mAutoFocusCandidates.Clear();
-  mAutoFocusFired = true;
-}
-
-// https://html.spec.whatwg.org/#flush-autofocus-candidates
-void Document::FlushAutoFocusCandidates() {
-  MOZ_ASSERT(GetBrowsingContext()->IsTop());
+static already_AddRefed<nsPIDOMWindowOuter> FindTopWindowForElement(
+    Element* element) {
+  Document* document = element->OwnerDoc();
+  if (!document) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
+  if (!window) {
+    return nullptr;
+  }
+
+  // Trying to find the top window (equivalent to window.top).
+  if (nsCOMPtr<nsPIDOMWindowOuter> top = window->GetInProcessTop()) {
+    window = std::move(top);
+  }
+  return window.forget();
+}
+
+/**
+ * nsAutoFocusEvent is used to dispatch a focus event for an
+ * nsGenericHTMLFormElement with the autofocus attribute enabled.
+ */
+class nsAutoFocusEvent : public Runnable {
+ public:
+  explicit nsAutoFocusEvent(nsCOMPtr<Element>&& aElement,
+                            nsCOMPtr<nsPIDOMWindowOuter>&& aTopWindow)
+      : mozilla::Runnable("nsAutoFocusEvent"),
+        mElement(std::move(aElement)),
+        mTopWindow(std::move(aTopWindow)) {}
+
+  NS_IMETHOD Run() override {
+    nsCOMPtr<nsPIDOMWindowOuter> currentTopWindow =
+        FindTopWindowForElement(mElement);
+    if (currentTopWindow != mTopWindow) {
+      // The element's top window changed from when the event was queued.
+      // Don't take away focus from an unrelated window.
+      return NS_OK;
+    }
+
+    if (Document* doc = mTopWindow->GetExtantDoc()) {
+      if (doc->IsAutoFocusFired()) {
+        return NS_OK;
+      }
+      doc->SetAutoFocusFired();
+    }
+
+    // Don't steal focus from the user.
+    if (mTopWindow->GetFocusedElement()) {
+      return NS_OK;
+    }
+
+    FocusOptions options;
+    ErrorResult rv;
+    mElement->Focus(options, CallerType::System, rv);
+    return rv.StealNSResult();
+  }
+
+ private:
+  nsCOMPtr<Element> mElement;
+  nsCOMPtr<nsPIDOMWindowOuter> mTopWindow;
+};
+
+void Document::SetAutoFocusElement(Element* aAutoFocusElement) {
   if (mAutoFocusFired) {
-    return;
-  }
-
-  if (!mPresShell) {
-    return;
-  }
-
-  MOZ_ASSERT(HasAutoFocusCandidates());
-  MOZ_ASSERT(mPresShell->DidInitialize());
-
-  nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetWindow();
-  // We should be the top document
-  if (!topWindow) {
-    return;
-  }
-
-#ifdef DEBUG
-  {
-    // Trying to find the top window (equivalent to window.top).
-    nsCOMPtr<nsPIDOMWindowOuter> top = topWindow->GetInProcessTop();
-    MOZ_ASSERT(topWindow == top);
-  }
-#endif
-
-  // Don't steal the focus from the user
-  if (topWindow->GetFocusedElement()) {
-    SetAutoFocusFired();
-    return;
-  }
-
-  MOZ_ASSERT(mDocumentURI);
-  nsAutoCString ref;
-  // GetRef never fails
-  nsresult rv = mDocumentURI->GetRef(ref);
-  if (NS_SUCCEEDED(rv) &&
-      nsContentUtils::GetTargetElement(this, NS_ConvertUTF8toUTF16(ref))) {
-    SetAutoFocusFired();
-    return;
-  }
-
-  nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mAutoFocusCandidates);
-  while (iter.HasMore()) {
-    nsCOMPtr<Element> autoFocusElement = do_QueryReferent(iter.GetNext());
-    if (!autoFocusElement) {
-      continue;
-    }
-    RefPtr<Document> autoFocusElementDoc = autoFocusElement->OwnerDoc();
-    // Get the latest info about the frame and allow scripts
-    // 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) {
+    // Too late.
+    return;
+  }
+
+  if (mAutoFocusElement) {
+    // The spec disallows multiple autofocus elements, so we consider only the
+    // first one to preserve the old behavior.
+    return;
+  }
+
+  mAutoFocusElement = do_GetWeakReference(aAutoFocusElement);
+  TriggerAutoFocus();
+}
+
+void Document::SetAutoFocusFired() { mAutoFocusFired = true; }
+
+bool Document::IsAutoFocusFired() { return mAutoFocusFired; }
+
+void Document::TriggerAutoFocus() {
+  if (mAutoFocusFired) {
+    return;
+  }
+
+  if (!mPresShell || !mPresShell->DidInitialize()) {
+    // Delay autofocus until frames are constructed so that we don't thrash
+    // style and layout calculations.
+    return;
+  }
+
+  nsCOMPtr<Element> autoFocusElement = do_QueryReferent(mAutoFocusElement);
+  if (autoFocusElement && autoFocusElement->OwnerDoc() == this) {
+    nsCOMPtr<nsPIDOMWindowOuter> topWindow =
+        FindTopWindowForElement(autoFocusElement);
+    if (!topWindow) {
       return;
     }
 
-    // Re-get the element because the ownerDoc() might have changed
-    autoFocusElementDoc = autoFocusElement->OwnerDoc();
-    BrowsingContext* bc = autoFocusElementDoc->GetBrowsingContext();
-    if (!bc) {
-      continue;
-    }
-
-    // If doc is not fully active, then remove element from candidates, and
-    // continue.
-    if (!autoFocusElementDoc->IsCurrentActiveDocument()) {
-      iter.Remove();
-      continue;
-    }
-
-    nsCOMPtr<nsIContentSink> sink =
-        do_QueryInterface(autoFocusElementDoc->GetCurrentContentSink());
-    if (sink) {
-      nsHtml5TreeOpExecutor* executor =
-          static_cast<nsHtml5TreeOpExecutor*>(sink->AsExecutor());
-      if (executor) {
-        // This is a HTML5 document
-        MOZ_ASSERT(autoFocusElementDoc->IsHTMLDocument());
-        // If doc's script-blocking style sheet counter is greater than 0, th
-        // return.
-        if (executor->WaitForPendingSheets()) {
-          // In this case, element is the currently-best candidate, but doc is
-          // not ready for autofocusing. We'll try again next time flush
-          // autofocus candidates is called.
-          ScheduleFlushAutoFocusCandidates();
-          return;
-        }
-      }
-    }
-
-    // The autofocus element could be moved to a different
-    // top level BC.
-    if (bc->Top()->GetDocument() != this) {
-      continue;
-    }
-
-    iter.Remove();
-
-    // Let inclusiveAncestorDocuments be a list consisting of doc, plus the
-    // active documents of each of doc's browsing context's ancestor browsing
-    // contexts.
-    // If any Document in inclusiveAncestorDocuments has non-null target
-    // element, then continue.
-    bool shouldFocus = true;
-    while (bc) {
-      Document* doc = bc->GetDocument();
-      if (!doc) {
-        shouldFocus = false;
-        break;
-      }
-
-      nsIURI* uri = doc->GetDocumentURI();
-      if (!uri) {
-        shouldFocus = false;
-        break;
-      }
-
-      nsAutoCString ref;
-      nsresult rv = uri->GetRef(ref);
-      // If there is an element in the document tree that has an ID equal to
-      // fragment
-      if (NS_SUCCEEDED(rv) &&
-          nsContentUtils::GetTargetElement(doc, NS_ConvertUTF8toUTF16(ref))) {
-        shouldFocus = false;
-        break;
-      }
-      bc = bc->GetParent();
-    }
-
-    if (!shouldFocus) {
-      continue;
-    }
-
-    MOZ_ASSERT(topWindow);
-    if (TryAutoFocusCandidate(*autoFocusElement)) {
-      // We've successfully autofocused an element, don't
-      // need to try to focus the rest.
-      SetAutoFocusFired();
-      break;
-    }
-  }
-
-  if (HasAutoFocusCandidates()) {
-    ScheduleFlushAutoFocusCandidates();
-  }
-}
-
-bool Document::TryAutoFocusCandidate(Element& aElement) {
-  const FocusOptions options;
-  if (RefPtr<Element> target = nsFocusManager::GetTheFocusableArea(
-          &aElement, nsFocusManager::ProgrammaticFocusFlags(options))) {
-    target->Focus(options, CallerType::NonSystem, IgnoreErrors());
-    return true;
-  }
-
-  return false;
+    // NOTE: This may be removed in the future since the spec technically
+    // allows autofocus after load.
+    nsCOMPtr<Document> topDoc = topWindow->GetExtantDoc();
+    if (topDoc &&
+        topDoc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE) {
+      return;
+    }
+
+    nsCOMPtr<nsIRunnable> event =
+        new nsAutoFocusEvent(std::move(autoFocusElement), topWindow.forget());
+    nsresult rv = NS_DispatchToCurrentThread(event.forget());
+    NS_ENSURE_SUCCESS_VOID(rv);
+  }
 }
 
 void Document::SetScrollToRef(nsIURI* aDocumentURI) {
   if (!aDocumentURI) {
     return;
   }
 
   nsAutoCString ref;
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -1922,18 +1922,16 @@ class Document : public nsINode,
 
   // Pushes aElement onto the top layer
   void TopLayerPush(Element&);
 
   // Removes the topmost element for which aPredicate returns true from the top
   // layer. The removed element, if any, is returned.
   Element* TopLayerPop(FunctionRef<bool(Element*)> aPredicate);
 
-  MOZ_CAN_RUN_SCRIPT bool TryAutoFocusCandidate(Element& aElement);
-
  public:
   // Removes all the elements with fullscreen flag set from the top layer, and
   // clears their fullscreen flag.
   void CleanupFullscreenState();
 
   // Pops the fullscreen element from the top layer and clears its
   // fullscreen flag. Returns whether there was any fullscreen element.
   enum class UpdateViewport : bool { No, Yes };
@@ -3100,24 +3098,20 @@ class Document : public nsINode,
   virtual enum MediaDocumentKind MediaDocumentKind() const {
     return MediaDocumentKind::NotMedia;
   }
 
   DocumentState GetDocumentState() const { return mDocumentState; }
 
   nsISupports* GetCurrentContentSink();
 
-  void ElementWithAutoFocusInserted(Element* aAutoFocusCandidate);
-  MOZ_CAN_RUN_SCRIPT void FlushAutoFocusCandidates();
-  void ScheduleFlushAutoFocusCandidates();
-  bool HasAutoFocusCandidates() const {
-    return !mAutoFocusCandidates.IsEmpty();
-  }
-
+  void SetAutoFocusElement(Element* aAutoFocusElement);
+  void TriggerAutoFocus();
   void SetAutoFocusFired();
+  bool IsAutoFocusFired();
 
   void SetScrollToRef(nsIURI* aDocumentURI);
   MOZ_CAN_RUN_SCRIPT void ScrollToRef();
   void ResetScrolledToRefAlready() { mScrolledToRefAlready = false; }
 
   void SetChangeScrollPosWhenScrollingToRef(bool aValue) {
     mChangeScrollPosWhenScrollingToRef = aValue;
   }
@@ -3951,18 +3945,16 @@ class Document : public nsINode,
  public:
   const OriginTrials& Trials() const { return mTrials; }
 
  private:
   void DoCacheAllKnownLangPrefs();
   void RecomputeLanguageFromCharset();
   bool GetSHEntryHasUserInteraction();
 
-  void AppendAutoFocusCandidateToTopDocument(Element* aAutoFocusCandidate);
-
  public:
   void SetMayNeedFontPrefsUpdate() { mMayNeedFontPrefsUpdate = true; }
 
   bool MayNeedFontPrefsUpdate() { return mMayNeedFontPrefsUpdate; }
 
   void SetSHEntryHasUserInteraction(bool aHasInteraction);
 
   already_AddRefed<nsAtom> GetContentLanguageAsAtomForStyle() const;
@@ -5142,21 +5134,17 @@ class Document : public nsINode,
   nsRevocableEventPtr<nsRunnableMethod<Document, void, false>>
       mPendingTitleChangeEvent;
 
   RefPtr<nsDOMNavigationTiming> mTiming;
 
   // Recorded time of change to 'loading' state.
   TimeStamp mLoadingTimeStamp;
 
-  // Decided to use nsTObserverArray because it allows us to
-  // remove candidates while iterating them and this is what
-  // the spec defines. We could implement the spec without
-  // using nsTObserverArray, however using nsTObserverArray is more clear.
-  nsTObserverArray<nsWeakPtr> mAutoFocusCandidates;
+  nsWeakPtr mAutoFocusElement;
 
   nsCString mScrollToRef;
 
   // Weak reference to the scope object (aka the script global object)
   // that, unlike mScriptGlobalObject, is never unset once set. This
   // is a weak reference to avoid leaks due to circular references.
   nsWeakPtr mScopeObject;
 
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -164,31 +164,31 @@ class nsContentSink : public nsICSSLoade
   // stylesheets are all done loading.
  public:
   void StartLayout(bool aIgnorePendingSheets);
 
   static void NotifyDocElementCreated(Document* aDoc);
 
   Document* GetDocument() { return mDocument; }
 
-  // Later on we might want to make this more involved somehow
-  // (e.g. stop waiting after some timeout or whatnot).
-  bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
-
  protected:
   inline int32_t GetNotificationInterval() {
     if (mDynamicLowerValue) {
       return 1000;
     }
 
     return mozilla::StaticPrefs::content_notify_interval();
   }
 
   virtual nsresult FlushTags() = 0;
 
+  // Later on we might want to make this more involved somehow
+  // (e.g. stop waiting after some timeout or whatnot).
+  bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
+
   void DoProcessLinkHeader();
 
   void StopDeflecting() {
     mDeflectedCount = mozilla::StaticPrefs::content_sink_perf_deflect_count();
   }
 
  protected:
   RefPtr<Document> mDocument;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2978,69 +2978,16 @@ BrowserParent* nsContentUtils::GetCommon
       aBrowserParent1, aBrowserParent2, [](BrowserParent* aBrowserParent) {
         return aBrowserParent->GetBrowserBridgeParent()
                    ? aBrowserParent->GetBrowserBridgeParent()->Manager()
                    : nullptr;
       });
 }
 
 /* static */
-Element* nsContentUtils::GetTargetElement(Document* aDocument,
-                                          const nsAString& aAnchorName) {
-  MOZ_ASSERT(aDocument);
-
-  if (aAnchorName.IsEmpty()) {
-    return nullptr;
-  }
-  // 1. If there is an element in the document tree that has an ID equal to
-  //    fragment, then return the first such element in tree order.
-  if (Element* el = aDocument->GetElementById(aAnchorName)) {
-    return el;
-  }
-
-  // 2. If there is an a element in the document tree that has a name
-  // attribute whose value is equal to fragment, then return the first such
-  // element in tree order.
-  //
-  // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
-  if (aDocument->IsHTMLDocument()) {
-    nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName);
-    // Loop through the named nodes looking for the first anchor
-    uint32_t length = list->Length();
-    for (uint32_t i = 0; i < length; i++) {
-      nsIContent* node = list->Item(i);
-      if (node->IsHTMLElement(nsGkAtoms::a)) {
-        return node->AsElement();
-      }
-    }
-  } else {
-    constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
-    // Get the list of anchor elements
-    nsCOMPtr<nsINodeList> list =
-        aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
-    // Loop through the anchors looking for the first one with the given name.
-    for (uint32_t i = 0; true; i++) {
-      nsIContent* node = list->Item(i);
-      if (!node) {  // End of list
-        break;
-      }
-
-      // Compare the name attribute
-      if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                                         aAnchorName, eCaseMatters)) {
-        return node->AsElement();
-      }
-    }
-  }
-
-  // 3. Return null.
-  return nullptr;
-}
-
-/* static */
 template <typename FPT, typename FRT, typename SPT, typename SRT>
 Maybe<int32_t> nsContentUtils::ComparePoints(
     const RangeBoundaryBase<FPT, FRT>& aFirstBoundary,
     const RangeBoundaryBase<SPT, SRT>& aSecondBoundary) {
   if (!aFirstBoundary.IsSet() || !aSecondBoundary.IsSet()) {
     return Nothing{};
   }
 
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -521,20 +521,16 @@ class nsContentUtils {
   /**
    * Returns the common BrowserParent ancestor, if any, for two given
    * BrowserParent.
    */
   static mozilla::dom::BrowserParent* GetCommonBrowserParentAncestor(
       mozilla::dom::BrowserParent* aBrowserParent1,
       mozilla::dom::BrowserParent* aBrowserParent2);
 
-  // https://html.spec.whatwg.org/#target-element
-  // https://html.spec.whatwg.org/#find-a-potential-indicated-element
-  static Element* GetTargetElement(Document* aDocument,
-                                   const nsAString& aAnchorName);
   /**
    * Returns true if aNode1 is before aNode2 in the same connected
    * tree.
    * aNode1Index and aNode2Index are in/out arguments. If non-null, and value is
    * Some, that value is used instead of calling slow ComputeIndexOf on the
    * parent node. If value is Nothing, the value will be set to the return value
    * of ComputeIndexOf.
    */
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -375,17 +375,18 @@ NS_IMETHODIMP
 nsFocusManager::GetActiveBrowsingContext(BrowsingContext** aBrowsingContext) {
   NS_IF_ADDREF(*aBrowsingContext = GetActiveBrowsingContext());
   return NS_OK;
 }
 
 void nsFocusManager::FocusWindow(nsPIDOMWindowOuter* aWindow,
                                  CallerType aCallerType) {
   if (RefPtr<nsFocusManager> fm = sInstance) {
-    fm->SetFocusedWindowWithCallerType(aWindow, aCallerType);
+    fm->SetFocusedWindowWithCallerType(aWindow, aCallerType,
+                                       sInstance->GenerateFocusActionId());
   }
 }
 
 NS_IMETHODIMP
 nsFocusManager::GetFocusedWindow(mozIDOMWindowProxy** aFocusedWindow) {
   NS_IF_ADDREF(*aFocusedWindow = mFocusedWindow);
   return NS_OK;
 }
@@ -396,57 +397,55 @@ nsFocusManager::GetFocusedContentBrowsin
   MOZ_DIAGNOSTIC_ASSERT(
       XRE_IsParentProcess(),
       "We only have use cases for this in the parent process");
   NS_IF_ADDREF(*aBrowsingContext = GetFocusedBrowsingContextInChrome());
   return NS_OK;
 }
 
 nsresult nsFocusManager::SetFocusedWindowWithCallerType(
-    mozIDOMWindowProxy* aWindowToFocus, CallerType aCallerType) {
-  LOGFOCUS(("<<SetFocusedWindow begin>>"));
+    mozIDOMWindowProxy* aWindowToFocus, CallerType aCallerType,
+    uint64_t aActionId) {
+  LOGFOCUS(("<<SetFocusedWindow begin actionid: %" PRIu64 ">>", aActionId));
 
   nsCOMPtr<nsPIDOMWindowOuter> windowToFocus =
       nsPIDOMWindowOuter::From(aWindowToFocus);
   NS_ENSURE_TRUE(windowToFocus, NS_ERROR_FAILURE);
 
   nsCOMPtr<Element> frameElement = windowToFocus->GetFrameElementInternal();
-  Maybe<uint64_t> actionIdFromSetFocusInner;
   if (frameElement) {
     // pass false for aFocusChanged so that the caret does not get updated
     // and scrolling does not occur.
-    actionIdFromSetFocusInner = SetFocusInner(frameElement, 0, false, true);
+    SetFocusInner(frameElement, 0, false, true, aActionId);
   } else {
     // this is a top-level window. If the window has a child frame focused,
     // clear the focus. Otherwise, focus should already be in this frame, or
     // already cleared. This ensures that focus will be in this frame and not
     // in a child.
     nsIContent* content = windowToFocus->GetFocusedElement();
     if (content) {
       if (nsCOMPtr<nsPIDOMWindowOuter> childWindow = GetContentWindow(content))
         ClearFocus(windowToFocus);
     }
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> rootWindow = windowToFocus->GetPrivateRoot();
-  const uint64_t actionId = actionIdFromSetFocusInner.isSome()
-                                ? actionIdFromSetFocusInner.value()
-                                : sInstance->GenerateFocusActionId();
   if (rootWindow) {
-    RaiseWindow(rootWindow, aCallerType, actionId);
-  }
-
-  LOGFOCUS(("<<SetFocusedWindow end actionid: %" PRIu64 ">>", actionId));
+    RaiseWindow(rootWindow, aCallerType, aActionId);
+  }
+
+  LOGFOCUS(("<<SetFocusedWindow end actionid: %" PRIu64 ">>", aActionId));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
     mozIDOMWindowProxy* aWindowToFocus) {
-  return SetFocusedWindowWithCallerType(aWindowToFocus, CallerType::System);
+  return SetFocusedWindowWithCallerType(aWindowToFocus, CallerType::System,
+                                        GenerateFocusActionId());
 }
 
 NS_IMETHODIMP
 nsFocusManager::GetFocusedElement(Element** aFocusedElement) {
   RefPtr<Element> focusedElement = mFocusedElement;
   focusedElement.forget(aFocusedElement);
   return NS_OK;
 }
@@ -466,17 +465,17 @@ nsFocusManager::GetLastFocusMethod(mozID
 }
 
 NS_IMETHODIMP
 nsFocusManager::SetFocus(Element* aElement, uint32_t aFlags) {
   LOGFOCUS(("<<SetFocus begin>>"));
 
   NS_ENSURE_ARG(aElement);
 
-  SetFocusInner(aElement, aFlags, true, true);
+  SetFocusInner(aElement, aFlags, true, true, GenerateFocusActionId());
 
   LOGFOCUS(("<<SetFocus end>>"));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFocusManager::ElementIsFocusable(Element* aElement, uint32_t aFlags,
@@ -539,17 +538,17 @@ nsFocusManager::MoveFocus(mozIDOMWindowP
   LOGCONTENTNAVIGATION("Element to be focused: %s", newFocus.get());
 
   if (newFocus && newFocus->IsElement()) {
     // for caret movement, pass false for the aFocusChanged argument,
     // otherwise the caret will end up moving to the focus position. This
     // would be a problem because the caret would move to the beginning of the
     // focused link making it impossible to navigate the caret over a link.
     SetFocusInner(MOZ_KnownLive(newFocus->AsElement()), aFlags,
-                  aType != MOVEFOCUS_CARET, true);
+                  aType != MOVEFOCUS_CARET, true, GenerateFocusActionId());
     *aElement = do_AddRef(newFocus->AsElement()).take();
   } else if (aType == MOVEFOCUS_ROOT || aType == MOVEFOCUS_CARET) {
     // no content was found, so clear the focus for these two types.
     ClearFocus(window);
   }
 
   LOGFOCUS(("<<MoveFocus end>>"));
 
@@ -1468,25 +1467,24 @@ static bool IsEmeddededInNoautofocusPopu
   nsIFrame* menuPopup =
       nsLayoutUtils::GetClosestFrameOfType(f, LayoutFrameType::MenuPopup);
   MOZ_ASSERT(menuPopup, "NS_FRAME_IN_POPUP lied?");
   return static_cast<nsMenuPopupFrame*>(menuPopup)
       ->PopupElement()
       .GetXULBoolAttr(nsGkAtoms::noautofocus);
 }
 
-Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
-                                              int32_t aFlags,
-                                              bool aFocusChanged,
-                                              bool aAdjustWidget) {
+void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
+                                   bool aFocusChanged, bool aAdjustWidget,
+                                   uint64_t aActionId) {
   // if the element is not focusable, just return and leave the focus as is
   RefPtr<Element> elementToFocus =
       FlushAndCheckIfFocusable(aNewContent, aFlags);
   if (!elementToFocus) {
-    return Nothing();
+    return;
   }
 
   const RefPtr<BrowsingContext> focusedBrowsingContext =
       GetFocusedBrowsingContext();
 
   // check if the element to focus is a frame (iframe) containing a child
   // document. Frames are never directly focused; instead focusing a frame
   // means focus what is inside the frame. To do this, the descendant content
@@ -1512,72 +1510,72 @@ Maybe<uint64_t> nsFocusManager::SetFocus
     newBrowsingContext = newWindow->GetBrowsingContext();
   }
 
   // if the element is already focused, just return. Note that this happens
   // after the frame check above so that we compare the element that will be
   // focused rather than the frame it is in.
   if (!newWindow || (newBrowsingContext == GetFocusedBrowsingContext() &&
                      elementToFocus == mFocusedElement)) {
-    return Nothing();
+    return;
   }
 
   MOZ_ASSERT(newBrowsingContext);
 
   BrowsingContext* browsingContextToFocus = newBrowsingContext;
   if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(elementToFocus)) {
     // Only look at pre-existing browsing contexts. If this function is
     // called during reflow, calling GetBrowsingContext() could cause frame
     // loader initialization at a time when it isn't safe.
     if (BrowsingContext* bc = flo->GetExtantBrowsingContext()) {
       // If focus is already in the subtree rooted at bc, return early
       // to match the single-process focus semantics. Otherwise, we'd
       // blur and immediately refocus whatever is focused.
       BrowsingContext* walk = focusedBrowsingContext;
       while (walk) {
         if (walk == bc) {
-          return Nothing();
+          return;
         }
         walk = walk->GetParent();
       }
       browsingContextToFocus = bc;
     }
   }
 
   // don't allow focus to be placed in docshells or descendants of docshells
   // that are being destroyed. Also, ensure that the page hasn't been
   // unloaded. The prevents content from being refocused during an unload event.
   nsCOMPtr<nsIDocShell> newDocShell = newWindow->GetDocShell();
   nsCOMPtr<nsIDocShell> docShell = newDocShell;
   while (docShell) {
     bool inUnload;
     docShell->GetIsInUnload(&inUnload);
     if (inUnload) {
-      return Nothing();
+      return;
     }
 
     bool beingDestroyed;
     docShell->IsBeingDestroyed(&beingDestroyed);
     if (beingDestroyed) {
-      return Nothing();
+      return;
     }
 
     BrowsingContext* bc = docShell->GetBrowsingContext();
 
     nsCOMPtr<nsIDocShellTreeItem> parentDsti;
     docShell->GetInProcessParent(getter_AddRefs(parentDsti));
     docShell = do_QueryInterface(parentDsti);
     if (!docShell && !XRE_IsParentProcess()) {
       // We don't have an in-process parent, but let's see if we have
       // an in-process ancestor or if an out-of-process ancestor
       // is discarded.
       do {
         bc = bc->GetParent();
         if (bc && bc->IsDiscarded()) {
-          return Nothing();
+          return;
         }
       } while (bc && !bc->IsInProcess());
       if (bc) {
         docShell = bc->GetDocShell();
       } else {
         docShell = nullptr;
       }
     }
@@ -1613,22 +1611,22 @@ Maybe<uint64_t> nsFocusManager::SetFocus
           do_QueryInterface(browsingContextToFocus->GetDOMWindow());
       MOZ_ASSERT(focused && newFocus,
                  "BrowsingContext should always have a window here.");
       focusedPrincipal = focused->GetPrincipal();
       newPrincipal = newFocus->GetPrincipal();
     }
 
     if (!focusedPrincipal || !newPrincipal) {
-      return Nothing();
+      return;
     }
 
     if (!focusedPrincipal->Subsumes(newPrincipal)) {
       NS_WARNING("Not allowed to focus the new window!");
-      return Nothing();
+      return;
     }
   }
 
   // to check if the new element is in the active window, compare the
   // new root docshell for the new element with the active window's docshell.
   RefPtr<BrowsingContext> newRootBrowsingContext = nullptr;
   bool isElementInActiveWindow = false;
   if (XRE_IsParentProcess()) {
@@ -1725,22 +1723,21 @@ Maybe<uint64_t> nsFocusManager::SetFocus
       !nsContentUtils::CanCallerAccess(mFocusedElement)) {
     sendFocusEvent = false;
   }
 
   LOGCONTENT("Shift Focus: %s", elementToFocus.get());
   LOGFOCUS((" Flags: %x Current Window: %p New Window: %p Current Element: %p",
             aFlags, mFocusedWindow.get(), newWindow.get(),
             mFocusedElement.get()));
-  const uint64_t actionId = GenerateFocusActionId();
   LOGFOCUS(
       (" In Active Window: %d Moves to different BrowsingContext: %d "
        "SendFocus: %d actionid: %" PRIu64,
        isElementInActiveWindow, focusMovesToDifferentBC, sendFocusEvent,
-       actionId));
+       aActionId));
 
   if (sendFocusEvent) {
     Maybe<BlurredElementInfo> blurredInfo;
     if (mFocusedElement) {
       blurredInfo.emplace(*mFocusedElement);
     }
     // return if blurring fails or the focus changes during the blur
     if (focusedBrowsingContext) {
@@ -1783,29 +1780,29 @@ Maybe<uint64_t> nsFocusManager::SetFocus
           focusMovesToDifferentBC &&
           IsEmeddededInNoautofocusPopup(*browsingContextToFocus);
 
       // TODO: MOZ_KnownLive is required due to bug 1770680
       if (!Blur(MOZ_KnownLive(needToClearFocusedElement
                                   ? focusedBrowsingContext.get()
                                   : nullptr),
                 commonAncestor, focusMovesToDifferentBC, aAdjustWidget,
-                remainActive, actionId, elementToFocus)) {
-        return Some(actionId);
+                remainActive, aActionId, elementToFocus)) {
+        return;
       }
     }
 
     Focus(newWindow, elementToFocus, aFlags, focusMovesToDifferentBC,
-          aFocusChanged, false, aAdjustWidget, actionId, blurredInfo);
+          aFocusChanged, false, aAdjustWidget, aActionId, blurredInfo);
   } else {
     // otherwise, for inactive windows and when the caller cannot steal the
     // focus, update the node in the window, and  raise the window if desired.
     if (allowFrameSwitch) {
       AdjustWindowFocus(newBrowsingContext, true, IsWindowVisible(newWindow),
-                        actionId);
+                        aActionId);
     }
 
     // set the focus node and method as needed
     uint32_t focusMethod =
         aFocusChanged ? aFlags & METHODANDRING_MASK
                       : newWindow->GetFocusMethod() |
                             (aFlags & (FLAG_SHOWRING | FLAG_NOSHOWRING));
     newWindow->SetFocusedElement(elementToFocus, focusMethod);
@@ -1827,31 +1824,30 @@ Maybe<uint64_t> nsFocusManager::SetFocus
     if (aFlags & FLAG_RAISE) {
       if (newRootBrowsingContext) {
         if (XRE_IsParentProcess() || newRootBrowsingContext->IsInProcess()) {
           nsCOMPtr<nsPIDOMWindowOuter> outerWindow =
               newRootBrowsingContext->GetDOMWindow();
           RaiseWindow(outerWindow,
                       aFlags & FLAG_NONSYSTEMCALLER ? CallerType::NonSystem
                                                     : CallerType::System,
-                      actionId);
+                      aActionId);
         } else {
           mozilla::dom::ContentChild* contentChild =
               mozilla::dom::ContentChild::GetSingleton();
           MOZ_ASSERT(contentChild);
           contentChild->SendRaiseWindow(newRootBrowsingContext,
                                         aFlags & FLAG_NONSYSTEMCALLER
                                             ? CallerType::NonSystem
                                             : CallerType::System,
-                                        actionId);
+                                        aActionId);
         }
       }
     }
   }
-  return Some(actionId);
 }
 
 static already_AddRefed<BrowsingContext> GetParentIgnoreChromeBoundary(
     BrowsingContext* aBC) {
   // Chrome BrowsingContexts are only available in the parent process, so if
   // we're in a content process, we only worry about the context tree.
   if (XRE_IsParentProcess()) {
     return aBC->Canonical()->GetParentCrossChromeBoundary();
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -209,17 +209,18 @@ class nsFocusManager final : public nsIF
   MOZ_CAN_RUN_SCRIPT nsresult DetermineElementToMoveFocus(
       nsPIDOMWindowOuter* aWindow, nsIContent* aStart, int32_t aType,
       bool aNoParentTraversal, bool aNavigateByKey, nsIContent** aNextContent);
 
   /**
    * Setter for focusedWindow with CallerType
    */
   MOZ_CAN_RUN_SCRIPT nsresult SetFocusedWindowWithCallerType(
-      mozIDOMWindowProxy* aWindowToFocus, mozilla::dom::CallerType aCallerType);
+      mozIDOMWindowProxy* aWindowToFocus, mozilla::dom::CallerType aCallerType,
+      uint64_t aActionId);
 
   /**
    * Given an element, which must be the focused element, activate the remote
    * frame it embeds, if any.
    */
   void ActivateRemoteFrameIfNeeded(mozilla::dom::Element&, uint64_t aActionId);
 
   /**
@@ -308,23 +309,20 @@ class nsFocusManager final : public nsIF
    * bitmask of the flags defined in nsIFocusManager. If aFocusChanged is
    * true, then the focus has actually shifted and the caret position will be
    * updated to the new focus, aNewContent will be scrolled into view (unless
    * a flag disables this) and the focus method for the window will be updated.
    * If aAdjustWidget is false, don't change the widget focus state.
    *
    * All actual focus changes must use this method to do so. (as opposed
    * to those that update the focus in an inactive window for instance).
-   *
-   * Returns Nothing() if we end up not trying to focus the element,
-   * otherwise returns the generated action id.
    */
-  MOZ_CAN_RUN_SCRIPT Maybe<uint64_t> SetFocusInner(
-      mozilla::dom::Element* aNewContent, int32_t aFlags, bool aFocusChanged,
-      bool aAdjustWidget);
+  MOZ_CAN_RUN_SCRIPT void SetFocusInner(mozilla::dom::Element* aNewContent,
+                                        int32_t aFlags, bool aFocusChanged,
+                                        bool aAdjustWidget, uint64_t aActionId);
 
   /**
    * Returns true if aPossibleAncestor is the same as aWindow or an
    * ancestor of aWindow.
    */
   bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
                         nsPIDOMWindowOuter* aWindow) const;
   bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -211,13 +211,13 @@ void nsStyledElement::ParseStyleAttribut
 }
 
 nsresult nsStyledElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsStyledElementBase::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (HasAttr(nsGkAtoms::autofocus) && aContext.AllowsAutoFocus() &&
       (!IsSVGElement() || IsFocusable())) {
-    aContext.OwnerDoc().ElementWithAutoFocusInserted(this);
+    aContext.OwnerDoc().SetAutoFocusElement(this);
   }
 
   return NS_OK;
 }
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -109,17 +109,16 @@ class HTMLContentSink : public nsContent
   NS_IMETHOD DidBuildModel(bool aTerminated) override;
   NS_IMETHOD WillInterrupt(void) override;
   void WillResume() override;
   NS_IMETHOD SetParser(nsParserBase* aParser) override;
   virtual void FlushPendingNotifications(FlushType aType) override;
   virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
   virtual nsISupports* GetTarget() override;
   virtual bool IsScriptExecuting() override;
-  virtual bool WaitForPendingSheets() override;
   virtual void ContinueInterruptedParsingAsync() override;
 
   // nsIHTMLContentSink
   NS_IMETHOD OpenContainer(ElementType aNodeType) override;
   NS_IMETHOD CloseContainer(ElementType aTag) override;
 
  protected:
   virtual ~HTMLContentSink();
@@ -920,20 +919,16 @@ nsISupports* HTMLContentSink::GetTarget(
 bool HTMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); }
 
 void HTMLContentSink::ContinueInterruptedParsingIfEnabled() {
   if (mParser && mParser->IsParserEnabled()) {
     static_cast<nsIParser*>(mParser.get())->ContinueInterruptedParsing();
   }
 }
 
-bool HTMLContentSink::WaitForPendingSheets() {
-  return nsContentSink::WaitForPendingSheets();
-}
-
 void HTMLContentSink::ContinueInterruptedParsingAsync() {
   nsCOMPtr<nsIRunnable> ev = NewRunnableMethod(
       "HTMLContentSink::ContinueInterruptedParsingIfEnabled", this,
       &HTMLContentSink::ContinueInterruptedParsingIfEnabled);
 
   RefPtr<Document> doc = mHTMLDocument;
   doc->Dispatch(mozilla::TaskCategory::Other, ev.forget());
 }
--- a/dom/html/reftests/autofocus/autofocus-after-load-ref.html
+++ b/dom/html/reftests/autofocus/autofocus-after-load-ref.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
   <link rel='stylesheet' type='text/css' href='style.css'>
   <body>
-    <input autofocus><textarea></textarea><select></select><button></button>
+    <input><textarea></textarea><select></select><button></button>
   </body>
 </html>
--- a/dom/tests/browser/browser_autofocus_background.js
+++ b/dom/tests/browser/browser_autofocus_background.js
@@ -20,23 +20,16 @@ add_task(async function() {
   BrowserTestUtils.loadURIString(backgroundTab.linkedBrowser, URL);
   await loadedPromise;
 
   // Get active element in the tab.
   let tagName = await SpecialPowers.spawn(
     backgroundTab.linkedBrowser,
     [],
     async function() {
-      // Spec asks us to flush autofocus candidates in the
-      // `update-the-rendering` step, so we need to wait
-      // for a rAF to ensure autofocus candidates are
-      // flushed.
-      await new Promise(r => {
-        content.requestAnimationFrame(r);
-      });
       return content.document.activeElement.tagName;
     }
   );
 
   is(
     tagName,
     "INPUT",
     "The background tab's focused element should be the <input>"
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1845,19 +1845,17 @@ nsresult PresShell::Initialize() {
     }
     // Something in mFrameConstructor->ContentInserted may have caused
     // Destroy() to get called, bug 337586.  Or, nsAutoCauseReflowNotifier
     // (which sets up a script blocker) going out of scope may have killed us
     // too
     NS_ENSURE_STATE(!mHaveShutDown);
   }
 
-  if (mDocument->HasAutoFocusCandidates()) {
-    mDocument->ScheduleFlushAutoFocusCandidates();
-  }
+  mDocument->TriggerAutoFocus();
 
   NS_ASSERTION(rootFrame, "How did that happen?");
 
   // Note: when the frame was created above it had the NS_FRAME_IS_DIRTY bit
   // set, but XBL processing could have caused a reflow which clears it.
   if (MOZ_LIKELY(rootFrame->HasAnyStateBits(NS_FRAME_IS_DIRTY))) {
     // Unset the DIRTY bits so that FrameNeedsReflow() will work right.
     rootFrame->RemoveStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
@@ -3133,18 +3131,62 @@ nsresult PresShell::GoToAnchor(const nsA
   // 2. If the indicated part of the document is the top of the document,
   // then:
   // (handled below when `target` is null, and anchor is `top`)
 
   // 3.1. Let target be element that is the indicated part of the document.
   //
   // https://html.spec.whatwg.org/#target-element
   // https://html.spec.whatwg.org/#find-a-potential-indicated-element
-  RefPtr<Element> target =
-      nsContentUtils::GetTargetElement(mDocument, aAnchorName);
+  RefPtr<Element> target = [&]() -> Element* {
+    // 1. If there is an element in the document tree that has an ID equal to
+    //    fragment, then return the first such element in tree order.
+    if (Element* el = mDocument->GetElementById(aAnchorName)) {
+      return el;
+    }
+
+    // 2. If there is an a element in the document tree that has a name
+    // attribute whose value is equal to fragment, then return the first such
+    // element in tree order.
+    //
+    // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
+    if (mDocument->IsHTMLDocument()) {
+      nsCOMPtr<nsINodeList> list = mDocument->GetElementsByName(aAnchorName);
+      // Loop through the named nodes looking for the first anchor
+      uint32_t length = list->Length();
+      for (uint32_t i = 0; i < length; i++) {
+        nsIContent* node = list->Item(i);
+        if (node->IsHTMLElement(nsGkAtoms::a)) {
+          return node->AsElement();
+        }
+      }
+    } else {
+      constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
+      // Get the list of anchor elements
+      nsCOMPtr<nsINodeList> list =
+          mDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
+      // Loop through the anchors looking for the first one with the given name.
+      for (uint32_t i = 0; true; i++) {
+        nsIContent* node = list->Item(i);
+        if (!node) {  // End of list
+          break;
+        }
+
+        // Compare the name attribute
+        if (node->IsElement() &&
+            node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                                           aAnchorName, eCaseMatters)) {
+          return node->AsElement();
+        }
+      }
+    }
+
+    // 3. Return null.
+    return nullptr;
+  }();
 
   // 1. If there is no indicated part of the document, set the Document's
   //    target element to null.
   // 2.1. Set the Document's target element to null.
   // 3.2. Set the Document's target element to target.
   esm->SetContentState(target, ElementState::URLTARGET);
 
   // TODO: Spec probably needs a section to account for this.
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1838,17 +1838,16 @@ uint32_t nsRefreshDriver::ObserverCount(
   sum += mStyleFlushObservers.Length();
   sum += mLayoutFlushObservers.Length();
   sum += mPendingFullscreenEvents.Length();
   sum += mFrameRequestCallbackDocs.Length();
   sum += mThrottledFrameRequestCallbackDocs.Length();
   sum += mViewManagerFlushIsPending;
   sum += mEarlyRunners.Length();
   sum += mTimerAdjustmentObservers.Length();
-  sum += mAutoFocusFlushDocuments.Length();
   return sum;
 }
 
 bool nsRefreshDriver::HasObservers() const {
   for (const ObserverArray& array : mObservers) {
     if (!array.IsEmpty()) {
       return true;
     }
@@ -1859,17 +1858,17 @@ bool nsRefreshDriver::HasObservers() con
   // adjustment observers should not influence timer starting or stopping.
   return mViewManagerFlushIsPending || !mStyleFlushObservers.IsEmpty() ||
          !mLayoutFlushObservers.IsEmpty() ||
          !mAnimationEventFlushObservers.IsEmpty() ||
          !mResizeEventFlushObservers.IsEmpty() ||
          !mPendingFullscreenEvents.IsEmpty() ||
          !mFrameRequestCallbackDocs.IsEmpty() ||
          !mThrottledFrameRequestCallbackDocs.IsEmpty() ||
-         !mAutoFocusFlushDocuments.IsEmpty() || !mEarlyRunners.IsEmpty();
+         !mEarlyRunners.IsEmpty();
 }
 
 void nsRefreshDriver::AppendObserverDescriptionsToString(
     nsACString& aStr) const {
   for (const ObserverArray& array : mObservers) {
     for (const auto& observer : array.EndLimitedRange()) {
       aStr.AppendPrintf("%s [%s], ", observer.mDescription,
                         kFlushTypeNames[observer.mFlushType]);
@@ -1901,20 +1900,16 @@ void nsRefreshDriver::AppendObserverDesc
   if (!mFrameRequestCallbackDocs.IsEmpty()) {
     aStr.AppendPrintf("%zux Frame request callback doc, ",
                       mFrameRequestCallbackDocs.Length());
   }
   if (!mThrottledFrameRequestCallbackDocs.IsEmpty()) {
     aStr.AppendPrintf("%zux Throttled frame request callback doc, ",
                       mThrottledFrameRequestCallbackDocs.Length());
   }
-  if (!mAutoFocusFlushDocuments.IsEmpty()) {
-    aStr.AppendPrintf("%zux AutoFocus flush doc, ",
-                      mAutoFocusFlushDocuments.Length());
-  }
   if (!mEarlyRunners.IsEmpty()) {
     aStr.AppendPrintf("%zux Early runner, ", mEarlyRunners.Length());
   }
   // Remove last ", "
   aStr.Truncate(aStr.Length() - 2);
 }
 
 bool nsRefreshDriver::HasImageRequests() const {
@@ -2134,34 +2129,16 @@ static void GetProfileTimelineSubDocShel
 }
 
 static void TakeFrameRequestCallbacksFrom(
     Document* aDocument, nsTArray<DocumentFrameCallbacks>& aTarget) {
   aTarget.AppendElement(aDocument);
   aDocument->TakeFrameRequestCallbacks(aTarget.LastElement().mCallbacks);
 }
 
-void nsRefreshDriver::ScheduleAutoFocusFlush(Document* aDocument) {
-  MOZ_ASSERT(!mAutoFocusFlushDocuments.Contains(aDocument));
-  mAutoFocusFlushDocuments.AppendElement(aDocument);
-  EnsureTimerStarted();
-}
-
-void nsRefreshDriver::FlushAutoFocusDocuments() {
-  nsTArray<RefPtr<Document>> docs(std::move(mAutoFocusFlushDocuments));
-
-  for (const auto& doc : docs) {
-    MOZ_KnownLive(doc)->FlushAutoFocusCandidates();
-  }
-}
-
-void nsRefreshDriver::CancelFlushAutoFocus(Document* aDocument) {
-  mAutoFocusFlushDocuments.RemoveElement(aDocument);
-}
-
 // https://fullscreen.spec.whatwg.org/#run-the-fullscreen-steps
 void nsRefreshDriver::RunFullscreenSteps() {
   // Swap out the current pending events
   nsTArray<UniquePtr<PendingFullscreenEvent>> pendings(
       std::move(mPendingFullscreenEvents));
   for (UniquePtr<PendingFullscreenEvent>& event : pendings) {
     event->Dispatch();
   }
@@ -2592,17 +2569,16 @@ void nsRefreshDriver::Tick(VsyncId aId, 
     if (i == 1 && (!mPresContext || !mPresContext->GetPresShell())) {
       StopTimer();
       return;
     }
 
     if (i == 1) {
       // This is the FlushType::Style case.
 
-      FlushAutoFocusDocuments();
       DispatchScrollEvents();
       DispatchVisualViewportScrollEvents();
       DispatchAnimationEvents();
       RunFullscreenSteps();
       RunFrameRequestCallbacks(aNowTime);
 
       if (mPresContext && mPresContext->GetPresShell()) {
         AutoTArray<PresShell*, 16> observers;
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -341,18 +341,16 @@ class nsRefreshDriver final : public moz
   void ClearPendingTransactions() override;
   void ResetInitialTransactionId(TransactionId aTransactionId) override;
   mozilla::TimeStamp GetTransactionStart() override;
   mozilla::VsyncId GetVsyncId() override;
   mozilla::TimeStamp GetVsyncStart() override;
 
   bool IsWaitingForPaint(mozilla::TimeStamp aTime);
 
-  void ScheduleAutoFocusFlush(Document* aDocument);
-
   // nsARefreshObserver
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override {
     return TransactionIdAllocator::AddRef();
   }
   NS_IMETHOD_(MozExternalRefCountType) Release(void) override {
     return TransactionIdAllocator::Release();
   }
   virtual void WillRefresh(mozilla::TimeStamp aTime) override;
@@ -444,18 +442,16 @@ class nsRefreshDriver final : public moz
 
   void AddForceNotifyContentfulPaintPresContext(nsPresContext* aPresContext);
   void FlushForceNotifyContentfulPaintPresContext();
 
   // Mark that we've just run a tick from vsync, used to throttle 'extra'
   // paints to one per vsync (see CanDoExtraTick).
   void FinishedVsyncTick() { mAttemptedExtraTickSinceLastVsync = false; }
 
-  void CancelFlushAutoFocus(Document* aDocument);
-
  private:
   typedef nsTArray<RefPtr<VVPResizeEvent>> VisualViewportResizeEventArray;
   typedef nsTArray<RefPtr<mozilla::Runnable>> ScrollEventArray;
   typedef nsTArray<RefPtr<VVPScrollEvent>> VisualViewportScrollEventArray;
   using RequestTable = nsTHashSet<RefPtr<imgIRequest>>;
   struct ImageStartData {
     ImageStartData() = default;
 
@@ -473,18 +469,16 @@ class nsRefreshDriver final : public moz
     mozilla::FlushType mFlushType;
 
     bool operator==(nsARefreshObserver* aObserver) const {
       return mObserver == aObserver;
     }
     operator RefPtr<nsARefreshObserver>() { return mObserver; }
   };
   typedef nsTObserverArray<ObserverData> ObserverArray;
-  MOZ_CAN_RUN_SCRIPT
-  void FlushAutoFocusDocuments();
   void RunFullscreenSteps();
   void DispatchAnimationEvents();
   MOZ_CAN_RUN_SCRIPT
   void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
   void UpdateIntersectionObservations(mozilla::TimeStamp aNowTime);
   void UpdateRelevancyOfContentVisibilityAutoFrames();
 
   enum class IsExtraTick {
@@ -670,17 +664,16 @@ class nsRefreshDriver final : public moz
 
   AutoTArray<mozilla::PresShell*, 16> mResizeEventFlushObservers;
   AutoTArray<mozilla::PresShell*, 16> mDelayedResizeEventFlushObservers;
   AutoTArray<mozilla::PresShell*, 16> mStyleFlushObservers;
   AutoTArray<mozilla::PresShell*, 16> mLayoutFlushObservers;
   // nsTArray on purpose, because we want to be able to swap.
   nsTArray<Document*> mFrameRequestCallbackDocs;
   nsTArray<Document*> mThrottledFrameRequestCallbackDocs;
-  nsTArray<RefPtr<Document>> mAutoFocusFlushDocuments;
   nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
   nsTArray<mozilla::UniquePtr<mozilla::PendingFullscreenEvent>>
       mPendingFullscreenEvents;
   AutoTArray<mozilla::AnimationEventDispatcher*, 16>
       mAnimationEventFlushObservers;
 
   // nsPresContexts which `NotifyContentfulPaint` have been called,
   // however the corresponding paint doesn't come from a regular
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -126,18 +126,16 @@ class nsHtml5TreeOpExecutor final
    */
   NS_IMETHOD WillInterrupt() override;
 
   /**
    * Unimplemented. For interface compat only.
    */
   void WillResume() override;
 
-  virtual nsIContentSink* AsExecutor() override { return this; }
-
   virtual void InitialTranslationCompleted() override;
 
   /**
    * Sets the parser.
    */
   NS_IMETHOD SetParser(nsParserBase* aParser) override;
 
   /**
--- a/parser/htmlparser/nsIContentSink.h
+++ b/parser/htmlparser/nsIContentSink.h
@@ -85,22 +85,16 @@ class nsIContentSink : public nsISupport
 
   /**
    * This method gets called when the parser i/o gets unblocked,
    * and we're about to start dumping content again to the sink.
    */
   virtual void WillResume() = 0;
 
   /**
-   * This method returns nullptr unless `this` can
-   * be cast as nsHtml5TreeOpExecutor.
-   */
-  virtual nsIContentSink* AsExecutor() { return nullptr; }
-
-  /**
    * This method gets called by the parser so that the content
    * sink can retain a reference to the parser. The expectation
    * is that the content sink will drop the reference when it
    * gets the DidBuildModel notification i.e. when parsing is done.
    */
   NS_IMETHOD SetParser(nsParserBase* aParser) = 0;
 
   /**
--- a/parser/htmlparser/nsIHTMLContentSink.h
+++ b/parser/htmlparser/nsIHTMLContentSink.h
@@ -78,19 +78,13 @@ class nsIHTMLContentSink : public nsICon
 
   /**
    *  This method gets called by the parser when a close
    *  container tag has been consumed and needs to be closed.
    *
    * @param  aTag - The tag to be closed.
    */
   NS_IMETHOD CloseContainer(ElementType aTag) = 0;
-
-  /**
-   *  This method returns true if there are more than one
-   *  pending style sheets, false otherwise.
-   */
-  virtual bool WaitForPendingSheets() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID)
 
 #endif /* nsIHTMLContentSink_h___ */
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html.ini
@@ -0,0 +1,5 @@
+[autofocus-dialog.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [<dialog> can contain autofocus, without stopping page autofocus content from working]
+    expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-in-not-fully-active-document.html.ini
@@ -0,0 +1,3 @@
+[autofocus-in-not-fully-active-document.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/autofocus-on-stable-document.html.ini
@@ -0,0 +1,5 @@
+[autofocus-on-stable-document.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [Autofocus should work if an element with autofocus is inserted into a document which was loaded some time ago.]
+    expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html.ini
@@ -0,0 +1,8 @@
+[document-with-fragment-empty.html]
+  [Autofocus elements in iframed documents with empty fragments should work.]
+    expected:
+      if not debug and (os == "win") and (processor == "x86"): [FAIL, PASS]
+      if debug and (os == "android"): PASS
+      if debug and (os == "mac"): PASS
+      if debug and (os == "linux"): PASS
+      [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html.ini
@@ -0,0 +1,6 @@
+[document-with-fragment-nonexistent.html]
+  [Autofocus elements in iframed documents with non-existent fragments should work.]
+    expected:
+      if debug and (os == "linux"): PASS
+      if debug and (os == "android"): PASS
+      [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html.ini
@@ -0,0 +1,7 @@
+[document-with-fragment-top.html]
+  [Autofocus elements in iframed documents with "top" fragments should work.]
+    expected:
+      if debug and (os == "android"): PASS
+      if debug and (os == "linux"): PASS
+      if debug and (os == "mac"): PASS
+      [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-reconnected.html.ini
@@ -0,0 +1,5 @@
+[first-reconnected.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [The second autofocus element wins if the first autofocus element was disconnected and reconnected before flushing the autofocus candidates.]
+    expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-when-later-but-before.html.ini
@@ -0,0 +1,3 @@
+[first-when-later-but-before.html]
+  [The temporally first autofocus in the document wins, even if an element is inserted later that is previous in the document tree.]
+    expected: [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first-when-later.html.ini
@@ -0,0 +1,3 @@
+[first-when-later.html]
+  [The first autofocus in the document wins, even if elements are inserted later.]
+    expected: [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/first.html.ini
@@ -0,0 +1,3 @@
+[first.html]
+  [The first autofocus element in the document should win.]
+    expected: [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/focusable-area-in-top-document.html.ini
@@ -0,0 +1,5 @@
+[focusable-area-in-top-document.html]
+  [If topDocument's focused area is not topDocument, autofocus is not processed.]
+    expected:
+      if (processor == "x86") and (os == "linux"): [FAIL, PASS]
+      [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-autofocus-on-changing-input-type.html.ini
@@ -0,0 +1,3 @@
+[no-autofocus-on-changing-input-type.html]
+  [Changing input type should not refocus on the element.]
+    expected: [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-cross-origin-autofocus.html.ini
@@ -0,0 +1,3 @@
+[no-cross-origin-autofocus.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/no-sandboxed-automatic-features.html.ini
@@ -0,0 +1,3 @@
+[no-sandboxed-automatic-features.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/not-on-first-task.html.ini
@@ -0,0 +1,3 @@
+[not-on-first-task.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/queue-non-focusable.html.ini
@@ -0,0 +1,8 @@
+[queue-non-focusable.html]
+  [If the first autofocus element is not focusable, but becomes focusable before a frame, it should be focused.]
+    expected:
+      if debug and (os == "win") and swgl: PASS
+      if debug and (os == "android"): PASS
+      if debug and (os == "linux"): PASS
+      if debug and (os == "mac"): PASS
+      [PASS, FAIL]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/same-origin-autofocus.html.ini
@@ -0,0 +1,5 @@
+[same-origin-autofocus.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [Autofocus should not work in the same origin grand child iframe]
+    expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-another-top-level-browsing-context.html.ini
@@ -0,0 +1,3 @@
+[skip-another-top-level-browsing-context.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-non-focusable.html.ini
@@ -0,0 +1,5 @@
+[skip-non-focusable.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [Non-focusable autofocus element is skipped.]
+    expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/skip-not-fully-active.html.ini
@@ -0,0 +1,3 @@
+[skip-not-fully-active.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini
@@ -0,0 +1,5 @@
+[spin-by-blocking-style-sheet.html]
+  expected: TIMEOUT
+  [Script-blocking style sheet should pause flushing autofocus candidates.]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/supported-elements.html.ini
@@ -0,0 +1,17 @@
+[supported-elements.html]
+  expected:
+    if (os == "android") and fission: [OK, TIMEOUT]
+  [Contenteditable element should support autofocus]
+    expected: FAIL
+
+  [Element with tabindex should support autofocus]
+    expected: FAIL
+
+  [Host element with delegatesFocus including no focusable descendants should be skipped]
+    expected: FAIL
+
+  [Area element should support autofocus]
+    expected: FAIL
+
+  [Host element with delegatesFocus should support autofocus]
+    expected: FAIL
--- a/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/update-the-rendering.html.ini
+++ b/testing/web-platform/meta/html/interaction/focus/the-autofocus-attribute/update-the-rendering.html.ini
@@ -1,5 +1,5 @@
 [update-the-rendering.html]
   expected:
     if (os == "android") and fission: [OK, TIMEOUT]
   ["Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks]
-    expected: [PASS, FAIL]
+    expected: FAIL
--- a/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html
+++ b/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-top.html
@@ -5,22 +5,19 @@
 
 <iframe src="resources/frame-with-autofocus-element.html#top"></iframe>
 
 <script>
 'use strict';
 
 promise_test(async () => {
   await waitForLoad(window);
-  const iframe = document.querySelector('iframe');
   await waitUntilStableAutofocusState();
-  assert_equals(document.activeElement, iframe,
+  assert_equals(document.activeElement, document.querySelector('iframe'),
       'Autofocus elements in iframes should be focused.');
-  const doc = iframe.contentDocument;
-  assert_true(!doc.querySelector(':target'));
 
   let input = document.createElement('input');
   input.autofocus = true;
   document.body.appendChild(input);
   await waitUntilStableAutofocusState();
   assert_not_equals(document.activeElement, input);
 }, 'Autofocus elements in iframed documents with "top" fragments should work.');
 
--- a/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-valid.html
+++ b/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/document-with-fragment-valid.html
@@ -16,33 +16,17 @@ promise_test(async () => {
   const doc = iframe.contentDocument;
   assert_true(!!doc.querySelector(':target'));
 
   let input = doc.createElement('input');
   input.autofocus = true;
   doc.body.appendChild(input);
   await waitUntilStableAutofocusState();
   assert_not_equals(doc.activeElement, input);
-  iframe.remove();
-}, 'Autofocus elements in iframed documents with URL fragments should be skipped. (id matches)');
-
-promise_test(async () => {
-  let iframe = await waitForIframeLoad("resources/frame-with-a.html");
-  iframe.contentWindow.location.hash = 'anchor1';
-  await waitForEvent(iframe.contentWindow, 'hashchange');
-  const doc = iframe.contentDocument;
-  assert_true(!!doc.querySelector(':target'));
-
-  let input = doc.createElement('input');
-  input.autofocus = true;
-  doc.body.appendChild(input);
-  await waitUntilStableAutofocusState();
-  assert_not_equals(doc.activeElement, input);
-  iframe.remove();
-}, 'Autofocus elements in iframed documents with URL fragments should be skipped.(a element)');
+}, 'Autofocus elements in iframed documents with URL fragments should be skipped.');
 
 promise_test(async () => {
   let w = window.open('resources/frame-with-anchor.html');
   await waitForLoad(w);
   w.location.hash = 'anchor1';
   await waitForEvent(w, 'hashchange');
   const doc = w.document;
   assert_true(!!doc.querySelector(':target'));
deleted file mode 100644
--- a/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/resources/frame-with-a.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<body>
-<a name="anchor1"></a>
-</body>
--- a/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/resources/utils.js
+++ b/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/resources/utils.js
@@ -34,18 +34,8 @@ function timeOut(test, ms) {
 // function.
 // Exception: If the document has script-blocking style sheets, this function
 // doesn't work well.
 async function waitUntilStableAutofocusState(w) {
   let targetWindow = w || window;
   // Awaiting one animation frame is an easy way to determine autofocus state.
   await waitForAnimationFrame(targetWindow);
 }
-
-async function waitForIframeLoad(src, w = window) {
-  const iframe = w.document.createElement("iframe");
-  let loadPromise = new Promise(resolve => {
-    iframe.addEventListener("load", () => resolve(iframe));
-  });
-  iframe.src = src;
-  w.document.body.appendChild(iframe);
-  return loadPromise;
-}
--- a/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html
+++ b/testing/web-platform/tests/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html
@@ -1,19 +1,17 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/utils.js"></script>
+<link rel="stylesheet" href="resources/erase-first.css?pipe=trickle(d1)">
 
 <input id="first" autofocus>
 <input id="second" autofocus>
 
-<link rel="stylesheet" href="resources/erase-first.css?pipe=trickle(d1)">
-
 <script>
 'use strict';
 
 promise_test(async () => {
-  await waitForLoad(window);
-  await waitForAnimationFrame();
+  await waitForEvent(document.body, 'focus', {capture:true});
   assert_equals(document.activeElement.id, 'second');
 }, 'Script-blocking style sheet should pause flushing autofocus candidates.');
 </script>