Bug 1074738 - GetCurrentDoc fixes in content/base, r=wchen
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 02 Oct 2014 21:45:44 +0300
changeset 231977 929d78de0f8a7ea4d0e0e2d9e91e363ec2aadd4b
parent 231976 086b51f4ba0b61befd338d38aae0ad5de0504848
child 231978 a9bf2deaec5d9e5db349ad0984bde2ae35799d53
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswchen
bugs1074738
milestone35.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 1074738 - GetCurrentDoc fixes in content/base, r=wchen
content/base/public/Element.h
content/base/src/Element.cpp
content/base/src/FragmentOrElement.cpp
content/base/src/Link.cpp
content/base/src/nsCCUncollectableMarker.cpp
content/base/src/nsContentList.cpp
content/base/src/nsContentSink.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocumentEncoder.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsINode.cpp
content/base/src/nsImageLoadingContent.cpp
content/base/src/nsMappedAttributeElement.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsRange.cpp
content/base/src/nsReferencedElement.cpp
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -1270,16 +1270,31 @@ private:
 
   nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
                                      bool aFlushLayout = true);
 
   // Data members
   EventStates mState;
 };
 
+class RemoveFromBindingManagerRunnable : public nsRunnable
+{
+public:
+  RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
+                                   nsIContent* aContent,
+                                   nsIDocument* aDoc);
+
+  NS_IMETHOD Run();
+private:
+  virtual ~RemoveFromBindingManagerRunnable();
+  nsRefPtr<nsBindingManager> mManager;
+  nsRefPtr<nsIContent> mContent;
+  nsCOMPtr<nsIDocument> mDoc;
+};
+
 class DestinationInsertionPointList : public nsINodeList
 {
 public:
   explicit DestinationInsertionPointList(Element* aElement);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DestinationInsertionPointList)
 
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -425,17 +425,17 @@ Element::WrapObject(JSContext *aCx)
     }
   }
 
   nsIDocument* doc;
   if (HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     doc = OwnerDoc();
   }
   else {
-    doc = GetCurrentDoc();
+    doc = GetComposedDoc();
   }
 
   if (!doc) {
     // There's no baseclass that cares about this call so we just
     // return here.
     return obj;
   }
 
@@ -588,17 +588,17 @@ void
 Element::ScrollIntoView()
 {
   ScrollIntoView(true, ScrollOptions());
 }
 
 void
 Element::ScrollIntoView(bool aTop, const ScrollOptions &aOptions)
 {
-  nsIDocument *document = GetCurrentDoc();
+  nsIDocument *document = GetComposedDoc();
   if (!document) {
     return;
   }
 
   // Get the presentation shell
   nsCOMPtr<nsIPresShell> presShell = document->GetShell();
   if (!presShell) {
     return;
@@ -762,17 +762,17 @@ Element::GetClientRects()
 void
 Element::AddToIdTable(nsIAtom* aId)
 {
   NS_ASSERTION(HasID(), "Node doesn't have an ID?");
   if (IsInShadowTree()) {
     ShadowRoot* containingShadow = GetContainingShadow();
     containingShadow->AddToIdTable(this, aId);
   } else {
-    nsIDocument* doc = GetCurrentDoc();
+    nsIDocument* doc = GetUncomposedDoc();
     if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) {
       doc->AddToIdTable(this, aId);
     }
   }
 }
 
 void
 Element::RemoveFromIdTable()
@@ -785,17 +785,17 @@ Element::RemoveFromIdTable()
   if (IsInShadowTree()) {
     ShadowRoot* containingShadow = GetContainingShadow();
     // Check for containingShadow because it may have
     // been deleted during unlinking.
     if (containingShadow) {
       containingShadow->RemoveFromIdTable(this, id);
     }
   } else {
-    nsIDocument* doc = GetCurrentDoc();
+    nsIDocument* doc = GetUncomposedDoc();
     if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) {
       doc->RemoveFromIdTable(this, id);
     }
   }
 }
 
 already_AddRefed<ShadowRoot>
 Element::CreateShadowRoot(ErrorResult& aError)
@@ -1192,19 +1192,19 @@ Element::GetElementsByClassName(const ns
 nsresult
 Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                     nsIContent* aBindingParent,
                     bool aCompileEventHandlers)
 {
   NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
   NS_PRECONDITION((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()),
                   "Must have the same owner document");
-  NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
+  NS_PRECONDITION(!aParent || aDocument == aParent->GetUncomposedDoc(),
                   "aDocument must be current doc of aParent");
-  NS_PRECONDITION(!GetCurrentDoc(), "Already have a document.  Unbind first!");
+  NS_PRECONDITION(!GetUncomposedDoc(), "Already have a document.  Unbind first!");
   // Note that as we recurse into the kids, they'll have a non-null parent.  So
   // only assert if our parent is _changing_ while we have a parent.
   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
                   "Already have a parent.  Unbind first!");
   NS_PRECONDITION(!GetBindingParent() ||
                   aBindingParent == GetBindingParent() ||
                   (!aBindingParent && aParent &&
                    aParent->GetBindingParent() == GetBindingParent()),
@@ -1401,66 +1401,63 @@ Element::BindToTree(nsIDocument* aDocume
                              aCompileEventHandlers);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // XXXbz script execution during binding can trigger some of these
   // postcondition asserts....  But we do want that, since things will
   // generally be quite broken when that happens.
-  NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
+  NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
                    "Bound to wrong binding parent");
 
   return NS_OK;
 }
 
