Bug 1411687 - part 1: HTMLEditor::GetBlockNodeParent() and HTMLEditor::GetBlock() should take an ancestor limiter node optionally r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 26 Oct 2017 22:54:30 +0900
changeset 688512 93c2eec593eb00f9e17631ac97b94dad97245b88
parent 688511 aee86cd0a8bab6b95db1243b120f046cc2b5a27c
child 688513 2cc74de2adfeb2531fef963f5ba287f09f3e4a2f
push id86761
push usermasayuki@d-toybox.com
push dateMon, 30 Oct 2017 05:49:37 +0000
reviewersm_kato
bugs1411687
milestone58.0a1
Bug 1411687 - part 1: HTMLEditor::GetBlockNodeParent() and HTMLEditor::GetBlock() should take an ancestor limiter node optionally r?m_kato Perhaps, most callers don't need parent block outside active editing host. Therefore, callers of these methods should be able to specify the editing host for making those methods stop looking for a block ancestor. Then, callers can avoid using EditorUtils::IsDescendantOf() and nsContentUtils::IsContentDescendantOf(). MozReview-Commit-ID: 7IK4gAVHY5d
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -743,38 +743,58 @@ HTMLEditor::IsBlockNode(nsINode* aNode)
 {
   return aNode && NodeIsBlockStatic(aNode);
 }
 
 /**
  * GetBlockNodeParent returns enclosing block level ancestor, if any.
  */
 Element*
-HTMLEditor::GetBlockNodeParent(nsINode* aNode)
+HTMLEditor::GetBlockNodeParent(nsINode* aNode,
+                               nsINode* aAncestorLimiter)
 {
   MOZ_ASSERT(aNode);
+  MOZ_ASSERT(!aAncestorLimiter ||
+             aNode == aAncestorLimiter ||
+             EditorUtils::IsDescendantOf(aNode, aAncestorLimiter),
+             "aNode isn't in aAncestorLimiter");
+
+  // The caller has already reached the limiter.
+  if (aNode == aAncestorLimiter) {
+    return nullptr;
+  }
 
   nsCOMPtr<nsINode> p = aNode->GetParentNode();
 
   while (p) {
     if (NodeIsBlockStatic(p)) {
       return p->AsElement();
     }
+    // Now, we have reached the limiter, there is no block in its ancestors.
+    if (p == aAncestorLimiter) {
+      return nullptr;
+    }
     p = p->GetParentNode();
   }
 
   return nullptr;
 }
 
 /**
  * Returns the node if it's a block, otherwise GetBlockNodeParent
  */
 Element*
-HTMLEditor::GetBlock(nsINode& aNode)
+HTMLEditor::GetBlock(nsINode& aNode,
+                     nsINode* aAncestorLimiter)
 {
+  MOZ_ASSERT(!aAncestorLimiter ||
+             &aNode == aAncestorLimiter ||
+             EditorUtils::IsDescendantOf(&aNode, aAncestorLimiter),
+             "aNode isn't in aAncestorLimiter");
+
   if (NodeIsBlockStatic(&aNode)) {
     return aNode.AsElement();
   }
   return GetBlockNodeParent(&aNode);
 }
 
 /**
  * IsNextCharInNodeWhitespace() checks the adjacent content in the same node to
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -180,19 +180,30 @@ public:
 
   /**
    * This sets background on the appropriate container element (table, cell,)
    * or calls into nsTextEditor to set the page background.
    */
   nsresult SetCSSBackgroundColor(const nsAString& aColor);
   nsresult SetHTMLBackgroundColor(const nsAString& aColor);
 
-  // Block methods moved from EditorBase
-  static Element* GetBlockNodeParent(nsINode* aNode);
-  static Element* GetBlock(nsINode& aNode);
+  /**
+   * GetBlockNodeParent() returns parent or nearest ancestor of aNode if
+   * there is a block parent.  If aAncestorLimiter is not nullptr,
+   * this stops looking for the result.
+   */
+  static Element* GetBlockNodeParent(nsINode* aNode,
+                                     nsINode* aAncestorLimiter = nullptr);
+  /**
+   * GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
+   * if there is a block parent.  If aAncestorLimiter is not nullptr,
+   * this stops looking for the result.
+   */
+  static Element* GetBlock(nsINode& aNode,
+                           nsINode* aAncestorLimiter = nullptr);
 
   void IsNextCharInNodeWhitespace(nsIContent* aContent,
                                   int32_t aOffset,
                                   bool* outIsSpace,
                                   bool* outIsNBSP,
                                   nsIContent** outNode = nullptr,
                                   int32_t* outOffset = 0);
   void IsPrevCharInNodeWhitespace(nsIContent* aContent,