Title: [115897] trunk
Revision
115897
Author
ad...@chromium.org
Date
2012-05-02 15:04:15 -0700 (Wed, 02 May 2012)

Log Message

Childlist mutations in shadow DOM should be observable with MutationObservers
https://bugs.webkit.org/show_bug.cgi?id=85402

Reviewed by Ojan Vafai.

Source/WebCore:

Though Mutation Events are not supported in Shadow DOM,
MutationObservers are supposed to be. Due to a misplacement of the
ChildListMutationScope, they were erroneously getting skipped.

This patch moves code around to properly notify when childlist are
mutated in shadow DOM and covers that change with a new test.

Test: fast/mutation/shadow-dom.html

* dom/ContainerNode.cpp:
(WebCore::willRemoveChild): Handle notification of removal directly.
(WebCore::willRemoveChildren): ditto.
(WebCore::dispatchChildInsertionEvents): Remove notification of insertion.
(WebCore::dispatchChildRemovalEvents): Remove notification of removal.
(WebCore::updateTreeAfterInsertion): Handle notification of insertion directly.

LayoutTests:

Added test covering childList mutations as well as attribute and
characterData mutations (these were already working).

* fast/mutation/shadow-dom-expected.txt: Added.
* fast/mutation/shadow-dom.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (115896 => 115897)


--- trunk/LayoutTests/ChangeLog	2012-05-02 22:01:37 UTC (rev 115896)
+++ trunk/LayoutTests/ChangeLog	2012-05-02 22:04:15 UTC (rev 115897)
@@ -1,3 +1,16 @@
+2012-05-02  Adam Klein  <ad...@chromium.org>
+
+        Childlist mutations in shadow DOM should be observable with MutationObservers
+        https://bugs.webkit.org/show_bug.cgi?id=85402
+
+        Reviewed by Ojan Vafai.
+
+        Added test covering childList mutations as well as attribute and
+        characterData mutations (these were already working).
+
+        * fast/mutation/shadow-dom-expected.txt: Added.
+        * fast/mutation/shadow-dom.html: Added.
+
 2012-05-02  Eric Carlson  <eric.carl...@apple.com>
 
         Crash in WebCore::TextTrackList::remove

Added: trunk/LayoutTests/fast/mutation/shadow-dom-expected.txt (0 => 115897)


--- trunk/LayoutTests/fast/mutation/shadow-dom-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mutation/shadow-dom-expected.txt	2012-05-02 22:04:15 UTC (rev 115897)
@@ -0,0 +1,18 @@
+Test that MutationObservers operate in Shadow DOM
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Mutations in shadow DOM should have been observed:
+PASS mutations.length is 4
+PASS mutations[0].type is "attributes"
+PASS mutations[1].type is "childList"
+PASS mutations[2].type is "characterData"
+PASS mutations[3].type is "childList"
+
+Observing from outside shadow DOM should not see mutations in the shadow:
+PASS mutations is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/mutation/shadow-dom.html (0 => 115897)


--- trunk/LayoutTests/fast/mutation/shadow-dom.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mutation/shadow-dom.html	2012-05-02 22:04:15 UTC (rev 115897)
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<body>
+<input type="range">
+<script src=""
+<script>
+description('Test that MutationObservers operate in Shadow DOM');
+
+function doTest() {
+    function mutate(elt) {
+        elt.setAttribute('data-foo', 'bar');
+        elt.insertBefore(document.createTextNode('hello'), elt.firstChild);
+        elt.firstChild.textContent = 'goodbye';
+        elt.removeChild(elt.firstChild);
+    }
+
+    var shadowRoot = internals.shadowRoot(document.querySelector('input'));
+    var observer = new WebKitMutationObserver(function(mutations) {
+        window.mutations = mutations;
+    });
+
+    observer.observe(shadowRoot.firstChild, {attributes: true, childList: true, characterData: true, subtree: true});
+    mutate(shadowRoot.firstChild);
+
+    setTimeout(function() {
+        debug('Mutations in shadow DOM should have been observed:');
+        shouldBe('mutations.length', '4');
+        shouldBe('mutations[0].type', '"attributes"');
+        shouldBe('mutations[1].type', '"childList"');
+        shouldBe('mutations[2].type', '"characterData"');
+        shouldBe('mutations[3].type', '"childList"');
+        observer.disconnect();
+
+        window.mutations = null;
+        observer.observe(document, {attributes: true, childList: true, characterData: true, subtree: true});
+        mutate(shadowRoot.firstChild);
+        setTimeout(function() {
+            debug('\nObserving from outside shadow DOM should not see mutations in the shadow:');
+            shouldBeNull('mutations');
+            finishJSTest();
+        }, 0);
+    }, 0);
+}
+
+if (window.internals) {
+    doTest();
+    window.jsTestIsAsync = true;
+} else
+    testFailed('This test only runs in DRT');
+</script>
+<script src=""
+</body>

