⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 243233 in webkit


Ignore:
Timestamp:
Mar 20, 2019, 1:26:18 PM (7 years ago)
Author:
rniwa@webkit.org
Message:

appendChild should throw when inserting an ancestor of a template into its content adopted to another document
https://bugs.webkit.org/show_bug.cgi?id=195984

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Rebaselined the test that is not fully passing.

  • web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy-expected.txt:

Source/WebCore:

The WPT test caught a bug that appendChild and other DOM insertion functions were incorrectly assuming that
any node that's in a HTML template element has the current document's template document as its owner.
The assumption is wrong when the template element's content DocumentFragment is adopted to another document.

Fixed the bug by always checking the ancestor host elements in checkAcceptChild. Also

Test: fast/dom/insert-template-parent-into-adopted-content.html

  • dom/ContainerNode.cpp:

(WebCore::isInTemplateContent): Deleted. This code is simply wrong.
(WebCore::containsConsideringHostElements): Deleted. Call sites are updated to use containsIncludingHostElements.
(WebCore::containsIncludingHostElements): Moved from Node.cpp and optimized this code a bit. It's more efficient
to get the parent node and check for ShadowRoot and DocumentFragment only when the parent is null than to check
for those two node types before getting the parent node.
(WebCore::checkAcceptChild): Merged two code paths to call containsIncludingHostElements. The early return for
a pseudo element is there only to prevent tree corruption in release build even in the presence of a major bug
so it shouldn't be an spec compliance issue.

  • dom/Node.cpp:

(WebCore::Node::containsIncludingHostElements const): Deleted.

  • dom/Node.h:

LayoutTests:

