Backed out changeset 0478d1bf6e32 (bug 1596209) on request from emilio. CLOSED TREE

--HG--
extra : rebase_source : 3c14fff8de93d231125ec8714aae98e51fbf6aeb
extra : amend_source : 5f1791c11b41593330cc8c94bdf67e1a0cf11fb1
This commit is contained in:
Sebastian Hengst 2019-11-15 19:11:06 +01:00
Родитель 1b12ed0729
Коммит 9ad1a69782
8 изменённых файлов: 157 добавлений и 1 удалений

Просмотреть файл

@ -47,9 +47,17 @@ struct MOZ_STACK_CLASS BindContext final {
// Whether our subtree root is changing as a result of this operation.
bool SubtreeRootChanges() const { return mSubtreeRootChanges; }
// Returns the binding parent of the subtree to be inserted.
//
// This can be null.
Element* GetBindingParent() const { return mBindingParent; }
// This constructor should be used for regular appends to content.
explicit BindContext(nsINode& aParent)
: mDoc(*aParent.OwnerDoc()),
mBindingParent(aParent.IsContent()
? aParent.AsContent()->GetBindingParent()
: nullptr),
mInComposedDoc(aParent.IsInComposedDoc()),
mInUncomposedDoc(aParent.IsInUncomposedDoc()),
mSubtreeRootChanges(true),
@ -65,6 +73,7 @@ struct MOZ_STACK_CLASS BindContext final {
// This constructor is only meant to be used in that situation.
explicit BindContext(ShadowRoot& aShadowRoot)
: mDoc(*aShadowRoot.OwnerDoc()),
mBindingParent(aShadowRoot.Host()),
mInComposedDoc(aShadowRoot.IsInComposedDoc()),
mInUncomposedDoc(false),
mSubtreeRootChanges(false),
@ -77,6 +86,7 @@ struct MOZ_STACK_CLASS BindContext final {
enum ForNativeAnonymous { ForNativeAnonymous };
BindContext(Element& aParentElement, enum ForNativeAnonymous)
: mDoc(*aParentElement.OwnerDoc()),
mBindingParent(&aParentElement),
mInComposedDoc(aParentElement.IsInComposedDoc()),
mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
mSubtreeRootChanges(true),
@ -104,6 +114,8 @@ struct MOZ_STACK_CLASS BindContext final {
Document& mDoc;
Element* const mBindingParent;
const bool mInComposedDoc;
const bool mInUncomposedDoc;

Просмотреть файл

@ -402,9 +402,34 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
// only assert if our parent is _changing_ while we have a parent.
MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
"Already have a parent. Unbind first!");
MOZ_ASSERT(
!GetBindingParent() ||
aContext.GetBindingParent() == GetBindingParent() ||
(!aContext.GetBindingParent() && aParent.IsContent() &&
aParent.AsContent()->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
aContext.GetBindingParent() == &aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
MOZ_ASSERT(aContext.GetBindingParent() || !aParent.IsContent() ||
aContext.GetBindingParent() ==
aParent.AsContent()->GetBindingParent(),
"We should be passed the right binding parent");
// First set the binding parent
if (Element* bindingParent = aContext.GetBindingParent()) {
ExtendedContentSlots()->mBindingParent = bindingParent;
}
const bool hadParent = !!GetParentNode();
NS_ASSERTION(!aContext.GetBindingParent() ||
IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
aParent.IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
if (aParent.IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
}
@ -472,6 +497,8 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
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");
MOZ_ASSERT(aParent.IsInUncomposedDoc() == IsInUncomposedDoc());
MOZ_ASSERT(aParent.IsInComposedDoc() == IsInComposedDoc());
MOZ_ASSERT(aParent.IsInShadowTree() == IsInShadowTree());
@ -506,7 +533,9 @@ void CharacterData::UnbindFromTree(bool aNullParent) {
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
}
if (nsExtendedContentSlots* slots = GetExistingExtendedContentSlots()) {
nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
if (slots) {
slots->mBindingParent = nullptr;
if (aNullParent || !mParent->IsInShadowTree()) {
slots->mContainingShadow = nullptr;
}

Просмотреть файл

@ -1460,9 +1460,36 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
// only assert if our parent is _changing_ while we have a parent.
MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
"Already have a parent. Unbind first!");
MOZ_ASSERT(
!GetBindingParent() ||
aContext.GetBindingParent() == GetBindingParent() ||
(!aContext.GetBindingParent() && aParent.IsContent() &&
aParent.AsContent()->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
MOZ_ASSERT(aContext.GetBindingParent() != this,
"Content must not be its own binding parent");
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
aContext.GetBindingParent() == &aParent,
"Native anonymous content must have its parent as its "
"own binding parent");
MOZ_ASSERT(aContext.GetBindingParent() || !aParent.IsContent() ||
aContext.GetBindingParent() ==
aParent.AsContent()->GetBindingParent(),
"We should be passed the right binding parent");
// First set the binding parent
if (Element* bindingParent = aContext.GetBindingParent()) {
ExtendedDOMSlots()->mBindingParent = bindingParent;
}
const bool hadParent = !!GetParentNode();
NS_ASSERTION(!aContext.GetBindingParent() ||
IsRootOfNativeAnonymousSubtree() ||
!HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
aParent.IsInNativeAnonymousSubtree(),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
if (aParent.IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
}
@ -1600,6 +1627,8 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
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");
MOZ_ASSERT(aParent.IsInUncomposedDoc() == IsInUncomposedDoc());
MOZ_ASSERT(aParent.IsInComposedDoc() == IsInComposedDoc());
MOZ_ASSERT(aParent.IsInShadowTree() == IsInShadowTree());
@ -1736,6 +1765,7 @@ void Element::UnbindFromTree(bool aNullParent) {
}
if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) {
slots->mBindingParent = nullptr;
if (aNullParent || !mParent->IsInShadowTree()) {
slots->mContainingShadow = nullptr;
}

Просмотреть файл

@ -530,12 +530,16 @@ static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
void nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots() {
mBindingParent = nullptr;
mContainingShadow = nullptr;
mAssignedSlot = nullptr;
}
void nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(
nsCycleCollectionTraversalCallback& aCb) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mBindingParent");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mBindingParent));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mContainingShadow");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
@ -629,6 +633,7 @@ size_t FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(
// The following member are not measured:
// - mControllers: because it is non-owning
// - mBindingParent: because it is some ancestor element.
return n;
}
@ -1056,6 +1061,28 @@ void nsIContent::SetAssignedSlot(HTMLSlotElement* aSlot) {
ExtendedContentSlots()->mAssignedSlot = aSlot;
}
#ifdef DEBUG
void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
(GetParent() && GetBindingParent() == GetParent()),
"root of native anonymous subtree must have parent equal "
"to binding parent");
MOZ_ASSERT(!GetParent() || !IsInComposedDoc() ||
((GetBindingParent() == GetParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
// Unfortunately default content for XBL insertion points
// is anonymous content that is bound with the parent of
// the insertion point as the parent but the bound element
// for the binding as the binding parent. So we have to
// complicate the assert a bit here.
(GetBindingParent() &&
(GetBindingParent() == GetParent()->GetBindingParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)),
"For connected nodes, flag and GetBindingParent() check "
"should match");
}
#endif
void FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
OOMReporter& aError) {
if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {

Просмотреть файл

@ -62,6 +62,7 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
SetFlags(NODE_IS_IN_SHADOW_TREE);
Bind();
ExtendedDOMSlots()->mBindingParent = aElement;
ExtendedDOMSlots()->mContainingShadow = this;
}

Просмотреть файл

@ -185,11 +185,18 @@ class nsIContent : public nsINode {
*/
nsIContent* FindFirstNonChromeOnlyAccessContent() const;
#ifdef DEBUG
void AssertAnonymousSubtreeRelatedInvariants() const;
#endif
/**
* Returns true if and only if this node has a parent, but is not in
* its parent's child list.
*/
bool IsRootOfAnonymousSubtree() const {
#ifdef DEBUG
AssertAnonymousSubtreeRelatedInvariants();
#endif
return HasFlag(NODE_IS_ANONYMOUS_ROOT);
}
@ -364,6 +371,21 @@ class nsIContent : public nsINode {
*/
virtual IMEState GetDesiredIMEState();
/**
* Gets content node with the binding (or native code, possibly on the
* frame) responsible for our construction (and existence). Used by
* native-anonymous content and shadow DOM.
*
* null for all explicit content (i.e., content reachable from the top
* of its GetParent() chain via child lists).
*
* @return the binding parent
*/
mozilla::dom::Element* GetBindingParent() const {
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mBindingParent.get() : nullptr;
}
/**
* Gets the ShadowRoot binding for this element.
*
@ -696,6 +718,13 @@ class nsIContent : public nsINode {
virtual size_t SizeOfExcludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const;
/**
* The nearest enclosing content node with a binding that created us.
*
* @see nsIContent::GetBindingParent
*/
RefPtr<mozilla::dom::Element> mBindingParent;
/**
* @see nsIContent::GetContainingShadow
*/

Просмотреть файл

@ -536,6 +536,20 @@ void nsINode::LastRelease() {
FragmentOrElement::RemoveBlackMarkedNode(this);
}
#ifdef DEBUG
void nsINode::CheckNotNativeAnonymous() const {
if (!IsContent()) return;
nsIContent* content =
static_cast<const nsIContent*>(this)->GetBindingParent();
while (content) {
if (content->IsRootOfNativeAnonymousSubtree()) {
NS_ERROR("Element not marked to be in native anonymous subtree!");
break;
}
content = content->GetBindingParent();
}
}
#endif
std::ostream& operator<<(std::ostream& aStream, const nsINode& aNode) {
nsAutoString elemDesc;

Просмотреть файл

@ -1242,7 +1242,15 @@ class nsINode : public mozilla::dom::EventTarget {
* Returns true if |this| or any of its ancestors is native anonymous.
*/
bool IsInNativeAnonymousSubtree() const {
#ifdef DEBUG
if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
return true;
}
CheckNotNativeAnonymous();
return false;
#else
return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
#endif
}
/**
@ -2033,6 +2041,12 @@ class nsINode : public mozilla::dom::EventTarget {
nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& aError) {}
#ifdef DEBUG
// Note: virtual so that IsInNativeAnonymousSubtree can be called accross
// module boundaries.
virtual void CheckNotNativeAnonymous() const;
#endif
void EnsurePreInsertionValidity1(mozilla::ErrorResult& aError);
void EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
nsINode* aRefChild,