Modified: trunk/Source/WebCore/ChangeLog (115896 => 115897)


--- trunk/Source/WebCore/ChangeLog	2012-05-02 22:01:37 UTC (rev 115896)
+++ trunk/Source/WebCore/ChangeLog	2012-05-02 22:04:15 UTC (rev 115897)
@@ -1,3 +1,26 @@
+2012-05-02  Adam Klein  <ad...@chromium.org>
+
+        Childlist mutations in shadow DOM should be observable with MutationObservers
+        https://bugs.webkit.org/show_bug.cgi?id=85402
+
+        Reviewed by Ojan Vafai.
+
+        Though Mutation Events are not supported in Shadow DOM,
+        MutationObservers are supposed to be. Due to a misplacement of the
+        ChildListMutationScope, they were erroneously getting skipped.
+
+        This patch moves code around to properly notify when childlist are
+        mutated in shadow DOM and covers that change with a new test.
+
+        Test: fast/mutation/shadow-dom.html
+
+        * dom/ContainerNode.cpp:
+        (WebCore::willRemoveChild): Handle notification of removal directly.
+        (WebCore::willRemoveChildren): ditto.
+        (WebCore::dispatchChildInsertionEvents): Remove notification of insertion.
+        (WebCore::dispatchChildRemovalEvents): Remove notification of removal.
+        (WebCore::updateTreeAfterInsertion): Handle notification of insertion directly.
+
 2012-05-02  Eric Carlson  <eric.carl...@apple.com>
 
         Crash in WebCore::TextTrackList::remove

Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (115896 => 115897)


--- trunk/Source/WebCore/dom/ContainerNode.cpp	2012-05-02 22:01:37 UTC (rev 115896)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp	2012-05-02 22:04:15 UTC (rev 115897)
@@ -328,6 +328,12 @@
 
 static void willRemoveChild(Node* child)
 {
+#if ENABLE(MUTATION_OBSERVERS)
+    ASSERT(child->parentNode());
+    ChildListMutationScope(child->parentNode()).willRemoveChild(child);
+    child->notifyMutationObserversNodeWillDetach();
+#endif
+
     dispatchChildRemovalEvents(child);
     child->document()->nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
     child->willRemove();
@@ -346,6 +352,12 @@
 
     for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
         Node* child = it->get();
+
+#if ENABLE(MUTATION_OBSERVERS)
+        mutation.willRemoveChild(child);
+        child->notifyMutationObserversNodeWillDetach();
+#endif
+
         // fire removed from document mutation events.
         dispatchChildRemovalEvents(child);
         child->willRemove();
@@ -936,13 +948,6 @@
     RefPtr<Node> c = child;
     RefPtr<Document> document = child->document();
 
-#if ENABLE(MUTATION_OBSERVERS)
-    if (c->parentNode()) {
-        ChildListMutationScope mutation(c->parentNode());
-        mutation.childAdded(c.get());
-    }
-#endif
-
     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
 
@@ -967,14 +972,6 @@
     RefPtr<Node> c = child;
     RefPtr<Document> document = child->document();
 
-#if ENABLE(MUTATION_OBSERVERS)
-    if (c->parentNode()) {
-        ChildListMutationScope mutation(c->parentNode());
-        mutation.willRemoveChild(c.get());
-        c->notifyMutationObserversNodeWillDetach();
-    }
-#endif
-
     // dispatch pre-removal mutation events
     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
@@ -991,6 +988,10 @@
     ASSERT(parent->refCount());
     ASSERT(child->refCount());
 
+#if ENABLE(MUTATION_OBSERVERS)
+    ChildListMutationScope(parent).childAdded(child);
+#endif
+
     parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
 
     ChildNodeInsertionNotifier(parent).notify(child);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to