Title: [126131] trunk
Revision
126131
Author
morr...@google.com
Date
2012-08-20 21:21:28 -0700 (Mon, 20 Aug 2012)

Log Message

load event shouldn't fired during node insertion traversals.
https://bugs.webkit.org/show_bug.cgi?id=94447

Reviewed by Ryosuke Niwa.

Source/WebCore:

HTMLFrameElementBase::didNotifyDescendantInsertions() with empty @src
can trigger a load event during ChildNodeInsertionNotifier
traversal, whose handler can make DOM tree state inconsistent.

This change introduces a post traversal hook,
didNotifySubtreeInsertions(), for the insertion traversal and
replaces the problematic didNotifyDescendantInsertions() with it.

Since didNotifySubtreeInsertions() is invoked after the traversal,
it is safe for event handlers to mutate the tree.

Test: fast/frames/iframe-onload-and-domnodeinserted.html

* dom/ContainerNodeAlgorithms.h:
(ChildNodeInsertionNotifier): Added a post subtree notification.
(WebCore::ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument):
(WebCore::ChildNodeInsertionNotifier::notify):
* dom/Node.h:
(WebCore::Node::didNotifySubtreeInsertions): Newly added.
* html/HTMLFrameElementBase.cpp:
(WebCore::HTMLFrameElementBase::insertedInto): Now returns InsertionShouldCallDidNotifySubtreeInsertions
(WebCore::HTMLFrameElementBase::didNotifySubtreeInsertions): Replaced didNotifyDescendantInsertions()
* html/HTMLFrameElementBase.h:
(HTMLFrameElementBase):

LayoutTests:

* fast/frames/iframe-onload-and-domnodeinserted-expected.txt: Added.
* fast/frames/iframe-onload-and-domnodeinserted.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (126130 => 126131)


--- trunk/LayoutTests/ChangeLog	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/LayoutTests/ChangeLog	2012-08-21 04:21:28 UTC (rev 126131)
@@ -1,3 +1,13 @@
+2012-08-20  MORITA Hajime  <morr...@google.com>
+
+        load event shouldn't fired during node insertion traversals.
+        https://bugs.webkit.org/show_bug.cgi?id=94447
+
+        Reviewed by Ryosuke Niwa.
+
+        * fast/frames/iframe-onload-and-domnodeinserted-expected.txt: Added.
+        * fast/frames/iframe-onload-and-domnodeinserted.html: Added.
+
 2012-08-20  Shinya Kawanaka  <shin...@chromium.org>
 
         ShadowRoot.cloneNode() must always throw a DATA_CLONE_ERR exception.

Added: trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt (0 => 126131)


--- trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt	2012-08-21 04:21:28 UTC (rev 126131)
@@ -0,0 +1,11 @@
+This test ensures that any tree mutation in the load event handler cannot harm the tree consistency.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS loadEventFired is true
+PASS unless crash.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Property changes on: trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted.html (0 => 126131)


--- trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted.html	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted.html	2012-08-21 04:21:28 UTC (rev 126131)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<div id="g"></div>
+<script>
+description("This test ensures that any tree mutation in the load event handler cannot harm the tree consistency.")
+var docElement = document.documentElement;
+
+textareaElement = document.createElement("textarea");
+iframeElement = document.createElement("iframe");
+
+var loadEventFired = false;
+textareaElement.appendChild(iframeElement);
+iframeElement.addEventListener("load", function () { iframeElement.innerHTML = "X"; loadEventFired = true; }, false);
+textareaElement.addEventListener("DOMNodeInserted", function () { document.implementation.createDocument("", "", null).adoptNode(textareaElement) }, false);
+document.documentElement.appendChild(textareaElement); // The DOMNodeInserted event is triggered here through innerHTML = "X"
+document.getElementById("g").appendChild(textareaElement);
+shouldBeTrue("loadEventFired");
+debug("PASS unless crash.");
+</script>
+<script src=""
+</body>
+</html>
Property changes on: trunk/LayoutTests/fast/frames/iframe-onload-and-domnodeinserted.html
___________________________________________________________________

Added: svn:eol-style

Modified: trunk/Source/WebCore/ChangeLog (126130 => 126131)


