Skip to content

Instantly share code, notes, and snippets.

@zbraniecki
Created January 17, 2019 18:29
Show Gist options
  • Select an option

  • Save zbraniecki/b9128f3ac439321da7b5e4581fb650f3 to your computer and use it in GitHub Desktop.

Select an option

Save zbraniecki/b9128f3ac439321da7b5e4581fb650f3 to your computer and use it in GitHub Desktop.
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -1337,7 +1337,8 @@ Document::Document(const char* aContentT
mThrowOnDynamicMarkupInsertionCounter(0),
mIgnoreOpensDuringUnloadCounter(0),
mDocLWTheme(Doc_Theme_Uninitialized),
- mSavedResolution(1.0f) {
+ mSavedResolution(1.0f),
+ mPendingInitialTranslation(false) {
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
SetIsInDocument();
@@ -3127,6 +3128,9 @@ void Document::LocalizationLinkAdded(Ele
// will be resolved once the end of l10n resource
// container is reached.
mL10nResources.AppendElement(href);
+
+ //printf("In Document::LocalizationLinkAdded, setting mPendingInitialTranslation to true.\n");
+ mPendingInitialTranslation = true;
}
}
@@ -3174,6 +3178,21 @@ void Document::TriggerInitialDocumentTra
}
}
+void Document::InitialDocumentTranslationCompleted() {
+ //printf("Document::InitialDocumentTranslationCompleted.\n");
+ mPendingInitialTranslation = false;
+
+ nsCOMPtr<nsIContentSink> sink;
+ if (mParser) {
+ sink = mParser->GetContentSink();
+ } else {
+ sink = do_QueryReferent(mWeakSink);
+ }
+ if (sink) {
+ sink->InitialDocumentTranslationCompleted();
+ }
+}
+
bool Document::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) {
MOZ_ASSERT(NS_IsMainThread());
@@ -8136,7 +8155,6 @@ void Document::SetReadyStateInternal(Rea
mXULPersist->Init();
}
}
- TriggerInitialDocumentTranslation();
}
RecordNavigationTiming(rs);
diff --git a/dom/base/Document.h b/dom/base/Document.h
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3394,7 +3394,6 @@ class Document : public nsINode,
*/
void LocalizationLinkRemoved(Element* aLinkElement);
- protected:
/**
* This method should be collect as soon as the
* parsing of the document is completed.
@@ -3409,6 +3408,9 @@ class Document : public nsINode,
*/
void TriggerInitialDocumentTranslation();
+ virtual void InitialDocumentTranslationCompleted();
+
+ protected:
RefPtr<mozilla::dom::DocumentL10n> mDocumentL10n;
private:
@@ -4440,9 +4442,13 @@ class Document : public nsINode,
// Pres shell resolution saved before entering fullscreen mode.
float mSavedResolution;
+ bool mPendingInitialTranslation;
+
public:
// Needs to be public because the bindings code pokes at it.
js::ExpandoAndGeneration mExpandoAndGeneration;
+
+ bool HasPendingInitialTranslation() { return mPendingInitialTranslation; }
};
NS_DEFINE_STATIC_IID_ACCESSOR(Document, NS_IDOCUMENT_IID)
diff --git a/dom/base/nsContentSink.cpp b/dom/base/nsContentSink.cpp
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -1170,8 +1170,10 @@ void nsContentSink::StartLayout(bool aIg
mDeferredLayoutStart = true;
- if (!aIgnorePendingSheets && WaitForPendingSheets()) {
- // Bail out; we'll start layout when the sheets load
+ if (!aIgnorePendingSheets &&
+ (WaitForPendingSheets() ||
+ mDocument->HasPendingInitialTranslation())) {
+ // Bail out; we'll start layout when the sheets and l10n load
return;
}
diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -1073,6 +1073,8 @@ nsresult nsXMLContentSink::HandleEndElem
// probably need to deal here.... (and stop appending them on open).
mState = eXMLContentSinkState_InEpilog;
+ mDocument->TriggerInitialDocumentTranslation();
+
// We might have had no occasion to start layout yet. Do so now.
MaybeStartLayout(false);
}
@@ -1407,6 +1409,10 @@ nsresult nsXMLContentSink::AddText(const
return NS_OK;
}
+void nsXMLContentSink::InitialDocumentTranslationCompleted() {
+ StartLayout(false);
+}
+
void nsXMLContentSink::FlushPendingNotifications(FlushType aType) {
// Only flush tags if we're not doing the notification ourselves
// (since we aren't reentrant)
diff --git a/dom/xml/nsXMLContentSink.h b/dom/xml/nsXMLContentSink.h
--- a/dom/xml/nsXMLContentSink.h
+++ b/dom/xml/nsXMLContentSink.h
@@ -67,6 +67,7 @@ class nsXMLContentSink : public nsConten
NS_IMETHOD WillInterrupt(void) override;
NS_IMETHOD WillResume(void) override;
NS_IMETHOD SetParser(nsParserBase* aParser) override;
+ virtual void InitialDocumentTranslationCompleted() override;
virtual void FlushPendingNotifications(mozilla::FlushType aType) override;
virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
virtual nsISupports* GetTarget() override;
diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -449,6 +449,12 @@ void XULDocument::AddElementToDocumentPo
}
}
+void XULDocument::InitialDocumentTranslationCompleted() {
+ //printf("XULDocument::InitialDocumentTranslationCompleted.\n");
+ mPendingInitialTranslation = false;
+ DoneWalking();
+}
+
void XULDocument::AddSubtreeToDocument(nsIContent* aContent) {
MOZ_ASSERT(aContent->GetComposedDoc() == this, "Element not in doc!");
@@ -971,7 +977,17 @@ nsresult XULDocument::DoneWalking() {
// XXXldb This is where we should really be setting the chromehidden
// attribute.
+
if (!mDocumentLoaded) {
+ //printf("In XULDocument::DoneWalking.\n");
+ if (mPendingInitialTranslation) {
+ //printf("Document::mPendingInitialTranslation is true.\n");
+ TriggerInitialDocumentTranslation();
+ return NS_OK;
+ } else {
+ //printf("Document::mPendingInitialTranslation is false.\n");
+ }
+
// Make sure we don't reenter here from StartLayout(). Note that
// setting mDocumentLoaded to true here means that if StartLayout()
// causes ResumeWalk() to be reentered, we'll take the other branch of
@@ -983,18 +999,10 @@ nsresult XULDocument::DoneWalking() {
NotifyPossibleTitleChange(false);
- // For performance reasons, we want to trigger the DocumentL10n's
- // `TriggerInitialDocumentTranslation` within the same microtask that will
- // be created for a `MozBeforeInitialXULLayout` event listener.
- AddEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
- mDocumentL10n, true, false);
-
nsContentUtils::DispatchTrustedEvent(
this, ToSupports(this), NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
CanBubble::eYes, Cancelable::eNo);
- RemoveEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
- mDocumentL10n, true);
// Before starting layout, check whether we're a toplevel chrome
// window. If we are, setup some state so that we don't have to restyle
diff --git a/dom/xul/XULDocument.h b/dom/xul/XULDocument.h
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -76,6 +76,8 @@ class XULDocument final : public XMLDocu
virtual void EndLoad() override;
+ virtual void InitialDocumentTranslationCompleted() override;
+
// nsIMutationObserver interface
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
diff --git a/intl/l10n/DocumentL10n.cpp b/intl/l10n/DocumentL10n.cpp
--- a/intl/l10n/DocumentL10n.cpp
+++ b/intl/l10n/DocumentL10n.cpp
@@ -312,13 +312,16 @@ class L10nReadyHandler final : public Pr
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(L10nReadyHandler)
- explicit L10nReadyHandler(Promise* aPromise) : mPromise(aPromise) {}
+ explicit L10nReadyHandler(Promise* aPromise, Document* aDocument)
+ : mPromise(aPromise), mDocument(aDocument) {}
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
+ mDocument->InitialDocumentTranslationCompleted();
mPromise->MaybeResolveWithUndefined();
}
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
+ mDocument->InitialDocumentTranslationCompleted();
mPromise->MaybeRejectWithUndefined();
}
@@ -326,6 +329,7 @@ class L10nReadyHandler final : public Pr
~L10nReadyHandler() = default;
RefPtr<Promise> mPromise;
+ RefPtr<Document> mDocument;
};
NS_IMPL_CYCLE_COLLECTION(L10nReadyHandler, mPromise)
@@ -351,7 +355,8 @@ void DocumentL10n::TriggerInitialDocumen
RefPtr<Promise> promise;
mDOMLocalization->TranslateRoots(getter_AddRefs(promise));
- RefPtr<PromiseNativeHandler> l10nReadyHandler = new L10nReadyHandler(mReady);
+ RefPtr<PromiseNativeHandler> l10nReadyHandler =
+ new L10nReadyHandler(mReady, mDocument);
promise->AppendNativeHandler(l10nReadyHandler);
}
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -170,6 +170,7 @@ nsHtml5TreeOpExecutor::DidBuildModel(boo
}
if (!destroying) {
+ mDocument->TriggerInitialDocumentTranslation();
nsContentSink::StartLayout(false);
}
}
@@ -228,6 +229,10 @@ nsHtml5TreeOpExecutor::SetParser(nsParse
return NS_OK;
}
+void nsHtml5TreeOpExecutor::InitialDocumentTranslationCompleted() {
+ nsContentSink::StartLayout(false);
+}
+
void nsHtml5TreeOpExecutor::FlushPendingNotifications(FlushType aType) {
if (aType >= FlushType::EnsurePresShellInitAndFrames) {
// Bug 577508 / 253951
diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -136,6 +136,8 @@ class nsHtml5TreeOpExecutor final
*/
NS_IMETHOD WillResume() override;
+ virtual void InitialDocumentTranslationCompleted() override;
+
/**
* Sets the parser.
*/
diff --git a/parser/htmlparser/nsIContentSink.h b/parser/htmlparser/nsIContentSink.h
--- a/parser/htmlparser/nsIContentSink.h
+++ b/parser/htmlparser/nsIContentSink.h
@@ -130,6 +130,8 @@ class nsIContentSink : public nsISupport
* Posts a runnable that continues parsing.
*/
virtual void ContinueInterruptedParsingAsync() {}
+
+ virtual void InitialDocumentTranslationCompleted() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentSink, NS_ICONTENT_SINK_IID)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment