Chromium Code Reviews| Index: sky/engine/core/dom/ContainerNode.cpp |
| diff --git a/sky/engine/core/dom/ContainerNode.cpp b/sky/engine/core/dom/ContainerNode.cpp |
| index e3d68999ff9a50aa4737281bc53cc949001ac416..f82ca93a3de45db8f21e602a40683c02553232cb 100644 |
| --- a/sky/engine/core/dom/ContainerNode.cpp |
| +++ b/sky/engine/core/dom/ContainerNode.cpp |
| @@ -73,18 +73,6 @@ ContainerNode::~ContainerNode() |
| removeDetachedChildren(); |
| } |
| -bool ContainerNode::isChildTypeAllowed(const Node& child) const |
| -{ |
| - if (!child.isDocumentFragment()) |
| - return childTypeAllowed(child.nodeType()); |
| - |
| - for (Node* node = toDocumentFragment(child).firstChild(); node; node = node->nextSibling()) { |
| - if (!childTypeAllowed(node->nodeType())) |
| - return false; |
| - } |
| - return true; |
| -} |
| - |
| bool ContainerNode::containsConsideringHostElements(const Node& newChild) const |
| { |
| if (isInShadowTree() || document().isTemplateDocument()) |
| @@ -92,51 +80,38 @@ bool ContainerNode::containsConsideringHostElements(const Node& newChild) const |
| return newChild.contains(this); |
| } |
| -bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild, ExceptionState& exceptionState) const |
| +void ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild, ExceptionState& exceptionState) const |
| { |
| // Not mentioned in spec: throw NotFoundError if newChild is null |
| if (!newChild) { |
| exceptionState.throwDOMException(NotFoundError, "The new child element is null."); |
| - return false; |
| + return; |
| } |
| - // Use common case fast path if possible. |
| - if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()) { |
| - ASSERT(isChildTypeAllowed(*newChild)); |
| - if (containsConsideringHostElements(*newChild)) { |
| - exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent."); |
| - return false; |
| - } |
| - return true; |
| + if (newChild->isTreeScope()) { |
| + exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '" + newChild->nodeName() + "' may not be inserted inside nodes of type '" + nodeName() + "'."); |
| + return; |
| } |
| if (containsConsideringHostElements(*newChild)) { |
| exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent."); |
| - return false; |
| + return; |
| } |
| - if (oldChild && isDocumentNode()) { |
| - if (!toDocument(this)->canReplaceChild(*newChild, *oldChild)) { |
| - // FIXME: Adjust 'Document::canReplaceChild' to return some additional detail (or an error message). |
| - exceptionState.throwDOMException(HierarchyRequestError, "Failed to replace child."); |
| - return false; |
| + // TODO(esprehn): Remove this, sky should allow multiple top level elements. |
| + if (isDocumentNode()) { |
| + unsigned elementCount = 0; |
| + if (newChild->isElementNode()) { |
| + elementCount = 1; |
| + } else if (newChild->isDocumentFragment()) { |
| + for (Element* element = ElementTraversal::firstChild(*newChild); element; element = ElementTraversal::nextSibling(*element)) |
| + ++elementCount; |
| + } |
| + if (elementCount > 1 || ((!oldChild || !oldChild->isElementNode()) && elementCount && document().documentElement())) { |
| + exceptionState.throwDOMException(HierarchyRequestError, "Document can only contain one Element."); |
| + return; |
| } |
| - } else if (!isChildTypeAllowed(*newChild)) { |
| - exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '" + newChild->nodeName() + "' may not be inserted inside nodes of type '" + nodeName() + "'."); |
| - return false; |
| - } |
| - |
| - return true; |
| -} |
| - |
| -bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, ExceptionState& exceptionState) const |
| -{ |
| - ASSERT(isChildTypeAllowed(newChild)); |
| - if (newChild.contains(this)) { |
| - exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent."); |
| - return false; |
| } |
| - return true; |
| } |
| PassRefPtr<Node> ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState) |
| @@ -152,12 +127,10 @@ PassRefPtr<Node> ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* re |
| return appendChild(newChild, exceptionState); |
| } |
| - // Make sure adding the new child is OK. |
| - if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return newChild; |
| - } |
| + checkAcceptChild(newChild.get(), 0, exceptionState); |
| + if (exceptionState.hadException()) |
| + return nullptr; |
| + |
| ASSERT(newChild); |
| // NotFoundError: Raised if refChild is not a child of this node |
| @@ -179,13 +152,6 @@ PassRefPtr<Node> ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* re |
| if (targets.isEmpty()) |
| return newChild; |
| - // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. |
|
ojan
2014/11/18 02:46:57
I think we still need this because of blur events,
esprehn
2014/11/18 03:01:40
Ah yeah, damn. Maybe we should make them async?
|
| - if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return newChild; |
| - } |
| - |
| ChildListMutationScope mutation(*this); |
| for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { |
| ASSERT(*it); |
| @@ -268,12 +234,9 @@ PassRefPtr<Node> ContainerNode::replaceChild(PassRefPtr<Node> newChild, PassRefP |
| RefPtr<Node> child = oldChild; |
| - // Make sure replacing the old child with the new is ok |
| - if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return child; |
| - } |
| + checkAcceptChild(newChild.get(), child.get(), exceptionState); |
| + if (exceptionState.hadException()) |
| + return nullptr; |
| // NotFoundError: Raised if oldChild is not a child of this node. |
| if (child->parentNode() != this) { |
| @@ -293,25 +256,11 @@ PassRefPtr<Node> ContainerNode::replaceChild(PassRefPtr<Node> newChild, PassRefP |
| if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do |
| return child; |
| - // Does this one more time because removeChild() fires a MutationEvent. |
|
ojan
2014/11/18 02:46:57
Ditto
|
| - if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return child; |
| - } |
| - |
| NodeVector targets; |
| collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
| if (exceptionState.hadException()) |
| return nullptr; |
| - // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent. |
|
ojan
2014/11/18 02:46:56
Ditto
|
| - if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return child; |
| - } |
| - |
| // Add the new child(ren) |
| for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { |
| ASSERT(*it); |
| @@ -545,12 +494,10 @@ PassRefPtr<Node> ContainerNode::appendChild(PassRefPtr<Node> newChild, Exception |
| // If it is, it can be deleted as a side effect of sending mutation events. |
| ASSERT(refCount() || parentOrShadowHostNode()); |
| - // Make sure adding the new child is ok |
| - if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return newChild; |
| - } |
| + checkAcceptChild(newChild.get(), 0, exceptionState); |
| + if (exceptionState.hadException()) |
| + return nullptr; |
| + |
| ASSERT(newChild); |
| if (newChild == m_lastChild) // nothing to do |
| @@ -564,13 +511,6 @@ PassRefPtr<Node> ContainerNode::appendChild(PassRefPtr<Node> newChild, Exception |
| if (targets.isEmpty()) |
| return newChild; |
| - // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. |
|
ojan
2014/11/18 02:46:56
ditto
|
| - if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) { |
| - if (exceptionState.hadException()) |
| - return nullptr; |
| - return newChild; |
| - } |
| - |
| // Now actually add the child(ren) |
| ChildListMutationScope mutation(*this); |
| for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { |