Bug 1292278 - Zero-index the namespace manager URIs. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Fri, 05 Aug 2016 14:21:54 -0700
changeset 308858 2629e4786dd8d07169068f86b84d7c24670306fd
parent 308857 59d426e1165ab0cd81c0624b046559c43a015950
child 308859 aab58242977a66a0c9343b4fed56e4b3192170db
push id20279
push usercbook@mozilla.com
push dateWed, 10 Aug 2016 14:04:43 +0000
treeherderfx-team@531100c1d950 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1292278
milestone51.0a1
Bug 1292278 - Zero-index the namespace manager URIs. r=bz The current setup here tries to "save" an entry in the list by checking for the "None" namespace everywhere and special-casing it. We can simplify this a lot by just adding the empty atom to the beginning of the array, which is the value that servo uses to represent "namespace none" anyway.
dom/base/nsNameSpaceManager.cpp
dom/base/nsNameSpaceManager.h
layout/style/ServoBindings.cpp
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -61,16 +61,18 @@ bool nsNameSpaceManager::Init()
   rv = AddDisabledNameSpace(dont_AddRef(uri), id); \
   NS_ENSURE_SUCCESS(rv, false)
 
   mozilla::Preferences::AddStrongObservers(this, kObservedPrefs);
   mMathMLDisabled = mozilla::Preferences::GetBool(kPrefMathMLDisabled);
 
 
   // Need to be ordered according to ID.
+  MOZ_ASSERT(mURIArray.IsEmpty());
+  REGISTER_NAMESPACE(nsGkAtoms::empty, kNameSpaceID_None);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xmlns, kNameSpaceID_XMLNS);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xml, kNameSpaceID_XML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xhtml, kNameSpaceID_XHTML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xlink, kNameSpaceID_XLink);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xslt, kNameSpaceID_XSLT);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_xbl, kNameSpaceID_XBL);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_mathml, kNameSpaceID_MathML);
   REGISTER_NAMESPACE(nsGkAtoms::nsuri_rdf, kNameSpaceID_RDF);
@@ -92,42 +94,43 @@ nsNameSpaceManager::RegisterNameSpace(co
     aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details
 
     return NS_OK;
   }
 
   nsCOMPtr<nsIAtom> atom = NS_Atomize(aURI);
   nsresult rv = NS_OK;
   if (!mURIToIDTable.Get(atom, &aNameSpaceID)) {
-    aNameSpaceID = mURIArray.Length() + 1; // id is index + 1
+    aNameSpaceID = mURIArray.Length();
 
     rv = AddNameSpace(atom.forget(), aNameSpaceID);
     if (NS_FAILED(rv)) {
       aNameSpaceID = kNameSpaceID_Unknown;
     }
   }
 
   NS_POSTCONDITION(aNameSpaceID >= -1, "Bogus namespace ID");
   
   return rv;
 }
 
 nsresult
 nsNameSpaceManager::GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI)
 {
   NS_PRECONDITION(aNameSpaceID >= 0, "Bogus namespace ID");
-  
-  int32_t index = aNameSpaceID - 1; // id is index + 1
-  if (index < 0 || index >= int32_t(mURIArray.Length())) {
+
+  // We have historically treated GetNameSpaceURI calls for kNameSpaceID_None
+  // as erroneous.
+  if (aNameSpaceID <= 0 || aNameSpaceID >= int32_t(mURIArray.Length())) {
     aURI.Truncate();
 
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
-  mURIArray.ElementAt(index)->ToString(aURI);
+  mURIArray.ElementAt(aNameSpaceID)->ToString(aURI);
 
   return NS_OK;
 }
 
 int32_t
 nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI,
                                    bool aInChromeDoc)
 {
@@ -219,39 +222,35 @@ nsNameSpaceManager::HasElementCreator(in
 nsresult nsNameSpaceManager::AddNameSpace(already_AddRefed<nsIAtom> aURI,
                                           const int32_t aNameSpaceID)
 {
   nsCOMPtr<nsIAtom> uri = aURI;
   if (aNameSpaceID < 0) {
     // We've wrapped...  Can't do anything else here; just bail.
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  
-  NS_ASSERTION(aNameSpaceID - 1 == (int32_t) mURIArray.Length(),
-               "BAD! AddNameSpace not called in right order!");
 
+  MOZ_ASSERT(aNameSpaceID == (int32_t) mURIArray.Length());
   mURIArray.AppendElement(uri.forget());
   mURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
 
   return NS_OK;
 }
 
 nsresult
 nsNameSpaceManager::AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI,
                                          const int32_t aNameSpaceID)
 {
   nsCOMPtr<nsIAtom> uri = aURI;
   if (aNameSpaceID < 0) {
     // We've wrapped...  Can't do anything else here; just bail.
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  NS_ASSERTION(aNameSpaceID - 1 == (int32_t) mURIArray.Length(),
-               "BAD! AddDisabledNameSpace not called in right order!");
-
+  MOZ_ASSERT(aNameSpaceID == (int32_t) mURIArray.Length());
   mURIArray.AppendElement(uri.forget());
   mDisabledURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
 
   return NS_OK;
 }
 
 // nsISupports
 NS_IMPL_ISUPPORTS(nsNameSpaceManager,
--- a/dom/base/nsNameSpaceManager.h
+++ b/dom/base/nsNameSpaceManager.h
@@ -37,19 +37,29 @@ class nsNameSpaceManager final : public 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   virtual nsresult RegisterNameSpace(const nsAString& aURI,
                                      int32_t& aNameSpaceID);
 
   virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
 
+  // Returns the atom for the namespace URI associated with the given ID. The
+  // ID must be within range and not be kNameSpaceID_None (i.e. zero);
   nsIAtom* NameSpaceURIAtom(int32_t aNameSpaceID) {
-    MOZ_ASSERT(aNameSpaceID > 0 && (int64_t) aNameSpaceID <= (int64_t) mURIArray.Length());
-    return mURIArray.ElementAt(aNameSpaceID - 1); // id is index + 1
+    MOZ_ASSERT(aNameSpaceID > 0);
+    return NameSpaceURIAtomForServo(aNameSpaceID);
+  }
+
+  // NB: This function should only be called by Servo code (and the above
+  // accessor), which uses the empty atom to represent kNameSpaceID_None.
+  nsIAtom* NameSpaceURIAtomForServo(int32_t aNameSpaceID) {
+    MOZ_ASSERT(aNameSpaceID >= 0);
+    MOZ_ASSERT((int64_t) aNameSpaceID < (int64_t) mURIArray.Length());
+    return mURIArray.ElementAt(aNameSpaceID);
   }
 
   int32_t GetNameSpaceID(const nsAString& aURI,
                          bool aInChromeDoc);
   int32_t GetNameSpaceID(nsIAtom* aURI,
                          bool aInChromeDoc);
 
   bool HasElementCreator(int32_t aNameSpaceID);
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -150,17 +150,17 @@ Gecko_LocalName(RawGeckoElement* aElemen
 {
   return aElement->NodeInfo()->NameAtom();
 }
 
 nsIAtom*
 Gecko_Namespace(RawGeckoElement* aElement)
 {
   int32_t id = aElement->NodeInfo()->NamespaceID();
-  return nsContentUtils::NameSpaceManager()->NameSpaceURIAtom(id);
+  return nsContentUtils::NameSpaceManager()->NameSpaceURIAtomForServo(id);
 }
 
 nsIAtom*
 Gecko_GetElementId(RawGeckoElement* aElement)
 {
   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::id);
   return attr ? attr->GetAtomValue() : nullptr;
 }