Bug 1556095 - Make BindContext carry a bit more information. r=bzbarsky

This makes some callers a bit less awkward by not having, for example, to read
from the parent node or not depending on whether Element::BindToTree has been
called already or not.

Differential Revision: https://phabricator.services.mozilla.com/D33368

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-06-01 14:40:33 +00:00
parent 3cacbcf87b
commit a14f58fefe
9 changed files with 58 additions and 27 deletions

View File

@ -24,6 +24,22 @@ struct MOZ_STACK_CLASS BindContext final {
// OwnerDoc().
Document& OwnerDoc() const { return mDoc; }
// Whether we're getting connected.
//
// https://dom.spec.whatwg.org/#connected
bool InComposedDoc() const { return mInComposedDoc; }
// Whether we're getting bound to the document tree.
//
// https://dom.spec.whatwg.org/#in-a-document-tree
bool InUncomposedDoc() const { return mInUncomposedDoc; }
Document* GetComposedDoc() const { return mInComposedDoc ? &mDoc : nullptr; }
Document* GetUncomposedDoc() const {
return mInUncomposedDoc ? &mDoc : nullptr;
}
// Whether our subtree root is changing as a result of this operation.
bool SubtreeRootChanges() const { return mSubtreeRootChanges; }
@ -35,10 +51,12 @@ struct MOZ_STACK_CLASS BindContext final {
// This constructor should be used for regular appends to content.
explicit BindContext(nsINode& aParentNode)
: mDoc(*aParentNode.OwnerDoc()),
mSubtreeRootChanges(true),
mBindingParent(aParentNode.IsContent()
? aParentNode.AsContent()->GetBindingParent()
: nullptr) {}
: nullptr),
mInComposedDoc(aParentNode.IsInComposedDoc()),
mInUncomposedDoc(aParentNode.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {}
// When re-binding a shadow host into a tree, we re-bind all the shadow tree
// from the root. In that case, the shadow tree contents remain within the
@ -48,30 +66,42 @@ struct MOZ_STACK_CLASS BindContext final {
// This constructor is only meant to be used in that situation.
explicit BindContext(ShadowRoot& aShadowRoot)
: mDoc(*aShadowRoot.OwnerDoc()),
mSubtreeRootChanges(false),
mBindingParent(aShadowRoot.Host()) {}
mBindingParent(aShadowRoot.Host()),
mInComposedDoc(aShadowRoot.IsInComposedDoc()),
mInUncomposedDoc(false),
mSubtreeRootChanges(false) {}
// This constructor is meant to be used when inserting native-anonymous
// children into a subtree.
enum ForNativeAnonymous { ForNativeAnonymous };
BindContext(Element& aParentElement, enum ForNativeAnonymous)
: mDoc(*aParentElement.OwnerDoc()),
mSubtreeRootChanges(true),
mBindingParent(&aParentElement) {}
mBindingParent(&aParentElement),
mInComposedDoc(aParentElement.IsInComposedDoc()),
mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {
MOZ_ASSERT(mInComposedDoc, "Binding NAC in a disconnected subtree?");
}
// This is meant to be used to bind XBL anonymous content.
BindContext(nsXBLBinding& aBinding, Element& aParentElement)
: mDoc(*aParentElement.OwnerDoc()),
mSubtreeRootChanges(true),
mBindingParent(aBinding.GetBoundElement()) {}
mBindingParent(aBinding.GetBoundElement()),
mInComposedDoc(aParentElement.IsInComposedDoc()),
mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
mSubtreeRootChanges(true) {}
private:
Document& mDoc;
Element* const mBindingParent;
const bool mInComposedDoc;
const bool mInUncomposedDoc;
// Whether the bind operation will change the subtree root of the content
// we're binding.
const bool mSubtreeRootChanges;
Element* const mBindingParent;
};
} // namespace dom

View File

@ -481,6 +481,8 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
UpdateEditableState(false);
MOZ_ASSERT(OwnerDoc() == aParent.OwnerDoc(), "Bound to wrong document");
MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc());
MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc());
MOZ_ASSERT(&aParent == GetParentNode(), "Bound to wrong parent node");
MOZ_ASSERT(aContext.GetBindingParent() == GetBindingParent(),
"Bound to wrong binding parent");

View File

