void nsNodeUtils::LastRelease(nsINode* aNode) { nsINode::nsSlots* slots = aNode->GetExistingSlots(); if (slots) { if (!slots->mMutationObservers.IsEmpty()) { NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers, nsIMutationObserver, NodeWillBeDestroyed, (aNode)); } delete slots; aNode->mSlots = nullptr; } // Kill properties first since that may run external code, so we want to // be in as complete state as possible at that time. if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) { // Delete all properties before tearing down the document. Some of the // properties are bound to nsINode objects and the destructor functions of // the properties may want to use the owner document of the nsINode. static_cast<nsIDocument*>(aNode)->DeleteAllProperties(); } else { if (aNode->HasProperties()) { // Strong reference to the document so that deleting properties can't // delete the document. nsCOMPtr<nsIDocument> document = aNode->OwnerDoc(); document->DeleteAllPropertiesFor(aNode); } // I wonder whether it's faster to do the HasFlag check first.... if (aNode->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) && aNode->HasFlag(ADDED_TO_FORM)) { // Tell the form (if any) this node is going away. Don't // notify, since we're being destroyed in any case. static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true); } if (aNode->IsHTMLElement(nsGkAtoms::img) && aNode->HasFlag(ADDED_TO_FORM)) { HTMLImageElement* imageElem = static_cast<HTMLImageElement*>(aNode); imageElem->ClearForm(true); } } aNode->UnsetFlags(NODE_HAS_PROPERTIES); if (aNode->NodeType() != nsIDOMNode::DOCUMENT_NODE && aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) { #ifdef DEBUG if (nsContentUtils::IsInitialized()) { EventListenerManager* manager = nsContentUtils::GetExistingListenerManagerForNode(aNode); if (!manager) { NS_ERROR("Huh, our bit says we have a listener manager list, " "but there's nothing in the hash!?!!"); } } #endif nsContentUtils::RemoveListenerManager(aNode); aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER); } if (aNode->IsElement()) { nsIDocument* ownerDoc = aNode->OwnerDoc(); Element* elem = aNode->AsElement(); ownerDoc->ClearBoxObjectFor(elem); NS_ASSERTION(aNode->HasFlag(NODE_FORCE_XBL_BINDINGS) || !elem->GetXBLBinding(), "Non-forced node has binding on destruction"); // if NODE_FORCE_XBL_BINDINGS is set, the node might still have a binding // attached if (aNode->HasFlag(NODE_FORCE_XBL_BINDINGS) && ownerDoc->BindingManager()) { ownerDoc->BindingManager()->RemovedFromDocument(elem, ownerDoc); } } aNode->ReleaseWrapper(aNode); FragmentOrElement::RemoveBlackMarkedNode(aNode); }