Chromium Code Reviews

Unified Diff: Source/core/dom/Node.cpp

Issue 1085843002: Implement DOM: prepend, append, before, after & replaceWith (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
« no previous file with comments | « Source/core/dom/Node.h ('k') | Source/core/dom/ParentNode.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/dom/Node.cpp
diff --git a/Source/core/dom/Node.cpp b/Source/core/dom/Node.cpp
index 56fb995d78a7033954fdda8b5b547b0d8d05500c..17f1020cc98f3ee50ba34fc6bc38dfd28bbbd2d1 100644
--- a/Source/core/dom/Node.cpp
+++ b/Source/core/dom/Node.cpp
@@ -382,6 +382,51 @@ void Node::clearRareData()
}
#endif
+static bool isNodeInNodes(const Node& node, const HeapVector<NodeOrString>& nodes)
philipj_slow 2015/06/26 14:13:25 Maybe move this block of statics to just before No
Paritosh Kumar 2015/06/30 10:49:09 Done.
+{
+ for (NodeOrString nodeOrString : nodes) {
philipj_slow 2015/06/26 14:13:26 I guess this should be "for (const NodeOrString& n
Paritosh Kumar 2015/06/30 10:49:09 Ohh, sorry. Thanks.
+ if (nodeOrString.isNode() && nodeOrString.getAsNode() == &node)
+ return true;
+ }
+ return false;
+}
+
+static Node* viablePreviousSibling(const Node& node, const HeapVector<NodeOrString>& nodes)
+{
+ for (Node* sibling = node.previousSibling(); sibling; sibling = sibling->previousSibling()) {
+ if (!isNodeInNodes(*sibling, nodes))
+ return sibling;
+ }
+ return nullptr;
+}
+
+static Node* viableNextSibling(const Node& node, const HeapVector<NodeOrString>& nodes)
+{
+ for (Node* sibling = node.nextSibling(); sibling; sibling = sibling->nextSibling()) {
+ if (!isNodeInNodes(*sibling, nodes))
+ return sibling;
+ }
+ return nullptr;
+}
+
+static PassRefPtrWillBeRawPtr<Node> nodeOrStringToNode(const NodeOrString& nodeOrString, Document& document)
+{
+ if (nodeOrString.isNode())
+ return nodeOrString.getAsNode();
+ return Text::create(document, nodeOrString.getAsString());
+}
+
+static PassRefPtrWillBeRawPtr<Node> convertNodesIntoNode(const HeapVector<NodeOrString>& nodes, Document& document)
+{
+ if (nodes.size() == 1)
+ return nodeOrStringToNode(nodes[0], document);
+
+ RefPtrWillBeRawPtr<Node> node = DocumentFragment::create(document);
philipj_slow 2015/06/26 14:13:26 For clarity I would name this fragment instead of
Paritosh Kumar 2015/06/30 10:49:08 Done.
+ for (const NodeOrString& nodeOrString : nodes)
+ node->appendChild(nodeOrStringToNode(nodeOrString, document), ASSERT_NO_EXCEPTION);
+ return node.release();
+}
+
Node* Node::toNode()
{
return this;
@@ -501,6 +546,49 @@ PassRefPtrWillBeRawPtr<Node> Node::appendChild(PassRefPtrWillBeRawPtr<Node> newC
return nullptr;
}
+void Node::prepend(const HeapVector<NodeOrString>& nodes, ExceptionState& exceptionState)
+{
+ this->insertBefore(convertNodesIntoNode(nodes, document()), this->firstChild(), exceptionState);
philipj_slow 2015/06/26 14:13:26 Is "this->" needed?
Paritosh Kumar 2015/06/30 10:49:09 No.
philipj_slow 2015/07/02 09:20:01 How about the "this->" at the beginning of the lin
+}
+
+void Node::append(const HeapVector<NodeOrString>& nodes, ExceptionState& exceptionState)
+{
+ this->appendChild(convertNodesIntoNode(nodes, document()), exceptionState);
+}
+
+void Node::before(const HeapVector<NodeOrString>& nodes, ExceptionState& exceptionState)
+{
+ Node* parent = parentNode();
+ if (!parent)
+ return;
+ Node* viablePreviousSiblingNode = viablePreviousSibling(*this, nodes);
philipj_slow 2015/06/26 14:13:26 Can this bit be written like the spec, with an |vi
Paritosh Kumar 2015/06/30 10:49:09 Changed with conditional. Yes, this should be viab
philipj_slow 2015/07/02 09:20:01 I see that you changed the before.html test, but c
+ if (!viablePreviousSiblingNode)
+ parent->insertBefore(convertNodesIntoNode(nodes, document()), parent->firstChild(), exceptionState);
+ else
+ parent->insertBefore(convertNodesIntoNode(nodes, document()), viablePreviousSiblingNode, exceptionState);
+}
+
+void Node::after(const HeapVector<NodeOrString>& nodes, ExceptionState& exceptionState)
+{
+ Node* parent = parentNode();
+ if (!parent)
+ return;
+ Node* viableNextSiblingNode = viableNextSibling(*this, nodes);
+ parent->insertBefore(convertNodesIntoNode(nodes, document()), viableNextSiblingNode, exceptionState);
+}
+
+void Node::replaceWith(const HeapVector<NodeOrString>& nodes, ExceptionState& exceptionState)
+{
+ Node* parent = parentNode();
+ if (!parent)
+ return;
+ Node* viableNextSiblingNode = viableNextSibling(*this, nodes);
+ if (parent == parentNode())
philipj_slow 2015/06/26 14:13:26 The spec says "If context object’s parent is paren
Paritosh Kumar 2015/06/30 10:49:09 Hmmm, This looks very strange but @Annevk has take
philipj_slow 2015/07/02 09:20:01 Discussed with Anne on IRC: http://krijnhoetmer.nl
+ parent->replaceChild(convertNodesIntoNode(nodes, document()), this, exceptionState);
+ else
+ parent->insertBefore(convertNodesIntoNode(nodes, document()), viableNextSiblingNode, exceptionState);
+}
+
void Node::remove(ExceptionState& exceptionState)
{
if (ContainerNode* parent = parentNode())
« no previous file with comments | « Source/core/dom/Node.h ('k') | Source/core/dom/ParentNode.h » ('j') | no next file with comments »

Powered by Google App Engine