Title: [93736] branches/chromium/835

Diff

Copied: branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt (from rev 93521, trunk/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt) (0 => 93736)


--- branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt	                        (rev 0)
+++ branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt	2011-08-24 21:25:07 UTC (rev 93736)
@@ -0,0 +1,2 @@
+
+For the test to pass there should be no crash.

Copied: branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload.html (from rev 93521, trunk/LayoutTests/fast/loader/document-destruction-within-unload.html) (0 => 93736)


--- branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload.html	                        (rev 0)
+++ branches/chromium/835/LayoutTests/fast/loader/document-destruction-within-unload.html	2011-08-24 21:25:07 UTC (rev 93736)
@@ -0,0 +1,17 @@
+<html>
+<body>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function done() {
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+</script>
+<iframe src=""
+<p>For the test to pass there should be no crash.</p>
+</body>
+</html>

Copied: branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html (from rev 93521, trunk/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html) (0 => 93736)


--- branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html	                        (rev 0)
+++ branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html	2011-08-24 21:25:07 UTC (rev 93736)
@@ -0,0 +1,18 @@
+<html>
+<body>
+<script>
+function runTest() {
+    var test = document.getElementById('root').contentDocument;
+    test.firstChild.setAttribute('onunload', "parent.clearUs();");
+    location.reload();
+}
+
+function clearUs() {
+    document.write();
+    parent.done();
+}
+</script>
+<object data=""
+<object data="" id="root" _onload_="runTest();"></object>
+</body>
+</html>

Copied: branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg (from rev 93521, trunk/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg) (0 => 93736)


--- branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg	                        (rev 0)
+++ branches/chromium/835/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg	2011-08-24 21:25:07 UTC (rev 93736)
@@ -0,0 +1,2 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+</svg>

Modified: branches/chromium/835/Source/WebCore/loader/FrameLoader.cpp (93735 => 93736)


--- branches/chromium/835/Source/WebCore/loader/FrameLoader.cpp	2011-08-24 21:20:13 UTC (rev 93735)
+++ branches/chromium/835/Source/WebCore/loader/FrameLoader.cpp	2011-08-24 21:25:07 UTC (rev 93736)
@@ -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)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to