--- trunk/Source/WebCore/ChangeLog	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/Source/WebCore/ChangeLog	2012-08-21 04:21:28 UTC (rev 126131)
@@ -1,3 +1,35 @@
+2012-08-20  MORITA Hajime  <morr...@google.com>
+
+        load event shouldn't fired during node insertion traversals.
+        https://bugs.webkit.org/show_bug.cgi?id=94447
+
+        Reviewed by Ryosuke Niwa.
+
+        HTMLFrameElementBase::didNotifyDescendantInsertions() with empty @src
+        can trigger a load event during ChildNodeInsertionNotifier
+        traversal, whose handler can make DOM tree state inconsistent.
+
+        This change introduces a post traversal hook,
+        didNotifySubtreeInsertions(), for the insertion traversal and
+        replaces the problematic didNotifyDescendantInsertions() with it.
+
+        Since didNotifySubtreeInsertions() is invoked after the traversal,
+        it is safe for event handlers to mutate the tree.
+
+        Test: fast/frames/iframe-onload-and-domnodeinserted.html
+
+        * dom/ContainerNodeAlgorithms.h:
+        (ChildNodeInsertionNotifier): Added a post subtree notification.
+        (WebCore::ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument):
+        (WebCore::ChildNodeInsertionNotifier::notify):
+        * dom/Node.h:
+        (WebCore::Node::didNotifySubtreeInsertions): Newly added.
+        * html/HTMLFrameElementBase.cpp:
+        (WebCore::HTMLFrameElementBase::insertedInto): Now returns InsertionShouldCallDidNotifySubtreeInsertions
+        (WebCore::HTMLFrameElementBase::didNotifySubtreeInsertions): Replaced didNotifyDescendantInsertions()
+        * html/HTMLFrameElementBase.h:
+        (HTMLFrameElementBase):
+
 2012-08-20  Shinya Kawanaka  <shin...@chromium.org> 
 
         Regression(r126127): Build break on multiple platforms

Modified: trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h (126130 => 126131)


--- trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h	2012-08-21 04:21:28 UTC (rev 126131)
@@ -46,6 +46,7 @@
     void notifyNodeInsertedIntoTree(ContainerNode*);
 
     ContainerNode* m_insertionPoint;
+    Vector< RefPtr<Node> > m_postInsertionNotificationTargets;
 };
 
 class ChildNodeRemovalNotifier {
@@ -197,8 +198,16 @@
     if (node->isContainerNode())
         notifyDescendantInsertedIntoDocument(toContainerNode(node));
 
-    if (request == Node::InsertionShouldCallDidNotifyDescendantInsertions)
+    switch (request) {
+    case Node::InsertionDone:
+        break;
+    case Node::InsertionShouldCallDidNotifyDescendantInsertions:
         node->didNotifyDescendantInsertions(m_insertionPoint);
+        break;
+    case Node::InsertionShouldCallDidNotifySubtreeInsertions:
+        m_postInsertionNotificationTargets.append(node);
+        break;
+    }
 }
 
 inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode* node)
@@ -235,6 +244,9 @@
         notifyNodeInsertedIntoDocument(node);
     else if (node->isContainerNode())
         notifyNodeInsertedIntoTree(toContainerNode(node));
+
+    for (size_t i = 0; i < m_postInsertionNotificationTargets.size(); ++i)
+        m_postInsertionNotificationTargets[i]->didNotifySubtreeInsertions(m_insertionPoint);
 }
 
 

Modified: trunk/Source/WebCore/dom/Node.h (126130 => 126131)


--- trunk/Source/WebCore/dom/Node.h	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/Source/WebCore/dom/Node.h	2012-08-21 04:21:28 UTC (rev 126131)
@@ -547,11 +547,13 @@
     //
     enum InsertionNotificationRequest {
         InsertionDone,
-        InsertionShouldCallDidNotifyDescendantInsertions
+        InsertionShouldCallDidNotifyDescendantInsertions,
+        InsertionShouldCallDidNotifySubtreeInsertions
     };
 
     virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint);
     virtual void didNotifyDescendantInsertions(ContainerNode*) { }
+    virtual void didNotifySubtreeInsertions(ContainerNode*) { }
 
     // Notifies the node that it is no longer part of the tree.
     //

Modified: trunk/Source/WebCore/html/HTMLFrameElementBase.cpp (126130 => 126131)


--- trunk/Source/WebCore/html/HTMLFrameElementBase.cpp	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/Source/WebCore/html/HTMLFrameElementBase.cpp	2012-08-21 04:21:28 UTC (rev 126131)
@@ -157,11 +157,11 @@
 {
     HTMLFrameOwnerElement::insertedInto(insertionPoint);
     if (insertionPoint->inDocument())
-        return InsertionShouldCallDidNotifyDescendantInsertions;
+        return InsertionShouldCallDidNotifySubtreeInsertions;
     return InsertionDone;
 }
 
-void HTMLFrameElementBase::didNotifyDescendantInsertions(ContainerNode* insertionPoint)
+void HTMLFrameElementBase::didNotifySubtreeInsertions(ContainerNode* insertionPoint)
 {
     ASSERT_UNUSED(insertionPoint, insertionPoint->inDocument());
 

Modified: trunk/Source/WebCore/html/HTMLFrameElementBase.h (126130 => 126131)


--- trunk/Source/WebCore/html/HTMLFrameElementBase.h	2012-08-21 03:57:42 UTC (rev 126130)
+++ trunk/Source/WebCore/html/HTMLFrameElementBase.h	2012-08-21 04:21:28 UTC (rev 126131)
@@ -51,7 +51,7 @@
 
     virtual void parseAttribute(const Attribute&) OVERRIDE;
     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
-    virtual void didNotifyDescendantInsertions(ContainerNode*) OVERRIDE;
+    virtual void didNotifySubtreeInsertions(ContainerNode*) OVERRIDE;
     virtual void attach();
 
 private:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to