From 2a9aacbacbbadc05042597831bb0da1363425d4b Mon Sep 17 00:00:00 2001 From: Zibi Braniecki Date: Thu, 23 May 2019 19:01:35 +0000 Subject: [PATCH] Bug 1546432 - Add roots management to Mutations. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D31337 --HG-- extra : moz-landing-system : lando --- intl/l10n/DocumentL10n.cpp | 44 +++++++++++++++++++++++++++++++++++--- intl/l10n/DocumentL10n.h | 14 ++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/intl/l10n/DocumentL10n.cpp b/intl/l10n/DocumentL10n.cpp index 0e1d1b417673..5fdb6415ca18 100644 --- a/intl/l10n/DocumentL10n.cpp +++ b/intl/l10n/DocumentL10n.cpp @@ -63,6 +63,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DocumentL10n) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMLocalization) NS_IMPL_CYCLE_COLLECTION_UNLINK(mContentSink) NS_IMPL_CYCLE_COLLECTION_UNLINK(mReady) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoots) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DocumentL10n) @@ -71,6 +72,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DocumentL10n) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMLocalization) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReady) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoots) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DocumentL10n) @@ -102,8 +104,8 @@ DocumentL10n::~DocumentL10n() { void DocumentL10n::DisconnectMutations() { if (mMutations) { - mDocument->RemoveMutationObserver(mMutations); mMutations->Disconnect(); + DisconnectRoots(); } } @@ -645,7 +647,7 @@ void DocumentL10n::TriggerInitialDocumentTranslation() { GetTranslatables(*elem, elements, rv); - mMutations->ConnectRoot(elem); + ConnectRoot(elem); RefPtr promise = TranslateElements(elements, rv); if (!promise) { @@ -676,7 +678,6 @@ void DocumentL10n::InitialDocumentTranslationCompleted() { mContentSink->InitialDocumentTranslationCompleted(); mContentSink = nullptr; } - mDocument->AddMutationObserverUnlessExists(mMutations); } Promise* DocumentL10n::Ready() { return mReady; } @@ -687,6 +688,43 @@ void DocumentL10n::OnChange() { } } +void DocumentL10n::ConnectRoot(nsINode* aNode) { + nsCOMPtr global = aNode->GetOwnerGlobal(); + if (!global) { + return; + } + +#ifdef DEBUG + for (auto iter = mRoots.ConstIter(); !iter.Done(); iter.Next()) { + nsINode* root = iter.Get()->GetKey(); + + MOZ_ASSERT( + root != aNode && !root->Contains(aNode) && !aNode->Contains(root), + "Cannot add a root that overlaps with existing root."); + } +#endif + + mRoots.PutEntry(aNode); + + aNode->AddMutationObserverUnlessExists(mMutations); +} + +void DocumentL10n::DisconnectRoot(nsINode* aNode) { + if (mRoots.Contains(aNode)) { + aNode->RemoveMutationObserver(mMutations); + mRoots.RemoveEntry(aNode); + } +} + +void DocumentL10n::DisconnectRoots() { + for (auto iter = mRoots.ConstIter(); !iter.Done(); iter.Next()) { + nsRefPtrHashKey* elem = iter.Get(); + + elem->GetKey()->RemoveMutationObserver(mMutations); + } + mRoots.Clear(); +} + void DocumentL10n::SetRootInfo(Element* aElement) { nsAutoCString primaryLocale; LocaleService::GetInstance()->GetAppLocaleAsBCP47(primaryLocale); diff --git a/intl/l10n/DocumentL10n.h b/intl/l10n/DocumentL10n.h index 888818a45700..50b7e3ef914b 100644 --- a/intl/l10n/DocumentL10n.h +++ b/intl/l10n/DocumentL10n.h @@ -85,6 +85,7 @@ class DocumentL10n final : public nsIObserver, nsCOMPtr mDOMLocalization; nsCOMPtr mContentSink; RefPtr mMutations; + nsTHashtable> mRoots; already_AddRefed MaybeWrapPromise(Promise* aPromise); void RegisterObservers(); @@ -142,6 +143,18 @@ class DocumentL10n final : public nsIObserver, Promise* Ready(); + /** + * Add node to nodes observed for localization + * related changes. + */ + void ConnectRoot(nsINode* aNode); + + /** + * Remove node from nodes observed for localization + * related changes. + */ + void DisconnectRoot(nsINode* aNode); + void TriggerInitialDocumentTranslation(); void InitialDocumentTranslationCompleted(); @@ -150,6 +163,7 @@ class DocumentL10n final : public nsIObserver, void OnChange(); protected: + void DisconnectRoots(); }; } // namespace dom