Bug 976302 - MutationRecord should use mozilla::dom::DOMString, r=bz
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 26 Feb 2014 02:45:08 +0200
changeset 170943 655aaacbacba9f8da6d4ef8f065529cc53d55fcd
parent 170942 8df08e8c41076621e1d21e00ea86b660cc678377
child 170944 a4c51a14aaf2a1bce896cc833fdcdf51fe812dcb
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbz
bugs976302
milestone30.0a1
Bug 976302 - MutationRecord should use mozilla::dom::DOMString, r=bz
content/base/src/nsDOMMutationObserver.cpp
content/base/src/nsDOMMutationObserver.h
content/base/src/nsGkAtomList.h
dom/bindings/DOMString.h
--- a/content/base/src/nsDOMMutationObserver.cpp
+++ b/content/base/src/nsDOMMutationObserver.cpp
@@ -108,26 +108,25 @@ nsMutationReceiver::AttributeWillChange(
 {
   if (nsAutoMutationBatch::IsBatching() ||
       !ObservesAttr(aElement, aNameSpaceID, aAttribute) ||
       aElement->ChromeOnlyAccess()) {
     return;
   }
 
   nsDOMMutationRecord* m =
-    Observer()->CurrentRecord(NS_LITERAL_STRING("attributes"));
+    Observer()->CurrentRecord(nsGkAtoms::attributes);
 
   NS_ASSERTION(!m->mTarget || m->mTarget == aElement,
                "Wrong target!");
-  NS_ASSERTION(m->mAttrName.IsVoid() ||
-               m->mAttrName.Equals(nsDependentAtomString(aAttribute)),
+  NS_ASSERTION(!m->mAttrName || m->mAttrName == aAttribute,
                "Wrong attribute!");
   if (!m->mTarget) {
     m->mTarget = aElement;
-    m->mAttrName = nsAtomString(aAttribute);
+    m->mAttrName = aAttribute;
     if (aNameSpaceID == kNameSpaceID_None) {
       m->mAttrNamespace.SetIsVoid(true);
     } else {
       nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID,
                                                           m->mAttrNamespace);
     }
   }
 
@@ -145,17 +144,17 @@ nsMutationReceiver::CharacterDataWillCha
 {
   if (nsAutoMutationBatch::IsBatching() ||
       !CharacterData() || !(Subtree() || aContent == Target()) ||
       aContent->ChromeOnlyAccess()) {
     return;
   }
   
   nsDOMMutationRecord* m =
-    Observer()->CurrentRecord(NS_LITERAL_STRING("characterData"));
+    Observer()->CurrentRecord(nsGkAtoms::characterData);
  
   NS_ASSERTION(!m->mTarget || m->mTarget == aContent,
                "Wrong target!");
 
   if (!m->mTarget) {
     m->mTarget = aContent;
   }
   if (CharacterDataOldValue() && m->mPrevValue.IsVoid()) { 
@@ -178,17 +177,17 @@ nsMutationReceiver::ContentAppended(nsID
   if (nsAutoMutationBatch::IsBatching()) {
     if (parent == nsAutoMutationBatch::GetBatchTarget()) {
       nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList);
     }
     return;
   }
 
   nsDOMMutationRecord* m =
-    Observer()->CurrentRecord(NS_LITERAL_STRING("childList"));
+    Observer()->CurrentRecord(nsGkAtoms::childList);
   NS_ASSERTION(!m->mTarget || m->mTarget == parent,
                "Wrong target!");
   if (m->mTarget) {
     // Already handled case.
     return;
   }
   m->mTarget = parent;
   m->mAddedNodes = new nsSimpleContentList(parent);
@@ -216,17 +215,17 @@ nsMutationReceiver::ContentInserted(nsID
   if (nsAutoMutationBatch::IsBatching()) {
     if (parent == nsAutoMutationBatch::GetBatchTarget()) {
       nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList);
     }
     return;
   }
 
   nsDOMMutationRecord* m =
-    Observer()->CurrentRecord(NS_LITERAL_STRING("childList"));
+    Observer()->CurrentRecord(nsGkAtoms::childList);
   if (m->mTarget) {
     // Already handled case.
     return;  
   }
   m->mTarget = parent;
   m->mAddedNodes = new nsSimpleContentList(parent);
   m->mAddedNodes->AppendElement(aChild);
   m->mPreviousSibling = aChild->GetPreviousSibling();
@@ -288,17 +287,17 @@ nsMutationReceiver::ContentRemoved(nsIDo
         // subtree are kept in the same observation set.
         transientReceivers->AppendObject(new nsMutationReceiver(aChild, orig));
       }
     }
   }
 
   if (ChildList() && (Subtree() || parent == Target())) {
     nsDOMMutationRecord* m =
-      Observer()->CurrentRecord(NS_LITERAL_STRING("childList"));
+      Observer()->CurrentRecord(nsGkAtoms::childList);
     if (m->mTarget) {
       // Already handled case.
       return;
     }
     m->mTarget = parent;
     m->mRemovedNodes = new nsSimpleContentList(parent);
     m->mRemovedNodes->AppendElement(aChild);
     m->mPreviousSibling = aPreviousSibling;
@@ -675,33 +674,33 @@ nsDOMMutationObserver::HandleMutationsIn
     }
     delete suppressedObservers;
     suppressedObservers = nullptr;
   }
   sCurrentObserver = nullptr;
 }
 
 nsDOMMutationRecord*
