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

Changeset 274626 in webkit


Ignore:
Timestamp:
Mar 18, 2021, 2:18:40 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

ASSERTION FAILED: node.isConnected() in matchSlottedPseudoElementRules
https://bugs.webkit.org/show_bug.cgi?id=221440

Patch by Frédéric Wang <fwang@igalia.com> on 2021-03-18
Reviewed by Ryosuke Niwa.

ReplaceSelectionCommand::doApply() removes a <br> from an element and immediately calls
highestNodeToRemoveInPruning() on that element. The former operation may destroy the
element's renderer and confuses the latter operation. This happens in particular for a
<summary> element which ends up being removed from the tree. This in turn causes unexpected
issues such as a debug assertion failure in matchSlottedPseudoElementRules. To address that
problem, ensure the document is laid out before calling highestNodeToRemoveInPruning().
This patch also increases and improves use of RefPtr<Node>.

  • editing/CompositeEditCommand.cpp:

(WebCore::CompositeEditCommand::removeNodeAndPruneAncestors): Use auto & makeRefPtr.
(WebCore::CompositeEditCommand::prune): Store local highestNodeToRemove variable in a RefPtr.
(WebCore::CompositeEditCommand::cleanupAfterDeletion): Store local node variable in a RefPtr.
(WebCore::CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph): Store local parentNode variable in a RefPtr.

  • editing/Editing.cpp:

(WebCore::highestNodeToRemoveInPruning): Store local currentNode variable in a a RefPtr.

  • editing/ReplaceSelectionCommand.cpp:

(WebCore::ReplaceSelectionCommand::doApply): Use auto & makeRefPtr. Store local odeToRemove variable in a RefPtr.
Ensure the document is laid out before calling highestNodeToRemoveInPruning.

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r274625 r274626  
     12021-03-18  Frédéric Wang  <fwang@igalia.com>
     2
     3        ASSERTION FAILED: node.isConnected() in matchSlottedPseudoElementRules
     4        https://bugs.webkit.org/show_bug.cgi?id=221440
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        ReplaceSelectionCommand::doApply() removes a <br> from an element and immediately calls
     9        highestNodeToRemoveInPruning() on that element. The former operation may destroy the
     10        element's renderer and confuses the latter operation. This happens in particular for a
     11        <summary> element which ends up being removed from the tree. This in turn causes unexpected
     12        issues such as a debug assertion failure in matchSlottedPseudoElementRules. To address that
     13        problem, ensure the document is laid out before calling highestNodeToRemoveInPruning().
     14        This patch also increases and improves use of RefPtr<Node>.
     15
     16        * editing/CompositeEditCommand.cpp:
     17        (WebCore::CompositeEditCommand::removeNodeAndPruneAncestors): Use auto & makeRefPtr.
     18        (WebCore::CompositeEditCommand::prune): Store local highestNodeToRemove variable in a RefPtr.
     19        (WebCore::CompositeEditCommand::cleanupAfterDeletion): Store local node variable in a RefPtr.
     20        (WebCore::CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph): Store local parentNode variable in a RefPtr.
     21        * editing/Editing.cpp:
     22        (WebCore::highestNodeToRemoveInPruning): Store local currentNode variable in a  a RefPtr.
     23        * editing/ReplaceSelectionCommand.cpp:
     24        (WebCore::ReplaceSelectionCommand::doApply): Use auto & makeRefPtr. Store local odeToRemove variable in a  RefPtr.
     25        Ensure the document is laid out before calling highestNodeToRemoveInPruning.
     26
    1272021-03-18  Devin Rousso  <drousso@apple.com>
    228
  • trunk/Source/WebCore/editing/CompositeEditCommand.cpp

    r273621 r274626  
    613613void CompositeEditCommand::removeNodeAndPruneAncestors(Node& node)
    614614{
    615     RefPtr<ContainerNode> parent = node.parentNode();
     615    auto parent = makeRefPtr(node.parentNode());
    616616    removeNode(node);
    617617    prune(parent.get());
     
    657657void CompositeEditCommand::prune(Node* node)
    658658{
    659     if (auto* highestNodeToRemove = highestNodeToRemoveInPruning(node))
     659    if (auto highestNodeToRemove = makeRefPtr(highestNodeToRemoveInPruning(node)))
    660660        removeNode(*highestNodeToRemove);
    661661}
     
    12981298        // Note: We want the rightmost candidate.
    12991299        Position position = caretAfterDelete.deepEquivalent().downstream();
    1300         Node* node = position.deprecatedNode();
     1300        auto node = makeRefPtr(position.deprecatedNode());
    13011301        ASSERT(node);
    13021302        // Normally deletion will leave a br as a placeholder.
     
    13071307        // div or an li), remove it during the move (the list removal code
    13081308        // expects this behavior).
    1309         else if (isBlock(node)) {
     1309        else if (isBlock(node.get())) {
    13101310            // If caret position after deletion and destination position coincides,
    13111311            // node should not be removed.
    13121312            if (!position.rendersInDifferentPosition(destination.deepEquivalent())) {
    1313                 prune(node);
     1313                prune(node.get());
    13141314                return;
    13151315            }
     
    16281628        ASSERT(caretPos.deprecatedEditingOffset() == 0);
    16291629        Text& textNode = downcast<Text>(*caretPos.deprecatedNode());
    1630         ContainerNode* parentNode = textNode.parentNode();
     1630        auto parentNode = makeRefPtr(textNode.parentNode());
    16311631        // The preserved newline must be the first thing in the node, since otherwise the previous
    16321632        // paragraph would be quoted, and we verified that it wasn't above.
    16331633        deleteTextFromNode(textNode, 0, 1);
    1634         prune(parentNode);
     1634        prune(parentNode.get());
    16351635    }
    16361636
  • trunk/Source/WebCore/editing/Editing.cpp

    r273227 r274626  
    629629    Node* previousNode = nullptr;
    630630    auto* rootEditableElement = node ? node->rootEditableElement() : nullptr;
    631     for (; node; node = node->parentNode()) {
    632         if (auto* renderer = node->renderer()) {
    633             if (!renderer->canHaveChildren() || hasARenderedDescendant(node, previousNode) || rootEditableElement == node)
     631    for (auto currentNode = makeRefPtr(node); currentNode; currentNode = currentNode->parentNode()) {
     632        if (auto* renderer = currentNode->renderer()) {
     633            if (!renderer->canHaveChildren() || hasARenderedDescendant(currentNode.get(), previousNode) || rootEditableElement == currentNode.get())
    634634                return previousNode;
    635635        }
    636         previousNode = node;
     636        previousNode = currentNode.get();
    637637    }
    638638    return nullptr;
  • trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp

    r274472 r274626  
    12981298
    12991299    if (endBR && (plainTextFragment || shouldRemoveEndBR(endBR.get(), originalVisPosBeforeEndBR))) {
    1300         RefPtr<Node> parent = endBR->parentNode();
     1300        auto parent = makeRefPtr(endBR->parentNode());
    13011301        insertedNodes.willRemoveNode(endBR.get());
    13021302        removeNode(*endBR);
    1303         if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) {
    1304             insertedNodes.willRemoveNode(nodeToRemove);
     1303        document().updateLayoutIgnorePendingStylesheets();
     1304        if (auto nodeToRemove = makeRefPtr(highestNodeToRemoveInPruning(parent.get()))) {
     1305            insertedNodes.willRemoveNode(nodeToRemove.get());
    13051306            removeNode(*nodeToRemove);
    13061307        }
Note: See TracChangeset for help on using the changeset viewer.