diff --git a/content/base/src/DirectionalityUtils.cpp b/content/base/src/DirectionalityUtils.cpp index 9e642f78b8f7..27ad96119ba8 100644 --- a/content/base/src/DirectionalityUtils.cpp +++ b/content/base/src/DirectionalityUtils.cpp @@ -385,7 +385,9 @@ static nsINode* WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true, nsINode* aChangedNode = nullptr) { - MOZ_ASSERT(aElement, "aElement is null"); + MOZ_ASSERT(aElement, "Must have an element"); + MOZ_ASSERT(aElement->HasDirAuto(), "Element must have dir=auto"); + if (DoesNotParticipateInAutoDirection(aElement)) { return nullptr; } @@ -428,6 +430,7 @@ class nsTextNodeDirectionalityMap nsTextNodeDirectionalityMap* map = reinterpret_cast(aPropertyValue); + map->EnsureMapIsClear(textNode); delete map; } @@ -511,6 +514,14 @@ private: return PL_DHASH_REMOVE; } + static PLDHashOperator ClearEntry(nsPtrHashKey* aEntry, void* aData) + { + Element* rootNode = aEntry->GetKey(); + rootNode->ClearHasDirAutoSet(); + rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy); + return PL_DHASH_REMOVE; + } + public: void UpdateAutoDirection(Directionality aDir) { @@ -522,6 +533,13 @@ public: mElements.EnumerateEntries(ResetNodeDirection, aTextNode); } + void EnsureMapIsClear(nsINode* aTextNode) + { + uint32_t clearedEntries = + mElements.EnumerateEntries(ClearEntry, aTextNode); + MOZ_ASSERT(clearedEntries == 0, "Map should be empty already"); + } + static void RemoveElementFromMap(nsINode* aTextNode, Element* aElement) { if (aTextNode->HasTextNodeDirectionalityMap()) { @@ -552,6 +570,13 @@ public: "Map missing in ResetTextNodeDirection"); GetDirectionalityMap(aTextNode)->ResetAutoDirection(aTextNode); } + + static void EnsureMapIsClearFor(nsINode* aTextNode) + { + if (aTextNode->HasTextNodeDirectionalityMap()) { + GetDirectionalityMap(aTextNode)->EnsureMapIsClear(aTextNode); + } + } }; Directionality @@ -655,6 +680,7 @@ WalkDescendantsResetAutoDirection(Element* aElement) if (child->HasTextNodeDirectionalityMap()) { nsTextNodeDirectionalityMap::ResetTextNodeDirection(child); + nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child); } child = child->GetNextNode(aElement); } @@ -731,9 +757,13 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir, if (parent->HasDirAuto()) { bool resetDirection = false; + nsINode* directionWasSetByTextNode = + static_cast(parent->GetProperty(nsGkAtoms::dirAutoSetBy)); if (!parent->HasDirAutoSet()) { // Fast path if parent's direction is not yet set by any descendant + MOZ_ASSERT(!directionWasSetByTextNode, + "dirAutoSetBy property should be null"); resetDirection = true; } else { // If parent's direction is already set, we need to know if @@ -741,8 +771,6 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir, // We will walk parent's descendants in tree order starting from // aTextNode to optimize for the most common case where text nodes are // being appended to tree. - nsINode* directionWasSetByTextNode = - static_cast(parent->GetProperty(nsGkAtoms::dirAutoSetBy)); if (!directionWasSetByTextNode) { resetDirection = true; } else if (directionWasSetByTextNode != aTextNode) { @@ -758,9 +786,6 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir, // we found the node that set the element's direction after our // text node, so we need to reset the direction resetDirection = true; - nsTextNodeDirectionalityMap::RemoveElementFromMap( - directionWasSetByTextNode, parent - ); break; } @@ -770,6 +795,11 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir, } if (resetDirection) { + if (directionWasSetByTextNode) { + nsTextNodeDirectionalityMap::RemoveElementFromMap( + directionWasSetByTextNode, parent + ); + } parent->SetDirectionality(aDir, aNotify); nsTextNodeDirectionalityMap::AddEntryToMap(aTextNode, parent); SetDirectionalityOnDescendants(parent, aDir, aNotify); @@ -790,6 +820,7 @@ SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset, bool aNotify) { if (!NodeAffectsDirAutoAncestor(aTextNode)) { + nsTextNodeDirectionalityMap::EnsureMapIsClearFor(aTextNode); return; } @@ -846,6 +877,7 @@ void ResetDirectionSetByTextNode(nsTextNode* aTextNode) { if (!NodeAffectsDirAutoAncestor(aTextNode)) { + nsTextNodeDirectionalityMap::EnsureMapIsClearFor(aTextNode); return; }