Relanding patches that (hopefully) don't affect Tdhtml

This commit is contained in:
cvshook%sicking.cc 2006-03-24 00:09:50 +00:00
parent ace148d610
commit 1b3207b1d5
16 changed files with 365 additions and 557 deletions

View File

@ -3623,43 +3623,11 @@ nsDocument::GetLocalName(nsAString& aLocalName)
return NS_OK;
}
nsresult
nsDocument::IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent)
{
if (aNodeType != nsIDOMNode::COMMENT_NODE &&
aNodeType != nsIDOMNode::ELEMENT_NODE &&
aNodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE &&
aNodeType != nsIDOMNode::DOCUMENT_TYPE_NODE) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
if (aNodeType == nsIDOMNode::ELEMENT_NODE && mRootContent &&
mRootContent != aRefContent) {
// We already have a child Element, and we're not trying to
// replace it, so throw an error.
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
if (aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) {
nsCOMPtr<nsIDOMDocumentType> docType;
GetDoctype(getter_AddRefs(docType));
nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
if (docTypeContent && docTypeContent != aRefContent) {
// We already have a doctype, and we're not trying to
// replace it, so throw an error.
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
nsIDOMNode** aReturn)
{
return nsGenericElement::doInsertBefore(aNewChild, aRefChild, nsnull, this,
return nsGenericElement::doReplaceOrInsertBefore(PR_FALSE, aNewChild, aRefChild, nsnull, this,
aReturn);
}
@ -3667,7 +3635,7 @@ NS_IMETHODIMP
nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
nsIDOMNode** aReturn)
{
return nsGenericElement::doReplaceChild(aNewChild, aOldChild, nsnull, this,
return nsGenericElement::doReplaceOrInsertBefore(PR_TRUE, aNewChild, aOldChild, nsnull, this,
aReturn);
}

View File

@ -772,8 +772,6 @@ protected:
nsString mBaseTarget;
private:
nsresult IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent);
void PostUnblockOnloadEvent();
static EventHandlerFunc HandleOnloadBlockerEvent;
static EventDestructorFunc DestroyOnloadBlockerEvent;

View File

@ -52,7 +52,7 @@
#include "nsIDOMUserDataHandler.h"
class nsDocumentFragment : public nsGenericElement,
public nsIDocumentFragment,
public nsIDOMDocumentFragment,
public nsIDOM3Node
{
public:
@ -62,11 +62,6 @@ public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// interface nsIDocumentFragment
NS_IMETHOD DisconnectChildren();
NS_IMETHOD ReconnectChildren();
NS_IMETHOD DropChildReferences();
// interface nsIDOMDocumentFragment
NS_IMETHOD GetNodeName(nsAString& aNodeName)
{ return nsGenericElement::GetNodeName(aNodeName); }
@ -194,7 +189,6 @@ nsDocumentFragment::~nsDocumentFragment()
// QueryInterface implementation for nsDocumentFragment
NS_INTERFACE_MAP_BEGIN(nsDocumentFragment)
NS_INTERFACE_MAP_ENTRY(nsIDocumentFragment)
NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentFragment)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOM3Node)
@ -208,71 +202,6 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDocumentFragment)
NS_IMPL_RELEASE(nsDocumentFragment)
NS_IMETHODIMP
nsDocumentFragment::DisconnectChildren()
{
PRUint32 i, count = GetChildCount();
for (i = 0; i < count; i++) {
NS_ASSERTION(GetChildAt(i)->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
// Safe to unbind PR_FALSE, since kids should never have a current document
// or a binding parent
GetChildAt(i)->UnbindFromTree(PR_FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsDocumentFragment::ReconnectChildren()
{
PRUint32 i, count = GetChildCount();
NS_PRECONDITION(GetCurrentDoc() == nsnull,
"We really shouldn't have a current doc!");
for (i = 0; i < count; i++) {
nsIContent *child = GetChildAt(i);
nsIContent *parent = child->GetParent();
if (parent) {
// This is potentially a O(n**2) operation, but it should only
// happen in error cases (such as out of memory or something
// similar) so we don't care for now.
// XXXbz I don't think this is O(n**2) with our IndexOf cache, is it?
PRInt32 indx = parent->IndexOf(child);
if (indx >= 0) {
parent->RemoveChildAt(indx, PR_TRUE);
}
}
nsresult rv = child->BindToTree(nsnull, this, nsnull, PR_FALSE);
if (NS_FAILED(rv)) {
// It's all bad now... Just forget about this kid, I guess
child->UnbindFromTree();
mAttrsAndChildren.RemoveChildAt(i);
// Adjust count and iterator accordingly
--count;
--i;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocumentFragment::DropChildReferences()
{
PRUint32 count = mAttrsAndChildren.ChildCount();
while (count > 0) {
mAttrsAndChildren.RemoveChildAt(--count);
}
return NS_OK;
}
NS_IMETHODIMP
nsDocumentFragment::GetNodeType(PRUint16* aNodeType)
{

View File

@ -772,6 +772,8 @@ nsDOMEventRTTearoff::AddEventListener(const nsAString& aType,
//----------------------------------------------------------------------
PRUint32 nsMutationGuard::sMutationCount = 0;
nsDOMSlots::nsDOMSlots(PtrBits aFlags)
: mFlags(aFlags),
mBindingParent(nsnull)
@ -2302,7 +2304,12 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
"Incorrect aDocument");
PRBool isAppend = (aIndex == aChildArray.ChildCount());
PRUint32 childCount = aChildArray.ChildCount();
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
nsMutationGuard::DidMutate();
PRBool isAppend = (aIndex == childCount);
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
@ -2390,6 +2397,8 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
"Incorrect aDocument");
nsMutationGuard::DidMutate();
nsINode* container = aParent;
if (!container) {
container = aDocument;
@ -2496,51 +2505,20 @@ nsGenericElement::DispatchClickEvent(nsPresContext* aPresContext,
* aChild is one of aNode's ancestors. -- jst@citec.fi
*/
/* static */
PRBool
nsGenericElement::isSelfOrAncestor(nsIContent *aNode,
nsIContent *aPossibleAncestor)
{
NS_PRECONDITION(aNode, "Must have a node");
if (aNode == aPossibleAncestor)
return PR_TRUE;
/*
* If aPossibleAncestor doesn't have children it can't be our ancestor
*/
if (aPossibleAncestor->GetChildCount() == 0) {
return PR_FALSE;
}
for (nsIContent* ancestor = aNode->GetParent();
ancestor;
ancestor = ancestor->GetParent()) {
if (ancestor == aPossibleAncestor) {
/*
* We found aPossibleAncestor as one of our ancestors
*/
return PR_TRUE;
}
}
return PR_FALSE;
}
NS_IMETHODIMP
nsGenericElement::InsertBefore(nsIDOMNode *aNewChild, nsIDOMNode *aRefChild,
nsIDOMNode **aReturn)
{
return doInsertBefore(aNewChild, aRefChild, this, GetCurrentDoc(),
aReturn);
return doReplaceOrInsertBefore(PR_FALSE, aNewChild, aRefChild, this, GetCurrentDoc(),
aReturn);
}
NS_IMETHODIMP
nsGenericElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
nsIDOMNode** aReturn)
{
return doReplaceChild(aNewChild, aOldChild, this, GetCurrentDoc(),
aReturn);
return doReplaceOrInsertBefore(PR_TRUE, aNewChild, aOldChild, this, GetCurrentDoc(),
aReturn);
}
NS_IMETHODIMP
@ -2570,6 +2548,10 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, PRUint16 aNewNodeType,
"Bogus node type passed");
#endif
if (aParent && nsContentUtils::ContentIsDescendantOf(aParent, aNewChild)) {
return PR_FALSE;
}
// The allowed child nodes differ for documents and elements
switch (aNewNodeType) {
case nsIDOMNode::COMMENT_NODE :
@ -2794,9 +2776,12 @@ NS_IMPL_ISUPPORTS1(nsFragmentObserver, nsIDocumentObserver)
/* static */
nsresult
nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
nsIContent* aParent, nsIDocument* aDocument,
nsIDOMNode** aReturn)
nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
nsIDOMNode* aNewChild,
nsIDOMNode* aRefChild,
nsIContent* aParent,
nsIDocument* aDocument,
nsIDOMNode** aReturn)
{
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
@ -2804,54 +2789,51 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
*aReturn = nsnull;
if (!aNewChild) {
if (!aNewChild || (aReplace && !aRefChild)) {
return NS_ERROR_NULL_POINTER;
}
// Keep a strong reference to the node that we'll return to ensure it
// doesn't go away.
nsCOMPtr<nsIDOMNode> returnVal = aReplace ? aRefChild : aNewChild;
nsCOMPtr<nsIContent> refContent;
nsresult res = NS_OK;
PRInt32 refPos = 0;
PRInt32 insPos;
nsINode* container = aParent;
if (!container) {
container = aDocument;
}
// Figure out which index to insert at
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.
*/
refContent = do_QueryInterface(aRefChild);
insPos = container->IndexOf(refContent);
if (insPos < 0) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
refPos = container->IndexOf(refContent);
if (aRefChild == aNewChild) {
NS_ADDREF(*aReturn = aNewChild);
if (refPos < 0) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
return NS_OK;
}
} else {
refPos = container->GetChildCount();
insPos = container->GetChildCount();
}
nsCOMPtr<nsIContent> newContent(do_QueryInterface(aNewChild, &res));
if (NS_FAILED(res)) {
nsCOMPtr<nsIContent> newContent = do_QueryInterface(aNewChild);
if (!newContent) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
PRUint16 nodeType = 0;
res = aNewChild->GetNodeType(&nodeType);
NS_ENSURE_SUCCESS(res, res);
if (NS_FAILED(res)) {
return res;
}
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_FALSE,
// Make sure that the inserted node is allowed as a child of its new parent.
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, aReplace,
refContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
@ -2876,14 +2858,37 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
}
}
}
/*
* Make sure the new child is not aParent or one of aParent's
* ancestors. Doing this check here should be safe even if newContent
* is a document fragment.
*/
if (aParent && isSelfOrAncestor(aParent, newContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
// We want an update batch when we expect several mutations to be performed,
// which is when we're replacing a node, or when we're inserting a fragment.
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL,
aReplace || nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
// If we're replacing
if (aReplace) {
// Getting (and addrefing) the following child here is sort of wasteful
// in the common case, but really, it's not that expensive. Get over it.
refContent = container->GetChildAt(insPos + 1);
nsMutationGuard guard;
res = container->RemoveChildAt(insPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
if (guard.Mutated(1)) {
insPos = refContent ? container->IndexOf(refContent) :
container->GetChildCount();
if (insPos < 0) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
// Passing PR_FALSE for aIsReplace since we now have removed the node
// to be replaced.
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument,
PR_FALSE, refContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
}
/*
@ -2892,23 +2897,42 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
* 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);
PRUint32 count = newContent->GetChildCount();
PRUint32 old_count = container->GetChildCount();
PRBool do_notify = refContent || !aParent;
PRBool do_notify = !!aRefChild || !aParent;
// Copy the children into a separate array to avoid having to deal with
// mutations to the fragment while we're inserting.
nsCOMArray<nsIContent> fragChildren;
if (!fragChildren.SetCapacity(count)) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint32 i;
for (i = 0; i < count; i++) {
nsIContent* child = newContent->GetChildAt(i);
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
fragChildren.AppendObject(child);
}
// Remove the children from the fragment and flag for possible mutations.
PRBool mutated = PR_FALSE;
for (i = count; i > 0;) {
// We don't need to update i if someone mutates the DOM. The only thing
// that'd happen is that the resulting child list might be unexpected,
// but we should never crash since RemoveChildAt is out-of-bounds safe.
nsMutationGuard guard;
newContent->RemoveChildAt(--i, PR_TRUE);
mutated = mutated || guard.Mutated(1);
}
// Set up observer that notifies if needed.
nsRefPtr<nsFragmentObserver> fragmentObs;
if (count && !do_notify) {
fragmentObs = new nsFragmentObserver(old_count, aParent, aDocument);
fragmentObs = new nsFragmentObserver(container->GetChildCount(), aParent, aDocument);
NS_ENSURE_TRUE(fragmentObs, NS_ERROR_OUT_OF_MEMORY);
fragmentObs->Connect();
}
doc_fragment->DisconnectChildren();
// 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
@ -2916,26 +2940,44 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL,
count && !do_notify);
/*
* Iterate through the fragment's children, removing each from
* the fragment and inserting it into the child list of its
* new parent.
*/
// Iterate through the fragment's children, and insert them in the new
// parent
for (i = 0; i < count; ++i) {
// Get the n:th child from the array.
nsIContent* childContent = fragChildren[i];
nsCOMPtr<nsIContent> childContent;
// If we've had any unexpeted mutations so far we need to recheck that
// the child can still be inserted.
if (mutated) {
// We really only need to update insPos if we *just* got an unexpected
// mutation as opposed to 3 insertions ago. But this is an edgecase so
// no need to over optimize.
insPos = refContent ? container->IndexOf(refContent) :
container->GetChildCount();
if (insPos < 0) {
// Someone seriously messed up the childlist. We have no idea
// where to insert the remaining children, so just bail.
res = NS_ERROR_DOM_NOT_FOUND_ERR;
break;
}
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);
nsCOMPtr<nsIDOMNode> tmpNode = do_QueryInterface(childContent);
PRUint16 tmpType = 0;
tmpNode->GetNodeType(&tmpType);
if (childContent->GetParent() || childContent->IsInDoc() ||
!IsAllowedAsChild(childContent, tmpType, aParent, aDocument, PR_FALSE,
refContent)) {
res = NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
break;
}
}
nsMutationGuard guard;
// XXXbz how come no reparenting here? That seems odd...
// Insert the child and increment the insertion position
res = container->InsertChildAt(childContent, refPos++, do_notify);
// Insert the child.
res = container->InsertChildAt(childContent, insPos, do_notify);
if (NS_FAILED(res)) {
break;
}
@ -2943,17 +2985,21 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
if (fragmentObs) {
fragmentObs->ChildBound();
}
// Check to see if any evil mutation events mucked around with the
// child list.
mutated = mutated || guard.Mutated(1);
++insPos;
}
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 or document they were inserted into.
doc_fragment->ReconnectChildren();
if (fragmentObs) {
fragmentObs->Disconnect();
}
// We could try to put the nodes back into the fragment here if we
// really cared.
return res;
}
@ -2962,9 +3008,9 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
NS_ASSERTION(count && !do_notify, "Unexpected state");
fragmentObs->Finish();
}
doc_fragment->DropChildReferences();
} else {
}
else {
// Not inserting a fragment but rather a single node.
nsIContent* bindingParent = newContent->GetBindingParent();
if (bindingParent == newContent ||
(bindingParent && bindingParent == newContent->GetParent())) {
@ -2972,247 +3018,67 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
/*
* 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
*/
nsCOMPtr<nsIDOMNode> oldParent;
res = aNewChild->GetParentNode(getter_AddRefs(oldParent));
NS_ENSURE_SUCCESS(res, res);
PRBool newContentIsXUL = newContent->IsContentOfType(eXUL);
// Remove the element from the old parent if one exists
nsINode* oldParent = newContent->GetParent();
if (!oldParent) {
oldParent = newContent->GetCurrentDoc();
// See bug 53901. Crappy XUL sometimes lies about being in the document
if (oldParent && newContentIsXUL && oldParent->IndexOf(newContent) < 0) {
oldParent = nsnull;
}
}
if (oldParent) {
nsCOMPtr<nsIDOMNode> tmpNode;
PRInt32 removeIndex = oldParent->IndexOf(newContent);
NS_ASSERTION(removeIndex >= 0 &&
!(oldParent == container && removeIndex == insPos),
"invalid removeIndex");
PRUint32 origChildCount = container->GetChildCount();
nsMutationGuard guard;
/*
* We don't care here if the return fails or not.
*/
oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));
res = oldParent->RemoveChildAt(removeIndex, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
PRUint32 newChildCount = container->GetChildCount();
// Adjust insert index if the node we ripped out was a sibling
// of the node we're inserting before
if (oldParent == container && removeIndex < insPos) {
--insPos;
}
/*
* 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 (guard.Mutated(1)) {
insPos = refContent ? container->IndexOf(refContent) :
container->GetChildCount();
if (insPos < 0) {
// Someone seriously messed up the childlist. We have no idea
// where to insert the new child, so just bail.
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
if (refContent == container->GetChildAt(refPos - 1)) {
refPos--;
}
} else {
/*
* If we didn't get aRefChild we simply decrement refPos.
*/
refPos--;
if (newContent->GetParent() || newContent->IsInDoc() ||
!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_FALSE,
refContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
}
if (!newContent->IsContentOfType(eXUL)) {
if (!newContentIsXUL) {
nsContentUtils::ReparentContentWrapper(newContent, aParent,
container->GetOwnerDoc(),
old_doc);
}
res = container->InsertChildAt(newContent, refPos, PR_TRUE);
if (NS_FAILED(res)) {
return res;
}
res = container->InsertChildAt(newContent, insPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
}
*aReturn = aNewChild;
NS_ADDREF(*aReturn);
returnVal.swap(*aReturn);
return res;
}
/* static */
nsresult
nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
nsIContent* aParent, nsIDocument* aDocument,
nsIDOMNode** aReturn)
{
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
"Incorrect aDocument");
*aReturn = nsnull;
if (!aNewChild || !aOldChild) {
return NS_ERROR_NULL_POINTER;
}
nsresult res = NS_OK;
PRInt32 oldPos = 0;
nsCOMPtr<nsIContent> oldContent = do_QueryInterface(aOldChild);
nsINode* container = aParent;
if (!container) {
container = aDocument;
}
// if oldContent is null IndexOf will return < 0, which is what we want
// since aOldChild couldn't be a child.
oldPos = container->IndexOf(oldContent);
if (oldPos < 0) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
nsCOMPtr<nsIContent> replacedChild = container->GetChildAt(oldPos);
PRUint16 nodeType = 0;
res = aNewChild->GetNodeType(&nodeType);
if (NS_FAILED(res)) {
return res;
}
nsCOMPtr<nsIContent> newContent(do_QueryInterface(aNewChild, &res));
if (NS_FAILED(res)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_TRUE,
oldContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
nsIDocument* old_doc = newContent->GetOwnerDoc();
// XXXbz The document code and content code have two totally different
// security checks here. Why? Because I'm afraid to change such things this
// close to 1.8. But which should we do here, really? Or both? For example
// what should a caller with UniversalBrowserRead/Write/whatever be able to
// do, exactly? Do we need to be more careful with documents because random
// callers _can_ get access to them? That might be....
if (old_doc && old_doc != container->GetOwnerDoc()) {
if (aParent) {
if (!nsContentUtils::CanCallerAccess(aNewChild)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
} else {
nsCOMPtr<nsIDOMNode> doc(do_QueryInterface(aDocument));
if (NS_FAILED(nsContentUtils::CheckSameOrigin(doc, aNewChild))) {
return NS_ERROR_DOM_SECURITY_ERR;
}
}
}
/*
* Make sure the new child is not aParent or one of aParent's
* ancestors. Doing this check here should be safe even if newContent
* is a document fragment.
*/
if (aParent && isSelfOrAncestor(aParent, newContent)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
// We're ready to start inserting children, so let's start a batch
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, PR_TRUE);
/*
* Check if this is a document fragment. If it is, 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<nsIContent> childContent;
PRUint32 i, count = newContent->GetChildCount();
res = container->RemoveChildAt(oldPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
/*
* Iterate through the fragments children, removing each from
* the fragment and inserting it into the child list of its
* new parent.
*/
for (i = 0; i < count; ++i) {
// Always get and remove the first child, since the child indexes
// change as we go along.
childContent = newContent->GetChildAt(0);
res = newContent->RemoveChildAt(0, PR_FALSE);
NS_ENSURE_SUCCESS(res, res);
// XXXbz how come no reparenting here?
// Insert the child and increment the insertion position
res = container->InsertChildAt(childContent, oldPos++, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
}
}
else {
nsCOMPtr<nsIDOMNode> oldParent;
res = aNewChild->GetParentNode(getter_AddRefs(oldParent));
NS_ENSURE_SUCCESS(res, 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) {
PRUint32 origChildCount = container->GetChildCount();
/*
* We don't care here if the return fails or not.
*/
nsCOMPtr<nsIDOMNode> tmpNode;
oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));
PRUint32 newChildCount = container->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 oldPos is still correct (unless it's zero).
*/
if (oldPos && origChildCount != newChildCount) {
/*
* Check if aOldChild is now at oldPos - 1, this will happend if
* the new child was one of aOldChilds' previous siblings.
*/
nsIContent *tmpContent = container->GetChildAt(oldPos - 1);
if (oldContent == tmpContent) {
oldPos--;
}
}
}
if (!newContent->IsContentOfType(eXUL)) {
nsContentUtils::ReparentContentWrapper(newContent, aParent,
container->GetOwnerDoc(),
old_doc);
}
// If we're replacing a child with itself the child
// has already been removed from this element once we get here.
if (aNewChild != aOldChild) {
res = container->RemoveChildAt(oldPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
}
res = container->InsertChildAt(newContent, oldPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
}
return CallQueryInterface(replacedChild, aReturn);
}
/* static */
nsresult
nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild,

View File

@ -283,6 +283,77 @@ private:
nsCOMPtr<nsIContent> mContent;
};
/**
* Class used to detect unexpected mutations. To use the class create an
* nsMutationGuard on the stack before unexpected mutations could occur.
* You can then at any time call Mutated to check if any unexpected mutations
* have occured.
*
* When a guard is instantiated sMutationCount is set to 300. It is then
* decremented by every mutation (capped at 0). This means that we can only
* detect 300 mutations during the lifetime of a single guard, however that
* should be more then we ever care about as we usually only care if more then
* one mutation has occured.
*
* When the guard goes out of scope it will adjust sMutationCount so that over
* the lifetime of the guard the guard itself has not affected sMutationCount,
* while mutations that happened while the guard was alive still will. This
* allows a guard to be instantiated even if there is another guard higher up
* on the callstack watching for mutations.
*
* The only thing that has to be avoided is for an outer guard to be used
* while an inner guard is alive. This can be avoided by only ever
* instantiating a single guard per scope and only using the guard in the
* current scope.
*/
class nsMutationGuard {
public:
nsMutationGuard()
{
mDelta = eMaxMutations - sMutationCount;
sMutationCount = eMaxMutations;
}
~nsMutationGuard()
{
sMutationCount =
mDelta > sMutationCount ? 0 : sMutationCount - mDelta;
}
/**
* Returns true if any unexpected mutations have occured. You can pass in
* an 8-bit ignore count to ignore a number of expected mutations.
*/
PRBool Mutated(PRUint8 aIgnoreCount)
{
return sMutationCount < NS_STATIC_CAST(PRUint32, eMaxMutations - aIgnoreCount);
}
// This function should be called whenever a mutation that we want to keep
// track of happen. For now this is only done when children are added or
// removed, but we might do it for attribute changes too in the future.
static void DidMutate()
{
if (sMutationCount) {
--sMutationCount;
}
}
private:
// mDelta is the amount sMutationCount was adjusted when the guard was
// initialized. It is needed so that we can undo that adjustment once
// the guard dies.
PRUint32 mDelta;
// The value 300 is not important, as long as it is bigger then anything
// ever passed to Mutated().
enum { eMaxMutations = 300 };
// sMutationCount is a global mutation counter which is decreased by one at
// every mutation. It is capped at 0 to avoid wrapping.
// It's value is always between 0 and 300, inclusive.
static PRUint32 sMutationCount;
};
/**
* A generic base class for DOM elements, implementing many nsIContent,
@ -576,43 +647,22 @@ public:
static PRBool ShouldFocus(nsIContent *aContent);
/**
* Checks if a node is the ancestor of another.
*/
static PRBool isSelfOrAncestor(nsIContent *aNode,
nsIContent *aPossibleAncestor);
/**
* Actual implementation of the DOM InsertBefore method. Shared by
* nsDocument. When called from nsDocument, aParent will be null.
* Actual implementation of the DOM InsertBefore and ReplaceChild methods.
* Shared by nsDocument. When called from nsDocument, aParent will be null.
*
* @param aReplace True if aNewChild should replace aRefChild. False if
* aNewChild should be inserted before aRefChild.
* @param aNewChild The child to insert
* @param aRefChild The child to insert before
* @param aRefChild The child to insert before or replace
* @param aParent The parent to use for the new child
* @param aDocument The document to use for the new child.
* Must be non-null, if aParent is null and must match
* aParent->GetCurrentDoc() if aParent is not null.
* @param aReturn [out] the child we insert
*/
static nsresult doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
nsIContent* aParent, nsIDocument* aDocument,
nsIDOMNode** aReturn);
/**
* Actual implementation of the DOM ReplaceChild method. Shared by
* nsDocument. When called from nsDocument, aParent will be null.
*
* @param aNewChild The child to replace with
* @param aOldChild The child to replace
* @param aParent The parent to use for the new child
* @param aDocument The document to use for the new child.
* Must be non-null if aParent is null and must match
* aParent->GetCurrentDoc() if aParent is not null.
* @param aChildArray The child array to work with
* @param aReturn [out] the child we insert
*/
static nsresult doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
nsIContent* aParent, nsIDocument* aDocument,
nsIDOMNode** aReturn);
static nsresult doReplaceOrInsertBefore(PRBool aReplace, nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
nsIContent* aParent, nsIDocument* aDocument,
nsIDOMNode** aReturn);
/**
* Actual implementation of the DOM RemoveChild method. Shared by
@ -706,7 +756,7 @@ public:
const nsAttrName* mName;
const nsAttrValue* mValue;
};
protected:
/**
* Set attribute and (if needed) notify documentobservers and fire off
@ -1011,41 +1061,6 @@ protected:
nsAttrAndChildArray mAttrsAndChildren;
};
// Internal non-public interface
// IID for the nsIDocumentFragment interface
#define NS_IDOCUMENTFRAGMENT_IID \
{ 0xd8fb2853, 0xf6d6, 0x4499, \
{0x9c, 0x60, 0x6c, 0xa2, 0x75, 0x35, 0x09, 0xeb} }
// nsIDocumentFragment interface
/**
* These methods are supposed to be used when *all* children of a
* document fragment are moved at once into a new parent w/o
* changing the relationship between the children. If the moving
* operation fails and some children were moved to a new parent and
* some weren't, ReconnectChildren() should be called to remove the
* children from their possible new parent and re-insert the
* children into the document fragment. Once the operation is
* complete and all children are successfully moved into their new
* parent DropChildReferences() should be called so that the
* document fragment will loose its references to the children.
*/
class nsIDocumentFragment : public nsIDOMDocumentFragment
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENTFRAGMENT_IID)
/** Tell the children their parent is gone */
NS_IMETHOD DisconnectChildren() = 0;
/** Put all children back in the fragment */
NS_IMETHOD ReconnectChildren() = 0;
/** Drop references to children */
NS_IMETHOD DropChildReferences() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentFragment, NS_IDOCUMENTFRAGMENT_IID)
#define NS_FORWARD_NSIDOMNODE_NO_CLONENODE(_to) \
NS_IMETHOD GetNodeName(nsAString& aNodeName) { \
return _to GetNodeName(aNodeName); \

View File

@ -85,9 +85,8 @@ class txXMLParser
#endif
nsresult
txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer,
const txXPathNode& aLoader, nsAString& aErrMsg,
txXPathNode** aResult)
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
nsAString& aErrMsg, txXPathNode** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nsnull;
@ -109,11 +108,7 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer,
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel);
if (http) {
nsCOMPtr<nsIURI> refUri;
NS_NewURI(getter_AddRefs(refUri), aReferrer);
if (refUri) {
http->SetReferrer(refUri);
}
http->SetReferrer(loaderUri);
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
PR_FALSE);

View File

@ -57,9 +57,8 @@ class txXPathNode;
* of the document aLoader.
*/
extern "C" nsresult
txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer,
const txXPathNode& aLoader, nsAString& aErrMsg,
txXPathNode** aResult);
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
nsAString& aErrMsg, txXPathNode** aResult);
#ifdef TX_EXE
/**

View File

@ -474,13 +474,12 @@ txExecutionState::retrieveDocument(const nsAString& aUri)
if (!entry->mDocument) {
// open URI
nsAutoString errMsg, refUri;
// XXX we should get the referrer from the actual node
nsAutoString errMsg;
// XXX we should get the loader from the actual node
// triggering the load, but this will do for the time being
txXPathNodeUtils::getBaseURI(*mLoadedDocuments.mSourceDocument, refUri);
nsresult rv;
rv = txParseDocumentFromURI(aUri, refUri,
*mLoadedDocuments.mSourceDocument, errMsg,
rv = txParseDocumentFromURI(aUri, *mLoadedDocuments.mSourceDocument,
errMsg,
getter_Transfers(entry->mDocument));
if (NS_FAILED(rv) || !entry->mDocument) {

View File

@ -799,24 +799,44 @@ void txSyncCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
nsresult
TX_CompileStylesheet(nsIDOMNode* aNode, txStylesheet** aStylesheet)
{
nsCOMPtr<nsIDOMDocument> document;
aNode->GetOwnerDocument(getter_AddRefs(document));
if (!document) {
document = do_QueryInterface(aNode);
// If we move GetBaseURI to nsINode this can be simplified.
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIContent> cont = do_QueryInterface(aNode);
if (cont) {
doc = cont->GetOwnerDoc();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
uri = cont->GetBaseURI();
}
else {
doc = do_QueryInterface(aNode);
NS_ASSERTION(doc, "aNode should be a doc or an element by now");
uri = doc->GetBaseURI();
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
nsIURI *uri = doc->GetBaseURI();
nsCAutoString baseURI;
uri->GetSpec(baseURI);
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
nsCAutoString spec;
uri->GetSpec(spec);
NS_ConvertUTF8toUTF16 baseURI(spec);
uri = doc->GetDocumentURI();
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
uri->GetSpec(spec);
NS_ConvertUTF8toUTF16 stylesheetURI(spec);
nsRefPtr<txSyncCompileObserver> obs = new txSyncCompileObserver();
NS_ENSURE_TRUE(obs, NS_ERROR_OUT_OF_MEMORY);
NS_ConvertUTF8toUTF16 base(baseURI);
nsRefPtr<txStylesheetCompiler> compiler =
new txStylesheetCompiler(base, obs);
new txStylesheetCompiler(stylesheetURI, obs);
NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
compiler->setBaseURI(baseURI);
nsresult rv = handleNode(aNode, compiler);
if (NS_FAILED(rv)) {
compiler->cancel(rv);

View File

@ -50,20 +50,20 @@
#include "txStringUtils.h"
#include "txXSLTFunctions.h"
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI,
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI,
txACompileObserver* aObserver)
: txStylesheetCompilerState(aObserver)
{
mStatus = init(aBaseURI, nsnull, nsnull);
mStatus = init(aStylesheetURI, nsnull, nsnull);
}
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI,
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI,
txStylesheet* aStylesheet,
txListIterator* aInsertPosition,
txACompileObserver* aObserver)
: txStylesheetCompilerState(aObserver)
{
mStatus = init(aBaseURI, aStylesheet, aInsertPosition);
mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition);
}
nsrefcnt
@ -83,6 +83,19 @@ txStylesheetCompiler::Release()
return mRefCnt;
}
void
txStylesheetCompiler::setBaseURI(const nsString& aBaseURI)
{
NS_ASSERTION(mObjectStack.size() == 1 && !mObjectStack.peek(),
"Execution already started");
if (NS_FAILED(mStatus)) {
return;
}
mElementContext->mBaseURI = aBaseURI;
}
nsresult
txStylesheetCompiler::startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName,
nsIAtom* aPrefix,
@ -394,7 +407,7 @@ txStylesheetCompiler::doneLoading()
{
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
("Compiler::doneLoading: %s\n",
NS_LossyConvertUTF16toASCII(mURI).get()));
NS_LossyConvertUTF16toASCII(mStylesheetURI).get()));
if (NS_FAILED(mStatus)) {
return mStatus;
}
@ -410,7 +423,7 @@ txStylesheetCompiler::cancel(nsresult aError, const PRUnichar *aErrorText,
{
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
("Compiler::cancel: %s, module: %d, code %d\n",
NS_LossyConvertUTF16toASCII(mURI).get(),
NS_LossyConvertUTF16toASCII(mStylesheetURI).get(),
NS_ERROR_GET_MODULE(aError),
NS_ERROR_GET_CODE(aError)));
if (NS_SUCCEEDED(mStatus)) {
@ -439,8 +452,8 @@ txStylesheetCompiler::loadURI(const nsAString& aUri,
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
("Compiler::loadURI forwards %s thru %s\n",
NS_LossyConvertUTF16toASCII(aUri).get(),
NS_LossyConvertUTF16toASCII(mURI).get()));
if (mURI.Equals(aUri)) {
NS_LossyConvertUTF16toASCII(mStylesheetURI).get()));
if (mStylesheetURI.Equals(aUri)) {
return NS_ERROR_XSLT_LOAD_RECURSION;
}
return mObserver ? mObserver->loadURI(aUri, aReferrerUri, aCompiler) :
@ -554,21 +567,21 @@ txStylesheetCompilerState::txStylesheetCompilerState(txACompileObserver* aObserv
}
nsresult
txStylesheetCompilerState::init(const nsAString& aBaseURI,
txStylesheetCompilerState::init(const nsAString& aStylesheetURI,
txStylesheet* aStylesheet,
txListIterator* aInsertPosition)
{
NS_ASSERTION(!aStylesheet || aInsertPosition,
"must provide insertposition if loading subsheet");
mURI = aBaseURI;
mStylesheetURI = aStylesheetURI;
// Check for fragment identifier of an embedded stylesheet.
PRInt32 fragment = aBaseURI.FindChar('#') + 1;
PRInt32 fragment = aStylesheetURI.FindChar('#') + 1;
if (fragment > 0) {
PRInt32 fragmentLength = aBaseURI.Length() - fragment;
PRInt32 fragmentLength = aStylesheetURI.Length() - fragment;
if (fragmentLength > 0) {
// This is really an embedded stylesheet, not just a
// "url#". We may want to unescape the fragment.
mTarget = Substring(aBaseURI, (PRUint32)fragment,
mTarget = Substring(aStylesheetURI, (PRUint32)fragment,
fragmentLength);
mEmbedStatus = eNeedEmbed;
mHandlerTable = gTxEmbedHandler;
@ -593,7 +606,7 @@ txStylesheetCompilerState::init(const nsAString& aBaseURI,
mIsTopCompiler = PR_TRUE;
}
mElementContext = new txElementContext(aBaseURI);
mElementContext = new txElementContext(aStylesheetURI);
NS_ENSURE_TRUE(mElementContext && mElementContext->mMappings,
NS_ERROR_OUT_OF_MEMORY);
@ -750,7 +763,7 @@ txStylesheetCompilerState::loadIncludedStylesheet(const nsAString& aURI)
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
("CompilerState::loadIncludedStylesheet: %s\n",
NS_LossyConvertUTF16toASCII(aURI).get()));
if (mURI.Equals(aURI)) {
if (mStylesheetURI.Equals(aURI)) {
return NS_ERROR_XSLT_LOAD_RECURSION;
}
NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED);
@ -780,7 +793,7 @@ txStylesheetCompilerState::loadIncludedStylesheet(const nsAString& aURI)
return NS_ERROR_OUT_OF_MEMORY;
}
rv = mObserver->loadURI(aURI, mURI, compiler);
rv = mObserver->loadURI(aURI, mStylesheetURI, compiler);
if (NS_FAILED(rv)) {
mChildCompilerList.RemoveElement(compiler);
}
@ -795,7 +808,7 @@ txStylesheetCompilerState::loadImportedStylesheet(const nsAString& aURI,
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
("CompilerState::loadImportedStylesheet: %s\n",
NS_LossyConvertUTF16toASCII(aURI).get()));
if (mURI.Equals(aURI)) {
if (mStylesheetURI.Equals(aURI)) {
return NS_ERROR_XSLT_LOAD_RECURSION;
}
NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED);
@ -813,7 +826,7 @@ txStylesheetCompilerState::loadImportedStylesheet(const nsAString& aURI,
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = mObserver->loadURI(aURI, mURI, compiler);
nsresult rv = mObserver->loadURI(aURI, mStylesheetURI, compiler);
if (NS_FAILED(rv)) {
mChildCompilerList.RemoveElement(compiler);
}

View File

@ -99,7 +99,7 @@ public:
txStylesheetCompilerState(txACompileObserver* aObserver);
~txStylesheetCompilerState();
nsresult init(const nsAString& aBaseURI, txStylesheet* aStylesheet,
nsresult init(const nsAString& aStylesheetURI, txStylesheet* aStylesheet,
txListIterator* aInsertPosition);
// Embedded stylesheets state
@ -175,13 +175,13 @@ protected:
eInEmbed,
eHasEmbed
} mEmbedStatus;
nsString mURI;
nsString mStylesheetURI;
PRPackedBool mIsTopCompiler;
PRPackedBool mDoneWithThisStylesheet;
private:
txStack mObjectStack;
txStack mOtherStack;
private:
txInstruction** mNextInstrPtr;
txListIterator mToplevelIterator;
nsVoidArray mGotoTargetPointers;
@ -200,15 +200,17 @@ class txStylesheetCompiler : private txStylesheetCompilerState,
{
public:
friend class txStylesheetCompilerState;
txStylesheetCompiler(const nsAString& aBaseURI,
txStylesheetCompiler(const nsAString& aStylesheetURI,
txACompileObserver* aObserver);
txStylesheetCompiler(const nsAString& aBaseURI,
txStylesheetCompiler(const nsAString& aStylesheetURI,
txStylesheet* aStylesheet,
txListIterator* aInsertPosition,
txACompileObserver* aObserver);
virtual nsrefcnt AddRef();
virtual nsrefcnt Release();
void setBaseURI(const nsString& aBaseURI);
nsresult startElement(PRInt32 aNamespaceID, nsIAtom* aLocalName,
nsIAtom* aPrefix, txStylesheetAttr* aAttributes,
PRInt32 aAttrCount);

View File

@ -1019,6 +1019,8 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
nsresult rv = EnsureContentsGenerated();
NS_ENSURE_SUCCESS(rv, rv);
nsMutationGuard::DidMutate();
nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.ChildAt(aIndex);
NS_ENSURE_TRUE(oldKid, NS_ERROR_FAILURE);
@ -1078,7 +1080,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
nsCOMPtr<nsIDOMXULSelectControlItemElement> curItem;
controlElement->GetCurrentItem(getter_AddRefs(curItem));
nsCOMPtr<nsIContent> curNode = do_QueryInterface(curItem);
if (curNode && isSelfOrAncestor(curNode, oldKid)) {
if (curNode && nsContentUtils::ContentIsDescendantOf(curNode, oldKid)) {
// Current item going away
nsCOMPtr<nsIBoxObject> box;
controlElement->GetBoxObject(getter_AddRefs(box));

View File

@ -333,7 +333,7 @@ nsXULContentUtils::MakeElementURI(nsIDocument* aDocument, const nsAString& aElem
CopyUTF16toUTF8(aElementID, aURI);
}
else {
nsIURI *docURL = aDocument->GetBaseURI();
nsIURI *docURL = aDocument->GetDocumentURI();
// XXX Urgh. This is so broken; I'd really just like to use
// NS_MakeAbsolueURI(). Unfortunatly, doing that breaks
@ -389,7 +389,7 @@ nsXULContentUtils::MakeElementID(nsIDocument* aDocument, const nsAString& aURI,
// Convert a URI into an element ID that can be accessed from the
// DOM APIs.
nsCAutoString spec;
aDocument->GetBaseURI()->GetSpec(spec);
aDocument->GetDocumentURI()->GetSpec(spec);
// XXX FIX ME to not do a copy
nsAutoString str(aURI);

View File

@ -411,6 +411,8 @@ nsXFormsModelElement::InitializeInstances()
// Parse the whitespace-separated list.
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
nsRefPtr<nsIURI> baseURI = content->GetBaseURI();
nsRefPtr<nsIURI> docURI = content->GetOwnerDoc() ?
content->GetOwnerDoc()->GetDocumentURI() : nsnull;
nsCStringArray schemas;
schemas.ParseString(NS_ConvertUTF16toUTF8(schemaList).get(), " \t\r\n");
@ -432,7 +434,7 @@ nsXFormsModelElement::InitializeInstances()
newURL->GetRef(ref);
newURL->SetRef(EmptyCString());
PRBool equals = PR_FALSE;
newURL->Equals(baseURI, &equals);
newURL->Equals(docURI, &equals);
if (equals) {
// We will not be able to locate the <xsd:schema> element using the
// getElementById function defined on our document when <xsd:schema>

View File

@ -762,13 +762,13 @@ nsPresContext::SetShell(nsIPresShell* aShell)
nsIDocument *doc = mShell->GetDocument();
NS_ASSERTION(doc, "expect document here");
if (doc) {
nsIURI *baseURI = doc->GetBaseURI();
nsIURI *docURI = doc->GetDocumentURI();
if (mMedium != nsLayoutAtoms::print && baseURI) {
if (mMedium != nsLayoutAtoms::print && docURI) {
PRBool isChrome = PR_FALSE;
PRBool isRes = PR_FALSE;
baseURI->SchemeIs("chrome", &isChrome);
baseURI->SchemeIs("resource", &isRes);
docURI->SchemeIs("chrome", &isChrome);
docURI->SchemeIs("resource", &isRes);
if (!isChrome && !isRes)
mImageAnimationMode = mImageAnimationModePref;

View File

@ -371,8 +371,8 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
if (!document) return NS_OK; // No doc means don't submit, see Bug 28988
// Resolve url to an absolute url
nsIURI *docURL = document->GetBaseURI();
if (!docURL) {
nsIURI *baseURI = document->GetBaseURI();
if (!baseURI) {
NS_ERROR("No Base URL found in Form Submit!\n");
return NS_OK; // No base URL -> exit early, see Bug 30721
}
@ -396,7 +396,7 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
// Necko's MakeAbsoluteURI doesn't reuse the baseURL's rel path if it is
// passed a zero length rel path.
nsCAutoString relPath;
docURL->GetSpec(relPath);
baseURI->GetSpec(relPath);
if (!relPath.IsEmpty()) {
CopyUTF8toUTF16(relPath, href);
@ -420,7 +420,7 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
if (NS_SUCCEEDED(result = NS_NewURI(getter_AddRefs(actionURL), href,
flatDocCharset.get(),
docURL))) {
baseURI))) {
result = actionURL->SchemeIs("javascript", &isJSURL);
}
// Append the URI encoded variable/value pairs for GET's
@ -436,7 +436,7 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
}
nsCOMPtr<nsIURI> uri;
result = NS_NewURI(getter_AddRefs(uri), href,
flatDocCharset.get(), docURL);
flatDocCharset.get(), baseURI);
if (NS_FAILED(result)) return result;
// Now pass on absolute url to the click handler