-nsDOMMutationObserver::CurrentRecord(const nsAString& aType)
+nsDOMMutationObserver::CurrentRecord(nsIAtom* aType)
 {
   NS_ASSERTION(sMutationLevel > 0, "Unexpected mutation level!");
 
   while (mCurrentMutations.Length() < sMutationLevel) {
     mCurrentMutations.AppendElement(static_cast<nsDOMMutationRecord*>(nullptr));
   }
 
   uint32_t last = sMutationLevel - 1;
   if (!mCurrentMutations[last]) {
     nsRefPtr<nsDOMMutationRecord> r = new nsDOMMutationRecord(aType, GetParentObject());
     mCurrentMutations[last] = r;
     AppendMutationRecord(r.forget());
     ScheduleForRun();
   }
 
-  NS_ASSERTION(mCurrentMutations[last]->mType.Equals(aType),
+  NS_ASSERTION(mCurrentMutations[last]->mType == aType,
                "Unexpected MutationRecord type!");
 
   return mCurrentMutations[last];
 }
 
 nsDOMMutationObserver::~nsDOMMutationObserver()
 {
   for (int32_t i = 0; i < mReceivers.Count(); ++i) {
@@ -827,17 +826,17 @@ nsAutoMutationBatch::Done()
     }
     if (wantsChildList && (mRemovedNodes.Length() || mAddedNodes.Length())) {
       nsRefPtr<nsSimpleContentList> addedList =
         new nsSimpleContentList(mBatchTarget);
       for (uint32_t i = 0; i < mAddedNodes.Length(); ++i) {
         addedList->AppendElement(mAddedNodes[i]);
       }
       nsRefPtr<nsDOMMutationRecord> m =
-        new nsDOMMutationRecord(NS_LITERAL_STRING("childList"),
+        new nsDOMMutationRecord(nsGkAtoms::childList,
                                 ob->GetParentObject());
       m->mTarget = mBatchTarget;
       m->mRemovedNodes = removedList;
       m->mAddedNodes = addedList;
       m->mPreviousSibling = mPrevSibling;
       m->mNextSibling = mNextSibling;
       ob->AppendMutationRecord(m.forget());
     }
--- a/content/base/src/nsDOMMutationObserver.h
+++ b/content/base/src/nsDOMMutationObserver.h
@@ -27,20 +27,19 @@
 
 class nsDOMMutationObserver;
 using mozilla::dom::MutationObservingInfo;
 
 class nsDOMMutationRecord : public nsISupports,
                             public nsWrapperCache
 {
 public:
-  nsDOMMutationRecord(const nsAString& aType, nsISupports* aOwner)
+  nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner)
   : mType(aType), mOwner(aOwner)
   {
-    mAttrName.SetIsVoid(PR_TRUE);
     mAttrNamespace.SetIsVoid(PR_TRUE);
     mPrevValue.SetIsVoid(PR_TRUE);
     SetIsDOMBinding();
   }
   virtual ~nsDOMMutationRecord() {}
 
   nsISupports* GetParentObject() const
   {
@@ -51,19 +50,19 @@ public:
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::MutationRecordBinding::Wrap(aCx, aScope, this);
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMMutationRecord)
 
-  void GetType(nsString& aRetVal) const
+  void GetType(mozilla::dom::DOMString& aRetVal) const
   {
-    aRetVal = mType;
+    aRetVal.SetOwnedAtom(mType, mozilla::dom::DOMString::eNullNotExpected);
   }
 
   nsINode* GetTarget() const
   {
     return mTarget;
   }
 
   nsINodeList* AddedNodes();
@@ -75,34 +74,34 @@ public:
     return mPreviousSibling;
   }
 
   nsINode* GetNextSibling() const
   {
     return mNextSibling;
   }
 
-  void GetAttributeName(nsString& aRetVal) const
+  void GetAttributeName(mozilla::dom::DOMString& aRetVal) const
   {
-    aRetVal = mAttrName;
+    aRetVal.SetOwnedAtom(mAttrName, mozilla::dom::DOMString::eTreatNullAsNull);
   }
 
-  void GetAttributeNamespace(nsString& aRetVal) const
+  void GetAttributeNamespace(mozilla::dom::DOMString& aRetVal) const
   {
-    aRetVal = mAttrNamespace;
+    aRetVal.SetOwnedString(mAttrNamespace);
   }
 
-  void GetOldValue(nsString& aRetVal) const
+  void GetOldValue(mozilla::dom::DOMString& aRetVal) const
   {
-    aRetVal = mPrevValue;
+    aRetVal.SetOwnedString(mPrevValue);
   }
 
   nsCOMPtr<nsINode>             mTarget;
-  nsString                      mType;
-  nsString                      mAttrName;
+  nsCOMPtr<nsIAtom>             mType;
+  nsCOMPtr<nsIAtom>             mAttrName;
   nsString                      mAttrNamespace;
   nsString                      mPrevValue;
   nsRefPtr<nsSimpleContentList> mAddedNodes;
   nsRefPtr<nsSimpleContentList> mRemovedNodes;
   nsCOMPtr<nsINode>             mPreviousSibling;
   nsCOMPtr<nsINode>             mNextSibling;
 
   nsRefPtr<nsDOMMutationRecord> mNext;
@@ -428,17 +427,17 @@ protected:
 
   already_AddRefed<nsIVariant> TakeRecords();
 
   void GetAllSubtreeObserversFor(nsINode* aNode,
                                  nsTArray<nsMutationReceiver*>& aObservers);
   void ScheduleForRun();
   void RescheduleForRun();
 
-  nsDOMMutationRecord* CurrentRecord(const nsAString& aType);
+  nsDOMMutationRecord* CurrentRecord(nsIAtom* aType);
   bool HasCurrentRecord(const nsAString& aType);
 
   bool Suppressed()
   {
     if (mOwner) {
       nsCOMPtr<nsIDocument> d = mOwner->GetExtantDoc();
       return d && d->IsInSyncOperation();
     }
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -101,16 +101,17 @@ GK_ATOM(area, "area")
 GK_ATOM(arrow, "arrow")
 GK_ATOM(article, "article")
 GK_ATOM(ascending, "ascending")
 GK_ATOM(aside, "aside")
 GK_ATOM(aspectRatio, "aspect-ratio")
 GK_ATOM(assign, "assign")
 GK_ATOM(async, "async")
 GK_ATOM(attribute, "attribute")
+GK_ATOM(attributes, "attributes")
 GK_ATOM(attributeSet, "attribute-set")
 GK_ATOM(aural, "aural")
 GK_ATOM(_auto, "auto")
 GK_ATOM(autocheck, "autocheck")
 GK_ATOM(autocomplete, "autocomplete")
 GK_ATOM(autofocus, "autofocus")
 GK_ATOM(autoplay, "autoplay")
 GK_ATOM(autorepeatbutton, "autorepeatbutton")
@@ -167,23 +168,25 @@ GK_ATOM(cdataSectionElements, "cdata-sec
 GK_ATOM(ceiling, "ceiling")
 GK_ATOM(cell, "cell")
 GK_ATOM(cellpadding, "cellpadding")
 GK_ATOM(cellspacing, "cellspacing")
 GK_ATOM(center, "center")
 GK_ATOM(ch, "ch")
 GK_ATOM(change, "change")
 GK_ATOM(_char, "char")
+GK_ATOM(characterData, "characterData")
 GK_ATOM(charcode, "charcode")
 GK_ATOM(charoff, "charoff")
 GK_ATOM(charset, "charset")
 GK_ATOM(checkbox, "checkbox")
 GK_ATOM(checked, "checked")
 GK_ATOM(child, "child")
 GK_ATOM(children, "children")
+GK_ATOM(childList, "childList")
 GK_ATOM(choose, "choose")
 GK_ATOM(chromemargin, "chromemargin")
 GK_ATOM(chromeOnlyContent, "chromeOnlyContent")
 GK_ATOM(exposeToUntrustedContent, "exposeToUntrustedContent")
 GK_ATOM(circ, "circ")
 GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
 GK_ATOM(_class, "class")
--- a/dom/bindings/DOMString.h
+++ b/dom/bindings/DOMString.h
@@ -7,32 +7,34 @@
 #define mozilla_dom_DOMString_h
 
 #include "nsStringGlue.h"
 #include "nsStringBuffer.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "nsDOMString.h"
+#include "nsIAtom.h"
 
 namespace mozilla {
 namespace dom {
 
 /**
  * A class for representing string return values.  This can be either passed to
  * callees that have an nsString or nsAString out param or passed to a callee
  * that actually knows about this class and can work with it.  Such a callee may
- * call SetStringBuffer on this object, but only if it plans to keep holding a
- * strong ref to the stringbuffer!
+ * call SetStringBuffer or SetOwnedString or SetOwnedAtom on this object, but
+ * only if it plans to keep holding a strong ref to the internal stringbuffer!
  *
  * The proper way to store a value in this class is to either to do nothing
  * (which leaves this as an empty string), to call SetStringBuffer with a
- * non-null stringbuffer, to call SetNull(), or to call AsAString() and set the
- * value in the resulting nsString.  These options are mutually exclusive!
- * Don't do more than one of them.
+ * non-null stringbuffer, to call SetOwnedString, to call SetOwnedAtom, to call
+ * SetNull(), or to call AsAString() and set the value in the resulting
+ * nsString.  These options are mutually exclusive! Don't do more than one of
+ * them.
  *
  * The proper way to extract a value is to check IsNull().  If not null, then
  * check HasStringBuffer().  If that's true, check for a zero length, and if the
  * length is nonzero call StringBuffer().  If the length is zero this is the
  * empty string.  If HasStringBuffer() returns false, call AsAString() and get
  * the value from that.
  */
 class MOZ_STACK_CLASS DOMString {
@@ -98,16 +100,51 @@ public:
     MOZ_ASSERT(mString.empty(), "We already have a string?");
     MOZ_ASSERT(!mIsNull, "We're already set as null");
     MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
     MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
     mStringBuffer = aStringBuffer;
     mLength = aLength;
   }
 
+  void SetOwnedString(const nsAString& aString)
+  {
+    MOZ_ASSERT(mString.empty(), "We already have a string?");
+    MOZ_ASSERT(!mIsNull, "We're already set as null");
+    MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
+    nsStringBuffer* buf = nsStringBuffer::FromString(aString);
+    if (buf) {
+      SetStringBuffer(buf, aString.Length());
+    } else if (aString.IsVoid()) {
+      SetNull();
+    } else if (!aString.IsEmpty()) {
+      AsAString() = aString;
+    }
+  }
+
+  enum NullHandling
+  {
+    eTreatNullAsNull,
+    eTreatNullAsEmpty,
+    eNullNotExpected
+  };
+
+  void SetOwnedAtom(nsIAtom* aAtom, NullHandling aNullHandling)
+  {
+    MOZ_ASSERT(mString.empty(), "We already have a string?");
+    MOZ_ASSERT(!mIsNull, "We're already set as null");
+    MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
+    MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected);
+    if (aNullHandling == eNullNotExpected || aAtom) {
+      SetStringBuffer(aAtom->GetStringBuffer(), aAtom->GetLength());
+    } else if (aNullHandling == eTreatNullAsNull) {
+      SetNull();
+    }
+  }
+
   void SetNull()
   {
     MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
     MOZ_ASSERT(mString.empty(), "Should have no string if null");
     mIsNull = true;
   }
 
   bool IsNull() const