Slot elements should support fallback contents
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Oct 2015 20:36:34 +0000 (20:36 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Oct 2015 20:36:34 +0000 (20:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149701

Reviewed by Antti Koivisto.

Source/WebCore:

Following discussions on Github discussions [1] [2], we're adding the default rule of `display: contents`
on slot elements and making slot elements render its children when there are no assigned nodes [3].

Make these changes by attaching renderers on direct-children of slot elements when there are no assigned
nodes during render tree construction. Note `display: contents` will be aded in webkit.org/b/149439.

[1] https://github.com/w3c/webcomponents/issues/317
[2] https://github.com/w3c/webcomponents/issues/308
[3] https://github.com/w3c/webcomponents/issues/308#issuecomment-143655347

Tests: fast/shadow-dom/css-scoping-shadow-slot-fallback.html
       fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html

* style/StyleResolveTree.cpp:
(WebCore::Style::attachSlotAssignees):
(WebCore::Style::detachSlotAssignees):
(WebCore::Style::resolveSlotAssignees):

LayoutTests:

Added tests for fallback contents in slot elements. One of them could be safely submitted to CSS WG,
and the other one is a style recalc test.

* fast/shadow-dom/css-scoping-shadow-slot-fallback-expected.html: Added.
* fast/shadow-dom/css-scoping-shadow-slot-fallback.html: Added.
* fast/shadow-dom/shadow-layout-after-slot-fallback-changes-expected.html: Added.
* fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190430 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback-expected.html [new file with mode: 0644]
LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback.html [new file with mode: 0644]
LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes-expected.html [new file with mode: 0644]
LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/style/StyleResolveTree.cpp

index c3e5005..d3a9816 100644 (file)
@@ -1,3 +1,18 @@
+2015-10-01  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Slot elements should support fallback contents
+        https://bugs.webkit.org/show_bug.cgi?id=149701
+
+        Reviewed by Antti Koivisto.
+
+        Added tests for fallback contents in slot elements. One of them could be safely submitted to CSS WG,
+        and the other one is a style recalc test.
+
+        * fast/shadow-dom/css-scoping-shadow-slot-fallback-expected.html: Added.
+        * fast/shadow-dom/css-scoping-shadow-slot-fallback.html: Added.
+        * fast/shadow-dom/shadow-layout-after-slot-fallback-changes-expected.html: Added.
+        * fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html: Added.
+
 2015-10-01  Keith Miller  <keith_miller@apple.com>
 
         [ES6] Add TypedArray.prototype functionality.
diff --git a/LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback-expected.html b/LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback-expected.html
new file mode 100644 (file)
index 0000000..e704d24
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <p>Test passes if you see a single 100px by 100px green box below.</p>
+    <div style="width: 100px; height: 100px; background: green;"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback.html b/LayoutTests/fast/shadow-dom/css-scoping-shadow-slot-fallback.html
new file mode 100644 (file)
index 0000000..f35361c
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Scoping - slot element without distributed nodes must render its fallback content</title>
+    <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+    <link rel="match" href="reference/green-box.html"/>
+</head>
+<body>
+    <style>
+    my-host {
+        display: block;
+        background-color: red;
+        width: 100px;
+        height: 50px;
+    }
+    .red {
+        background-color: red;
+    }
+    .green {
+        background-color: green;
+    }
+    div {
+        width: 100px;
+        height: 50px;
+    }
+    slot {
+        border: solid 10px red;
+    }
+    </style>
+    <p>Test passes if you see a single 100px by 100px green box below.</p>
+    <my-host></my-host>
+    <div class="red"><slot><div class="green"></div></slot></div>
+    <script>
+
+    try {
+        var shadowHost = document.querySelector('my-host');
+        shadowRoot = shadowHost.attachShadow({mode: 'open'});
+        shadowRoot.innerHTML = '<slot style="border: solid 10px red;">'
+            + '<div style="width: 100%; height: 100%; background-color: green;"></div></slot>';
+    } catch (exception) {
+        document.body.appendChild(document.createTextNode(exception));
+    }
+
+    </script>
+</body>
+</html>
diff --git a/LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes-expected.html b/LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes-expected.html
new file mode 100644 (file)
index 0000000..e704d24
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <p>Test passes if you see a single 100px by 100px green box below.</p>
+    <div style="width: 100px; height: 100px; background: green;"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html b/LayoutTests/fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html
new file mode 100644 (file)
index 0000000..0057ebd
--- /dev/null
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>Test passes if you see a single 100px by 100px green box below.</p> 
+<my-host id="host1"><div style="background: red;">FAIL</div></my-host>
+<my-host id="host2"><div slot="foo" style="background: red;">FAIL</div></my-host>
+<my-host id="host3"></my-host>
+<my-host id="host4" style="background: red;"><slot></slot></my-host>
+<my-host id="host5" style="background: green;"><slot><div style="background: red;"></div></slot></my-host>
+<style>
+
+my-host {
+    display: block;
+    width: 100px;
+    height: 20px;
+    overflow: hidden;
+}
+
+my-host div {
+    width: 100%;
+    height: 100%;
+}
+
+</style>
+<script>
+
+function forceLayout() {
+    if (window.internals)
+        internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
+    else
+        document.querySelector('p').getBoundingClientRect();
+}
+
+try {
+    var host1 = document.getElementById('host1');
+    host1.attachShadow({mode: 'open'}).innerHTML = '<slot><div style="width: 100%; height: 100%; background-color: green;"></div></slot>';
+
+    var host2 = document.getElementById('host2');
+    host2.attachShadow({mode: 'open'}).innerHTML = '<slot name="foo"><div style="width: 100%; height: 100%; background-color: green;"></div></slot>';
+
+    var host3 = document.getElementById('host3');
+    host3.attachShadow({mode: 'open'}).innerHTML = '<slot>FAIL</slot>';
+
+    forceLayout();
+
+    host1.removeChild(host1.firstChild);
+    forceLayout();
+
+    host2.firstChild.slot = 'bar';
+    forceLayout();
+
+    var child3 = document.createElement('div');
+    child3.style.backgroundColor = 'green';
+    host3.appendChild(child3);
+    forceLayout();
+
+    var host4 = document.getElementById('host4');
+    var child4 = document.createElement('div');
+    child4.style.backgroundColor = 'green';
+    host4.firstChild.appendChild(child4);
+
+    var host5 = document.getElementById('host5');
+    host5.firstChild.removeChild(host5.firstChild.firstChild);
+
+} catch (exception) {
+    document.body.appendChild(document.createTextNode(exception));
+}
+
+</script>
+</body>
+</html>
index 6aa13dc..981812d 100644 (file)
@@ -1,3 +1,28 @@
+2015-10-01  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Slot elements should support fallback contents
+        https://bugs.webkit.org/show_bug.cgi?id=149701
+
+        Reviewed by Antti Koivisto.
+
+        Following discussions on Github discussions [1] [2], we're adding the default rule of `display: contents`
+        on slot elements and making slot elements render its children when there are no assigned nodes [3].
+
+        Make these changes by attaching renderers on direct-children of slot elements when there are no assigned
+        nodes during render tree construction. Note `display: contents` will be aded in webkit.org/b/149439.
+
+        [1] https://github.com/w3c/webcomponents/issues/317
+        [2] https://github.com/w3c/webcomponents/issues/308
+        [3] https://github.com/w3c/webcomponents/issues/308#issuecomment-143655347
+
+        Tests: fast/shadow-dom/css-scoping-shadow-slot-fallback.html
+               fast/shadow-dom/shadow-layout-after-slot-fallback-changes.html
+
+        * style/StyleResolveTree.cpp:
+        (WebCore::Style::attachSlotAssignees):
+        (WebCore::Style::detachSlotAssignees):
+        (WebCore::Style::resolveSlotAssignees):
+
 2015-10-01  Brent Fulgham  <bfulgham@apple.com>
 
         Latch does not clear when a scroll snap animation is triggered
index 1909245..43987e5 100644 (file)
@@ -480,6 +480,13 @@ static void attachSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedSty
             else if (is<Element>(*child))
                 attachRenderTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
         }
+    } else {
+        for (Node* child = slot.firstChild(); child; child = child->nextSibling()) {
+            if (is<Text>(*child))
+                attachTextRenderer(downcast<Text>(*child), renderTreePosition);
+            else if (is<Element>(*child))
+                attachRenderTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
+        }
     }
     slot.clearNeedsStyleRecalc();
     slot.clearChildNeedsStyleRecalc();
@@ -581,6 +588,13 @@ static void detachSlotAssignees(HTMLSlotElement& slot, DetachType detachType)
             else if (is<Element>(*child))
                 detachRenderTree(downcast<Element>(*child), detachType);
         }
+    } else {
+        for (Node* child = slot.firstChild(); child; child = child->nextSibling()) {
+            if (is<Text>(*child))
+                detachTextRenderer(downcast<Text>(*child));
+            else if (is<Element>(*child))
+                detachRenderTree(downcast<Element>(*child), detachType);
+        }
     }
     slot.clearNeedsStyleRecalc();
     slot.clearChildNeedsStyleRecalc();
@@ -852,6 +866,13 @@ static void resolveSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedSt
             else if (is<Element>(*child))
                 resolveTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, change);
         }
+    } else {
+        for (Node* child = slot.firstChild(); child; child = child->nextSibling()) {
+            if (is<Text>(*child))
+                resolveTextNode(downcast<Text>(*child), renderTreePosition);
+            else if (is<Element>(*child))
+                resolveTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, change);
+        }
     }
     slot.clearNeedsStyleRecalc();
     slot.clearChildNeedsStyleRecalc();