-class RemoveFromBindingManagerRunnable : public nsRunnable {
-public:
-  RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
-                                   Element* aElement,
-                                   nsIDocument* aDoc):
-    mManager(aManager), mElement(aElement), mDoc(aDoc)
-  {}
-
-  NS_IMETHOD Run()
-  {
-    // It may be the case that the element was removed from the
-    // DOM, causing this runnable to be created, then inserted back
-    // into the document before the this runnable had a chance to
-    // tear down the binding. Only tear down the binding if the element
-    // is still no longer in the DOM. nsXBLService::LoadBinding tears
-    // down the old binding if the element is inserted back into the
-    // DOM and loads a different binding.
-    if (!mElement->IsInDoc()) {
-      mManager->RemovedFromDocumentInternal(mElement, mDoc);
-    }
-
-    return NS_OK;
+RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
+                                                                   nsIContent* aContent,
+                                                                   nsIDocument* aDoc):
+  mManager(aManager), mContent(aContent), mDoc(aDoc)
+{}
+
+RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
+
+NS_IMETHODIMP
+RemoveFromBindingManagerRunnable::Run()
+{
+  // It may be the case that the element was removed from the
+  // DOM, causing this runnable to be created, then inserted back
+  // into the document before the this runnable had a chance to
+  // tear down the binding. Only tear down the binding if the element
+  // is still no longer in the DOM. nsXBLService::LoadBinding tears
+  // down the old binding if the element is inserted back into the
+  // DOM and loads a different binding.
+  if (!mContent->IsInComposedDoc()) {
+    mManager->RemovedFromDocumentInternal(mContent, mDoc);
   }
 
-private:
-  nsRefPtr<nsBindingManager> mManager;
-  nsRefPtr<Element> mElement;
-  nsCOMPtr<nsIDocument> mDoc;
-};
+  return NS_OK;
+}
+
 
 void
 Element::UnbindFromTree(bool aDeep, bool aNullParent)
 {
-  NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
+  NS_PRECONDITION(aDeep || (!GetUncomposedDoc() && !GetBindingParent()),
                   "Shallow unbind won't clear document and binding parent on "
                   "kids!");
 
   RemoveFromIdTable();
 
   // Make sure to unbind this node before doing the kids
-  nsIDocument *document =
-    HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
+  nsIDocument* document =
+    HasFlag(NODE_FORCE_XBL_BINDINGS) || IsInShadowTree() ?
+      OwnerDoc() : GetUncomposedDoc();
 
   if (aNullParent) {
     if (IsFullScreenAncestor()) {
       // The element being removed is an ancestor of the full-screen element,
       // exit full-screen state.
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       NS_LITERAL_CSTRING("DOM"), OwnerDoc(),
                                       nsContentUtils::eDOM_PROPERTIES,
@@ -1597,17 +1594,17 @@ nsresult
 Element::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
                                            bool aNotify)
 {
   Element::nsDOMSlots *slots = DOMSlots();
 
   slots->mSMILOverrideStyleRule = aStyleRule;
 
   if (aNotify) {
-    nsIDocument* doc = GetCurrentDoc();
+    nsIDocument* doc = GetComposedDoc();
     // Only need to request a restyle if we're in a document.  (We might not
     // be in a document, if we're clearing animation effects on a target node
     // that's been detached since the previous animation sample.)
     if (doc) {
       nsCOMPtr<nsIPresShell> shell = doc->GetShell();
       if (shell) {
         shell->RestyleForAnimation(this,
           eRestyle_StyleAttribute | eRestyle_ChangeAnimationPhase);
@@ -2015,17 +2012,17 @@ Element::SetAttrAndNotify(int32_t aNames
                           nsAttrValue& aParsedValue,
                           uint8_t aModType,
                           bool aFireMutation,
                           bool aNotify,
                           bool aCallAfterSetAttr)
 {
   nsresult rv;
 
-  nsIDocument* document = GetCurrentDoc();
+  nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
 
   nsMutationGuard::DidMutate();
 
   // Copy aParsedValue for later use since it will be lost when we call
   // SetAndTakeMappedAttr below
   nsAttrValue aValueForAfterSetAttr;
   if (aCallAfterSetAttr) {
@@ -2228,17 +2225,17 @@ Element::UnsetAttr(int32_t aNameSpaceID,
   int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
   if (index < 0) {
     return NS_OK;
   }
 
   nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsIDocument *document = GetCurrentDoc();
+  nsIDocument *document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
 
   if (aNotify) {
     nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
                                      nsIDOMMutationEvent::REMOVAL);
   }
 
   bool hasMutationListeners = aNotify &&
@@ -2617,17 +2614,17 @@ Element::PostHandleEventForLinks(EventCh
 
   switch (aVisitor.mEvent->message) {
   case NS_MOUSE_BUTTON_DOWN:
     {
       if (aVisitor.mEvent->AsMouseEvent()->button ==
             WidgetMouseEvent::eLeftButton) {
         // don't make the link grab the focus if there is no link handler
         nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
-        nsIDocument *document = GetCurrentDoc();
+        nsIDocument *document = GetComposedDoc();
         if (handler && document) {
           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
           if (fm) {
             aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
             nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
             fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
                                nsIFocusManager::FLAG_NOSCROLL);
           }
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -198,17 +198,17 @@ nsIContent::GetDesiredIMEState()
   // textarea) must override this method, so, we don't need to worry about
   // that here.
   nsIContent *editableAncestor = GetEditingHost();
 
   // This is in another editable content, use the result of it.
   if (editableAncestor && editableAncestor != this) {
     return editableAncestor->GetDesiredIMEState();
   }
-  nsIDocument* doc = GetCurrentDoc();
+  nsIDocument* doc = GetComposedDoc();
   if (!doc) {
     return IMEState(IMEState::DISABLED);
   }
   nsIPresShell* ps = doc->GetShell();
   if (!ps) {
     return IMEState(IMEState::DISABLED);
   }
   nsPresContext* pc = ps->GetPresContext();
@@ -233,20 +233,20 @@ nsIContent::HasIndependentSelection()
 }
 
 dom::Element*
 nsIContent::GetEditingHost()
 {
   // If this isn't editable, return nullptr.
   NS_ENSURE_TRUE(IsEditableInternal(), nullptr);
 
-  nsIDocument* doc = GetCurrentDoc();
+  nsIDocument* doc = GetComposedDoc();
   NS_ENSURE_TRUE(doc, nullptr);
   // If this is in designMode, we should return <body>
-  if (doc->HasFlag(NODE_IS_EDITABLE)) {
+  if (doc->HasFlag(NODE_IS_EDITABLE) && !IsInShadowTree()) {
     return doc->GetBodyElement();
   }
 
   nsIContent* content = this;
   for (dom::Element* parent = GetParentElement();
        parent && parent->HasFlag(NODE_IS_EDITABLE);
        parent = content->GetParentElement()) {
     content = parent;
@@ -1496,17 +1496,19 @@ FragmentOrElement::RemoveBlackMarkedNode
 bool
 FragmentOrElement::CanSkipInCC(nsINode* aNode)
 {
   // Don't try to optimize anything during shutdown.
   if (nsCCUncollectableMarker::sGeneration == 0) {
     return false;
   }
 
-  nsIDocument* currentDoc = aNode->GetCurrentDoc();
+  //XXXsmaug Need to figure out in which cases Shadow DOM can be optimized out
+  //         from the CC graph.
+  nsIDocument* currentDoc = aNode->GetUncomposedDoc();
   if (currentDoc &&
       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {
     return !NeedsScriptTraverse(aNode);
   }
 
   // Bail out early if aNode is somewhere in anonymous content,
   // or otherwise unusual.
   if (aNode->UnoptimizableCCNode()) {
@@ -1673,17 +1675,17 @@ bool
 FragmentOrElement::CanSkip(nsINode* aNode, bool aRemovingAllowed)
 {
   // Don't try to optimize anything during shutdown.
   if (nsCCUncollectableMarker::sGeneration == 0) {
     return false;
   }
 
   bool unoptimizable = aNode->UnoptimizableCCNode();
-  nsIDocument* currentDoc = aNode->GetCurrentDoc();
+  nsIDocument* currentDoc = aNode->GetUncomposedDoc();
   if (currentDoc &&
       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration()) &&
       (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode) ||
        OwnedByBindingManager(currentDoc, aNode))) {
     MarkNodeChildren(aNode);
     return true;
   }
 
@@ -1802,17 +1804,17 @@ bool
 FragmentOrElement::CanSkipThis(nsINode* aNode)
 {
   if (nsCCUncollectableMarker::sGeneration == 0) {
     return false;
   }
   if (aNode->IsBlack()) {
     return true;
   }
-  nsIDocument* c = aNode->GetCurrentDoc();
+  nsIDocument* c = aNode->GetUncomposedDoc();
   return 
     ((c && nsCCUncollectableMarker::InGeneration(c->GetMarkedCCGeneration())) ||
      aNode->InCCBlackTree()) && !NeedsScriptTraverse(aNode);
 }
 
 void
 FragmentOrElement::InitCCCallbacks()
 {
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -72,34 +72,34 @@ Link::LinkState() const
   // We are a constant method, but we are just lazily doing things and have to
   // track that state.  Cast away that constness!
   Link *self = const_cast<Link *>(this);
 
   Element *element = self->mElement;
 
   // If we have not yet registered for notifications and need to,
   // due to our href changing, register now!
-  if (!mRegistered && mNeedsRegistration && element->IsInDoc()) {
+  if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc()) {
     // Only try and register once.
     self->mNeedsRegistration = false;
 
     nsCOMPtr<nsIURI> hrefURI(GetURI());
 
     // Assume that we are not visited until we are told otherwise.
     self->mLinkState = eLinkState_Unvisited;
 
     // Make sure the href attribute has a valid link (bug 23209).
     // If we have a good href, register with History if available.
     if (mHistory && hrefURI) {
       nsresult rv = mHistory->RegisterVisitedCallback(hrefURI, self);
       if (NS_SUCCEEDED(rv)) {
         self->mRegistered = true;
 
         // And make sure we are in the document's link map.
-        element->GetCurrentDoc()->AddStyleRelevantLink(self);
+        element->GetComposedDoc()->AddStyleRelevantLink(self);
       }
     }
   }
 
   // Otherwise, return our known state.
   if (mLinkState == eLinkState_Visited) {
     return NS_EVENT_STATE_VISITED;
   }
@@ -464,17 +464,17 @@ Link::ResetLinkState(bool aNotify, bool 
   } else {
     defaultState = eLinkState_NotLink;
   }
 
   // If !mNeedsRegstration, then either we've never registered, or we're
   // currently registered; in either case, we should remove ourself
   // from the doc and the history.
   if (!mNeedsRegistration && mLinkState != eLinkState_NotLink) {
-    nsIDocument *doc = mElement->GetCurrentDoc();
+    nsIDocument *doc = mElement->GetComposedDoc();
     if (doc && (mRegistered || mLinkState == eLinkState_Visited)) {
       // Tell the document to forget about this link if we've registered
       // with it before.
       doc->ForgetLink(this);
     }
 
     UnregisterFromHistory();
   }
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -73,17 +73,17 @@ nsCCUncollectableMarker::Init()
   sInited = true;
 
   return NS_OK;
 }
 
 static void
 MarkUserData(void* aNode, nsIAtom* aKey, void* aValue, void* aData)
 {
-  nsIDocument* d = static_cast<nsINode*>(aNode)->GetCurrentDoc();
+  nsIDocument* d = static_cast<nsINode*>(aNode)->GetUncomposedDoc();
   if (d && nsCCUncollectableMarker::InGeneration(d->GetMarkedCCGeneration())) {
     Element::MarkUserData(aNode, aKey, aValue, aData);
   }
 }
 
 static void
 MarkChildMessageManagers(nsIMessageBroadcaster* aMM)
 {
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -426,20 +426,20 @@ nsContentList::nsContentList(nsINode* aR
   }
   else {
     mMatchAll = false;
   }
   mRootNode->AddMutationObserver(this);
 
   // We only need to flush if we're in an non-HTML document, since the
   // HTML5 parser doesn't need flushing.  Further, if we're not in a
-  // document at all right now (in the GetCurrentDoc() sense), we're
+  // document at all right now (in the GetUncomposedDoc() sense), we're
   // not parser-created and don't need to be flushing stuff under us
   // to get our kids right.
-  nsIDocument* doc = mRootNode->GetCurrentDoc();
+  nsIDocument* doc = mRootNode->GetUncomposedDoc();
   mFlushesNeeded = doc && !doc->IsHTML();
 }
 
 nsContentList::nsContentList(nsINode* aRootNode,
                              nsContentListMatchFunc aFunc,
                              nsContentListDestroyFunc aDestroyFunc,
                              void* aData,
                              bool aDeep,
@@ -459,20 +459,20 @@ nsContentList::nsContentList(nsINode* aR
     mDeep(aDeep),
     mFuncMayDependOnAttr(aFuncMayDependOnAttr)
 {
   NS_ASSERTION(mRootNode, "Must have root");
   mRootNode->AddMutationObserver(this);
 
   // We only need to flush if we're in an non-HTML document, since the
   // HTML5 parser doesn't need flushing.  Further, if we're not in a
-  // document at all right now (in the GetCurrentDoc() sense), we're
+  // document at all right now (in the GetUncomposedDoc() sense), we're
   // not parser-created and don't need to be flushing stuff under us
   // to get our kids right.
-  nsIDocument* doc = mRootNode->GetCurrentDoc();
+  nsIDocument* doc = mRootNode->GetUncomposedDoc();
   mFlushesNeeded = doc && !doc->IsHTML();
 }
 
 nsContentList::~nsContentList()
 {
   RemoveFromHashtable();
   if (mRootNode) {
     mRootNode->RemoveMutationObserver(this);
@@ -502,17 +502,17 @@ nsContentList::Length(bool aDoFlush)
   return mElements.Length();
 }
 
 nsIContent *
 nsContentList::Item(uint32_t aIndex, bool aDoFlush)
 {
   if (mRootNode && aDoFlush && mFlushesNeeded) {
     // XXX sXBL/XBL2 issue
-    nsIDocument* doc = mRootNode->GetCurrentDoc();
+    nsIDocument* doc = mRootNode->GetUncomposedDoc();
     if (doc) {
       // Flush pending content changes Bug 4891.
       doc->FlushPendingNotifications(Flush_ContentAndNotify);
     }
   }
 
   if (mState != LIST_UP_TO_DATE)
     PopulateSelf(std::min(aIndex, UINT32_MAX - 1) + 1);
@@ -999,17 +999,17 @@ nsContentList::RemoveFromHashtable()
   }
 }
 
 void
 nsContentList::BringSelfUpToDate(bool aDoFlush)
 {
   if (mRootNode && aDoFlush && mFlushesNeeded) {
     // XXX sXBL/XBL2 issue
-    nsIDocument* doc = mRootNode->GetCurrentDoc();
+    nsIDocument* doc = mRootNode->GetUncomposedDoc();
     if (doc) {
       // Flush pending content changes Bug 4891.
       doc->FlushPendingNotifications(Flush_ContentAndNotify);
     }
   }
 
   if (mState != LIST_UP_TO_DATE)
     PopulateSelf(uint32_t(-1));
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1178,17 +1178,17 @@ nsContentSink::StartLayout(bool aIgnoreP
   // frameset document, disable the scroll bars on the views.
 
   mDocument->SetScrollToRef(mDocument->GetDocumentURI());
 }
 
 void
 nsContentSink::NotifyAppend(nsIContent* aContainer, uint32_t aStartIndex)
 {
-  if (aContainer->GetCurrentDoc() != mDocument) {
+  if (aContainer->GetUncomposedDoc() != mDocument) {
     // aContainer is not actually in our document anymore.... Just bail out of
     // here; notifying on our document for this append would be wrong.
     return;
   }
 
   mInNotification++;
   
   {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2448,27 +2448,28 @@ nsContentUtils::GenerateStateKey(nsICont
   if (aContent->IsInAnonymousSubtree()) {
     return NS_OK;
   }
 
   if (IsAutocompleteOff(aContent)) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(aContent->GetCurrentDoc()));
+  nsCOMPtr<nsIHTMLDocument> htmlDocument =
+    do_QueryInterface(aContent->GetUncomposedDoc());
 
   KeyAppendInt(partID, aKey);  // first append a partID
   bool generatedUniqueKey = false;
 
   if (htmlDocument) {
     // Flush our content model so it'll be up to date
     // If this becomes unnecessary and the following line is removed,
     // please also remove the corresponding flush operation from
     // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
-    aContent->GetCurrentDoc()->FlushPendingNotifications(Flush_Content);
+    aContent->GetUncomposedDoc()->FlushPendingNotifications(Flush_Content);
 
     nsContentList *htmlForms = htmlDocument->GetForms();
     nsContentList *htmlFormControls = htmlDocument->GetFormControls();
 
     NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
 
     // If we have a form control and can calculate form information, use that
     // as the key - it is more reliable than just recording position in the
@@ -2842,17 +2843,17 @@ nsContentUtils::SplitExpatName(const cha
   }
   *aLocalName = NS_NewAtom(Substring(nameStart, nameEnd)).take();
 }
 
 // static
 nsPresContext*
 nsContentUtils::GetContextForContent(const nsIContent* aContent)
 {
-  nsIDocument* doc = aContent->GetCurrentDoc();
+  nsIDocument* doc = aContent->GetComposedDoc();
   if (doc) {
     nsIPresShell *presShell = doc->GetShell();
     if (presShell) {
       return presShell->GetPresContext();
     }
   }
   return nullptr;
 }
@@ -4399,17 +4400,17 @@ nsContentUtils::SetNodeTextContent(nsICo
         }
         nsContentUtils::MaybeFireNodeRemoved(child, aContent, doc);
       }
     }
   }
 
   // Might as well stick a batch around this since we're performing several
   // mutations.
-  mozAutoDocUpdate updateBatch(aContent->GetCurrentDoc(),
+  mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(),
     UPDATE_CONTENT_MODEL, true);
   nsAutoMutationBatch mb;
 
   uint32_t childCount = aContent->GetChildCount();
 
   if (aTryReuse && !aValue.IsEmpty()) {
     uint32_t removeIndex = 0;
 
@@ -6099,17 +6100,19 @@ nsContentUtils::IsFocusedContent(const n
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
 
   return fm && fm->GetFocusedContent() == aContent;
 }
 
 bool
 nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
 {
-  nsIDocument* doc = aContent->GetCurrentDoc();
+  //XXXsmaug Shadow DOM spec issue!
+  //         We may need to change this to GetComposedDoc().
+  nsIDocument* doc = aContent->GetUncomposedDoc();
   if (!doc) {
     return false;
   }
 
   // If the subdocument lives in another process, the frame is
   // tabbable.
   if (EventStateManager::IsRemoteTarget(aContent)) {
     return true;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6051,17 +6051,18 @@ nsDocument::RegisterElement(JSContext* a
       JS::RootedObject wrapper(aCx);
       if ((wrapper = cache->GetWrapper())) {
         if (!JS_SetPrototype(aCx, wrapper, protoObject)) {
           continue;
         }
       }
 
       EnqueueLifecycleCallback(nsIDocument::eCreated, elem, nullptr, definition);
-      if (elem->GetCurrentDoc()) {
+      //XXXsmaug It is unclear if we should use GetComposedDoc() here.
+      if (elem->GetUncomposedDoc()) {
         // Normally callbacks can not be enqueued until the created
         // callback has been invoked, however, the attached callback
         // in element upgrade is an exception so pretend the created
         // callback has been invoked.
         elem->GetCustomElementData()->mCreatedCallbackInvoked = true;
 
         EnqueueLifecycleCallback(nsIDocument::eAttached, elem, nullptr, definition);
       }
@@ -11522,17 +11523,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   NS_IMETHOD Run()
   {
     nsCOMPtr<Element> e = do_QueryReferent(mElement);
     nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
     if (!e || !d || gPendingPointerLockRequest != this ||
-        e->GetCurrentDoc() != d) {
+        e->GetUncomposedDoc() != d) {
       Handled();
       DispatchPointerLockError(d);
       return NS_OK;
     }
 
     // We're about to enter fullscreen mode.
     nsDocument* doc = static_cast<nsDocument*>(d.get());
     if (doc->mAsyncFullscreenPending ||
@@ -11637,17 +11638,17 @@ NS_IMETHODIMP
 nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
 {
   MOZ_ASSERT(aChoices.isUndefined());
 
   nsCOMPtr<Element> e = do_QueryReferent(mElement);
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
   nsDocument* d = static_cast<nsDocument*>(doc.get());
   if (!e || !d || gPendingPointerLockRequest != this ||
-      e->GetCurrentDoc() != d ||
+      e->GetUncomposedDoc() != d ||
       (!mUserInputOrChromeCaller && !d->mIsApprovedForFullscreen)) {
     Handled();
     DispatchPointerLockError(d);
     return NS_OK;
   }
 
   // Mark handled here so that we don't need to call it everywhere below.
   Handled();
@@ -11704,17 +11705,17 @@ nsDocument::Observe(nsISupports *aSubjec
       // Run() method gets called again.
       nsCOMPtr<Element> el =
         do_QueryReferent(gPendingPointerLockRequest->mElement);
       nsCOMPtr<nsIDocument> doc =
         do_QueryReferent(gPendingPointerLockRequest->mDocument);
       bool userInputOrChromeCaller =
         gPendingPointerLockRequest->mUserInputOrChromeCaller;
       gPendingPointerLockRequest->Handled();
-      if (doc == this && el && el->GetCurrentDoc() == doc) {
+      if (doc == this && el && el->GetUncomposedDoc() == doc) {
         nsPointerLockPermissionRequest* clone =
           new nsPointerLockPermissionRequest(el, userInputOrChromeCaller);
         gPendingPointerLockRequest = clone;
         nsCOMPtr<nsIRunnable> r = gPendingPointerLockRequest.get();
         NS_DispatchToMainThread(r);
       }
     }
   } else if (strcmp("app-theme-changed", aTopic) == 0) {
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -327,17 +327,17 @@ IsInvisibleBreak(nsINode *aNode) {
   // if a BR node is visible without using the editor.
   Element* elt = aNode->AsElement();
   if (!elt->IsHTML(nsGkAtoms::br) ||
       !aNode->IsEditable()) {
     return false;
   }
 
   // Grab the editor associated with the document
-  nsIDocument *doc = aNode->GetCurrentDoc();
+  nsIDocument *doc = aNode->GetComposedDoc();
   if (doc) {
     nsPIDOMWindow *window = doc->GetWindow();
     if (window) {
       nsIDocShell *docShell = window->GetDocShell();
       if (docShell) {
         nsCOMPtr<nsIEditor> editor;
         docShell->GetEditor(getter_AddRefs(editor));
         nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -187,17 +187,17 @@ nsFrameLoader::~nsFrameLoader()
 }
 
 nsFrameLoader*
 nsFrameLoader::Create(Element* aOwner, bool aNetworkCreated)
 {
   NS_ENSURE_TRUE(aOwner, nullptr);
   nsIDocument* doc = aOwner->OwnerDoc();
   NS_ENSURE_TRUE(!doc->IsResourceDoc() &&
-                 ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
+                 ((!doc->IsLoadedAsData() && aOwner->GetUncomposedDoc()) ||
                    doc->IsStaticDocument()),
                  nullptr);
 
   return new nsFrameLoader(aOwner, aNetworkCreated);
 }
 
 NS_IMETHODIMP
 nsFrameLoader::LoadFrame()
@@ -868,22 +868,22 @@ nsFrameLoader::ShowRemoteFrame(const nsI
     }
   }
 
   // FIXME/bug 589337: Show()/Hide() is pretty expensive for
   // cross-process layers; need to figure out what behavior we really
   // want here.  For now, hack.
   if (!mRemoteBrowserShown) {
     if (!mOwnerContent ||
-        !mOwnerContent->GetCurrentDoc()) {
+        !mOwnerContent->GetUncomposedDoc()) {
       return false;
     }
 
     nsRefPtr<layers::LayerManager> layerManager =
-      nsContentUtils::LayerManagerForDocument(mOwnerContent->GetCurrentDoc());
+      nsContentUtils::LayerManagerForDocument(mOwnerContent->GetUncomposedDoc());
     if (!layerManager) {
       // This is just not going to work.
       return false;
     }
 
     mRemoteBrowser->Show(size);
     mRemoteBrowserShown = true;
 
@@ -1068,18 +1068,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   }
 
   nsCOMPtr<nsIDocument> ourParentDocument =
     ourChildDocument->GetParentDocument();
   nsCOMPtr<nsIDocument> otherParentDocument =
     otherChildDocument->GetParentDocument();
 
   // Make sure to swap docshells between the two frames.
-  nsIDocument* ourDoc = ourContent->GetCurrentDoc();
-  nsIDocument* otherDoc = otherContent->GetCurrentDoc();
+  nsIDocument* ourDoc = ourContent->GetUncomposedDoc();
+  nsIDocument* otherDoc = otherContent->GetUncomposedDoc();
   if (!ourDoc || !otherDoc) {
     // Again, how odd, given that we had docshells
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   NS_ASSERTION(ourDoc == ourParentDocument, "Unexpected parent document");
   NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document");
 
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -292,17 +292,17 @@ nsGenericDOMDataNode::SetTextInternal(ui
 
   uint32_t endOffset = aOffset + aCount;
 
   // Make sure the text fragment can hold the new data.
   if (aLength > aCount && !mText.CanGrowBy(aLength - aCount)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  nsIDocument *document = GetCurrentDoc();
+  nsIDocument *document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
 
   bool haveMutationListeners = aNotify &&
     nsContentUtils::HasMutationListeners(this,
       NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED,
       this);
 
   nsCOMPtr<nsIAtom> oldValue;
@@ -460,19 +460,19 @@ nsGenericDOMDataNode::ToCString(nsAStrin
 nsresult
 nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                  nsIContent* aBindingParent,
                                  bool aCompileEventHandlers)
 {
   NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
   NS_PRECONDITION(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(),
                   "Must have the same owner document");
-  NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
+  NS_PRECONDITION(!aParent || aDocument == aParent->GetUncomposedDoc(),
                   "aDocument must be current doc of aParent");
-  NS_PRECONDITION(!GetCurrentDoc() && !IsInDoc(),
+  NS_PRECONDITION(!GetUncomposedDoc() && !IsInDoc(),
                   "Already have a document.  Unbind first!");
   // Note that as we recurse into the kids, they'll have a non-null parent.  So
   // only assert if our parent is _changing_ while we have a parent.
   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
                   "Already have a parent.  Unbind first!");
   NS_PRECONDITION(!GetBindingParent() ||
                   aBindingParent == GetBindingParent() ||
                   (!aBindingParent && aParent &&
@@ -545,38 +545,34 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
     // update our subtree pointer.
     SetSubtreeRootPointer(aParent->SubtreeRoot());
   }
 
   nsNodeUtils::ParentChainChanged(this);
 
   UpdateEditableState(false);
 
-  NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
+  NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
                    "Bound to wrong binding parent");
 
   return NS_OK;
 }
 
 void
 nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   // Unset frame flags; if we need them again later, they'll get set again.
   UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
              NS_REFRAME_IF_WHITESPACE);
-  
-  nsIDocument *document = GetCurrentDoc();
-  if (document) {
-    // Notify XBL- & nsIAnonymousContentCreator-generated
-    // anonymous content that the document is changing.
-    // This is needed to update the insertion point.
-    document->BindingManager()->RemovedFromDocument(this, document);
-  }
+
+  nsIDocument* document =
+    HasFlag(NODE_FORCE_XBL_BINDINGS) || IsInShadowTree() ?
+      OwnerDoc() : GetUncomposedDoc();
 
   if (aNullParent) {
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nullptr;
     }
     SetParentIsContent(false);
@@ -585,16 +581,26 @@ nsGenericDOMDataNode::UnbindFromTree(boo
 
   if (aNullParent || !mParent->IsInShadowTree()) {
     UnsetFlags(NODE_IS_IN_SHADOW_TREE);
 
     // Begin keeping track of our subtree root.
     SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
   }
 
+  if (document) {
+    // Notify XBL- & nsIAnonymousContentCreator-generated
+    // anonymous content that the document is changing.
+    if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+      nsContentUtils::AddScriptRunner(
+        new RemoveFromBindingManagerRunnable(document->BindingManager(), this,
+                                             document));
+    }
+  }
+
   nsDataSlots *slots = GetExistingDataSlots();
   if (slots) {
     slots->mBindingParent = nullptr;
     if (aNullParent || !mParent->IsInShadowTree()) {
       slots->mContainingShadow = nullptr;
     }
   }
 
@@ -850,17 +856,17 @@ nsGenericDOMDataNode::SplitData(uint32_t
 
   uint32_t cutStartOffset = aCloneAfterOriginal ? aOffset : 0;
   uint32_t cutLength = aCloneAfterOriginal ? length - aOffset : aOffset;
   rv = SubstringData(cutStartOffset, cutLength, cutText);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  nsIDocument* document = GetCurrentDoc();
+  nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, true);
 
   // Use Clone for creating the new node so that the new node is of same class
   // as this node!
   nsCOMPtr<nsIContent> newContent = CloneDataNode(mNodeInfo, false);
   if (!newContent) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -194,17 +194,17 @@ nsINode::CreateSlots()
 bool
 nsINode::IsEditableInternal() const
 {
   if (HasFlag(NODE_IS_EDITABLE)) {
     // The node is in an editable contentEditable subtree.
     return true;
   }
 
-  nsIDocument *doc = GetCurrentDoc();
+  nsIDocument *doc = GetUncomposedDoc();
 
   // Check if the node is in a document and the document is in designMode.
   return doc && doc->HasFlag(NODE_IS_EDITABLE);
 }
 
 static nsIContent* GetEditorRootContent(nsIEditor* aEditor)
 {
   nsCOMPtr<nsIDOMElement> rootElement;
@@ -1331,17 +1331,17 @@ nsINode::UnoptimizableCCNode() const
           AsElement()->IsInNamespace(kNameSpaceID_XBL));
 }
 
 /* static */
 bool
 nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
 {
   if (MOZ_LIKELY(!cb.WantAllTraces())) {
-    nsIDocument *currentDoc = tmp->GetCurrentDoc();
+    nsIDocument *currentDoc = tmp->GetUncomposedDoc();
     if (currentDoc &&
         nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {
       return false;
     }
 
     if (nsCCUncollectableMarker::sGeneration) {
       // If we're black no need to traverse.
       if (tmp->IsBlack() || tmp->InCCBlackTree()) {
@@ -1493,17 +1493,17 @@ nsINode::doInsertChildAt(nsIContent* aKi
                   "Inserting node that already has parent");
   nsresult rv;
 
   // The id-handling code, and in the future possibly other code, need to
   // react to unexpected attribute changes.
   nsMutationGuard::DidMutate();
 
   // Do this before checking the child-count since this could cause mutations
-  nsIDocument* doc = GetCurrentDoc();
+  nsIDocument* doc = GetUncomposedDoc();
   mozAutoDocUpdate updateBatch(GetCrossShadowCurrentDoc(), UPDATE_CONTENT_MODEL, aNotify);
 
   if (OwnerDoc() != aKid->OwnerDoc()) {
     rv = AdoptNodeIntoOwnerDoc(this, aKid);
     NS_ENSURE_SUCCESS(rv, rv);
   } else if (OwnerDoc()->DidDocumentOpen()) {
     rv = CheckForOutdatedParent(this, aKid);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -1923,17 +1923,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
     nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
 
     // Removing a child can run script, via XBL destructors.
     nsMutationGuard guard;
 
     // Scope for the mutation batch and scriptblocker, so they go away
     // while kungFuDeathGrip is still alive.
     {
-      mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
+      mozAutoDocUpdate batch(newContent->GetComposedDoc(),
                              UPDATE_CONTENT_MODEL, true);
       nsAutoMutationBatch mb(oldParent, true, true);
       oldParent->RemoveChildAt(removeIndex, true);
       if (nsAutoMutationBatch::GetCurrentBatch() == &mb) {
         mb.RemovalDone();
         mb.SetPrevSibling(oldParent->GetChildAt(removeIndex - 1));
         mb.SetNextSibling(oldParent->GetChildAt(removeIndex));
       }
@@ -1988,30 +1988,30 @@ nsINode::ReplaceOrInsertBefore(bool aRep
     fragChildren.emplace();
 
     // Copy the children into a separate array to avoid having to deal with
     // mutations to the fragment later on here.
     fragChildren->SetCapacity(count);
     for (nsIContent* child = newContent->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
-      NS_ASSERTION(child->GetCurrentDoc() == nullptr,
+      NS_ASSERTION(child->GetComposedDoc() == nullptr,
                    "How did we get a child with a current doc?");
       fragChildren->AppendElement(child);
     }
 
     // Hold a strong ref to nodeToInsertBefore across the removals
     nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
 
     nsMutationGuard guard;
 
     // Scope for the mutation batch and scriptblocker, so they go away
     // while kungFuDeathGrip is still alive.
     {
-      mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
+      mozAutoDocUpdate batch(newContent->GetComposedDoc(),
                              UPDATE_CONTENT_MODEL, true);
       nsAutoMutationBatch mb(newContent, false, true);
 
       for (uint32_t i = count; i > 0;) {
         newContent->RemoveChildAt(--i, true);
       }
     }
 
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -1058,17 +1058,17 @@ nsImageLoadingContent::GetOurOwnerDoc()
 
 nsIDocument*
 nsImageLoadingContent::GetOurCurrentDoc()
 {
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ENSURE_TRUE(thisContent, nullptr);
 
-  return thisContent->GetCurrentDoc();
+  return thisContent->GetComposedDoc();
 }
 
 nsIFrame*
 nsImageLoadingContent::GetOurPrimaryFrame()
 {
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   return thisContent->GetPrimaryFrame();
--- a/content/base/src/nsMappedAttributeElement.cpp
+++ b/content/base/src/nsMappedAttributeElement.cpp
@@ -15,17 +15,17 @@ nsMappedAttributeElement::WalkContentSty
 }
 
 bool
 nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument,
                                              nsIAtom* aName,
                                              nsAttrValue& aValue,
                                              nsresult* aRetval)
 {
-  NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document");
+  NS_PRECONDITION(aDocument == GetComposedDoc(), "Unexpected document");
   nsHTMLStyleSheet* sheet = aDocument ?
     aDocument->GetAttributeStyleSheet() : nullptr;
 
   *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
                                                     this, sheet);
   return true;
 }
 
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -204,19 +204,19 @@ CheckPluginStopEvent::Run()
          ", no action", this));
     objLC->mPendingCheckPluginStopEvent = nullptr;
     return NS_OK;
   }
 
   // In an active document, but still no frame. Flush layout to see if we can
   // regain a frame now.
   LOG(("OBJLC [%p]: CheckPluginStopEvent - No frame, flushing layout", this));
-  nsIDocument* currentDoc = content->GetCurrentDoc();
-  if (currentDoc) {
-    currentDoc->FlushPendingNotifications(Flush_Layout);
+  nsIDocument* composedDoc = content->GetComposedDoc();
+  if (composedDoc) {
+    composedDoc->FlushPendingNotifications(Flush_Layout);
     if (objLC->mPendingCheckPluginStopEvent != this) {
       LOG(("OBJLC [%p]: CheckPluginStopEvent - superseded in layout flush",
            this));
       return NS_OK;
     } else if (content->GetPrimaryFrame()) {
       LOG(("OBJLC [%p]: CheckPluginStopEvent - frame gained in layout flush",
            this));
       objLC->mPendingCheckPluginStopEvent = nullptr;
@@ -234,17 +234,17 @@ CheckPluginStopEvent::Run()
 
 /**
  * Helper task for firing simple events
  */
 class nsSimplePluginEvent : public nsRunnable {
 public:
   nsSimplePluginEvent(nsIContent* aTarget, const nsAString &aEvent)
     : mTarget(aTarget)
-    , mDocument(aTarget->GetCurrentDoc())
+    , mDocument(aTarget->GetComposedDoc())
     , mEvent(aEvent)
   {
     MOZ_ASSERT(aTarget && mDocument);
   }
 
   nsSimplePluginEvent(nsIDocument* aTarget, const nsAString& aEvent)
     : mTarget(aTarget)
     , mDocument(aTarget)
@@ -656,17 +656,17 @@ nsObjectLoadingContent::IsSupportedDocum
 
   nsCOMPtr<nsIWebNavigationInfo> info(
     do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
   if (!info) {
     return false;
   }
 
   nsCOMPtr<nsIWebNavigation> webNav;
-  nsIDocument* currentDoc = thisContent->GetCurrentDoc();
+  nsIDocument* currentDoc = thisContent->GetComposedDoc();
   if (currentDoc) {
     webNav = do_GetInterface(currentDoc->GetWindow());
   }
 
   uint32_t supported;
   nsresult rv = info->IsTypeSupported(aMimeType, webNav, &supported);
 
   if (NS_FAILED(rv)) {
@@ -725,17 +725,17 @@ nsObjectLoadingContent::UnbindFromTree(b
     QueueCheckPluginStopEvent();
   } else if (mType != eType_Image) {
     // nsImageLoadingContent handles the image case.
     // Reset state and clear pending events
     /// XXX(johns): The implementation for GenericFrame notes that ideally we
     ///             would keep the docshell around, but trash the frameloader
     UnloadObject();
   }
-  nsIDocument* doc = thisContent->GetCurrentDoc();
+  nsIDocument* doc = thisContent->GetComposedDoc();
   if (doc && doc->IsActive()) {
     nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(doc,
                                                        NS_LITERAL_STRING("PluginRemoved"));
     NS_DispatchToCurrentThread(ev);
   }
 }
 
 nsObjectLoadingContent::nsObjectLoadingContent()
@@ -781,17 +781,17 @@ nsObjectLoadingContent::InstantiatePlugi
   }
 
   mInstantiating = true;
   AutoSetInstantiatingToFalse autoInstantiating(this);
 
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent *>(this));
 
-  nsCOMPtr<nsIDocument> doc = thisContent->GetCurrentDoc();
+  nsCOMPtr<nsIDocument> doc = thisContent->GetComposedDoc();
   if (!doc || !InActiveDocument(thisContent)) {
     NS_ERROR("Shouldn't be calling "
              "InstantiatePluginInstance without an active document");
     return NS_ERROR_FAILURE;
   }
 
   // Instantiating an instance can result in script execution, which
   // can destroy this DOM object. Don't allow that for the scope
@@ -1173,18 +1173,18 @@ nsObjectLoadingContent::OnStopRequest(ns
     js::ProfileEntry::Category::NETWORK);
 
   // Handle object not loading error because source was a tracking URL.
   // We make a note of this object node by including it in a dedicated
   // array of blocked tracking nodes under its parent document.
   if (aStatusCode == NS_ERROR_TRACKING_URI) {
     nsCOMPtr<nsIContent> thisNode =
       do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
-    if (thisNode) {
-      thisNode->GetCurrentDoc()->AddBlockedTrackingNode(thisNode);
+    if (thisNode && thisNode->IsInComposedDoc()) {
+      thisNode->GetComposedDoc()->AddBlockedTrackingNode(thisNode);
     }
   }
 
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
@@ -2655,17 +2655,17 @@ nsObjectLoadingContent::NotifyStateChang
   // manually notify object state changes.
   thisContent->AsElement()->UpdateState(false);
 
   if (!aNotify) {
     // We're done here
     return;
   }
 
-  nsIDocument* doc = thisContent->GetCurrentDoc();
+  nsIDocument* doc = thisContent->GetComposedDoc();
   if (!doc) {
     return; // Nothing to do
   }
 
   EventStates newState = ObjectState();
 
   if (newState != aOldState) {
     // This will trigger frame construction
@@ -3344,17 +3344,17 @@ nsObjectLoadingContent::GetContentDocume
 {
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   if (!thisContent->IsInDoc()) {
     return nullptr;
   }
 
-  // XXXbz should this use GetCurrentDoc()?  sXBL/XBL2 issue!
+  // XXXbz should this use GetComposedDoc()?  sXBL/XBL2 issue!
   nsIDocument *sub_doc = thisContent->OwnerDoc()->GetSubDocumentFor(thisContent);
   if (!sub_doc) {
     return nullptr;
   }
 
   // Return null for cross-origin contentDocument.
   if (!nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
     return nullptr;
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -1079,25 +1079,25 @@ nsRange::IsValidBoundary(nsINode* aNode)
       if (root) {
         return root;
       }
     }
   }
 
   // Elements etc. must be in document or in document fragment,
   // text nodes in document, in document fragment or in attribute.
-  nsINode* root = aNode->GetCurrentDoc();
+  nsINode* root = aNode->GetUncomposedDoc();
   if (root) {
     return root;
   }
 
   root = aNode->SubtreeRoot();
 
   NS_ASSERTION(!root->IsNodeOfType(nsINode::eDOCUMENT),
-               "GetCurrentDoc should have returned a doc");
+               "GetUncomposedDoc should have returned a doc");
 
   // We allow this because of backward compatibility.
   return root;
 }
 
 void
 nsRange::SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aRv)
 {
--- a/content/base/src/nsReferencedElement.cpp
+++ b/content/base/src/nsReferencedElement.cpp
@@ -42,17 +42,17 @@ nsReferencedElement::Reset(nsIContent* a
     // assumes UTF-8 and doesn't handle UTF-8 errors.
     // https://bugzilla.mozilla.org/show_bug.cgi?id=951082
     CopyUTF8toUTF16(refPart, ref);
   }
   if (ref.IsEmpty())
     return;
 
   // Get the current document
-  nsIDocument *doc = aFromContent->GetCurrentDoc();
+  nsIDocument *doc = aFromContent->GetComposedDoc();
   if (!doc)
     return;
 
   nsIContent* bindingParent = aFromContent->GetBindingParent();
   if (bindingParent) {
     nsXBLBinding* binding = bindingParent->GetXBLBinding();
     if (binding) {
       bool isEqualExceptRef;
@@ -119,17 +119,17 @@ nsReferencedElement::Reset(nsIContent* a
 
   HaveNewDocument(doc, aWatch, ref);
 }
 
 void
 nsReferencedElement::ResetWithID(nsIContent* aFromContent, const nsString& aID,
                                  bool aWatch)
 {
-  nsIDocument *doc = aFromContent->GetCurrentDoc();
+  nsIDocument *doc = aFromContent->GetComposedDoc();
   if (!doc)
     return;
 
   // XXX Need to take care of XBL/XBL2
 
   if (aWatch) {
     nsCOMPtr<nsIAtom> atom = do_GetAtom(aID);
     if (!atom)