зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1425440 - Introduce nsINode::RemoveChildNode, r=catalinb
This commit is contained in:
Родитель
205d40e2d7
Коммит
41d4da5cef
|
@ -331,6 +331,11 @@ Attr::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Attr::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
|
||||
|
|
|
@ -1177,6 +1177,12 @@ FragmentOrElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
doRemoveChildAt(IndexOf(aKid), aNotify, aKid, mAttrsAndChildren);
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
|
||||
OOMReporter& aError)
|
||||
|
|
|
@ -123,6 +123,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError) override;
|
||||
virtual void SetTextContentInternal(const nsAString& aTextContent,
|
||||
|
|
|
@ -4401,6 +4401,28 @@ nsDocument::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
"(maybe somebody called GetRootElement() too early?)");
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
if (aKid->IsElement()) {
|
||||
// Destroy the link map up front before we mess with the child list.
|
||||
DestroyElementMaps();
|
||||
}
|
||||
|
||||
// Preemptively clear mCachedRootElement, since we may be about to remove it
|
||||
// from our child list, and we don't want to return this maybe-obsolete value
|
||||
// from any GetRootElement() calls that happen inside of doRemoveChildAt().
|
||||
// (NOTE: for this to be useful, doRemoveChildAt() must NOT trigger any
|
||||
// GetRootElement() calls until after it's removed the child from mChildren.
|
||||
// Any call before that point would restore this soon-to-be-obsolete cached
|
||||
// answer, and our clearing here would be fruitless.)
|
||||
mCachedRootElement = nullptr;
|
||||
doRemoveChildAt(IndexOf(aKid), aNotify, aKid, mChildren);
|
||||
MOZ_ASSERT(mCachedRootElement != aKid,
|
||||
"Stale pointer in mCachedRootElement, after we tried to clear it "
|
||||
"(maybe somebody called GetRootElement() too early?)");
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::EnsureOnDemandBuiltInUASheet(StyleSheet* aSheet)
|
||||
{
|
||||
|
|
|
@ -560,6 +560,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override
|
||||
{
|
||||
|
|
|
@ -663,6 +663,11 @@ nsGenericDOMDataNode::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericDOMDataNode::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
}
|
||||
|
||||
nsXBLBinding *
|
||||
nsGenericDOMDataNode::DoGetXBLBinding() const
|
||||
{
|
||||
|
|
|
@ -110,6 +110,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError) override
|
||||
{
|
||||
|
|
|
@ -1927,7 +1927,7 @@ nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
|
|||
// nsIDocument::GetRootElement() calls until *after* it has removed aKid from
|
||||
// aChildArray. Any calls before then could potentially restore a stale
|
||||
// value for our cached root element, per note in
|
||||
// nsDocument::RemoveChildAt_Deprecated().
|
||||
// nsDocument::RemoveChildNode().
|
||||
MOZ_ASSERT(aKid && aKid->GetParentNode() == this &&
|
||||
aKid == GetChildAt_Deprecated(aIndex) &&
|
||||
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
|
||||
|
|
|
@ -778,6 +778,17 @@ public:
|
|||
*/
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Remove a child from this node. This method handles calling UnbindFromTree
|
||||
* on the child appropriately.
|
||||
*
|
||||
* @param aKid the content to remove
|
||||
* @param aNotify whether to notify the document (current document for
|
||||
* nsIContent, and |this| for nsIDocument) that the remove has
|
||||
* occurred
|
||||
*/
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Get a property associated with this node.
|
||||
*
|
||||
|
|
|
@ -195,6 +195,32 @@ HTMLFieldSetElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLFieldSetElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
bool firstLegendHasChanged = false;
|
||||
|
||||
if (mFirstLegend && aKid == mFirstLegend) {
|
||||
// If we are removing the first legend we have to found another one.
|
||||
nsIContent* child = mFirstLegend->GetNextSibling();
|
||||
mFirstLegend = nullptr;
|
||||
firstLegendHasChanged = true;
|
||||
|
||||
for (; child; child = child->GetNextSibling()) {
|
||||
if (child->IsHTMLElement(nsGkAtoms::legend)) {
|
||||
mFirstLegend = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsGenericHTMLFormElement::RemoveChildNode(aKid, aNotify);
|
||||
|
||||
if (firstLegendHasChanged) {
|
||||
NotifyElementsForFirstLegendChange(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLFieldSetElement::AddElement(nsGenericHTMLFormElement* aElement)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
// nsIFormControl
|
||||
NS_IMETHOD Reset() override;
|
||||
|
|
|
@ -95,6 +95,14 @@ HTMLOptGroupElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
nsGenericHTMLElement::RemoveChildAt_Deprecated(aIndex, aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLOptGroupElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(GetSelect(), this, nullptr, IndexOf(aKid),
|
||||
aNotify);
|
||||
nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
// nsIContent
|
||||
virtual nsresult GetEventTargetParent(
|
||||
|
|
|
@ -58,6 +58,30 @@ HTMLPictureElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
nsGenericHTMLElement::RemoveChildAt_Deprecated(aIndex, aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLPictureElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
if (aKid && aKid->IsHTMLElement(nsGkAtoms::img)) {
|
||||
HTMLImageElement* img = HTMLImageElement::FromContent(aKid);
|
||||
if (img) {
|
||||
img->PictureSourceRemoved(aKid->AsContent());
|
||||
}
|
||||
} else if (aKid && aKid->IsHTMLElement(nsGkAtoms::source)) {
|
||||
// Find all img siblings after this <source> to notify them of its demise
|
||||
nsCOMPtr<nsIContent> nextSibling = aKid->GetNextSibling();
|
||||
if (nextSibling && nextSibling->GetParentNode() == this) {
|
||||
do {
|
||||
HTMLImageElement* img = HTMLImageElement::FromContent(nextSibling);
|
||||
if (img) {
|
||||
img->PictureSourceRemoved(aKid->AsContent());
|
||||
}
|
||||
} while ( (nextSibling = nextSibling->GetNextSibling()) );
|
||||
}
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLPictureElement::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -224,7 +224,12 @@ HTMLSelectElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
nsGenericHTMLFormElementWithState::RemoveChildAt_Deprecated(aIndex, aNotify);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTMLSelectElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(this, this, nullptr, IndexOf(aKid), aNotify);
|
||||
nsGenericHTMLFormElementWithState::RemoveChildNode(aKid, aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLSelectElement::InsertOptionsIntoList(nsIContent* aOptions,
|
||||
|
|
|
@ -294,6 +294,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
// Overriden nsIFormControl methods
|
||||
NS_IMETHOD Reset() override;
|
||||
|
|
|
@ -100,6 +100,13 @@ SVGSwitchElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
MaybeInvalidate();
|
||||
}
|
||||
|
||||
void
|
||||
SVGSwitchElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
SVGSwitchElementBase::RemoveChildNode(aKid, aNotify);
|
||||
MaybeInvalidate();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIContent methods
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
// nsIContent
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
|
||||
|
|
|
@ -949,6 +949,101 @@ nsXULElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXULElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
// On the removal of a <treeitem>, <treechildren>, or <treecell> element,
|
||||
// the possibility exists that some of the items in the removed subtree
|
||||
// are selected (and therefore need to be deselected). We need to account for this.
|
||||
nsCOMPtr<nsIDOMXULMultiSelectControlElement> controlElement;
|
||||
nsCOMPtr<nsIListBoxObject> listBox;
|
||||
bool fireSelectionHandler = false;
|
||||
|
||||
// -1 = do nothing, -2 = null out current item
|
||||
// anything else = index to re-set as current
|
||||
int32_t newCurrentIndex = -1;
|
||||
|
||||
if (aKid->NodeInfo()->Equals(nsGkAtoms::listitem, kNameSpaceID_XUL)) {
|
||||
// This is the nasty case. We have (potentially) a slew of selected items
|
||||
// and cells going away.
|
||||
// First, retrieve the tree.
|
||||
// Check first whether this element IS the tree
|
||||
controlElement = do_QueryObject(this);
|
||||
|
||||
// If it's not, look at our parent
|
||||
if (!controlElement)
|
||||
GetParentTree(getter_AddRefs(controlElement));
|
||||
nsCOMPtr<nsIContent> controlContent(do_QueryInterface(controlElement));
|
||||
RefPtr<nsXULElement> xulElement = FromContentOrNull(controlContent);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> oldKidElem = do_QueryInterface(aKid);
|
||||
if (xulElement && oldKidElem) {
|
||||
// Iterate over all of the items and find out if they are contained inside
|
||||
// the removed subtree.
|
||||
int32_t length;
|
||||
controlElement->GetSelectedCount(&length);
|
||||
for (int32_t i = 0; i < length; i++) {
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> node;
|
||||
controlElement->MultiGetSelectedItem(i, getter_AddRefs(node));
|
||||
// we need to QI here to do an XPCOM-correct pointercompare
|
||||
nsCOMPtr<nsIDOMElement> selElem = do_QueryInterface(node);
|
||||
if (selElem == oldKidElem &&
|
||||
NS_SUCCEEDED(controlElement->RemoveItemFromSelection(node))) {
|
||||
length--;
|
||||
i--;
|
||||
fireSelectionHandler = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> curItem;
|
||||
controlElement->GetCurrentItem(getter_AddRefs(curItem));
|
||||
nsCOMPtr<nsIContent> curNode = do_QueryInterface(curItem);
|
||||
if (curNode && nsContentUtils::ContentIsDescendantOf(curNode, aKid)) {
|
||||
// Current item going away
|
||||
IgnoredErrorResult ignored;
|
||||
nsCOMPtr<nsIBoxObject> box = xulElement->GetBoxObject(ignored);
|
||||
listBox = do_QueryInterface(box);
|
||||
if (listBox && oldKidElem) {
|
||||
listBox->GetIndexOfItem(oldKidElem, &newCurrentIndex);
|
||||
}
|
||||
|
||||
// If any of this fails, we'll just set the current item to null
|
||||
if (newCurrentIndex == -1)
|
||||
newCurrentIndex = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsStyledElement::RemoveChildNode(aKid, aNotify);
|
||||
|
||||
if (newCurrentIndex == -2) {
|
||||
controlElement->SetCurrentItem(nullptr);
|
||||
} else if (newCurrentIndex > -1) {
|
||||
// Make sure the index is still valid
|
||||
int32_t treeRows;
|
||||
listBox->GetRowCount(&treeRows);
|
||||
if (treeRows > 0) {
|
||||
newCurrentIndex = std::min((treeRows - 1), newCurrentIndex);
|
||||
nsCOMPtr<nsIDOMElement> newCurrentItem;
|
||||
listBox->GetItemAtIndex(newCurrentIndex, getter_AddRefs(newCurrentItem));
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> xulCurItem = do_QueryInterface(newCurrentItem);
|
||||
if (xulCurItem)
|
||||
controlElement->SetCurrentItem(xulCurItem);
|
||||
} else {
|
||||
controlElement->SetCurrentItem(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
nsIDocument* doc;
|
||||
if (fireSelectionHandler && (doc = GetComposedDoc())) {
|
||||
nsContentUtils::DispatchTrustedEvent(doc,
|
||||
static_cast<nsIContent*>(this),
|
||||
NS_LITERAL_STRING("select"),
|
||||
false,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
|
||||
{
|
||||
|
|
|
@ -367,6 +367,7 @@ public:
|
|||
bool aCompileEventHandlers) override;
|
||||
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual void DestroyContent() override;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
Загрузка…
Ссылка в новой задаче