Changeset 249821 in webkit


Ignore:
Timestamp:
Sep 12, 2019 5:01:45 PM (5 years ago)
Author:
Chris Dumez
Message:

Node.replaceChild()'s pre-replacement validations are not done in the right order
https://bugs.webkit.org/show_bug.cgi?id=201741

Reviewed by Geoffrey Garen.

LayoutTests/imported/w3c:

Rebaseline WPT test now that more checks are passing.

  • web-platform-tests/dom/nodes/Node-replaceChild-expected.txt:

Source/WebCore:

Node.replaceChild()'s pre-replacement validations are not done in the right order (spec order):

In particular, we do not do check 3 (If child’s parent is not parent, then throw a
"NotFoundError" DOMException.) at the right time, because we were making this check
*after* checkPreReplacementValidity(), instead of *during*.

No new tests, rebaselined existing test.

  • dom/ContainerNode.cpp:

(WebCore::checkAcceptChild):
(WebCore::ContainerNode::ensurePreInsertionValidity):
(WebCore::checkPreReplacementValidity):
(WebCore::ContainerNode::replaceChild):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r249811 r249821  
     12019-09-12  Chris Dumez  <cdumez@apple.com>
     2
     3        Node.replaceChild()'s pre-replacement validations are not done in the right order
     4        https://bugs.webkit.org/show_bug.cgi?id=201741
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Rebaseline WPT test now that more checks are passing.
     9
     10        * web-platform-tests/dom/nodes/Node-replaceChild-expected.txt:
     11
    1122019-09-12  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/Node-replaceChild-expected.txt

    r249811 r249821  
    22PASS Should check the 'parent' type before checking whether 'child' is a child of 'parent'
    33PASS Should check that 'node' is not an ancestor of 'parent' before checking whether 'child' is a child of 'parent'
    4 FAIL Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent. assert_throws: function "function () {
    5       insertFunc.call(parent, node, child);
    6     }" threw object "HierarchyRequestError: The operation would yield an incorrect node tree." that is not a DOMException NotFoundError: property "code" is equal to 3, expected 8
    7 FAIL Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent of the type that 'parent' is. assert_throws: function "function () {
    8     insertFunc.call(parent, node, child);
    9   }" threw object "HierarchyRequestError: The operation would yield an incorrect node tree." that is not a DOMException NotFoundError: property "code" is equal to 3, expected 8
    10 FAIL Should check whether 'child' is a child of 'parent' before checking whether 'node' can be inserted into the document given the kids the document has right now. assert_throws: function "function () {
    11     insertFunc.call(parent, node, child);
    12   }" threw object "HierarchyRequestError: The operation would yield an incorrect node tree." that is not a DOMException NotFoundError: property "code" is equal to 3, expected 8
     4PASS Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent.
     5PASS Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent of the type that 'parent' is.
     6PASS Should check whether 'child' is a child of 'parent' before checking whether 'node' can be inserted into the document given the kids the document has right now.
    137PASS Passing null to replaceChild should throw a TypeError.
    148PASS If child's parent is not the context node, a NotFoundError exception should be thrown
  • trunk/Source/WebCore/ChangeLog

    r249820 r249821  
     12019-09-12  Chris Dumez  <cdumez@apple.com>
     2
     3        Node.replaceChild()'s pre-replacement validations are not done in the right order
     4        https://bugs.webkit.org/show_bug.cgi?id=201741
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Node.replaceChild()'s pre-replacement validations are not done in the right order (spec order):
     9        - https://dom.spec.whatwg.org/#concept-node-replace
     10
     11        In particular, we do not do check 3 (If child’s parent is not parent, then throw a
     12        "NotFoundError" DOMException.) at the right time, because we were making this check
     13        *after* checkPreReplacementValidity(), instead of *during*.
     14
     15        No new tests, rebaselined existing test.
     16
     17        * dom/ContainerNode.cpp:
     18        (WebCore::checkAcceptChild):
     19        (WebCore::ContainerNode::ensurePreInsertionValidity):
     20        (WebCore::checkPreReplacementValidity):
     21        (WebCore::ContainerNode::replaceChild):
     22
    1232019-09-12  Ryan Haddad  <ryanhaddad@apple.com>
    224
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r246490 r249821  
    312312}
    313313
    314 static inline ExceptionOr<void> checkAcceptChild(ContainerNode& newParent, Node& newChild, const Node* refChild, Document::AcceptChildOperation operation)
     314enum class ShouldValidateChildParent { No, Yes };
     315static inline ExceptionOr<void> checkAcceptChild(ContainerNode& newParent, Node& newChild, const Node* refChild, Document::AcceptChildOperation operation, ShouldValidateChildParent shouldValidateChildParent)
    315316{
    316317    if (containsIncludingHostElements(newChild, newParent))
     
    321322        ASSERT(!newParent.isDocumentTypeNode());
    322323        ASSERT(isChildTypeAllowed(newParent, newChild));
    323         if (operation == Document::AcceptChildOperation::InsertOrAdd && refChild && refChild->parentNode() != &newParent)
     324        if (shouldValidateChildParent == ShouldValidateChildParent::Yes && refChild && refChild->parentNode() != &newParent)
    324325            return Exception { NotFoundError };
    325326        return { };
     
    331332        return Exception { HierarchyRequestError };
    332333
    333     if (operation == Document::AcceptChildOperation::InsertOrAdd && refChild && refChild->parentNode() != &newParent)
     334    if (shouldValidateChildParent == ShouldValidateChildParent::Yes && refChild && refChild->parentNode() != &newParent)
    334335        return Exception { NotFoundError };
    335336
     
    355356ExceptionOr<void> ContainerNode::ensurePreInsertionValidity(Node& newChild, Node* refChild)
    356357{
    357     return checkAcceptChild(*this, newChild, refChild, Document::AcceptChildOperation::InsertOrAdd);
     358    return checkAcceptChild(*this, newChild, refChild, Document::AcceptChildOperation::InsertOrAdd, ShouldValidateChildParent::Yes);
    358359}
    359360
    360361// https://dom.spec.whatwg.org/#concept-node-replace
    361 static inline ExceptionOr<void> checkPreReplacementValidity(ContainerNode& newParent, Node& newChild, Node& oldChild)
    362 {
    363     return checkAcceptChild(newParent, newChild, &oldChild, Document::AcceptChildOperation::Replace);
     362static inline ExceptionOr<void> checkPreReplacementValidity(ContainerNode& newParent, Node& newChild, Node& oldChild, ShouldValidateChildParent shouldValidateChildParent)
     363{
     364    return checkAcceptChild(newParent, newChild, &oldChild, Document::AcceptChildOperation::Replace, shouldValidateChildParent);
    364365}
    365366
     
    490491
    491492    // Make sure replacing the old child with the new is ok
    492     auto validityResult = checkPreReplacementValidity(*this, newChild, oldChild);
     493    auto validityResult = checkPreReplacementValidity(*this, newChild, oldChild, ShouldValidateChildParent::Yes);
    493494    if (validityResult.hasException())
    494495        return validityResult.releaseException();
    495 
    496     // NotFoundError: Raised if oldChild is not a child of this node.
    497     if (oldChild.parentNode() != this)
    498         return Exception { NotFoundError };
    499496
    500497    RefPtr<Node> refChild = oldChild.nextSibling();
     
    512509    // Do this one more time because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
    513510    for (auto& child : targets) {
    514         validityResult = checkPreReplacementValidity(*this, child, oldChild);
     511        validityResult = checkPreReplacementValidity(*this, child, oldChild, ShouldValidateChildParent::No);
    515512        if (validityResult.hasException())
    516513            return validityResult.releaseException();
     
    530527        // Does this one more time because removeChild() fires a MutationEvent.
    531528        for (auto& child : targets) {
    532             validityResult = checkPreReplacementValidity(*this, child, oldChild);
     529            validityResult = checkPreReplacementValidity(*this, child, oldChild, ShouldValidateChildParent::No);
    533530            if (validityResult.hasException())
    534531                return validityResult.releaseException();
Note: See TracChangeset for help on using the changeset viewer.