Elements should be inserted into a template element as its content's last child
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 May 2017 03:03:37 +0000 (03:03 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 May 2017 03:03:37 +0000 (03:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171373
<rdar://problem/31862949>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Before this change, our HTML parser obeys the following premises:
1) A fostering child whose parent is a table should be inserted before its parent and under its grandparent.
2) When inserting into a template element, an element should be inserted into its content.

Let's walk through the example:
a) Before eventhandler takes place
template
table
    svg <- parser
b) After eventhandler takes place
template
    table
        svg <- parser
c) after parsing svg
template
    content
        svg
        (table)
    table

Finally, in the example, the svg element will be inserted into the content of the template element while
having its next sibling point to the table element. However, the table element is actually under the
template element not its content.

This messy tree is constructed because the second premise is incompleted. It should be: When inserting into
a template element, an element should be inserted into its content as its last child.
Quoted from Step 3 of https://html.spec.whatwg.org/multipage/syntax.html#appropriate-place-for-inserting-a-node
A correct tree will then looks like:
template
    content
        svg
    table

Tests: fast/dom/HTMLTemplateElement/insert-fostering-child-crash.html
       fast/dom/HTMLTemplateElement/insert-fostering-child.html

* html/parser/HTMLConstructionSite.cpp:
(WebCore::insert):
By nullifying task.nextChild, it will force the parser to append the element as task.parent's last child.

LayoutTests:

* fast/dom/HTMLTemplateElement/insert-fostering-child-expected.txt: Added.
* fast/dom/HTMLTemplateElement/insert-fostering-child.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/parser/HTMLConstructionSite.cpp

index e2b9878..ef24bcd 100644 (file)
@@ -1,3 +1,14 @@
+2017-05-12  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Elements should be inserted into a template element as its content's last child
+        https://bugs.webkit.org/show_bug.cgi?id=171373
+        <rdar://problem/31862949>
+
+        Reviewed by Ryosuke Niwa.
+
+        * fast/dom/HTMLTemplateElement/insert-fostering-child-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/insert-fostering-child.html: Added.
+
 2017-05-11  Simon Fraser  <simon.fraser@apple.com>
 
         Incorrect position when dragging jQuery Draggable elements with position fixed after pinch zoom
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child-expected.txt b/LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child-expected.txt
new file mode 100644 (file)
index 0000000..d753f43
--- /dev/null
@@ -0,0 +1,12 @@
+Test inserting a fostering child into HTMLTemplateElement
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS template.firstChild is table
+PASS template.content.lastChild is svg
+PASS svg.nextSibling is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child.html b/LayoutTests/fast/dom/HTMLTemplateElement/insert-fostering-child.html
new file mode 100644 (file)
index 0000000..06cb719
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../../resources/js-test-pre.js"></script>
+    <script>
+        jsTestIsAsync = true;
+
+        function checkOrder()
+        {
+            description('Test inserting a fostering child into HTMLTemplateElement');
+            shouldBe('template.firstChild', 'table');
+            svg = template.content.querySelector("svg");
+            shouldBe('template.content.lastChild', 'svg');
+            shouldBeNull('svg.nextSibling');
+            finishJSTest();
+        }
+
+        function eventhandler()
+        {
+            template.appendChild(table);
+        }
+    </script>
+</head>
+<!--The body element intends to be messy.-->
+<body onload=checkOrder()>
+    <template id="template">
+    </template>
+    <style onload="eventhandler()"></style>
+    <table id="table">
+        <iframe></iframe>
+        <svg></svg>
+    </table>
+</body>
+<script src="../../../resources/js-test-post.js"></script>
+</html>
\ No newline at end of file
index fced7bb..0047da3 100644 (file)
@@ -1,3 +1,51 @@
+2017-05-12  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Elements should be inserted into a template element as its content's last child
+        https://bugs.webkit.org/show_bug.cgi?id=171373
+        <rdar://problem/31862949>
+
+        Reviewed by Ryosuke Niwa.
+
+        Before this change, our HTML parser obeys the following premises:
+        1) A fostering child whose parent is a table should be inserted before its parent and under its grandparent.
+        2) When inserting into a template element, an element should be inserted into its content.
+
+        Let's walk through the example:
+        a) Before eventhandler takes place
+        template
+        table
+            svg <- parser
+        b) After eventhandler takes place
+        template
+            table
+                svg <- parser
+        c) after parsing svg
+        template
+            content
+                svg
+                (table)
+            table
+
+        Finally, in the example, the svg element will be inserted into the content of the template element while
+        having its next sibling point to the table element. However, the table element is actually under the
+        template element not its content.
+
+        This messy tree is constructed because the second premise is incompleted. It should be: When inserting into
+        a template element, an element should be inserted into its content as its last child.
+        Quoted from Step 3 of https://html.spec.whatwg.org/multipage/syntax.html#appropriate-place-for-inserting-a-node
+        A correct tree will then looks like:
+        template
+            content
+                svg
+            table
+
+        Tests: fast/dom/HTMLTemplateElement/insert-fostering-child-crash.html
+               fast/dom/HTMLTemplateElement/insert-fostering-child.html
+
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::insert):
+        By nullifying task.nextChild, it will force the parser to append the element as task.parent's last child.
+
 2017-05-12  Alex Christensen  <achristensen@webkit.org>
 
         Rename WKContentExtension to WKContentRuleList
index f8dc5a5..b15990a 100644 (file)
@@ -102,8 +102,10 @@ static inline bool isAllWhitespace(const String& string)
 
 static inline void insert(HTMLConstructionSiteTask& task)
 {
-    if (is<HTMLTemplateElement>(*task.parent))
+    if (is<HTMLTemplateElement>(*task.parent)) {
         task.parent = &downcast<HTMLTemplateElement>(*task.parent).content();
+        task.nextChild = nullptr;
+    }
 
     ASSERT(!task.child->parentNode());
     if (task.nextChild)