зеркало из https://github.com/mozilla/pjs.git
Bug 348156: Don't rely on UnbindFromTree to break cycles since that puts us in an inconsistent state. r/sr=jst
This commit is contained in:
Родитель
d97e408be2
Коммит
63dc8fc814
|
@ -5433,26 +5433,17 @@ nsDocument::Destroy()
|
||||||
if (mIsGoingAway)
|
if (mIsGoingAway)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PRInt32 count = mChildren.ChildCount();
|
|
||||||
|
|
||||||
mIsGoingAway = PR_TRUE;
|
mIsGoingAway = PR_TRUE;
|
||||||
DestroyLinkMap();
|
|
||||||
for (PRInt32 indx = 0; indx < count; ++indx) {
|
PRUint32 i, count = mChildren.ChildCount();
|
||||||
// XXXbz what we _should_ do here is to clear mChildren and null out
|
for (i = 0; i < count; ++i) {
|
||||||
// mRootContent. If we did this (or at least the latter), we could remove
|
nsNodeUtils::DestroySubtree(mChildren.ChildAt(i));
|
||||||
// the silly null-checks in nsHTMLDocument::MatchLinks. Unfortunately,
|
|
||||||
// doing that introduces several problems:
|
|
||||||
// 1) Focus issues (see bug 341730). The fix for bug 303260 may fix these.
|
|
||||||
// 2) Crashes in OnPageHide if it fires after Destroy. See bug 303260
|
|
||||||
// comments 9 and 10.
|
|
||||||
// So we're just creating an inconsistent DOM for now and hoping. :(
|
|
||||||
mChildren.ChildAt(indx)->UnbindFromTree();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mLayoutHistoryState = nsnull;
|
mLayoutHistoryState = nsnull;
|
||||||
|
|
||||||
nsContentList::OnDocumentDestroy(this);
|
nsContentList::OnDocumentDestroy(this);
|
||||||
delete mContentWrapperHash;
|
|
||||||
mContentWrapperHash = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsILayoutHistoryState>
|
already_AddRefed<nsILayoutHistoryState>
|
||||||
|
|
|
@ -3271,8 +3271,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
|
||||||
// Unlink any DOM slots of interest.
|
// Unlink any DOM slots of interest.
|
||||||
{
|
{
|
||||||
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
|
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
|
||||||
if (slots)
|
if (slots) {
|
||||||
slots->mAttributeMap = nsnull;
|
slots->mAttributeMap = nsnull;
|
||||||
|
if (tmp->IsNodeOfType(nsINode::eXUL))
|
||||||
|
NS_IF_RELEASE(slots->mControllers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
|
|
@ -677,3 +677,27 @@ nsNodeUtils::UnlinkUserData(nsINode *aNode)
|
||||||
DOM_USER_DATA_HANDLER);
|
DOM_USER_DATA_HANDLER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void
|
||||||
|
nsNodeUtils::DestroySubtree(nsIContent* aRoot)
|
||||||
|
{
|
||||||
|
nsXULElement* xul = nsXULElement::FromContent(aRoot);
|
||||||
|
if (xul) {
|
||||||
|
nsGenericElement::nsDOMSlots* slots = xul->GetExistingDOMSlots();
|
||||||
|
if (slots) {
|
||||||
|
NS_IF_RELEASE(slots->mControllers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIDocument *document = aRoot->GetOwnerDoc();
|
||||||
|
if (document) {
|
||||||
|
document->BindingManager()->ChangeDocumentFor(aRoot, document, nsnull);
|
||||||
|
document->ClearBoxObjectFor(aRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRUint32 i, count = aRoot->GetChildCount();
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
DestroySubtree(aRoot->GetChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -258,6 +258,14 @@ public:
|
||||||
*/
|
*/
|
||||||
static void UnlinkUserData(nsINode *aNode);
|
static void UnlinkUserData(nsINode *aNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove neccesary components of all nodes in a subtree to avoid leaking.
|
||||||
|
* So far this removes XBL bindings and XUL controllers.
|
||||||
|
*
|
||||||
|
* @param aRoot the node that is the root of the subtree to clear.
|
||||||
|
*/
|
||||||
|
static void DestroySubtree(nsIContent* aRoot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend PLDHashOperator PR_CALLBACK
|
friend PLDHashOperator PR_CALLBACK
|
||||||
AdoptFunc(nsAttrHashKey::KeyType aKey, nsIDOMNode *aData, void* aUserArg);
|
AdoptFunc(nsAttrHashKey::KeyType aKey, nsIDOMNode *aData, void* aUserArg);
|
||||||
|
|
|
@ -363,7 +363,7 @@ protected:
|
||||||
/** The request currently being submitted */
|
/** The request currently being submitted */
|
||||||
nsCOMPtr<nsIRequest> mSubmittingRequest;
|
nsCOMPtr<nsIRequest> mSubmittingRequest;
|
||||||
/** The web progress object we are currently listening to */
|
/** The web progress object we are currently listening to */
|
||||||
nsCOMPtr<nsIWebProgress> mWebProgress;
|
nsWeakPtr mWebProgress;
|
||||||
|
|
||||||
/** The default submit element -- WEAK */
|
/** The default submit element -- WEAK */
|
||||||
nsIFormControl* mDefaultSubmitElement;
|
nsIFormControl* mDefaultSubmitElement;
|
||||||
|
@ -1057,10 +1057,12 @@ nsHTMLFormElement::SubmitSubmission(nsIFormSubmission* aFormSubmission)
|
||||||
PRBool pending = PR_FALSE;
|
PRBool pending = PR_FALSE;
|
||||||
mSubmittingRequest->IsPending(&pending);
|
mSubmittingRequest->IsPending(&pending);
|
||||||
if (pending && !schemeIsJavaScript) {
|
if (pending && !schemeIsJavaScript) {
|
||||||
mWebProgress = do_GetInterface(docShell);
|
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||||
NS_ASSERTION(mWebProgress, "nsIDocShell not converted to nsIWebProgress!");
|
NS_ASSERTION(webProgress, "nsIDocShell not converted to nsIWebProgress!");
|
||||||
rv = mWebProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL);
|
rv = webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL);
|
||||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||||
|
mWebProgress = do_GetWeakReference(webProgress);
|
||||||
|
NS_ASSERTION(mWebProgress, "can't hold weak ref to webprogress!");
|
||||||
} else {
|
} else {
|
||||||
ForgetCurrentSubmission();
|
ForgetCurrentSubmission();
|
||||||
}
|
}
|
||||||
|
@ -1632,10 +1634,11 @@ nsHTMLFormElement::ForgetCurrentSubmission()
|
||||||
mNotifiedObservers = PR_FALSE;
|
mNotifiedObservers = PR_FALSE;
|
||||||
mIsSubmitting = PR_FALSE;
|
mIsSubmitting = PR_FALSE;
|
||||||
mSubmittingRequest = nsnull;
|
mSubmittingRequest = nsnull;
|
||||||
if (mWebProgress) {
|
nsCOMPtr<nsIWebProgress> webProgress = do_QueryReferent(mWebProgress);
|
||||||
mWebProgress->RemoveProgressListener(this);
|
if (webProgress) {
|
||||||
mWebProgress = nsnull;
|
webProgress->RemoveProgressListener(this);
|
||||||
}
|
}
|
||||||
|
mWebProgress = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIWebProgressListener
|
// nsIWebProgressListener
|
||||||
|
|
|
@ -107,6 +107,13 @@ nsXTFElementWrapper::Init()
|
||||||
NS_IMPL_ADDREF_INHERITED(nsXTFElementWrapper, nsXTFElementWrapperBase)
|
NS_IMPL_ADDREF_INHERITED(nsXTFElementWrapper, nsXTFElementWrapperBase)
|
||||||
NS_IMPL_RELEASE_INHERITED(nsXTFElementWrapper, nsXTFElementWrapperBase)
|
NS_IMPL_RELEASE_INHERITED(nsXTFElementWrapper, nsXTFElementWrapperBase)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXTFElementWrapper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXTFElementWrapper,
|
||||||
|
nsXTFElementWrapperBase)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXTFElement)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAttributeHandler)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXTFElementWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
nsXTFElementWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
|
|
||||||
// nsISupports interface
|
// nsISupports interface
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXTFElementWrapper,
|
||||||
|
nsXTFElementWrapperBase)
|
||||||
|
|
||||||
// nsIXTFElementWrapper
|
// nsIXTFElementWrapper
|
||||||
NS_DECL_NSIXTFELEMENTWRAPPER
|
NS_DECL_NSIXTFELEMENTWRAPPER
|
||||||
|
|
Загрузка…
Ссылка в новой задаче