Bug 1446961, restructuring to allow nsXULElement to be subclassed. Rename nsXULElement::Create to make it clearer it creates from the prototype element, r=bz
authorNeil Deakin <neil@mozilla.com>
Fri, 27 Apr 2018 11:04:37 -0400
changeset 416037 5be83a2594fbd2e4e7612d4a779027f03c22b39c
parent 416036 e872787876a553d1d210a325e31d7e236c4c0857
child 416038 5659ad69e1451dfe2fc9a13b7a0f81526951c6aa
push id102706
push userneil@mozilla.com
push dateFri, 27 Apr 2018 15:17:30 +0000
treeherdermozilla-inbound@19b49df2389f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1446961
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1446961, restructuring to allow nsXULElement to be subclassed. Rename nsXULElement::Create to make it clearer it creates from the prototype element, r=bz
dom/base/nsContentUtils.cpp
dom/bindings/BindingUtils.cpp
dom/xbl/nsXBLContentSink.cpp
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xul/XULDocument.cpp
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9992,43 +9992,43 @@ nsContentUtils::NewXULOrHTMLElement(Elem
     // Step 6.1.
     if (synchronousCustomElements) {
       DoCustomElementCreate(aResult, nodeInfo->GetDocument(), nodeInfo,
                             definition->mConstructor, rv);
       if (rv.MaybeSetPendingException(cx)) {
         if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
           NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
         } else {
-          NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+          NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()));
         }
       }
       return NS_OK;
     }
 
     // Step 6.2.
     if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
       NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
     } else {
-      NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+      NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()));
     }
     (*aResult)->SetCustomElementData(new CustomElementData(definition->mType));
     nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
     return NS_OK;
   }
 
   if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
     // Per the Custom Element specification, unknown tags that are valid custom
     // element names should be HTMLElement instead of HTMLUnknownElement.
     if (isCustomElementName) {
       NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
     } else {
       *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
     }
   } else {
-    NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+    NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()));
   }
 
   if (!*aResult) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (customElementEnabled && isCustomElement) {
     (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -3870,17 +3870,18 @@ HTMLConstructor(JSContext* aCx, unsigned
     RefPtr<NodeInfo> nodeInfo =
       doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
                                           nullptr,
                                           ns,
                                           nsINode::ELEMENT_NODE);
     MOZ_ASSERT(nodeInfo);
 
     if (ns == kNameSpaceID_XUL) {
-      element = new nsXULElement(nodeInfo.forget());
+      element = nsXULElement::Construct(nodeInfo.forget());
+
     } else {
       if (tag == eHTMLTag_userdefined) {
         // Autonomous custom element.
         element = NS_NewHTMLElement(nodeInfo.forget());
       } else {
         // Customized built-in element.
         element = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
       }
--- a/dom/xbl/nsXBLContentSink.cpp
+++ b/dom/xbl/nsXBLContentSink.cpp
@@ -869,17 +869,17 @@ nsXBLContentSink::CreateElement(const ch
   *aAppendContent = true;
   RefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
 
   prototype->mNodeInfo = aNodeInfo;
 
   AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
 
   Element* result;
-  nsresult rv = nsXULElement::Create(prototype, mDocument, false, false, &result);
+  nsresult rv = nsXULElement::CreateFromPrototype(prototype, mDocument, false, false, &result);
   *aResult = result;
   return rv;
 #endif
 }
 
 nsresult
 nsXBLContentSink::AddAttributes(const char16_t** aAtts, Element* aElement)
 {
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1295,17 +1295,17 @@ nsXBLPrototypeBinding::ReadContentNode(n
         attrs[i].mName.SetTo(ni);
       }
 
       rv = prototype->SetAttrAt(i, val, documentURI);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsresult rv =
-      nsXULElement::Create(prototype, aDocument, false, false, getter_AddRefs(element));
+      nsXULElement::CreateFromPrototype(prototype, aDocument, false, false, getter_AddRefs(element));
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
 #endif
     NS_NewElement(getter_AddRefs(element), nodeInfo.forget(), NOT_FROM_PARSER);
 
     for (uint32_t i = 0; i < attrCount; i++) {
       rv = ReadNamespace(aStream, namespaceID);
       NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -3319,17 +3319,17 @@ XULDocument::CreateElementFromPrototype(
                 NS_ConvertUTF16toUTF8(aPrototype->mNodeInfo->QualifiedName()).get()));
     }
 
     RefPtr<Element> result;
 
     if (aPrototype->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
         // If it's a XUL element, it'll be lightweight until somebody
         // monkeys with it.
-        rv = nsXULElement::Create(aPrototype, this, true, aIsRoot, getter_AddRefs(result));
+        rv = nsXULElement::CreateFromPrototype(aPrototype, this, true, aIsRoot, getter_AddRefs(result));
         if (NS_FAILED(rv)) return rv;
     }
     else {
         // If it's not a XUL element, it's gonna be heavyweight no matter
         // what. So we need to copy everything out of the prototype
         // into the element.  Get a nodeinfo from our nodeinfo manager
         // for this node.
         RefPtr<mozilla::dom::NodeInfo> newNodeInfo;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -123,17 +123,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULEl
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULElementTearoff)
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoaderOwner)
 NS_INTERFACE_MAP_END_AGGREGATED(mElement)
 
 //----------------------------------------------------------------------
 // nsXULElement
 //
 
-nsXULElement::nsXULElement(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo)
+nsXULElement::nsXULElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsStyledElement(aNodeInfo),
       mBindingParent(nullptr)
 {
     XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements);
 
     // We may be READWRITE by default; check.
     if (IsReadWriteTextElement()) {
         AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
@@ -157,19 +157,36 @@ nsXULElement::MaybeUpdatePrivateLifetime
     nsPIDOMWindowOuter* win = OwnerDoc()->GetWindow();
     nsCOMPtr<nsIDocShell> docShell = win ? win->GetDocShell() : nullptr;
     if (docShell) {
         docShell->SetAffectPrivateSessionLifetime(false);
     }
 }
 
 /* static */
+nsXULElement* NS_NewBasicXULElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+{
+  return new nsXULElement(aNodeInfo);
+}
+
+ /* static */
+nsXULElement* nsXULElement::Construct(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+{
+  // Check tagname and create other types of elements here
+
+  RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
+  return NS_NewBasicXULElement(nodeInfo.forget());
+}
+
+/* static */
 already_AddRefed<nsXULElement>
-nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *aNodeInfo,
-                     bool aIsScriptable, bool aIsRoot)
+nsXULElement::CreateFromPrototype(nsXULPrototypeElement* aPrototype,
+                                  mozilla::dom::NodeInfo *aNodeInfo,
+                                  bool aIsScriptable,
+                                  bool aIsRoot)
 {
     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     nsCOMPtr<Element> baseElement;
     NS_NewXULElement(getter_AddRefs(baseElement), ni.forget(), dom::FROM_PARSER_NETWORK);
 
     if (baseElement) {
         nsXULElement* element = FromNode(baseElement);
 
@@ -204,21 +221,21 @@ nsXULElement::Create(nsXULPrototypeEleme
 
         return baseElement.forget().downcast<nsXULElement>();
     }
 
     return nullptr;
 }
 
 nsresult
-nsXULElement::Create(nsXULPrototypeElement* aPrototype,
-                     nsIDocument* aDocument,
-                     bool aIsScriptable,
-                     bool aIsRoot,
-                     Element** aResult)
+nsXULElement::CreateFromPrototype(nsXULPrototypeElement* aPrototype,
+                                  nsIDocument* aDocument,
+                                  bool aIsScriptable,
+                                  bool aIsRoot,
+                                  Element** aResult)
 {
     // Create an nsXULElement from a prototype
     NS_PRECONDITION(aPrototype != nullptr, "null ptr");
     if (! aPrototype)
         return NS_ERROR_NULL_POINTER;
 
     NS_PRECONDITION(aResult != nullptr, "null ptr");
     if (! aResult)
@@ -229,18 +246,18 @@ nsXULElement::Create(nsXULPrototypeEleme
         mozilla::dom::NodeInfo* ni = aPrototype->mNodeInfo;
         nodeInfo = aDocument->NodeInfoManager()->
           GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(), ni->NamespaceID(),
                       ELEMENT_NODE);
     } else {
         nodeInfo = aPrototype->mNodeInfo;
     }
 
-    RefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
-                                            aIsScriptable, aIsRoot);
+    RefPtr<nsXULElement> element = CreateFromPrototype(aPrototype, nodeInfo,
+                                                       aIsScriptable, aIsRoot);
     element.forget(aResult);
 
     return NS_OK;
 }
 
 nsresult
 NS_NewXULElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                  FromParser aFromParser)