@ -1758,6 +1758,8 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
// postcondition asserts.... But we do want that, since things will
// generally be quite broken when that happens.
MOZ_ASSERT(OwnerDoc() == aParent.OwnerDoc(), "Bound to wrong document");
MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc());
MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc());
MOZ_ASSERT(&aParent == GetParentNode(), "Bound to wrong parent node");
MOZ_ASSERT(aContext.GetBindingParent() == GetBindingParent(),
"Bound to wrong binding parent");

View File

@ -13,6 +13,7 @@
#include "nsImageLoadingContent.h"
#include "nsError.h"
#include "nsIContent.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/dom/Document.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMWindow.h"
@ -1613,8 +1614,7 @@ void nsImageLoadingContent::NotifyOwnerDocumentActivityChanged() {
void nsImageLoadingContent::BindToTree(BindContext& aContext,
nsINode& aParent) {
// We may be getting connected, if so our image should be tracked,
// NOTE(emilio): Using aParent to avoid silly virtual call.
if (aParent.IsInComposedDoc()) {
if (aContext.InComposedDoc()) {
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
}

View File

@ -567,10 +567,9 @@ already_AddRefed<nsIDocShell> nsObjectLoadingContent::SetupDocShell(
nsresult nsObjectLoadingContent::BindToTree(BindContext& aContext,
nsINode& aParent) {
nsImageLoadingContent::BindToTree(aContext, aParent);
// NOTE(emilio): Using aParent to avoid silly QI.
// FIXME(emilio): Should probably use composed doc?
if (aParent.IsInUncomposedDoc()) {
aContext.OwnerDoc().AddPlugin(this);
if (Document* doc = aContext.GetUncomposedDoc()) {
doc->AddPlugin(this);
}
return NS_OK;
}

View File

@ -82,13 +82,13 @@ nsresult nsMathMLElement::BindToTree(BindContext& aContext, nsINode& aParent) {
// FIXME(emilio): Probably should be composed, this uses all the other link
// infrastructure.
if (IsInUncomposedDoc()) {
aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
if (Document* doc = aContext.GetUncomposedDoc()) {
doc->RegisterPendingLinkUpdate(this);
}
// Set the bit in the document for telemetry.
if (IsInComposedDoc()) {
aContext.OwnerDoc().SetMathMLEnabled();
if (Document* doc = aContext.GetComposedDoc()) {
doc->SetMathMLEnabled();
}
return rv;

View File

@ -161,8 +161,8 @@ nsresult SVGAElement::BindToTree(BindContext& aContext, nsINode& aParent) {
nsresult rv = SVGAElementBase::BindToTree(aContext, aParent);
NS_ENSURE_SUCCESS(rv, rv);
if (IsInComposedDoc()) {
aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
if (Document* doc = aContext.GetComposedDoc()) {
doc->RegisterPendingLinkUpdate(this);
}
return NS_OK;

View File

@ -140,9 +140,8 @@ nsresult SVGAnimationElement::BindToTree(BindContext& aContext,
NS_ENSURE_SUCCESS(rv, rv);
// Add myself to the animation controller's master set of animation elements.
if (IsInComposedDoc()) {
if (SMILAnimationController* controller =
aContext.OwnerDoc().GetAnimationController()) {
if (Document* doc = aContext.GetComposedDoc()) {
if (SMILAnimationController* controller = doc->GetAnimationController()) {
controller->RegisterAnimationElement(this);
}
const nsAttrValue* href =

View File

@ -370,10 +370,9 @@ SMILTimeContainer* SVGSVGElement::GetTimedDocumentRoot() {
nsresult SVGSVGElement::BindToTree(BindContext& aContext, nsINode& aParent) {
SMILAnimationController* smilController = nullptr;
// NOTE(emilio): Using aParent because we still haven't called our base class.
// FIXME(emilio, bug 1555948): Should probably use IsInComposedDoc()?
if (aParent.IsInUncomposedDoc()) {
if ((smilController = aContext.OwnerDoc().GetAnimationController())) {
// FIXME(emilio, bug 1555948): Should probably use composed doc.
if (Document* doc = aContext.GetUncomposedDoc()) {
if ((smilController = doc->GetAnimationController())) {
// SMIL is enabled in this document
if (WillBeOutermostSVG(aParent, aContext.GetBindingParent())) {
// We'll be the outermost <svg> element. We'll need a time container.