зеркало из https://github.com/mozilla/pjs.git
Back out a few of my patches to see if any caused the Tdhtml regression in bug 331364.
This commit is contained in:
Родитель
4c05ba4736
Коммит
6cc41878a9
|
@ -362,7 +362,10 @@ public:
|
|||
/**
|
||||
* Return the root content object for this document.
|
||||
*/
|
||||
virtual nsIContent *GetRootContent() const = 0;
|
||||
nsIContent *GetRootContent() const
|
||||
{
|
||||
return mRootContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors to the collection of stylesheets owned by this document.
|
||||
|
@ -910,6 +913,10 @@ protected:
|
|||
// This is just a weak pointer; the parent document owns its children.
|
||||
nsIDocument* mParentDocument;
|
||||
|
||||
// A weak reference to the only child element, or null if no
|
||||
// such element exists.
|
||||
nsIContent* mRootContent;
|
||||
|
||||
nsCOMPtr<nsIBindingManager> mBindingManager;
|
||||
nsNodeInfoManager* mNodeInfoManager; // [STRONG]
|
||||
|
||||
|
|
|
@ -748,16 +748,27 @@ nsDocument::~nsDocument()
|
|||
mSubDocuments = nsnull;
|
||||
}
|
||||
|
||||
// Destroy link map now so we don't waste time removing
|
||||
// links one by one
|
||||
DestroyLinkMap();
|
||||
if (mRootContent) {
|
||||
if (mRootContent->GetCurrentDoc()) {
|
||||
NS_ASSERTION(mRootContent->GetCurrentDoc() == this,
|
||||
"Unexpected current doc in root content");
|
||||
// The root content still has a pointer back to the document,
|
||||
// clear the document pointer in all children.
|
||||
|
||||
// Destroy link map now so we don't waste time removing
|
||||
// links one by one
|
||||
DestroyLinkMap();
|
||||
|
||||
PRUint32 count = mChildren.ChildCount();
|
||||
for (indx = PRInt32(count) - 1; indx >= 0; --indx) {
|
||||
mChildren.ChildAt(indx)->UnbindFromTree();
|
||||
mChildren.RemoveChildAt(indx);
|
||||
PRUint32 count = mChildren.ChildCount();
|
||||
for (indx = PRInt32(count) - 1; indx >= 0; --indx) {
|
||||
mChildren.ChildAt(indx)->UnbindFromTree();
|
||||
mChildren.RemoveChildAt(indx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mRootContent = nsnull;
|
||||
|
||||
// Let the stylesheets know we're going away
|
||||
indx = mStyleSheets.Count();
|
||||
while (--indx >= 0) {
|
||||
|
@ -972,6 +983,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup)
|
|||
// links one by one
|
||||
DestroyLinkMap();
|
||||
|
||||
mRootContent = nsnull;
|
||||
PRUint32 count = mChildren.ChildCount();
|
||||
for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
|
||||
nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
|
||||
|
@ -1679,22 +1691,6 @@ nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
|
|||
return data.mResult;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsDocument::GetRootContent() const
|
||||
{
|
||||
// Loop backwards because any non-elements, such as doctypes and PIs
|
||||
// are likely to appear before the root element.
|
||||
PRUint32 i;
|
||||
for (i = mChildren.ChildCount(); i > 0; --i) {
|
||||
nsIContent* child = mChildren.ChildAt(i - 1);
|
||||
if (child->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIContent *
|
||||
nsDocument::GetChildAt(PRUint32 aIndex) const
|
||||
{
|
||||
|
@ -1717,13 +1713,37 @@ nsresult
|
|||
nsDocument::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (aKid->IsContentOfType(nsIContent::eELEMENT) && GetRootContent()) {
|
||||
NS_ERROR("Inserting element child when we already have one");
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
if (aKid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
if (mRootContent) {
|
||||
NS_ERROR("Inserting element child when we already have one");
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
mRootContent = aKid;
|
||||
}
|
||||
|
||||
return nsGenericElement::doInsertChildAt(aKid, aIndex, aNotify,
|
||||
nsnull, this, mChildren);
|
||||
nsresult rv = nsGenericElement::doInsertChildAt(aKid, aIndex, aNotify,
|
||||
nsnull, this, mChildren);
|
||||
|
||||
if (NS_FAILED(rv) && mRootContent == aKid) {
|
||||
PRInt32 kidIndex = mChildren.IndexOfChild(aKid);
|
||||
NS_ASSERTION(kidIndex == -1,
|
||||
"Error result and still have same root content but it's in "
|
||||
"our child list?");
|
||||
// Check to make sure that we're keeping mRootContent in sync with our
|
||||
// child list... but really, if kidIndex != -1 we have major problems
|
||||
// coming up; hence the assert above. This check is just a feeble attempt
|
||||
// to not die due to mRootContent being bogus.
|
||||
if (kidIndex == -1) {
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1741,19 +1761,58 @@ nsresult
|
|||
nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
||||
{
|
||||
nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
|
||||
if (!oldKid) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (oldKid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
// Destroy the link map up front before we mess with the child list.
|
||||
DestroyLinkMap();
|
||||
}
|
||||
|
||||
return nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid,
|
||||
nsresult rv = NS_OK;
|
||||
if (oldKid) {
|
||||
if (oldKid == mRootContent) {
|
||||
NS_ASSERTION(oldKid->IsContentOfType(nsIContent::eELEMENT),
|
||||
"Non-element root content?");
|
||||
// Destroy the link map up front and null out mRootContent before we mess
|
||||
// with the child list. Hopefully no one in doRemoveChildAt will compare
|
||||
// the content being removed to GetRootContent().... Need to do this
|
||||
// before calling doRemoveChildAt because DOM events might fire while
|
||||
// we're inside the doInsertChildAt call and want to set a new
|
||||
// mRootContent; if they do that, setting mRootContent after the
|
||||
// doRemoveChildAt call would clobber state. If we ever fix the issue of
|
||||
// DOM events firing at inconvenient times, consider changing the order
|
||||
// here. Just make sure we DestroyLinkMap() before unbinding the
|
||||
// content.
|
||||
DestroyLinkMap();
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
|
||||
rv = nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid,
|
||||
nsnull, this, mChildren);
|
||||
if (NS_FAILED(rv) && mChildren.IndexOfChild(oldKid) != -1) {
|
||||
mRootContent = oldKid;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsDocument::VerifyRootContentState()
|
||||
{
|
||||
nsIContent* elementChild = nsnull;
|
||||
for (PRUint32 i = 0; i < GetChildCount(); ++i) {
|
||||
nsIContent* kid = GetChildAt(i);
|
||||
NS_ASSERTION(kid, "Must have kid here");
|
||||
|
||||
if (kid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
NS_ASSERTION(!elementChild, "Multiple element kids?");
|
||||
elementChild = kid;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(mRootContent == elementChild, "Incorrect mRootContent");
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
PRInt32
|
||||
nsDocument::GetNumberOfStyleSheets() const
|
||||
{
|
||||
|
@ -2489,11 +2548,28 @@ nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype)
|
|||
*aDoctype = nsnull;
|
||||
PRInt32 i, count;
|
||||
count = mChildren.ChildCount();
|
||||
for (i = 0; i < count; i++) {
|
||||
CallQueryInterface(mChildren.ChildAt(i), aDoctype);
|
||||
nsCOMPtr<nsIDOMNode> rootContentNode(do_QueryInterface(mRootContent) );
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
|
||||
if (*aDoctype) {
|
||||
for (i = 0; i < count; i++) {
|
||||
node = do_QueryInterface(mChildren.ChildAt(i));
|
||||
|
||||
NS_ASSERTION(node, "null element of mChildren");
|
||||
|
||||
// doctype can't be after the root
|
||||
// XXX Do we really want to enforce this when we don't enforce
|
||||
// anything else?
|
||||
if (node == rootContentNode)
|
||||
return NS_OK;
|
||||
|
||||
if (node) {
|
||||
PRUint16 nodeType;
|
||||
|
||||
node->GetNodeType(&nodeType);
|
||||
|
||||
if (nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) {
|
||||
return CallQueryInterface(node, aDoctype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2524,14 +2600,16 @@ nsDocument::GetDocumentElement(nsIDOMElement** aDocumentElement)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocumentElement);
|
||||
|
||||
nsIContent* root = GetRootContent();
|
||||
if (root) {
|
||||
return CallQueryInterface(root, aDocumentElement);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mRootContent) {
|
||||
rv = CallQueryInterface(mRootContent, aDocumentElement);
|
||||
NS_ASSERTION(NS_OK == rv, "Must be a DOM Element");
|
||||
} else {
|
||||
*aDocumentElement = nsnull;
|
||||
}
|
||||
|
||||
*aDocumentElement = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3545,11 +3623,43 @@ 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::doReplaceOrInsertBefore(PR_FALSE, aNewChild, aRefChild, nsnull, this,
|
||||
return nsGenericElement::doInsertBefore(aNewChild, aRefChild, nsnull, this,
|
||||
aReturn);
|
||||
}
|
||||
|
||||
|
@ -3557,7 +3667,7 @@ NS_IMETHODIMP
|
|||
nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
||||
nsIDOMNode** aReturn)
|
||||
{
|
||||
return nsGenericElement::doReplaceOrInsertBefore(PR_TRUE, aNewChild, aOldChild, nsnull, this,
|
||||
return nsGenericElement::doReplaceChild(aNewChild, aOldChild, nsnull, this,
|
||||
aReturn);
|
||||
}
|
||||
|
||||
|
@ -3945,7 +4055,7 @@ NS_IMETHODIMP
|
|||
nsDocument::LookupPrefix(const nsAString& aNamespaceURI,
|
||||
nsAString& aPrefix)
|
||||
{
|
||||
nsCOMPtr<nsIDOM3Node> root(do_QueryInterface(GetRootContent()));
|
||||
nsCOMPtr<nsIDOM3Node> root(do_QueryInterface(mRootContent));
|
||||
if (root) {
|
||||
return root->LookupPrefix(aNamespaceURI, aPrefix);
|
||||
}
|
||||
|
@ -3958,7 +4068,7 @@ NS_IMETHODIMP
|
|||
nsDocument::LookupNamespaceURI(const nsAString& aNamespacePrefix,
|
||||
nsAString& aNamespaceURI)
|
||||
{
|
||||
if (NS_FAILED(nsContentUtils::LookupNamespaceURI(GetRootContent(),
|
||||
if (NS_FAILED(nsContentUtils::LookupNamespaceURI(mRootContent,
|
||||
aNamespacePrefix,
|
||||
aNamespaceURI))) {
|
||||
SetDOMStringToNull(aNamespaceURI);
|
||||
|
@ -5033,13 +5143,12 @@ nsDocument::Destroy()
|
|||
if (mIsGoingAway)
|
||||
return;
|
||||
|
||||
PRInt32 count = mChildren.ChildCount();
|
||||
|
||||
mIsGoingAway = PR_TRUE;
|
||||
DestroyLinkMap();
|
||||
|
||||
PRInt32 count = mChildren.ChildCount();
|
||||
for (PRInt32 indx = count; indx > 0; --indx) {
|
||||
mChildren.ChildAt(indx - 1)->UnbindFromTree();
|
||||
mChildren.RemoveChildAt(indx - 1);
|
||||
for (PRInt32 indx = 0; indx < count; ++indx) {
|
||||
mChildren.ChildAt(indx)->UnbindFromTree();
|
||||
}
|
||||
|
||||
// Propagate the out-of-band notification to each PresShell's anonymous
|
||||
|
@ -5201,13 +5310,12 @@ nsDocument::OnPageShow(PRBool aPersisted)
|
|||
mVisible = PR_TRUE;
|
||||
UpdateLinkMap();
|
||||
|
||||
nsIContent* root = GetRootContent();
|
||||
if (aPersisted && root) {
|
||||
if (aPersisted) {
|
||||
// Send out notifications that our <link> elements are attached.
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(this,
|
||||
nsHTMLAtoms::link,
|
||||
kNameSpaceID_Unknown,
|
||||
root);
|
||||
mRootContent);
|
||||
|
||||
if (links) {
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
|
@ -5229,12 +5337,11 @@ nsDocument::OnPageHide(PRBool aPersisted)
|
|||
{
|
||||
// Send out notifications that our <link> elements are detached,
|
||||
// but only if this is not a full unload.
|
||||
nsIContent* root = GetRootContent();
|
||||
if (aPersisted && root) {
|
||||
if (aPersisted) {
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(this,
|
||||
nsHTMLAtoms::link,
|
||||
kNameSpaceID_Unknown,
|
||||
root);
|
||||
mRootContent);
|
||||
|
||||
if (links) {
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
|
|
|
@ -385,7 +385,6 @@ public:
|
|||
nsIDocument* aSubDoc);
|
||||
virtual nsIDocument* GetSubDocumentFor(nsIContent *aContent) const;
|
||||
virtual nsIContent* FindContentForSubDocument(nsIDocument *aDocument) const;
|
||||
virtual nsIContent* GetRootContent() const;
|
||||
|
||||
/**
|
||||
* Get the style sheets owned by this document.
|
||||
|
@ -706,6 +705,10 @@ protected:
|
|||
// Dispatch an event to the ScriptGlobalObject for this document
|
||||
void DispatchEventToWindow(nsEvent *aEvent);
|
||||
|
||||
#ifdef DEBUG
|
||||
void VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
nsDocument();
|
||||
virtual ~nsDocument();
|
||||
|
||||
|
@ -769,6 +772,8 @@ protected:
|
|||
nsString mBaseTarget;
|
||||
|
||||
private:
|
||||
nsresult IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent);
|
||||
|
||||
void PostUnblockOnloadEvent();
|
||||
static EventHandlerFunc HandleOnloadBlockerEvent;
|
||||
static EventDestructorFunc DestroyOnloadBlockerEvent;
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#include "nsIDOMUserDataHandler.h"
|
||||
|
||||
class nsDocumentFragment : public nsGenericElement,
|
||||
public nsIDOMDocumentFragment,
|
||||
public nsIDocumentFragment,
|
||||
public nsIDOM3Node
|
||||
{
|
||||
public:
|
||||
|
@ -62,6 +62,11 @@ 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); }
|
||||
|
@ -189,6 +194,7 @@ 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)
|
||||
|
@ -202,6 +208,71 @@ 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)
|
||||
{
|
||||
|
|
|
@ -772,8 +772,6 @@ nsDOMEventRTTearoff::AddEventListener(const nsAString& aType,
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PRUint32 nsMutationGuard::sMutationCount = 0;
|
||||
|
||||
nsDOMSlots::nsDOMSlots(PtrBits aFlags)
|
||||
: mFlags(aFlags),
|
||||
mBindingParent(nsnull)
|
||||
|
@ -2304,12 +2302,7 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
|||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
"Incorrect aDocument");
|
||||
|
||||
PRUint32 childCount = aChildArray.ChildCount();
|
||||
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
||||
PRBool isAppend = (aIndex == childCount);
|
||||
PRBool isAppend = (aIndex == aChildArray.ChildCount());
|
||||
|
||||
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
|
@ -2397,8 +2390,6 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
|||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
"Incorrect aDocument");
|
||||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
|
@ -2505,20 +2496,51 @@ 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 doReplaceOrInsertBefore(PR_FALSE, aNewChild, aRefChild, this, GetCurrentDoc(),
|
||||
aReturn);
|
||||
return doInsertBefore(aNewChild, aRefChild, this, GetCurrentDoc(),
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
||||
nsIDOMNode** aReturn)
|
||||
{
|
||||
return doReplaceOrInsertBefore(PR_TRUE, aNewChild, aOldChild, this, GetCurrentDoc(),
|
||||
aReturn);
|
||||
return doReplaceChild(aNewChild, aOldChild, this, GetCurrentDoc(),
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2548,10 +2570,6 @@ 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 :
|
||||
|
@ -2776,12 +2794,9 @@ NS_IMPL_ISUPPORTS1(nsFragmentObserver, nsIDocumentObserver)
|
|||
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
||||
nsIDOMNode* aNewChild,
|
||||
nsIDOMNode* aRefChild,
|
||||
nsIContent* aParent,
|
||||
nsIDocument* aDocument,
|
||||
nsIDOMNode** aReturn)
|
||||
nsGenericElement::doInsertBefore(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,
|
||||
|
@ -2789,51 +2804,54 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
|
||||
*aReturn = nsnull;
|
||||
|
||||
if (!aNewChild || (aReplace && !aRefChild)) {
|
||||
if (!aNewChild) {
|
||||
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 insPos;
|
||||
PRInt32 refPos = 0;
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
|
||||
// Figure out which index to insert at
|
||||
if (aRefChild) {
|
||||
refContent = do_QueryInterface(aRefChild);
|
||||
insPos = container->IndexOf(refContent);
|
||||
if (insPos < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (aRefChild == aNewChild) {
|
||||
NS_ADDREF(*aReturn = aNewChild);
|
||||
refPos = container->IndexOf(refContent);
|
||||
|
||||
return NS_OK;
|
||||
if (refPos < 0) {
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
} else {
|
||||
insPos = container->GetChildCount();
|
||||
refPos = container->GetChildCount();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> newContent = do_QueryInterface(aNewChild);
|
||||
if (!newContent) {
|
||||
nsCOMPtr<nsIContent> newContent(do_QueryInterface(aNewChild, &res));
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
PRUint16 nodeType = 0;
|
||||
res = aNewChild->GetNodeType(&nodeType);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// Make sure that the inserted node is allowed as a child of its new parent.
|
||||
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, aReplace,
|
||||
res = aNewChild->GetNodeType(&nodeType);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_FALSE,
|
||||
refContent)) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
@ -2858,37 +2876,14 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2897,42 +2892,23 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
* 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();
|
||||
PRBool do_notify = refContent || !aParent;
|
||||
PRUint32 old_count = container->GetChildCount();
|
||||
|
||||
// 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);
|
||||
}
|
||||
PRBool do_notify = !!aRefChild || !aParent;
|
||||
|
||||
// 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(container->GetChildCount(), aParent, aDocument);
|
||||
fragmentObs = new nsFragmentObserver(old_count, 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
|
||||
|
@ -2940,44 +2916,26 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL,
|
||||
count && !do_notify);
|
||||
|
||||
// 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];
|
||||
/*
|
||||
* Iterate through the fragment's children, removing each from
|
||||
* the fragment and inserting it into the child list of its
|
||||
* new parent.
|
||||
*/
|
||||
|
||||
// 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;
|
||||
}
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
// XXXbz how come no reparenting here? That seems odd...
|
||||
// Insert the child.
|
||||
res = container->InsertChildAt(childContent, insPos, do_notify);
|
||||
// Insert the child and increment the insertion position
|
||||
res = container->InsertChildAt(childContent, refPos++, do_notify);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
break;
|
||||
}
|
||||
|
@ -2985,21 +2943,17 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
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;
|
||||
}
|
||||
|
@ -3008,9 +2962,9 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
NS_ASSERTION(count && !do_notify, "Unexpected state");
|
||||
fragmentObs->Finish();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not inserting a fragment but rather a single node.
|
||||
|
||||
doc_fragment->DropChildReferences();
|
||||
} else {
|
||||
nsIContent* bindingParent = newContent->GetBindingParent();
|
||||
if (bindingParent == newContent ||
|
||||
(bindingParent && bindingParent == newContent->GetParent())) {
|
||||
|
@ -3018,65 +2972,245 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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);
|
||||
if (oldParent) {
|
||||
PRInt32 removeIndex = oldParent->IndexOf(newContent);
|
||||
NS_ASSERTION(removeIndex >= 0 &&
|
||||
!(oldParent == container && removeIndex == insPos),
|
||||
"invalid removeIndex");
|
||||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
|
||||
nsMutationGuard guard;
|
||||
PRUint32 origChildCount = container->GetChildCount();
|
||||
|
||||
res = oldParent->RemoveChildAt(removeIndex, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
/*
|
||||
* We don't care here if the return fails or not.
|
||||
*/
|
||||
oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));
|
||||
|
||||
// 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;
|
||||
}
|
||||
PRUint32 newChildCount = container->GetChildCount();
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 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 (newContent->GetParent() || newContent->IsInDoc() ||
|
||||
!IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_FALSE,
|
||||
refContent)) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
if (refContent == container->GetChildAt(refPos - 1)) {
|
||||
refPos--;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If we didn't get aRefChild we simply decrement refPos.
|
||||
*/
|
||||
refPos--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!newContentIsXUL) {
|
||||
if (!newContent->IsContentOfType(eXUL)) {
|
||||
nsContentUtils::ReparentContentWrapper(newContent, aParent,
|
||||
container->GetOwnerDoc(),
|
||||
old_doc);
|
||||
}
|
||||
|
||||
res = container->InsertChildAt(newContent, insPos, PR_TRUE);
|
||||
res = container->InsertChildAt(newContent, refPos, PR_TRUE);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
*aReturn = aNewChild;
|
||||
NS_ADDREF(*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);
|
||||
}
|
||||
|
||||
returnVal.swap(*aReturn);
|
||||
|
||||
return res;
|
||||
return CallQueryInterface(replacedChild, aReturn);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -283,77 +283,6 @@ 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,
|
||||
|
@ -647,22 +576,43 @@ public:
|
|||
static PRBool ShouldFocus(nsIContent *aContent);
|
||||
|
||||
/**
|
||||
* Actual implementation of the DOM InsertBefore and ReplaceChild methods.
|
||||
* Shared by nsDocument. When called from nsDocument, aParent will be null.
|
||||
* 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.
|
||||
*
|
||||
* @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 or replace
|
||||
* @param aRefChild The child to insert before
|
||||
* @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 doReplaceOrInsertBefore(PRBool aReplace, nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsIDOMNode** aReturn);
|
||||
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);
|
||||
|
||||
/**
|
||||
* Actual implementation of the DOM RemoveChild method. Shared by
|
||||
|
@ -756,7 +706,7 @@ public:
|
|||
const nsAttrName* mName;
|
||||
const nsAttrValue* mValue;
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Set attribute and (if needed) notify documentobservers and fire off
|
||||
|
@ -1061,6 +1011,41 @@ 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); \
|
||||
|
|
|
@ -417,6 +417,8 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup)
|
|||
mLinks = nsnull;
|
||||
mAnchors = nsnull;
|
||||
|
||||
mBodyContent = nsnull;
|
||||
|
||||
mImageMaps.Clear();
|
||||
mForms = nsnull;
|
||||
|
||||
|
@ -1171,6 +1173,12 @@ nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent,
|
|||
{
|
||||
NS_ABORT_IF_FALSE(aContent, "Null content!");
|
||||
|
||||
if (aContainer == mRootContent) {
|
||||
// Reset mBodyContent in case we got a new body.
|
||||
|
||||
mBodyContent = nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = UnregisterNamedItems(aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1623,62 +1631,66 @@ nsHTMLDocument::GetURL(nsAString& aURL)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aBody);
|
||||
*aBody = nsnull;
|
||||
|
||||
nsIContent* body = GetBodyContent();
|
||||
|
||||
if (body) {
|
||||
// There is a body element, return that as the body.
|
||||
return CallQueryInterface(body, aBody);
|
||||
}
|
||||
|
||||
// The document is most likely a frameset document so look for the
|
||||
// outer most frameset element
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
|
||||
nsresult rv;
|
||||
if (IsXHTML()) {
|
||||
rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
|
||||
NS_LITERAL_STRING("frameset"),
|
||||
getter_AddRefs(nodeList));
|
||||
} else {
|
||||
rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"),
|
||||
getter_AddRefs(nodeList));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsISupports* element = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nodeList->Item(0, getter_AddRefs(node));
|
||||
|
||||
return node ? CallQueryInterface(node, aBody) : NS_OK;
|
||||
if (mBodyContent || GetBodyContent()) {
|
||||
// There is a body element, return that as the body.
|
||||
element = mBodyContent;
|
||||
} else {
|
||||
// The document is most likely a frameset document so look for the
|
||||
// outer most frameset element
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
|
||||
nsresult rv;
|
||||
if (IsXHTML()) {
|
||||
rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
|
||||
NS_LITERAL_STRING("frameset"),
|
||||
getter_AddRefs(nodeList));
|
||||
} else {
|
||||
rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"),
|
||||
getter_AddRefs(nodeList));
|
||||
}
|
||||
|
||||
if (nodeList) {
|
||||
rv |= nodeList->Item(0, getter_AddRefs(node));
|
||||
|
||||
element = node;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return element ? CallQueryInterface(element, aBody) : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
|
||||
{
|
||||
nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
|
||||
nsIContent* root = GetRootContent();
|
||||
nsCOMPtr<nsIContent> body(do_QueryInterface(aBody));
|
||||
nsCOMPtr<nsIDOMElement> root(do_QueryInterface(mRootContent));
|
||||
|
||||
// The body element must be either a body tag or a frameset tag. And we must
|
||||
// have a html root tag, otherwise GetBody will not return the newly set
|
||||
// body.
|
||||
if (!newBody || !(newBody->Tag() == nsHTMLAtoms::body ||
|
||||
newBody->Tag() == nsHTMLAtoms::frameset) ||
|
||||
!root || !root->IsContentOfType(nsIContent::eHTML) ||
|
||||
root->Tag() != nsHTMLAtoms::html) {
|
||||
// The body element must be either a body tag or a frameset tag.
|
||||
if (!body || !root || !(body->Tag() == nsHTMLAtoms::body ||
|
||||
body->Tag() == nsHTMLAtoms::frameset)) {
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(root);
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
|
||||
// Use DOM methods so that we pass through the appropriate security checks.
|
||||
nsCOMPtr<nsIDOMNode> currentBody = do_QueryInterface(GetBodyContent());
|
||||
if (currentBody) {
|
||||
return rootElem->ReplaceChild(aBody, currentBody, getter_AddRefs(tmp));
|
||||
if (mBodyContent || GetBodyContent()) {
|
||||
root->ReplaceChild(aBody, mBodyContent, getter_AddRefs(tmp));
|
||||
} else {
|
||||
root->AppendChild(aBody, getter_AddRefs(tmp));
|
||||
}
|
||||
|
||||
return rootElem->AppendChild(aBody, getter_AddRefs(tmp));
|
||||
mBodyContent = aBody;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1972,10 +1984,10 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
// (http://bugzilla.mozilla.org/show_bug.cgi?id=55334).
|
||||
|
||||
// Hold on to our root element
|
||||
nsCOMPtr<nsIContent> root = GetRootContent();
|
||||
nsCOMPtr<nsIContent> root(mRootContent);
|
||||
|
||||
if (root) {
|
||||
PRInt32 rootIndex = mChildren.IndexOfChild(root);
|
||||
PRInt32 rootIndex = mChildren.IndexOfChild(mRootContent);
|
||||
NS_ASSERTION(rootIndex >= 0, "Root must be in list!");
|
||||
|
||||
PRUint32 count = root->GetChildCount();
|
||||
|
@ -1985,7 +1997,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
root->RemoveChildAt(count, PR_TRUE);
|
||||
}
|
||||
|
||||
count = root->GetAttrCount();
|
||||
count = mRootContent->GetAttrCount();
|
||||
|
||||
// Remove all attributes from the root element
|
||||
while (count-- > 0) {
|
||||
|
@ -1995,6 +2007,8 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
|
||||
// Remove the root from the childlist
|
||||
mChildren.RemoveChildAt(rootIndex);
|
||||
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
|
||||
// Call Reset(), this will now do the full reset, except removing
|
||||
|
@ -2016,6 +2030,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
// element was never set to null)
|
||||
|
||||
mChildren.AppendChild(root);
|
||||
mRootContent = root;
|
||||
}
|
||||
|
||||
if (mEditingIsOn) {
|
||||
|
@ -2425,12 +2440,11 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId,
|
|||
// If IdTableIsLive(), no need to look for the element in the document,
|
||||
// since we're fully maintaining our table's state as the DOM mutates.
|
||||
if (!IdTableIsLive()) {
|
||||
nsIContent* root = GetRootContent();
|
||||
if (IdTableShouldBecomeLive()) {
|
||||
// Just make sure our table is up to date and call this method again
|
||||
// to look up in the hashtable.
|
||||
if (root) {
|
||||
RegisterNamedItems(root);
|
||||
if (mRootContent) {
|
||||
RegisterNamedItems(mRootContent);
|
||||
}
|
||||
return GetElementById(aElementId, aReturn);
|
||||
}
|
||||
|
@ -2438,8 +2452,8 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId,
|
|||
NS_WARN_IF_FALSE(!aElementId.IsEmpty(),
|
||||
"getElementById(\"\") called, fix caller?");
|
||||
|
||||
if (root && !aElementId.IsEmpty()) {
|
||||
e = nsContentUtils::MatchElementId(root, idAtom);
|
||||
if (mRootContent && !aElementId.IsEmpty()) {
|
||||
e = nsContentUtils::MatchElementId(mRootContent, idAtom);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2447,9 +2461,9 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId,
|
|||
#ifdef DEBUG
|
||||
// No reason to call MatchElementId if !IdTableIsLive, since
|
||||
// we'd have done just that already
|
||||
if (IdTableIsLive() && GetRootContent() && !aElementId.IsEmpty()) {
|
||||
if (IdTableIsLive() && mRootContent && !aElementId.IsEmpty()) {
|
||||
nsIContent* eDebug =
|
||||
nsContentUtils::MatchElementId(GetRootContent(), idAtom);
|
||||
nsContentUtils::MatchElementId(mRootContent, idAtom);
|
||||
NS_ASSERTION(!eDebug,
|
||||
"We got null for |e| but MatchElementId found something?");
|
||||
}
|
||||
|
@ -2578,7 +2592,11 @@ nsHTMLDocument::GetPixelDimensions(nsIPresShell* aShell,
|
|||
|
||||
// Find the <body> element: this is what we'll want to use for the
|
||||
// document's width and height values.
|
||||
nsIContent* body = GetBodyContent();
|
||||
if (!mBodyContent && !GetBodyContent()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> body = do_QueryInterface(mBodyContent);
|
||||
|
||||
// Now grab its frame
|
||||
nsIFrame* frame = aShell->GetPrimaryFrameFor(body);
|
||||
|
@ -2667,7 +2685,8 @@ nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor)
|
|||
{
|
||||
aAlinkColor.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->GetALink(aAlinkColor);
|
||||
|
@ -2685,7 +2704,8 @@ nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetAlinkColor(const nsAString& aAlinkColor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->SetALink(aAlinkColor);
|
||||
|
@ -2706,7 +2726,8 @@ nsHTMLDocument::GetLinkColor(nsAString& aLinkColor)
|
|||
{
|
||||
aLinkColor.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->GetLink(aLinkColor);
|
||||
|
@ -2724,7 +2745,8 @@ nsHTMLDocument::GetLinkColor(nsAString& aLinkColor)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetLinkColor(const nsAString& aLinkColor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->SetLink(aLinkColor);
|
||||
|
@ -2745,7 +2767,8 @@ nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
|
|||
{
|
||||
aVlinkColor.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->GetVLink(aVlinkColor);
|
||||
|
@ -2763,7 +2786,8 @@ nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetVlinkColor(const nsAString& aVlinkColor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->SetVLink(aVlinkColor);
|
||||
|
@ -2784,7 +2808,8 @@ nsHTMLDocument::GetBgColor(nsAString& aBgColor)
|
|||
{
|
||||
aBgColor.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->GetBgColor(aBgColor);
|
||||
|
@ -2796,7 +2821,8 @@ nsHTMLDocument::GetBgColor(nsAString& aBgColor)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetBgColor(const nsAString& aBgColor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->SetBgColor(aBgColor);
|
||||
|
@ -2811,7 +2837,8 @@ nsHTMLDocument::GetFgColor(nsAString& aFgColor)
|
|||
{
|
||||
aFgColor.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->GetText(aFgColor);
|
||||
|
@ -2823,7 +2850,8 @@ nsHTMLDocument::GetFgColor(nsAString& aFgColor)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLDocument::SetFgColor(const nsAString& aFgColor)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyContent());
|
||||
nsCOMPtr<nsIDOMHTMLBodyElement> body;
|
||||
GetBodyElement(getter_AddRefs(body));
|
||||
|
||||
if (body) {
|
||||
body->SetText(aFgColor);
|
||||
|
@ -3307,11 +3335,10 @@ nsHTMLDocument::ResolveName(const nsAString& aName,
|
|||
entry->mNameContentList = list;
|
||||
NS_ADDREF(entry->mNameContentList);
|
||||
|
||||
nsIContent* root = GetRootContent();
|
||||
if (root && !aName.IsEmpty()) {
|
||||
if (mRootContent && !aName.IsEmpty()) {
|
||||
// We'll never get here if !IsXHTML(), so we can just pass
|
||||
// PR_FALSE to FindNamedItems().
|
||||
FindNamedItems(name, root, *entry, PR_FALSE);
|
||||
FindNamedItems(name, mRootContent, *entry, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3400,27 +3427,42 @@ nsHTMLDocument::ResolveName(const nsAString& aName,
|
|||
|
||||
//----------------------------
|
||||
|
||||
nsIContent*
|
||||
PRBool
|
||||
nsHTMLDocument::GetBodyContent()
|
||||
{
|
||||
// Loop backwards because any non-elements, such as doctypes and PIs
|
||||
// are likly to appear before the root element.
|
||||
nsIContent* html = GetRootContent();
|
||||
if (html && html->Tag() == nsHTMLAtoms::html &&
|
||||
html->IsContentOfType(nsIContent::eHTML)) {
|
||||
if (!mRootContent) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Look for body inside html
|
||||
PRUint32 i, count = html->GetChildCount();
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsIContent* body = html->GetChildAt(i);
|
||||
if (body->Tag() == nsHTMLAtoms::body &&
|
||||
body->IsContentOfType(nsIContent::eHTML)) {
|
||||
return body;
|
||||
}
|
||||
PRUint32 i, child_count = mRootContent->GetChildCount();
|
||||
|
||||
for (i = 0; i < child_count; ++i) {
|
||||
nsIContent *child = mRootContent->GetChildAt(i);
|
||||
NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (child->NodeInfo()->Equals(nsHTMLAtoms::body, mDefaultNamespaceID) &&
|
||||
child->IsContentOfType(nsIContent::eHTML)) {
|
||||
mBodyContent = do_QueryInterface(child);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::GetBodyElement(nsIDOMHTMLBodyElement** aBody)
|
||||
{
|
||||
*aBody = nsnull;
|
||||
|
||||
if (!mBodyContent && !GetBodyContent()) {
|
||||
// No body in this document.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CallQueryInterface(mBodyContent, aBody);
|
||||
}
|
||||
|
||||
// forms related stuff
|
||||
|
|
|
@ -234,7 +234,8 @@ protected:
|
|||
|
||||
static void DocumentWriteTerminationFunc(nsISupports *aRef);
|
||||
|
||||
nsIContent* GetBodyContent();
|
||||
PRBool GetBodyContent();
|
||||
void GetBodyElement(nsIDOMHTMLBodyElement** aBody);
|
||||
|
||||
void GetDomainURI(nsIURI **uri);
|
||||
|
||||
|
@ -320,6 +321,8 @@ protected:
|
|||
// Load flags of the document's channel
|
||||
PRUint32 mLoadFlags;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> mBodyContent;
|
||||
|
||||
/*
|
||||
* Bug 13871: Frameset spoofing - find out if document.domain was set
|
||||
*/
|
||||
|
|
|
@ -347,7 +347,7 @@ nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObjec
|
|||
nsHTMLDocument::SetScriptGlobalObject(aScriptGlobalObject);
|
||||
|
||||
if (aScriptGlobalObject) {
|
||||
if (!GetRootContent()) {
|
||||
if (!mRootContent) {
|
||||
// Create synthetic document
|
||||
nsresult rv = CreateSyntheticDocument();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
|
||||
|
@ -606,7 +606,7 @@ nsImageDocument::CreateSyntheticDocument()
|
|||
nsresult rv = nsMediaDocument::CreateSyntheticDocument();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIContent* body = GetBodyContent();
|
||||
nsCOMPtr<nsIContent> body = do_QueryInterface(mBodyContent);
|
||||
if (!body) {
|
||||
NS_WARNING("no body on image document!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -651,10 +651,7 @@ nsImageDocument::CheckOverflowing(PRBool changeState)
|
|||
nsPresContext *context = shell->GetPresContext();
|
||||
nsRect visibleArea = context->GetVisibleArea();
|
||||
|
||||
nsIContent* content = GetBodyContent();
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mBodyContent);
|
||||
nsRefPtr<nsStyleContext> styleContext =
|
||||
context->StyleSet()->ResolveStyleFor(content, nsnull);
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ nsMediaDocument::CreateSyntheticDocument()
|
|||
if (!body) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mBodyContent = do_QueryInterface(body);
|
||||
|
||||
root->AppendChildTo(body, PR_FALSE);
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ nsPluginDocument::CreateSyntheticPluginDocument()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// then attach our plugin
|
||||
|
||||
nsIContent* body = GetBodyContent();
|
||||
nsCOMPtr<nsIContent> body = do_QueryInterface(mBodyContent);
|
||||
if (!body) {
|
||||
NS_WARNING("no body on plugin document!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -129,12 +129,6 @@ protected:
|
|||
|
||||
// implementation helpers:
|
||||
void GetOffsetToAncestor(nsIContent* ancestor, float &x, float &y);
|
||||
PRBool IsRoot() {
|
||||
NS_ASSERTION((IsInDoc() && !GetParent()) ==
|
||||
(GetOwnerDoc() && (GetOwnerDoc()->GetRootContent() == this)),
|
||||
"Can't determine if we're root");
|
||||
return IsInDoc() && !GetParent();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> mWidth;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> mHeight;
|
||||
|
@ -990,7 +984,8 @@ nsSVGSVGElement::GetCTM(nsIDOMSVGMatrix **_retval)
|
|||
if (!ancestorCTM) {
|
||||
// we didn't find an SVG ancestor
|
||||
float s=1, x=0, y=0;
|
||||
if (IsRoot()) {
|
||||
if (ownerDoc &&
|
||||
ownerDoc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
// we're the root element. get our currentScale and currentTranslate vals
|
||||
mCurrentScale->GetValue(&s);
|
||||
mCurrentTranslate->GetX(&x);
|
||||
|
@ -1098,7 +1093,8 @@ nsSVGSVGElement::GetScreenCTM(nsIDOMSVGMatrix **_retval)
|
|||
if (!ancestorScreenCTM) {
|
||||
// we didn't find an SVG ancestor
|
||||
float s=1, x=0, y=0;
|
||||
if (IsRoot()) {
|
||||
if (ownerDoc &&
|
||||
ownerDoc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
// we're the root element. get our currentScale and currentTranslate vals
|
||||
mCurrentScale->GetValue(&s);
|
||||
mCurrentTranslate->GetX(&x);
|
||||
|
@ -1276,7 +1272,8 @@ nsSVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
|
|||
if (doc) {
|
||||
nsIPresShell* presShell = doc->GetShellAt(0);
|
||||
NS_ASSERTION(presShell, "no presShell");
|
||||
if (presShell && IsRoot()) {
|
||||
if (presShell &&
|
||||
doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsGUIEvent event(PR_TRUE, NS_SVG_ZOOM, 0);
|
||||
event.eventStructType = NS_SVGZOOM_EVENT;
|
||||
|
@ -1300,7 +1297,8 @@ nsSVGSVGElement::SetCurrentTranslate(float x, float y)
|
|||
if (doc) {
|
||||
nsIPresShell* presShell = doc->GetShellAt(0);
|
||||
NS_ASSERTION(presShell, "no presShell");
|
||||
if (presShell && IsRoot()) {
|
||||
if (presShell &&
|
||||
doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent event(PR_TRUE, NS_SVG_SCROLL);
|
||||
event.eventStructType = NS_SVG_EVENT;
|
||||
|
@ -1402,7 +1400,8 @@ nsSVGSVGElement::DidModifySVGObservable (nsISVGValue* observable,
|
|||
// dispatch an SVGZoom or SVGScroll DOM event before repainting
|
||||
nsCOMPtr<nsIDOMSVGNumber> n = do_QueryInterface(observable);
|
||||
if (n && n==mCurrentScale) {
|
||||
if (mDispatchEvent && IsRoot()) {
|
||||
if (mDispatchEvent &&
|
||||
doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsGUIEvent event(PR_TRUE, NS_SVG_ZOOM, 0);
|
||||
event.eventStructType = NS_SVGZOOM_EVENT;
|
||||
|
@ -1415,7 +1414,8 @@ nsSVGSVGElement::DidModifySVGObservable (nsISVGValue* observable,
|
|||
else {
|
||||
nsCOMPtr<nsIDOMSVGPoint> p = do_QueryInterface(observable);
|
||||
if (p && p==mCurrentTranslate) {
|
||||
if (mDispatchEvent && IsRoot()) {
|
||||
if (mDispatchEvent &&
|
||||
doc->GetRootContent() == NS_STATIC_CAST(nsIContent*, this)) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsEvent event(PR_TRUE, NS_SVG_SCROLL);
|
||||
event.eventStructType = NS_SVG_EVENT;
|
||||
|
|
|
@ -121,10 +121,7 @@ nsSVGDocument::GetURL(nsAString& aURL)
|
|||
NS_IMETHODIMP
|
||||
nsSVGDocument::GetRootElement(nsIDOMSVGSVGElement** aRootElement)
|
||||
{
|
||||
*aRootElement = nsnull;
|
||||
nsIContent* root = GetRootContent();
|
||||
|
||||
return root ? CallQueryInterface(root, aRootElement) : NS_OK;
|
||||
return CallQueryInterface(mRootContent, aRootElement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -546,7 +546,7 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn)
|
|||
mEventQService->PopThreadEventQueue(modalEventQueue);
|
||||
|
||||
// We set return to true unless there was a parsing error
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(GetRootContent());
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mRootContent);
|
||||
if (node) {
|
||||
nsAutoString name, ns;
|
||||
if (NS_SUCCEEDED(node->GetLocalName(name)) &&
|
||||
|
@ -771,15 +771,14 @@ nsXMLDocument::GetElementById(const nsAString& aElementId,
|
|||
// If we tried to load a document and something went wrong, we might not have
|
||||
// root content. This can happen when you do document.load() and the document
|
||||
// to load is not XML, for example.
|
||||
nsIContent* root = GetRootContent();
|
||||
if (!root)
|
||||
if (!mRootContent)
|
||||
return NS_OK;
|
||||
|
||||
// XXX For now, we do a brute force search of the content tree.
|
||||
// We should come up with a more efficient solution.
|
||||
// Note that content is *not* refcounted here, so do *not* release it!
|
||||
nsIContent *content =
|
||||
nsContentUtils::MatchElementId(root, aElementId);
|
||||
nsContentUtils::MatchElementId(mRootContent, aElementId);
|
||||
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
|
|
|
@ -85,8 +85,9 @@ class txXMLParser
|
|||
#endif
|
||||
|
||||
nsresult
|
||||
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
||||
nsAString& aErrMsg, txXPathNode** aResult)
|
||||
txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer,
|
||||
const txXPathNode& aLoader, nsAString& aErrMsg,
|
||||
txXPathNode** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = nsnull;
|
||||
|
@ -108,7 +109,11 @@ txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
|||
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel);
|
||||
if (http) {
|
||||
http->SetReferrer(loaderUri);
|
||||
nsCOMPtr<nsIURI> refUri;
|
||||
NS_NewURI(getter_AddRefs(refUri), aReferrer);
|
||||
if (refUri) {
|
||||
http->SetReferrer(refUri);
|
||||
}
|
||||
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
||||
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
|
||||
PR_FALSE);
|
||||
|
|
|
@ -57,8 +57,9 @@ class txXPathNode;
|
|||
* of the document aLoader.
|
||||
*/
|
||||
extern "C" nsresult
|
||||
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
||||
nsAString& aErrMsg, txXPathNode** aResult);
|
||||
txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer,
|
||||
const txXPathNode& aLoader, nsAString& aErrMsg,
|
||||
txXPathNode** aResult);
|
||||
|
||||
#ifdef TX_EXE
|
||||
/**
|
||||
|
|
|
@ -474,12 +474,13 @@ txExecutionState::retrieveDocument(const nsAString& aUri)
|
|||
|
||||
if (!entry->mDocument) {
|
||||
// open URI
|
||||
nsAutoString errMsg;
|
||||
// XXX we should get the loader from the actual node
|
||||
nsAutoString errMsg, refUri;
|
||||
// XXX we should get the referrer 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, *mLoadedDocuments.mSourceDocument,
|
||||
errMsg,
|
||||
rv = txParseDocumentFromURI(aUri, refUri,
|
||||
*mLoadedDocuments.mSourceDocument, errMsg,
|
||||
getter_Transfers(entry->mDocument));
|
||||
|
||||
if (NS_FAILED(rv) || !entry->mDocument) {
|
||||
|
|
|
@ -799,44 +799,24 @@ void txSyncCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
|
|||
nsresult
|
||||
TX_CompileStylesheet(nsIDOMNode* aNode, txStylesheet** aStylesheet)
|
||||
{
|
||||
// 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<nsIDOMDocument> document;
|
||||
aNode->GetOwnerDocument(getter_AddRefs(document));
|
||||
if (!document) {
|
||||
document = do_QueryInterface(aNode);
|
||||
}
|
||||
|
||||
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);
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
|
||||
nsIURI *uri = doc->GetBaseURI();
|
||||
nsCAutoString baseURI;
|
||||
uri->GetSpec(baseURI);
|
||||
|
||||
nsRefPtr<txSyncCompileObserver> obs = new txSyncCompileObserver();
|
||||
NS_ENSURE_TRUE(obs, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ConvertUTF8toUTF16 base(baseURI);
|
||||
nsRefPtr<txStylesheetCompiler> compiler =
|
||||
new txStylesheetCompiler(stylesheetURI, obs);
|
||||
new txStylesheetCompiler(base, 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);
|
||||
|
|
|
@ -50,20 +50,20 @@
|
|||
#include "txStringUtils.h"
|
||||
#include "txXSLTFunctions.h"
|
||||
|
||||
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI,
|
||||
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI,
|
||||
txACompileObserver* aObserver)
|
||||
: txStylesheetCompilerState(aObserver)
|
||||
{
|
||||
mStatus = init(aStylesheetURI, nsnull, nsnull);
|
||||
mStatus = init(aBaseURI, nsnull, nsnull);
|
||||
}
|
||||
|
||||
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI,
|
||||
txStylesheetCompiler::txStylesheetCompiler(const nsAString& aBaseURI,
|
||||
txStylesheet* aStylesheet,
|
||||
txListIterator* aInsertPosition,
|
||||
txACompileObserver* aObserver)
|
||||
: txStylesheetCompilerState(aObserver)
|
||||
{
|
||||
mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition);
|
||||
mStatus = init(aBaseURI, aStylesheet, aInsertPosition);
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
|
@ -83,19 +83,6 @@ 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,
|
||||
|
@ -407,7 +394,7 @@ txStylesheetCompiler::doneLoading()
|
|||
{
|
||||
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
|
||||
("Compiler::doneLoading: %s\n",
|
||||
NS_LossyConvertUTF16toASCII(mStylesheetURI).get()));
|
||||
NS_LossyConvertUTF16toASCII(mURI).get()));
|
||||
if (NS_FAILED(mStatus)) {
|
||||
return mStatus;
|
||||
}
|
||||
|
@ -423,7 +410,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(mStylesheetURI).get(),
|
||||
NS_LossyConvertUTF16toASCII(mURI).get(),
|
||||
NS_ERROR_GET_MODULE(aError),
|
||||
NS_ERROR_GET_CODE(aError)));
|
||||
if (NS_SUCCEEDED(mStatus)) {
|
||||
|
@ -452,8 +439,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(mStylesheetURI).get()));
|
||||
if (mStylesheetURI.Equals(aUri)) {
|
||||
NS_LossyConvertUTF16toASCII(mURI).get()));
|
||||
if (mURI.Equals(aUri)) {
|
||||
return NS_ERROR_XSLT_LOAD_RECURSION;
|
||||
}
|
||||
return mObserver ? mObserver->loadURI(aUri, aReferrerUri, aCompiler) :
|
||||
|
@ -567,21 +554,21 @@ txStylesheetCompilerState::txStylesheetCompilerState(txACompileObserver* aObserv
|
|||
}
|
||||
|
||||
nsresult
|
||||
txStylesheetCompilerState::init(const nsAString& aStylesheetURI,
|
||||
txStylesheetCompilerState::init(const nsAString& aBaseURI,
|
||||
txStylesheet* aStylesheet,
|
||||
txListIterator* aInsertPosition)
|
||||
{
|
||||
NS_ASSERTION(!aStylesheet || aInsertPosition,
|
||||
"must provide insertposition if loading subsheet");
|
||||
mStylesheetURI = aStylesheetURI;
|
||||
mURI = aBaseURI;
|
||||
// Check for fragment identifier of an embedded stylesheet.
|
||||
PRInt32 fragment = aStylesheetURI.FindChar('#') + 1;
|
||||
PRInt32 fragment = aBaseURI.FindChar('#') + 1;
|
||||
if (fragment > 0) {
|
||||
PRInt32 fragmentLength = aStylesheetURI.Length() - fragment;
|
||||
PRInt32 fragmentLength = aBaseURI.Length() - fragment;
|
||||
if (fragmentLength > 0) {
|
||||
// This is really an embedded stylesheet, not just a
|
||||
// "url#". We may want to unescape the fragment.
|
||||
mTarget = Substring(aStylesheetURI, (PRUint32)fragment,
|
||||
mTarget = Substring(aBaseURI, (PRUint32)fragment,
|
||||
fragmentLength);
|
||||
mEmbedStatus = eNeedEmbed;
|
||||
mHandlerTable = gTxEmbedHandler;
|
||||
|
@ -606,7 +593,7 @@ txStylesheetCompilerState::init(const nsAString& aStylesheetURI,
|
|||
mIsTopCompiler = PR_TRUE;
|
||||
}
|
||||
|
||||
mElementContext = new txElementContext(aStylesheetURI);
|
||||
mElementContext = new txElementContext(aBaseURI);
|
||||
NS_ENSURE_TRUE(mElementContext && mElementContext->mMappings,
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -763,7 +750,7 @@ txStylesheetCompilerState::loadIncludedStylesheet(const nsAString& aURI)
|
|||
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
|
||||
("CompilerState::loadIncludedStylesheet: %s\n",
|
||||
NS_LossyConvertUTF16toASCII(aURI).get()));
|
||||
if (mStylesheetURI.Equals(aURI)) {
|
||||
if (mURI.Equals(aURI)) {
|
||||
return NS_ERROR_XSLT_LOAD_RECURSION;
|
||||
}
|
||||
NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
@ -793,7 +780,7 @@ txStylesheetCompilerState::loadIncludedStylesheet(const nsAString& aURI)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = mObserver->loadURI(aURI, mStylesheetURI, compiler);
|
||||
rv = mObserver->loadURI(aURI, mURI, compiler);
|
||||
if (NS_FAILED(rv)) {
|
||||
mChildCompilerList.RemoveElement(compiler);
|
||||
}
|
||||
|
@ -808,7 +795,7 @@ txStylesheetCompilerState::loadImportedStylesheet(const nsAString& aURI,
|
|||
PR_LOG(txLog::xslt, PR_LOG_ALWAYS,
|
||||
("CompilerState::loadImportedStylesheet: %s\n",
|
||||
NS_LossyConvertUTF16toASCII(aURI).get()));
|
||||
if (mStylesheetURI.Equals(aURI)) {
|
||||
if (mURI.Equals(aURI)) {
|
||||
return NS_ERROR_XSLT_LOAD_RECURSION;
|
||||
}
|
||||
NS_ENSURE_TRUE(mObserver, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
@ -826,7 +813,7 @@ txStylesheetCompilerState::loadImportedStylesheet(const nsAString& aURI,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = mObserver->loadURI(aURI, mStylesheetURI, compiler);
|
||||
nsresult rv = mObserver->loadURI(aURI, mURI, compiler);
|
||||
if (NS_FAILED(rv)) {
|
||||
mChildCompilerList.RemoveElement(compiler);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
txStylesheetCompilerState(txACompileObserver* aObserver);
|
||||
~txStylesheetCompilerState();
|
||||
|
||||
nsresult init(const nsAString& aStylesheetURI, txStylesheet* aStylesheet,
|
||||
nsresult init(const nsAString& aBaseURI, txStylesheet* aStylesheet,
|
||||
txListIterator* aInsertPosition);
|
||||
|
||||
// Embedded stylesheets state
|
||||
|
@ -175,13 +175,13 @@ protected:
|
|||
eInEmbed,
|
||||
eHasEmbed
|
||||
} mEmbedStatus;
|
||||
nsString mStylesheetURI;
|
||||
nsString mURI;
|
||||
PRPackedBool mIsTopCompiler;
|
||||
PRPackedBool mDoneWithThisStylesheet;
|
||||
txStack mObjectStack;
|
||||
txStack mOtherStack;
|
||||
|
||||
private:
|
||||
txStack mObjectStack;
|
||||
txStack mOtherStack;
|
||||
txInstruction** mNextInstrPtr;
|
||||
txListIterator mToplevelIterator;
|
||||
nsVoidArray mGotoTargetPointers;
|
||||
|
@ -200,17 +200,15 @@ class txStylesheetCompiler : private txStylesheetCompilerState,
|
|||
{
|
||||
public:
|
||||
friend class txStylesheetCompilerState;
|
||||
txStylesheetCompiler(const nsAString& aStylesheetURI,
|
||||
txStylesheetCompiler(const nsAString& aBaseURI,
|
||||
txACompileObserver* aObserver);
|
||||
txStylesheetCompiler(const nsAString& aStylesheetURI,
|
||||
txStylesheetCompiler(const nsAString& aBaseURI,
|
||||
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);
|
||||
|
|
|
@ -1019,8 +1019,6 @@ 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);
|
||||
|
||||
|
@ -1080,7 +1078,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
|||
nsCOMPtr<nsIDOMXULSelectControlItemElement> curItem;
|
||||
controlElement->GetCurrentItem(getter_AddRefs(curItem));
|
||||
nsCOMPtr<nsIContent> curNode = do_QueryInterface(curItem);
|
||||
if (curNode && nsContentUtils::ContentIsDescendantOf(curNode, oldKid)) {
|
||||
if (curNode && isSelfOrAncestor(curNode, oldKid)) {
|
||||
// Current item going away
|
||||
nsCOMPtr<nsIBoxObject> box;
|
||||
controlElement->GetBoxObject(getter_AddRefs(box));
|
||||
|
|
|
@ -1429,7 +1429,7 @@ nsXULDocument::GetPixelDimensions(nsIPresShell* aShell, PRInt32* aWidth,
|
|||
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsIFrame* frame = aShell->GetPrimaryFrameFor(GetRootContent());
|
||||
nsIFrame* frame = aShell->GetPrimaryFrameFor(mRootContent);
|
||||
if (frame) {
|
||||
nsIView* view = frame->GetView();
|
||||
// If we have a view check if it's scrollable. If not,
|
||||
|
@ -1963,7 +1963,7 @@ nsXULDocument::Init()
|
|||
nsresult
|
||||
nsXULDocument::StartLayout(void)
|
||||
{
|
||||
if (!GetRootContent()) {
|
||||
if (!mRootContent) {
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING)) {
|
||||
nsCAutoString urlspec;
|
||||
|
@ -2950,9 +2950,7 @@ nsXULDocument::ResumeWalk()
|
|||
mDocumentLoaded = PR_TRUE;
|
||||
|
||||
nsAutoString title;
|
||||
nsIContent *rootContent = GetRootContent();
|
||||
if (rootContent)
|
||||
rootContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::title, title);
|
||||
mRootContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::title, title);
|
||||
SetTitle(title);
|
||||
|
||||
StartLayout();
|
||||
|
@ -3603,7 +3601,7 @@ nsXULDocument::OverlayForwardReference::Resolve()
|
|||
mOverlay->GetAttr(kNameSpaceID_None, nsXULAtoms::id, id);
|
||||
if (id.IsEmpty()) {
|
||||
// overlay had no id, use the root element
|
||||
mDocument->InsertElement(mDocument->GetRootContent(), mOverlay, notify);
|
||||
mDocument->InsertElement(mDocument->mRootContent, mOverlay, notify);
|
||||
mResolved = PR_TRUE;
|
||||
return eResolve_Succeeded;
|
||||
}
|
||||
|
|
|
@ -333,7 +333,7 @@ nsXULContentUtils::MakeElementURI(nsIDocument* aDocument, const nsAString& aElem
|
|||
CopyUTF16toUTF8(aElementID, aURI);
|
||||
}
|
||||
else {
|
||||
nsIURI *docURL = aDocument->GetDocumentURI();
|
||||
nsIURI *docURL = aDocument->GetBaseURI();
|
||||
|
||||
// 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->GetDocumentURI()->GetSpec(spec);
|
||||
aDocument->GetBaseURI()->GetSpec(spec);
|
||||
|
||||
// XXX FIX ME to not do a copy
|
||||
nsAutoString str(aURI);
|
||||
|
|
|
@ -411,8 +411,6 @@ 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");
|
||||
|
@ -434,7 +432,7 @@ nsXFormsModelElement::InitializeInstances()
|
|||
newURL->GetRef(ref);
|
||||
newURL->SetRef(EmptyCString());
|
||||
PRBool equals = PR_FALSE;
|
||||
newURL->Equals(docURI, &equals);
|
||||
newURL->Equals(baseURI, &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>
|
||||
|
|
|
@ -762,13 +762,13 @@ nsPresContext::SetShell(nsIPresShell* aShell)
|
|||
nsIDocument *doc = mShell->GetDocument();
|
||||
NS_ASSERTION(doc, "expect document here");
|
||||
if (doc) {
|
||||
nsIURI *docURI = doc->GetDocumentURI();
|
||||
nsIURI *baseURI = doc->GetBaseURI();
|
||||
|
||||
if (mMedium != nsLayoutAtoms::print && docURI) {
|
||||
if (mMedium != nsLayoutAtoms::print && baseURI) {
|
||||
PRBool isChrome = PR_FALSE;
|
||||
PRBool isRes = PR_FALSE;
|
||||
docURI->SchemeIs("chrome", &isChrome);
|
||||
docURI->SchemeIs("resource", &isRes);
|
||||
baseURI->SchemeIs("chrome", &isChrome);
|
||||
baseURI->SchemeIs("resource", &isRes);
|
||||
|
||||
if (!isChrome && !isRes)
|
||||
mImageAnimationMode = mImageAnimationModePref;
|
||||
|
|
|
@ -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 *baseURI = document->GetBaseURI();
|
||||
if (!baseURI) {
|
||||
nsIURI *docURL = document->GetBaseURI();
|
||||
if (!docURL) {
|
||||
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;
|
||||
baseURI->GetSpec(relPath);
|
||||
docURL->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(),
|
||||
baseURI))) {
|
||||
docURL))) {
|
||||
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(), baseURI);
|
||||
flatDocCharset.get(), docURL);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// Now pass on absolute url to the click handler
|
||||
|
|
Загрузка…
Ссылка в новой задаче