@@ -263,17 +280,17 @@ NS_NewXULElement(Element** aResult, alre
 void
 NS_TrustedNewXULElement(Element** aResult,
                         already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
 {
     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     NS_PRECONDITION(ni, "need nodeinfo for non-proto Create");
 
     // Create an nsXULElement with the specified namespace and tag.
-    NS_ADDREF(*aResult = new nsXULElement(ni.forget()));
+    NS_ADDREF(*aResult = nsXULElement::Construct(ni.forget()));
 }
 
 //----------------------------------------------------------------------
 // nsISupports interface
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
@@ -301,17 +318,17 @@ NS_INTERFACE_MAP_END_INHERITING(nsStyled
 
 nsresult
 nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                     bool aPreallocateChildren) const
 {
     *aResult = nullptr;
 
     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
-    RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
+    RefPtr<nsXULElement> element = Construct(ni.forget());
 
     nsresult rv = element->mAttrsAndChildren.EnsureCapacityToClone(mAttrsAndChildren,
                                                                    aPreallocateChildren);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Note that we're _not_ copying mControllers.
 
     uint32_t count = mAttrsAndChildren.AttrCount();
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -330,24 +330,33 @@ enum {
 
 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
 
 #undef XUL_ELEMENT_FLAG_BIT
 
 class nsXULElement final : public nsStyledElement,
                            public nsIDOMNode
 {
+protected:
+    // Use Construct to construct elements instead of this constructor.
+    explicit nsXULElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
+
 public:
     using Element::Blur;
     using Element::Focus;
-    explicit nsXULElement(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo);
 
     static nsresult
-    Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument,
-           bool aIsScriptable, bool aIsRoot, mozilla::dom::Element** aResult);
+    CreateFromPrototype(nsXULPrototypeElement* aPrototype,
+                        nsIDocument* aDocument,
+                        bool aIsScriptable,
+                        bool aIsRoot,
+                        mozilla::dom::Element** aResult);
+
+    // This is the constructor for nsXULElements.
+    static nsXULElement* Construct(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
     NS_IMPL_FROMNODE(nsXULElement, kNameSpaceID_XUL)
 
     // nsISupports
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
 
     // nsINode
@@ -718,25 +727,30 @@ protected:
     nsIControllers *Controllers() {
       nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
       return slots ? slots->mControllers.get() : nullptr;
     }
 
     void UnregisterAccessKey(const nsAString& aOldValue);
     bool BoolAttrIsTrue(nsAtom* aName) const;
 
+    friend nsXULElement*
+    NS_NewBasicXULElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
+
     friend nsresult
     NS_NewXULElement(mozilla::dom::Element** aResult, mozilla::dom::NodeInfo *aNodeInfo,
                      mozilla::dom::FromParser aFromParser, const nsAString* aIs);
     friend void
     NS_TrustedNewXULElement(mozilla::dom::Element** aResult, mozilla::dom::NodeInfo *aNodeInfo);
 
     static already_AddRefed<nsXULElement>
-    Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *aNodeInfo,
-           bool aIsScriptable, bool aIsRoot);
+    CreateFromPrototype(nsXULPrototypeElement* aPrototype,
+                        mozilla::dom::NodeInfo *aNodeInfo,
+                        bool aIsScriptable,
+                        bool aIsRoot);
 
     bool IsReadWriteTextElement() const
     {
         return IsAnyOfXULElements(nsGkAtoms::textbox, nsGkAtoms::textarea) &&
                !HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
     }
 
     virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;