| Index: Source/WebCore/loader/FrameLoader.cpp
|
| ===================================================================
|
| --- Source/WebCore/loader/FrameLoader.cpp (revision 93735)
|
| +++ Source/WebCore/loader/FrameLoader.cpp (working copy)
|
| @@ -367,7 +367,7 @@
|
| Node* currentFocusedNode = m_frame->document()->focusedNode();
|
| if (currentFocusedNode)
|
| currentFocusedNode->aboutToUnload();
|
| - if (m_frame->domWindow()) {
|
| + if (m_frame->domWindow() && m_pageDismissalEventBeingDispatched == NoDismissal) {
|
| if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
|
| m_pageDismissalEventBeingDispatched = PageHideDismissal;
|
| m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
|
| @@ -1678,6 +1678,20 @@
|
| m_documentLoader->detachFromFrame();
|
|
|
| m_documentLoader = loader;
|
| +
|
| + // The following abomination is brought to you by the unload event.
|
| + // The detachChildren() call above may trigger a child frame's unload event,
|
| + // which could do something obnoxious like call document.write("") on
|
| + // the main frame, which results in detaching children while detaching children.
|
| + // This can cause the new m_documentLoader to be detached from its Frame*, but still
|
| + // be alive. To make matters worse, DocumentLoaders with a null Frame* aren't supposed
|
| + // to happen when they're still alive (and many places below us on the stack think the
|
| + // DocumentLoader is still usable). Ergo, we reattach loader to its Frame, and pretend
|
| + // like nothing ever happened.
|
| + if (m_documentLoader && !m_documentLoader->frame()) {
|
| + ASSERT(!m_documentLoader->isLoading());
|
| + m_documentLoader->setFrame(m_frame);
|
| + }
|
| }
|
|
|
| void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
|
| @@ -2348,12 +2362,14 @@
|
|
|
| void FrameLoader::detachChildren()
|
| {
|
| - // FIXME: Is it really necessary to do this in reverse order?
|
| - Frame* previous;
|
| - for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
|
| - previous = child->tree()->previousSibling();
|
| - child->loader()->detachFromParent();
|
| - }
|
| + typedef Vector<RefPtr<Frame> > FrameVector;
|
| + FrameVector childrenToDetach;
|
| + childrenToDetach.reserveCapacity(m_frame->tree()->childCount());
|
| + for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling())
|
| + childrenToDetach.append(child);
|
| + FrameVector::iterator end = childrenToDetach.end();
|
| + for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++)
|
| + (*it)->loader()->detachFromParent();
|
| }
|
|
|
| void FrameLoader::closeAndRemoveChild(Frame* child)
|
|
|