diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index d07101598e28..4a8a0aa36fda 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -439,10 +439,13 @@ public: * @param aNotify whether to notify the document (current document for * nsIContent, and |this| for nsIDocument) that the remove has * occurred + * @param aMutationEvent whether to fire a mutation event * * Note: If there is no child at aIndex, this method will simply do nothing. */ - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify) = 0; + virtual nsresult RemoveChildAt(PRUint32 aIndex, + PRBool aNotify, + PRBool aMutationEvent = PR_TRUE) = 0; /** * Get a property associated with this node. diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 0500ec21887a..4d7e9490782b 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -84,6 +84,7 @@ REQUIRES = xpcom \ shistory \ editor \ windowwatcher \ + html5 \ $(NULL) ifdef ACCESSIBILITY diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index cfb95ecb2f8d..79ecf16f933f 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -794,7 +794,7 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement, nsresult nsContentSink::ProcessMETATag(nsIContent* aContent) { - NS_ASSERTION(aContent, "missing base-element"); + NS_ASSERTION(aContent, "missing meta-element"); nsresult rv = NS_OK; @@ -810,6 +810,16 @@ nsContentSink::ProcessMETATag(nsIContent* aContent) rv = ProcessHeaderData(fieldAtom, result, aContent); } } + NS_ENSURE_SUCCESS(rv, rv); + + /* Look for the viewport meta tag. If we find it, process it and put the + * data into the document header. */ + if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, + nsGkAtoms::viewport, eIgnoreCase)) { + nsAutoString value; + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value); + rv = nsContentUtils::ProcessViewportInfo(mDocument, value); + } return rv; } diff --git a/content/base/src/nsContentSink.h b/content/base/src/nsContentSink.h index 5f6d705d664a..432d20525d43 100644 --- a/content/base/src/nsContentSink.h +++ b/content/base/src/nsContentSink.h @@ -146,6 +146,8 @@ class nsContentSink : public nsICSSLoaderObserver, virtual void UpdateChildCounts() = 0; + PRBool IsTimeToNotify(); + protected: nsContentSink(); virtual ~nsContentSink(); @@ -241,12 +243,14 @@ protected: nsIURI **aManifestURI, CacheSelectionAction *aAction); +public: // Searches for the offline cache manifest attribute and calls one // of the above defined methods to select the document's application // cache, let it be associated with the document and eventually // schedule the cache update process. void ProcessOfflineManifest(nsIContent *aElement); +protected: // Tries to scroll to the URI's named anchor. Once we've successfully // done that, further calls to this method will be ignored. void ScrollToRef(); @@ -255,10 +259,9 @@ protected: // Start layout. If aIgnorePendingSheets is true, this will happen even if // we still have stylesheet loads pending. Otherwise, we'll wait until the // stylesheets are all done loading. +public: void StartLayout(PRBool aIgnorePendingSheets); - - PRBool IsTimeToNotify(); - +protected: void FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 0bc447356c67..1ac7c833f5e2 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -164,6 +164,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIMIMEHeaderParam.h" #include "nsIDOMDragEvent.h" #include "nsDOMDataTransfer.h" +#include "nsHtml5Module.h" #ifdef IBMBIDI #include "nsIBidiKeyboard.h" @@ -3579,6 +3580,58 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode, // for compiling event handlers... so just bail out. nsCOMPtr document = node->GetOwnerDoc(); NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE); + + PRBool bCaseSensitive = document->IsCaseSensitive(); + + nsCOMPtr htmlDoc(do_QueryInterface(document)); + PRBool bHTML = htmlDoc && !bCaseSensitive; + + if (bHTML && nsHtml5Module::Enabled) { + // See if the document has a cached fragment parser. nsHTMLDocument is the + // only one that should really have one at the moment. + nsCOMPtr parser = document->GetFragmentParser(); + if (parser) { + // Get the parser ready to use. + parser->Reset(); + } + else { + // Create a new parser for this operation. + parser = nsHtml5Module::NewHtml5Parser(); + if (!parser) { + return NS_ERROR_OUT_OF_MEMORY; + } + document->SetFragmentParser(parser); + } + nsCOMPtr frag; + rv = NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager()); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr contextAsContent = do_QueryInterface(aContextNode); + if (contextAsContent && !contextAsContent->IsNodeOfType(nsINode::eELEMENT)) { + contextAsContent = contextAsContent->GetParent(); + if (contextAsContent && !contextAsContent->IsNodeOfType(nsINode::eELEMENT)) { + // can this even happen? + contextAsContent = nsnull; + } + } + + if (contextAsContent) { + parser->ParseFragment(aFragment, + frag, + contextAsContent->Tag(), + contextAsContent->GetNameSpaceID(), + (document->GetCompatibilityMode() == eCompatibility_NavQuirks)); + } else { + parser->ParseFragment(aFragment, + frag, + nsGkAtoms::body, + kNameSpaceID_XHTML, + (document->GetCompatibilityMode() == eCompatibility_NavQuirks)); + } + + NS_ADDREF(*aReturn = frag); + return NS_OK; + } nsAutoTArray tagStack; nsAutoString uriStr, nameStr; @@ -3636,14 +3689,9 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode, } nsCAutoString contentType; - PRBool bCaseSensitive = PR_TRUE; nsAutoString buf; document->GetContentType(buf); LossyCopyUTF16toASCII(buf, contentType); - bCaseSensitive = document->IsCaseSensitive(); - - nsCOMPtr htmlDoc(do_QueryInterface(document)); - PRBool bHTML = htmlDoc && !bCaseSensitive; // See if the document has a cached fragment parser. nsHTMLDocument is the // only one that should really have one at the moment. diff --git a/content/base/src/nsDOMAttribute.cpp b/content/base/src/nsDOMAttribute.cpp index fab7e7f9a2ac..d27d8585c148 100644 --- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -699,8 +699,9 @@ nsDOMAttribute::AppendChildTo(nsIContent* aKid, PRBool aNotify) } nsresult -nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { + NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on attribute child removal."); if (aIndex != 0 || !mChild) { return NS_OK; } diff --git a/content/base/src/nsDOMAttribute.h b/content/base/src/nsDOMAttribute.h index fca0ef499744..e6efc5c21cef 100644 --- a/content/base/src/nsDOMAttribute.h +++ b/content/base/src/nsDOMAttribute.h @@ -98,7 +98,7 @@ public: virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 9d0ba64a7761..f602da6f2140 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3221,8 +3221,9 @@ nsDocument::AppendChildTo(nsIContent* aKid, PRBool aNotify) } nsresult -nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { + NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on document child removal."); nsCOMPtr oldKid = GetChildAt(aIndex); if (!oldKid) { return NS_OK; @@ -3234,7 +3235,8 @@ nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) } nsresult rv = nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid, - nsnull, this, mChildren); + nsnull, this, mChildren, + aMutationEvent); mCachedRootContent = nsnull; return rv; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index bced2bef9360..c424b20c401e 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -810,7 +810,7 @@ public: virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 416ad049c235..fb4c4f8bfa95 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -752,7 +752,7 @@ nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, } nsresult -nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { return NS_OK; } diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index 42661ff6990d..93e410abd1cd 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -166,7 +166,7 @@ public: virtual PRInt32 IndexOf(nsINode* aPossibleChild) const; virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 73218beb3c8a..ec40c94743da 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -3246,14 +3246,14 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, } nsresult -nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { nsCOMPtr oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex); NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt"); if (oldKid) { return doRemoveChildAt(aIndex, aNotify, oldKid, this, GetCurrentDoc(), - mAttrsAndChildren); + mAttrsAndChildren, aMutationEvent); } return NS_OK; @@ -3264,7 +3264,8 @@ nsresult nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid, nsIContent* aParent, nsIDocument* aDocument, - nsAttrAndChildArray& aChildArray) + nsAttrAndChildArray& aChildArray, + PRBool aMutationEvent) { NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument, @@ -3300,6 +3301,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, mozAutoSubtreeModified subtree(nsnull, nsnull); if (aNotify && + aMutationEvent && nsContentUtils::HasMutationListeners(aKid, NS_EVENT_BITS_MUTATION_NODEREMOVED, container)) { mozAutoRemovableBlockerRemover blockerRemover; diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 87962975cf37..d11e541757a8 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -354,7 +354,7 @@ public: virtual PRInt32 IndexOf(nsINode* aPossibleChild) const; virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, @@ -654,7 +654,8 @@ public: static nsresult doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid, nsIContent* aParent, nsIDocument* aDocument, - nsAttrAndChildArray& aChildArray); + nsAttrAndChildArray& aChildArray, + PRBool aMutationEvent); /** * Helper methods for implementing querySelector/querySelectorAll diff --git a/content/base/src/nsHTMLContentSerializer.cpp b/content/base/src/nsHTMLContentSerializer.cpp index 85c03c5bd1ca..2e9354c69123 100644 --- a/content/base/src/nsHTMLContentSerializer.cpp +++ b/content/base/src/nsHTMLContentSerializer.cpp @@ -68,6 +68,7 @@ #include "nsLWBrkCIID.h" #include "nsIScriptElement.h" #include "nsAttrName.h" +#include "nsHtml5Module.h" static const char kMozStr[] = "moz"; @@ -100,6 +101,7 @@ nsHTMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, return NS_OK; } +#include "nsIHTMLDocument.h" void nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent, nsIDOMElement *aOriginalElement, @@ -108,19 +110,40 @@ nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent, nsIAtom* aTagName, nsAString& aStr) { + PRInt32 count = aContent->GetAttrCount(); + if (!count) + return; + nsresult rv; - PRUint32 index, count; nsAutoString nameStr, valueStr; - - count = aContent->GetAttrCount(); - NS_NAMED_LITERAL_STRING(_mozStr, "_moz"); - // Loop backward over the attributes, since the order they are stored in is - // the opposite of the order they were parsed in (see bug 213347 for reason). - // index is unsigned, hence index >= 0 is always true. - for (index = count; index > 0; ) { - --index; + // HTML5 parser stored them in the order they were parsed so we want to + // loop forward in that case. + nsIDocument* doc = aContent->GetOwnerDocument(); + PRBool caseSensitive = doc && doc->IsCaseSensitive(); + PRBool loopForward = PR_FALSE; + if (!caseSensitive) { + nsCOMPtr htmlDoc(do_QueryInterface(doc)); + if (htmlDoc) { + loopForward = nsHtml5Module::Enabled; + } + } + PRInt32 index, limit, step; + if (loopForward) { + index = 0; + limit = count; + step = 1; + } + else { + // Loop backward over the attributes, since the order they are stored in is + // the opposite of the order they were parsed in (see bug 213347 for reason). + index = count - 1; + limit = -1; + step = -1; + } + + for (; index != limit; index += step) { const nsAttrName* name = aContent->GetAttrNameAt(index); PRInt32 namespaceID = name->NamespaceID(); nsIAtom* attrName = name->LocalName(); diff --git a/content/base/test/test_bug417255.html b/content/base/test/test_bug417255.html index ef0563ae8d95..96e7b2c8c8fe 100644 --- a/content/base/test/test_bug417255.html +++ b/content/base/test/test_bug417255.html @@ -15,20 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=417255 Mozilla Bug 417255 -

+
-

+

-
+
-

+

-
+
-

+

-
+