Bug 865537. Part 1: Add nsRange::SetEnableGravitationOnElementRemoval to suppress 'gravitation' behavior on node removal. r=smaug
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 07 Jun 2013 16:26:28 +1200
changeset 145840 0d91e2d9da8ddb6334046e48abb44b2c386a97dc
parent 145839 976829350bd603154dfc5b0ef88dee0177e738c3
child 145841 0285f4360664dd705c97c46978c9bb364268e590
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs865537
milestone24.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 865537. Part 1: Add nsRange::SetEnableGravitationOnElementRemoval to suppress 'gravitation' behavior on node removal. r=smaug
content/base/src/nsRange.cpp
content/base/src/nsRange.h
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -657,16 +657,21 @@ nsRange::ContentRemoved(nsIDocument* aDo
     if (aIndexInContainer < mEndOffset) {
       --mEndOffset;
     }
   }
   else if (nsContentUtils::ContentIsDescendantOf(mEndParent, aChild)) {
     gravitateEnd = true;
   }
 
+  if (!mEnableGravitationOnElementRemoval) {
+    // Do not gravitate.
+    return;
+  }
+
   if (gravitateStart || gravitateEnd) {
     DoSetRange(gravitateStart ? container : mStartParent.get(),
                gravitateStart ? aIndexInContainer : mStartOffset,
                gravitateEnd ? container : mEndParent.get(),
                gravitateEnd ? aIndexInContainer : mEndOffset,
                mRoot);
   }
   if (container->IsSelectionDescendant() &&
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -43,16 +43,17 @@ public:
     , mStartOffset(0)
     , mEndOffset(0)
     , mIsPositioned(false)
     , mIsDetached(false)
     , mMaySpanAnonymousSubtrees(false)
     , mInSelection(false)
     , mStartOffsetWasIncremented(false)
     , mEndOffsetWasIncremented(false)
+    , mEnableGravitationOnElementRemoval(true)
 #ifdef DEBUG
     , mAssertNextInsertOrAppendIndex(-1)
     , mAssertNextInsertOrAppendNode(nullptr)
 #endif
   {
     SetIsDOMBinding();
     MOZ_ASSERT(aNode, "range isn't in a document!");
     mOwner = aNode->OwnerDoc();
@@ -67,16 +68,30 @@ public:
                               nsIDOMRange** aRange);
   static nsresult CreateRange(nsINode* aStartParent, int32_t aStartOffset,
                               nsINode* aEndParent, int32_t aEndOffset,
                               nsRange** aRange);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
 
+  /**
+   * The DOM Range spec requires that when a node is removed from its parent,
+   * and the node's subtree contains the start or end point of a range, that
+   * start or end point is moved up to where the node was removed from its
+   * parent.
+   * For some internal uses of Ranges it's useful to disable that behavior,
+   * so that a range of children within a single parent is preserved even if
+   * that parent is removed from the document tree.
+   */
+  void SetEnableGravitationOnElementRemoval(bool aEnable)
+  {
+    mEnableGravitationOnElementRemoval = aEnable;
+  }
+
   // nsIDOMRange interface
   NS_DECL_NSIDOMRANGE
   
   nsINode* GetRoot() const
   {
     return mRoot;
   }
 
@@ -294,16 +309,17 @@ protected:
   int32_t mEndOffset;
 
   bool mIsPositioned;
   bool mIsDetached;
   bool mMaySpanAnonymousSubtrees;
   bool mInSelection;
   bool mStartOffsetWasIncremented;
   bool mEndOffsetWasIncremented;
+  bool mEnableGravitationOnElementRemoval;
 #ifdef DEBUG
   int32_t  mAssertNextInsertOrAppendIndex;
   nsINode* mAssertNextInsertOrAppendNode;
 #endif
 };
 
 inline nsISupports*
 ToCanonicalSupports(nsRange* aRange)