Skip to content
Permalink
Browse files
Add an argument indicating the type of removal to Node::removedFrom
https://bugs.webkit.org/show_bug.cgi?id=178505

Reviewed by Antti Koivisto.

Like r223628, added RemovalType as the first argument to Node::removedFrom, which contains two booleans indicating
whether the node just become disconnected from a document, and whether node's tree scope had changed or not.

These boolean flags simplifies the logic in removedFrom implementations, and are required to have a better
guarantee about the correctness of node flags during calls to removedFrom. Right now, Node::isConnected() and
Node::isInShadowTree() are both outdated until Node::removedFrom is called.

Also renamed the second argument of removedFrom to parentOfRemovedTree to make the semantics clear.

Note that in some implementations of removedFrom, we check whether isConnected() was true to decide whether
the node had already been disconnected from a document prior to calls to this particular call of removedFrom.
This extra check is no longer necessary since no node will be removed from a document without first being inserted
completely somewhere after r223458.

No new tests since there should be no behavioral changes.

* dom/ContainerNodeAlgorithms.cpp:
(WebCore::notifyNodeInsertedIntoDocument): Replaced RELEASE_ASSERT with RELEASE_ASSERT_WITH_SECURITY_IMPLICATION.
(WebCore::notifyNodeRemovedFromDocument): Replaced the check that the node had not been re-connected by scripts
by a release assert now that we believe we've eliminated all causes of these unwanted DOM mutations in r223458.
Also moved the code to call setCSSTarget to Element::removedFrom. This random call to setCSSTarget predates r114351,
as well as r40475. It was originally introduced by r29311 into Node::removedFromDocument() ten years ago.
(WebCore::notifyNodeRemovedFromTree): Moved NoEventDispatchAssertion to notifyChildNodeRemoved.
(WebCore::notifyChildNodeRemoved): Added NoEventDispatchAssertion.
* dom/ContainerNodeAlgorithms.h:
* dom/Element.cpp:
(WebCore::Element::removedFrom): Replaced the complicated code to detect when this element is removed from a document
and its tree scope had changed by removalType.disconnectedFromDocument and removalType.treeScopeChanged.
* dom/Element.h:
* dom/Node.cpp:
(WebCore::Node::removedFrom):
* dom/Node.h: Replaced a long block of comments above insertedInto by two lines of concise comments now that
the semantics of insertedInto and didFinishInsertingNode are more clear, and enforced by assertions.
(WebCore::Node::RemovalType::RemovalType): Addedl
* dom/ProcessingInstruction.cpp:
(WebCore::ProcessingInstruction::removedFrom):
* dom/ProcessingInstruction.h:
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::removedFrom): The extra !isConnected() check is no longer needed. See the description above.
* dom/ShadowRoot.h:
* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::removedFrom):
* html/FormAssociatedElement.h:
* html/HTMLBaseElement.cpp:
(WebCore::HTMLBaseElement::removedFrom):
* html/HTMLBaseElement.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::removedFrom):
* html/HTMLFormControlElement.h:
* html/HTMLFormControlElementWithState.cpp:
(WebCore::HTMLFormControlElementWithState::removedFrom):
* html/HTMLFormControlElementWithState.h:
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::removedFrom):
* html/HTMLFormElement.h:
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::removedFrom):
* html/HTMLFrameSetElement.h:
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::removedFrom):
* html/HTMLImageElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::removedFrom):
* html/HTMLInputElement.h:
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::removedFrom): The extra !isConnected() check is no longer needed. See above.
* html/HTMLLinkElement.h:
* html/HTMLMapElement.cpp:
(WebCore::HTMLMapElement::removedFrom):
* html/HTMLMapElement.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::removedFrom):
* html/HTMLMediaElement.h:
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::removedFrom):
* html/HTMLObjectElement.h:
* html/HTMLSlotElement.cpp:
(WebCore::HTMLSlotElement::removedFrom): Simplifies the logic to detect when this slot element is being
removed from a shadow tree using removalType.treeScopeChanged.
* html/HTMLSlotElement.h:
* html/HTMLSourceElement.cpp:
(WebCore::HTMLSourceElement::insertedInto): Added a FIXME for an obvious bug.
(WebCore::HTMLSourceElement::removedFrom): Ditto.
* html/HTMLSourceElement.h:
* html/HTMLStyleElement.cpp:
(WebCore::HTMLStyleElement::removedFrom):
* html/HTMLStyleElement.h:
* html/HTMLTitleElement.cpp:
(WebCore::HTMLTitleElement::removedFrom):
* html/HTMLTitleElement.h:
* html/HTMLTrackElement.cpp:
(WebCore::HTMLTrackElement::removedFrom): Ditto.
* html/HTMLTrackElement.h:
* svg/SVGElement.cpp:
(WebCore::SVGElement::removedFrom): Replaced isConnected() check before calling Node::removedFrom by the check of
removalType.disconnectedFromDocument.
* svg/SVGElement.h:
* svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::removedFrom):
* svg/SVGFEImageElement.h:
* svg/SVGFontFaceElement.cpp:
(WebCore::SVGFontFaceElement::removedFrom):
* svg/SVGFontFaceElement.h:
* svg/SVGMPathElement.cpp:
(WebCore::SVGMPathElement::removedFrom):
* svg/SVGMPathElement.h:
* svg/SVGPathElement.cpp:
(WebCore::SVGPathElement::removedFrom):
* svg/SVGPathElement.h:
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::removedFrom):
* svg/SVGSVGElement.h:
* svg/SVGStyleElement.cpp:
(WebCore::SVGStyleElement::removedFrom): The extra !isConnected() check is no longer needed. See above.
* svg/SVGStyleElement.h:
* svg/SVGTRefElement.cpp:
(WebCore::SVGTRefElement::removedFrom):
* svg/SVGTRefElement.h:
* svg/SVGTextPathElement.cpp:
(WebCore::SVGTextPathElement::removedFrom):
* svg/SVGTextPathElement.h:
* svg/SVGTitleElement.cpp:
(WebCore::SVGTitleElement::removedFrom):
* svg/SVGTitleElement.h:
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::removedFrom):
* svg/SVGUseElement.h:
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::removedFrom):
* svg/animation/SVGSMILElement.h:


