Title: [106613] trunk
Revision
106613
Author
[email protected]
Date
2012-02-02 18:47:04 -0800 (Thu, 02 Feb 2012)

Log Message

StyleRecalc should occur when shadow root exists and light children are changed.
https://bugs.webkit.org/show_bug.cgi?id=76262

Patch by Shinya Kawanaka <[email protected]> on 2012-02-02
Reviewed by Hajime Morita.

Source/WebCore:

When light children is changed, the element included in HTMLContentElement may also be changed.
So we have to recalculate inclusion of content element again.

Test: fast/dom/shadow/shadow-contents-fallback-dynamic.html

* dom/Element.cpp:
(WebCore::Element::childrenChanged):

LayoutTests:

Tests for dynamic content fallback.
Also, unnecessary RenderText objects in previous test expectations were removed.

* fast/dom/shadow/shadow-contents-fallback-dynamic-expected.txt: Added.
* fast/dom/shadow/shadow-contents-fallback-dynamic.html: Added.
* platform/chromium-win/fast/html/details-remove-child-2-expected.txt:
* platform/gtk/fast/html/details-remove-child-2-expected.txt:
* platform/mac/fast/html/details-remove-child-2-expected.txt:
* platform/qt/fast/html/details-remove-child-2-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (106612 => 106613)


--- trunk/LayoutTests/ChangeLog	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/LayoutTests/ChangeLog	2012-02-03 02:47:04 UTC (rev 106613)
@@ -1,3 +1,20 @@
+2012-02-02  Shinya Kawanaka  <[email protected]>
+
+        StyleRecalc should occur when shadow root exists and light children are changed.
+        https://bugs.webkit.org/show_bug.cgi?id=76262
+
+        Reviewed by Hajime Morita.
+
+        Tests for dynamic content fallback.
+        Also, unnecessary RenderText objects in previous test expectations were removed.
+
+        * fast/dom/shadow/shadow-contents-fallback-dynamic-expected.txt: Added.
+        * fast/dom/shadow/shadow-contents-fallback-dynamic.html: Added.
+        * platform/chromium-win/fast/html/details-remove-child-2-expected.txt:
+        * platform/gtk/fast/html/details-remove-child-2-expected.txt:
+        * platform/mac/fast/html/details-remove-child-2-expected.txt:
+        * platform/qt/fast/html/details-remove-child-2-expected.txt:
+
 2012-02-02  Raymond Toy  <[email protected]>
 
         noteGrainOn needs more tests

Added: trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic-expected.txt (0 => 106613)


--- trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic-expected.txt	2012-02-03 02:47:04 UTC (rev 106613)
@@ -0,0 +1,26 @@
+testAppendFallback
+PASS
+testAppendFallbackDeep
+PASS
+testRemoveFallback
+PASS
+testRemoveFallbackDeep
+PASS
+testRemove1
+PASS
+testRemove2
+PASS
+testRemove3
+PASS
+testReplaceFallback
+PASS
+testFallbackContentChanged
+PASS
+testComplexAppend
+PASS
+testComplexRemove
+PASS
+testComplexReplace
+PASS
+TEST COMPLETED
+

Added: trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic.html (0 => 106613)


--- trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-contents-fallback-dynamic.html	2012-02-03 02:47:04 UTC (rev 106613)
@@ -0,0 +1,401 @@
+ <!DOCTYPE html>
+<html>
+<head>
+<style>
+/* relative positioning ensures underlying RenderLayer */
+.container {
+    position: relative;
+}
+
+.span {
+    display: boxed-inline;
+    margin: 2px;
+    border: solid;
+}
+</style>
+<script>
+function log(message) {
+    document.getElementById('console').innerHTML += (message + "\n");
+}
+
+function removeAllChildren(elem) {
+    while (elem.firstChild)
+        elem.removeChild(elem.firstChild);
+}
+
+function cleanUp() {
+    removeAllChildren(document.getElementById('actual-container'));
+    removeAllChildren(document.getElementById('expect-container'));
+}
+
+function removeContainerLines(text) {
+    var lines = text.split('\n');
+    lines.splice(0, 2);
+    return lines.join('\n');
+}
+
+function check() {
+    var refContainerRenderTree = internals.elementRenderTreeAsText(document.getElementById('expect-container'));
+    var refRenderTree = removeContainerLines(refContainerRenderTree);
+
+    var targetContainerRenderTree = internals.elementRenderTreeAsText(document.getElementById('actual-container'));
+    var targetRenderTree = removeContainerLines(targetContainerRenderTree);
+
+    if (targetRenderTree == refRenderTree)
+        log("PASS");
+    else {
+        log("FAIL");
+        log("Expected: ");
+        log(refRenderTree);
+        log("Actual: ");
+        log(targetRenderTree);
+    }
+}
+
+function createSpanWithText(text) {
+    var span = document.createElement('span');
+    span.appendChild(document.createTextNode(text));
+    return span;
+}
+
+function appendShadow(target, select) {
+    var root = internals.ensureShadowRoot(target);
+
+    var content = internals.createContentElement(document);
+    content.setAttribute('select', select);
+    content.appendChild(createSpanWithText("FALLBACK"));
+
+    root.appendChild(document.createTextNode("{SHADOW: "));
+    root.appendChild(content);
+    root.appendChild(document.createTextNode("}"));
+}
+
+function appendShadowDeep(target, select) {
+    var root = internals.ensureShadowRoot(target);
+
+    var child = document.createElement("span");
+    {
+        var content = internals.createContentElement(document);
+        content.setAttribute('select', select);
+        content.appendChild(createSpanWithText("FALLBACK"));
+
+        child.appendChild(document.createTextNode("{INNER: "));
+        child.appendChild(content);
+        child.appendChild(document.createTextNode("}"));
+    }
+
+    root.appendChild(document.createTextNode("{SHADOW: "));
+    root.appendChild(child);
+    root.appendChild(document.createTextNode("}"));
+}
+
+function testAppendFallback(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span>content</span>";
+
+    appendShadow(target, "#append");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.innerHTML = "<span id='append'>appended</span>";
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>appended</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testAppendFallbackDeep(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span>content</span>";
+
+    appendShadowDeep(target, "#append-deep");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.innerHTML = "<span id='append-deep'>appended</span>";
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>{INNER: <span>appended</span>}</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testRemoveFallback(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='remove'>content</span>";
+
+    appendShadow(target, "#remove");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.innerHTML = "<span>content</span>"
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>FALLBACK</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testRemoveFallbackDeep(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='remove-deep'>content</span>";
+
+    appendShadowDeep(target, "#remove-deep");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.innerHTML = "<span>content</span>"
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>{INNER: <span>FALLBACK</span>}</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testRemove1(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='remove1-1'>content 1</span><span id='remove1-2'>content 2</span>";
+    appendShadow(target, "span");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.removeChild(document.getElementById('remove1-1'));
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>content 2</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testRemove2(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='testremove2-1'>content 1</span><span id='testremove2-2'>content 2</span>";
+    appendShadow(target, "span");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.removeChild(document.getElementById('testremove2-2'));
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>content 1</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testRemove3(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='testremove3-1'>content 1</span><span id='testremove3-2'>content 2</span>";
+    appendShadow(target, "span");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.removeChild(document.getElementById('testremove3-1'));
+            target.removeChild(document.getElementById('testremove3-2'));
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>FALLBACK</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testReplaceFallback(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span id='to-replace'>content</span>";
+
+    appendShadow(target, "#to-replace");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.innerHTML = "<span id='to-replace'>replaced</span>";
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>replaced</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testFallbackContentChanged(callIfDone) {
+    var target = document.createElement('div');
+    target.innerHTML = "<span>content</span>";
+
+    appendShadow(target, "#non-element");
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, callIfDone) {
+        return function() {
+            target.appendChild(createSpanWithText('appended content'));
+            document.getElementById('expect-container').innerHTML = "<div>{SHADOW: <span>FALLBACK</span>}</div>";
+            callIfDone();
+        };
+    })(target, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testComplexAppend(callIfDone) {
+    var target = document.createElement('div');
+    appendShadow(target, '#complex-1');
+
+    var selectContent = document.createElement('span');
+    selectContent.setAttribute('id', 'complex-1');
+    appendShadow(selectContent, 'span');
+
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+    target.appendChild(selectContent);
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, selectContent, callIfDone) {
+        return function() {
+            selectContent.appendChild(createSpanWithText('SELECTED'));
+            document.getElementById('expect-container').innerHTML =
+                "<div>{SHADOW: <span>{SHADOW: <span>SELECTED</span>}</span>}</div>";
+            callIfDone();
+        };
+    })(target, selectContent, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testComplexRemove(callIfDone) {
+    var target = document.createElement('div');
+    appendShadow(target, '#complex-2');
+
+    var selectContent = document.createElement('span');
+    selectContent.setAttribute('id', 'complex-2');
+    {
+        selectContent.appendChild(createSpanWithText('SELECTED'));
+    }
+    appendShadow(selectContent, 'span');
+
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+    target.appendChild(selectContent);
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, selectContent, callIfDone) {
+        return function() {
+            removeAllChildren(selectContent);
+            document.getElementById('expect-container').innerHTML =
+                "<div>{SHADOW: <span>{SHADOW: <span>FALLBACK</span>}</span>}</div>";
+            callIfDone();
+        };
+    })(target, selectContent, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+function testComplexReplace(callIfDone) {
+    var target = document.createElement('div');
+    appendShadow(target, '#complex-3');
+
+    var selectContent = document.createElement('span');
+    selectContent.setAttribute('id', 'complex-3');
+    {
+    }
+    appendShadow(selectContent, 'span');
+
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+    target.appendChild(selectContent);
+    target.appendChild(document.createTextNode('[WONT SELECTED]'));
+
+    document.getElementById('actual-container').appendChild(target);
+
+    var f = (function(target, selectContent, callIfDone) {
+        return function() {
+            removeAllChildren(selectContent);
+            selectContent.appendChild(createSpanWithText('REPLACED'));
+            document.getElementById('expect-container').innerHTML =
+                "<div>{SHADOW: <span>{SHADOW: <span>REPLACED</span>}</span>}</div>";
+            callIfDone();
+        };
+    })(target, selectContent, callIfDone);
+
+    setTimeout(f, 0);
+}
+
+var testFuncs = [
+    testAppendFallback,
+    testAppendFallbackDeep,
+    testRemoveFallback,
+    testRemoveFallbackDeep,
+    testRemove1,
+    testRemove2,
+    testRemove3,
+    testReplaceFallback,
+    testFallbackContentChanged,
+    testComplexAppend,
+    testComplexRemove,
+    testComplexReplace,
+
+];
+
+function doTestIfLeft() {
+    var test = testFuncs.shift();
+    if (test == null)
+        return doneTest();
+
+    var callIfDone = function() {
+        setTimeout(function() {
+            check();
+            cleanUp();
+            doTestIfLeft();
+        }, 0);
+    };
+
+    log(test.name);
+    test(callIfDone);
+}
+
+function doneTest() {
+    log("TEST COMPLETED");
+    layoutTestController.notifyDone();
+}
+
+function doTest() {
+    if (window.layoutTestController) {
+        layoutTestController.waitUntilDone();
+        layoutTestController.dumpAsText();
+    }
+
+    cleanUp();
+    doTestIfLeft();
+}
+</script>
+</head>
+<body _onload_="doTest()">
+
+<div id="actual-container" class="container"></div>
+<div id="expect-container" class="container"></div>
+<pre id="console"></pre>
+
+</body>
+</html>

Modified: trunk/LayoutTests/platform/chromium-win/fast/html/details-remove-child-2-expected.txt (106612 => 106613)


--- trunk/LayoutTests/platform/chromium-win/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/LayoutTests/platform/chromium-win/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:47:04 UTC (rev 106613)
@@ -9,6 +9,5 @@
           RenderText {#text} at (16,0) size 54x19
             text run at (16,0) width 54: "summary"
         RenderBlock (anonymous) at (0,20) size 784x20
-          RenderText {#text} at (0,0) size 0x0
           RenderText {#text} at (0,0) size 150x19
             text run at (0,0) width 150: "should have no bold test."

Modified: trunk/LayoutTests/platform/gtk/fast/html/details-remove-child-2-expected.txt (106612 => 106613)


--- trunk/LayoutTests/platform/gtk/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/LayoutTests/platform/gtk/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:47:04 UTC (rev 106613)
@@ -9,6 +9,5 @@
           RenderText {#text} at (16,0) size 60x17
             text run at (16,0) width 60: "summary"
         RenderBlock (anonymous) at (0,18) size 784x18
-          RenderText {#text} at (0,0) size 0x0
           RenderText {#text} at (0,0) size 160x17
             text run at (0,0) width 160: "should have no bold test."

Modified: trunk/LayoutTests/platform/mac/fast/html/details-remove-child-2-expected.txt (106612 => 106613)


--- trunk/LayoutTests/platform/mac/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/LayoutTests/platform/mac/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:47:04 UTC (rev 106613)
@@ -9,6 +9,5 @@
           RenderText {#text} at (16,0) size 58x18
             text run at (16,0) width 58: "summary"
         RenderBlock (anonymous) at (0,18) size 784x18
-          RenderText {#text} at (0,0) size 0x0
           RenderText {#text} at (0,0) size 157x18
             text run at (0,0) width 157: "should have no bold test."

Modified: trunk/LayoutTests/platform/qt/fast/html/details-remove-child-2-expected.txt (106612 => 106613)


--- trunk/LayoutTests/platform/qt/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/LayoutTests/platform/qt/fast/html/details-remove-child-2-expected.txt	2012-02-03 02:47:04 UTC (rev 106613)
@@ -9,6 +9,5 @@
           RenderText {#text} at (16,0) size 65x21
             text run at (16,0) width 65: "summary"
         RenderBlock (anonymous) at (0,21) size 784x21
-          RenderText {#text} at (0,0) size 0x0
           RenderText {#text} at (0,0) size 177x21
             text run at (0,0) width 177: "should have no bold test."

Modified: trunk/Source/WebCore/ChangeLog (106612 => 106613)


--- trunk/Source/WebCore/ChangeLog	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/Source/WebCore/ChangeLog	2012-02-03 02:47:04 UTC (rev 106613)
@@ -1,3 +1,18 @@
+2012-02-02  Shinya Kawanaka  <[email protected]>
+
+        StyleRecalc should occur when shadow root exists and light children are changed.
+        https://bugs.webkit.org/show_bug.cgi?id=76262
+
+        Reviewed by Hajime Morita.
+
+        When light children is changed, the element included in HTMLContentElement may also be changed.
+        So we have to recalculate inclusion of content element again.
+
+        Test: fast/dom/shadow/shadow-contents-fallback-dynamic.html
+
+        * dom/Element.cpp:
+        (WebCore::Element::childrenChanged):
+
 2012-02-02  Ami Fischman  <[email protected]>
 
         Avoid crashing renderer when GPU process dies by not caching textures between video frames.

Modified: trunk/Source/WebCore/dom/Element.cpp (106612 => 106613)


--- trunk/Source/WebCore/dom/Element.cpp	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/Source/WebCore/dom/Element.cpp	2012-02-03 02:47:04 UTC (rev 106613)
@@ -1359,6 +1359,11 @@
         checkForEmptyStyleChange(this, renderStyle());
     else
         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
+
+    if (hasRareData()) {
+        if (ShadowRoot* root = shadowRoot())
+            root->hostChildrenChanged();
+    }
 }
 
 void Element::beginParsingChildren()

Modified: trunk/Source/WebCore/dom/ShadowRoot.cpp (106612 => 106613)


--- trunk/Source/WebCore/dom/ShadowRoot.cpp	2012-02-03 02:40:49 UTC (rev 106612)
+++ trunk/Source/WebCore/dom/ShadowRoot.cpp	2012-02-03 02:47:04 UTC (rev 106613)
@@ -142,8 +142,9 @@
 {
     if (!hasContentElement())
         return;
+
     // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle().
-    setNeedsStyleRecalc();
+    setNeedsReattachHostChildrenAndShadow();
 }
 
 bool ShadowRoot::isInclusionSelectorActive() const
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to