Added a regression test.

  • fast/dom/insert-template-parent-into-adopted-content-expected.txt: Added.
  • fast/dom/insert-template-parent-into-adopted-content.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243228 r243233  
     12019-03-19  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        appendChild should throw when inserting an ancestor of a template into its content adopted to another document
     4        https://bugs.webkit.org/show_bug.cgi?id=195984
     5
     6        Reviewed by Darin Adler.
     7
     8        Added a regression test.
     9
     10        * fast/dom/insert-template-parent-into-adopted-content-expected.txt: Added.
     11        * fast/dom/insert-template-parent-into-adopted-content.html: Added.
     12
    1132019-03-20  Simon Fraser  <simon.fraser@apple.com>
    214
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r243218 r243233  
     12019-03-19  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        appendChild should throw when inserting an ancestor of a template into its content adopted to another document
     4        https://bugs.webkit.org/show_bug.cgi?id=195984
     5
     6        Reviewed by Darin Adler.
     7
     8        Rebaselined the test that is not fully passing.
     9
     10        * web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy-expected.txt:
     11
    1122019-03-20  Oriol Brufau  <obrufau@igalia.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy-expected.txt

    r224156 r243233  
    11
    22PASS Template content should throw when its ancestor is being appended.
    3 FAIL Template content should throw exception when its ancestor in a different document but connected via host is being append. assert_throws: Template content should throw if any of ancestor is being appended. function "() => {
    4     tmpl.content.appendChild(parent);
    5   }" did not throw
     3PASS Template content should throw exception when its ancestor in a different document but connected via host is being append.
    64
  • trunk/Source/WebCore/ChangeLog

    r243229 r243233  
     12019-03-19  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        appendChild should throw when inserting an ancestor of a template into its content adopted to another document
     4        https://bugs.webkit.org/show_bug.cgi?id=195984
     5
     6        Reviewed by Darin Adler.
     7
     8        The WPT test caught a bug that appendChild and other DOM insertion functions were incorrectly assuming that
     9        any node that's in a HTML template element has the current document's template document as its owner.
     10        The assumption is wrong when the template element's content DocumentFragment is adopted to another document.
     11
     12        Fixed the bug by always checking the ancestor host elements in checkAcceptChild. Also
     13
     14        Test: fast/dom/insert-template-parent-into-adopted-content.html
     15
     16        * dom/ContainerNode.cpp:
     17        (WebCore::isInTemplateContent): Deleted. This code is simply wrong.
     18        (WebCore::containsConsideringHostElements): Deleted. Call sites are updated to use containsIncludingHostElements.
     19        (WebCore::containsIncludingHostElements): Moved from Node.cpp and optimized this code a bit. It's more efficient
     20        to get the parent node and check for ShadowRoot and DocumentFragment only when the parent is null than to check
     21        for those two node types before getting the parent node.
     22        (WebCore::checkAcceptChild): Merged two code paths to call containsIncludingHostElements. The early return for
     23        a pseudo element is there only to prevent tree corruption in release build even in the presence of a major bug
     24        so it shouldn't be an spec compliance issue.
     25        * dom/Node.cpp:
     26        (WebCore::Node::containsIncludingHostElements const): Deleted.
     27        * dom/Node.h:
     28
    1292019-03-20  Timothy Hatcher  <timothy@apple.com>
    230
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r243175 r243233  
    293293}
    294294
    295 static inline bool isInTemplateContent(const Node* node)
    296 {
    297     Document& document = node->document();
    298     return &document == document.templateDocument();
    299 }
    300 
    301 static inline bool containsConsideringHostElements(const Node& newChild, const Node& newParent)
    302 {
    303     return (newParent.isInShadowTree() || isInTemplateContent(&newParent))
    304         ? newChild.containsIncludingHostElements(&newParent)
    305         : newChild.contains(&newParent);
     295static bool containsIncludingHostElements(const Node& possibleAncestor, const Node& node)
     296{
     297    const Node* currentNode = &node;
     298    do {
     299        if (currentNode == &possibleAncestor)
     300            return true;
     301        const ContainerNode* parent = currentNode->parentNode();
     302        if (!parent) {
     303            if (is<ShadowRoot>(currentNode))
     304                parent = downcast<ShadowRoot>(currentNode)->host();
     305            else if (is<DocumentFragment>(*currentNode) && downcast<DocumentFragment>(*currentNode).isTemplateContent())
     306                parent = static_cast<const TemplateContentDocumentFragment*>(currentNode)->host();
     307        }
     308        currentNode = parent;
     309    } while (currentNode);
     310
     311    return false;
    306312}
    307313
    308314static inline ExceptionOr<void> checkAcceptChild(ContainerNode& newParent, Node& newChild, const Node* refChild, Document::AcceptChildOperation operation)
    309315{
     316    if (containsIncludingHostElements(newChild, newParent))
     317        return Exception { HierarchyRequestError };
     318
    310319    // Use common case fast path if possible.
    311320    if ((newChild.isElementNode() || newChild.isTextNode()) && newParent.isElementNode()) {
    312321        ASSERT(!newParent.isDocumentTypeNode());
    313322        ASSERT(isChildTypeAllowed(newParent, newChild));
    314         if (containsConsideringHostElements(newChild, newParent))
    315             return Exception { HierarchyRequestError };
    316323        if (operation == Document::AcceptChildOperation::InsertOrAdd && refChild && refChild->parentNode() != &newParent)
    317324            return Exception { NotFoundError };
     
    322329    ASSERT(!newChild.isPseudoElement());
    323330    if (newChild.isPseudoElement())
    324         return Exception { HierarchyRequestError };
    325 
    326     if (containsConsideringHostElements(newChild, newParent))
    327331        return Exception { HierarchyRequestError };
    328332
     
    343347    ASSERT(!newParent.isDocumentTypeNode());
    344348    ASSERT(isChildTypeAllowed(newParent, newChild));
    345     if (containsConsideringHostElements(newChild, newParent))
     349    if (containsIncludingHostElements(newChild, newParent))
    346350        return Exception { HierarchyRequestError };
    347351    return { };
  • trunk/Source/WebCore/dom/Node.cpp

    r243122 r243233  
    10301030}
    10311031
    1032 bool Node::containsIncludingHostElements(const Node* node) const
    1033 {
    1034     while (node) {
    1035         if (node == this)
    1036             return true;
    1037         if (is<DocumentFragment>(*node) && downcast<DocumentFragment>(*node).isTemplateContent())
    1038             node = static_cast<const TemplateContentDocumentFragment*>(node)->host();
    1039         else
    1040             node = node->parentOrShadowHostNode();
    1041     }
    1042     return false;
    1043 }
    1044 
    10451032Node* Node::pseudoAwarePreviousSibling() const
    10461033{
  • trunk/Source/WebCore/dom/Node.h

    r243122 r243233  
    393393    WEBCORE_EXPORT bool contains(const Node*) const;
    394394    bool containsIncludingShadowDOM(const Node*) const;
    395     bool containsIncludingHostElements(const Node*) const;
    396395
    397396    // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
Note: See TracChangeset for help on using the changeset viewer.