Canonical link: https://commits.webkit.org/194703@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223685 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
rniwa committed Oct 19, 2017
1 parent 1f03708 commit f84f10e977679a5a772777635785741198ef7db8
Showing with 329 additions and 196 deletions.
  1. +138 −0 Source/WebCore/ChangeLog
  2. +27 −27 Source/WebCore/dom/ContainerNodeAlgorithms.cpp
  3. +1 −1 Source/WebCore/dom/ContainerNodeAlgorithms.h
  4. +18 −16 Source/WebCore/dom/Element.cpp
  5. +1 −1 Source/WebCore/dom/Element.h
  6. +2 −2 Source/WebCore/dom/Node.cpp
  7. +13 −21 Source/WebCore/dom/Node.h
  8. +3 −3 Source/WebCore/dom/ProcessingInstruction.cpp
  9. +1 −1 Source/WebCore/dom/ProcessingInstruction.h
  10. +3 −3 Source/WebCore/dom/ShadowRoot.cpp
  11. +1 −1 Source/WebCore/dom/ShadowRoot.h
  12. +1 −1 Source/WebCore/html/FormAssociatedElement.cpp
  13. +1 −1 Source/WebCore/html/FormAssociatedElement.h
  14. +3 −3 Source/WebCore/html/HTMLBaseElement.cpp
  15. +1 −1 Source/WebCore/html/HTMLBaseElement.h
  16. +4 −4 Source/WebCore/html/HTMLFormControlElement.cpp
  17. +1 −1 Source/WebCore/html/HTMLFormControlElement.h
  18. +3 −3 Source/WebCore/html/HTMLFormControlElementWithState.cpp
  19. +1 −1 Source/WebCore/html/HTMLFormControlElementWithState.h
  20. +2 −2 Source/WebCore/html/HTMLFormElement.cpp
  21. +1 −1 Source/WebCore/html/HTMLFormElement.h
  22. +3 −3 Source/WebCore/html/HTMLFrameSetElement.cpp
  23. +1 −1 Source/WebCore/html/HTMLFrameSetElement.h
  24. +5 −5 Source/WebCore/html/HTMLImageElement.cpp
  25. +1 −1 Source/WebCore/html/HTMLImageElement.h
  26. +3 −3 Source/WebCore/html/HTMLInputElement.cpp
  27. +1 −1 Source/WebCore/html/HTMLInputElement.h
  28. +3 −3 Source/WebCore/html/HTMLLinkElement.cpp
  29. +1 −1 Source/WebCore/html/HTMLLinkElement.h
  30. +3 −3 Source/WebCore/html/HTMLMapElement.cpp
  31. +1 −1 Source/WebCore/html/HTMLMapElement.h
  32. +3 −3 Source/WebCore/html/HTMLMediaElement.cpp
  33. +1 −1 Source/WebCore/html/HTMLMediaElement.h
  34. +3 −3 Source/WebCore/html/HTMLObjectElement.cpp
  35. +1 −1 Source/WebCore/html/HTMLObjectElement.h
  36. +4 −6 Source/WebCore/html/HTMLSlotElement.cpp
  37. +1 −1 Source/WebCore/html/HTMLSlotElement.h
  38. +6 −4 Source/WebCore/html/HTMLSourceElement.cpp
  39. +1 −1 Source/WebCore/html/HTMLSourceElement.h
  40. +3 −3 Source/WebCore/html/HTMLStyleElement.cpp
  41. +1 −1 Source/WebCore/html/HTMLStyleElement.h
  42. +2 −2 Source/WebCore/html/HTMLTitleElement.cpp
  43. +1 −1 Source/WebCore/html/HTMLTitleElement.h
  44. +6 −4 Source/WebCore/html/HTMLTrackElement.cpp
  45. +1 −1 Source/WebCore/html/HTMLTrackElement.h
  46. +4 −5 Source/WebCore/svg/SVGElement.cpp
  47. +1 −1 Source/WebCore/svg/SVGElement.h
  48. +3 −3 Source/WebCore/svg/SVGFEImageElement.cpp
  49. +1 −1 Source/WebCore/svg/SVGFEImageElement.h
  50. +3 −3 Source/WebCore/svg/SVGFontFaceElement.cpp
  51. +1 −1 Source/WebCore/svg/SVGFontFaceElement.h
  52. +4 −4 Source/WebCore/svg/SVGMPathElement.cpp
  53. +1 −1 Source/WebCore/svg/SVGMPathElement.h
  54. +2 −2 Source/WebCore/svg/SVGPathElement.cpp
  55. +1 −1 Source/WebCore/svg/SVGPathElement.h
  56. +3 −3 Source/WebCore/svg/SVGSVGElement.cpp
  57. +1 −1 Source/WebCore/svg/SVGSVGElement.h
  58. +3 −3 Source/WebCore/svg/SVGStyleElement.cpp
  59. +1 −1 Source/WebCore/svg/SVGStyleElement.h
  60. +3 −3 Source/WebCore/svg/SVGTRefElement.cpp
  61. +1 −1 Source/WebCore/svg/SVGTRefElement.h
  62. +3 −3 Source/WebCore/svg/SVGTextPathElement.cpp
  63. +1 −1 Source/WebCore/svg/SVGTextPathElement.h
  64. +2 −2 Source/WebCore/svg/SVGTitleElement.cpp
  65. +1 −1 Source/WebCore/svg/SVGTitleElement.h
  66. +2 −2 Source/WebCore/svg/SVGUseElement.cpp
  67. +1 −1 Source/WebCore/svg/SVGUseElement.h
  68. +3 −3 Source/WebCore/svg/animation/SVGSMILElement.cpp
  69. +1 −1 Source/WebCore/svg/animation/SVGSMILElement.h
