nsGenericElement::InsertBefore(nsIDOMNode *aNewChild, nsIDOMNode *aRefChild, nsIDOMNode **aReturn) { if (!aReturn) { return NS_ERROR_NULL_POINTER;
NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn) { return nsGenericElement::doInsertBefore(aNewChild, aRefChild, aReturn);
nsGenericElement::InsertBefore(nsIDOMNode *aNewChild, nsIDOMNode *aRefChild,                               nsIDOMNode **aReturn){  if (!aReturn) {    return NS_ERROR_NULL_POINTER;  }  *aReturn = nsnull;  if (!aNewChild) {    return NS_ERROR_NULL_POINTER;  }  nsCOMPtr<nsIContent> refContent;  nsresult res = NS_OK;  PRInt32 refPos = 0;  if (aRefChild) {    refContent = do_QueryInterface(aRefChild, &res);    if (NS_FAILED(res)) {      /*       * If aRefChild doesn't support the nsIContent interface it can't be       * an existing child of this node.       */      return NS_ERROR_DOM_NOT_FOUND_ERR;    }    refPos = IndexOf(refContent);    if (refPos < 0) {      return NS_ERROR_DOM_NOT_FOUND_ERR;    }  } else {    refPos = GetChildCount();  }  PRUint16 nodeType = 0;  res = aNewChild->GetNodeType(&nodeType);  if (NS_FAILED(res)) {    return res;  }  switch (nodeType) {  case nsIDOMNode::ELEMENT_NODE :  case nsIDOMNode::TEXT_NODE :  case nsIDOMNode::CDATA_SECTION_NODE :  case nsIDOMNode::ENTITY_REFERENCE_NODE :  case nsIDOMNode::PROCESSING_INSTRUCTION_NODE :  case nsIDOMNode::COMMENT_NODE :  case nsIDOMNode::DOCUMENT_FRAGMENT_NODE :    break;  default:    /*     * aNewChild is of invalid type.     */    return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;  }  nsCOMPtr<nsIContent> newContent(do_QueryInterface(aNewChild, &res));  if (NS_FAILED(res)) {    return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;  }  nsCOMPtr<nsIDocument> old_doc = newContent->GetDocument();  if (old_doc && old_doc != GetDocument() &&      !nsContentUtils::CanCallerAccess(aNewChild)) {    return NS_ERROR_DOM_SECURITY_ERR;  }  /*   * Make sure the new child is not "this" node or one of this nodes   * ancestors. Doing this check here should be safe even if newContent   * is a document fragment.   */  if (isSelfOrAncestor(this, newContent)) {    return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;  }  /*   * Check if we're inserting a document fragment. If we are, we need   * to remove the children of the document fragment and add them   * individually (i.e. we don't add the actual document fragment).   */  if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {    nsCOMPtr<nsIDocumentFragment> doc_fragment(do_QueryInterface(newContent));    NS_ENSURE_TRUE(doc_fragment, NS_ERROR_UNEXPECTED);    doc_fragment->DisconnectChildren();    PRUint32 count = newContent->GetChildCount();    PRUint32 old_count = GetChildCount();    PRBool do_notify = !!aRefChild;    // If do_notify is true, then we don't have to handle the notifications    // ourselves...  Also, if count is 0 there will be no updates.  So we only    // want an update batch to happen if count is nonzero and do_notify is not    // true.    mozAutoDocUpdate updateBatch(GetDocument(), UPDATE_CONTENT_MODEL,                                 count && !do_notify);        /*     * Iterate through the fragments children, removing each from     * the fragment and inserting it into the child list of its     * new parent.     */    nsCOMPtr<nsIContent> childContent;    for (PRUint32 i = 0; i < count; ++i) {      // Get the n:th child from the document fragment. Since we      // disconnected the children from the document fragment they      // won't be removed from the document fragment when inserted      // into the new parent. This lets us do this operation *much*      // faster.      childContent = newContent->GetChildAt(i);      // Insert the child and increment the insertion position      res = InsertChildAt(childContent, refPos++, do_notify);      if (NS_FAILED(res)) {        break;      }    }    if (NS_FAILED(res)) {      // This should put the children that were moved out of the      // document fragment back into the document fragment and remove      // them from the element they were intserted into.      doc_fragment->ReconnectChildren();      return res;    }    nsIDocument *doc = GetDocument();    if (count && !do_notify && doc) {      doc->ContentAppended(this, old_count);    }    doc_fragment->DropChildReferences();  } else {    nsCOMPtr<nsIDOMNode> oldParent;    res = aNewChild->GetParentNode(getter_AddRefs(oldParent));    if (NS_FAILED(res)) {      return res;    }    /*     * Remove the element from the old parent if one exists, since oldParent     * is a nsIDOMNode this will do the right thing even if the parent of     * aNewChild is a document. This code also handles the case where the     * new child is alleady a child of this node-- jst@citec.fi     */    if (oldParent) {      nsCOMPtr<nsIDOMNode> tmpNode;      PRUint32 origChildCount = GetChildCount();      /*       * We don't care here if the return fails or not.       */      oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));      PRUint32 newChildCount = GetChildCount();      /*       * Check if our child count changed during the RemoveChild call, if       * it did then oldParent is most likely this node. In this case we       * must check if refPos is still correct (unless it's zero).       */      if (refPos && origChildCount != newChildCount) {        if (refContent) {          /*           * If we did get aRefChild we check if that is now at refPos - 1,           * this will happend if the new child was one of aRefChilds'           * previous siblings.           */          if (refContent == GetChildAt(refPos - 1)) {            refPos--;          }        } else {          /*           * If we didn't get aRefChild we simply decrement refPos.           */          refPos--;        }      }    }    if (!newContent->IsContentOfType(eXUL)) {      nsContentUtils::ReparentContentWrapper(newContent, this, GetDocument(),                                             old_doc);    }    res = InsertChildAt(newContent, refPos, PR_TRUE);    if (NS_FAILED(res)) {      return res;    }  }  *aReturn = aNewChild;  NS_ADDREF(*aReturn);  return res;}