diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 988c896b02db..770f80811a2f 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -381,6 +381,7 @@ #include "nsIX509Cert.h" #include "nsIX509CertValidity.h" #include "nsIXMLContentSink.h" +#include "nsIHTMLContentSink.h" #include "nsIXULRuntime.h" #include "nsImageLoadingContent.h" #include "nsImportModule.h" @@ -12790,6 +12791,27 @@ void Document::FlushAutoFocusCandidates() { iter.Remove(); continue; } + + nsCOMPtr sink = + do_QueryInterface(autoFocusElementDoc->GetCurrentContentSink()); + if (sink) { + nsHtml5TreeOpExecutor* executor = + static_cast(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) { diff --git a/dom/base/nsContentSink.h b/dom/base/nsContentSink.h index ec89ff95877f..39b14217135a 100644 --- a/dom/base/nsContentSink.h +++ b/dom/base/nsContentSink.h @@ -169,6 +169,10 @@ class nsContentSink : public nsICSSLoaderObserver, 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) { @@ -180,10 +184,6 @@ class nsContentSink : public nsICSSLoaderObserver, 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() { diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp index ddf596d4174f..e7956d674ce6 100644 --- a/dom/html/nsHTMLContentSink.cpp +++ b/dom/html/nsHTMLContentSink.cpp @@ -114,6 +114,7 @@ class HTMLContentSink : public nsContentSink, public nsIHTMLContentSink { virtual void SetDocumentCharset(NotNull aEncoding) override; virtual nsISupports* GetTarget() override; virtual bool IsScriptExecuting() override; + virtual bool WaitForPendingSheets() override; virtual void ContinueInterruptedParsingAsync() override; // nsIHTMLContentSink @@ -924,6 +925,10 @@ void HTMLContentSink::ContinueInterruptedParsingIfEnabled() { } } +bool HTMLContentSink::WaitForPendingSheets() { + return nsContentSink::WaitForPendingSheets(); +} + void HTMLContentSink::ContinueInterruptedParsingAsync() { nsCOMPtr ev = NewRunnableMethod( "HTMLContentSink::ContinueInterruptedParsingIfEnabled", this, diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index 65a1f619e911..e47d99a1b2f2 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -131,6 +131,8 @@ class nsHtml5TreeOpExecutor final */ void WillResume() override; + virtual nsIContentSink* AsExecutor() override { return this; } + virtual void InitialTranslationCompleted() override; /** diff --git a/parser/htmlparser/nsIContentSink.h b/parser/htmlparser/nsIContentSink.h index 10a872a3e578..aa77c192c79e 100644 --- a/parser/htmlparser/nsIContentSink.h +++ b/parser/htmlparser/nsIContentSink.h @@ -89,6 +89,12 @@ class nsIContentSink : public nsISupports { */ 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 diff --git a/parser/htmlparser/nsIHTMLContentSink.h b/parser/htmlparser/nsIHTMLContentSink.h index 835044be6578..3e81d5d77090 100644 --- a/parser/htmlparser/nsIHTMLContentSink.h +++ b/parser/htmlparser/nsIHTMLContentSink.h @@ -83,6 +83,12 @@ class nsIHTMLContentSink : public nsIContentSink { * @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) diff --git 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 index 4d4e1da137db..fb87eca77a6e 100644 --- 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 @@ -2,11 +2,12 @@ - + +