Bug 1374999 - stylo: Iterate over manually created editor NAC. r?bholley draft
authorCameron McCormack <cam@mcc.id.au>
Tue, 27 Jun 2017 17:34:48 -0700
changeset 601088 47b119ac05208b2d5b463b1ae82d5b07bf886acf
parent 600694 8f80d594c08d5c7a112e5d4b9eb44ffca717eb7b
child 635165 fd7dcd2951a233fb402cc46acf175b5767fbdb46
push id65954
push userbmo:cam@mcc.id.au
push dateWed, 28 Jun 2017 00:35:01 +0000
reviewersbholley
bugs1374999
milestone56.0a1
Bug 1374999 - stylo: Iterate over manually created editor NAC. r?bholley MozReview-Commit-ID: 1CiWVfYbxaJ
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsGkAtomList.h
editor/libeditor/HTMLAnonymousNodeEditor.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -10263,16 +10263,22 @@ nsContentUtils::AppendNativeAnonymousChi
     AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
     primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
     for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
       MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == aContent);
       AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids, aFlags);
     }
   }
 
+  // Get manually created NAC (editor resize handles, etc.).
+  if (auto nac = static_cast<ManualNAC*>(
+        aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
+    aKids.AppendElements(*nac);
+  }
+
   // The root scroll frame is not the primary frame of the root element.
   // Detect and handle this case.
   if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
       aContent == aContent->OwnerDoc()->GetRootElement()) {
     AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
   }
 }
 
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -190,16 +190,22 @@ struct EventNameMapping
   // True if mAtom is possibly used by special SVG/SMIL events, but
   // mMessage is eUnidentifiedEvent. See EventNameList.h
   bool mMaybeSpecialSVGorSMILEvent;
 };
 
 typedef bool (*CallOnRemoteChildFunction) (mozilla::dom::TabParent* aTabParent,
                                            void* aArg);
 
+namespace mozilla {
+// 16 seems to be the maximum number of manual NAC nodes that editor
+// creates for a given element.
+typedef AutoTArray<mozilla::dom::Element*,16> ManualNAC;
+}
+
 class nsContentUtils
 {
   friend class nsAutoScriptBlockerSuppressNodeRemoved;
   typedef mozilla::dom::Element Element;
   typedef mozilla::TimeDuration TimeDuration;
 
 public:
   static nsresult Init();
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2156,16 +2156,17 @@ GK_ATOM(transitionsOfBeforeProperty, "Tr
 GK_ATOM(transitionsOfAfterProperty, "TransitionsOfAfterProperty") // FrameTransitions*
 GK_ATOM(genConInitializerProperty, "QuoteNodeProperty")
 GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
 GK_ATOM(lockedStyleStates, "lockedStyleStates")
 GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
 GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
 GK_ATOM(paintRequestTime, "PaintRequestTime")
 GK_ATOM(pseudoProperty, "PseudoProperty")  // CSSPseudoElementType
+GK_ATOM(manualNACProperty, "ManualNACProperty") // ManualNAC*
 
 // Languages for lang-specific transforms
 GK_ATOM(Japanese, "ja")
 GK_ATOM(Chinese, "zh-CN")
 GK_ATOM(Taiwanese, "zh-TW")
 GK_ATOM(HongKongChinese, "zh-HK")
 GK_ATOM(Unicode, "x-unicode")
 
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
@@ -221,16 +221,26 @@ HTMLEditor::CreateAnonymousElement(nsIAt
     nsresult rv =
       newContent->BindToTree(doc, parentContent, parentContent, true);
     if (NS_FAILED(rv)) {
       newContent->UnbindFromTree();
       return nullptr;
     }
   }
 
+  // Record the NAC on the element, so that AllChildrenIterator can find it.
+  auto nac = static_cast<ManualNAC*>(
+      parentContent->GetProperty(nsGkAtoms::manualNACProperty));
+  if (!nac) {
+    nac = new ManualNAC();
+    parentContent->SetProperty(nsGkAtoms::manualNACProperty, nac,
+                               nsINode::DeleteProperty<ManualNAC>);
+  }
+  nac->AppendElement(newContent);
+
   ElementDeletionObserver* observer =
     new ElementDeletionObserver(newContent, parentContent);
   NS_ADDREF(observer); // NodeWillBeDestroyed releases.
   parentContent->AddMutationObserver(observer);
   newContent->AddMutationObserver(observer);
 
 #ifdef DEBUG
   // Editor anonymous content gets passed to PostRecreateFramesFor... which
@@ -298,16 +308,26 @@ HTMLEditor::DeleteRefToAnonymousNode(nsI
       docObserver->ContentRemoved(aContent->GetComposedDoc(),
                                   aParentContent, aContent, -1,
                                   aContent->GetPreviousSibling());
       if (document) {
         docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
       }
     }
   }
+
+  // Remove reference from the parent element.
+  auto nac = static_cast<mozilla::ManualNAC*>(
+      aParentContent->GetProperty(nsGkAtoms::manualNACProperty));
+  MOZ_ASSERT(nac);
+  nac->RemoveElement(aContent);
+  if (nac->IsEmpty()) {
+    aParentContent->DeleteProperty(nsGkAtoms::manualNACProperty);
+  }
+
   aContent->UnbindFromTree();
 }
 
 // The following method is mostly called by a selection listener. When a
 // selection change is notified, the method is called to check if resizing
 // handles, a grabber and/or inline table editing UI need to be displayed
 // or refreshed
 NS_IMETHODIMP