Diff
Modified: branches/safari-534.54-branch/LayoutTests/ChangeLog (103422 => 103423)
--- branches/safari-534.54-branch/LayoutTests/ChangeLog 2011-12-21 19:42:20 UTC (rev 103422)
+++ branches/safari-534.54-branch/LayoutTests/ChangeLog 2011-12-21 19:45:52 UTC (rev 103423)
@@ -1,5 +1,20 @@
2011-12-21 Lucas Forschler <lforsch...@apple.com>
+ Merge 93521
+
+ 2011-08-22 Nate Chapin <jap...@chromium.org>
+
+ Test for https://bugs.webkit.org/show_bug.cgi?id=64741.
+
+ Reviewed by Adam Barth.
+
+ * fast/loader/document-destruction-within-unload-expected.txt: Added.
+ * fast/loader/document-destruction-within-unload.html: Added.
+ * fast/loader/resources/document-destruction-within-unload-iframe.html: Added.
+ * fast/loader/resources/document-destruction-within-unload.svg: Added.
+
+2011-12-21 Lucas Forschler <lforsch...@apple.com>
+
Merge 93514
2011-08-22 Abhishek Arya <infe...@chromium.org>
Copied: branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt (from rev 93521, trunk/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt) (0 => 103423)
--- branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt (rev 0)
+++ branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt 2011-12-21 19:45:52 UTC (rev 103423)
@@ -0,0 +1,2 @@
+
+For the test to pass there should be no crash.
Copied: branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload.html (from rev 93521, trunk/LayoutTests/fast/loader/document-destruction-within-unload.html) (0 => 103423)
--- branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload.html (rev 0)
+++ branches/safari-534.54-branch/LayoutTests/fast/loader/document-destruction-within-unload.html 2011-12-21 19:45:52 UTC (rev 103423)
@@ -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/safari-534.54-branch/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 => 103423)
--- branches/safari-534.54-branch/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html (rev 0)
+++ branches/safari-534.54-branch/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html 2011-12-21 19:45:52 UTC (rev 103423)
@@ -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/safari-534.54-branch/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg (from rev 93521, trunk/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg) (0 => 103423)
--- branches/safari-534.54-branch/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg (rev 0)
+++ branches/safari-534.54-branch/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg 2011-12-21 19:45:52 UTC (rev 103423)
@@ -0,0 +1,2 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+</svg>
Modified: branches/safari-534.54-branch/Source/WebCore/ChangeLog (103422 => 103423)
--- branches/safari-534.54-branch/Source/WebCore/ChangeLog 2011-12-21 19:42:20 UTC (rev 103422)
+++ branches/safari-534.54-branch/Source/WebCore/ChangeLog 2011-12-21 19:45:52 UTC (rev 103423)
@@ -1,5 +1,27 @@
2011-12-21 Lucas Forschler <lforsch...@apple.com>
+ Merge 93521
+
+ 2011-08-22 Nate Chapin <jap...@chromium.org>
+
+ Unload events can crash us when they blank out
+ a parent frame.
+ https://bugs.webkit.org/show_bug.cgi?id=64741
+
+ Reviewed by Adam Barth.
+
+ Test: fast/loader/document-destruction-within-unload.html
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::stopLoading): Prevent unload events
+ from going into infinite recursion.
+ (WebCore::FrameLoader::setDocumentLoader): Ensure we don't
+ let set m_documentLoader to a DocumentLoader with a null Frame*.
+ (WebCore::FrameLoader::detachChildren): Save off a vector of
+ children to detach, rather than doing it inline.
+
+2011-12-21 Lucas Forschler <lforsch...@apple.com>
+
Merge 93514
2011-08-22 Abhishek Arya <infe...@chromium.org>
Modified: branches/safari-534.54-branch/Source/WebCore/loader/FrameLoader.cpp (103422 => 103423)
--- branches/safari-534.54-branch/Source/WebCore/loader/FrameLoader.cpp 2011-12-21 19:42:20 UTC (rev 103422)
+++ branches/safari-534.54-branch/Source/WebCore/loader/FrameLoader.cpp 2011-12-21 19:45:52 UTC (rev 103423)
@@ -380,7 +380,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());
@@ -1890,6 +1890,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)
@@ -2597,12 +2611,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)