@@ -1,3 +1,141 @@
2017-10-19 Ryosuke Niwa <rniwa@webkit.org>

Add an argument indicating the type of removal to Node::removedFrom
https://bugs.webkit.org/show_bug.cgi?id=178505

Reviewed by Antti Koivisto.

Like r223628, added RemovalType as the first argument to Node::removedFrom, which contains two booleans indicating
whether the node just become disconnected from a document, and whether node's tree scope had changed or not.

These boolean flags simplifies the logic in removedFrom implementations, and are required to have a better
guarantee about the correctness of node flags during calls to removedFrom. Right now, Node::isConnected() and
Node::isInShadowTree() are both outdated until Node::removedFrom is called.

Also renamed the second argument of removedFrom to parentOfRemovedTree to make the semantics clear.

Note that in some implementations of removedFrom, we check whether isConnected() was true to decide whether
the node had already been disconnected from a document prior to calls to this particular call of removedFrom.
This extra check is no longer necessary since no node will be removed from a document without first being inserted
completely somewhere after r223458.

No new tests since there should be no behavioral changes.

* dom/ContainerNodeAlgorithms.cpp:
(WebCore::notifyNodeInsertedIntoDocument): Replaced RELEASE_ASSERT with RELEASE_ASSERT_WITH_SECURITY_IMPLICATION.
(WebCore::notifyNodeRemovedFromDocument): Replaced the check that the node had not been re-connected by scripts
by a release assert now that we believe we've eliminated all causes of these unwanted DOM mutations in r223458.
Also moved the code to call setCSSTarget to Element::removedFrom. This random call to setCSSTarget predates r114351,
as well as r40475. It was originally introduced by r29311 into Node::removedFromDocument() ten years ago.
(WebCore::notifyNodeRemovedFromTree): Moved NoEventDispatchAssertion to notifyChildNodeRemoved.
(WebCore::notifyChildNodeRemoved): Added NoEventDispatchAssertion.
* dom/ContainerNodeAlgorithms.h:
* dom/Element.cpp:
(WebCore::Element::removedFrom): Replaced the complicated code to detect when this element is removed from a document
and its tree scope had changed by removalType.disconnectedFromDocument and removalType.treeScopeChanged.
* dom/Element.h:
* dom/Node.cpp:
(WebCore::Node::removedFrom):
* dom/Node.h: Replaced a long block of comments above insertedInto by two lines of concise comments now that
the semantics of insertedInto and didFinishInsertingNode are more clear, and enforced by assertions.
(WebCore::Node::RemovalType::RemovalType): Addedl
* dom/ProcessingInstruction.cpp:
(WebCore::ProcessingInstruction::removedFrom):
* dom/ProcessingInstruction.h:
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::removedFrom): The extra !isConnected() check is no longer needed. See the description above.
* dom/ShadowRoot.h:
* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::removedFrom):
* html/FormAssociatedElement.h:
* html/HTMLBaseElement.cpp:
(WebCore::HTMLBaseElement::removedFrom):
* html/HTMLBaseElement.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::removedFrom):
* html/HTMLFormControlElement.h:
* html/HTMLFormControlElementWithState.cpp:
(WebCore::HTMLFormControlElementWithState::removedFrom):
* html/HTMLFormControlElementWithState.h:
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::removedFrom):
* html/HTMLFormElement.h:
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::removedFrom):
* html/HTMLFrameSetElement.h:
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::removedFrom):
* html/HTMLImageElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::removedFrom):
* html/HTMLInputElement.h:
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::removedFrom): The extra !isConnected() check is no longer needed. See above.
* html/HTMLLinkElement.h:
* html/HTMLMapElement.cpp:
(WebCore::HTMLMapElement::removedFrom):
* html/HTMLMapElement.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::removedFrom):
* html/HTMLMediaElement.h:
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::removedFrom):
* html/HTMLObjectElement.h:
* html/HTMLSlotElement.cpp:
(WebCore::HTMLSlotElement::removedFrom): Simplifies the logic to detect when this slot element is being
removed from a shadow tree using removalType.treeScopeChanged.
* html/HTMLSlotElement.h:
* html/HTMLSourceElement.cpp:
(WebCore::HTMLSourceElement::insertedInto): Added a FIXME for an obvious bug.
(WebCore::HTMLSourceElement::removedFrom): Ditto.
* html/HTMLSourceElement.h:
* html/HTMLStyleElement.cpp:
(WebCore::HTMLStyleElement::removedFrom):
* html/HTMLStyleElement.h:
* html/HTMLTitleElement.cpp:
(WebCore::HTMLTitleElement::removedFrom):
* html/HTMLTitleElement.h:
* html/HTMLTrackElement.cpp:
(WebCore::HTMLTrackElement::removedFrom): Ditto.
* html/HTMLTrackElement.h:
* svg/SVGElement.cpp:
(WebCore::SVGElement::removedFrom): Replaced isConnected() check before calling Node::removedFrom by the check of
removalType.disconnectedFromDocument.
* svg/SVGElement.h:
* svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::removedFrom):
* svg/SVGFEImageElement.h:
* svg/SVGFontFaceElement.cpp:
(WebCore::SVGFontFaceElement::removedFrom):
* svg/SVGFontFaceElement.h:
* svg/SVGMPathElement.cpp:
(WebCore::SVGMPathElement::removedFrom):
* svg/SVGMPathElement.h:
* svg/SVGPathElement.cpp:
(WebCore::SVGPathElement::removedFrom):
* svg/SVGPathElement.h:
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::removedFrom):
* svg/SVGSVGElement.h:
* svg/SVGStyleElement.cpp:
(WebCore::SVGStyleElement::removedFrom): The extra !isConnected() check is no longer needed. See above.
* svg/SVGStyleElement.h:
* svg/SVGTRefElement.cpp:
(WebCore::SVGTRefElement::removedFrom):
* svg/SVGTRefElement.h:
* svg/SVGTextPathElement.cpp:
(WebCore::SVGTextPathElement::removedFrom):
* svg/SVGTextPathElement.h:
* svg/SVGTitleElement.cpp:
(WebCore::SVGTitleElement::removedFrom):
* svg/SVGTitleElement.h:
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::removedFrom):
* svg/SVGUseElement.h:
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::removedFrom):
* svg/animation/SVGSMILElement.h:

2017-10-19 Ms2ger <Ms2ger@igalia.com>

Update the signatures of compressedTexSubImage3D.
@@ -48,15 +48,15 @@ static void notifyNodeInsertedIntoDocument(ContainerNode& parentOfInsertedTree,
return;

for (RefPtr<Node> child = downcast<ContainerNode>(node).firstChild(); child; child = child->nextSibling()) {
RELEASE_ASSERT(node.isConnected() && child->parentNode() == &node);
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(node.isConnected() && child->parentNode() == &node);
notifyNodeInsertedIntoDocument(parentOfInsertedTree, *child, treeScopeChange, postInsertionNotificationTargets);
}

if (!is<Element>(node))
return;

if (RefPtr<ShadowRoot> root = downcast<Element>(node).shadowRoot()) {
RELEASE_ASSERT(node.isConnected() && root->host() == &node);
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(node.isConnected() && root->host() == &node);
notifyNodeInsertedIntoDocument(parentOfInsertedTree, *root, TreeScopeChange::DidNotChange, postInsertionNotificationTargets);
}
}
@@ -103,58 +103,58 @@ NodeVector notifyChildNodeInserted(ContainerNode& parentOfInsertedTree, Node& no
return postInsertionNotificationTargets;
}

static void notifyNodeRemovedFromDocument(ContainerNode& insertionPoint, Node& node)
static void notifyNodeRemovedFromDocument(ContainerNode& parentOfRemovedTree, TreeScopeChange treeScopeChange, Node& node)
{
ASSERT(insertionPoint.isConnected());
node.removedFrom(insertionPoint);
ASSERT(parentOfRemovedTree.isConnected());
ASSERT(node.isConnected());
node.removedFrom(Node::RemovalType { /* disconnectedFromDocument */ true, treeScopeChange == TreeScopeChange::Changed }, parentOfRemovedTree);

if (!is<ContainerNode>(node))
return;

ChildNodesLazySnapshot snapshot(downcast<ContainerNode>(node));
while (RefPtr<Node> child = snapshot.nextNode()) {
// If we have been added to the document during this loop, then we
// don't want to tell the rest of our children that they've been
// removed from the document because they haven't.
if (!node.isConnected() && child->parentNode() == &node)
notifyNodeRemovedFromDocument(insertionPoint, *child.get());
for (RefPtr<Node> child = downcast<ContainerNode>(node).firstChild(); child; child = child->nextSibling()) {
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!node.isConnected() && child->parentNode() == &node);
notifyNodeRemovedFromDocument(parentOfRemovedTree, treeScopeChange, *child.get());
}

if (!is<Element>(node))
return;

if (node.document().cssTarget() == &node)
node.document().setCSSTarget(nullptr);

if (RefPtr<ShadowRoot> root = downcast<Element>(node).shadowRoot()) {
if (!node.isConnected() && root->host() == &node)
notifyNodeRemovedFromDocument(insertionPoint, *root.get());
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!node.isConnected() && root->host() == &node);
notifyNodeRemovedFromDocument(parentOfRemovedTree, TreeScopeChange::DidNotChange, *root.get());
}
}

static void notifyNodeRemovedFromTree(ContainerNode& insertionPoint, Node& node)
static void notifyNodeRemovedFromTree(ContainerNode& parentOfRemovedTree, TreeScopeChange treeScopeChange, Node& node)
{
NoEventDispatchAssertion assertNoEventDispatch;
ASSERT(!insertionPoint.isConnected());
ASSERT(!parentOfRemovedTree.isConnected());

node.removedFrom(insertionPoint);
node.removedFrom(Node::RemovalType { /* disconnectedFromDocument */ false, treeScopeChange == TreeScopeChange::Changed }, parentOfRemovedTree);

for (Node* child = node.firstChild(); child; child = child->nextSibling())
notifyNodeRemovedFromTree(insertionPoint, *child);
if (!is<ContainerNode>(node))
return;

for (RefPtr<Node> child = downcast<ContainerNode>(node).firstChild(); child; child = child->nextSibling())
notifyNodeRemovedFromTree(parentOfRemovedTree, treeScopeChange, *child);

if (!is<Element>(node))
return;

if (RefPtr<ShadowRoot> root = downcast<Element>(node).shadowRoot())
notifyNodeRemovedFromTree(insertionPoint, *root);
notifyNodeRemovedFromTree(parentOfRemovedTree, TreeScopeChange::DidNotChange, *root);
}

void notifyChildNodeRemoved(ContainerNode& insertionPoint, Node& child)
void notifyChildNodeRemoved(ContainerNode& parentOfRemovedTree, Node& child)
{
NoEventDispatchAssertion assertNoEventDispatch;

// Tree scope has changed if the container node from which "node" is removed is in a document or a shadow root.
auto treeScopeChange = parentOfRemovedTree.isInTreeScope() ? TreeScopeChange::Changed : TreeScopeChange::DidNotChange;
if (child.isConnected())
notifyNodeRemovedFromDocument(insertionPoint, child);
notifyNodeRemovedFromDocument(parentOfRemovedTree, treeScopeChange, child);
else
notifyNodeRemovedFromTree(insertionPoint, child);
notifyNodeRemovedFromTree(parentOfRemovedTree, treeScopeChange, child);
}

void addChildNodesToDeletionQueue(Node*& head, Node*& tail, ContainerNode& container)
@@ -27,7 +27,7 @@
namespace WebCore {

NodeVector notifyChildNodeInserted(ContainerNode& parentOfInsertedTree, Node&);
void notifyChildNodeRemoved(ContainerNode& insertionPoint, Node&);
void notifyChildNodeRemoved(ContainerNode& parentOfRemovedTree, Node&);
void removeDetachedChildrenInContainer(ContainerNode&);

enum SubframeDisconnectPolicy {
@@ -1683,7 +1683,7 @@ Node::InsertedIntoResult Element::insertedInto(InsertionType insertionType, Cont
return InsertedIntoResult::Done;
}

void Element::removedFrom(ContainerNode& insertionPoint)
void Element::removedFrom(RemovalType removalType, ContainerNode& parentOfRemovedTree)
{
#if ENABLE(FULLSCREEN_API)
if (containsFullScreenElement())
@@ -1696,47 +1696,49 @@ void Element::removedFrom(ContainerNode& insertionPoint)

setSavedLayerScrollPosition(ScrollPosition());

if (insertionPoint.isInTreeScope()) {
TreeScope* oldScope = &insertionPoint.treeScope();
bool becomeDisconnected = isConnected();
HTMLDocument* oldDocument = becomeDisconnected && is<HTMLDocument>(oldScope->documentScope()) ? &downcast<HTMLDocument>(oldScope->documentScope()) : nullptr;

// ContainerNode::removeBetween always sets the removed chid's tree scope to Document's but InTreeScope flag is unset in Node::removedFrom.
// So this element has been removed from the old tree scope only if InTreeScope flag is set and this element's tree scope is Document's.
if (!isInTreeScope() || &treeScope() != &document())
if (parentOfRemovedTree.isInTreeScope()) {
TreeScope* oldScope = &parentOfRemovedTree.treeScope();
Document* oldDocument = removalType.disconnectedFromDocument ? &oldScope->documentScope() : nullptr;
HTMLDocument* oldHTMLDocument = oldDocument && is<HTMLDocument>(*oldDocument) ? &downcast<HTMLDocument>(*oldDocument) : nullptr;
if (!removalType.treeScopeChanged)
oldScope = nullptr;

const AtomicString& idValue = getIdAttribute();
if (!idValue.isNull()) {
if (oldScope)
updateIdForTreeScope(*oldScope, idValue, nullAtom());
if (oldDocument)
updateIdForDocument(*oldDocument, idValue, nullAtom(), AlwaysUpdateHTMLDocumentNamedItemMaps);
if (oldHTMLDocument)
updateIdForDocument(*oldHTMLDocument, idValue, nullAtom(), AlwaysUpdateHTMLDocumentNamedItemMaps);
}

const AtomicString& nameValue = getNameAttribute();
if (!nameValue.isNull()) {
if (oldScope)
updateNameForTreeScope(*oldScope, nameValue, nullAtom());
if (oldDocument)
updateNameForDocument(*oldDocument, nameValue, nullAtom());
if (oldHTMLDocument)
updateNameForDocument(*oldHTMLDocument, nameValue, nullAtom());
}

if (oldScope && hasTagName(labelTag)) {
if (oldScope->shouldCacheLabelsByForAttribute())
updateLabel(*oldScope, attributeWithoutSynchronization(forAttr), nullAtom());
}

if (becomeDisconnected && UNLIKELY(isDefinedCustomElement()))
if (oldDocument) {
if (oldDocument->cssTarget() == this)
oldDocument->setCSSTarget(nullptr);
}

if (removalType.disconnectedFromDocument && UNLIKELY(isDefinedCustomElement()))
CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*this);
}

if (!parentNode()) {
if (auto* shadowRoot = insertionPoint.shadowRoot())
if (auto* shadowRoot = parentOfRemovedTree.shadowRoot())
shadowRoot->hostChildElementDidChange(*this);
}

ContainerNode::removedFrom(insertionPoint);
ContainerNode::removedFrom(removalType, parentOfRemovedTree);

if (hasPendingResources())
document().accessSVGExtensions().removeElementFromPendingResources(this);
@@ -552,7 +552,7 @@ class Element : public ContainerNode {
Element(const QualifiedName&, Document&, ConstructionType);

InsertedIntoResult insertedInto(InsertionType, ContainerNode&) override;
void removedFrom(ContainerNode&) override;
void removedFrom(RemovalType, ContainerNode&) override;
void childrenChanged(const ChildChange&) override;
void removeAllEventListeners() final;
virtual void parserDidSetAttributes();
@@ -1253,9 +1253,9 @@ Node::InsertedIntoResult Node::insertedInto(InsertionType insertionType, Contain
return InsertedIntoResult::Done;
}

void Node::removedFrom(ContainerNode& insertionPoint)
void Node::removedFrom(RemovalType removalType, ContainerNode&)
{
if (insertionPoint.isConnected())
if (removalType.disconnectedFromDocument)
clearFlag(IsConnectedFlag);
if (isInShadowTree() && !treeScope().rootNode().isShadowRoot())
clearFlag(IsInShadowTreeFlag);
@@ -433,21 +433,6 @@ class Node : public EventTarget {

virtual const RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO);

// -----------------------------------------------------------------------------
// Notification of document structure changes (see ContainerNode.h for more notification methods)
//
// At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also
// when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). The call happens _after_ the node has been added to the tree.
// This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
// dispatching.
//
// WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree.
// Implementation can determine the type of subtree by seeing insertionPoint->isConnected().
//
// There is another callback named didFinishInsertingNode(), which is called after all descendants are notified.
// Only a few subclasses actually need this. To utilize this, the node should return InsertedIntoResult::NeedsPostInsertionCallback
// from insrtedInto().
//
enum class InsertedIntoResult {
Done,
NeedsPostInsertionCallback,
@@ -463,15 +448,22 @@ class Node : public EventTarget {
bool connectedToDocument { false };
bool treeScopeChanged { false };
};
// Called *after* this node or its ancestor is inserted into a new parent (may or may not be a part of document) by scripts or parser.
// insertedInto **MUST NOT** invoke scripts. Return NeedsPostInsertionCallback and implement didFinishInsertingNode instead to run scripts.
virtual InsertedIntoResult insertedInto(InsertionType, ContainerNode& parentOfInsertedTree);
virtual void didFinishInsertingNode() { }

// Notifies the node that it is no longer part of the tree.
//
// This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
// dispatching, and is called _after_ the node is removed from the tree.
//
virtual void removedFrom(ContainerNode& insertionPoint);
struct RemovalType {
#if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
RemovalType(bool disconnectedFromDocument, bool treeScopeChanged)
: disconnectedFromDocument(disconnectedFromDocument)
, treeScopeChanged(treeScopeChanged)
{ }
#endif
bool disconnectedFromDocument { false };
bool treeScopeChanged { false };
};
virtual void removedFrom(RemovalType, ContainerNode& parentOfRemovedTree);

#if ENABLE(TREE_DEBUGGING)
virtual void formatForDebugger(char* buffer, unsigned length) const;

0 comments on commit f84f10e

Please sign in to comment.