merge m-c to devtools
authorRob Campbell <rcampbell@mozilla.com>
Sun, 10 Apr 2011 10:47:40 -0300
changeset 67807 6ae459b3a539f359896e2567a4fc786928108e96
parent 67806 bc1ba93ee006d7392468277f491926fec0df89bd (current diff)
parent 67754 fe3f7889918b2c2a7a37e75d78d6fd436d3949a0 (diff)
child 67808 102a2b309cc38da0808ce766795b6730b7f99414
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.2a1pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge m-c to devtools
content/mathml/content/src/mathml.dtd
content/xml/content/src/xhtml11.dtd
embedding/browser/gtk/Makefile.in
embedding/browser/gtk/src/EmbedCertificates.cpp
embedding/browser/gtk/src/EmbedCertificates.h
embedding/browser/gtk/src/EmbedContentListener.cpp
embedding/browser/gtk/src/EmbedContentListener.h
embedding/browser/gtk/src/EmbedContextMenuInfo.cpp
embedding/browser/gtk/src/EmbedContextMenuInfo.h
embedding/browser/gtk/src/EmbedEventListener.cpp
embedding/browser/gtk/src/EmbedEventListener.h
embedding/browser/gtk/src/EmbedGtkTools.cpp
embedding/browser/gtk/src/EmbedGtkTools.h
embedding/browser/gtk/src/EmbedPrivate.cpp
embedding/browser/gtk/src/EmbedPrivate.h
embedding/browser/gtk/src/EmbedProgress.cpp
embedding/browser/gtk/src/EmbedProgress.h
embedding/browser/gtk/src/EmbedPrompter.cpp
embedding/browser/gtk/src/EmbedPrompter.h
embedding/browser/gtk/src/EmbedWindow.cpp
embedding/browser/gtk/src/EmbedWindow.h
embedding/browser/gtk/src/EmbedWindowCreator.cpp
embedding/browser/gtk/src/EmbedWindowCreator.h
embedding/browser/gtk/src/GtkPromptService.cpp
embedding/browser/gtk/src/GtkPromptService.h
embedding/browser/gtk/src/Makefile.in
embedding/browser/gtk/src/gtkmozembed.h
embedding/browser/gtk/src/gtkmozembed2.cpp
embedding/browser/gtk/src/gtkmozembed_glue.cpp
embedding/browser/gtk/src/gtkmozembed_internal.h
embedding/browser/gtk/src/gtkmozembedmarshal.list
embedding/browser/gtk/src/gtkmozembedprivate.h
embedding/browser/gtk/tests/Makefile.in
embedding/browser/gtk/tests/TestGtkEmbed.cpp
embedding/browser/gtk/tests/TestGtkEmbedChild.cpp
embedding/browser/gtk/tests/TestGtkEmbedMDI.cpp
embedding/browser/gtk/tests/TestGtkEmbedNotebook.cpp
embedding/browser/gtk/tests/TestGtkEmbedSocket.cpp
extensions/java/Makefile.in
extensions/java/xpcom/Makefile.in
extensions/java/xpcom/glue/Makefile.in
extensions/java/xpcom/glue/nsJavaXPCOMGlue.cpp
extensions/java/xpcom/interfaces/Makefile.in
extensions/java/xpcom/interfaces/gen-nsError.pl
extensions/java/xpcom/interfaces/org/mozilla/xpcom/GREVersionRange.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/IAppFileLocProvider.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/IGRE.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/IJavaXPCOMUtils.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/IMozilla.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/INIParser.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/IXPCOM.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/Mozilla.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/ProfileLock.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/VersionComparator.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/XPCOMException.java
extensions/java/xpcom/interfaces/org/mozilla/xpcom/XPCOMInitializationException.java
extensions/java/xpcom/package/Makefile.in
extensions/java/xpcom/package/javaconnect.jst
extensions/java/xpcom/package/packages-mac
extensions/java/xpcom/package/packages-unix
extensions/java/xpcom/package/packages-win
extensions/java/xpcom/src/MacJawt.mm
extensions/java/xpcom/src/Makefile.in
extensions/java/xpcom/src/dlldeps-javaxpcom.cpp
extensions/java/xpcom/src/nsAppFileLocProviderProxy.cpp
extensions/java/xpcom/src/nsAppFileLocProviderProxy.h
extensions/java/xpcom/src/nsJavaInterfaces.cpp
extensions/java/xpcom/src/nsJavaInterfaces.h
extensions/java/xpcom/src/nsJavaWrapper.cpp
extensions/java/xpcom/src/nsJavaWrapper.h
extensions/java/xpcom/src/nsJavaXPCOMBindingUtils.cpp
extensions/java/xpcom/src/nsJavaXPCOMBindingUtils.h
extensions/java/xpcom/src/nsJavaXPTCStub.cpp
extensions/java/xpcom/src/nsJavaXPTCStub.h
extensions/java/xpcom/src/nsJavaXPTCStubWeakRef.cpp
extensions/java/xpcom/src/nsJavaXPTCStubWeakRef.h
extensions/java/xpcom/src/org/mozilla/xpcom/internal/GREImpl.java
extensions/java/xpcom/src/org/mozilla/xpcom/internal/JavaXPCOMMethods.java
extensions/java/xpcom/src/org/mozilla/xpcom/internal/MozillaImpl.java
extensions/java/xpcom/src/org/mozilla/xpcom/internal/XPCOMImpl.java
extensions/java/xpcom/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java
extensions/java/xpcom/src/org/mozilla/xpcom/internal/XPCOMJavaProxyBase.java
extensions/java/xpcom/tests/LocationProvider.java
extensions/java/xpcom/tests/Makefile.in
extensions/java/xpcom/tests/TestArray.java
extensions/java/xpcom/tests/TestINIParser.java
extensions/java/xpcom/tests/TestJavaProxy.java
extensions/java/xpcom/tests/TestProps.java
extensions/java/xpcom/tests/TestQI.java
extensions/java/xpcom/tests/TestVersionComparator.java
extensions/java/xpcom/tests/testparams/Makefile.in
extensions/java/xpcom/tests/testparams/TestParams.java
extensions/java/xpcom/tests/testparams/nsIJXTestArrayParams.idl
extensions/java/xpcom/tests/testparams/nsIJXTestParams.idl
extensions/java/xpcom/tests/testparams/nsJXTestParams.js
extensions/java/xpcom/tests/testparams/xpctests.js
extensions/java/xpcom/tools/genifaces/GenerateJavaInterfaces.cpp
extensions/java/xpcom/tools/genifaces/Makefile.in
extensions/java/xpcom/tools/xpidl/Makefile.in
extensions/java/xpcom/tools/xpidl/xpidl.c
extensions/java/xpcom/tools/xpidl/xpidl.h
extensions/java/xpcom/tools/xpidl/xpidl_doc.c
extensions/java/xpcom/tools/xpidl/xpidl_header.c
extensions/java/xpcom/tools/xpidl/xpidl_idl.c
extensions/java/xpcom/tools/xpidl/xpidl_java.c
extensions/java/xpcom/tools/xpidl/xpidl_javastub.c
extensions/java/xpcom/tools/xpidl/xpidl_typelib.c
extensions/java/xpcom/tools/xpidl/xpidl_util.c
mobile/app/macbuild/.DS_Store
mobile/app/macbuild/CVS/Entries
mobile/app/macbuild/CVS/Repository
mobile/app/macbuild/CVS/Root
toolkit/components/console/hudservice/tests/browser/browser_webconsole_console_logging_api.js
xpcom/glue/nsGREGlue.cpp
xulrunner/app/nsRegisterGRE.h
xulrunner/app/nsRegisterGREUnix.cpp
xulrunner/app/nsRegisterGREVoid.cpp
xulrunner/app/nsRegisterGREWin.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -89,22 +89,22 @@ DIST_GARBAGE = config.cache config.log c
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 ifdef WINCE
 check::
 	$(PYTHON) $(topsrcdir)/build/mobile/devicemanager-utils.py copy $(DIST)/bin
 endif
 
 default alldep all:: $(topsrcdir)/configure config.status
-	$(RM) -rf $(DIST)/sdk
-	$(RM) -rf $(DIST)/include
-	$(RM) -rf $(DIST)/private
-	$(RM) -rf $(DIST)/public
-	$(RM) -rf $(DIST)/bin/components
-	$(RM) -rf _tests
+	$(RM) -r $(DIST)/sdk
+	$(RM) -r $(DIST)/include
+	$(RM) -r $(DIST)/private
+	$(RM) -r $(DIST)/public
+	$(RM) -r $(DIST)/bin/components
+	$(RM) -r _tests
 
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	@echo "STOP!  configure.in has changed, and your configure is out of date."
 	@echo "Please rerun autoconf and re-configure your build directory."
 	@echo "To ignore this message, touch 'configure' in the source directory,"
 	@echo "but your build might not succeed."
 	@exit 1
 
@@ -112,30 +112,30 @@ config.status: $(topsrcdir)/configure
 	@echo "STOP!  configure has changed and needs to be run in this build directory."
 	@echo "Please rerun configure."
 	@echo "To ignore this message, touch 'config.status' in the build directory,"
 	@echo "but your build might not succeed."
 	@exit 1
 
 # Build pseudo-external modules first when export is explicitly called
 export::
-	$(RM) -rf $(DIST)/sdk
+	$(RM) -r $(DIST)/sdk
 	$(MAKE) -C config export
 	$(MAKE) tier_nspr
 
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 distclean::
 	cat unallmakefiles | $(XARGS) rm -f
-	rm -f unallmakefiles $(DIST_GARBAGE)
+	$(RM) unallmakefiles $(DIST_GARBAGE)
 
 ifeq ($(OS_ARCH),WINNT)
 # we want to copy PDB files on Windows
 MAKE_SYM_STORE_ARGS := -c --vcs-info
 ifdef PDBSTR_PATH
 MAKE_SYM_STORE_ARGS += -i
 endif
 DUMP_SYMS_BIN ?= $(topsrcdir)/toolkit/crashreporter/tools/win32/dump_syms_vc$(_MSC_VER).exe
@@ -171,18 +171,18 @@ export SYMBOL_INDEX_NAME = \
   $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
 
 buildsymbols:
 ifdef MOZ_CRASHREPORTER
 ifdef USE_ELF_HACK
 	$(MAKE) -C $(MOZ_BUILD_APP)/installer elfhack
 endif
 	echo building symbol store
-	$(RM) -rf $(DIST)/crashreporter-symbols
-	$(RM) -f "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
+	$(RM) -r $(DIST)/crashreporter-symbols
+	$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
 	  $(MAKE_SYM_STORE_ARGS)                                          \
 	  $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir))               \
 	  $(DUMP_SYMS_BIN)                                                \
 	  $(DIST)/crashreporter-symbols                                   \
 	  $(MAKE_SYM_STORE_PATH) >                                        \
 	  $(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME)
@@ -194,18 +194,18 @@ endif
 	grep "sym" $(SYMBOL_INDEX_NAME) > $(SYMBOL_INDEX_NAME).tmp && \
 	  mv $(SYMBOL_INDEX_NAME).tmp $(SYMBOL_INDEX_NAME)
 	cd $(DIST)/crashreporter-symbols && \
           zip -r9D "../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip" . -i "*.sym" -i "*.txt"
 else
 ifdef WINCE
 ifdef SYMBOLSTORE_PATH
 	echo building symbol store with symstore.exe
-	$(RM) -rf $(DIST)/symbols
-	$(RM) -f "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
+	$(RM) -r $(DIST)/symbols
+	$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/symbols
 	$(SYMBOLSTORE_PATH) add -r -f "$(subst /,\,$(shell pwd -W))\*.PDB" \
 	  -s $(DIST)/symbols/ -t "$(MOZ_PKG_APPNAME)" -v "$(MOZ_PKG_VERSION)"
 	echo packing symbols
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
 	cd $(DIST)/symbols && \
 	  zip -r9D "../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip" .
 endif # SYMBOLSTORE_PATH
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -152,21 +152,22 @@ void
 NotificationController::ScheduleContentInsertion(nsAccessible* aContainer,
                                                  nsIContent* aStartChildNode,
                                                  nsIContent* aEndChildNode)
 {
   // Ignore content insertions until we constructed accessible tree.
   if (mTreeConstructedState == eTreeConstructionPending)
     return;
 
-  nsRefPtr<ContentInsertion> insertion =
-    new ContentInsertion(mDocument, aContainer, aStartChildNode, aEndChildNode);
-
-  if (insertion && mContentInsertions.AppendElement(insertion))
+  nsRefPtr<ContentInsertion> insertion = new ContentInsertion(mDocument,
+                                                              aContainer);
+  if (insertion && insertion->InitChildList(aStartChildNode, aEndChildNode) &&
+      mContentInsertions.AppendElement(insertion)) {
     ScheduleProcessing();
+  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: protected
 
 void
 NotificationController::ScheduleProcessing()
 {
@@ -676,25 +677,41 @@ NotificationController::TextEnumerator(n
   return PL_DHASH_NEXT;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationController: content inserted notification
 
 NotificationController::ContentInsertion::
-  ContentInsertion(nsDocAccessible* aDocument, nsAccessible* aContainer,
-                   nsIContent* aStartChildNode, nsIContent* aEndChildNode) :
+  ContentInsertion(nsDocAccessible* aDocument, nsAccessible* aContainer) :
   mDocument(aDocument), mContainer(aContainer)
 {
+}
+
+bool
+NotificationController::ContentInsertion::
+  InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode)
+{
+  bool haveToUpdate = false;
+
   nsIContent* node = aStartChildNode;
   while (node != aEndChildNode) {
-    mInsertedContent.AppendElement(node);
+    // Notification triggers for content insertion even if no content was
+    // actually inserted, check if the given content has a frame to discard
+    // this case early.
+    if (node->GetPrimaryFrame()) {
+      if (mInsertedContent.AppendElement(node))
+        haveToUpdate = true;
+    }
+
     node = node->GetNextSibling();
   }
+
+  return haveToUpdate;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController::ContentInsertion)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController::ContentInsertion)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContainer)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/accessible/src/base/NotificationController.h
+++ b/accessible/src/base/NotificationController.h
@@ -316,23 +316,23 @@ private:
   nsTArray<nsRefPtr<nsDocAccessible> > mHangingChildDocuments;
 
   /**
    * Storage for content inserted notification information.
    */
   class ContentInsertion
   {
   public:
-    ContentInsertion(nsDocAccessible* aDocument, nsAccessible* aContainer,
-                     nsIContent* aStartChildNode, nsIContent* aEndChildNode);
+    ContentInsertion(nsDocAccessible* aDocument, nsAccessible* aContainer);
     virtual ~ContentInsertion() { mDocument = nsnull; }
 
     NS_INLINE_DECL_REFCOUNTING(ContentInsertion)
     NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentInsertion)
 
+    bool InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode);
     void Process();
 
   private:
     ContentInsertion();
     ContentInsertion(const ContentInsertion&);
     ContentInsertion& operator = (const ContentInsertion&);
 
     // The document used to process content insertion, matched to document of
--- a/accessible/src/base/nsAccTreeWalker.cpp
+++ b/accessible/src/base/nsAccTreeWalker.cpp
@@ -61,18 +61,18 @@ struct WalkState
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccTreeWalker
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccTreeWalker::
   nsAccTreeWalker(nsIWeakReference* aShell, nsIContent* aContent,
-                  PRBool aWalkAnonContent) :
-  mWeakShell(aShell), mState(nsnull)
+                  PRBool aWalkAnonContent, bool aWalkCache) :
+  mWeakShell(aShell), mState(nsnull), mWalkCache(aWalkCache)
 {
   NS_ASSERTION(aContent, "No node for the accessible tree walker!");
 
   if (aContent)
     mState = new WalkState(aContent);
 
   mChildFilter = aWalkAnonContent ? nsIContent::eAllChildren :
                                   nsIContent::eAllButXBL;
@@ -109,17 +109,18 @@ nsAccTreeWalker::NextChildInternal(bool 
   if (mState->childList)
     mState->childList->GetLength(&length);
 
   while (mState->childIdx < length) {
     nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx);
     mState->childIdx++;
 
     bool isSubtreeHidden = false;
-    nsAccessible* accessible =
+    nsAccessible* accessible = mWalkCache ?
+      GetAccService()->GetAccessibleInWeakShell(childNode, mWeakShell) :
       GetAccService()->GetOrCreateAccessible(childNode, presShell, mWeakShell,
                                              &isSubtreeHidden);
 
     if (accessible)
       return accessible;
 
     // Walk down into subtree to find accessibles.
     if (!isSubtreeHidden) {
--- a/accessible/src/base/nsAccTreeWalker.h
+++ b/accessible/src/base/nsAccTreeWalker.h
@@ -49,17 +49,17 @@ struct WalkState;
 
 /**
  * This class is used to walk the DOM tree to create accessible tree.
  */
 class nsAccTreeWalker
 {
 public:
   nsAccTreeWalker(nsIWeakReference *aShell, nsIContent *aNode, 
-                  PRBool aWalkAnonymousContent);
+                  PRBool aWalkAnonymousContent, bool aWalkCache = false);
   virtual ~nsAccTreeWalker();
 
   /**
    * Return the next child accessible.
    *
    * @note Returned accessible is bound to the document, if the accessible is
    *       rejected during tree creation then the caller should be unbind it
    *       from the document.
@@ -90,12 +90,13 @@ private:
 
   /**
    * Pop state from stack.
    */
   void PopState();
 
   nsCOMPtr<nsIWeakReference> mWeakShell;
   PRInt32 mChildFilter;
+  bool mWalkCache;
   WalkState* mState;
 };
 
 #endif 
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -96,19 +96,18 @@ nsApplicationAccessible *nsAccessNode::g
 NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode)
   NS_INTERFACE_MAP_ENTRY(nsIAccessNode)
   NS_INTERFACE_MAP_ENTRY(nsAccessNode)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessNode)
 NS_INTERFACE_MAP_END
  
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsAccessNode, nsIAccessNode)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsAccessNode, nsIAccessNode,
-                                      LastRelease())
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccessNode)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsAccessNode, LastRelease())
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode construction/desctruction
 
 nsAccessNode::
   nsAccessNode(nsIContent *aContent, nsIWeakReference *aShell) :
   mContent(aContent), mWeakShell(aShell)
 {
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -469,45 +469,54 @@ nsAccessible::GetPreviousSibling(nsIAcce
 
   /* readonly attribute nsIAccessible firstChild; */
 NS_IMETHODIMP
 nsAccessible::GetFirstChild(nsIAccessible **aFirstChild) 
 {
   NS_ENSURE_ARG_POINTER(aFirstChild);
   *aFirstChild = nsnull;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 childCount = GetChildCount();
   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
 
   if (childCount > 0)
     NS_ADDREF(*aFirstChild = GetChildAt(0));
 
   return NS_OK;
 }
 
   /* readonly attribute nsIAccessible lastChild; */
 NS_IMETHODIMP
 nsAccessible::GetLastChild(nsIAccessible **aLastChild)
 {
   NS_ENSURE_ARG_POINTER(aLastChild);
   *aLastChild = nsnull;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 childCount = GetChildCount();
   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
 
   NS_IF_ADDREF(*aLastChild = GetChildAt(childCount - 1));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild)
 {
   NS_ENSURE_ARG_POINTER(aChild);
   *aChild = nsnull;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 childCount = GetChildCount();
   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
 
   // If child index is negative, then return last child.
   // XXX: do we really need this?
   if (aChildIndex < 0)
     aChildIndex = childCount - 1;
 
@@ -521,16 +530,19 @@ nsAccessible::GetChildAt(PRInt32 aChildI
 
 // readonly attribute nsIArray children;
 NS_IMETHODIMP
 nsAccessible::GetChildren(nsIArray **aOutChildren)
 {
   NS_ENSURE_ARG_POINTER(aOutChildren);
   *aOutChildren = nsnull;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 childCount = GetChildCount();
   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMutableArray> children =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -550,16 +562,19 @@ nsAccessible::GetAllowsAnonChildAccessib
 }
 
 /* readonly attribute long childCount; */
 NS_IMETHODIMP
 nsAccessible::GetChildCount(PRInt32 *aChildCount) 
 {
   NS_ENSURE_ARG_POINTER(aChildCount);
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   *aChildCount = GetChildCount();
   return *aChildCount != -1 ? NS_OK : NS_ERROR_FAILURE;  
 }
 
 /* readonly attribute long indexInParent; */
 NS_IMETHODIMP
 nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
 {
@@ -2807,88 +2822,75 @@ nsAccessible::RemoveChild(nsAccessible* 
   mEmbeddedObjCollector = nsnull;
 
   return PR_TRUE;
 }
 
 nsAccessible*
 nsAccessible::GetChildAt(PRUint32 aIndex)
 {
-  if (EnsureChildren())
-    return nsnull;
-
   nsAccessible *child = mChildren.SafeElementAt(aIndex, nsnull);
   if (!child)
     return nsnull;
 
 #ifdef DEBUG
   nsAccessible* realParent = child->mParent;
   NS_ASSERTION(!realParent || realParent == this,
                "Two accessibles have the same first child accessible!");
 #endif
 
   return child;
 }
 
 PRInt32
 nsAccessible::GetChildCount()
 {
-  return EnsureChildren() ? -1 : mChildren.Length();
+  return mChildren.Length();
 }
 
 PRInt32
 nsAccessible::GetIndexOf(nsAccessible* aChild)
 {
-  return EnsureChildren() || (aChild->mParent != this) ?
-    -1 : aChild->GetIndexInParent();
+  return (aChild->mParent != this) ? -1 : aChild->GetIndexInParent();
 }
 
 PRInt32
 nsAccessible::GetIndexInParent() const
 {
   return mIndexInParent;
 }
 
 PRInt32
 nsAccessible::GetEmbeddedChildCount()
 {
-  if (EnsureChildren())
-    return -1;
-
   if (IsChildrenFlag(eMixedChildren)) {
     if (!mEmbeddedObjCollector)
       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
     return mEmbeddedObjCollector ? mEmbeddedObjCollector->Count() : -1;
   }
 
   return GetChildCount();
 }
 
 nsAccessible*
 nsAccessible::GetEmbeddedChildAt(PRUint32 aIndex)
 {
-  if (EnsureChildren())
-    return nsnull;
-
   if (IsChildrenFlag(eMixedChildren)) {
     if (!mEmbeddedObjCollector)
       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
     return mEmbeddedObjCollector ?
       mEmbeddedObjCollector->GetAccessibleAt(aIndex) : nsnull;
   }
 
   return GetChildAt(aIndex);
 }
 
 PRInt32
 nsAccessible::GetIndexOfEmbeddedChild(nsAccessible* aChild)
 {
-  if (EnsureChildren())
-    return -1;
-
   if (IsChildrenFlag(eMixedChildren)) {
     if (!mEmbeddedObjCollector)
       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
     return mEmbeddedObjCollector ?
       mEmbeddedObjCollector->GetIndexAt(aChild) : -1;
   }
 
   return GetIndexOf(aChild);
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1422,36 +1422,36 @@ void
 nsDocAccessible::ContentRemoved(nsIContent* aContainerNode,
                                 nsIContent* aChildNode)
 {
   // Update the whole tree of this document accessible when the container is
   // null (document element is removed).
   nsAccessible* container = aContainerNode ?
     GetAccessibleOrContainer(aContainerNode) : this;
 
-  UpdateTree(container, aChildNode, PR_FALSE);
+  UpdateTree(container, aChildNode, false);
 }
 
 void
 nsDocAccessible::RecreateAccessible(nsIContent* aContent)
 {
   // XXX: we shouldn't recreate whole accessible subtree, instead we should
   // subclass hide and show events to handle them separately and implement their
   // coalescence with normal hide and show events. Note, in this case they
   // should be coalesced with normal show/hide events.
 
   // Check if the node is in DOM still.
   nsIContent* parentContent = aContent->GetParent();
   if (parentContent && parentContent->IsInDoc()) {
     nsAccessible* container = GetAccessibleOrContainer(parentContent);
 
     // Remove and reinsert.
-    UpdateTree(container, aContent, PR_FALSE);
+    UpdateTree(container, aContent, false);
     container->UpdateChildren();
-    UpdateTree(container, aContent, PR_TRUE);
+    UpdateTree(container, aContent, true);
   }
 }
 
 void
 nsDocAccessible::NotifyOfCachingStart(nsAccessible* aAccessible)
 {
   if (!mCacheRoot)
     mCacheRoot = aAccessible;
@@ -1463,25 +1463,30 @@ nsDocAccessible::NotifyOfCachingEnd(nsAc
   if (mCacheRoot == aAccessible && !mIsPostCacheProcessing) {
     // Allow invalidation list insertions while container children are recached.
     mIsPostCacheProcessing = PR_TRUE;
 
     // Invalidate children of container accessible for each element in
     // invalidation list.
     for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) {
       nsIContent* content = mInvalidationList[idx];
-      if (!HasAccessible(content)) {
-        // Make sure we keep children updated. While we're inside of caching
-        // loop then we must exist it with cached children.
+      nsAccessible* accessible = GetAccessible(content);
+      if (!accessible) {
         nsAccessible* container = GetContainerAccessible(content);
         NS_ASSERTION(container,
                      "Got a referenced element that is not in document!");
-        if (container)
+        if (container) {
           container->UpdateChildren();
+          accessible = GetAccessible(content);
+        }
       }
+
+      // Make sure the subtree is created.
+      if (accessible)
+        CacheChildrenInSubtree(accessible);
     }
     mInvalidationList.Clear();
 
     mCacheRoot = nsnull;
     mIsPostCacheProcessing = PR_FALSE;
   }
 }
 
@@ -1792,26 +1797,38 @@ nsDocAccessible::ProcessContentInserted(
   // double processing, however generated events are coalesced and we don't
   // harm an AT.
   // Theoretically the element might be not in tree at all at this point what
   // means there's no container.
   for (PRUint32 idx = 0; idx < aInsertedContent->Length(); idx++) {
     nsAccessible* directContainer =
       GetContainerAccessible(aInsertedContent->ElementAt(idx));
     if (directContainer)
-      UpdateTree(directContainer, aInsertedContent->ElementAt(idx), PR_TRUE);
+      UpdateTree(directContainer, aInsertedContent->ElementAt(idx), true);
   }
 }
 
 void
 nsDocAccessible::UpdateTree(nsAccessible* aContainer, nsIContent* aChildNode,
-                            PRBool aIsInsert)
+                            bool aIsInsert)
 {
-  PRUint32 updateFlags =
-    UpdateTreeInternal(aChildNode, aChildNode->GetNextSibling(), aIsInsert);
+  PRUint32 updateFlags = eNoAccessible;
+
+  // If child node is not accessible then look for its accessible children.
+  nsAccessible* child = GetAccessible(aChildNode);
+  if (child) {
+    updateFlags |= UpdateTreeInternal(child, aIsInsert);
+
+  } else {
+    nsAccTreeWalker walker(mWeakShell, aChildNode,
+                           aContainer->GetAllowsAnonChildAccessibles(), true);
+
+    while ((child = walker.NextChild()))
+      updateFlags |= UpdateTreeInternal(child, aIsInsert);
+  }
 
   // Content insertion/removal is not cause of accessible tree change.
   if (updateFlags == eNoAccessible)
     return;
 
   // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
   // if it did.
   if (aIsInsert && !(updateFlags & eAlertAccessible)) {
@@ -1844,107 +1861,87 @@ nsDocAccessible::UpdateTree(nsAccessible
   nsRefPtr<AccEvent> reorderEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_REORDER, aContainer->GetNode(),
                  eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
   if (reorderEvent)
     FireDelayedAccessibleEvent(reorderEvent);
 }
 
 PRUint32
-nsDocAccessible::UpdateTreeInternal(nsIContent* aStartNode,
-                                    nsIContent* aEndNode,
-                                    PRBool aIsInsert)
+nsDocAccessible::UpdateTreeInternal(nsAccessible* aChild, bool aIsInsert)
 {
-  PRUint32 updateFlags = eNoAccessible;
-  for (nsIContent* node = aStartNode; node != aEndNode;
-       node = node->GetNextSibling()) {
+  PRUint32 updateFlags = eAccessible;
+
+  nsINode* node = aChild->GetNode();
+  if (aIsInsert) {
+    // Create accessible tree for shown accessible.
+    CacheChildrenInSubtree(aChild);
+
+  } else {
+    // Fire menupopup end event before hide event if a menu goes away.
+
+    // XXX: We don't look into children of hidden subtree to find hiding
+    // menupopup (as we did prior bug 570275) because we don't do that when
+    // menu is showing (and that's impossible until bug 606924 is fixed).
+    // Nevertheless we should do this at least because layout coalesces
+    // the changes before our processing and we may miss some menupopup
+    // events. Now we just want to be consistent in content insertion/removal
+    // handling.
+    if (aChild->ARIARole() == nsIAccessibleRole::ROLE_MENUPOPUP) {
+      nsRefPtr<AccEvent> event =
+        new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
 
-    // Tree update triggers for content insertion even if no content was
-    // inserted actually, check if the given content has a frame to discard
-    // this case early.
-    if (aIsInsert && !node->GetPrimaryFrame())
-      continue;
+      if (event)
+        FireDelayedAccessibleEvent(event);
+    }
+  }
+
+  // Fire show/hide event.
+  nsRefPtr<AccEvent> event;
+  if (aIsInsert)
+    event = new AccShowEvent(aChild, node);
+  else
+    event = new AccHideEvent(aChild, node);
 
-    nsAccessible* accessible = GetAccessible(node);
+  if (event)
+    FireDelayedAccessibleEvent(event);
 
-    if (!accessible) {
-      updateFlags |= UpdateTreeInternal(node->GetFirstChild(), nsnull,
-                                        aIsInsert);
-      continue;
+  if (aIsInsert) {
+    PRUint32 ariaRole = aChild->ARIARole();
+    if (ariaRole == nsIAccessibleRole::ROLE_MENUPOPUP) {
+      // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
+      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
+                                 node, AccEvent::eRemoveDupes);
+
+    } else if (ariaRole == nsIAccessibleRole::ROLE_ALERT) {
+      // Fire EVENT_ALERT if ARIA alert appears.
+      updateFlags = eAlertAccessible;
+      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
+                                 AccEvent::eRemoveDupes);
     }
 
-    updateFlags |= eAccessible;
-
-    if (aIsInsert) {
-      // Create accessible tree for shown accessible.
-      CacheChildrenInSubtree(accessible);
-
-    } else {
-      // Fire menupopup end event before hide event if a menu goes away.
-
-      // XXX: We don't look into children of hidden subtree to find hiding
-      // menupopup (as we did prior bug 570275) because we don't do that when
-      // menu is showing (and that's impossible until bug 606924 is fixed).
-      // Nevertheless we should do this at least because layout coalesces
-      // the changes before our processing and we may miss some menupopup
-      // events. Now we just want to be consistent in content insertion/removal
-      // handling.
-      if (accessible->ARIARole() == nsIAccessibleRole::ROLE_MENUPOPUP) {
-        nsRefPtr<AccEvent> event =
-          new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, accessible);
-
-        if (event)
-          FireDelayedAccessibleEvent(event);
-      }
+    // If focused node has been shown then it means its frame was recreated
+    // while it's focused. Fire focus event on new focused accessible. If
+    // the queue contains focus event for this node then it's suppressed by
+    // this one.
+    if (node == gLastFocusedNode) {
+      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
+                                 node, AccEvent::eCoalesceFromSameDocument);
     }
-
-    // Fire show/hide event.
-    nsRefPtr<AccEvent> event;
-    if (aIsInsert)
-      event = new AccShowEvent(accessible, node);
-    else
-      event = new AccHideEvent(accessible, node);
-
-    if (event)
-      FireDelayedAccessibleEvent(event);
+  } else {
+    // Update the tree for content removal.
+    // The accessible parent may differ from container accessible if
+    // the parent doesn't have own DOM node like list accessible for HTML
+    // selects.
+    nsAccessible* parent = aChild->GetParent();
+    NS_ASSERTION(parent, "No accessible parent?!");
+    if (parent)
+      parent->RemoveChild(aChild);
 
-    if (aIsInsert) {
-      PRUint32 ariaRole = accessible->ARIARole();
-      if (ariaRole == nsIAccessibleRole::ROLE_MENUPOPUP) {
-        // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
-        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
-                                   node, AccEvent::eRemoveDupes);
-
-      } else if (ariaRole == nsIAccessibleRole::ROLE_ALERT) {
-        // Fire EVENT_ALERT if ARIA alert appears.
-        updateFlags = eAlertAccessible;
-        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
-                                   AccEvent::eRemoveDupes);
-      }
-
-      // If focused node has been shown then it means its frame was recreated
-      // while it's focused. Fire focus event on new focused accessible. If
-      // the queue contains focus event for this node then it's suppressed by
-      // this one.
-      if (node == gLastFocusedNode) {
-        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
-                                   node, AccEvent::eCoalesceFromSameDocument);
-      }
-    } else {
-      // Update the tree for content removal.
-      // The accessible parent may differ from container accessible if
-      // the parent doesn't have own DOM node like list accessible for HTML
-      // selects.
-      nsAccessible* parent = accessible->GetParent();
-      NS_ASSERTION(parent, "No accessible parent?!");
-      if (parent)
-        parent->RemoveChild(accessible);
-
-      UncacheChildrenInSubtree(accessible);
-    }
+    UncacheChildrenInSubtree(aChild);
   }
 
   return updateFlags;
 }
 
 void
 nsDocAccessible::CacheChildrenInSubtree(nsAccessible* aRoot)
 {
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -438,31 +438,29 @@ protected:
    */
   void ProcessContentInserted(nsAccessible* aContainer,
                               const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent);
 
   /**
    * Update the accessible tree for content insertion or removal.
    */
   void UpdateTree(nsAccessible* aContainer, nsIContent* aChildNode,
-                  PRBool aIsInsert);
+                  bool aIsInsert);
 
   /**
    * Helper for UpdateTree() method. Go down to DOM subtree and updates
    * accessible tree. Return one of these flags.
    */
   enum EUpdateTreeFlags {
     eNoAccessible = 0,
     eAccessible = 1,
     eAlertAccessible = 2
   };
 
-  PRUint32 UpdateTreeInternal(nsIContent* aStartNode,
-                              nsIContent* aEndNode,
-                              PRBool aIsInsert);
+  PRUint32 UpdateTreeInternal(nsAccessible* aChild, bool aIsInsert);
 
   /**
    * Create accessible tree.
    */
   void CacheChildrenInSubtree(nsAccessible* aRoot);
 
   /**
    * Remove accessibles in subtree from node to accessible map.
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -2207,17 +2207,16 @@ nsHyperTextAccessible::GetChildOffset(PR
       mOffsets.RemoveElementsAt(aChildIndex, count);
 
     return mOffsets[aChildIndex - 1];
   }
 
   PRUint32 lastOffset = mOffsets.IsEmpty() ?
     0 : mOffsets[mOffsets.Length() - 1];
 
-  EnsureChildren();
   while (mOffsets.Length() < aChildIndex) {
     nsAccessible* child = mChildren[mOffsets.Length()];
     lastOffset += nsAccUtils::TextLength(child);
     mOffsets.AppendElement(lastOffset);
   }
 
   return mOffsets[aChildIndex - 1];
 }
--- a/accessible/tests/mochitest/events/Makefile.in
+++ b/accessible/tests/mochitest/events/Makefile.in
@@ -64,16 +64,17 @@ include $(topsrcdir)/config/rules.mk
 		test_dragndrop.html \
 		test_flush.html \
 		test_focus.html \
 		test_focus.xul \
 		test_focus_name.html \
 		test_focusdoc.html \
 		test_menu.xul \
 		test_mutation.html \
+		test_mutation.xhtml \
 		test_scroll.xul \
 		test_selection.html \
 		test_statechange.html \
 		test_text_alg.html \
 		test_text.html \
 		test_textattrchange.html \
 		test_tree.xul \
 		test_valuechange.html \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_mutation.xhtml
@@ -0,0 +1,99 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+  <title>Accessible mutation events testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <bindings xmlns="http://www.mozilla.org/xbl" >
+    <binding id="button">
+      <content>
+        <button xmlns="http://www.w3.org/1999/xhtml">a button</button>
+      </content>
+    </binding>
+  </bindings>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    /**
+     * Insert a not accessible bound element containing an accessible element
+     * in anonymous content.
+     */
+    function insertBinding(aContainerID)
+    {
+      this.containerNode = getNode(aContainerID);
+
+      function getButtonFromBinding(aNode)
+      {
+        try { return document.getAnonymousNodes(aNode.firstChild)[0]; }
+        catch (e) { return null; }
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getButtonFromBinding, this.containerNode),
+        new invokerChecker(EVENT_REORDER, this.containerNode)
+      ];
+
+      this.invoke = function insertBinding_invoke()
+      {
+        var span = document.createElement("span");
+        span.setAttribute("style", "-moz-binding:url(#button)");
+        this.containerNode.appendChild(span);
+      }
+
+      this.getID = function insertBinding_getID()
+      {
+        return "insert button binding";
+      }
+    }
+
+    /**
+     * Do tests.
+     */
+    var gQueue = null;
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new insertBinding("testContainer"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=646369"
+     title="UpdateTree should rely on accessible tree walker rather than DOM tree traversal">
+    Mozilla Bug 646369</a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <div id="testContainer"></div>
+</body>
+</html>
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -9,16 +9,17 @@ builtin(include, build/autoconf/nspr.m4)
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/freetype2.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
+builtin(include, build/autoconf/lto.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
 MOZ_READ_MOZCONFIG(.)
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -313,37 +313,37 @@ endif
 
 LOWER_APP_NAME = $(shell echo $(APP_NAME) | tr '[A-Z]' '[a-z]')
 
 AB_CD = $(MOZ_UI_LOCALE)
 
 AB := $(firstword $(subst -, ,$(AB_CD)))
 
 clean clobber repackage::
-	rm -rf $(DIST)/$(APP_NAME).app
+	$(RM) -r $(DIST)/$(APP_NAME).app
 
 ifdef LIBXUL_SDK
 APPFILES = Resources
 else
 APPFILES = MacOS
 endif
 
 libs repackage:: $(PROGRAM) application.ini
-	mkdir -p $(DIST)/$(APP_NAME).app/Contents/MacOS
+	$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
-	mkdir -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
+	$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%LOWER_APP_NAME%/$(LOWER_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
 	sed -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox-bin
 else
-	rm -f $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
+	$(RM) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
 endif
 	-cp -L $(DIST)/bin/mangle $(DIST)/bin/shlibsign $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	cp -RL $(DIST)/branding/firefox.icns $(DIST)/$(APP_NAME).app/Contents/Resources/firefox.icns
 	cp -RL $(DIST)/branding/document.icns $(DIST)/$(APP_NAME).app/Contents/Resources/document.icns
 	printf APPLMOZB > $(DIST)/$(APP_NAME).app/Contents/PkgInfo
 #       remove CVS dirs from packaged app
 	find $(DIST)/$(APP_NAME).app -type d -name "CVS" -prune -exec rm -rf {} \;
--- a/browser/base/content/aboutDialog.css
+++ b/browser/base/content/aboutDialog.css
@@ -1,14 +1,14 @@
 #aboutDialog {
   padding-top: 0;
   -moz-padding-end: 0;
   padding-bottom: 10px;
   -moz-padding-start: 0;
-  width: 600px;
+  width: 620px;
 }
 
 #clientBox {
   background-color: #F7F7F7;
   color: #222222;
 }
 
 #leftBox {
@@ -53,20 +53,16 @@
 }
 
 .text-blurb {
   margin-bottom: 10px;
   -moz-margin-start: 0;
   -moz-padding-start: 0;
 }
 
-#updateBox {
-  margin-bottom: 10px;
-}
-
 #updateButton,
 #updateDeck > hbox > label {
   -moz-margin-start: 0;
   -moz-padding-start: 0;
 }
 
 #updateDeck > hbox > label:not([class="text-link"]) {
   color: #909090;
@@ -94,8 +90,41 @@
 }
 
 #trademark {
   font-size: xx-small;
   text-align: center;
   color: #999999;
   margin-top: 10px;
 }
+
+#currentChannel {
+  margin: 0;
+  padding: 0;
+  font-weight: bold;
+}
+
+#channelSelector {
+  margin-top: 10px;
+}
+
+#channelMenulist {
+  margin: 0;
+}
+
+.channel-description {
+  margin: 10px 0;
+  text-align: center;
+}
+
+#detailsBox,
+#channelSelector,
+.channel-description {
+  -moz-transition: opacity 250ms;
+}
+
+#contentDeck:not([selectedIndex="0"]) > #detailsBox,
+#contentDeck:not([selectedIndex="1"]) > #channelSelector,
+#channelDescriptionDeck:not([selectedIndex="0"]) > #releaseDescription,
+#channelDescriptionDeck:not([selectedIndex="1"]) > #betaDescription,
+#channelDescriptionDeck:not([selectedIndex="2"]) > #auroraDescription {
+  opacity: 0;
+}
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -83,16 +83,18 @@ function init(aEvent)
     document.getElementById("extra-trademark").hidden = true;
   }
 #endif
 
 #ifdef MOZ_UPDATER
   gAppUpdater = new appUpdater();
 #endif
 
+  gChannelSelector.init();
+
 #ifdef XP_MACOSX
   // it may not be sized at this point, and we need its width to calculate its position
   window.sizeToContent();
   window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5);
 #endif
 }
 
 #ifdef MOZ_UPDATER
@@ -567,8 +569,73 @@ appUpdater.prototype =
     if (!aIID.equals(Components.interfaces.nsIProgressEventSink) &&
         !aIID.equals(Components.interfaces.nsIRequestObserver) &&
         !aIID.equals(Components.interfaces.nsISupports))
       throw Components.results.NS_ERROR_NO_INTERFACE;
     return this;
   }
 };
 #endif
+
+var gChannelSelector = {
+  validChannels: { release: 1, beta: 1, aurora: 1 },
+  
+  init: function() {
+    try {
+      this.channelValue = Services.prefs.getCharPref("app.update.desiredChannel");
+    } catch (e) {
+      let defaults = Services.prefs.getDefaultBranch("");
+      this.channelValue = defaults.getCharPref("app.update.channel");
+    }
+
+    // Only show channel selector UI on valid update channels.
+    if (this.channelValue in this.validChannels) {
+      document.getElementById("currentChannelText").hidden = false;
+      this.setChannelLabel(this.channelValue);
+      this.setChannelMenuitem(this.channelValue);
+    }
+  },
+
+  selectChannel: function(aSelectedItem) {
+    document.getElementById("channelDescriptionDeck").selectedPanel =
+      document.getElementById(aSelectedItem.value + "Description");
+  },
+
+  cancel: function() {
+    this.setChannelMenuitem(this.channelValue);
+    this.hide();
+  },
+
+  apply: function() {
+    this.channelValue = document.getElementById("channelMenulist").selectedItem.value;
+    this.setChannelLabel(this.channelValue);
+
+    // Change app update channel.
+    Services.prefs.setCharPref("app.update.desiredChannel", this.channelValue);
+
+    // App updater will look at app.update.desiredChannel for new channel value
+    // and will clear it when the update is complete.
+    gAppUpdater.isChecking = true;
+    gAppUpdater.checker.checkForUpdates(gAppUpdater.updateCheckListener, true);
+
+    this.hide();
+  },
+
+  show: function() {
+    document.getElementById("contentDeck").selectedPanel =
+      document.getElementById("channelSelector");
+  },
+
+  hide: function() {
+    document.getElementById("contentDeck").selectedPanel =
+      document.getElementById("detailsBox");  
+  },
+
+  setChannelLabel: function(aValue) {
+    let channelLabel = document.getElementById("currentChannel");
+    channelLabel.value = document.getElementById(aValue + "Menuitem").label;
+  },
+
+  setChannelMenuitem: function(aValue) {
+    document.getElementById("channelMenulist").selectedItem =
+      document.getElementById(aValue + "Menuitem");
+  }
+}
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -72,54 +72,91 @@
 
   <vbox>
     <hbox id="clientBox">
       <vbox id="leftBox" flex="1"/>
       <vbox id="rightBox" flex="1">
 #expand <label id="version" value="__MOZ_APP_VERSION__"/>
         <label id="distribution" class="text-blurb"/>
         <label id="distributionId" class="text-blurb"/>
-        <vbox id="updateBox">
+
+        <!-- Make sure the selectedIndex attribute is always set so that the CSS
+             selectors for transitions work -->        
+        <deck id="contentDeck" selectedIndex="0">
+          <vbox id="detailsBox">
+            <vbox id="updateBox">
 #ifdef MOZ_UPDATER
-          <deck id="updateDeck" orient="vertical">
-            <hbox id="updateButtonBox" align="center">
-              <button id="updateButton" align="start"
-                      oncommand="gAppUpdater.buttonOnCommand();"/>
-              <spacer flex="1"/>
-            </hbox>
-            <hbox id="checkingForUpdates" align="center">
-              <image class="update-throbber"/><label>&update.checkingForUpdates;</label>
-            </hbox>
-            <hbox id="checkingAddonCompat" align="center">
-              <image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
-            </hbox>
-            <hbox id="downloading" align="center">
-              <image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
+              <deck id="updateDeck" orient="vertical">
+                <hbox id="updateButtonBox" align="center">
+                  <button id="updateButton" align="start"
+                          oncommand="gAppUpdater.buttonOnCommand();"/>
+                  <spacer flex="1"/>
+                </hbox>
+                <hbox id="checkingForUpdates" align="center">
+                  <image class="update-throbber"/><label>&update.checkingForUpdates;</label>
+                </hbox>
+                <hbox id="checkingAddonCompat" align="center">
+                  <image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
+                </hbox>
+                <hbox id="downloading" align="center">
+                  <image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
+                </hbox>
+                <hbox id="downloadFailed" align="center">
+                  <label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
+                </hbox>
+                <hbox id="adminDisabled" align="center">
+                  <label>&update.adminDisabled;</label>
+                </hbox>
+                <hbox id="noUpdatesFound" align="center">
+                  <label>&update.noUpdatesFound;</label>
+                </hbox>
+                <hbox id="manualUpdate" align="center">
+                  <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
+                </hbox>
+              </deck>
+#endif
+            </vbox>
+
+            <description class="text-blurb" id="currentChannelText" hidden="true">
+              &channel.description.start;<label id="currentChannel"/>&channel.description.end;<label id="channelChangeLink" class="text-link" onclick="gChannelSelector.show();">&channel.change;</label>
+            </description>
+            <description class="text-blurb">
+              &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
+            </description>
+            <description class="text-blurb">
+              &contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
+            </description>
+          </vbox>
+
+          <vbox id="channelSelector">
+            <hbox pack="center" align="center">
+              <label>&channel.selector.start;</label>
+              <menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);">
+                <menupopup>
+                  <menuitem id="releaseMenuitem" label="Release" value="release"/>
+                  <menuitem id="betaMenuitem" label="Beta" value="beta"/>
+                  <menuseparator/>
+                  <menuitem id="auroraMenuitem" label="Aurora" value="aurora"/>
+                </menupopup>
+              </menulist>
+              <label>&channel.selector.end;</label>
             </hbox>
-            <hbox id="downloadFailed" align="center">
-              <label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
-            </hbox>
-            <hbox id="adminDisabled" align="center">
-              <label>&update.adminDisabled;</label>
-            </hbox>
-            <hbox id="noUpdatesFound" align="center">
-              <label>&update.noUpdatesFound;</label>
+
+            <deck id="channelDescriptionDeck" selectedIndex="0">
+              <description id="releaseDescription" class="channel-description">&channel.release.description;</description>
+              <description id="betaDescription" class="channel-description">&channel.beta.description;</description>
+              <description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
+            </deck>
+
+            <hbox id="channelSelectorButtons" pack="center">
+              <button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
+              <button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
             </hbox>
-            <hbox id="manualUpdate" align="center">
-              <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
-            </hbox>
-          </deck>
-#endif
-        </vbox>
-        <description class="text-blurb">
-          &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
-        </description>
-        <description class="text-blurb">
-          &contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
-        </description>
+          </vbox>
+        </deck>
       </vbox>
     </hbox>
     <vbox id="bottomBox">
       <hbox pack="center">
         <label class="text-link bottom-link" href="about:license">&bottomLinks.license;</label>
         <label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
         <label class="text-link bottom-link" href="http://www.mozilla.com/legal/privacy/">&bottomLinks.privacy;</label>
       </hbox>
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -315,18 +315,20 @@ let TabView = {
   afterUndoCloseTab: function () {
     if (this._window)
       this._window.UI.restoredClosedTab = false;
   },
 
   // ----------
   // On move to group pop showing.
   moveToGroupPopupShowing: function TabView_moveToGroupPopupShowing(event) {
-    // there are hidden tabs so initialize the iframe and update the context menu
-    if ((gBrowser.tabs.length - gBrowser.visibleTabs.length) > 0)
+    // Update the context menu only if Panorama was already initialized or if
+    // there are hidden tabs.
+    let numHiddenTabs = gBrowser.tabs.length - gBrowser.visibleTabs.length;
+    if (this._window || numHiddenTabs > 0)
       this.updateContextMenu(TabContextMenu.contextTab, event.target);
   },
 
   // ----------
   // Function: _addToolbarButton
   // Adds the TabView button to the TabsToolbar.
   _addToolbarButton: function TabView__addToolbarButton() {
     let buttonId = "tabview-button";
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -686,16 +686,17 @@ GroupItem.prototype = Utils.extend(new I
       }, {
         duration: 170,
         complete: function() {
           iQ(this).hide();
         }
       });
 
       this.droppable(false);
+      this.removeTrenches();
       this._createUndoButton();
     } else
       this.close();
     
     this._makeClosestTabActive();
   },
   
   // ----------
@@ -735,16 +736,17 @@ GroupItem.prototype = Utils.extend(new I
   _unhide: function GroupItem__unhide() {
     let self = this;
 
     this._cancelFadeAwayUndoButtonTimer();
     this.hidden = false;
     this.$undoContainer.remove();
     this.$undoContainer = null;
     this.droppable(true);
+    this.setTrenches(this.bounds);
 
     GroupItems.setActiveGroupItem(this);
     if (this._activeTab)
       UI.setActiveTab(this._activeTab);
 
     iQ(this.container).show().animate({
       "-moz-transform": "scale(1)",
       "opacity": 1
@@ -1198,16 +1200,41 @@ GroupItem.prototype = Utils.extend(new I
     
     // adjust the tray
     this.adjustAppTabTray(true);
 
     xulTab.removeEventListener("error", this._onAppTabError, false);
   },
 
   // ----------
+  // Arranges the given xul:tab as an app tab in the group's apptab tray
+  arrangeAppTab: function GroupItem_arrangeAppTab(xulTab) {
+    let self = this;
+
+    let elements = iQ(".appTabIcon", this.$appTabTray);
+    let length = elements.length;
+
+    elements.each(function(icon) {
+      let $icon = iQ(icon);
+      if ($icon.data("xulTab") != xulTab)
+        return;
+
+      let targetIndex = xulTab._tPos;
+
+      $icon.remove();
+      if (targetIndex < (length - 1))
+        self.$appTabTray[0].insertBefore(
+          icon,
+        iQ(".appTabIcon:nth-child(" + (targetIndex + 1) + ")", self.$appTabTray)[0]);
+      else
+        $icon.appendTo(self.$appTabTray);
+    });
+  },
+
+  // ----------
   // Function: hideExpandControl
   // Hide the control which expands a stacked groupItem into a quick-look view.
   hideExpandControl: function GroupItem_hideExpandControl() {
     this.$expander.hide();
   },
 
   // ----------
   // Function: showExpandControl
@@ -1232,18 +1259,18 @@ GroupItem.prototype = Utils.extend(new I
       return false;
 
     var bb = this.getContentBounds();
     var options = {
       return: 'widthAndColumns',
       count: count || this._children.length,
       hideTitle: false
     };
-    let arrObj = Items.arrange(null, bb, options);
- 
+    let arrObj = Items.arrange(this._children, bb, options);
+
     let shouldStack = arrObj.childWidth < TabItems.minTabWidth * 1.35;
     this._columns = shouldStack ? null : arrObj.columns;
 
     return shouldStack;
   },
 
   // ----------
   // Function: _freezeItemSize
@@ -1416,30 +1443,30 @@ GroupItem.prototype = Utils.extend(new I
       child.isStacked = true;
       if (numInPile-- > 0) {
         children.push(child);
       } else {
         child.setHidden(true);
       }
     });
 
+    self._isStacked = true;
+
     let angleAccum = 0;
     children.forEach(function GroupItem__stackArrange_apply(child, index) {
       child.setZ(zIndex);
       zIndex--;
 
       // Force a recalculation of height because we've changed how the title
       // is shown.
       child.setBounds(box, !animate || child.getHidden(), {force:true});
       child.setRotation((UI.rtl ? -1 : 1) * angleAccum);
       child.setHidden(false);
       angleAccum += angleDelta;
     });
-
-    self._isStacked = true;
   },
   
   // ----------
   // Function: _gridArrange
   // Arranges the children into a grid.
   //
   // Parameters:
   //   childrenToArrange - array of <TabItem> children
@@ -2030,16 +2057,25 @@ let GroupItems = {
   removeAppTab: function GroupItems_removeAppTab(xulTab) {
     this.groupItems.forEach(function(groupItem) {
       groupItem.removeAppTab(xulTab);
     });
     this.updateGroupCloseButtons();
   },
 
   // ----------
+  // Function: arrangeAppTab
+  // Arranges the given xul:tab as an app tab from app tab tray in all groups
+  arrangeAppTab: function GroupItems_arrangeAppTab(xulTab) {
+    this.groupItems.forEach(function(groupItem) {
+      groupItem.arrangeAppTab(xulTab);
+    });
+  },
+
+  // ----------
   // Function: getNextID
   // Returns the next unused groupItem ID.
   getNextID: function GroupItems_getNextID() {
     var result = this.nextID;
     this.nextID++;
     this._save();
     return result;
   },
--- a/browser/base/content/tabview/items.js
+++ b/browser/base/content/tabview/items.js
@@ -909,17 +909,16 @@ let Items = {
   //
   // Possible "options" properties:
   //   animate - whether to animate; default: true.
   //   z - the z index to set all the items; default: don't change z.
   //   return - if set to 'widthAndColumns', it'll return an object with the
   //     width of children and the columns.
   //   count - overrides the item count for layout purposes;
   //     default: the actual item count
-  //   padding - pixels between each item
   //   columns - (int) a preset number of columns to use
   //   dropPos - a <Point> which should have a one-tab space left open, used
   //             when a tab is dragged over.
   //
   // Returns:
   //   By default, an object with three properties: `rects`, the list of <Rect>s,
   //   `dropIndex`, the index which a dragged tab should have if dropped
   //   (null if no `dropPos` was specified), and the number of columns (`columns`).
--- a/browser/base/content/tabview/tabitems.js
+++ b/browser/base/content/tabview/tabitems.js
@@ -225,26 +225,16 @@ TabItem.prototype = Utils.extend(new Ite
   forceCanvasSize: function TabItem_forceCanvasSize(w, h) {
     this.canvasSizeForced = true;
     this.$canvas[0].width = w;
     this.$canvas[0].height = h;
     this.tabCanvas.paint();
   },
 
   // ----------
-  // Function: _getFontSizeFromWidth
-  // Private method that returns the fontsize to use given the tab's width
-  _getFontSizeFromWidth: function TabItem__getFontSizeFromWidth(width) {
-    let widthRange = new Range(0,TabItems.tabWidth);
-    let proportion = widthRange.proportion(width-TabItems.tabItemPadding.x, true);
-    // proportion is in [0,1]
-    return TabItems.fontSizeRange.scale(proportion);
-  },
-
-  // ----------
   // Function: unforceCanvasSize
   // Stops holding the thumbnail resolution; allows it to shift to the
   // size of thumbnail on screen. Note that this call does not nest, unlike
   // <TabItems.resumePainting>; if you call forceCanvasSize multiple
   // times, you just need a single unforce to clear them all.
   unforceCanvasSize: function TabItem_unforceCanvasSize() {
     this.canvasSizeForced = false;
   },
@@ -368,16 +358,29 @@ TabItem.prototype = Utils.extend(new Ite
           groupItem.add(self, {immediately: true});
 
           // if it matches the selected tab or no active tab and the browser
           // tab is hidden, the active group item would be set.
           if (self.tab == gBrowser.selectedTab ||
               (!GroupItems.getActiveGroupItem() && !self.tab.hidden))
             GroupItems.setActiveGroupItem(self.parent);
         }
+      } else {
+        // When duplicating a non-blank orphaned tab, create a group including both of them.
+        // This prevents overlaid tabs in Tab View (only one tab appears to be there).
+        // In addition, as only one active orphaned tab is shown when Tab View is hidden
+        // and there are two tabs shown after the duplication, it also prevents
+        // the inactive tab to suddenly disappear when toggling Tab View twice.
+        //
+        // Fixes:
+        //   Bug 645653 - Middle-click on reload button to duplicate orphan tabs does not create a group
+        //   Bug 643119 - Ctrl+Drag to duplicate does not work for orphaned tabs
+        //   ... (and any other way of duplicating a non-blank orphaned tab).
+        if (GroupItems.getActiveGroupItem() == null)
+          GroupItems.newTab(self, {immediately: true});
       }
     } else {
       // create tab by double click is handled in UI_init().
       if (!TabItems.creatingNewOrphanTab)
         GroupItems.newTab(self, {immediately: true});
     }
 
     self._reconnected = true;
@@ -435,26 +438,24 @@ TabItem.prototype = Utils.extend(new Ite
     if (rect.left != this.bounds.left || options.force)
       css.left = rect.left;
 
     if (rect.top != this.bounds.top || options.force)
       css.top = rect.top;
 
     if (rect.width != this.bounds.width || options.force) {
       css.width = rect.width - TabItems.tabItemPadding.x;
-      css.fontSize = this._getFontSizeFromWidth(rect.width);
+      css.fontSize = TabItems.getFontSizeFromWidth(rect.width);
       css.fontSize += 'px';
     }
 
     if (rect.height != this.bounds.height || options.force) {
+      css.height = rect.height - TabItems.tabItemPadding.y;
       if (!this.isStacked)
-          css.height = rect.height - TabItems.tabItemPadding.y -
-                       TabItems.fontSizeRange.max;
-      else
-        css.height = rect.height - TabItems.tabItemPadding.y;
+        css.height -= TabItems.fontSizeRange.max;
     }
 
     if (Utils.isEmptyObject(css))
       return;
 
     this.bounds.copy(rect);
 
     // If this is a brand new tab don't animate it in from
@@ -1275,67 +1276,69 @@ let TabItems = {
     var sane = true;
     if (!Utils.isRect(data.bounds)) {
       Utils.log('TabItems.storageSanity: bad bounds', data.bounds);
       sane = false;
     }
 
     return sane;
   },
-  
+
+  // ----------
+  // Function: getFontSizeFromWidth
+  // Private method that returns the fontsize to use given the tab's width
+  getFontSizeFromWidth: function TabItem_getFontSizeFromWidth(width) {
+    let widthRange = new Range(0, TabItems.tabWidth);
+    let proportion = widthRange.proportion(width - TabItems.tabItemPadding.x, true);
+    // proportion is in [0,1]
+    return TabItems.fontSizeRange.scale(proportion);
+  },
+
   // ----------
   // Function: _getWidthForHeight
   // Private method that returns the tabitem width given a height.
-  // Set options.hideTitle=true to measure without a title.
-  // Default is to measure with a title.
-  _getWidthForHeight: function TabItems__getWidthForHeight(height, options) {    
-    let titleSize = (options !== undefined && options.hideTitle === true) ? 
-      0 : TabItems.fontSizeRange.max;
-    return Math.max(0, Math.max(TabItems.minTabHeight, height - titleSize)) * 
-      TabItems.invTabAspect;
+  _getWidthForHeight: function TabItems__getWidthForHeight(height) {
+    return height * TabItems.invTabAspect;
   },
 
   // ----------
   // Function: _getHeightForWidth
   // Private method that returns the tabitem height given a width.
-  // Set options.hideTitle=false to measure without a title.
-  // Default is to measure with a title.
-  _getHeightForWidth: function TabItems__getHeightForWidth(width, options) {
-    let titleSize = (options !== undefined && options.hideTitle === true) ? 
-      0 : TabItems.fontSizeRange.max;
-    return Math.max(0, Math.max(TabItems.minTabWidth,width)) *
-      TabItems.tabAspect + titleSize;
+  _getHeightForWidth: function TabItems__getHeightForWidth(width) {
+    return width * TabItems.tabAspect;
   },
-  
+
   // ----------
   // Function: calcValidSize
   // Pass in a desired size, and receive a size based on proper title
   // size and aspect ratio.
   calcValidSize: function TabItems_calcValidSize(size, options) {
     Utils.assert(Utils.isPoint(size), 'input is a Point');
-    let retSize = new Point(0,0);
-    if (size.x==-1) {
-      retSize.x = this._getWidthForHeight(size.y, options);
-      retSize.y = size.y;
-    } else if (size.y==-1) {
-      retSize.x = size.x;
-      retSize.y = this._getHeightForWidth(size.x, options);
-    } else {
-      let fitHeight = this._getHeightForWidth(size.x, options);
-      let fitWidth = this._getWidthForHeight(size.y, options);
+
+    let width = Math.max(TabItems.minTabWidth, size.x);
+    let showTitle = !options || !options.hideTitle;
+    let titleSize = showTitle ? TabItems.fontSizeRange.max : 0;
+    let height = Math.max(TabItems.minTabHeight, size.y - titleSize);
+    let retSize = new Point(width, height);
 
-      // Go with the smallest final dimension.
-      if (fitWidth < size.x) {
-        retSize.x = fitWidth;
-        retSize.y = size.y;
-      } else {
-        retSize.x = size.x;
-        retSize.y = fitHeight;
-      }
+    if (size.x > -1)
+      retSize.y = this._getHeightForWidth(width);
+    if (size.y > -1)
+      retSize.x = this._getWidthForHeight(height);
+
+    if (size.x > -1 && size.y > -1) {
+      if (retSize.x < size.x)
+        retSize.y = this._getHeightForWidth(retSize.x);
+      else
+        retSize.x = this._getWidthForHeight(retSize.y);
     }
+
+    if (showTitle)
+      retSize.y += titleSize;
+
     return retSize;
   }
 };
 
 // ##########
 // Class: TabPriorityQueue
 // Container that returns tab items in a priority order
 // Current implementation assigns tab to either a high priority
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -750,19 +750,26 @@ let UI = {
       }
     };
 
     // TabMove
     this._eventListeners.move = function(tab) {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
-      let activeGroupItem = GroupItems.getActiveGroupItem();
-      if (activeGroupItem)
-        self.setReorderTabItemsOnShow(activeGroupItem);
+      if (GroupItems.groupItems.length > 0) {
+        if (tab.pinned) {
+          if (gBrowser._numPinnedTabs > 1)
+            GroupItems.arrangeAppTab(tab);
+        } else {
+          let activeGroupItem = GroupItems.getActiveGroupItem();
+          if (activeGroupItem)
+            self.setReorderTabItemsOnShow(activeGroupItem);
+        }
+      }
     };
 
     // TabSelect
     this._eventListeners.select = function(tab) {
       if (tab.ownerDocument.defaultView != gWindow)
         return;
 
       self.onTabSelect(tab);
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -68,16 +68,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug595930.js \
                  browser_tabview_bug595943.js \
                  browser_tabview_bug595965.js \
                  browser_tabview_bug596781.js \
                  browser_tabview_bug597248.js \
                  browser_tabview_bug597360.js \
                  browser_tabview_bug597399.js \
                  browser_tabview_bug597980.js \
+                 browser_tabview_bug598375.js \
                  browser_tabview_bug598600.js \
                  browser_tabview_bug599626.js \
                  browser_tabview_bug600645.js \
                  browser_tabview_bug600812.js \
                  browser_tabview_bug602432.js \
                  browser_tabview_bug604098.js \
                  browser_tabview_bug604699.js \
                  browser_tabview_bug606657.js \
@@ -100,16 +101,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug623768.js \
                  browser_tabview_bug624265.js \
                  browser_tabview_bug624931.js \
                  browser_tabview_bug624727.js \
                  browser_tabview_bug624847.js \
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_bug625424.js \
+                 browser_tabview_bug625666.js \
                  browser_tabview_bug626368.js \
                  browser_tabview_bug626525.js \
                  browser_tabview_bug626791.js \
                  browser_tabview_bug627288.js \
                  browser_tabview_bug627736.js \
                  browser_tabview_bug628165.js \
                  browser_tabview_bug628270.js \
                  browser_tabview_bug629189.js \
@@ -117,17 +119,22 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug630102.js \
                  browser_tabview_bug630157.js \
                  browser_tabview_bug631662.js \
                  browser_tabview_bug631752.js \
                  browser_tabview_bug633788.js \
                  browser_tabview_bug634077.js \
                  browser_tabview_bug634085.js \
                  browser_tabview_bug634158.js \
+                 browser_tabview_bug634672.js \
                  browser_tabview_bug635696.js \
+                 browser_tabview_bug640765.js \
+                 browser_tabview_bug641802.js \
+                 browser_tabview_bug644097.js \
+                 browser_tabview_bug645653.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_expander.js \
                  browser_tabview_firstrun_pref.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
                  browser_tabview_orphaned_tabs.js \
@@ -138,12 +145,13 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_startup_transitions.js \
                  browser_tabview_undo_group.js \
                  dummy_page.html \
                  head.js \
                  search1.html \
                  search2.html \
                  test_bug599626.html \
                  test_bug600645.html \
+                 test_bug644097.html \
                  $(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug598375.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (win) {
+    registerCleanupFunction(function () win.close());
+
+    let cw = win.TabView.getContentWindow();
+    let groupItem = cw.GroupItems.groupItems[0];
+    groupItem.setBounds(new cw.Rect(cw.innerWidth - 200, 0, 200, 200));
+
+    whenTabViewIsHidden(finish, win);
+
+    let button = cw.document.getElementById("exit-button");
+    EventUtils.synthesizeMouseAtCenter(button, {}, cw);
+  });
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug610208.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug610208.js
@@ -120,28 +120,30 @@ function test() {
     groupItem.setUserSize();
 
     cleanUpTest('testResizeGroup', originalBounds, next);
   }
 
   // make sure we don't freeze item size when removing an item from a stack
   let testRemoveWhileStacked = function () {
     let oldBounds = groupItem.getBounds();
-    groupItem.setSize(150, 200, true);
+    groupItem.setSize(250, 250, true);
     groupItem.setUserSize();
 
     let originalBounds = groupItem.getChild(0).getBounds();
-    ok(!groupItem._isStacked, 'testRemoveWhileStacked: group is not stacked');
+    ok(!groupItem.isStacked(), 'testRemoveWhileStacked: group is not stacked');
 
-    // add a new tab to let the group stack
-    win.gBrowser.loadOneTab('about:blank', {inBackground: true});
-    ok(groupItem._isStacked, 'testRemoveWhileStacked: group is now stacked');
+    // add new tabs to let the group stack
+    while (!groupItem.isStacked())
+      win.gBrowser.loadOneTab('about:blank', {inBackground: true});
 
     afterAllTabsLoaded(function () {
       groupItem.getChild(0).close();
+      ok(!groupItem.isStacked(), 'testRemoveWhileStacked: group is not stacked');
+
       let bounds = groupItem.getChild(0).getBounds();
       ok(originalBounds.equals(bounds), 'testRemoveWhileStacked: tabs did not change their size');
 
       // reset group size
       groupItem.setBounds(oldBounds);
       groupItem.setUserSize();
 
       next();
@@ -151,34 +153,34 @@ function test() {
   // 1) make sure item size is frozen when removing an item in expanded mode
   // 2) make sure item size stays frozen while moving the mouse in the expanded
   // layer
   let testExpandedMode = function () {
     let oldBounds = groupItem.getBounds();
     groupItem.setSize(100, 100, true);
     groupItem.setUserSize();
 
-    ok(groupItem._isStacked, 'testExpandedMode: group is stacked');
+    ok(groupItem.isStacked(), 'testExpandedMode: group is stacked');
 
     groupItem.addSubscriber(groupItem, 'expanded', function () {
       groupItem.removeSubscriber(groupItem, 'expanded');
       onExpanded();
     });
 
     groupItem.addSubscriber(groupItem, 'collapsed', function () {
       groupItem.removeSubscriber(groupItem, 'collapsed');
       onCollapsed();
     });
 
     let onExpanded = function () {
       let originalBounds = groupItem.getChild(0).getBounds();
       let tabItem = groupItem.getChild(1);
       let bounds = tabItem.getBounds();
 
-      for (let i=0; i<3; i++)
+      while (groupItem.getChildren().length > 2)
         groupItem.getChild(1).close();
 
       ok(originalBounds.equals(groupItem.getChild(0).getBounds()), 'testExpandedMode: tabs did not change their size');
 
       // move the mouse over the expanded layer
       let trayBounds = groupItem.expanded.bounds;
       let target = groupItem.expanded.$tray[0];
       EventUtils.synthesizeMouse(target, trayBounds.right - 5, trayBounds.bottom -5, {type: 'mousemove'}, cw);
--- a/browser/base/content/test/tabview/browser_tabview_bug618816.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug618816.js
@@ -1,47 +1,41 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   let cw;
-
-  let createGroupItem = function () {
-    let bounds = new cw.Rect(20, 20, 400, 200);
-    let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
-
-    let groupItemId = groupItem.id;
-    registerCleanupFunction(function() {
-      let groupItem = cw.GroupItems.groupItem(groupItemId);
-      if (groupItem)
-        groupItem.close();
-    });
-
-    return groupItem;
-  }
+  let win;
 
   let testFocusTitle = function () {
     let title = 'title';
-    let groupItem = createGroupItem();
+    let groupItem = cw.GroupItems.groupItems[0];
     groupItem.setTitle(title);
 
     let target = groupItem.$titleShield[0];
     EventUtils.synthesizeMouseAtCenter(target, {}, cw);
 
     let input = groupItem.$title[0];
     is(input.selectionStart, 0, 'the whole text is selected');
     is(input.selectionEnd, title.length, 'the whole text is selected');
 
     EventUtils.synthesizeMouseAtCenter(input, {}, cw);
     is(input.selectionStart, title.length, 'caret is at the rightmost position and no text is selected');
     is(input.selectionEnd, title.length, 'caret is at the rightmost position and no text is selected');
 
-    groupItem.close();
-    hideTabView(finish);
+    win.close();
+    finish();
   }
 
   waitForExplicitFinish();
 
-  showTabView(function () {
-    cw = TabView.getContentWindow();
-    testFocusTitle();
+  newWindowWithTabView(function (tvwin) {
+    win = tvwin;
+
+    registerCleanupFunction(function () {
+      if (!win.closed)
+        win.close();
+    });
+
+    cw = win.TabView.getContentWindow();
+    SimpleTest.waitForFocus(testFocusTitle, cw);
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug624953.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624953.js
@@ -1,39 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
-  let finishTest = function (groupItem) {
-    groupItem.addSubscriber(groupItem, 'groupHidden', function () {
-      groupItem.removeSubscriber(groupItem, 'groupHidden');
-      groupItem.closeHidden();
-      hideTabView(finish);
-    });
-
-    groupItem.closeAll();
-  }
-
   showTabView(function () {
     let cw = TabView.getContentWindow();
 
-    let bounds = new cw.Rect(20, 20, 150, 200);
-    let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
-    cw.GroupItems.setActiveGroupItem(groupItem);
-
-    for (let i=0; i<4; i++)
-      gBrowser.loadOneTab('about:blank', {inBackground: true});
-
-    ok(!groupItem._isStacked, 'groupItem is not stacked');
+    let groupItem = createGroupItemWithBlankTabs(window, 200, 240, 20, 4)
+    ok(!groupItem.isStacked(), 'groupItem is not stacked');
     cw.GroupItems.pauseArrange();
 
-    groupItem.setSize(150, 150);
+    groupItem.setSize(100, 100, true);
     groupItem.setUserSize();
-    ok(!groupItem._isStacked, 'groupItem is still not stacked');
+    ok(!groupItem.isStacked(), 'groupItem is still not stacked');
 
     cw.GroupItems.resumeArrange();
-    ok(groupItem._isStacked, 'groupItem is now stacked');
+    ok(groupItem.isStacked(), 'groupItem is now stacked');
 
-    finishTest(groupItem);
+    closeGroupItem(groupItem, finish);
   });
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug625666.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let cw;
+
+  let getTabItemAspect = function (tabItem) {
+    let bounds = cw.iQ('.thumb', tabItem.container).bounds();
+    let padding = cw.TabItems.tabItemPadding;
+    return (bounds.height + padding.y) / (bounds.width + padding.x);
+  }
+
+  let getAspectRange = function () {
+    let aspect = cw.TabItems.tabAspect;
+    let variance = aspect / 100 * 1.5;
+    return new cw.Range(aspect - variance, aspect + variance);
+  }
+
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (win) {
+    registerCleanupFunction(function () win.close());
+    cw = win.TabView.getContentWindow();
+
+    // prepare orphan tab
+    let tabItem = win.gBrowser.tabs[0]._tabViewTabItem;
+    tabItem.parent.remove(tabItem, {immediately: true});
+    tabItem.setBounds(new cw.Rect(20, 20, 200, 165), true);
+
+    let bounds = tabItem.getBounds();
+
+    // prepare group item
+    let box = new cw.Rect(20, 300, 400, 200);
+    let groupItem = new cw.GroupItem([], {bounds: box, immediately: true});
+
+    groupItem.setBounds(new cw.Rect(20, 100, 400, 200));
+    groupItem.pushAway(true);
+
+    let newBounds = tabItem.getBounds();
+    ok(newBounds.width < bounds.width, "The new width of item is smaller than the old one.");
+    ok(newBounds.height < bounds.height, "The new height of item is smaller than the old one.");
+
+    let aspectRange = getAspectRange();
+    let aspect = getTabItemAspect(tabItem);
+    ok(aspectRange.contains(aspect), "orphaned tabItem's aspect is correct");
+
+    finish();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug634672.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let cw;
+  let win;
+
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (tvwin) {
+    win = tvwin;
+    cw = win.TabView.getContentWindow();
+
+    registerCleanupFunction(function () {
+      if (win && !win.closed)
+        win.close();
+    });
+
+    // fill the group item with some tabs
+    for (let i = 0; i < 5; i++)
+      win.gBrowser.loadOneTab("about:blank");
+
+    let groupItem = cw.GroupItems.groupItems[0];
+    groupItem.setSize(400, 400, true);
+    let range = new cw.Range(1, 400);
+
+    // determine the groupItem's largest possible stacked size
+    while (range.extent > 1) {
+      let pivot = Math.floor(range.extent / 2);
+      groupItem.setSize(range.min + pivot, range.min + pivot, true);
+
+      if (groupItem.isStacked())
+        range.min += pivot;
+      else
+        range.max -= pivot;
+    }
+
+    // stack the group
+    groupItem.setSize(range.min, range.min, true);
+    ok(groupItem.isStacked(), "groupItem is stacked");
+
+    // one step back to un-stack the groupItem
+    groupItem.setSize(range.max, range.max, true);
+    ok(!groupItem.isStacked(), "groupItem is no longer stacked");
+
+    // check that close buttons are visible
+    let tabItem = groupItem.getChild(0);
+    isnot(tabItem.$close.css("display"), "none", "close button is visible");
+
+    finish();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug640765.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let contentWindow;
+let groupItem;
+
+function test() {
+  waitForExplicitFinish();
+
+  let newTabOne = gBrowser.addTab();
+  let newTabTwo = gBrowser.addTab();
+  let newTabThree = gBrowser.addTab();
+
+  gBrowser.pinTab(newTabOne);
+  gBrowser.pinTab(newTabTwo);
+  gBrowser.pinTab(newTabThree);
+
+  registerCleanupFunction(function() {
+    TabView.hide();
+    while (gBrowser.tabs.length > 1)
+      gBrowser.removeTab(gBrowser.tabs[0]);
+  });
+
+  showTabView(function() {
+    contentWindow = document.getElementById("tab-view").contentWindow;
+    is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
+
+    groupItem = contentWindow.GroupItems.groupItems[0];
+
+    is(xulTabForAppTabIcon(0), newTabOne,
+       "New tab one matches the first app tab icon in tabview");
+    is(xulTabForAppTabIcon(1), newTabTwo,
+       "New tab two matches the second app tab icon in tabview");
+    is(xulTabForAppTabIcon(2), newTabThree,
+       "New tab three matches the third app tab icon in tabview");
+
+    // move the last tab to the first position
+    gBrowser.moveTabTo(newTabThree, 0);
+    is(xulTabForAppTabIcon(0), newTabThree,
+       "New tab three matches the first app tab icon in tabview");
+    is(xulTabForAppTabIcon(1), newTabOne,
+       "New tab one matches the second app tab icon in tabview");
+    is(xulTabForAppTabIcon(2), newTabTwo,
+       "New tab two matches the third app tab icon in tabview");
+
+    // move the first tab to the second position
+    gBrowser.moveTabTo(newTabThree, 1);
+    is(xulTabForAppTabIcon(0), newTabOne,
+       "New tab one matches the first app tab icon in tabview");
+    is(xulTabForAppTabIcon(1), newTabThree,
+       "New tab three matches the second app tab icon in tabview");
+    is(xulTabForAppTabIcon(2), newTabTwo,
+       "New tab two matches the third app tab icon in tabview");
+
+    hideTabView(function() {
+      gBrowser.removeTab(newTabOne);
+      gBrowser.removeTab(newTabTwo);
+      gBrowser.removeTab(newTabThree);
+      finish();
+    });
+  });
+}
+
+function xulTabForAppTabIcon(index) {
+    return contentWindow.iQ(
+             contentWindow.iQ(".appTabIcon", 
+                              groupItem.$appTabTray)[index]).data("xulTab");
+}
+
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug641802.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let openMoveToGroupPopup = function () {
+    let tab = gBrowser.selectedTab;
+    document.popupNode = tab;
+    contextMenu.openPopup(tab, "end_after", 0, 0, true, false);
+    tvMenuPopup.openPopup(tvMenu, "end_after", 0, 0, true, false);
+  }
+
+  let hideMoveToGroupPopup = function () {
+    tvMenuPopup.hidePopup();
+    contextMenu.hidePopup();
+  }
+
+  let assertValidPrerequisites = function (visible) {
+    let cw = TabView.getContentWindow();
+    is(cw.GroupItems.groupItems.length, 1, "there is one groupItem");
+    is(gBrowser.tabs.length, 1, "there is one tab");
+    is(TabView.isVisible(), visible, "tabview is visible");
+  }
+
+  let tvMenu = document.getElementById("context_tabViewMenu");
+  let contextMenu = document.getElementById("tabContextMenu");
+  let tvMenuPopup = document.getElementById("context_tabViewMenuPopup");
+
+  waitForExplicitFinish();
+
+  registerCleanupFunction(function () {
+    hideMoveToGroupPopup();
+    hideTabView(function () {});
+
+    let groupItems = TabView.getContentWindow().GroupItems.groupItems;
+    if (groupItems.length > 1)
+      closeGroupItem(groupItems[0], function () {});
+  });
+
+  showTabView(function () {
+    assertValidPrerequisites(true);
+
+    hideTabView(function () {
+      let groupItem = createGroupItemWithBlankTabs(window, 200, 200, 10, 1);
+      groupItem.setTitle("group2");
+
+      gBrowser.selectedTab = gBrowser.tabs[0];
+
+      executeSoon(function () {
+        openMoveToGroupPopup();
+        is(tvMenuPopup.firstChild.getAttribute("label"), "group2", "menuItem is present");
+        hideMoveToGroupPopup();
+
+        closeGroupItem(groupItem, function () {
+          openMoveToGroupPopup();
+          is(tvMenuPopup.firstChild.tagName, "menuseparator", "menuItem is not present");
+          hideMoveToGroupPopup();
+
+          assertValidPrerequisites(false);
+          finish();
+        });
+      });
+    });
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug644097.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function (win) {
+    registerCleanupFunction(function () win.close());
+
+    let cw = win.TabView.getContentWindow();
+    let groupItem = cw.GroupItems.groupItems[0];
+
+    // create some tabs with favIcons
+    for (let i = 0; i < 3; i++)
+      win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/tabview/test_bug644097.html", {inBackground: true});
+
+    win.gBrowser.removeTab(win.gBrowser.tabs[0]);
+
+    // shrink the group until it stacks
+    let size = 400;
+    while (!groupItem.isStacked() && --size)
+      groupItem.setSize(size, size, true);
+
+    // determine the tabItem at the top of the stack
+    let tabItem;
+    groupItem.getChildren().forEach(function (item) {
+      if (groupItem.isTopOfStack(item))
+        tabItem = item;
+    });
+
+    ok(tabItem, "we found the tabItem at the top of the stack");
+
+    let fav = tabItem.$fav;
+    is(fav.css("display"), "block", "the favIcon is visible");
+    is(fav.css("left"), "0px", "the favIcon is at the left-most position");
+    is(fav.css("top"), "0px", "the favIcon is at the top-most position");
+
+    finish();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug645653.js
@@ -0,0 +1,83 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* Orphans a non-blank tab, duplicates it and checks whether a new group is created with two tabs.
+ * The original one should be the first tab of the new group.
+ *
+ * This prevents overlaid tabs in Tab View (only one tab appears to be there).
+ * In addition, as only one active orphaned tab is shown when Tab View is hidden
+ * and there are two tabs shown after the duplication, it also prevents
+ * the inactive tab to suddenly disappear when toggling Tab View twice.
+ *
+ * Covers:
+ *   Bug 645653 - Middle-click on reload button to duplicate orphan tabs does not create a group
+ *   Bug 643119 - Ctrl+Drag to duplicate does not work for orphaned tabs
+ *   ... (and any other way of duplicating a non-blank orphaned tab).
+ *
+ * See tabitems.js::_reconnect() for the fix.
+ *
+ * Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
+ */
+
+function loadedAboutMozilla(tab) {
+  return tab.linkedBrowser.contentDocument.getElementById('moztext');
+}
+
+function test() {
+  waitForExplicitFinish();
+  showTabView(function() {
+    ok(TabView.isVisible(), "Tab View is visible");
+
+    let contentWindow = TabView.getContentWindow();
+    is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup.");
+
+    let originalGroupItem = contentWindow.GroupItems.groupItems[0];
+    is(originalGroupItem.getChildren().length, 1, "There is one tab item in that group.");
+
+    let originalTabItem = originalGroupItem.getChild(0);
+    ok(originalTabItem, "The tabitem has been found.");
+
+    // close the group => orphan the tab
+    originalGroupItem.close();
+    contentWindow.GroupItems.setActiveGroupItem(originalGroupItem);
+    is(contentWindow.GroupItems.groupItems.length, 0, "There are not any groups now.");
+
+    ok(TabView.isVisible(), "Tab View is still shown.");
+
+    hideTabView(function() {
+      ok(!TabView.isVisible(), "Tab View is not shown anymore.");
+
+      // load a non-blank page
+      loadURI('about:mozilla');
+
+      afterAllTabsLoaded(function() {
+        ok(loadedAboutMozilla(originalTabItem.tab), "The original tab loaded about:mozilla.");
+
+        // duplicate it
+        duplicateTabIn(originalTabItem.tab, "tabshift");
+
+        afterAllTabsLoaded(function() {
+          // check
+          is(gBrowser.selectedTab, originalTabItem.tab, "The selected tab is the original one.");
+          is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item again.");
+          let groupItem = contentWindow.GroupItems.groupItems[0];
+          is(groupItem.getChildren().length, 2, "There are two tab items in that group.");
+          is(originalTabItem, groupItem.getChild(0), "The first tab item in the group is the original one.");
+          let otherTab = groupItem.getChild(1);
+          ok(loadedAboutMozilla(otherTab.tab), "The other tab loaded about:mozilla.");
+
+          // clean up
+          gBrowser.removeTab(otherTab.tab);
+          is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item after closing the second tab.");
+          is(groupItem.getChildren().length, 1, "There is only one tab item after closing the second tab.");
+          is(originalTabItem, groupItem.getChild(0), "The first tab item in the group is still the original one.");
+          loadURI("about:blank");
+          afterAllTabsLoaded(function() {
+            finish();
+          });
+        });
+      });
+    });
+  });
+}
+
--- a/browser/base/content/test/tabview/browser_tabview_expander.js
+++ b/browser/base/content/test/tabview/browser_tabview_expander.js
@@ -12,17 +12,17 @@ function onTabViewWindowLoaded(win) {
 
   let contentWindow = win.document.getElementById("tab-view").contentWindow;
   let [originalTab] = win.gBrowser.visibleTabs;
   let currentGroup = contentWindow.GroupItems.getActiveGroupItem();
   
   // let's create a group small enough to get stacked
   let group = new contentWindow.GroupItem([], {
     immediately: true,
-    bounds: {left: 20, top: 300, width: 300, height: 300}
+    bounds: {left: 20, top: 300, width: 400, height: 400}
   });
 
   let expander = contentWindow.iQ(group.container).find(".stackExpander");
   ok("length" in expander && expander.length == 1, "The group has an expander.");
 
   // procreate!
   contentWindow.GroupItems.setActiveGroupItem(group);
   for (var i=0; i<7; i++) {
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -101,17 +101,18 @@ function afterAllTabsLoaded(callback, wi
     this.removeEventListener("load", onLoad, true);
     stillToLoad--;
     if (!stillToLoad)
       callback();
   }
 
   for (let a = 0; a < win.gBrowser.tabs.length; a++) {
     let browser = win.gBrowser.tabs[a].linkedBrowser;
-    if (browser.contentDocument.readyState != "complete") {
+    if (browser.contentDocument.readyState != "complete" ||
+        browser.webProgress.isLoadingDocument) {
       stillToLoad++;
       browser.addEventListener("load", onLoad, true);
     }
   }
 
   if (!stillToLoad)
     callback();
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/test_bug644097.html
@@ -0,0 +1,8 @@
+<html>
+  <head>
+    <title>Bug 644097</title>
+    <link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/>
+  </head>
+  <body>
+  </body>
+</html>
--- a/browser/installer/windows/Makefile.in
+++ b/browser/installer/windows/Makefile.in
@@ -89,27 +89,29 @@ endif
 
 installer::
 	$(MAKE) -C .. installer-stage
 	$(MAKE) $(CONFIG_DIR)/setup.exe
 
 # For building the uninstaller during the application build so it can be
 # included for mar file generation.
 uninstaller::
-	$(RM) -rf $(CONFIG_DIR) && mkdir $(CONFIG_DIR)
+	$(RM) -r $(CONFIG_DIR)
+	$(MKDIR) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(DIST)/branding/,$(BRANDING_FILES)) $(CONFIG_DIR)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in > $(CONFIG_DIR)/defines.nsi
 	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
 	  --preprocess-locale $(topsrcdir) \
 	  $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
 
 $(CONFIG_DIR)/setup.exe::
-	$(RM) -rf $(CONFIG_DIR) && mkdir $(CONFIG_DIR)
+	$(RM) -r $(CONFIG_DIR)
+	$(MKDIR) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(DIST)/branding/,$(BRANDING_FILES)) $(CONFIG_DIR)
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in > $(CONFIG_DIR)/defines.nsi
 	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
 	  --preprocess-locale $(topsrcdir) \
 	  $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
 
--- a/browser/locales/en-US/chrome/browser/aboutDialog.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutDialog.dtd
@@ -49,8 +49,32 @@
 
 <!-- LOCALIZATION NOTE (update.downloading.start,update.downloading.end): update.downloading.start and 
      update.downloading.end all go into one line, with the amount downloaded inserted in between. As this
      is all in one line, try to make the localized text short (see bug 596813 for screenshots). The — is
      the "em dash" (long dash).
      example: Downloading update — 111 KB of 13 MB -->
 <!ENTITY update.downloading.start   "Downloading update — ">
 <!ENTITY update.downloading.end     "">
+
+<!-- LOCALIZATION NOTE (channel.description.start,channel.description.end): channel.description.start and
+     channel.description.end create one sentence, with the current channel label inserted in between.
+     example: You are currently on the _Stable_ update channel. -->
+<!ENTITY channel.description.start  "You are currently on the ">
+<!ENTITY channel.description.end    " update channel. ">
+
+<!ENTITY channel.change             "Change">
+
+<!ENTITY channel.release.description       "Enjoy the tried and tested final release being used by hundreds of millions around the world. Stay in control of your online experience with super speed, easy customization and the latest Web technologies.">
+<!ENTITY channel.beta.description          "Experience cutting edge features with more stability. Provide feedback to help refine and polish what will be in the final release.">
+<!ENTITY channel.aurora.description        "Experience the newest innovations in an unstable environment that's not for the faint of heart. Provide feedback on features and performance to help determine what makes the final release.">
+
+<!-- LOCALIZATION NOTE (channel.selector.start,channel.selector.end): channel.selector.start and
+     channel.selector.end create one sentence, with a channel selection menulist instered in between.
+     This is all in one line, so try to make the localized text short.
+     example: Switch to the [Stable] update channel. -->
+<!ENTITY channel.selector.start          "Switch to the">
+<!ENTITY channel.selector.end            "update channel.">
+
+<!-- LOCALIZATION NOTE (channel.selector.applyButton): This button applies the user's choice to switch
+     to a new update channel and starts the application update process. -->
+<!ENTITY channel.selector.applyButton    "Apply and Update">
+<!ENTITY channel.selector.cancelButton   "Cancel">
new file mode 100644
--- /dev/null
+++ b/build/autoconf/lto.m4
@@ -0,0 +1,15 @@
+dnl check if the build is using lto. This is really primitive and only detects llvm based
+dnl compilers right now.
+AC_DEFUN(MOZ_DOING_LTO,
+[
+  cat > conftest.c <<EOF
+                  int foo = 1;
+EOF
+  $1=no
+  if ${CC-cc} ${CFLAGS} -S conftest.c -o conftest.s >/dev/null 2>&1; then
+    if grep '^target triple =' conftest.s; then
+      $1=yes
+    fi
+  fi
+  rm -f conftest.[cs]
+])
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -99,18 +99,17 @@ endif
 
 HEADERS = \
 	$(DEPTH)/mozilla-config.h \
 	$(srcdir)/nsStaticComponents.h \
 	$(NULL)
 
 export:: $(TARGETS) $(HEADERS)
 	$(INSTALL) $(IFLAGS1) $(HEADERS) $(DIST)/include
-	-rm -f $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES)
-	-rm -f $(DIST)/bin/chrome/chromelist.txt
+	-$(RM) $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES)
 ifdef HOST_PROGRAM
 	$(INSTALL) $(HOST_PROGRAM) $(DIST)/bin
 endif
 
 # Generate a new buildid every time we "export" in config... that's only
 # supposed to be once per-build!
 export::
 ifdef MOZ_BUILD_DATE
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -182,18 +182,16 @@ MOZ_DIRECTX_SDK_PATH = @MOZ_DIRECTX_SDK_
 MOZ_DIRECTX_SDK_CPU_SUFFIX = @MOZ_DIRECTX_SDK_CPU_SUFFIX@
 MOZ_D3DX9_VERSION = @MOZ_D3DX9_VERSION@
 MOZ_D3DX9_CAB = @MOZ_D3DX9_CAB@
 MOZ_D3DCOMPILER_CAB = @MOZ_D3DCOMPILER_CAB@
 MOZ_D3DX9_DLL = @MOZ_D3DX9_DLL@
 MOZ_D3DCOMPILER_DLL = @MOZ_D3DCOMPILER_DLL@
 
 
-MOZ_JAVAXPCOM = @MOZ_JAVAXPCOM@
-JAVA_INCLUDE_PATH="@JAVA_INCLUDE_PATH@"
 JAVA="@JAVA@"
 JAVAC="@JAVAC@"
 JAR="@JAR@"
 
 TAR=@TAR@
 
 MAKENSISU=@MAKENSISU@
 
--- a/config/config.mk
+++ b/config/config.mk
@@ -154,16 +154,19 @@ JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(c
 ifneq (,$(SIMPLE_PROGRAMS)$(PROGRAM))
 JEMALLOC_LIBS += $(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
 endif
 endif
 endif
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
+MKDIR ?= mkdir
+SLEEP ?= sleep
+TOUCH ?= touch
 
 # determine debug-related options
 _DEBUG_CFLAGS :=
 _DEBUG_LDFLAGS :=
 
 ifdef MOZ_DEBUG
   _DEBUG_CFLAGS += $(MOZ_DEBUG_ENABLE_DEFS) $(MOZ_DEBUG_FLAGS)
   _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -929,42 +929,42 @@ endif # MOZ_PROFILE_GENERATE || MOZ_PROF
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
 checkout:
 	$(MAKE) -C $(topsrcdir) -f client.mk checkout
 
 clean clobber realclean clobber_all:: $(SUBMAKEFILES)
-	-rm -f $(ALL_TRASH)
-	-rm -rf $(ALL_TRASH_DIRS)
+	-$(RM) $(ALL_TRASH)
+	-$(RM) -r $(ALL_TRASH_DIRS)
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 
 distclean:: $(SUBMAKEFILES)
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(STATIC_DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
-	-rm -rf $(ALL_TRASH_DIRS) 
-	-rm -f $(ALL_TRASH)  \
+	-$(RM) -r $(ALL_TRASH_DIRS) 
+	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
 	$(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \
 	$(wildcard *.$(IMPORT_LIB_SUFFIX))
 ifeq ($(OS_ARCH),OS2)
-	-rm -f $(PROGRAM:.exe=.map)
+	-$(RM) $(PROGRAM:.exe=.map)
 endif
 
 alltags:
-	rm -f TAGS
+	$(RM) TAGS
 	find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM)
 
 #
 # PROGRAM = Foo
 # creates OBJS, links with LIBS to create Foo
 #
 $(PROGRAM): $(PROGOBJS) $(LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS)
-	@rm -f $@.manifest
+	@$(RM) $@.manifest
 ifeq (WINCE,$(OS_ARCH))
 	$(EXPAND_LD) -NOLOGO -OUT:$@ $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 else
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 	$(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		if test -f "$(srcdir)/$@.manifest"; then \
@@ -1105,46 +1105,46 @@ ifndef NO_DIST_INSTALL
 	$(INSTALL) $(IFLAGS2) $^.quantify $(FINAL_TARGET)
 endif
 
 ifdef DTRACE_PROBE_OBJ
 EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
 endif
 
 $(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
-	rm -f $(LIBRARY)
+	$(RM) $(LIBRARY)
 	$(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS)
 	$(RANLIB) $@
 
 $(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
 	$(EXPAND_LIBS_GEN) $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) > $@
 
 ifeq (,$(filter-out WINNT WINCE, $(OS_ARCH)))
 $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
 endif
 
 ifeq ($(OS_ARCH),OS2)
 $(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
-	rm -f $@
+	$(RM) $@
 	echo LIBRARY $(SHARED_LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
 	echo PROTMODE >> $@
 	echo CODE    LOADONCALL MOVEABLE DISCARDABLE >> $@
 	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
 	echo EXPORTS >> $@
 
 	$(ADD_TO_DEF_FILE)
 
 $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
-	rm -f $@
+	$(RM) $@
 	$(IMPLIB) $@ $^
 	$(RANLIB) $@
 endif # OS/2
 
 $(HOST_LIBRARY): $(HOST_OBJS) Makefile
-	rm -f $@
+	$(RM) $@
 	$(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS)
 	$(HOST_RANLIB) $@
 
 ifdef HAVE_DTRACE
 ifndef XP_MACOSX
 ifdef DTRACE_PROBE_OBJ
 ifndef DTRACE_LIB_DEPENDENT
 $(DTRACE_PROBE_OBJ): $(OBJS)
@@ -1156,24 +1156,24 @@ endif
 
 # On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files,
 # so instead of deleting .o files after repacking them into a dylib, we make
 # symlinks back to the originals. The symlinks are a no-op for stabs debugging,
 # so no need to conditionalize on OS version or debugging format.
 
 $(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS_DEPS) $(LIBRARY) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) $(GLOBAL_DEPS)
 ifndef INCREMENTAL_LINKER
-	rm -f $@
+	$(RM) $@
 endif
 ifdef DTRACE_LIB_DEPENDENT
 ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
-	@rm -f $(DTRACE_PROBE_OBJ)
+	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
 endif # DTRACE_LIB_DEPENDENT
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
@@ -1181,17 +1181,17 @@ ifdef EMBED_MANIFEST_AT
 		rm -f $@.manifest; \
 	fi
 endif   # EMBED_MANIFEST_AT
 endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 endif	# WINNT && !GCC
-	@rm -f foodummyfilefoo $(DELETE_AFTER_LINK)
+	@$(RM) foodummyfilefoo $(DELETE_AFTER_LINK)
 	chmod +x $@
 ifdef ENABLE_STRIP
 	$(STRIP) $@
 endif
 ifdef MOZ_POST_DSO_LIB_COMMAND
 	$(MOZ_POST_DSO_LIB_COMMAND) $@
 endif
 
@@ -1297,17 +1297,17 @@ endif
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
 %.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 ifdef STRICT_CPLUSPLUS_SUFFIX
 	echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
-	rm -f t_$*.cc
+	$(RM) t_$*.cc
 else
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 endif #STRICT_CPLUSPLUS_SUFFIX
 
 $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
@@ -1347,22 +1347,24 @@ ifdef GNU_CC
 	$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
 else
 	$(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS)
 endif
 endif
 
 # need 3 separate lines for OS/2
 %:: %.pl
-	rm -f $@
+	$(RM) $@
 	cp $< $@
 	chmod +x $@
 
 %:: %.sh
-	rm -f $@; cp $< $@; chmod +x $@
+	$(RM) $@
+	cp $< $@
+	chmod +x $@
 
 # Cancel these implicit rules
 #
 %: %,v
 
 %: RCS/%,v
 
 %: s.%
@@ -1446,23 +1448,16 @@ endif
 
 ###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ################################################################################
 # Copy each element of EXPORTS to $(DIST)/include
 
-ifdef MOZ_JAVAXPCOM
-ifneq ($(XPIDLSRCS),)
-$(JAVA_DIST_DIR)::
-	$(NSINSTALL) -D $@
-endif
-endif
-
 ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
 endif
 
 ifndef NO_DIST_INSTALL
@@ -1549,18 +1544,18 @@ export:: FORCE
 endif
 
 $(IDL_DIR)::
 	$(NSINSTALL) -D $@
 
 # generate .h files from into $(XPIDL_GEN_DIR), then export to $(DIST)/include;
 # warn against overriding existing .h file. 
 $(XPIDL_GEN_DIR)/.done:
-	@if test ! -d $(XPIDL_GEN_DIR); then echo Creating $(XPIDL_GEN_DIR)/.done; rm -rf $(XPIDL_GEN_DIR); mkdir $(XPIDL_GEN_DIR); fi
-	@touch $@
+	$(MKDIR) -p $(XPIDL_GEN_DIR)
+	@$(TOUCH) $@
 
 # don't depend on $(XPIDL_GEN_DIR), because the modification date changes
 # with any addition to the directory, regenerating all .h files -> everything.
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
 	$(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS)
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
@@ -1625,56 +1620,16 @@ ifndef NO_DIST_INSTALL
 export-idl:: $(XPIDLSRCS) $(IDL_DIR)
 	$(INSTALL) $(IFLAGS1) $^
 endif
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
-ifdef MOZ_JAVAXPCOM
-ifneq ($(XPIDLSRCS),)
-
-JAVA_XPIDLSRCS = $(XPIDLSRCS)
-
-# A single IDL file can contain multiple interfaces, which result in multiple
-# Java interface files.  So use hidden dependency files.
-JAVADEPFILES = $(addprefix $(JAVA_GEN_DIR)/.,$(JAVA_XPIDLSRCS:.idl=.java.pp))
-
-$(JAVA_GEN_DIR):
-	$(NSINSTALL) -D $@
-GARBAGE_DIRS += $(JAVA_GEN_DIR)
-
-# generate .java files into _javagen/[package name dirs]
-_JAVA_GEN_DIR = $(JAVA_GEN_DIR)/$(JAVA_IFACES_PKG_NAME)
-$(_JAVA_GEN_DIR):
-	$(NSINSTALL) -D $@
-
-$(JAVA_GEN_DIR)/.%.java.pp: %.idl $(XPIDL_COMPILE) $(_JAVA_GEN_DIR)
-	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m java -w $(XPIDL_FLAGS) -I$(srcdir) -I$(IDL_DIR) -o $(_JAVA_GEN_DIR)/$* $(_VPATH_SRCS)
-	@touch $@
-
-# "Install" generated Java interfaces.  We segregate them based on the XPI_NAME.
-# If XPI_NAME is not set, install into the "default" directory.
-ifneq ($(XPI_NAME),)
-JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/$(XPI_NAME)
-else
-JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/default
-endif
-
-$(JAVA_INSTALL_DIR):
-	$(NSINSTALL) -D $@
-
-export:: $(JAVA_DIST_DIR) $(JAVADEPFILES) $(JAVA_INSTALL_DIR)
-	(cd $(JAVA_GEN_DIR) && tar $(TAR_CREATE_FLAGS) - .) | (cd $(JAVA_INSTALL_DIR) && tar -xf -)
-
-endif # XPIDLSRCS
-endif # MOZ_JAVAXPCOM
-
 ################################################################################
 # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
 ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
 ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
 ifndef NO_JS_MANIFEST
 $(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0)
 endif
 endif
@@ -1844,17 +1799,17 @@ endif
 endif
 
 ifdef INSTALL_EXTENSION_ID
 ifndef XPI_NAME
 $(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
 endif
 
 libs::
-	$(RM) -rf "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
+	$(RM) -r "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
 	$(NSINSTALL) -D "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
 	cd $(FINAL_TARGET) && tar $(TAR_CREATE_FLAGS) - . | (cd "../../bin/extensions/$(INSTALL_EXTENSION_ID)" && tar -xf -)
 
 endif
 
 ifneq (,$(filter flat symlink,$(MOZ_CHROME_FILE_FORMAT)))
 _JAR_REGCHROME_DISABLE_JAR=1
 else
@@ -1916,17 +1871,17 @@ depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(
 else
 depend:: $(SUBMAKEFILES)
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
 dependclean:: $(SUBMAKEFILES)
-	rm -f $(MDDEPFILES)
+	$(RM) $(MDDEPFILES)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
 endif # MOZ_AUTO_DEPS
 
 endif # COMPILER_DEPEND
 
@@ -1939,17 +1894,17 @@ endif # COMPILER_DEPEND
 #
 #   We use $(CURDIR) in the rule's target to ensure that we don't find
 #   a dependency directory in the source tree via VPATH (perhaps from
 #   a previous build in the source tree) and thus neglect to create a
 #   dependency directory in the object directory, where we really need
 #   it.
 
 $(CURDIR)/$(MDDEPDIR):
-	@if test ! -d $@; then echo Creating $@; rm -rf $@; mkdir $@; else true; fi
+	$(MKDIR) -p $@
 
 ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 MDDEPEND_FILES		:= $(strip $(wildcard $(MDDEPDIR)/*.pp))
 
 ifneq (,$(MDDEPEND_FILES))
 # The script mddepend.pl checks the dependencies and writes to stdout
 # one rule to force out-of-date objects. For example,
--- a/configure.in
+++ b/configure.in
@@ -2002,16 +2002,18 @@ FIREFOX_VERSION=`cat $_topsrcdir/browser
 
 if test -z "$FIREFOX_VERSION"; then
     AC_MSG_ERROR([FIREFOX_VERSION is unexpectedly blank.])
 fi
 
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
 
+MOZ_DOING_LTO(lto_is_enabled)
+
 dnl ========================================================
 dnl System overrides of the defaults for target
 dnl ========================================================
 
 case "$target" in
 *-aix*)
     AC_DEFINE(AIX)
     if test ! "$GNU_CC"; then
@@ -2103,19 +2105,21 @@ case "$target" in
     STRIP="$STRIP -x -S"
     _PLATFORM_DEFAULT_TOOLKIT='cairo-cocoa'
     TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
     # The ExceptionHandling framework is needed for Objective-C exception
     # logging code in nsObjCExceptions.h. Currently we only use that in debug
     # builds.
     MOZ_DEBUG_LDFLAGS="$MOZ_DEBUG_LDFLAGS -framework ExceptionHandling"
 
+    if test "x$lto_is_enabled" = "xyes"; then
+        echo "Skipping -dead_strip because lto is enabled."
     dnl DTrace and -dead_strip don't interact well. See bug 403132.
     dnl ===================================================================
-    if test "x$enable_dtrace" = "xyes"; then
+    elif test "x$enable_dtrace" = "xyes"; then
         echo "Skipping -dead_strip because DTrace is enabled. See bug 403132."
     else
         dnl check for the presence of the -dead_strip linker flag
         AC_MSG_CHECKING([for -dead_strip option to ld])
         _SAVE_LDFLAGS=$LDFLAGS
         LDFLAGS="$LDFLAGS -Wl,-dead_strip"
         AC_TRY_LINK(,[return 0;],_HAVE_DEAD_STRIP=1,_HAVE_DEAD_STRIP=)
         if test -n "$_HAVE_DEAD_STRIP" ; then
@@ -4918,21 +4922,16 @@ if test -n "$SYSTEM_HUNSPELL"; then
     PKG_CHECK_MODULES(MOZ_HUNSPELL, hunspell)
 fi
 
 AC_SUBST(SYSTEM_HUNSPELL)
 
 dnl ========================================================
 dnl Java SDK support
 dnl ========================================================
-JAVA_INCLUDE_PATH=
-MOZ_ARG_WITH_STRING(java-include-path,
-[  --with-java-include-path=dir
-                          Location of Java SDK headers],
-    JAVA_INCLUDE_PATH=$withval)
 
 JAVA_BIN_PATH=
 MOZ_ARG_WITH_STRING(java-bin-path,
 [  --with-java-bin-path=dir
                           Location of Java binaries (java, javac, jar)],
     JAVA_BIN_PATH=$withval)
 
 dnl ========================================================
@@ -4945,17 +4944,16 @@ MOZ_ARG_HEADER(Application)
 
 BUILD_STATIC_LIBS=
 ENABLE_TESTS=1
 MOZ_ACTIVEX_SCRIPTING_SUPPORT=
 MOZ_BRANDING_DIRECTORY=
 MOZ_OFFICIAL_BRANDING=
 MOZ_FEEDS=1
 MOZ_INSTALLER=1
-MOZ_JAVAXPCOM=
 MOZ_JSDEBUGGER=1
 MOZ_MATHML=1
 MOZ_MORK=
 MOZ_MORKREADER=1
 MOZ_AUTH_EXTENSION=1
 MOZ_NO_ACTIVEX_SUPPORT=1
 MOZ_NO_FAST_LOAD=
 MOZ_OGG=1
@@ -6211,39 +6209,16 @@ dnl ====================================
 dnl = Universalchardet
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(universalchardet,
 [  --disable-universalchardet
                           Disable universal encoding detection],
   MOZ_UNIVERSALCHARDET=,
   MOZ_UNIVERSALCHARDET=1 )
 
-dnl ========================================================
-dnl JavaXPCOM
-dnl ========================================================
-case "${target}" in
-*-wince*)
-    MOZ_JAVAXPCOM=
-    ;;
-esac
-
-MOZ_ARG_ENABLE_BOOL(javaxpcom,
-[  --enable-javaxpcom
-                          Enable Java-XPCOM bridge],
-    MOZ_JAVAXPCOM=1,
-    MOZ_JAVAXPCOM=)
-
-case "$host_os" in
-  *mingw*)
-    if test -n "$JAVA_HOME"; then
-      JAVA_HOME=`cd "$JAVA_HOME" && pwd`
-    fi
-    ;;
-esac
-
 if test -n "${JAVA_BIN_PATH}"; then
   dnl Look for javac and jar in the specified path.
   JAVA_PATH="$JAVA_BIN_PATH"
 else
   dnl No path specified, so look for javac and jar in $JAVA_HOME & $PATH.
   JAVA_PATH="$JAVA_HOME/bin:$PATH"
 fi
 
@@ -6252,39 +6227,16 @@ MOZ_PATH_PROG(JAVAC, javac, :, [$JAVA_PA
 MOZ_PATH_PROG(JAR, jar, :, [$JAVA_PATH])
 
 if test -n "${JAVA_BIN_PATH}" -o "$OS_TARGET" = Android; then
   if test -z "$JAVA" -o "$JAVA" = ":" -o -z "$JAVAC" -o "$JAVAC" = ":" -o -z "$JAR" -o "$JAR" = ":"; then
     AC_MSG_ERROR([The programs java, javac and jar were not found.  Set \$JAVA_HOME to your java sdk directory or use --with-java-bin-path={java-bin-dir}])
   fi
 fi
 
-if test -n "${MOZ_JAVAXPCOM}"; then
-  if test -n "${JAVA_INCLUDE_PATH}"; then
-    dnl Make sure jni.h exists in the given include path.
-    if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
-      AC_MSG_ERROR([jni.h was not found in given include path $JAVA_INCLUDE_PATH.])
-    fi
-  else
-    case "$target_os" in
-      darwin*)
-        dnl Default to java system location
-        JAVA_INCLUDE_PATH=/System/Library/Frameworks/JavaVM.framework/Headers
-        ;;
-      *)
-        dnl Try $JAVA_HOME
-        JAVA_INCLUDE_PATH="$JAVA_HOME/include"
-        ;;
-    esac
-    if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
-      AC_MSG_ERROR([The header jni.h was not found.  Set \$JAVA_HOME to your java sdk directory, use --with-java-bin-path={java-bin-dir}, or reconfigure with --disable-javaxpcom.])
-    fi
-  fi
-fi
-
 dnl ========================================================
 dnl = ANGLE OpenGL->D3D translator for WebGL
 dnl = * only applies to win32
 dnl = * enabled by default (shipping build); requires explicit --disable to disable
 dnl ========================================================
 MOZ_ANGLE=
 MOZ_DIRECTX_SDK_PATH=
 MOZ_DIRECTX_SDK_CPU_SUFFIX=
@@ -6541,64 +6493,22 @@ if test -n "$LIBXUL_SDK_DIR" -a `echo "$
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
 if test -z "$MOZ_JSDEBUGGER" -a `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
     AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
 fi
 
-dnl This might be temporary: build tridentprofile only on Windows
-if test `echo "$MOZ_EXTENSIONS" | grep -c tridentprofile` -ne 0 && test "$OS_ARCH" != "WINNT"; then
-    AC_MSG_WARN([tridentprofile extension works only on Windows at this time. Removing tridentprofile from MOZ_EXTENSIONS.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|tridentprofile||'`
-fi
-
-dnl cookie must be built before tridentprofile. put it at list's end.
-if test `echo "$MOZ_EXTENSIONS" | grep -c tridentprofile` -ne 0; then
-  MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|tridentprofile||'`
-  MOZ_EXTENSIONS="$MOZ_EXTENSIONS tridentprofile"
-fi
-
 dnl xforms requires xtf
 if test -z "$MOZ_XTF" -a `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0; then
     AC_MSG_WARN([Cannot build XForms without XTF support.  Removing XForms from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|xforms||g'`
 fi
 
-if test `echo "$MOZ_EXTENSIONS" | grep -c auth` -ne 0; then
-    AC_MSG_WARN([auth is no longer an extension, use --disable-negotiateauth to disable.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|auth||g'`
-fi
-
-if test `echo "$MOZ_EXTENSIONS" | grep -c 'cookie\|permissions'` -ne 0; then
-    AC_MSG_WARN([cookie and permissions are no longer extensions, use --disable-permissions to disable.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|cookie||g; s|permissions||g'`
-fi
-
-if test `echo "$MOZ_EXTENSIONS" | grep -c pref` -ne 0; then
-    AC_MSG_WARN([pref is no longer an extension, use --disable-pref-extensions to disable.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|pref||g'`
-fi
-
-if test `echo "$MOZ_EXTENSIONS" | grep -c universalchardet` -ne 0; then
-    AC_MSG_WARN([universalchardet is no longer an extension, use --disable-universalchardet to disable.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|universalchardet||g'`
-fi
-
-if test `echo "$MOZ_EXTENSIONS" | grep -c java` -ne 0; then
-    AC_MSG_WARN([java is no longer an extension, use --enable-javaxpcom to enable.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|java||g'`
-fi
-
-if test `echo "$MOZ_EXTENSIONS" | grep -c spellcheck` -ne 0; then
-    AC_MSG_WARN([spellcheck is no longer an extension.])
-    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|spellcheck||g'`
-fi
-
 dnl Remove dupes
 MOZ_EXTENSIONS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_EXTENSIONS}`
 
 dnl Ensure every extension exists, to avoid mostly-inscrutable error messages
 dnl when trying to build a nonexistent extension.
 for extension in $MOZ_EXTENSIONS; do
     if test ! -d "${srcdir}/extensions/${extension}"; then
         AC_MSG_ERROR([Unrecognized extension provided to --enable-extensions: ${extension}.])
@@ -9036,18 +8946,16 @@ AC_SUBST(MOZ_PLACES)
 AC_SUBST(MOZ_PLACES_BOOKMARKS)
 AC_SUBST(MOZ_STORAGE)
 AC_SUBST(MOZ_TOOLKIT_SEARCH)
 AC_SUBST(MOZ_FEEDS)
 AC_SUBST(NS_PRINTING)
 AC_SUBST(MOZ_WEBGL)
 AC_SUBST(MOZ_HELP_VIEWER)
 
-AC_SUBST(MOZ_JAVAXPCOM)
-AC_SUBST(JAVA_INCLUDE_PATH)
 AC_SUBST(JAVA)
 AC_SUBST(JAVAC)
 AC_SUBST(JAR)
 
 AC_SUBST(MOZ_PROFILELOCKING)
 
 AC_SUBST(HAVE_XIE)
 AC_SUBST(MOZ_XIE_LIBS)
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/642022-1.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script>
+InstallTrigger.constructor.create(window).setTimeout(Array, 0);
+</script>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -81,10 +81,11 @@ load 590395-1.html
 load 595606-1.html
 load 595606-2.html
 load 606729-1.html
 load 593302-1.html
 load 593302-2.html
 load 610571-1.html
 load 604262-1.html
 load 628599-1.html
+load 642022-1.html
 load 637214-1.svg
 load 637214-2.svg
--- a/content/base/public/nsDOMEventTargetWrapperCache.h
+++ b/content/base/public/nsDOMEventTargetWrapperCache.h
@@ -49,25 +49,18 @@
 // EventSource and WebSocket.
 
 class nsDOMEventTargetWrapperCache : public nsDOMEventTargetHelper,
                                      public nsWrapperCache
 {
 public:  
   NS_DECL_ISUPPORTS_INHERITED
 
-  class NS_CYCLE_COLLECTION_INNERCLASS
-    : public NS_CYCLE_COLLECTION_CLASSNAME(nsDOMEventTargetHelper)
-  {
-    NS_IMETHOD RootAndUnlinkJSObjects(void *p);
-    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(nsDOMEventTargetWrapperCache,
-                                                            nsDOMEventTargetHelper)
-    NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
-  };
-  NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMEventTargetWrapperCache,
+                                                         nsDOMEventTargetHelper)
   
   void GetParentObject(nsIScriptGlobalObject **aParentObject)
   {
     if (mOwner) {
       CallQueryInterface(mOwner, aParentObject);
     }
     else {
       *aParentObject = nsnull;
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -95,20 +95,16 @@ nsDOMAttribute::~nsDOMAttribute()
   nsIContent* content = GetContentInternal();
   if (content) {
     content->RemoveMutationObserver(this);
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttribute)
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsDOMAttribute)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttribute)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mChild)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -117,16 +113,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsD
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
   if (tmp->mChild) {
     static_cast<nsTextNode*>(tmp->mChild)->UnbindFromAttribute();
     NS_RELEASE(tmp->mChild);
     tmp->mFirstChild = nsnull;
   }
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 DOMCI_NODE_DATA(Attr, nsDOMAttribute)
 
 // QueryInterface implementation for nsDOMAttribute
 NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
@@ -143,19 +140,19 @@ NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget,
                                  nsDOMEventRTTearoff::Create(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Attr)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsDOMAttribute, nsIDOMAttr)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsDOMAttribute, nsIDOMAttr,
-                                      nsNodeUtils::LastRelease(this))
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttribute)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsDOMAttribute,
+                                              nsNodeUtils::LastRelease(this))
 
 void
 nsDOMAttribute::SetMap(nsDOMAttributeMap *aMap)
 {
   if (mAttrMap && !aMap && sInitialized) {
     // We're breaking a relationship with content and not getting a new one,
     // need to locally cache value. GetValue() does that.
     GetValue(mValue);
--- a/content/base/src/nsDOMEventTargetWrapperCache.cpp
+++ b/content/base/src/nsDOMEventTargetWrapperCache.cpp
@@ -53,18 +53,18 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsD
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMEventTargetWrapperCache,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsDOMEventTargetWrapperCache)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventTargetWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMEventTargetWrapperCache)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMEventTargetWrapperCache, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMEventTargetWrapperCache, nsDOMEventTargetHelper)
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1754,24 +1754,19 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
     }
 
     return mXPathEvaluatorTearoff->QueryInterface(aIID, aInstancePtr);
   }
   else
 NS_INTERFACE_MAP_END
 
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsDocument, nsIDocument)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsDocument, 
-                                                        nsIDocument,
-                                                        nsNodeUtils::LastRelease(this))
-
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsDocument)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocument)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsDocument, 
+                                              nsNodeUtils::LastRelease(this))
 
 static PLDHashOperator
 SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number,
                 void *arg)
 {
   SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(arg);
@@ -1962,16 +1957,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedRootElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
 
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 
   tmp->mParentDocument = nsnull;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
 
   
   if (tmp->mBoxObjectTable) {
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -295,18 +295,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameLoader)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocShell)
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsFrameLoader::mMessageManager");
   cb.NoteXPCOMChild(static_cast<nsIContentFrameMessageManager*>(tmp->mMessageManager.get()));
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChildMessageManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIContentViewManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader::nsFrameLoader(nsIContent *aOwner, PRBool aNetworkCreated)
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -96,20 +96,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
                                      !mChrome && !mIsProcessManager)
   /* Message managers in child process support nsISyncMessageSender. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
   /* Process message manager doesn't support nsIChromeFrameMessageManager. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager,
                                      mChrome && !mIsProcessManager)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFrameMessageManager,
-                                          nsIContentFrameMessageManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFrameMessageManager,
-                                           nsIContentFrameMessageManager)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager)
 
 NS_IMETHODIMP
 nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
                                           nsIFrameMessageListener* aListener)
 {
   nsCOMPtr<nsIAtom> message = do_GetAtom(aMessage);
   PRUint32 len = mListeners.Length();
   for (PRUint32 i = 0; i < len; ++i) {
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -103,21 +103,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   if (ownerDoc) {
     ownerDoc->BindingManager()->Traverse(tmp, cb);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGenericDOMDataNode)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericDOMDataNode)
   NS_INTERFACE_MAP_ENTRY(nsIContent)
@@ -136,19 +133,19 @@ NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataN
                                  new nsNode3Tearoff(this))
   // nsNodeSH::PreCreate() depends on the identity pointer being the
   // same as nsINode (which nsIContent inherits), so if you change the
   // below line, make sure nsNodeSH::PreCreate() still does the right
   // thing!
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericDOMDataNode, nsIContent)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsGenericDOMDataNode, nsIContent,
-                                      nsNodeUtils::LastRelease(this))
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericDOMDataNode)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsGenericDOMDataNode,
+                                              nsNodeUtils::LastRelease(this))
 
 
 nsresult
 nsGenericDOMDataNode::GetNodeValue(nsAString& aNodeValue)
 {
   return GetData(aNodeValue);
 }
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1925,21 +1925,19 @@ nsDOMEventRTTearoff::~nsDOMEventRTTearof
 NS_IMPL_CYCLE_COLLECTION_1(nsDOMEventRTTearoff, mNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventRTTearoff)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget)
 NS_INTERFACE_MAP_END_AGGREGATED(mNode)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsDOMEventRTTearoff,
-                                          nsIDOMEventTarget)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsDOMEventRTTearoff,
-                                                        nsIDOMEventTarget,
-                                                        LastRelease())
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventRTTearoff)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsDOMEventRTTearoff,
+                                              LastRelease())
 
 nsDOMEventRTTearoff *
 nsDOMEventRTTearoff::Create(nsINode *aNode)
 {
   if (mCachedEventTearoffCount) {
     // We have cached unused instances of this class, return a cached
     // instance in stead of always creating a new one.
     nsDOMEventRTTearoff *tearoff =
@@ -4302,21 +4300,18 @@ nsINode::ReplaceOrInsertBefore(PRBool aR
 }
 
 //----------------------------------------------------------------------
 
 // nsISupports implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericElement)
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGenericElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 
   if (tmp->HasProperties() && tmp->IsXUL()) {
     tmp->DeleteProperty(nsGkAtoms::contextmenulistener);
     tmp->DeleteProperty(nsGkAtoms::popuplistener);
   }
 
@@ -4498,20 +4493,19 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement)
                                  new nsNode3Tearoff(this))
   // nsNodeSH::PreCreate() depends on the identity pointer being the
   // same as nsINode (which nsIContent inherits), so if you change the
   // below line, make sure nsNodeSH::PreCreate() still does the right
   // thing!
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericElement, nsIContent)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement,
-                                                        nsIContent,
-                                                        nsNodeUtils::LastRelease(this))
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericElement)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsGenericElement,
+                                              nsNodeUtils::LastRelease(this))
 
 nsresult
 nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   nsIDocument *document = GetOwnerDoc();
   if (document) {
     return document->BindingManager()->GetBindingImplementation(this, aIID,
                                                                 aInstancePtr);
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -58,51 +58,53 @@
 #endif
 
 namespace css = mozilla::css;
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsIAtom*
-nsStyledElement::GetClassAttributeName() const
+nsStyledElementNotElementCSSInlineStyle::GetClassAttributeName() const
 {
   return nsGkAtoms::_class;
 }
 
 nsIAtom*
-nsStyledElement::GetIDAttributeName() const
+nsStyledElementNotElementCSSInlineStyle::GetIDAttributeName() const
 {
   return nsGkAtoms::id;
 }
 
 nsIAtom*
-nsStyledElement::DoGetID() const
+nsStyledElementNotElementCSSInlineStyle::DoGetID() const
 {
   NS_ASSERTION(HasID(), "Unexpected call");
 
   // The nullcheck here is needed because nsGenericElement::UnsetAttr calls
   // out to various code between removing the attribute and we get a chance to
   // ClearHasID().
 
   const nsAttrValue* attr = mAttrsAndChildren.GetAttr(nsGkAtoms::id);
 
   return attr ? attr->GetAtomValue() : nsnull;
 }
 
 const nsAttrValue*
-nsStyledElement::DoGetClasses() const
+nsStyledElementNotElementCSSInlineStyle::DoGetClasses() const
 {
   NS_ASSERTION(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
   return mAttrsAndChildren.GetAttr(nsGkAtoms::_class);
 }
 
 PRBool
-nsStyledElement::ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
-                                const nsAString& aValue, nsAttrValue& aResult)
+nsStyledElementNotElementCSSInlineStyle::ParseAttribute(PRInt32 aNamespaceID,
+                                                        nsIAtom* aAttribute,
+                                                        const nsAString& aValue,
+                                                        nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::style) {
       SetMayHaveStyle();
       ParseStyleAttribute(aValue, aResult, PR_FALSE);
       return PR_TRUE;
     }
     if (aAttribute == nsGkAtoms::_class) {
@@ -125,46 +127,50 @@ nsStyledElement::ParseAttribute(PRInt32 
     }
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
 nsresult
-nsStyledElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                           PRBool aNotify)
+nsStyledElementNotElementCSSInlineStyle::UnsetAttr(PRInt32 aNameSpaceID,
+                                                   nsIAtom* aAttribute,
+                                                   PRBool aNotify)
 {
   nsAutoRemovableScriptBlocker scriptBlocker;
   if (aAttribute == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
     // Have to do this before clearing flag. See RemoveFromIdTable
     RemoveFromIdTable();
   }
 
   return nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
 nsresult
-nsStyledElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
-                              const nsAString* aValue, PRBool aNotify)
+nsStyledElementNotElementCSSInlineStyle::AfterSetAttr(PRInt32 aNamespaceID,
+                                                      nsIAtom* aAttribute,
+                                                      const nsAString* aValue,
+                                                      PRBool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None && !aValue &&
       aAttribute == nsGkAtoms::id) {
     // The id has been removed when calling UnsetAttr but we kept it because
     // the id is used for some layout stuff between UnsetAttr and AfterSetAttr.
     // Now. the id is really removed so it would not be safe to keep this flag.
     ClearHasID();
   }
 
   return nsGenericElement::AfterSetAttr(aNamespaceID, aAttribute, aValue,
                                         aNotify);
 }
 
 NS_IMETHODIMP
-nsStyledElement::SetInlineStyleRule(css::StyleRule* aStyleRule, PRBool aNotify)
+nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule,
+                                                            PRBool aNotify)
 {
   SetMayHaveStyle();
   PRBool modification = PR_FALSE;
   nsAutoString oldValueStr;
 
   PRBool hasListeners = aNotify &&
     nsContentUtils::HasMutationListeners(this,
                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
@@ -193,34 +199,35 @@ nsStyledElement::SetInlineStyleRule(css:
     static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION);
 
   return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nsnull,
                           oldValueStr, attrValue, modType, hasListeners,
                           aNotify, nsnull);
 }
 
 css::StyleRule*
-nsStyledElement::GetInlineStyleRule()
+nsStyledElementNotElementCSSInlineStyle::GetInlineStyleRule()
 {
   if (!MayHaveStyle()) {
     return nsnull;
   }
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
   if (attrVal && attrVal->Type() == nsAttrValue::eCSSStyleRule) {
     return attrVal->GetCSSStyleRuleValue();
   }
 
   return nsnull;
 }
 
 nsresult
-nsStyledElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            PRBool aCompileEventHandlers)
+nsStyledElementNotElementCSSInlineStyle::BindToTree(nsIDocument* aDocument,
+                                                    nsIContent* aParent,
+                                                    nsIContent* aBindingParent,
+                                                    PRBool aCompileEventHandlers)
 {
   nsresult rv = nsStyledElementBase::BindToTree(aDocument, aParent,
                                                 aBindingParent,
                                                 aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument && HasID() && !GetBindingParent()) {
     aDocument->AddToIdTable(this, DoGetID());
@@ -231,29 +238,30 @@ nsStyledElement::BindToTree(nsIDocument*
     // anything... need to fix that.
     ReparseStyleAttribute(PR_FALSE);
   }
 
   return NS_OK;
 }
 
 void
-nsStyledElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+nsStyledElementNotElementCSSInlineStyle::UnbindFromTree(PRBool aDeep,
+                                                        PRBool aNullParent)
 {
   RemoveFromIdTable();
 
   nsStyledElementBase::UnbindFromTree(aDeep, aNullParent);
 }
 
 
 // ---------------------------------------------------------------
 // Others and helpers
 
 nsIDOMCSSStyleDeclaration*
-nsStyledElement::GetStyle(nsresult* retval)
+nsStyledElementNotElementCSSInlineStyle::GetStyle(nsresult* retval)
 {
   nsXULElement* xulElement = nsXULElement::FromContent(this);
   if (xulElement) {
     nsresult rv = xulElement->EnsureLocalStyle();
     if (NS_FAILED(rv)) {
       *retval = rv;
       return nsnull;
     }
@@ -273,17 +281,17 @@ nsStyledElement::GetStyle(nsresult* retv
     SetMayHaveStyle();
   }
 
   *retval = NS_OK;
   return slots->mStyle;
 }
 
 nsresult
-nsStyledElement::ReparseStyleAttribute(PRBool aForceInDataDoc)
+nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(PRBool aForceInDataDoc)
 {
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   
   if (oldVal && oldVal->Type() != nsAttrValue::eCSSStyleRule) {
     nsAttrValue attrValue;
@@ -295,19 +303,19 @@ nsStyledElement::ReparseStyleAttribute(P
     nsresult rv = mAttrsAndChildren.SetAndTakeAttr(nsGkAtoms::style, attrValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   
   return NS_OK;
 }
 
 void
-nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
-                                     nsAttrValue& aResult,
-                                     PRBool aForceInDataDoc)
+nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aValue,
+                                                             nsAttrValue& aResult,
+                                                             PRBool aForceInDataDoc)
 {
   nsIDocument* doc = GetOwnerDoc();
 
   if (doc && (aForceInDataDoc ||
               !doc->IsLoadedAsData() ||
               doc->IsStaticDocument())) {
     PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
 
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -52,22 +52,22 @@
 namespace mozilla {
 namespace css {
 class StyleRule;
 }
 }
 
 typedef nsGenericElement nsStyledElementBase;
 
-class nsStyledElement : public nsStyledElementBase
+class nsStyledElementNotElementCSSInlineStyle : public nsStyledElementBase
 {
 
 protected:
 
-  inline nsStyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  inline nsStyledElementNotElementCSSInlineStyle(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsStyledElementBase(aNodeInfo)
   {}
 
 public:
 
   // nsIContent interface methods
   virtual nsIAtom* GetClassAttributeName() const;
   virtual nsIAtom* GetIDAttributeName() const;
@@ -109,9 +109,16 @@ protected:
    * Create the style struct from the style attr.  Used when an element is
    * first put into a document.  Only has an effect if the old value is a
    * string.  If aForceInDataDoc is true, will reparse even if we're in a data
    * document.
    */
   nsresult  ReparseStyleAttribute(PRBool aForceInDataDoc);
 };
 
+class nsStyledElement : public nsStyledElementNotElementCSSInlineStyle {
+protected:
+  inline nsStyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+    : nsStyledElementNotElementCSSInlineStyle(aNodeInfo)
+  {}
+};
+
 #endif // __NS_STYLEDELEMENT_H_
--- a/content/base/test/file_xhtmlserializer_2_basic.xhtml
+++ b/content/base/test/file_xhtmlserializer_2_basic.xhtml
@@ -15,17 +15,17 @@
 Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê 
 ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý 
 þ ÿ </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
 Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
 σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
 ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
 ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
-⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ ♦
 </p>
 <p> others
 Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
 ‚“ ” „ † ‡ ‰ ‹ › €
 </p>
 
 </body>
 </html>
\ No newline at end of file
--- a/content/base/test/file_xhtmlserializer_2_latin1.xhtml
+++ b/content/base/test/file_xhtmlserializer_2_latin1.xhtml
@@ -25,17 +25,17 @@
  &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
 &uuml; &yacute; 
 &thorn; &yuml; </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
 Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
 σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
 ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
 ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
-⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ ♦
 </p>
 <p> others
 Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
 ‚“ ” „ † ‡ ‰ ‹ › €
 </p>
 
 </body>
 </html>
\ No newline at end of file
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -760,18 +760,18 @@ WebGLContext::MozGetUnderlyingParamStrin
     return NS_OK;
 }
 
 
 //
 // XPCOM goop
 //
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -215,24 +215,20 @@ public:
     gfxPattern* GetPattern() {
         return mPattern;
     }
 
     /* nsIDOMCanvasGradient */
     NS_IMETHOD AddColorStop (float offset,
                              const nsAString& colorstr)
     {
+        if (!FloatValidate(offset) || offset < 0.0 || offset > 1.0)
+            return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
         nscolor color;
-
-        if (!FloatValidate(offset))
-            return NS_ERROR_DOM_SYNTAX_ERR;
-
-        if (offset < 0.0 || offset > 1.0)
-            return NS_ERROR_DOM_INDEX_SIZE_ERR;
-
         nsCSSParser parser;
         nsresult rv = parser.ParseColorString(nsString(colorstr),
                                               nsnull, 0, &color);
         if (NS_FAILED(rv))
             return NS_ERROR_DOM_SYNTAX_ERR;
 
         mPattern->AddColorStop(offset, gfxRGBA(color));
 
@@ -771,18 +767,18 @@ protected:
             *perDevPixel = devPixel;
         if (perCSSPixel)
             *perCSSPixel = cssPixel;
     }
 
     friend struct nsCanvasBidiProcessor;
 };
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCanvasRenderingContext2D)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -1114,16 +1110,17 @@ nsCanvasRenderingContext2D::SetDimension
     }
     if (surface) {
         if (gCanvasMemoryReporter == nsnull) {
             gCanvasMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasMemory);
             NS_RegisterMemoryReporter(gCanvasMemoryReporter);
         }
 
         gCanvasMemoryUsed += width * height * 4;
+        JS_updateMallocCounter(nsContentUtils::GetCurrentJSContext(), width * height * 4);
     }
 
     return InitializeWithSurface(NULL, surface, width, height);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) {
     Reset();
@@ -3839,42 +3836,61 @@ nsCanvasRenderingContext2D::GetImageData
     if (mCanvasElement &&
         HTMLCanvasElement()->IsWriteOnly() &&
         !nsContentUtils::IsCallerTrustedForRead())
     {
         // XXX ERRMSG we need to report an error to developers here! (bug 329026)
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
-    if (w == 0 || h == 0)
+    if (w == 0 || h == 0 || aDataLen != w * h * 4)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
-    if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    PRUint32 len = w * h * 4;
-    if (aDataLen != len)
+    CheckedInt32 rightMost = CheckedInt32(x) + w;
+    CheckedInt32 bottomMost = CheckedInt32(y) + h;
+
+    if (!rightMost.valid() || !bottomMost.valid())
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     /* Copy the surface contents to the buffer */
-    nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(aData,
-                                                            gfxIntSize(w, h),
-                                                            w * 4,
-                                                            gfxASurface::ImageFormatARGB32);
-    if (!tmpsurf || tmpsurf->CairoStatus())
+    nsRefPtr<gfxImageSurface> tmpsurf =
+        new gfxImageSurface(aData,
+                            gfxIntSize(w, h),
+                            w * 4,
+                            gfxASurface::ImageFormatARGB32);
+
+    if (tmpsurf->CairoStatus())
         return NS_ERROR_FAILURE;
 
     nsRefPtr<gfxContext> tmpctx = new gfxContext(tmpsurf);
 
-    if (!tmpctx || tmpctx->HasError())
+    if (tmpctx->HasError())
         return NS_ERROR_FAILURE;
 
-    tmpctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    tmpctx->SetSource(mSurface, gfxPoint(-(int)x, -(int)y));
-    tmpctx->Paint();
+    gfxRect srcRect(0, 0, mWidth, mHeight);
+    gfxRect destRect(x, y, w, h);
+
+    bool finishedPainting = false;
+    // In the common case, we want to avoid the Rectangle call.
+    if (!srcRect.Contains(destRect)) {
+        // If the requested area is entirely outside the canvas, we're done.
+        gfxRect tmp = srcRect.Intersect(destRect);
+        finishedPainting = tmp.IsEmpty();
+
+        // Set clipping region if necessary.
+        if (!finishedPainting) {
+            tmpctx->Rectangle(tmp);
+        }
+    }
+
+    if (!finishedPainting) {
+        tmpctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+        tmpctx->SetSource(mSurface, gfxPoint(-x, -y));
+        tmpctx->Paint();
+    }
 
     // make sure sUnpremultiplyTable has been created
     EnsureUnpremultiplyTable();
 
     // NOTE! dst is the same as src, and this relies on reading
     // from src and advancing that ptr before writing to dst.
     PRUint8 *src = aData;
     PRUint8 *dst = aData;
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -6103,23 +6103,23 @@ var g = ctx.createLinearGradient(0, 0, 1
 var _thrown = undefined; try {
   g.addColorStop(-1, '#000');
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   g.addColorStop(2, '#000');
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   g.addColorStop(Infinity, '#000');
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   g.addColorStop(-Infinity, '#000');
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   g.addColorStop(NaN, '#000');
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.gradient.object.return.html ]]] -->
 
 <p>Canvas test: 2d.gradient.object.return</p>
@@ -7952,40 +7952,36 @@ var ctx = canvas.getContext('2d');
 var _thrown_outer = false;
 try {
 
 ctx.fillStyle = '#000';
 ctx.fillRect(0, 0, 100, 50);
 ctx.fillStyle = '#fff';
 ctx.fillRect(20, 10, 60, 10);
 
-try {
-  var imgdata1 = ctx.getImageData(85, 25, -10, -10);
-  ok(imgdata1.data[0] === 255, "imgdata1.data[\""+(0)+"\"] === 255");
-  ok(imgdata1.data[1] === 255, "imgdata1.data[\""+(1)+"\"] === 255");
-  ok(imgdata1.data[2] === 255, "imgdata1.data[\""+(2)+"\"] === 255");
-  ok(imgdata1.data[3] === 255, "imgdata1.data[\""+(3)+"\"] === 255");
-  ok(imgdata1.data[imgdata1.data.length-4+0] === 0, "imgdata1.data[imgdata1.data.length-4+0] === 0");
-  ok(imgdata1.data[imgdata1.data.length-4+1] === 0, "imgdata1.data[imgdata1.data.length-4+1] === 0");
-  ok(imgdata1.data[imgdata1.data.length-4+2] === 0, "imgdata1.data[imgdata1.data.length-4+2] === 0");
-  ok(imgdata1.data[imgdata1.data.length-4+3] === 255, "imgdata1.data[imgdata1.data.length-4+3] === 255");
-} catch (e) {
-  ok(false, "Unexpected exception in first part of test_2d_imageData_get_source_negative()", e);
-}
+var imgdata1 = ctx.getImageData(85, 25, -10, -10);
+ok(imgdata1.data[0] === 255, "imgdata1.data[\""+(0)+"\"] === 255");
+ok(imgdata1.data[1] === 255, "imgdata1.data[\""+(1)+"\"] === 255");
+ok(imgdata1.data[2] === 255, "imgdata1.data[\""+(2)+"\"] === 255");
+ok(imgdata1.data[3] === 255, "imgdata1.data[\""+(3)+"\"] === 255");
+ok(imgdata1.data[imgdata1.data.length-4+0] === 0, "imgdata1.data[imgdata1.data.length-4+0] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+1] === 0, "imgdata1.data[imgdata1.data.length-4+1] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+2] === 0, "imgdata1.data[imgdata1.data.length-4+2] === 0");
+ok(imgdata1.data[imgdata1.data.length-4+3] === 255, "imgdata1.data[imgdata1.data.length-4+3] === 255");
 
 var imgdata2 = ctx.getImageData(0, 0, -1, -1);
 ok(imgdata2.data[0] === 0, "imgdata2.data[\""+(0)+"\"] === 0");
 ok(imgdata2.data[1] === 0, "imgdata2.data[\""+(1)+"\"] === 0");
 ok(imgdata2.data[2] === 0, "imgdata2.data[\""+(2)+"\"] === 0");
 ok(imgdata2.data[3] === 0, "imgdata2.data[\""+(3)+"\"] === 0");
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.get.source.outside.html ]]] -->
 
 <p>Canvas test: 2d.imageData.get.source.outside</p>
@@ -8023,20 +8019,54 @@ ok(imgdata3.data[2] === 0, "imgdata3.dat
 ok(imgdata3.data[3] === 0, "imgdata3.data[\""+(3)+"\"] === 0");
 
 var imgdata4 = ctx.getImageData(10, 60, 1, 1);
 ok(imgdata4.data[0] === 0, "imgdata4.data[\""+(0)+"\"] === 0");
 ok(imgdata4.data[1] === 0, "imgdata4.data[\""+(1)+"\"] === 0");
 ok(imgdata4.data[2] === 0, "imgdata4.data[\""+(2)+"\"] === 0");
 ok(imgdata4.data[3] === 0, "imgdata4.data[\""+(3)+"\"] === 0");
 
-} catch (e) {
-    _thrown_outer = true;
-}
-todo(!_thrown_outer, 'should not throw exception');
+var imgdata5 = ctx.getImageData(100, 10, 1, 1);
+ok(imgdata5.data[0] === 0, "imgdata5.data[\""+(0)+"\"] === 0");
+ok(imgdata5.data[1] === 0, "imgdata5.data[\""+(1)+"\"] === 0");
+ok(imgdata5.data[2] === 0, "imgdata5.data[\""+(2)+"\"] === 0");
+ok(imgdata5.data[3] === 0, "imgdata5.data[\""+(3)+"\"] === 0");
+
+var imgdata6 = ctx.getImageData(0, 10, 1, 1);
+ok(imgdata6.data[0] === 0, "imgdata6.data[\""+(0)+"\"] === 0");
+ok(imgdata6.data[1] === 136, "imgdata6.data[\""+(1)+"\"] === 136");
+ok(imgdata6.data[2] === 255, "imgdata6.data[\""+(2)+"\"] === 255");
+ok(imgdata6.data[3] === 255, "imgdata6.data[\""+(3)+"\"] === 255");
+
+var imgdata7 = ctx.getImageData(-10, 10, 20, 20);
+ok(imgdata7.data[ 0*4+0] === 0, "imgdata7.data[ 0*4+0] === 0");
+ok(imgdata7.data[ 0*4+1] === 0, "imgdata7.data[ 0*4+1] === 0");
+ok(imgdata7.data[ 0*4+2] === 0, "imgdata7.data[ 0*4+2] === 0");
+ok(imgdata7.data[ 0*4+3] === 0, "imgdata7.data[ 0*4+3] === 0");
+ok(imgdata7.data[ 9*4+0] === 0, "imgdata7.data[ 9*4+0] === 0");
+ok(imgdata7.data[ 9*4+1] === 0, "imgdata7.data[ 9*4+1] === 0");
+ok(imgdata7.data[ 9*4+2] === 0, "imgdata7.data[ 9*4+2] === 0");
+ok(imgdata7.data[ 9*4+3] === 0, "imgdata7.data[ 9*4+3] === 0");
+ok(imgdata7.data[10*4+0] === 0, "imgdata7.data[10*4+0] === 0");
+ok(imgdata7.data[10*4+1] === 136, "imgdata7.data[10*4+1] === 136");
+ok(imgdata7.data[10*4+2] === 255, "imgdata7.data[10*4+2] === 255");
+ok(imgdata7.data[10*4+3] === 255, "imgdata7.data[10*4+3] === 255");
+ok(imgdata7.data[19*4+0] === 0, "imgdata7.data[19*4+0] === 0");
+ok(imgdata7.data[19*4+1] === 136, "imgdata7.data[19*4+1] === 136");
+ok(imgdata7.data[19*4+2] === 255, "imgdata7.data[19*4+2] === 255");
+ok(imgdata7.data[19*4+3] === 255, "imgdata7.data[19*4+3] === 255");
+ok(imgdata7.data[20*4+0] === 0, "imgdata7.data[20*4+0] === 0");
+ok(imgdata7.data[20*4+1] === 0, "imgdata7.data[20*4+1] === 0");
+ok(imgdata7.data[20*4+2] === 0, "imgdata7.data[20*4+2] === 0");
+ok(imgdata7.data[20*4+3] === 0, "imgdata7.data[20*4+3] === 0");
+
+} catch (e) {
+    _thrown_outer = true;
+}
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.get.source.size.html ]]] -->
 
 <p>Canvas test: 2d.imageData.get.source.size</p>
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -81,20 +81,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventTargetHelper)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsPIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsDOMEventTargetHelper,
-                                          nsPIDOMEventTarget)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsDOMEventTargetHelper,
-                                           nsPIDOMEventTarget)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventTargetHelper)
 
 
 NS_IMETHODIMP
 nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
                                          nsIDOMEventListener* aListener,
                                          PRBool aUseCapture)
 {
   return AddEventListener(aType, aListener, aUseCapture, PR_FALSE, 0);
--- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
+++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
@@ -61,24 +61,21 @@ nsDOMNotifyAudioAvailableEvent::nsDOMNot
 
 DOMCI_DATA(NotifyAudioAvailableEvent, nsDOMNotifyAudioAvailableEvent)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMNotifyAudioAvailableEvent)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsDOMNotifyAudioAvailableEvent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
   if (tmp->mCachedArray) {
     NS_DROP_JS_OBJECTS(tmp, nsDOMNotifyAudioAvailableEvent);
     tmp->mCachedArray = nsnull;
   }
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMNotifyAudioAvailableEvent)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedArray)
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -337,18 +337,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventLi
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEventListenerManager)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEventListenerManager)
    NS_INTERFACE_MAP_ENTRY(nsIEventListenerManager)
    NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsEventListenerManager, nsIEventListenerManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsEventListenerManager, nsIEventListenerManager)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEventListenerManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEventListenerManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventListenerManager)
   PRUint32 count = tmp->mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     cb.NoteXPCOMChild(tmp->mListeners.ElementAt(i).mListener.get());
   }  
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -996,18 +996,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventSt
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEventStateManager)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEventStateManager)
    NS_INTERFACE_MAP_ENTRY(nsIEventStateManager)
    NS_INTERFACE_MAP_ENTRY(nsIObserver)
    NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsEventStateManager, nsIEventStateManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsEventStateManager, nsIEventStateManager)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEventStateManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEventStateManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventStateManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentTargetContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastMouseOverElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGestureDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGestureDownFrameOwner);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastLeftMouseDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastLeftMouseDownContentParent);
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -261,20 +261,18 @@ class nsGenericHTMLElementTearoff : publ
                                            nsIDOMNSHTMLElement)
 
 private:
   nsRefPtr<nsGenericHTMLElement> mElement;
 };
 
 NS_IMPL_CYCLE_COLLECTION_1(nsGenericHTMLElementTearoff, mElement)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericHTMLElementTearoff,
-                                          nsIDOMNSHTMLElement)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGenericHTMLElementTearoff,
-                                           nsIDOMNSHTMLElement)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericHTMLElementTearoff)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGenericHTMLElementTearoff)
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLElementTearoff)
   NS_INTERFACE_TABLE_INHERITED2(nsGenericHTMLElementTearoff,
                                 nsIDOMNSHTMLElement,
                                 nsIDOMElementCSSInlineStyle)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLElementTearoff)
 NS_INTERFACE_MAP_END_AGGREGATED(mElement)
 
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -2288,18 +2288,18 @@ NS_INTERFACE_TABLE_HEAD(nsFormControlLis
   NS_INTERFACE_TABLE2(nsFormControlList,
                       nsIHTMLCollection,
                       nsIDOMHTMLCollection)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsFormControlList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLCollection)
 NS_INTERFACE_MAP_END
 
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormControlList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormControlList)
 
 
 // nsIDOMHTMLCollection interface
 
 NS_IMETHODIMP    
 nsFormControlList::GetLength(PRUint32* aLength)
 {
   FlushPendingNotifications();
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -2086,20 +2086,18 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLOptionColl
                       nsIDOMNSHTMLOptionCollection,
                       nsIDOMHTMLOptionsCollection,
                       nsIDOMHTMLCollection)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHTMLOptionCollection)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLOptionsCollection)
 NS_INTERFACE_MAP_END
 
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsHTMLOptionCollection,
-                                          nsIHTMLCollection)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsHTMLOptionCollection,
-                                           nsIHTMLCollection)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTMLOptionCollection)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTMLOptionCollection)
 
 
 // nsIDOMNSHTMLOptionCollection interface
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::GetLength(PRUint32* aLength)
 {
   *aLength = mElements.Length();
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -215,18 +215,18 @@ public:
 
 private:
   nsCOMPtr<nsFrameSelection> mFrameSelection;
   nsCOMPtr<nsIContent>       mLimiter;
   nsIScrollableFrame        *mScrollFrame;
   nsWeakPtr mPresShellWeak;
 };
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsTextInputSelectionImpl, nsISelectionController)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsTextInputSelectionImpl, nsISelectionController)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextInputSelectionImpl)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTextInputSelectionImpl)
 NS_INTERFACE_TABLE_HEAD(nsTextInputSelectionImpl)
   NS_INTERFACE_TABLE3(nsTextInputSelectionImpl,
                       nsISelectionController,
                       nsISelectionDisplay,
                       nsISupportsWeakReference)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsTextInputSelectionImpl)
 NS_INTERFACE_MAP_END
 
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -228,20 +228,18 @@ nsHTMLFragmentContentSink::~nsHTMLFragme
   PR_FREEIF(mText);
 
   PRUint32 i;
   for (i = 0; i < NS_ARRAY_LENGTH(mNodeInfoCache); ++i) {
     NS_IF_RELEASE(mNodeInfoCache[i]);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsHTMLFragmentContentSink,
-                                          nsIContentSink)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsHTMLFragmentContentSink,
-                                           nsIContentSink)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTMLFragmentContentSink)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTMLFragmentContentSink)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTMLFragmentContentSink)
   NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
   NS_INTERFACE_MAP_ENTRY(nsIHTMLContentSink)
   NS_INTERFACE_MAP_ENTRY(nsIContentSink)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentSink)
 NS_INTERFACE_MAP_END
 
--- a/content/mathml/content/src/Makefile.in
+++ b/content/mathml/content/src/Makefile.in
@@ -59,20 +59,14 @@ include $(topsrcdir)/config/config.mk
 FORCE_STATIC_LIB = 1
 
 EXPORTS = \
 	$(NULL)
 
 
 include $(topsrcdir)/config/rules.mk
 
-EXPORT_RESOURCE_CONTENT = \
-		$(srcdir)/mathml.dtd \
-		$(NULL)
-libs::
-	$(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/res/dtd
-
 INCLUDES += 	\
 		-I$(srcdir)/../../../shared/public \
 		-I$(srcdir)/../../../base/src \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
deleted file mode 100644
--- a/content/mathml/content/src/mathml.dtd
+++ /dev/null
@@ -1,1592 +0,0 @@
-<!-- ***** BEGIN LICENSE BLOCK *****
-   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
-   -
-   - The contents of this file are subject to the Mozilla Public License Version
-   - 1.1 (the "License"); you may not use this file except in compliance with
-   - the License. You may obtain a copy of the License at
-   - http://www.mozilla.org/MPL/
-   -
-   - Software distributed under the License is distributed on an "AS IS" basis,
-   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-   - for the specific language governing rights and limitations under the
-   - License.
-   -
-   - The Original Code is Mozilla MathML Project.
-   -
-   - The Initial Developer of the Original Code is
-   - The University of Queensland.
-   - Portions created by the Initial Developer are Copyright (C) 2001
-   - the Initial Developer. All Rights Reserved.
-   -
-   - Contributor(s):
-   -       Roger B. Sidje <rbs@maths.uq.edu.au>
-   -       Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
-   -
-   - Alternatively, the contents of this file may be used under the terms of
-   - either the GNU General Public License Version 2 or later (the "GPL"), or
-   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-   - in which case the provisions of the GPL or the LGPL are applicable instead
-   - of those above. If you wish to allow use of your version of this file only
-   - under the terms of either the GPL or the LGPL, and not to allow others to
-   - use your version of this file under the terms of the MPL, indicate your
-   - decision by deleting the provisions above and replace them with the notice
-   - and other provisions required by the LGPL or the GPL. If you do not delete
-   - the provisions above, a recipient may use your version of this file under
-   - the terms of any one of the MPL, the GPL or the LGPL.
-   -
-   - ***** END LICENSE BLOCK ***** -->
-
-<!-- Entities defined in MathML 2.0 but with Unicode code points updated in
-     line with http://www.unicode.org/reports/tr25/tr25-9.html
-  -->
-<!ENTITY phi "&#x3D5;">
-<!ENTITY ShortLeftArrow "&#x2190;&#x200B;"><!ENTITY slarr "&#x2190;&#x200B;">
-<!ENTITY ShortUpArrow "&#x2191;&#x200B;">
-<!ENTITY ShortRightArrow "&#x2192;&#x200B;"><!ENTITY srarr "&#x2192;&#x200B;">
-<!ENTITY ShortDownArrow "&#x2193;&#x200B;">
-<!ENTITY OverParenthesis "&#x23DC;">
-<!ENTITY UnderParenthesis "&#x23DD;">
-<!ENTITY OverBrace "&#x23DE;">
-<!ENTITY UnderBrace "&#x23DF;">
-<!ENTITY trpezium "&#x23E2;">
-<!ENTITY elinters "&#x23E7;">
-<!ENTITY lbbrk "&#x2772;">
-<!ENTITY rbbrk "&#x2773;">
-<!ENTITY lobrk "&#x27E6;"><!ENTITY LeftDoubleBracket "&#x27E6;">
-<!ENTITY robrk "&#x27E7;"><!ENTITY RightDoubleBracket "&#x27E7;">
-<!ENTITY lang "&#x27E8;"><!ENTITY LeftAngleBracket "&#x27E8;"><!ENTITY langle "&#x27E8;">
-<!ENTITY rang "&#x27E9;"><!ENTITY RightAngleBracket "&#x27E9;"><!ENTITY rangle "&#x27E9;">
-<!ENTITY Lang "&#x27EA;">
-<!ENTITY Rang "&#x27EB;">
-<!ENTITY loang "&#x27EC;">
-<!ENTITY roang "&#x27ED;">
-<!ENTITY imath "&#x1D6A4;"><!ENTITY inodot "&#x1D6A4;">
-<!ENTITY jmath "&#x1D6A5;">
-
-<!-- MathML 2.0 entities - Auto-generated from the
-     "XHTML 1.1 plus MathML 2.0 plus SVG 1.1 DTD"
-     http://www.w3.org/Math/DTD/mathml2.tgz
-     as of Revision: xhtml-math11-f.dtd,v 1.16 2003/11/04 13:14:35
-
-                              *** *** ***
-
-     The "XHTML 1.1 plus MathML 2.0 plus SVG 1.1 DTD" file from which the
-     entities were retrieved had the following copyright notice:
-
-     Copyright 2002 World Wide Web Consortium
-        (Massachusetts Institute of Technology, Institut National de
-         Recherche en Informatique et en Automatique, Keio University).
-         All Rights Reserved.
-
-     Permission to use, copy, modify and distribute this DTD and its
-     accompanying documentation for any purpose and without fee is hereby
-     granted in perpetuity, provided that the above copyright notice and 
-     this paragraph appear in all copies.  The copyright holders make no
-     representation about the suitability of the DTD for any purpose.
-
-                              *** *** ***
-
-     The section listing entity declarations had the following notices:
-
-     Portions (C) International Organization for Standardization 1986:
-     Permission to copy in any form is granted for use with conforming
-     SGML systems and applications as defined in ISO 8879, provided
-     this notice is included in all copies.
-
-     (C) International Organization for Standardization 1991
-     Permission to copy in any form is granted for use with
-     conforming SGML systems and applications as defined in
-     ISO 8879, provided this notice is included in all copies.
-  -->
-<!ENTITY Tab "&#x9;">
-<!ENTITY NewLine "&#xA;">
-<!ENTITY excl "&#x21;">
-<!ENTITY quot "&#x22;">
-<!ENTITY num "&#x23;">
-<!ENTITY dollar "&#x24;">
-<!ENTITY percnt "&#x25;">
-<!ENTITY nvlt "&#x26;#x3C;&#x20D2;">
-<!ENTITY apos "&#x27;">
-<!ENTITY lpar "&#x28;">
-<!ENTITY rpar "&#x29;">
-<!ENTITY midast "&#x2A;"><!ENTITY ast "&#x2A;">
-<!ENTITY plus "&#x2B;">
-<!ENTITY comma "&#x2C;">
-<!ENTITY period "&#x2E;">
-<!ENTITY sol "&#x2F;">
-<!ENTITY colon "&#x3A;">
-<!ENTITY semi "&#x3B;">
-<!ENTITY equals "&#x3D;">
-<!ENTITY bne "&#x3D;&#x20E5;">
-<!ENTITY nvgt "&#x3E;&#x20D2;">
-<!ENTITY quest "&#x3F;">
-<!ENTITY commat "&#x40;">
-<!ENTITY lsqb "&#x5B;"><!ENTITY lbrack "&#x5B;">
-<!ENTITY bsol "&#x5C;">
-<!ENTITY bsolhsub "&#x5C;&#x2282;">
-<!ENTITY rsqb "&#x5D;"><!ENTITY rbrack "&#x5D;">
-<!ENTITY Hat "&#x5E;">
-<!ENTITY lowbar "&#x5F;">
-<!ENTITY grave "&#x60;"><!ENTITY DiacriticalGrave "&#x60;">
-<!ENTITY lcub "&#x7B;"><!ENTITY lbrace "&#x7B;">
-<!ENTITY verbar "&#x7C;"><!ENTITY VerticalLine "&#x7C;"><!ENTITY vert "&#x7C;">
-<!ENTITY rcub "&#x7D;"><!ENTITY rbrace "&#x7D;">
-<!ENTITY nbsp "&#xA0;"><!ENTITY NonBreakingSpace "&#xA0;">
-<!ENTITY iexcl "&#xA1;">
-<!ENTITY cent "&#xA2;">
-<!ENTITY pound "&#xA3;">
-<!ENTITY curren "&#xA4;">
-<!ENTITY yen "&#xA5;">
-<!ENTITY brvbar "&#xA6;">
-<!ENTITY sect "&#xA7;">
-<!ENTITY uml "&#xA8;"><!ENTITY Dot "&#xA8;"><!ENTITY die "&#xA8;"><!ENTITY DoubleDot "&#xA8;">
-<!ENTITY copy "&#xA9;">
-<!ENTITY ordf "&#xAA;">
-<!ENTITY laquo "&#xAB;">
-<!ENTITY not "&#xAC;">
-<!ENTITY shy "&#xAD;">
-<!ENTITY reg "&#xAE;"><!ENTITY circledR "&#xAE;">
-<!ENTITY macr "&#xAF;"><!ENTITY strns "&#xAF;"><!ENTITY OverBar "&#xAF;">
-<!ENTITY deg "&#xB0;">
-<!ENTITY plusmn "&#xB1;"><!ENTITY PlusMinus "&#xB1;"><!ENTITY pm "&#xB1;">
-<!ENTITY sup2 "&#xB2;">
-<!ENTITY sup3 "&#xB3;">
-<!ENTITY acute "&#xB4;"><!ENTITY DiacriticalAcute "&#xB4;">
-<!ENTITY micro "&#xB5;">
-<!ENTITY para "&#xB6;">
-<!ENTITY middot "&#xB7;"><!ENTITY CenterDot "&#xB7;"><!ENTITY centerdot "&#xB7;">
-<!ENTITY cedil "&#xB8;"><!ENTITY Cedilla "&#xB8;">
-<!ENTITY sup1 "&#xB9;">
-<!ENTITY ordm "&#xBA;">
-<!ENTITY raquo "&#xBB;">
-<!ENTITY frac14 "&#xBC;">
-<!ENTITY frac12 "&#xBD;"><!ENTITY half "&#xBD;">
-<!ENTITY frac34 "&#xBE;">
-<!ENTITY iquest "&#xBF;">
-<!ENTITY Agrave "&#xC0;">
-<!ENTITY Aacute "&#xC1;">
-<!ENTITY Acirc "&#xC2;">
-<!ENTITY Atilde "&#xC3;">
-<!ENTITY Auml "&#xC4;">
-<!ENTITY Aring "&#xC5;">
-<!ENTITY AElig "&#xC6;">
-<!ENTITY Ccedil "&#xC7;">
-<!ENTITY Egrave "&#xC8;">
-<!ENTITY Eacute "&#xC9;">
-<!ENTITY Ecirc "&#xCA;">
-<!ENTITY Euml "&#xCB;">
-<!ENTITY Igrave "&#xCC;">
-<!ENTITY Iacute "&#xCD;">
-<!ENTITY Icirc "&#xCE;">
-<!ENTITY Iuml "&#xCF;">
-<!ENTITY ETH "&#xD0;">
-<!ENTITY Ntilde "&#xD1;">
-<!ENTITY Ograve "&#xD2;">
-<!ENTITY Oacute "&#xD3;">
-<!ENTITY Ocirc "&#xD4;">
-<!ENTITY Otilde "&#xD5;">
-<!ENTITY Ouml "&#xD6;">
-<!ENTITY times "&#xD7;">
-<!ENTITY Oslash "&#xD8;">
-<!ENTITY Ugrave "&#xD9;">
-<!ENTITY Uacute "&#xDA;">
-<!ENTITY Ucirc "&#xDB;">
-<!ENTITY Uuml "&#xDC;">
-<!ENTITY Yacute "&#xDD;">
-<!ENTITY THORN "&#xDE;">
-<!ENTITY szlig "&#xDF;">
-<!ENTITY agrave "&#xE0;">
-<!ENTITY aacute "&#xE1;">
-<!ENTITY acirc "&#xE2;">
-<!ENTITY atilde "&#xE3;">
-<!ENTITY auml "&#xE4;">
-<!ENTITY aring "&#xE5;">
-<!ENTITY aelig "&#xE6;">
-<!ENTITY ccedil "&#xE7;">
-<!ENTITY egrave "&#xE8;">
-<!ENTITY eacute "&#xE9;">
-<!ENTITY ecirc "&#xEA;">
-<!ENTITY euml "&#xEB;">
-<!ENTITY igrave "&#xEC;">
-<!ENTITY iacute "&#xED;">
-<!ENTITY icirc "&#xEE;">
-<!ENTITY iuml "&#xEF;">
-<!ENTITY eth "&#xF0;">
-<!ENTITY ntilde "&#xF1;">
-<!ENTITY ograve "&#xF2;">
-<!ENTITY oacute "&#xF3;">
-<!ENTITY ocirc "&#xF4;">
-<!ENTITY otilde "&#xF5;">
-<!ENTITY ouml "&#xF6;">
-<!ENTITY divide "&#xF7;"><!ENTITY div "&#xF7;">
-<!ENTITY oslash "&#xF8;">
-<!ENTITY ugrave "&#xF9;">
-<!ENTITY uacute "&#xFA;">
-<!ENTITY ucirc "&#xFB;">
-<!ENTITY uuml "&#xFC;">
-<!ENTITY yacute "&#xFD;">
-<!ENTITY thorn "&#xFE;">
-<!ENTITY yuml "&#xFF;">
-<!ENTITY Amacr "&#x100;">
-<!ENTITY amacr "&#x101;">
-<!ENTITY Abreve "&#x102;">
-<!ENTITY abreve "&#x103;">
-<!ENTITY Aogon "&#x104;">
-<!ENTITY aogon "&#x105;">
-<!ENTITY Cacute "&#x106;">
-<!ENTITY cacute "&#x107;">
-<!ENTITY Ccirc "&#x108;">
-<!ENTITY ccirc "&#x109;">
-<!ENTITY Cdot "&#x10A;">
-<!ENTITY cdot "&#x10B;">
-<!ENTITY Ccaron "&#x10C;">
-<!ENTITY ccaron "&#x10D;">
-<!ENTITY Dcaron "&#x10E;">
-<!ENTITY dcaron "&#x10F;">
-<!ENTITY Dstrok "&#x110;">
-<!ENTITY dstrok "&#x111;">
-<!ENTITY Emacr "&#x112;">
-<!ENTITY emacr "&#x113;">
-<!ENTITY Edot "&#x116;">
-<!ENTITY edot "&#x117;">
-<!ENTITY Eogon "&#x118;">
-<!ENTITY eogon "&#x119;">
-<!ENTITY Ecaron "&#x11A;">
-<!ENTITY ecaron "&#x11B;">
-<!ENTITY Gcirc "&#x11C;">
-<!ENTITY gcirc "&#x11D;">
-<!ENTITY Gbreve "&#x11E;">
-<!ENTITY gbreve "&#x11F;">
-<!ENTITY Gdot "&#x120;">
-<!ENTITY gdot "&#x121;">
-<!ENTITY Gcedil "&#x122;">
-<!ENTITY Hcirc "&#x124;">
-<!ENTITY hcirc "&#x125;">
-<!ENTITY Hstrok "&#x126;">
-<!ENTITY hstrok "&#x127;">
-<!ENTITY Itilde "&#x128;">
-<!ENTITY itilde "&#x129;">
-<!ENTITY Imacr "&#x12A;">
-<!ENTITY imacr "&#x12B;">
-<!ENTITY Iogon "&#x12E;">
-<!ENTITY iogon "&#x12F;">
-<!ENTITY Idot "&#x130;">
-<!ENTITY IJlig "&#x132;">
-<!ENTITY ijlig "&#x133;">
-<!ENTITY Jcirc "&#x134;">
-<!ENTITY jcirc "&#x135;">
-<!ENTITY Kcedil "&#x136;">
-<!ENTITY kcedil "&#x137;">
-<!ENTITY kgreen "&#x138;">
-<!ENTITY Lacute "&#x139;">
-<!ENTITY lacute "&#x13A;">
-<!ENTITY Lcedil "&#x13B;">
-<!ENTITY lcedil "&#x13C;">
-<!ENTITY Lcaron "&#x13D;">
-<!ENTITY lcaron "&#x13E;">
-<!ENTITY Lmidot "&#x13F;">
-<!ENTITY lmidot "&#x140;">
-<!ENTITY Lstrok "&#x141;">
-<!ENTITY lstrok "&#x142;">
-<!ENTITY Nacute "&#x143;">
-<!ENTITY nacute "&#x144;">
-<!ENTITY Ncedil "&#x145;">
-<!ENTITY ncedil "&#x146;">
-<!ENTITY Ncaron "&#x147;">
-<!ENTITY ncaron "&#x148;">
-<!ENTITY napos "&#x149;">
-<!ENTITY ENG "&#x14A;">
-<!ENTITY eng "&#x14B;">
-<!ENTITY Omacr "&#x14C;">
-<!ENTITY omacr "&#x14D;">
-<!ENTITY Odblac "&#x150;">
-<!ENTITY odblac "&#x151;">
-<!ENTITY OElig "&#x152;">
-<!ENTITY oelig "&#x153;">
-<!ENTITY Racute "&#x154;">
-<!ENTITY racute "&#x155;">
-<!ENTITY Rcedil "&#x156;">
-<!ENTITY rcedil "&#x157;">
-<!ENTITY Rcaron "&#x158;">
-<!ENTITY rcaron "&#x159;">
-<!ENTITY Sacute "&#x15A;">
-<!ENTITY sacute "&#x15B;">
-<!ENTITY Scirc "&#x15C;">
-<!ENTITY scirc "&#x15D;">
-<!ENTITY Scedil "&#x15E;">
-<!ENTITY scedil "&#x15F;">
-<!ENTITY Scaron "&#x160;">
-<!ENTITY scaron "&#x161;">
-<!ENTITY Tcedil "&#x162;">
-<!ENTITY tcedil "&#x163;">
-<!ENTITY Tcaron "&#x164;">
-<!ENTITY tcaron "&#x165;">
-<!ENTITY Tstrok "&#x166;">
-<!ENTITY tstrok "&#x167;">
-<!ENTITY Utilde "&#x168;">
-<!ENTITY utilde "&#x169;">
-<!ENTITY Umacr "&#x16A;">
-<!ENTITY umacr "&#x16B;">
-<!ENTITY Ubreve "&#x16C;">
-<!ENTITY ubreve "&#x16D;">
-<!ENTITY Uring "&#x16E;">
-<!ENTITY uring "&#x16F;">
-<!ENTITY Udblac "&#x170;">
-<!ENTITY udblac "&#x171;">
-<!ENTITY Uogon "&#x172;">
-<!ENTITY uogon "&#x173;">
-<!ENTITY Wcirc "&#x174;">
-<!ENTITY wcirc "&#x175;">
-<!ENTITY Ycirc "&#x176;">
-<!ENTITY ycirc "&#x177;">
-<!ENTITY Yuml "&#x178;">
-<!ENTITY Zacute "&#x179;">
-<!ENTITY zacute "&#x17A;">
-<!ENTITY Zdot "&#x17B;">
-<!ENTITY zdot "&#x17C;">
-<!ENTITY Zcaron "&#x17D;">
-<!ENTITY zcaron "&#x17E;">
-<!ENTITY fnof "&#x192;">
-<!ENTITY imped "&#x1B5;">
-<!ENTITY gacute "&#x1F5;">
-<!ENTITY circ "&#x2C6;">
-<!ENTITY caron "&#x2C7;"><!ENTITY Hacek "&#x2C7;">
-<!ENTITY breve "&#x2D8;"><!ENTITY Breve "&#x2D8;">
-<!ENTITY dot "&#x2D9;"><!ENTITY DiacriticalDot "&#x2D9;">
-<!ENTITY ring "&#x2DA;">
-<!ENTITY ogon "&#x2DB;">
-<!ENTITY tilde "&#x2DC;"><!ENTITY DiacriticalTilde "&#x2DC;">
-<!ENTITY dblac "&#x2DD;"><!ENTITY DiacriticalDoubleAcute "&#x2DD;">
-<!ENTITY DownBreve " &#x311;">
-<!ENTITY UnderBar " &#x332;">
-<!ENTITY Alpha "&#x391;">
-<!ENTITY Beta "&#x392;">
-<!ENTITY Gamma "&#x393;">
-<!ENTITY Delta "&#x394;">
-<!ENTITY Epsilon "&#x395;">
-<!ENTITY Zeta "&#x396;">
-<!ENTITY Eta "&#x397;">
-<!ENTITY Theta "&#x398;">
-<!ENTITY Iota "&#x399;">
-<!ENTITY Kappa "&#x39A;">
-<!ENTITY Lambda "&#x39B;">
-<!ENTITY Mu "&#x39C;">
-<!ENTITY Nu "&#x39D;">
-<!ENTITY Xi "&#x39E;">
-<!ENTITY Omicron "&#x39F;">
-<!ENTITY Pi "&#x3A0;">
-<!ENTITY Rho "&#x3A1;">
-<!ENTITY Sigma "&#x3A3;">
-<!ENTITY Tau "&#x3A4;">
-<!ENTITY Upsilon "&#x3A5;">
-<!ENTITY Phi "&#x3A6;">
-<!ENTITY Chi "&#x3A7;">
-<!ENTITY Psi "&#x3A8;">
-<!ENTITY Omega "&#x3A9;">
-<!ENTITY alpha "&#x3B1;">
-<!ENTITY beta "&#x3B2;">
-<!ENTITY gamma "&#x3B3;">
-<!ENTITY delta "&#x3B4;">
-<!ENTITY epsilon "&#x3B5;"><!ENTITY epsiv "&#x3B5;"><!ENTITY varepsilon "&#x3B5;">
-<!ENTITY zeta "&#x3B6;">
-<!ENTITY eta "&#x3B7;">
-<!ENTITY theta "&#x3B8;">
-<!ENTITY iota "&#x3B9;">
-<!ENTITY kappa "&#x3BA;">
-<!ENTITY lambda "&#x3BB;">
-<!ENTITY mu "&#x3BC;">
-<!ENTITY nu "&#x3BD;">
-<!ENTITY xi "&#x3BE;">
-<!ENTITY omicron "&#x3BF;">
-<!ENTITY pi "&#x3C0;">
-<!ENTITY rho "&#x3C1;">
-<!ENTITY sigmaf "&#x3C2;"><!ENTITY sigmav "&#x3C2;"><!ENTITY varsigma "&#x3C2;">
-<!ENTITY sigma "&#x3C3;">
-<!ENTITY tau "&#x3C4;">
-<!ENTITY upsilon "&#x3C5;"><!ENTITY upsi "&#x3C5;">
-<!ENTITY phiv "&#x3C6;"><!ENTITY varphi "&#x3C6;">
-<!ENTITY chi "&#x3C7;">
-<!ENTITY psi "&#x3C8;">
-<!ENTITY omega "&#x3C9;">
-<!ENTITY thetasym "&#x3D1;"><!ENTITY thetav "&#x3D1;"><!ENTITY vartheta "&#x3D1;">
-<!ENTITY upsih "&#x3D2;"><!ENTITY Upsi "&#x3D2;">
-<!ENTITY straightphi "&#x3D5;">
-<!ENTITY piv "&#x3D6;"><!ENTITY varpi "&#x3D6;">
-<!ENTITY Gammad "&#x3DC;">
-<!ENTITY gammad "&#x3DD;"><!ENTITY digamma "&#x3DD;">
-<!ENTITY kappav "&#x3F0;"><!ENTITY varkappa "&#x3F0;">
-<!ENTITY rhov "&#x3F1;"><!ENTITY varrho "&#x3F1;">
-<!ENTITY epsi "&#x3F5;"><!ENTITY straightepsilon "&#x3F5;">
-<!ENTITY bepsi "&#x3F6;"><!ENTITY backepsilon "&#x3F6;">
-<!ENTITY IOcy "&#x401;">
-<!ENTITY DJcy "&#x402;">
-<!ENTITY GJcy "&#x403;">
-<!ENTITY Jukcy "&#x404;">
-<!ENTITY DScy "&#x405;">
-<!ENTITY Iukcy "&#x406;">
-<!ENTITY YIcy "&#x407;">
-<!ENTITY Jsercy "&#x408;">
-<!ENTITY LJcy "&#x409;">
-<!ENTITY NJcy "&#x40A;">
-<!ENTITY TSHcy "&#x40B;">
-<!ENTITY KJcy "&#x40C;">
-<!ENTITY Ubrcy "&#x40E;">
-<!ENTITY DZcy "&#x40F;">
-<!ENTITY Acy "&#x410;">
-<!ENTITY Bcy "&#x411;">
-<!ENTITY Vcy "&#x412;">
-<!ENTITY Gcy "&#x413;">
-<!ENTITY Dcy "&#x414;">
-<!ENTITY IEcy "&#x415;">
-<!ENTITY ZHcy "&#x416;">
-<!ENTITY Zcy "&#x417;">
-<!ENTITY Icy "&#x418;">
-<!ENTITY Jcy "&#x419;">
-<!ENTITY Kcy "&#x41A;">
-<!ENTITY Lcy "&#x41B;">
-<!ENTITY Mcy "&#x41C;">
-<!ENTITY Ncy "&#x41D;">
-<!ENTITY Ocy "&#x41E;">
-<!ENTITY Pcy "&#x41F;">
-<!ENTITY Rcy "&#x420;">
-<!ENTITY Scy "&#x421;">
-<!ENTITY Tcy "&#x422;">
-<!ENTITY Ucy "&#x423;">
-<!ENTITY Fcy "&#x424;">
-<!ENTITY KHcy "&#x425;">
-<!ENTITY TScy "&#x426;">
-<!ENTITY CHcy "&#x427;">
-<!ENTITY SHcy "&#x428;">
-<!ENTITY SHCHcy "&#x429;">
-<!ENTITY HARDcy "&#x42A;">
-<!ENTITY Ycy "&#x42B;">
-<!ENTITY SOFTcy "&#x42C;">
-<!ENTITY Ecy "&#x42D;">
-<!ENTITY YUcy "&#x42E;">
-<!ENTITY YAcy "&#x42F;">
-<!ENTITY acy "&#x430;">
-<!ENTITY bcy "&#x431;">
-<!ENTITY vcy "&#x432;">
-<!ENTITY gcy "&#x433;">
-<!ENTITY dcy "&#x434;">
-<!ENTITY iecy "&#x435;">
-<!ENTITY zhcy "&#x436;">
-<!ENTITY zcy "&#x437;">
-<!ENTITY icy "&#x438;">
-<!ENTITY jcy "&#x439;">
-<!ENTITY kcy "&#x43A;">
-<!ENTITY lcy "&#x43B;">
-<!ENTITY mcy "&#x43C;">
-<!ENTITY ncy "&#x43D;">
-<!ENTITY ocy "&#x43E;">
-<!ENTITY pcy "&#x43F;">
-<!ENTITY rcy "&#x440;">
-<!ENTITY scy "&#x441;">
-<!ENTITY tcy "&#x442;">
-<!ENTITY ucy "&#x443;">
-<!ENTITY fcy "&#x444;">
-<!ENTITY khcy "&#x445;">
-<!ENTITY tscy "&#x446;">
-<!ENTITY chcy "&#x447;">
-<!ENTITY shcy "&#x448;">
-<!ENTITY shchcy "&#x449;">
-<!ENTITY hardcy "&#x44A;">
-<!ENTITY ycy "&#x44B;">
-<!ENTITY softcy "&#x44C;">
-<!ENTITY ecy "&#x44D;">
-<!ENTITY yucy "&#x44E;">
-<!ENTITY yacy "&#x44F;">
-<!ENTITY iocy "&#x451;">
-<!ENTITY djcy "&#x452;">
-<!ENTITY gjcy "&#x453;">
-<!ENTITY jukcy "&#x454;">
-<!ENTITY dscy "&#x455;">
-<!ENTITY iukcy "&#x456;">
-<!ENTITY yicy "&#x457;">
-<!ENTITY jsercy "&#x458;">
-<!ENTITY ljcy "&#x459;">
-<!ENTITY njcy "&#x45A;">
-<!ENTITY tshcy "&#x45B;">
-<!ENTITY kjcy "&#x45C;">
-<!ENTITY ubrcy "&#x45E;">
-<!ENTITY dzcy "&#x45F;">
-<!ENTITY ensp "&#x2002;">
-<!ENTITY emsp "&#x2003;">
-<!ENTITY emsp13 "&#x2004;">
-<!ENTITY emsp14 "&#x2005;">
-<!ENTITY numsp "&#x2007;">
-<!ENTITY puncsp "&#x2008;">
-<!ENTITY thinsp "&#x2009;"><!ENTITY ThinSpace "&#x2009;">
-<!ENTITY ThickSpace "&#x2009;&#x200A;&#x200A;">
-<!ENTITY hairsp "&#x200A;"><!ENTITY VeryThinSpace "&#x200A;">
-<!ENTITY ZeroWidthSpace "&#x200B;"><!ENTITY NegativeMediumSpace "&#x200B;"><!ENTITY NegativeThickSpace "&#x200B;"><!ENTITY NegativeThinSpace "&#x200B;"><!ENTITY NegativeVeryThinSpace "&#x200B;">
-<!ENTITY zwnj "&#x200C;">
-<!ENTITY zwj "&#x200D;">
-<!ENTITY lrm "&#x200E;">
-<!ENTITY rlm "&#x200F;">
-<!ENTITY hyphen "&#x2010;"><!ENTITY dash "&#x2010;">
-<!ENTITY ndash "&#x2013;">
-<!ENTITY mdash "&#x2014;">
-<!ENTITY horbar "&#x2015;">
-<!ENTITY Verbar "&#x2016;"><!ENTITY Vert "&#x2016;">
-<!ENTITY lsquo "&#x2018;"><!ENTITY OpenCurlyQuote "&#x2018;">
-<!ENTITY rsquo "&#x2019;"><!ENTITY rsquor "&#x2019;"><!ENTITY CloseCurlyQuote "&#x2019;">
-<!ENTITY sbquo "&#x201A;"><!ENTITY lsquor "&#x201A;">
-<!ENTITY ldquo "&#x201C;"><!ENTITY OpenCurlyDoubleQuote "&#x201C;">
-<!ENTITY rdquo "&#x201D;"><!ENTITY rdquor "&#x201D;"><!ENTITY CloseCurlyDoubleQuote "&#x201D;">
-<!ENTITY bdquo "&#x201E;"><!ENTITY ldquor "&#x201E;">
-<!ENTITY dagger "&#x2020;">
-<!ENTITY Dagger "&#x2021;"><!ENTITY ddagger "&#x2021;">
-<!ENTITY bull "&#x2022;"><!ENTITY bullet "&#x2022;">
-<!ENTITY nldr "&#x2025;">
-<!ENTITY hellip "&#x2026;"><!ENTITY mldr "&#x2026;">
-<!ENTITY permil "&#x2030;">
-<!ENTITY pertenk "&#x2031;">
-<!ENTITY prime "&#x2032;">
-<!ENTITY Prime "&#x2033;">
-<!ENTITY tprime "&#x2034;">
-<!ENTITY bprime "&#x2035;"><!ENTITY backprime "&#x2035;">
-<!ENTITY lsaquo "&#x2039;">
-<!ENTITY rsaquo "&#x203A;">
-<!ENTITY oline "&#x203E;">
-<!ENTITY caret "&#x2041;">
-<!ENTITY hybull "&#x2043;">
-<!ENTITY frasl "&#x2044;">
-<!ENTITY bsemi "&#x204F;">
-<!ENTITY qprime "&#x2057;">
-<!ENTITY MediumSpace "&#x205F;">
-<!ENTITY NoBreak "&#x2060;">
-<!ENTITY af "&#x2061;"><!ENTITY ApplyFunction "&#x2061;">
-<!ENTITY it "&#x2062;"><!ENTITY InvisibleTimes "&#x2062;">
-<!ENTITY ic "&#x2063;"><!ENTITY InvisibleComma "&#x2063;">
-<!ENTITY euro "&#x20AC;">
-<!ENTITY tdot " &#x20DB;"><!ENTITY TripleDot " &#x20DB;">
-<!ENTITY DotDot " &#x20DC;">
-<!ENTITY Copf "&#x2102;"><!ENTITY complexes "&#x2102;">
-<!ENTITY incare "&#x2105;">
-<!ENTITY gscr "&#x210A;">
-<!ENTITY Hscr "&#x210B;"><!ENTITY hamilt "&#x210B;"><!ENTITY HilbertSpace "&#x210B;">
-<!ENTITY Hfr "&#x210C;"><!ENTITY Poincareplane "&#x210C;">
-<!ENTITY Hopf "&#x210D;"><!ENTITY quaternions "&#x210D;">
-<!ENTITY planckh "&#x210E;">
-<!ENTITY planck "&#x210F;"><!ENTITY plankv "&#x210F;"><!ENTITY hbar "&#x210F;"><!ENTITY hslash "&#x210F;">
-<!ENTITY Iscr "&#x2110;"><!ENTITY imagline "&#x2110;">
-<!ENTITY image "&#x2111;"><!ENTITY Ifr "&#x2111;"><!ENTITY Im "&#x2111;"><!ENTITY imagpart "&#x2111;">
-<!ENTITY Lscr "&#x2112;"><!ENTITY lagran "&#x2112;"><!ENTITY Laplacetrf "&#x2112;">
-<!ENTITY ell "&#x2113;">
-<!ENTITY Nopf "&#x2115;"><!ENTITY naturals "&#x2115;">
-<!ENTITY numero "&#x2116;">
-<!ENTITY copysr "&#x2117;">
-<!ENTITY weierp "&#x2118;"><!ENTITY wp "&#x2118;">
-<!ENTITY Popf "&#x2119;"><!ENTITY primes "&#x2119;">
-<!ENTITY Qopf "&#x211A;"><!ENTITY rationals "&#x211A;">
-<!ENTITY Rscr "&#x211B;"><!ENTITY realine "&#x211B;">
-<!ENTITY real "&#x211C;"><!ENTITY Rfr "&#x211C;"><!ENTITY Re "&#x211C;"><!ENTITY realpart "&#x211C;">
-<!ENTITY Ropf "&#x211D;"><!ENTITY reals "&#x211D;">
-<!ENTITY rx "&#x211E;">
-<!ENTITY trade "&#x2122;">
-<!ENTITY Zopf "&#x2124;"><!ENTITY integers "&#x2124;">
-<!ENTITY ohm "&#x2126;">
-<!ENTITY mho "&#x2127;">
-<!ENTITY Zfr "&#x2128;"><!ENTITY zeetrf "&#x2128;">
-<!ENTITY iiota "&#x2129;">
-<!ENTITY angst "&#x212B;">
-<!ENTITY Bscr "&#x212C;"><!ENTITY bernou "&#x212C;"><!ENTITY Bernoullis "&#x212C;">
-<!ENTITY Cfr "&#x212D;"><!ENTITY Cayleys "&#x212D;">
-<!ENTITY escr "&#x212F;">
-<!ENTITY Escr "&#x2130;"><!ENTITY expectation "&#x2130;">
-<!ENTITY Fscr "&#x2131;"><!ENTITY Fouriertrf "&#x2131;">
-<!ENTITY Mscr "&#x2133;"><!ENTITY phmmat "&#x2133;"><!ENTITY Mellintrf "&#x2133;">
-<!ENTITY oscr "&#x2134;"><!ENTITY order "&#x2134;"><!ENTITY orderof "&#x2134;">
-<!ENTITY alefsym "&#x2135;"><!ENTITY aleph "&#x2135;">
-<!ENTITY beth "&#x2136;">
-<!ENTITY gimel "&#x2137;">
-<!ENTITY daleth "&#x2138;">
-<!ENTITY DD "&#x2145;"><!ENTITY CapitalDifferentialD "&#x2145;">
-<!ENTITY dd "&#x2146;"><!ENTITY DifferentialD "&#x2146;">
-<!ENTITY ee "&#x2147;"><!ENTITY ExponentialE "&#x2147;"><!ENTITY exponentiale "&#x2147;">
-<!ENTITY ii "&#x2148;"><!ENTITY ImaginaryI "&#x2148;">
-<!ENTITY frac13 "&#x2153;">
-<!ENTITY frac23 "&#x2154;">
-<!ENTITY frac15 "&#x2155;">
-<!ENTITY frac25 "&#x2156;">
-<!ENTITY frac35 "&#x2157;">
-<!ENTITY frac45 "&#x2158;">
-<!ENTITY frac16 "&#x2159;">
-<!ENTITY frac56 "&#x215A;">
-<!ENTITY frac18 "&#x215B;">
-<!ENTITY frac38 "&#x215C;">
-<!ENTITY frac58 "&#x215D;">
-<!ENTITY frac78 "&#x215E;">
-<!ENTITY larr "&#x2190;"><!ENTITY LeftArrow "&#x2190;"><!ENTITY leftarrow "&#x2190;">
-<!ENTITY uarr "&#x2191;"><!ENTITY UpArrow "&#x2191;"><!ENTITY uparrow "&#x2191;">
-<!ENTITY rarr "&#x2192;"><!ENTITY RightArrow "&#x2192;"><!ENTITY rightarrow "&#x2192;">
-<!ENTITY darr "&#x2193;"><!ENTITY DownArrow "&#x2193;"><!ENTITY downarrow "&#x2193;">
-<!ENTITY harr "&#x2194;"><!ENTITY LeftRightArrow "&#x2194;"><!ENTITY leftrightarrow "&#x2194;">
-<!ENTITY varr "&#x2195;"><!ENTITY UpDownArrow "&#x2195;"><!ENTITY updownarrow "&#x2195;">
-<!ENTITY nwarr "&#x2196;"><!ENTITY nwarrow "&#x2196;"><!ENTITY UpperLeftArrow "&#x2196;">
-<!ENTITY nearr "&#x2197;"><!ENTITY nearrow "&#x2197;"><!ENTITY UpperRightArrow "&#x2197;">
-<!ENTITY searr "&#x2198;"><!ENTITY LowerRightArrow "&#x2198;"><!ENTITY searrow "&#x2198;">
-<!ENTITY swarr "&#x2199;"><!ENTITY LowerLeftArrow "&#x2199;"><!ENTITY swarrow "&#x2199;">
-<!ENTITY nlarr "&#x219A;"><!ENTITY nleftarrow "&#x219A;">
-<!ENTITY nrarr "&#x219B;"><!ENTITY nrightarrow "&#x219B;">
-<!ENTITY rarrw "&#x219D;"><!ENTITY rightsquigarrow "&#x219D;">
-<!ENTITY nrarrw "&#x219D;&#x338;">
-<!ENTITY Larr "&#x219E;"><!ENTITY twoheadleftarrow "&#x219E;">
-<!ENTITY Uarr "&#x219F;">
-<!ENTITY Rarr "&#x21A0;"><!ENTITY twoheadrightarrow "&#x21A0;">
-<!ENTITY Darr "&#x21A1;">
-<!ENTITY larrtl "&#x21A2;"><!ENTITY leftarrowtail "&#x21A2;">
-<!ENTITY rarrtl "&#x21A3;"><!ENTITY rightarrowtail "&#x21A3;">
-<!ENTITY mapstoleft "&#x21A4;"><!ENTITY LeftTeeArrow "&#x21A4;">
-<!ENTITY mapstoup "&#x21A5;"><!ENTITY UpTeeArrow "&#x21A5;">
-<!ENTITY map "&#x21A6;"><!ENTITY mapsto "&#x21A6;"><!ENTITY RightTeeArrow "&#x21A6;">
-<!ENTITY mapstodown "&#x21A7;"><!ENTITY DownTeeArrow "&#x21A7;">
-<!ENTITY larrhk "&#x21A9;"><!ENTITY hookleftarrow "&#x21A9;">
-<!ENTITY rarrhk "&#x21AA;"><!ENTITY hookrightarrow "&#x21AA;">
-<!ENTITY larrlp "&#x21AB;"><!ENTITY looparrowleft "&#x21AB;">
-<!ENTITY rarrlp "&#x21AC;"><!ENTITY looparrowright "&#x21AC;">
-<!ENTITY harrw "&#x21AD;"><!ENTITY leftrightsquigarrow "&#x21AD;">
-<!ENTITY nharr "&#x21AE;"><!ENTITY nleftrightarrow "&#x21AE;">
-<!ENTITY lsh "&#x21B0;"><!ENTITY Lsh "&#x21B0;">
-<!ENTITY rsh "&#x21B1;"><!ENTITY Rsh "&#x21B1;">
-<!ENTITY ldsh "&#x21B2;">
-<!ENTITY rdsh "&#x21B3;">
-<!ENTITY crarr "&#x21B5;">
-<!ENTITY cularr "&#x21B6;"><!ENTITY curvearrowleft "&#x21B6;">
-<!ENTITY curarr "&#x21B7;"><!ENTITY curvearrowright "&#x21B7;">
-<!ENTITY olarr "&#x21BA;"><!ENTITY circlearrowleft "&#x21BA;">
-<!ENTITY orarr "&#x21BB;"><!ENTITY circlearrowright "&#x21BB;">
-<!ENTITY lharu "&#x21BC;"><!ENTITY leftharpoonup "&#x21BC;"><!ENTITY LeftVector "&#x21BC;">
-<!ENTITY lhard "&#x21BD;"><!ENTITY DownLeftVector "&#x21BD;"><!ENTITY leftharpoondown "&#x21BD;">
-<!ENTITY uharr "&#x21BE;"><!ENTITY RightUpVector "&#x21BE;"><!ENTITY upharpoonright "&#x21BE;">
-<!ENTITY uharl "&#x21BF;"><!ENTITY LeftUpVector "&#x21BF;"><!ENTITY upharpoonleft "&#x21BF;">
-<!ENTITY rharu "&#x21C0;"><!ENTITY rightharpoonup "&#x21C0;"><!ENTITY RightVector "&#x21C0;">
-<!ENTITY rhard "&#x21C1;"><!ENTITY DownRightVector "&#x21C1;"><!ENTITY rightharpoondown "&#x21C1;">
-<!ENTITY dharr "&#x21C2;"><!ENTITY downharpoonright "&#x21C2;"><!ENTITY RightDownVector "&#x21C2;">
-<!ENTITY dharl "&#x21C3;"><!ENTITY downharpoonleft "&#x21C3;"><!ENTITY LeftDownVector "&#x21C3;">
-<!ENTITY rlarr "&#x21C4;"><!ENTITY RightArrowLeftArrow "&#x21C4;"><!ENTITY rightleftarrows "&#x21C4;">
-<!ENTITY udarr "&#x21C5;"><!ENTITY UpArrowDownArrow "&#x21C5;">
-<!ENTITY lrarr "&#x21C6;"><!ENTITY LeftArrowRightArrow "&#x21C6;"><!ENTITY leftrightarrows "&#x21C6;">
-<!ENTITY llarr "&#x21C7;"><!ENTITY leftleftarrows "&#x21C7;">
-<!ENTITY uuarr "&#x21C8;"><!ENTITY upuparrows "&#x21C8;">
-<!ENTITY rrarr "&#x21C9;"><!ENTITY rightrightarrows "&#x21C9;">
-<!ENTITY ddarr "&#x21CA;"><!ENTITY downdownarrows "&#x21CA;">
-<!ENTITY lrhar "&#x21CB;"><!ENTITY leftrightharpoons "&#x21CB;"><!ENTITY ReverseEquilibrium "&#x21CB;">
-<!ENTITY rlhar "&#x21CC;"><!ENTITY Equilibrium "&#x21CC;"><!ENTITY rightleftharpoons "&#x21CC;">
-<!ENTITY nlArr "&#x21CD;"><!ENTITY nLeftarrow "&#x21CD;">
-<!ENTITY nhArr "&#x21CE;"><!ENTITY nLeftrightarrow "&#x21CE;">
-<!ENTITY nrArr "&#x21CF;"><!ENTITY nRightarrow "&#x21CF;">
-<!ENTITY lArr "&#x21D0;"><!ENTITY DoubleLeftArrow "&#x21D0;"><!ENTITY Leftarrow "&#x21D0;">
-<!ENTITY uArr "&#x21D1;"><!ENTITY DoubleUpArrow "&#x21D1;"><!ENTITY Uparrow "&#x21D1;">
-<!ENTITY rArr "&#x21D2;"><!ENTITY DoubleRightArrow "&#x21D2;"><!ENTITY Implies "&#x21D2;"><!ENTITY Rightarrow "&#x21D2;">
-<!ENTITY dArr "&#x21D3;"><!ENTITY DoubleDownArrow "&#x21D3;"><!ENTITY Downarrow "&#x21D3;">
-<!ENTITY hArr "&#x21D4;"><!ENTITY iff "&#x21D4;"><!ENTITY DoubleLeftRightArrow "&#x21D4;"><!ENTITY Leftrightarrow "&#x21D4;">
-<!ENTITY vArr "&#x21D5;"><!ENTITY DoubleUpDownArrow "&#x21D5;"><!ENTITY Updownarrow "&#x21D5;">
-<!ENTITY nwArr "&#x21D6;">
-<!ENTITY neArr "&#x21D7;">
-<!ENTITY seArr "&#x21D8;">
-<!ENTITY swArr "&#x21D9;">
-<!ENTITY lAarr "&#x21DA;"><!ENTITY Lleftarrow "&#x21DA;">
-<!ENTITY rAarr "&#x21DB;"><!ENTITY Rrightarrow "&#x21DB;">
-<!ENTITY zigrarr "&#x21DD;">
-<!ENTITY larrb "&#x21E4;"><!ENTITY LeftArrowBar "&#x21E4;">
-<!ENTITY rarrb "&#x21E5;"><!ENTITY RightArrowBar "&#x21E5;">
-<!ENTITY duarr "&#x21F5;"><!ENTITY DownArrowUpArrow "&#x21F5;">
-<!ENTITY loarr "&#x21FD;">
-<!ENTITY roarr "&#x21FE;">
-<!ENTITY hoarr "&#x21FF;">
-<!ENTITY forall "&#x2200;"><!ENTITY ForAll "&#x2200;">
-<!ENTITY comp "&#x2201;"><!ENTITY complement "&#x2201;">
-<!ENTITY part "&#x2202;"><!ENTITY PartialD "&#x2202;">
-<!ENTITY npart "&#x2202;&#x338;">
-<!ENTITY exist "&#x2203;"><!ENTITY Exists "&#x2203;">
-<!ENTITY nexist "&#x2204;"><!ENTITY nexists "&#x2204;"><!ENTITY NotExists "&#x2204;">
-<!ENTITY empty "&#x2205;"><!ENTITY emptyv "&#x2205;"><!ENTITY emptyset "&#x2205;"><!ENTITY varnothing "&#x2205;">
-<!ENTITY nabla "&#x2207;"><!ENTITY Del "&#x2207;">
-<!ENTITY isin "&#x2208;"><!ENTITY isinv "&#x2208;"><!ENTITY Element "&#x2208;"><!ENTITY in "&#x2208;">
-<!ENTITY notin "&#x2209;"><!ENTITY notinva "&#x2209;"><!ENTITY NotElement "&#x2209;">
-<!ENTITY ni "&#x220B;"><!ENTITY niv "&#x220B;"><!ENTITY ReverseElement "&#x220B;"><!ENTITY SuchThat "&#x220B;">
-<!ENTITY notni "&#x220C;"><!ENTITY notniva "&#x220C;"><!ENTITY NotReverseElement "&#x220C;">
-<!ENTITY prod "&#x220F;"><!ENTITY Product "&#x220F;">
-<!ENTITY coprod "&#x2210;"><!ENTITY Coproduct "&#x2210;">
-<!ENTITY sum "&#x2211;"><!ENTITY Sum "&#x2211;">
-<!ENTITY minus "&#x2212;">
-<!ENTITY mnplus "&#x2213;"><!ENTITY MinusPlus "&#x2213;"><!ENTITY mp "&#x2213;">
-<!ENTITY plusdo "&#x2214;"><!ENTITY dotplus "&#x2214;">
-<!ENTITY setmn "&#x2216;"><!ENTITY ssetmn "&#x2216;"><!ENTITY Backslash "&#x2216;"><!ENTITY setminus "&#x2216;"><!ENTITY smallsetminus "&#x2216;">
-<!ENTITY lowast "&#x2217;">
-<!ENTITY compfn "&#x2218;"><!ENTITY SmallCircle "&#x2218;">
-<!ENTITY radic "&#x221A;"><!ENTITY Sqrt "&#x221A;">
-<!ENTITY prop "&#x221D;"><!ENTITY vprop "&#x221D;"><!ENTITY Proportional "&#x221D;"><!ENTITY propto "&#x221D;"><!ENTITY varpropto "&#x221D;">
-<!ENTITY infin "&#x221E;">
-<!ENTITY angrt "&#x221F;">
-<!ENTITY ang "&#x2220;"><!ENTITY angle "&#x2220;">
-<!ENTITY nang "&#x2220;&#x20D2;">
-<!ENTITY angmsd "&#x2221;"><!ENTITY measuredangle "&#x2221;">
-<!ENTITY angsph "&#x2222;">
-<!ENTITY mid "&#x2223;"><!ENTITY smid "&#x2223;"><!ENTITY shortmid "&#x2223;"><!ENTITY VerticalBar "&#x2223;">
-<!ENTITY nmid "&#x2224;"><!ENTITY nsmid "&#x2224;"><!ENTITY NotVerticalBar "&#x2224;"><!ENTITY nshortmid "&#x2224;">
-<!ENTITY spar "&#x2225;"><!ENTITY par "&#x2225;"><!ENTITY DoubleVerticalBar "&#x2225;"><!ENTITY parallel "&#x2225;"><!ENTITY shortparallel "&#x2225;">
-<!ENTITY npar "&#x2226;"><!ENTITY nspar "&#x2226;"><!ENTITY NotDoubleVerticalBar "&#x2226;"><!ENTITY nparallel "&#x2226;"><!ENTITY nshortparallel "&#x2226;">
-<!ENTITY and "&#x2227;"><!ENTITY wedge "&#x2227;">
-<!ENTITY or "&#x2228;"><!ENTITY vee "&#x2228;">
-<!ENTITY cap "&#x2229;">
-<!ENTITY caps "&#x2229;&#xFE00;">
-<!ENTITY cup "&#x222A;">
-<!ENTITY cups "&#x222A;&#xFE00;">
-<!ENTITY int "&#x222B;"><!ENTITY Integral "&#x222B;">
-<!ENTITY Int "&#x222C;">
-<!ENTITY tint "&#x222D;"><!ENTITY iiint "&#x222D;">
-<!ENTITY conint "&#x222E;"><!ENTITY ContourIntegral "&#x222E;"><!ENTITY oint "&#x222E;">
-<!ENTITY Conint "&#x222F;"><!ENTITY DoubleContourIntegral "&#x222F;">
-<!ENTITY Cconint "&#x2230;">
-<!ENTITY cwint "&#x2231;">
-<!ENTITY cwconint "&#x2232;"><!ENTITY ClockwiseContourIntegral "&#x2232;">
-<!ENTITY awconint "&#x2233;"><!ENTITY CounterClockwiseContourIntegral "&#x2233;">
-<!ENTITY there4 "&#x2234;"><!ENTITY Therefore "&#x2234;"><!ENTITY therefore "&#x2234;">
-<!ENTITY becaus "&#x2235;"><!ENTITY Because "&#x2235;"><!ENTITY because "&#x2235;">
-<!ENTITY ratio "&#x2236;">
-<!ENTITY Colon "&#x2237;"><!ENTITY Proportion "&#x2237;">
-<!ENTITY minusd "&#x2238;"><!ENTITY dotminus "&#x2238;">
-<!ENTITY mDDot "&#x223A;">
-<!ENTITY homtht "&#x223B;">
-<!ENTITY sim "&#x223C;"><!ENTITY thksim "&#x223C;"><!ENTITY thicksim "&#x223C;"><!ENTITY Tilde "&#x223C;">
-<!ENTITY nvsim "&#x223C;&#x20D2;">
-<!ENTITY bsim "&#x223D;"><!ENTITY backsim "&#x223D;">
-<!ENTITY ac "&#x223E;"><!ENTITY mstpos "&#x223E;">
-<!ENTITY acE "&#x223E;&#x333;">
-<!ENTITY acd "&#x223F;">
-<!ENTITY wreath "&#x2240;"><!ENTITY VerticalTilde "&#x2240;"><!ENTITY wr "&#x2240;">
-<!ENTITY nsim "&#x2241;"><!ENTITY NotTilde "&#x2241;">
-<!ENTITY esim "&#x2242;"><!ENTITY eqsim "&#x2242;"><!ENTITY EqualTilde "&#x2242;">
-<!ENTITY nesim "&#x2242;&#x338;"><!ENTITY NotEqualTilde "&#x2242;&#x338;">
-<!ENTITY sime "&#x2243;"><!ENTITY simeq "&#x2243;"><!ENTITY TildeEqual "&#x2243;">
-<!ENTITY nsime "&#x2244;"><!ENTITY NotTildeEqual "&#x2244;"><!ENTITY nsimeq "&#x2244;">
-<!ENTITY cong "&#x2245;"><!ENTITY TildeFullEqual "&#x2245;">
-<!ENTITY simne "&#x2246;">
-<!ENTITY ncong "&#x2247;"><!ENTITY NotTildeFullEqual "&#x2247;">
-<!ENTITY asymp "&#x2248;"><!ENTITY thkap "&#x2248;"><!ENTITY ap "&#x2248;"><!ENTITY approx "&#x2248;"><!ENTITY thickapprox "&#x2248;"><!ENTITY TildeTilde "&#x2248;">
-<!ENTITY nap "&#x2249;"><!ENTITY napprox "&#x2249;"><!ENTITY NotTildeTilde "&#x2249;">
-<!ENTITY ape "&#x224A;"><!ENTITY approxeq "&#x224A;">
-<!ENTITY apid "&#x224B;">
-<!ENTITY napid "&#x224B;&#x338;">
-<!ENTITY bcong "&#x224C;"><!ENTITY backcong "&#x224C;">
-<!ENTITY asympeq "&#x224D;"><!ENTITY CupCap "&#x224D;">
-<!ENTITY nvap "&#x224D;&#x20D2;">
-<!ENTITY bump "&#x224E;"><!ENTITY Bumpeq "&#x224E;"><!ENTITY HumpDownHump "&#x224E;">
-<!ENTITY nbump "&#x224E;&#x338;"><!ENTITY NotHumpDownHump "&#x224E;&#x338;">
-<!ENTITY bumpe "&#x224F;"><!ENTITY bumpeq "&#x224F;"><!ENTITY HumpEqual "&#x224F;">
-<!ENTITY nbumpe "&#x224F;&#x338;"><!ENTITY NotHumpEqual "&#x224F;&#x338;">
-<!ENTITY esdot "&#x2250;"><!ENTITY doteq "&#x2250;"><!ENTITY DotEqual "&#x2250;">
-<!ENTITY nedot "&#x2250;&#x338;">
-<!ENTITY eDot "&#x2251;"><!ENTITY doteqdot "&#x2251;">
-<!ENTITY efDot "&#x2252;"><!ENTITY fallingdotseq "&#x2252;">
-<!ENTITY erDot "&#x2253;"><!ENTITY risingdotseq "&#x2253;">
-<!ENTITY colone "&#x2254;"><!ENTITY Assign "&#x2254;"><!ENTITY coloneq "&#x2254;">
-<!ENTITY ecolon "&#x2255;"><!ENTITY eqcolon "&#x2255;">
-<!ENTITY ecir "&#x2256;"><!ENTITY eqcirc "&#x2256;">
-<!ENTITY cire "&#x2257;"><!ENTITY circeq "&#x2257;">
-<!ENTITY wedgeq "&#x2259;">
-<!ENTITY veeeq "&#x225A;">
-<!ENTITY trie "&#x225C;"><!ENTITY triangleq "&#x225C;">
-<!ENTITY equest "&#x225F;"><!ENTITY questeq "&#x225F;">
-<!ENTITY ne "&#x2260;"><!ENTITY NotEqual "&#x2260;">
-<!ENTITY equiv "&#x2261;"><!ENTITY Congruent "&#x2261;">
-<!ENTITY bnequiv "&#x2261;&#x20E5;">
-<!ENTITY nequiv "&#x2262;"><!ENTITY NotCongruent "&#x2262;">
-<!ENTITY le "&#x2264;"><!ENTITY leq "&#x2264;">
-<!ENTITY nvle "&#x2264;&#x20D2;">
-<!ENTITY ge "&#x2265;"><!ENTITY geq "&#x2265;"><!ENTITY GreaterEqual "&#x2265;">
-<!ENTITY nvge "&#x2265;&#x20D2;">
-<!ENTITY lE "&#x2266;"><!ENTITY leqq "&#x2266;"><!ENTITY LessFullEqual "&#x2266;">
-<!ENTITY nlE "&#x2266;&#x338;"><!ENTITY nleqq "&#x2266;&#x338;"><!ENTITY NotGreaterFullEqual "&#x2266;&#x338;">
-<!ENTITY gE "&#x2267;"><!ENTITY geqq "&#x2267;"><!ENTITY GreaterFullEqual "&#x2267;">
-<!ENTITY ngE "&#x2267;&#x338;"><!ENTITY ngeqq "&#x2267;&#x338;">
-<!ENTITY lnE "&#x2268;"><!ENTITY lneqq "&#x2268;">
-<!ENTITY lvnE "&#x2268;&#xFE00;"><!ENTITY lvertneqq "&#x2268;&#xFE00;">
-<!ENTITY gnE "&#x2269;"><!ENTITY gneqq "&#x2269;">
-<!ENTITY gvnE "&#x2269;&#xFE00;"><!ENTITY gvertneqq "&#x2269;&#xFE00;">
-<!ENTITY Lt "&#x226A;"><!ENTITY ll "&#x226A;"><!ENTITY NestedLessLess "&#x226A;">
-<!ENTITY nLt "&#x226A;&#x20D2;">
-<!ENTITY nLtv "&#x226A;&#x338;"><!ENTITY NotLessLess "&#x226A;&#x338;">
-<!ENTITY Gt "&#x226B;"><!ENTITY gg "&#x226B;"><!ENTITY NestedGreaterGreater "&#x226B;">
-<!ENTITY nGt "&#x226B;&#x20D2;">
-<!ENTITY nGtv "&#x226B;&#x338;"><!ENTITY NotGreaterGreater "&#x226B;&#x338;">
-<!ENTITY twixt "&#x226C;"><!ENTITY between "&#x226C;">
-<!ENTITY NotCupCap "&#x226D;">
-<!ENTITY nlt "&#x226E;"><!ENTITY nless "&#x226E;"><!ENTITY NotLess "&#x226E;">
-<!ENTITY ngt "&#x226F;"><!ENTITY ngtr "&#x226F;"><!ENTITY NotGreater "&#x226F;">
-<!ENTITY nle "&#x2270;"><!ENTITY nleq "&#x2270;"><!ENTITY NotLessEqual "&#x2270;">
-<!ENTITY nge "&#x2271;"><!ENTITY ngeq "&#x2271;"><!ENTITY NotGreaterEqual "&#x2271;">
-<!ENTITY lsim "&#x2272;"><!ENTITY lesssim "&#x2272;"><!ENTITY LessTilde "&#x2272;">
-<!ENTITY gsim "&#x2273;"><!ENTITY GreaterTilde "&#x2273;"><!ENTITY gtrsim "&#x2273;">
-<!ENTITY nlsim "&#x2274;"><!ENTITY NotLessTilde "&#x2274;">
-<!ENTITY ngsim "&#x2275;"><!ENTITY NotGreaterTilde "&#x2275;">
-<!ENTITY lg "&#x2276;"><!ENTITY LessGreater "&#x2276;"><!ENTITY lessgtr "&#x2276;">
-<!ENTITY gl "&#x2277;"><!ENTITY GreaterLess "&#x2277;"><!ENTITY gtrless "&#x2277;">
-<!ENTITY ntlg "&#x2278;"><!ENTITY NotLessGreater "&#x2278;">
-<!ENTITY ntgl "&#x2279;"><!ENTITY NotGreaterLess "&#x2279;">
-<!ENTITY pr "&#x227A;"><!ENTITY prec "&#x227A;"><!ENTITY Precedes "&#x227A;">
-<!ENTITY sc "&#x227B;"><!ENTITY succ "&#x227B;"><!ENTITY Succeeds "&#x227B;">
-<!ENTITY prcue "&#x227C;"><!ENTITY preccurlyeq "&#x227C;"><!ENTITY PrecedesSlantEqual "&#x227C;">
-<!ENTITY sccue "&#x227D;"><!ENTITY succcurlyeq "&#x227D;"><!ENTITY SucceedsSlantEqual "&#x227D;">
-<!ENTITY prsim "&#x227E;"><!ENTITY PrecedesTilde "&#x227E;"><!ENTITY precsim "&#x227E;">
-<!ENTITY scsim "&#x227F;"><!ENTITY SucceedsTilde "&#x227F;"><!ENTITY succsim "&#x227F;">
-<!ENTITY NotSucceedsTilde "&#x227F;&#x338;">
-<!ENTITY npr "&#x2280;"><!ENTITY NotPrecedes "&#x2280;"><!ENTITY nprec "&#x2280;">
-<!ENTITY nsc "&#x2281;"><!ENTITY NotSucceeds "&#x2281;"><!ENTITY nsucc "&#x2281;">
-<!ENTITY sub "&#x2282;"><!ENTITY subset "&#x2282;">
-<!ENTITY vnsub "&#x2282;&#x20D2;"><!ENTITY NotSubset "&#x2282;&#x20D2;"><!ENTITY nsubset "&#x2282;&#x20D2;">
-<!ENTITY sup "&#x2283;"><!ENTITY Superset "&#x2283;"><!ENTITY supset "&#x2283;">
-<!ENTITY vnsup "&#x2283;&#x20D2;"><!ENTITY NotSuperset "&#x2283;&#x20D2;"><!ENTITY nsupset "&#x2283;&#x20D2;">
-<!ENTITY suphsol "&#x2283;&#x2F;">
-<!ENTITY nsub "&#x2284;">
-<!ENTITY nsup "&#x2285;">
-<!ENTITY sube "&#x2286;"><!ENTITY subseteq "&#x2286;"><!ENTITY SubsetEqual "&#x2286;">
-<!ENTITY supe "&#x2287;"><!ENTITY SupersetEqual "&#x2287;"><!ENTITY supseteq "&#x2287;">
-<!ENTITY nsube "&#x2288;"><!ENTITY NotSubsetEqual "&#x2288;"><!ENTITY nsubseteq "&#x2288;">
-<!ENTITY nsupe "&#x2289;"><!ENTITY NotSupersetEqual "&#x2289;"><!ENTITY nsupseteq "&#x2289;">
-<!ENTITY subne "&#x228A;"><!ENTITY subsetneq "&#x228A;">
-<!ENTITY vsubne "&#x228A;&#xFE00;"><!ENTITY varsubsetneq "&#x228A;&#xFE00;">
-<!ENTITY supne "&#x228B;"><!ENTITY supsetneq "&#x228B;">
-<!ENTITY vsupne "&#x228B;&#xFE00;"><!ENTITY varsupsetneq "&#x228B;&#xFE00;">
-<!ENTITY cupdot "&#x228D;">
-<!ENTITY uplus "&#x228E;"><!ENTITY UnionPlus "&#x228E;">
-<!ENTITY sqsub "&#x228F;"><!ENTITY sqsubset "&#x228F;"><!ENTITY SquareSubset "&#x228F;">
-<!ENTITY NotSquareSubset "&#x228F;&#x338;">
-<!ENTITY sqsup "&#x2290;"><!ENTITY sqsupset "&#x2290;"><!ENTITY SquareSuperset "&#x2290;">
-<!ENTITY NotSquareSuperset "&#x2290;&#x338;">
-<!ENTITY sqsube "&#x2291;"><!ENTITY sqsubseteq "&#x2291;"><!ENTITY SquareSubsetEqual "&#x2291;">
-<!ENTITY sqsupe "&#x2292;"><!ENTITY sqsupseteq "&#x2292;"><!ENTITY SquareSupersetEqual "&#x2292;">
-<!ENTITY sqcap "&#x2293;"><!ENTITY SquareIntersection "&#x2293;">
-<!ENTITY sqcaps "&#x2293;&#xFE00;">
-<!ENTITY sqcup "&#x2294;"><!ENTITY SquareUnion "&#x2294;">
-<!ENTITY sqcups "&#x2294;&#xFE00;">
-<!ENTITY oplus "&#x2295;"><!ENTITY CirclePlus "&#x2295;">
-<!ENTITY ominus "&#x2296;"><!ENTITY CircleMinus "&#x2296;">
-<!ENTITY otimes "&#x2297;"><!ENTITY CircleTimes "&#x2297;">
-<!ENTITY osol "&#x2298;">
-<!ENTITY odot "&#x2299;"><!ENTITY CircleDot "&#x2299;">
-<!ENTITY ocir "&#x229A;"><!ENTITY circledcirc "&#x229A;">
-<!ENTITY oast "&#x229B;"><!ENTITY circledast "&#x229B;">
-<!ENTITY odash "&#x229D;"><!ENTITY circleddash "&#x229D;">
-<!ENTITY plusb "&#x229E;"><!ENTITY boxplus "&#x229E;">
-<!ENTITY minusb "&#x229F;"><!ENTITY boxminus "&#x229F;">
-<!ENTITY timesb "&#x22A0;"><!ENTITY boxtimes "&#x22A0;">
-<!ENTITY sdotb "&#x22A1;"><!ENTITY dotsquare "&#x22A1;">
-<!ENTITY vdash "&#x22A2;"><!ENTITY RightTee "&#x22A2;">
-<!ENTITY dashv "&#x22A3;"><!ENTITY LeftTee "&#x22A3;">
-<!ENTITY top "&#x22A4;"><!ENTITY DownTee "&#x22A4;">
-<!ENTITY perp "&#x22A5;"><!ENTITY bottom "&#x22A5;"><!ENTITY bot "&#x22A5;"><!ENTITY UpTee "&#x22A5;">
-<!ENTITY models "&#x22A7;">
-<!ENTITY vDash "&#x22A8;"><!ENTITY DoubleRightTee "&#x22A8;">
-<!ENTITY Vdash "&#x22A9;">
-<!ENTITY Vvdash "&#x22AA;">
-<!ENTITY VDash "&#x22AB;">
-<!ENTITY nvdash "&#x22AC;">
-<!ENTITY nvDash "&#x22AD;">
-<!ENTITY nVdash "&#x22AE;">
-<!ENTITY nVDash "&#x22AF;">
-<!ENTITY prurel "&#x22B0;">
-<!ENTITY vltri "&#x22B2;"><!ENTITY LeftTriangle "&#x22B2;"><!ENTITY vartriangleleft "&#x22B2;">
-<!ENTITY vrtri "&#x22B3;"><!ENTITY RightTriangle "&#x22B3;"><!ENTITY vartriangleright "&#x22B3;">
-<!ENTITY ltrie "&#x22B4;"><!ENTITY LeftTriangleEqual "&#x22B4;"><!ENTITY trianglelefteq "&#x22B4;">
-<!ENTITY nvltrie "&#x22B4;&#x20D2;">
-<!ENTITY rtrie "&#x22B5;"><!ENTITY RightTriangleEqual "&#x22B5;"><!ENTITY trianglerighteq "&#x22B5;">
-<!ENTITY nvrtrie "&#x22B5;&#x20D2;">
-<!ENTITY origof "&#x22B6;">
-<!ENTITY imof "&#x22B7;">
-<!ENTITY mumap "&#x22B8;"><!ENTITY multimap "&#x22B8;">
-<!ENTITY hercon "&#x22B9;">
-<!ENTITY intcal "&#x22BA;"><!ENTITY intercal "&#x22BA;">
-<!ENTITY veebar "&#x22BB;">
-<!ENTITY barvee "&#x22BD;">
-<!ENTITY angrtvb "&#x22BE;">
-<!ENTITY lrtri "&#x22BF;">
-<!ENTITY xwedge "&#x22C0;"><!ENTITY bigwedge "&#x22C0;"><!ENTITY Wedge "&#x22C0;">
-<!ENTITY xvee "&#x22C1;"><!ENTITY bigvee "&#x22C1;"><!ENTITY Vee "&#x22C1;">
-<!ENTITY xcap "&#x22C2;"><!ENTITY bigcap "&#x22C2;"><!ENTITY Intersection "&#x22C2;">
-<!ENTITY xcup "&#x22C3;"><!ENTITY bigcup "&#x22C3;"><!ENTITY Union "&#x22C3;">
-<!ENTITY diam "&#x22C4;"><!ENTITY Diamond "&#x22C4;"><!ENTITY diamond "&#x22C4;">
-<!ENTITY sdot "&#x22C5;">
-<!ENTITY sstarf "&#x22C6;"><!ENTITY Star "&#x22C6;">
-<!ENTITY divonx "&#x22C7;"><!ENTITY divideontimes "&#x22C7;">
-<!ENTITY bowtie "&#x22C8;">
-<!ENTITY ltimes "&#x22C9;">
-<!ENTITY rtimes "&#x22CA;">
-<!ENTITY lthree "&#x22CB;"><!ENTITY leftthreetimes "&#x22CB;">
-<!ENTITY rthree "&#x22CC;"><!ENTITY rightthreetimes "&#x22CC;">
-<!ENTITY bsime "&#x22CD;"><!ENTITY backsimeq "&#x22CD;">
-<!ENTITY cuvee "&#x22CE;"><!ENTITY curlyvee "&#x22CE;">
-<!ENTITY cuwed "&#x22CF;"><!ENTITY curlywedge "&#x22CF;">
-<!ENTITY Sub "&#x22D0;"><!ENTITY Subset "&#x22D0;">
-<!ENTITY Sup "&#x22D1;"><!ENTITY Supset "&#x22D1;">
-<!ENTITY Cap "&#x22D2;">
-<!ENTITY Cup "&#x22D3;">
-<!ENTITY fork "&#x22D4;"><!ENTITY pitchfork "&#x22D4;">
-<!ENTITY epar "&#x22D5;">
-<!ENTITY ltdot "&#x22D6;"><!ENTITY lessdot "&#x22D6;">
-<!ENTITY gtdot "&#x22D7;"><!ENTITY gtrdot "&#x22D7;">
-<!ENTITY Ll "&#x22D8;">
-<!ENTITY nLl "&#x22D8;&#x338;">
-<!ENTITY Gg "&#x22D9;"><!ENTITY ggg "&#x22D9;">
-<!ENTITY nGg "&#x22D9;&#x338;">
-<!ENTITY leg "&#x22DA;"><!ENTITY lesseqgtr "&#x22DA;"><!ENTITY LessEqualGreater "&#x22DA;">
-<!ENTITY lesg "&#x22DA;&#xFE00;">
-<!ENTITY gel "&#x22DB;"><!ENTITY GreaterEqualLess "&#x22DB;"><!ENTITY gtreqless "&#x22DB;">
-<!ENTITY gesl "&#x22DB;&#xFE00;">
-<!ENTITY cuepr "&#x22DE;"><!ENTITY curlyeqprec "&#x22DE;">
-<!ENTITY cuesc "&#x22DF;"><!ENTITY curlyeqsucc "&#x22DF;">
-<!ENTITY nprcue "&#x22E0;"><!ENTITY NotPrecedesSlantEqual "&#x22E0;">
-<!ENTITY nsccue "&#x22E1;"><!ENTITY NotSucceedsSlantEqual "&#x22E1;">
-<!ENTITY nsqsube "&#x22E2;"><!ENTITY NotSquareSubsetEqual "&#x22E2;">
-<!ENTITY nsqsupe "&#x22E3;"><!ENTITY NotSquareSupersetEqual "&#x22E3;">
-<!ENTITY lnsim "&#x22E6;">
-<!ENTITY gnsim "&#x22E7;">
-<!ENTITY prnsim "&#x22E8;"><!ENTITY precnsim "&#x22E8;">
-<!ENTITY scnsim "&#x22E9;"><!ENTITY succnsim "&#x22E9;">
-<!ENTITY nltri "&#x22EA;"><!ENTITY NotLeftTriangle "&#x22EA;"><!ENTITY ntriangleleft "&#x22EA;">
-<!ENTITY nrtri "&#x22EB;"><!ENTITY NotRightTriangle "&#x22EB;"><!ENTITY ntriangleright "&#x22EB;">
-<!ENTITY nltrie "&#x22EC;"><!ENTITY NotLeftTriangleEqual "&#x22EC;"><!ENTITY ntrianglelefteq "&#x22EC;">
-<!ENTITY nrtrie "&#x22ED;"><!ENTITY NotRightTriangleEqual "&#x22ED;"><!ENTITY ntrianglerighteq "&#x22ED;">
-<!ENTITY vellip "&#x22EE;">
-<!ENTITY ctdot "&#x22EF;">
-<!ENTITY utdot "&#x22F0;">
-<!ENTITY dtdot "&#x22F1;">
-<!ENTITY disin "&#x22F2;">
-<!ENTITY isinsv "&#x22F3;">
-<!ENTITY isins "&#x22F4;">
-<!ENTITY isindot "&#x22F5;">
-<!ENTITY notindot "&#x22F5;&#x338;">
-<!ENTITY notinvc "&#x22F6;">
-<!ENTITY notinvb "&#x22F7;">
-<!ENTITY isinE "&#x22F9;">
-<!ENTITY notinE "&#x22F9;&#x338;">
-<!ENTITY nisd "&#x22FA;">
-<!ENTITY xnis "&#x22FB;">
-<!ENTITY nis "&#x22FC;">
-<!ENTITY notnivc "&#x22FD;">
-<!ENTITY notnivb "&#x22FE;">
-<!ENTITY barwed "&#x2305;"><!ENTITY barwedge "&#x2305;">
-<!ENTITY Barwed "&#x2306;"><!ENTITY doublebarwedge "&#x2306;">
-<!ENTITY lceil "&#x2308;"><!ENTITY LeftCeiling "&#x2308;">
-<!ENTITY rceil "&#x2309;"><!ENTITY RightCeiling "&#x2309;">
-<!ENTITY lfloor "&#x230A;"><!ENTITY LeftFloor "&#x230A;">
-<!ENTITY rfloor "&#x230B;"><!ENTITY RightFloor "&#x230B;">
-<!ENTITY drcrop "&#x230C;">
-<!ENTITY dlcrop "&#x230D;">
-<!ENTITY urcrop "&#x230E;">
-<!ENTITY ulcrop "&#x230F;">
-<!ENTITY bnot "&#x2310;">
-<!ENTITY profline "&#x2312;">
-<!ENTITY profsurf "&#x2313;">
-<!ENTITY telrec "&#x2315;">
-<!ENTITY target "&#x2316;">
-<!ENTITY ulcorn "&#x231C;"><!ENTITY ulcorner "&#x231C;">
-<!ENTITY urcorn "&#x231D;"><!ENTITY urcorner "&#x231D;">
-<!ENTITY dlcorn "&#x231E;"><!ENTITY llcorner "&#x231E;">
-<!ENTITY drcorn "&#x231F;"><!ENTITY lrcorner "&#x231F;">
-<!ENTITY frown "&#x2322;"><!ENTITY sfrown "&#x2322;">
-<!ENTITY smile "&#x2323;"><!ENTITY ssmile "&#x2323;">
-<!ENTITY cylcty "&#x232D;">
-<!ENTITY profalar "&#x232E;">
-<!ENTITY topbot "&#x2336;">
-<!ENTITY ovbar "&#x233D;">
-<!ENTITY solbar "&#x233F;">
-<!ENTITY angzarr "&#x237C;">
-<!ENTITY lmoust "&#x23B0;"><!ENTITY lmoustache "&#x23B0;">
-<!ENTITY rmoust "&#x23B1;"><!ENTITY rmoustache "&#x23B1;">
-<!ENTITY tbrk "&#x23B4;"><!ENTITY OverBracket "&#x23B4;">
-<!ENTITY bbrk "&#x23B5;"><!ENTITY UnderBracket "&#x23B5;">
-<!ENTITY bbrktbrk "&#x23B6;">
-<!ENTITY blank "&#x2423;">
-<!ENTITY oS "&#x24C8;"><!ENTITY circledS "&#x24C8;">
-<!ENTITY boxh "&#x2500;"><!ENTITY HorizontalLine "&#x2500;">
-<!ENTITY boxv "&#x2502;">
-<!ENTITY boxdr "&#x250C;">
-<!ENTITY boxdl "&#x2510;">
-<!ENTITY boxur "&#x2514;">
-<!ENTITY boxul "&#x2518;">
-<!ENTITY boxvr "&#x251C;">
-<!ENTITY boxvl "&#x2524;">
-<!ENTITY boxhd "&#x252C;">
-<!ENTITY boxhu "&#x2534;">
-<!ENTITY boxvh "&#x253C;">
-<!ENTITY boxH "&#x2550;">
-<!ENTITY boxV "&#x2551;">
-<!ENTITY boxdR "&#x2552;">
-<!ENTITY boxDr "&#x2553;">
-<!ENTITY boxDR "&#x2554;">
-<!ENTITY boxdL "&#x2555;">
-<!ENTITY boxDl "&#x2556;">
-<!ENTITY boxDL "&#x2557;">
-<!ENTITY boxuR "&#x2558;">
-<!ENTITY boxUr "&#x2559;">
-<!ENTITY boxUR "&#x255A;">
-<!ENTITY boxuL "&#x255B;">
-<!ENTITY boxUl "&#x255C;">
-<!ENTITY boxUL "&#x255D;">
-<!ENTITY boxvR "&#x255E;">
-<!ENTITY boxVr "&#x255F;">
-<!ENTITY boxVR "&#x2560;">
-<!ENTITY boxvL "&#x2561;">
-<!ENTITY boxVl "&#x2562;">
-<!ENTITY boxVL "&#x2563;">
-<!ENTITY boxHd "&#x2564;">
-<!ENTITY boxhD "&#x2565;">
-<!ENTITY boxHD "&#x2566;">
-<!ENTITY boxHu "&#x2567;">
-<!ENTITY boxhU "&#x2568;">
-<!ENTITY boxHU "&#x2569;">
-<!ENTITY boxvH "&#x256A;">
-<!ENTITY boxVh "&#x256B;">
-<!ENTITY boxVH "&#x256C;">
-<!ENTITY uhblk "&#x2580;">
-<!ENTITY lhblk "&#x2584;">
-<!ENTITY block "&#x2588;">
-<!ENTITY blk14 "&#x2591;">
-<!ENTITY blk12 "&#x2592;">
-<!ENTITY blk34 "&#x2593;">
-<!ENTITY square "&#x25A1;"><!ENTITY squ "&#x25A1;"><!ENTITY Square "&#x25A1;">
-<!ENTITY squarf "&#x25AA;"><!ENTITY squf "&#x25AA;"><!ENTITY FilledVerySmallSquare "&#x25AA;"><!ENTITY blacksquare "&#x25AA;">
-<!ENTITY EmptyVerySmallSquare "&#x25AB;">
-<!ENTITY rect "&#x25AD;">
-<!ENTITY marker "&#x25AE;">
-<!ENTITY fltns "&#x25B1;">
-<!ENTITY xutri "&#x25B3;"><!ENTITY bigtriangleup "&#x25B3;">
-<!ENTITY utrif "&#x25B4;"><!ENTITY blacktriangle "&#x25B4;">
-<!ENTITY utri "&#x25B5;"><!ENTITY triangle "&#x25B5;">
-<!ENTITY rtrif "&#x25B8;"><!ENTITY blacktriangleright "&#x25B8;">
-<!ENTITY rtri "&#x25B9;"><!ENTITY triangleright "&#x25B9;">
-<!ENTITY xdtri "&#x25BD;"><!ENTITY bigtriangledown "&#x25BD;">
-<!ENTITY dtrif "&#x25BE;"><!ENTITY blacktriangledown "&#x25BE;">
-<!ENTITY dtri "&#x25BF;"><!ENTITY triangledown "&#x25BF;">
-<!ENTITY ltrif "&#x25C2;"><!ENTITY blacktriangleleft "&#x25C2;">
-<!ENTITY ltri "&#x25C3;"><!ENTITY triangleleft "&#x25C3;">
-<!ENTITY loz "&#x25CA;"><!ENTITY lozenge "&#x25CA;">
-<!ENTITY cir "&#x25CB;">
-<!ENTITY tridot "&#x25EC;">
-<!ENTITY xcirc "&#x25EF;"><!ENTITY bigcirc "&#x25EF;">
-<!ENTITY ultri "&#x25F8;">
-<!ENTITY urtri "&#x25F9;">
-<!ENTITY lltri "&#x25FA;">
-<!ENTITY EmptySmallSquare "&#x25FB;">
-<!ENTITY FilledSmallSquare "&#x25FC;">
-<!ENTITY starf "&#x2605;"><!ENTITY bigstar "&#x2605;">
-<!ENTITY star "&#x2606;">
-<!ENTITY phone "&#x260E;">
-<!ENTITY female "&#x2640;">
-<!ENTITY male "&#x2642;">
-<!ENTITY spades "&#x2660;"><!ENTITY spadesuit "&#x2660;">
-<!ENTITY clubs "&#x2663;"><!ENTITY clubsuit "&#x2663;">
-<!ENTITY hearts "&#x2665;"><!ENTITY heartsuit "&#x2665;">
-<!ENTITY diams "&#x2666;"><!ENTITY diamondsuit "&#x2666;">
-<!ENTITY sung "&#x266A;">
-<!ENTITY flat "&#x266D;">
-<!ENTITY natur "&#x266E;"><!ENTITY natural "&#x266E;">
-<!ENTITY sharp "&#x266F;">
-<!ENTITY check "&#x2713;"><!ENTITY checkmark "&#x2713;">
-<!ENTITY cross "&#x2717;">
-<!ENTITY malt "&#x2720;"><!ENTITY maltese "&#x2720;">
-<!ENTITY sext "&#x2736;">
-<!ENTITY VerticalSeparator "&#x2758;">
-<!ENTITY xlarr "&#x27F5;"><!ENTITY LongLeftArrow "&#x27F5;"><!ENTITY longleftarrow "&#x27F5;">
-<!ENTITY xrarr "&#x27F6;"><!ENTITY LongRightArrow "&#x27F6;"><!ENTITY longrightarrow "&#x27F6;">
-<!ENTITY xharr "&#x27F7;"><!ENTITY LongLeftRightArrow "&#x27F7;"><!ENTITY longleftrightarrow "&#x27F7;">
-<!ENTITY xlArr "&#x27F8;"><!ENTITY DoubleLongLeftArrow "&#x27F8;"><!ENTITY Longleftarrow "&#x27F8;">
-<!ENTITY xrArr "&#x27F9;"><!ENTITY DoubleLongRightArrow "&#x27F9;"><!ENTITY Longrightarrow "&#x27F9;">
-<!ENTITY xhArr "&#x27FA;"><!ENTITY DoubleLongLeftRightArrow "&#x27FA;"><!ENTITY Longleftrightarrow "&#x27FA;">
-<!ENTITY xmap "&#x27FC;"><!ENTITY longmapsto "&#x27FC;">
-<!ENTITY dzigrarr "&#x27FF;">
-<!ENTITY nvlArr "&#x2902;">
-<!ENTITY nvrArr "&#x2903;">
-<!ENTITY nvHarr "&#x2904;">
-<!ENTITY Map "&#x2905;">
-<!ENTITY lbarr "&#x290C;">
-<!ENTITY rbarr "&#x290D;"><!ENTITY bkarow "&#x290D;">
-<!ENTITY lBarr "&#x290E;">
-<!ENTITY rBarr "&#x290F;"><!ENTITY dbkarow "&#x290F;">
-<!ENTITY RBarr "&#x2910;"><!ENTITY drbkarow "&#x2910;">
-<!ENTITY DDotrahd "&#x2911;">
-<!ENTITY UpArrowBar "&#x2912;">
-<!ENTITY DownArrowBar "&#x2913;">
-<!ENTITY Rarrtl "&#x2916;">
-<!ENTITY latail "&#x2919;">
-<!ENTITY ratail "&#x291A;">
-<!ENTITY lAtail "&#x291B;">
-<!ENTITY rAtail "&#x291C;">
-<!ENTITY larrfs "&#x291D;">
-<!ENTITY rarrfs "&#x291E;">
-<!ENTITY larrbfs "&#x291F;">
-<!ENTITY rarrbfs "&#x2920;">
-<!ENTITY nwarhk "&#x2923;">
-<!ENTITY nearhk "&#x2924;">
-<!ENTITY searhk "&#x2925;"><!ENTITY hksearow "&#x2925;">
-<!ENTITY swarhk "&#x2926;"><!ENTITY hkswarow "&#x2926;">
-<!ENTITY nwnear "&#x2927;">
-<!ENTITY nesear "&#x2928;"><!ENTITY toea "&#x2928;">
-<!ENTITY seswar "&#x2929;"><!ENTITY tosa "&#x2929;">
-<!ENTITY swnwar "&#x292A;">
-<!ENTITY rarrc "&#x2933;">
-<!ENTITY nrarrc "&#x2933;&#x338;">
-<!ENTITY cudarrr "&#x2935;">
-<!ENTITY ldca "&#x2936;">
-<!ENTITY rdca "&#x2937;">
-<!ENTITY cudarrl "&#x2938;">
-<!ENTITY larrpl "&#x2939;">
-<!ENTITY curarrm "&#x293C;">
-<!ENTITY cularrp "&#x293D;">
-<!ENTITY rarrpl "&#x2945;">
-<!ENTITY harrcir "&#x2948;">
-<!ENTITY Uarrocir "&#x2949;">
-<!ENTITY lurdshar "&#x294A;">
-<!ENTITY ldrushar "&#x294B;">
-<!ENTITY LeftRightVector "&#x294E;">
-<!ENTITY RightUpDownVector "&#x294F;">
-<!ENTITY DownLeftRightVector "&#x2950;">
-<!ENTITY LeftUpDownVector "&#x2951;">
-<!ENTITY LeftVectorBar "&#x2952;">
-<!ENTITY RightVectorBar "&#x2953;">
-<!ENTITY RightUpVectorBar "&#x2954;">
-<!ENTITY RightDownVectorBar "&#x2955;">
-<!ENTITY DownLeftVectorBar "&#x2956;">
-<!ENTITY DownRightVectorBar "&#x2957;">
-<!ENTITY LeftUpVectorBar "&#x2958;">
-<!ENTITY LeftDownVectorBar "&#x2959;">
-<!ENTITY LeftTeeVector "&#x295A;">
-<!ENTITY RightTeeVector "&#x295B;">
-<!ENTITY RightUpTeeVector "&#x295C;">
-<!ENTITY RightDownTeeVector "&#x295D;">
-<!ENTITY DownLeftTeeVector "&#x295E;">
-<!ENTITY DownRightTeeVector "&#x295F;">
-<!ENTITY LeftUpTeeVector "&#x2960;">
-<!ENTITY LeftDownTeeVector "&#x2961;">
-<!ENTITY lHar "&#x2962;">
-<!ENTITY uHar "&#x2963;">
-<!ENTITY rHar "&#x2964;">
-<!ENTITY dHar "&#x2965;">
-<!ENTITY luruhar "&#x2966;">
-<!ENTITY ldrdhar "&#x2967;">
-<!ENTITY ruluhar "&#x2968;">
-<!ENTITY rdldhar "&#x2969;">
-<!ENTITY lharul "&#x296A;">
-<!ENTITY llhard "&#x296B;">
-<!ENTITY rharul "&#x296C;">
-<!ENTITY lrhard "&#x296D;">
-<!ENTITY udhar "&#x296E;"><!ENTITY UpEquilibrium "&#x296E;">
-<!ENTITY duhar "&#x296F;"><!ENTITY ReverseUpEquilibrium "&#x296F;">
-<!ENTITY RoundImplies "&#x2970;">
-<!ENTITY erarr "&#x2971;">
-<!ENTITY simrarr "&#x2972;">
-<!ENTITY larrsim "&#x2973;">
-<!ENTITY rarrsim "&#x2974;">
-<!ENTITY rarrap "&#x2975;">
-<!ENTITY ltlarr "&#x2976;">
-<!ENTITY gtrarr "&#x2978;">
-<!ENTITY subrarr "&#x2979;">
-<!ENTITY suplarr "&#x297B;">
-<!ENTITY lfisht "&#x297C;">
-<!ENTITY rfisht "&#x297D;">
-<!ENTITY ufisht "&#x297E;">
-<!ENTITY dfisht "&#x297F;">
-<!ENTITY lopar "&#x2985;">
-<!ENTITY ropar "&#x2986;">
-<!ENTITY lbrke "&#x298B;">
-<!ENTITY rbrke "&#x298C;">
-<!ENTITY lbrkslu "&#x298D;">
-<!ENTITY rbrksld "&#x298E;">
-<!ENTITY lbrksld "&#x298F;">
-<!ENTITY rbrkslu "&#x2990;">
-<!ENTITY langd "&#x2991;">
-<!ENTITY rangd "&#x2992;">
-<!ENTITY lparlt "&#x2993;">
-<!ENTITY rpargt "&#x2994;">
-<!ENTITY gtlPar "&#x2995;">
-<!ENTITY ltrPar "&#x2996;">
-<!ENTITY vzigzag "&#x299A;">
-<!ENTITY vangrt "&#x299C;">
-<!ENTITY angrtvbd "&#x299D;">
-<!ENTITY ange "&#x29A4;">
-<!ENTITY range "&#x29A5;">
-<!ENTITY dwangle "&#x29A6;">
-<!ENTITY uwangle "&#x29A7;">
-<!ENTITY angmsdaa "&#x29A8;">
-<!ENTITY angmsdab "&#x29A9;">
-<!ENTITY angmsdac "&#x29AA;">
-<!ENTITY angmsdad "&#x29AB;">
-<!ENTITY angmsdae "&#x29AC;">
-<!ENTITY angmsdaf "&#x29AD;">
-<!ENTITY angmsdag "&#x29AE;">
-<!ENTITY angmsdah "&#x29AF;">
-<!ENTITY bemptyv "&#x29B0;">
-<!ENTITY demptyv "&#x29B1;">
-<!ENTITY cemptyv "&#x29B2;">
-<!ENTITY raemptyv "&#x29B3;">
-<!ENTITY laemptyv "&#x29B4;">
-<!ENTITY ohbar "&#x29B5;">
-<!ENTITY omid "&#x29B6;">
-<!ENTITY opar "&#x29B7;">
-<!ENTITY operp "&#x29B9;">
-<!ENTITY olcross "&#x29BB;">
-<!ENTITY odsold "&#x29BC;">
-<!ENTITY olcir "&#x29BE;">
-<!ENTITY ofcir "&#x29BF;">
-<!ENTITY olt "&#x29C0;">
-<!ENTITY ogt "&#x29C1;">
-<!ENTITY cirscir "&#x29C2;">
-<!ENTITY cirE "&#x29C3;">
-<!ENTITY solb "&#x29C4;">
-<!ENTITY bsolb "&#x29C5;">
-<!ENTITY boxbox "&#x29C9;">
-<!ENTITY trisb "&#x29CD;">
-<!ENTITY rtriltri "&#x29CE;">
-<!ENTITY LeftTriangleBar "&#x29CF;">
-<!ENTITY NotLeftTriangleBar "&#x29CF;&#x338;">
-<!ENTITY RightTriangleBar "&#x29D0;">
-<!ENTITY NotRightTriangleBar "&#x29D0;&#x338;">
-<!ENTITY race "&#x29DA;">
-<!ENTITY iinfin "&#x29DC;">
-<!ENTITY infintie "&#x29DD;">
-<!ENTITY nvinfin "&#x29DE;">
-<!ENTITY eparsl "&#x29E3;">
-<!ENTITY smeparsl "&#x29E4;">
-<!ENTITY eqvparsl "&#x29E5;">
-<!ENTITY lozf "&#x29EB;"><!ENTITY blacklozenge "&#x29EB;">
-<!ENTITY RuleDelayed "&#x29F4;">
-<!ENTITY dsol "&#x29F6;">
-<!ENTITY xodot "&#x2A00;"><!ENTITY bigodot "&#x2A00;">
-<!ENTITY xoplus "&#x2A01;"><!ENTITY bigoplus "&#x2A01;">
-<!ENTITY xotime "&#x2A02;"><!ENTITY bigotimes "&#x2A02;">
-<!ENTITY xuplus "&#x2A04;"><!ENTITY biguplus "&#x2A04;">
-<!ENTITY xsqcup "&#x2A06;"><!ENTITY bigsqcup "&#x2A06;">
-<!ENTITY qint "&#x2A0C;"><!ENTITY iiiint "&#x2A0C;">
-<!ENTITY fpartint "&#x2A0D;">
-<!ENTITY cirfnint "&#x2A10;">
-<!ENTITY awint "&#x2A11;">
-<!ENTITY rppolint "&#x2A12;">
-<!ENTITY scpolint "&#x2A13;">
-<!ENTITY npolint "&#x2A14;">
-<!ENTITY pointint "&#x2A15;">
-<!ENTITY quatint "&#x2A16;">
-<!ENTITY intlarhk "&#x2A17;">
-<!ENTITY pluscir "&#x2A22;">
-<!ENTITY plusacir "&#x2A23;">
-<!ENTITY simplus "&#x2A24;">
-<!ENTITY plusdu "&#x2A25;">
-<!ENTITY plussim "&#x2A26;">
-<!ENTITY plustwo "&#x2A27;">
-<!ENTITY mcomma "&#x2A29;">
-<!ENTITY minusdu "&#x2A2A;">
-<!ENTITY loplus "&#x2A2D;">
-<!ENTITY roplus "&#x2A2E;">
-<!ENTITY Cross "&#x2A2F;">
-<!ENTITY timesd "&#x2A30;">
-<!ENTITY timesbar "&#x2A31;">
-<!ENTITY smashp "&#x2A33;">
-<!ENTITY lotimes "&#x2A34;">
-<!ENTITY rotimes "&#x2A35;">
-<!ENTITY otimesas "&#x2A36;">
-<!ENTITY Otimes "&#x2A37;">
-<!ENTITY odiv "&#x2A38;">
-<!ENTITY triplus "&#x2A39;">
-<!ENTITY triminus "&#x2A3A;">
-<!ENTITY tritime "&#x2A3B;">
-<!ENTITY iprod "&#x2A3C;"><!ENTITY intprod "&#x2A3C;">
-<!ENTITY amalg "&#x2A3F;">
-<!ENTITY capdot "&#x2A40;">
-<!ENTITY ncup "&#x2A42;">
-<!ENTITY ncap "&#x2A43;">
-<!ENTITY capand "&#x2A44;">
-<!ENTITY cupor "&#x2A45;">
-<!ENTITY cupcap "&#x2A46;">
-<!ENTITY capcup "&#x2A47;">
-<!ENTITY cupbrcap "&#x2A48;">
-<!ENTITY capbrcup "&#x2A49;">
-<!ENTITY cupcup "&#x2A4A;">
-<!ENTITY capcap "&#x2A4B;">
-<!ENTITY ccups "&#x2A4C;">
-<!ENTITY ccaps "&#x2A4D;">
-<!ENTITY ccupssm "&#x2A50;">
-<!ENTITY And "&#x2A53;">
-<!ENTITY Or "&#x2A54;">
-<!ENTITY andand "&#x2A55;">
-<!ENTITY oror "&#x2A56;">
-<!ENTITY orslope "&#x2A57;">
-<!ENTITY andslope "&#x2A58;">
-<!ENTITY andv "&#x2A5A;">
-<!ENTITY orv "&#x2A5B;">
-<!ENTITY andd "&#x2A5C;">
-<!ENTITY ord "&#x2A5D;">
-<!ENTITY wedbar "&#x2A5F;">
-<!ENTITY sdote "&#x2A66;">
-<!ENTITY simdot "&#x2A6A;">
-<!ENTITY congdot "&#x2A6D;">
-<!ENTITY ncongdot "&#x2A6D;&#x338;">
-<!ENTITY easter "&#x2A6E;">
-<!ENTITY apacir "&#x2A6F;">
-<!ENTITY apE "&#x2A70;">
-<!ENTITY napE "&#x2A70;&#x338;">
-<!ENTITY eplus "&#x2A71;">
-<!ENTITY pluse "&#x2A72;">
-<!ENTITY Esim "&#x2A73;">
-<!ENTITY Colone "&#x2A74;">
-<!ENTITY Equal "&#x2A75;">
-<!ENTITY eDDot "&#x2A77;"><!ENTITY ddotseq "&#x2A77;">
-<!ENTITY equivDD "&#x2A78;">
-<!ENTITY ltcir "&#x2A79;">
-<!ENTITY gtcir "&#x2A7A;">
-<!ENTITY ltquest "&#x2A7B;">
-<!ENTITY gtquest "&#x2A7C;">
-<!ENTITY les "&#x2A7D;"><!ENTITY leqslant "&#x2A7D;"><!ENTITY LessSlantEqual "&#x2A7D;">
-<!ENTITY nles "&#x2A7D;&#x338;"><!ENTITY nleqslant "&#x2A7D;&#x338;"><!ENTITY NotLessSlantEqual "&#x2A7D;&#x338;">
-<!ENTITY ges "&#x2A7E;"><!ENTITY geqslant "&#x2A7E;"><!ENTITY GreaterSlantEqual "&#x2A7E;">
-<!ENTITY nges "&#x2A7E;&#x338;"><!ENTITY ngeqslant "&#x2A7E;&#x338;"><!ENTITY NotGreaterSlantEqual "&#x2A7E;&#x338;">
-<!ENTITY lesdot "&#x2A7F;">
-<!ENTITY gesdot "&#x2A80;">
-<!ENTITY lesdoto "&#x2A81;">
-<!ENTITY gesdoto "&#x2A82;">
-<!ENTITY lesdotor "&#x2A83;">
-<!ENTITY gesdotol "&#x2A84;">
-<!ENTITY lap "&#x2A85;"><!ENTITY lessapprox "&#x2A85;">
-<!ENTITY gap "&#x2A86;"><!ENTITY gtrapprox "&#x2A86;">
-<!ENTITY lne "&#x2A87;"><!ENTITY lneq "&#x2A87;">
-<!ENTITY gne "&#x2A88;"><!ENTITY gneq "&#x2A88;">
-<!ENTITY lnap "&#x2A89;"><!ENTITY lnapprox "&#x2A89;">
-<!ENTITY gnap "&#x2A8A;"><!ENTITY gnapprox "&#x2A8A;">
-<!ENTITY lEg "&#x2A8B;"><!ENTITY lesseqqgtr "&#x2A8B;">
-<!ENTITY gEl "&#x2A8C;"><!ENTITY gtreqqless "&#x2A8C;">
-<!ENTITY lsime "&#x2A8D;">
-<!ENTITY gsime "&#x2A8E;">
-<!ENTITY lsimg "&#x2A8F;">
-<!ENTITY gsiml "&#x2A90;">
-<!ENTITY lgE "&#x2A91;">
-<!ENTITY glE "&#x2A92;">
-<!ENTITY lesges "&#x2A93;">
-<!ENTITY gesles "&#x2A94;">
-<!ENTITY els "&#x2A95;"><!ENTITY eqslantless "&#x2A95;">
-<!ENTITY egs "&#x2A96;"><!ENTITY eqslantgtr "&#x2A96;">
-<!ENTITY elsdot "&#x2A97;">
-<!ENTITY egsdot "&#x2A98;">
-<!ENTITY el "&#x2A99;">
-<!ENTITY eg "&#x2A9A;">
-<!ENTITY siml "&#x2A9D;">
-<!ENTITY simg "&#x2A9E;">
-<!ENTITY simlE "&#x2A9F;">
-<!ENTITY simgE "&#x2AA0;">
-<!ENTITY LessLess "&#x2AA1;">
-<!ENTITY NotNestedLessLess "&#x2AA1;&#x338;">
-<!ENTITY GreaterGreater "&#x2AA2;">
-<!ENTITY NotNestedGreaterGreater "&#x2AA2;&#x338;">
-<!ENTITY glj "&#x2AA4;">
-<!ENTITY gla "&#x2AA5;">
-<!ENTITY ltcc "&#x2AA6;">
-<!ENTITY gtcc "&#x2AA7;">
-<!ENTITY lescc "&#x2AA8;">
-<!ENTITY gescc "&#x2AA9;">
-<!ENTITY smt "&#x2AAA;">
-<!ENTITY lat "&#x2AAB;">
-<!ENTITY smte "&#x2AAC;">
-<!ENTITY smtes "&#x2AAC;&#xFE00;">
-<!ENTITY late "&#x2AAD;">
-<!ENTITY lates "&#x2AAD;&#xFE00;">
-<!ENTITY bumpE "&#x2AAE;">
-<!ENTITY pre "&#x2AAF;"><!ENTITY PrecedesEqual "&#x2AAF;"><!ENTITY preceq "&#x2AAF;">
-<!ENTITY npre "&#x2AAF;&#x338;"><!ENTITY NotPrecedesEqual "&#x2AAF;&#x338;"><!ENTITY npreceq "&#x2AAF;&#x338;">
-<!ENTITY sce "&#x2AB0;"><!ENTITY SucceedsEqual "&#x2AB0;"><!ENTITY succeq "&#x2AB0;">
-<!ENTITY nsce "&#x2AB0;&#x338;"><!ENTITY NotSucceedsEqual "&#x2AB0;&#x338;"><!ENTITY nsucceq "&#x2AB0;&#x338;">
-<!ENTITY prE "&#x2AB3;">
-<!ENTITY scE "&#x2AB4;">
-<!ENTITY prnE "&#x2AB5;"><!ENTITY precneqq "&#x2AB5;">
-<!ENTITY scnE "&#x2AB6;"><!ENTITY succneqq "&#x2AB6;">
-<!ENTITY prap "&#x2AB7;"><!ENTITY precapprox "&#x2AB7;">
-<!ENTITY scap "&#x2AB8;"><!ENTITY succapprox "&#x2AB8;">
-<!ENTITY prnap "&#x2AB9;"><!ENTITY precnapprox "&#x2AB9;">
-<!ENTITY scnap "&#x2ABA;"><!ENTITY succnapprox "&#x2ABA;">
-<!ENTITY Pr "&#x2ABB;">
-<!ENTITY Sc "&#x2ABC;">
-<!ENTITY subdot "&#x2ABD;">
-<!ENTITY supdot "&#x2ABE;">
-<!ENTITY subplus "&#x2ABF;">
-<!ENTITY supplus "&#x2AC0;">
-<!ENTITY submult "&#x2AC1;">
-<!ENTITY supmult "&#x2AC2;">
-<!ENTITY subedot "&#x2AC3;">
-<!ENTITY supedot "&#x2AC4;">
-<!ENTITY subE "&#x2AC5;"><!ENTITY subseteqq "&#x2AC5;">
-<!ENTITY nsubE "&#x2AC5;&#x338;"><!ENTITY nsubseteqq "&#x2AC5;&#x338;">
-<!ENTITY supE "&#x2AC6;"><!ENTITY supseteqq "&#x2AC6;">
-<!ENTITY nsupE "&#x2AC6;&#x338;"><!ENTITY nsupseteqq "&#x2AC6;&#x338;">
-<!ENTITY subsim "&#x2AC7;">
-<!ENTITY supsim "&#x2AC8;">
-<!ENTITY subnE "&#x2ACB;"><!ENTITY subsetneqq "&#x2ACB;">
-<!ENTITY vsubnE "&#x2ACB;&#xFE00;"><!ENTITY varsubsetneqq "&#x2ACB;&#xFE00;">
-<!ENTITY supnE "&#x2ACC;"><!ENTITY supsetneqq "&#x2ACC;">
-<!ENTITY vsupnE "&#x2ACC;&#xFE00;"><!ENTITY varsupsetneqq "&#x2ACC;&#xFE00;">
-<!ENTITY csub "&#x2ACF;">
-<!ENTITY csup "&#x2AD0;">
-<!ENTITY csube "&#x2AD1;">
-<!ENTITY csupe "&#x2AD2;">
-<!ENTITY subsup "&#x2AD3;">
-<!ENTITY supsub "&#x2AD4;">
-<!ENTITY subsub "&#x2AD5;">
-<!ENTITY supsup "&#x2AD6;">
-<!ENTITY suphsub "&#x2AD7;">
-<!ENTITY supdsub "&#x2AD8;">
-<!ENTITY forkv "&#x2AD9;">
-<!ENTITY topfork "&#x2ADA;">
-<!ENTITY mlcp "&#x2ADB;">
-<!ENTITY Dashv "&#x2AE4;"><!ENTITY DoubleLeftTee "&#x2AE4;">
-<!ENTITY Vdashl "&#x2AE6;">
-<!ENTITY Barv "&#x2AE7;">
-<!ENTITY vBar "&#x2AE8;">
-<!ENTITY vBarv "&#x2AE9;">
-<!ENTITY Vbar "&#x2AEB;">
-<!ENTITY Not "&#x2AEC;">
-<!ENTITY bNot "&#x2AED;">
-<!ENTITY rnmid "&#x2AEE;">
-<!ENTITY cirmid "&#x2AEF;">
-<!ENTITY midcir "&#x2AF0;">
-<!ENTITY topcir "&#x2AF1;">
-<!ENTITY nhpar "&#x2AF2;">
-<!ENTITY parsim "&#x2AF3;">
-<!ENTITY parsl "&#x2AFD;">
-<!ENTITY nparsl "&#x2AFD;&#x20E5;">
-<!ENTITY fflig "&#xFB00;">
-<!ENTITY filig "&#xFB01;">
-<!ENTITY fllig "&#xFB02;">
-<!ENTITY ffilig "&#xFB03;">
-<!ENTITY ffllig "&#xFB04;">
-<!ENTITY Ascr "&#x1D49C;">
-<!ENTITY Cscr "&#x1D49E;">
-<!ENTITY Dscr "&#x1D49F;">
-<!ENTITY Gscr "&#x1D4A2;">
-<!ENTITY Jscr "&#x1D4A5;">
-<!ENTITY Kscr "&#x1D4A6;">
-<!ENTITY Nscr "&#x1D4A9;">
-<!ENTITY Oscr "&#x1D4AA;">
-<!ENTITY Pscr "&#x1D4AB;">
-<!ENTITY Qscr "&#x1D4AC;">
-<!ENTITY Sscr "&#x1D4AE;">
-<!ENTITY Tscr "&#x1D4AF;">
-<!ENTITY Uscr "&#x1D4B0;">
-<!ENTITY Vscr "&#x1D4B1;">
-<!ENTITY Wscr "&#x1D4B2;">
-<!ENTITY Xscr "&#x1D4B3;">
-<!ENTITY Yscr "&#x1D4B4;">
-<!ENTITY Zscr "&#x1D4B5;">
-<!ENTITY ascr "&#x1D4B6;">
-<!ENTITY bscr "&#x1D4B7;">
-<!ENTITY cscr "&#x1D4B8;">
-<!ENTITY dscr "&#x1D4B9;">
-<!ENTITY fscr "&#x1D4BB;">
-<!ENTITY hscr "&#x1D4BD;">
-<!ENTITY iscr "&#x1D4BE;">
-<!ENTITY jscr "&#x1D4BF;">
-<!ENTITY kscr "&#x1D4C0;">
-<!ENTITY lscr "&#x1D4C1;">
-<!ENTITY mscr "&#x1D4C2;">
-<!ENTITY nscr "&#x1D4C3;">
-<!ENTITY pscr "&#x1D4C5;">
-<!ENTITY qscr "&#x1D4C6;">
-<!ENTITY rscr "&#x1D4C7;">
-<!ENTITY sscr "&#x1D4C8;">
-<!ENTITY tscr "&#x1D4C9;">
-<!ENTITY uscr "&#x1D4CA;">
-<!ENTITY vscr "&#x1D4CB;">
-<!ENTITY wscr "&#x1D4CC;">
-<!ENTITY xscr "&#x1D4CD;">
-<!ENTITY yscr "&#x1D4CE;">
-<!ENTITY zscr "&#x1D4CF;">
-<!ENTITY Afr "&#x1D504;">
-<!ENTITY Bfr "&#x1D505;">
-<!ENTITY Dfr "&#x1D507;">
-<!ENTITY Efr "&#x1D508;">
-<!ENTITY Ffr "&#x1D509;">
-<!ENTITY Gfr "&#x1D50A;">
-<!ENTITY Jfr "&#x1D50D;">
-<!ENTITY Kfr "&#x1D50E;">
-<!ENTITY Lfr "&#x1D50F;">
-<!ENTITY Mfr "&#x1D510;">
-<!ENTITY Nfr "&#x1D511;">
-<!ENTITY Ofr "&#x1D512;">
-<!ENTITY Pfr "&#x1D513;">
-<!ENTITY Qfr "&#x1D514;">
-<!ENTITY Sfr "&#x1D516;">
-<!ENTITY Tfr "&#x1D517;">
-<!ENTITY Ufr "&#x1D518;">
-<!ENTITY Vfr "&#x1D519;">
-<!ENTITY Wfr "&#x1D51A;">
-<!ENTITY Xfr "&#x1D51B;">
-<!ENTITY Yfr "&#x1D51C;">
-<!ENTITY afr "&#x1D51E;">
-<!ENTITY bfr "&#x1D51F;">
-<!ENTITY cfr "&#x1D520;">
-<!ENTITY dfr "&#x1D521;">
-<!ENTITY efr "&#x1D522;">
-<!ENTITY ffr "&#x1D523;">
-<!ENTITY gfr "&#x1D524;">
-<!ENTITY hfr "&#x1D525;">
-<!ENTITY ifr "&#x1D526;">
-<!ENTITY jfr "&#x1D527;">
-<!ENTITY kfr "&#x1D528;">
-<!ENTITY lfr "&#x1D529;">
-<!ENTITY mfr "&#x1D52A;">
-<!ENTITY nfr "&#x1D52B;">
-<!ENTITY ofr "&#x1D52C;">
-<!ENTITY pfr "&#x1D52D;">
-<!ENTITY qfr "&#x1D52E;">
-<!ENTITY rfr "&#x1D52F;">
-<!ENTITY sfr "&#x1D530;">
-<!ENTITY tfr "&#x1D531;">
-<!ENTITY ufr "&#x1D532;">
-<!ENTITY vfr "&#x1D533;">
-<!ENTITY wfr "&#x1D534;">
-<!ENTITY xfr "&#x1D535;">
-<!ENTITY yfr "&#x1D536;">
-<!ENTITY zfr "&#x1D537;">
-<!ENTITY Aopf "&#x1D538;">
-<!ENTITY Bopf "&#x1D539;">
-<!ENTITY Dopf "&#x1D53B;">
-<!ENTITY Eopf "&#x1D53C;">
-<!ENTITY Fopf "&#x1D53D;">
-<!ENTITY Gopf "&#x1D53E;">
-<!ENTITY Iopf "&#x1D540;">
-<!ENTITY Jopf "&#x1D541;">
-<!ENTITY Kopf "&#x1D542;">
-<!ENTITY Lopf "&#x1D543;">
-<!ENTITY Mopf "&#x1D544;">
-<!ENTITY Oopf "&#x1D546;">
-<!ENTITY Sopf "&#x1D54A;">
-<!ENTITY Topf "&#x1D54B;">
-<!ENTITY Uopf "&#x1D54C;">
-<!ENTITY Vopf "&#x1D54D;">
-<!ENTITY Wopf "&#x1D54E;">
-<!ENTITY Xopf "&#x1D54F;">
-<!ENTITY Yopf "&#x1D550;">
-<!ENTITY aopf "&#x1D552;">
-<!ENTITY bopf "&#x1D553;">
-<!ENTITY copf "&#x1D554;">
-<!ENTITY dopf "&#x1D555;">
-<!ENTITY eopf "&#x1D556;">
-<!ENTITY fopf "&#x1D557;">
-<!ENTITY gopf "&#x1D558;">
-<!ENTITY hopf "&#x1D559;">
-<!ENTITY iopf "&#x1D55A;">
-<!ENTITY jopf "&#x1D55B;">
-<!ENTITY kopf "&#x1D55C;">
-<!ENTITY lopf "&#x1D55D;">
-<!ENTITY mopf "&#x1D55E;">
-<!ENTITY nopf "&#x1D55F;">
-<!ENTITY oopf "&#x1D560;">
-<!ENTITY popf "&#x1D561;">
-<!ENTITY qopf "&#x1D562;">
-<!ENTITY ropf "&#x1D563;">
-<!ENTITY sopf "&#x1D564;">
-<!ENTITY topf "&#x1D565;">
-<!ENTITY uopf "&#x1D566;">
-<!ENTITY vopf "&#x1D567;">
-<!ENTITY wopf "&#x1D568;">
-<!ENTITY xopf "&#x1D569;">
-<!ENTITY yopf "&#x1D56A;">
-<!ENTITY zopf "&#x1D56B;">
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -65,17 +65,18 @@ using namespace mozilla;
 
 nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI)
   : nsMediaStream(aDecoder, aChannel, aURI),
     mOffset(0), mSuspendCount(0),
     mReopenOnError(PR_FALSE), mIgnoreClose(PR_FALSE),
     mCacheStream(this),
     mLock("nsMediaChannelStream.mLock"),
-    mCacheSuspendCount(0)
+    mCacheSuspendCount(0),
+    mIgnoreResume(PR_FALSE)
 {
 }
 
 nsMediaChannelStream::~nsMediaChannelStream()
 {
   if (mListener) {
     // Kill its reference to us since we're going away
     mListener->Revoke();
@@ -271,17 +272,20 @@ nsMediaChannelStream::OnStartRequest(nsI
     MutexAutoLock lock(mLock);
     mChannelStatistics.Start(TimeStamp::Now());
   }
 
   mReopenOnError = PR_FALSE;
   mIgnoreClose = PR_FALSE;
   if (mSuspendCount > 0) {
     // Re-suspend the channel if it needs to be suspended
+    // No need to call PossiblySuspend here since the channel is
+    // definitely in the right state for us in OneStartRequest.
     mChannel->Suspend();
+    mIgnoreResume = PR_FALSE;
   }
 
   // Fires an initial progress event and sets up the stall counter so stall events
   // fire if no download occurs within the required time frame.
   mDecoder->Progress(PR_FALSE);
 
   return NS_OK;
 }
@@ -551,17 +555,17 @@ void nsMediaChannelStream::CloseChannel(
   if (mListener) {
     mListener->Revoke();
     mListener = nsnull;
   }
 
   if (mChannel) {
     if (mSuspendCount > 0) {
       // Resume the channel before we cancel it
-      mChannel->Resume();
+      PossiblyResume();
     }
     // The status we use here won't be passed to the decoder, since
     // we've already revoked the listener. It can however be passed
     // to DocumentViewerImpl::LoadComplete if our channel is the one
     // that kicked off creation of a video document. We don't want that
     // document load to think there was an error.
     // NS_ERROR_PARSED_DATA_CACHED is the best thing we have for that
     // at the moment.
@@ -621,17 +625,17 @@ void nsMediaChannelStream::Suspend(PRBoo
       mIgnoreClose = PR_TRUE;
       CloseChannel();
       element->DownloadSuspended();
     } else if (mSuspendCount == 0) {
       {
         MutexAutoLock lock(mLock);
         mChannelStatistics.Stop(TimeStamp::Now());
       }
-      mChannel->Suspend();
+      PossiblySuspend();
       element->DownloadSuspended();
     }
   }
 
   ++mSuspendCount;
 }
 
 void nsMediaChannelStream::Resume()
@@ -652,17 +656,17 @@ void nsMediaChannelStream::Resume()
       // Just wake up our existing channel
       {
         MutexAutoLock lock(mLock);
         mChannelStatistics.Start(TimeStamp::Now());
       }
       // if an error occurs after Resume, assume it's because the server
       // timed out the connection and we should reopen it.
       mReopenOnError = PR_TRUE;
-      mChannel->Resume();
+      PossiblyResume();
       element->DownloadResumed();
     } else {
       PRInt64 totalLength = mCacheStream.GetLength();
       // If mOffset is at the end of the stream, then we shouldn't try to
       // seek to it. The seek will fail and be wasted anyway. We can leave
       // the channel dead; if the media cache wants to read some other data
       // in the future, it will call CacheClientSeek itself which will reopen the
       // channel.
@@ -862,16 +866,39 @@ nsMediaChannelStream::GetDownloadRate(PR
 }
 
 PRInt64
 nsMediaChannelStream::GetLength()
 {
   return mCacheStream.GetLength();
 }
 
+void
+nsMediaChannelStream::PossiblySuspend()
+{
+  PRBool isPending = PR_FALSE;
+  nsresult rv = mChannel->IsPending(&isPending);
+  if (NS_SUCCEEDED(rv) && isPending) {
+    mChannel->Suspend();
+    mIgnoreResume = PR_FALSE;
+  } else {
+    mIgnoreResume = PR_TRUE;
+  }
+}
+
+void
+nsMediaChannelStream::PossiblyResume()
+{
+  if (!mIgnoreResume) {
+    mChannel->Resume();
+  } else {
+    mIgnoreResume = PR_FALSE;
+  }
+}
+
 class nsMediaFileStream : public nsMediaStream
 {
 public:
   nsMediaFileStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
     nsMediaStream(aDecoder, aChannel, aURI), mSize(-1),
     mLock("nsMediaFileStream.mLock")
   {
   }
--- a/content/media/nsMediaStream.h
+++ b/content/media/nsMediaStream.h
@@ -447,16 +447,24 @@ protected:
 
   static NS_METHOD CopySegmentToCache(nsIInputStream *aInStream,
                                       void *aClosure,
                                       const char *aFromSegment,
                                       PRUint32 aToOffset,
                                       PRUint32 aCount,
                                       PRUint32 *aWriteCount);
 
+  // Suspend the channel only if the channels is currently downloading data.
+  // If it isn't we set a flag, mIgnoreResume, so that PossiblyResume knows
+  // whether to acutually resume or not.
+  void PossiblySuspend();
+
+  // Resume from a suspend if we actually suspended (See PossiblySuspend).
+  void PossiblyResume();
+
   // Main thread access only
   PRInt64            mOffset;
   nsRefPtr<Listener> mListener;
   // A data received event for the decoder that has been dispatched but has
   // not yet been processed.
   nsRevocableEventPtr<nsRunnableMethod<nsMediaChannelStream, void, false> > mDataReceivedEvent;
   PRUint32           mSuspendCount;
   // When this flag is set, if we get a network error we should silently
@@ -468,11 +476,16 @@ protected:
 
   // Any thread access
   nsMediaCacheStream mCacheStream;
 
   // This lock protects mChannelStatistics and mCacheSuspendCount
   Mutex               mLock;
   nsChannelStatistics mChannelStatistics;
   PRUint32            mCacheSuspendCount;
+
+  // PR_TRUE if we couldn't suspend the stream and we therefore don't want
+  // to resume later. This is usually due to the channel not being in the
+  // isPending state at the time of the suspend request.
+  PRPackedBool mIgnoreResume;
 };
 
 #endif
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -87,16 +87,31 @@ namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGLengthList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLengthList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLengthList)
 NS_INTERFACE_MAP_END
 
 
+nsIDOMSVGLength*
+DOMSVGLengthList::GetItemWithoutAddRef(PRUint32 aIndex)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  if (aIndex < Length()) {
+    EnsureItemAt(aIndex);
+    return mItems[aIndex];
+  }
+  return nsnull;
+}
+
 void
 DOMSVGLengthList::InternalListLengthWillChange(PRUint32 aNewLength)
 {
   PRUint32 oldLength = mItems.Length();
 
   if (aNewLength > DOMSVGLength::MaxListIndex()) {
     // It's safe to get out of sync with our internal list as long as we have
     // FEWER items than it does.
@@ -205,28 +220,22 @@ DOMSVGLengthList::Initialize(nsIDOMSVGLe
   Clear();
   return InsertItemBefore(newItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGLengthList::GetItem(PRUint32 index,
                           nsIDOMSVGLength **_retval)
 {
-#ifdef MOZ_SMIL
-  if (IsAnimValList()) {
-    Element()->FlushAnimations();
+  *_retval = GetItemWithoutAddRef(index);
+  if (!*_retval) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
-#endif
-  if (index < Length()) {
-    EnsureItemAt(index);
-    NS_ADDREF(*_retval = mItems[index]);
-    return NS_OK;
-  }
-  *_retval = nsnull;
-  return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  NS_ADDREF(*_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMSVGLengthList::InsertItemBefore(nsIDOMSVGLength *newItem,
                                    PRUint32 index,
                                    nsIDOMSVGLength **_retval)
 {
   *_retval = nsnull;
@@ -362,16 +371,22 @@ DOMSVGLengthList::RemoveItem(PRUint32 in
 
 NS_IMETHODIMP
 DOMSVGLengthList::AppendItem(nsIDOMSVGLength *newItem,
                              nsIDOMSVGLength **_retval)
 {
   return InsertItemBefore(newItem, Length(), _retval);
 }
 
+NS_IMETHODIMP
+DOMSVGLengthList::GetLength(PRUint32 *aNumberOfItems)
+{
+  return GetNumberOfItems(aNumberOfItems);
+}
+
 void
 DOMSVGLengthList::EnsureItemAt(PRUint32 aIndex)
 {
   if (!mItems[aIndex]) {
     mItems[aIndex] = new DOMSVGLength(this, AttrEnum(), aIndex, IsAnimValList());
   }
 }
 
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -104,16 +104,18 @@ public:
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() ==
                         const_cast<DOMSVGLengthList*>(this)->InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
+  nsIDOMSVGLength* GetItemWithoutAddRef(PRUint32 aIndex);
+
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(PRUint32 aNewLength);
 
 private:
 
   nsSVGElement* Element() {
     return mAList->mElement;
   }
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -87,16 +87,31 @@ namespace mozilla {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumberList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumberList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumberList)
 NS_INTERFACE_MAP_END
 
 
+nsIDOMSVGNumber*
+DOMSVGNumberList::GetItemWithoutAddRef(PRUint32 aIndex)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  if (aIndex < Length()) {
+    EnsureItemAt(aIndex);
+    return mItems[aIndex];
+  }
+  return nsnull;
+}
+
 void
 DOMSVGNumberList::InternalListLengthWillChange(PRUint32 aNewLength)
 {
   PRUint32 oldLength = mItems.Length();
 
   if (aNewLength > DOMSVGNumber::MaxListIndex()) {
     // It's safe to get out of sync with our internal list as long as we have
     // FEWER items than it does.
@@ -205,28 +220,22 @@ DOMSVGNumberList::Initialize(nsIDOMSVGNu
   Clear();
   return InsertItemBefore(newItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGNumberList::GetItem(PRUint32 index,
                           nsIDOMSVGNumber **_retval)
 {
-#ifdef MOZ_SMIL
-  if (IsAnimValList()) {
-    Element()->FlushAnimations();
+  *_retval = GetItemWithoutAddRef(index);
+  if (!*_retval) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
-#endif
-  if (index < Length()) {
-    EnsureItemAt(index);
-    NS_ADDREF(*_retval = mItems[index]);
-    return NS_OK;
-  }
-  *_retval = nsnull;
-  return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  NS_ADDREF(*_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMSVGNumberList::InsertItemBefore(nsIDOMSVGNumber *newItem,
                                    PRUint32 index,
                                    nsIDOMSVGNumber **_retval)
 {
   *_retval = nsnull;
@@ -362,16 +371,22 @@ DOMSVGNumberList::RemoveItem(PRUint32 in
 
 NS_IMETHODIMP
 DOMSVGNumberList::AppendItem(nsIDOMSVGNumber *newItem,
                              nsIDOMSVGNumber **_retval)
 {
   return InsertItemBefore(newItem, Length(), _retval);
 }
 
+NS_IMETHODIMP
+DOMSVGNumberList::GetLength(PRUint32 *aNumberOfItems)
+{
+  return GetNumberOfItems(aNumberOfItems);
+}
+
 void
 DOMSVGNumberList::EnsureItemAt(PRUint32 aIndex)
 {
   if (!mItems[aIndex]) {
     mItems[aIndex] = new DOMSVGNumber(this, AttrEnum(), aIndex, IsAnimValList());
   }
 }
 
--- a/content/svg/content/src/DOMSVGNumberList.h
+++ b/content/svg/content/src/DOMSVGNumberList.h
@@ -103,16 +103,18 @@ public:
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() ==
                         const_cast<DOMSVGNumberList*>(this)->InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
+  nsIDOMSVGNumber* GetItemWithoutAddRef(PRUint32 aIndex);
+
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(PRUint32 aNewLength);
 
 private:
 
   nsSVGElement* Element() {
     return mAList->mElement;
   }
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -91,16 +91,31 @@ DOMSVGPathSegList::~DOMSVGPathSegList()
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
   sSVGPathSegListTearoffTable.RemoveTearoff(key);
 }
 
+nsIDOMSVGPathSeg*
+DOMSVGPathSegList::GetItemWithoutAddRef(PRUint32 aIndex)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  if (aIndex < Length()) {
+    EnsureItemAt(aIndex);
+    return ItemAt(aIndex);
+  }
+  return nsnull;
+}
+
 void
 DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue)
 {
   // When the number of items in our internal counterpart changes, we MUST stay
   // in sync. Everything in the scary comment in
   // DOMSVGLengthList::InternalBaseValListWillChangeTo applies here just as
   // much, but we have the additional issue that failing to stay in sync would
   // mean that - assuming we aren't reading bad memory - we would likely end up
@@ -300,28 +315,22 @@ DOMSVGPathSegList::Initialize(nsIDOMSVGP
   Clear();
   return InsertItemBefore(aNewItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGPathSegList::GetItem(PRUint32 aIndex,
                            nsIDOMSVGPathSeg **_retval)
 {
-#ifdef MOZ_SMIL
-  if (IsAnimValList()) {
-    Element()->FlushAnimations();
+  *_retval = GetItemWithoutAddRef(aIndex);
+  if (!*_retval) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
-#endif
-  if (aIndex < Length()) {
-    EnsureItemAt(aIndex);
-    NS_ADDREF(*_retval = ItemAt(aIndex));
-    return NS_OK;
-  }
-  *_retval = nsnull;
-  return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  NS_ADDREF(*_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMSVGPathSegList::InsertItemBefore(nsIDOMSVGPathSeg *aNewItem,
                                     PRUint32 aIndex,
                                     nsIDOMSVGPathSeg **_retval)
 {
   *_retval = nsnull;
@@ -493,16 +502,22 @@ DOMSVGPathSegList::RemoveItem(PRUint32 a
 
 NS_IMETHODIMP
 DOMSVGPathSegList::AppendItem(nsIDOMSVGPathSeg *aNewItem,
                               nsIDOMSVGPathSeg **_retval)
 {
   return InsertItemBefore(aNewItem, Length(), _retval);
 }
 
+NS_IMETHODIMP
+DOMSVGPathSegList::GetLength(PRUint32 *aNumberOfItems)
+{
+  return GetNumberOfItems(aNumberOfItems);
+}
+
 void
 DOMSVGPathSegList::EnsureItemAt(PRUint32 aIndex)
 {
   if (!ItemAt(aIndex)) {
     ItemAt(aIndex) = DOMSVGPathSeg::CreateFor(this, aIndex, IsAnimValList());
   }
 }
 
--- a/content/svg/content/src/DOMSVGPathSegList.h
+++ b/content/svg/content/src/DOMSVGPathSegList.h
@@ -121,16 +121,18 @@ public:
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() ==
                         const_cast<DOMSVGPathSegList*>(this)->InternalList().CountItems(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
+  nsIDOMSVGPathSeg* GetItemWithoutAddRef(PRUint32 aIndex);
+
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
    * Called by internal code to notify us when we need to sync the length of
    * this DOM list with its internal list. This is called immediately prior to
    * the length of the internal list being changed so that any DOM list items
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -111,16 +111,31 @@ DOMSVGPointList::~DOMSVGPointList()
   // There are now no longer any references to us held by script or list items.
   // Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
   void *key = mIsAnimValList ?
     InternalAList().GetAnimValKey() :
     InternalAList().GetBaseValKey();
   sSVGPointListTearoffTable.RemoveTearoff(key);
 }
 
+nsIDOMSVGPoint*
+DOMSVGPointList::GetItemWithoutAddRef(PRUint32 aIndex)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  if (aIndex < Length()) {
+    EnsureItemAt(aIndex);
+    return mItems[aIndex];
+  }
+  return nsnull;
+}
+
 void
 DOMSVGPointList::InternalListWillChangeTo(const SVGPointList& aNewValue)
 {
   // When the number of items in our internal counterpart changes, we MUST stay
   // in sync. Everything in the scary comment in
   // DOMSVGLengthList::InternalBaseValListWillChangeTo applies here too!
 
   PRUint32 oldLength = mItems.Length();
@@ -256,28 +271,22 @@ DOMSVGPointList::Initialize(nsIDOMSVGPoi
   Clear();
   return InsertItemBefore(aNewItem, 0, _retval);
 }
 
 NS_IMETHODIMP
 DOMSVGPointList::GetItem(PRUint32 aIndex,
                          nsIDOMSVGPoint **_retval)
 {
-#ifdef MOZ_SMIL
-  if (IsAnimValList()) {
-    Element()->FlushAnimations();
+  *_retval = GetItemWithoutAddRef(aIndex);
+  if (!*_retval) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
-#endif
-  if (aIndex < Length()) {
-    EnsureItemAt(aIndex);
-    NS_ADDREF(*_retval = mItems[aIndex]);
-    return NS_OK;
-  }
-  *_retval = nsnull;
-  return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  NS_ADDREF(*_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMSVGPointList::InsertItemBefore(nsIDOMSVGPoint *aNewItem,
                                   PRUint32 aIndex,
                                   nsIDOMSVGPoint **_retval)
 {
   *_retval = nsnull;
@@ -413,16 +422,22 @@ DOMSVGPointList::RemoveItem(PRUint32 aIn
 
 NS_IMETHODIMP
 DOMSVGPointList::AppendItem(nsIDOMSVGPoint *aNewItem,
                             nsIDOMSVGPoint **_retval)
 {
   return InsertItemBefore(aNewItem, Length(), _retval);
 }
 
+NS_IMETHODIMP
+DOMSVGPointList::GetLength(PRUint32 *aNumberOfItems)
+{
+  return GetNumberOfItems(aNumberOfItems);
+}
+
 void
 DOMSVGPointList::EnsureItemAt(PRUint32 aIndex)
 {
   if (!mItems[aIndex]) {
     mItems[aIndex] = new DOMSVGPoint(this, aIndex, IsAnimValList());
   }
 }
 
--- a/content/svg/content/src/DOMSVGPointList.h
+++ b/content/svg/content/src/DOMSVGPointList.h
@@ -121,16 +121,18 @@ public:
   PRUint32 Length() const {
     NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
                       mItems.Length() ==
                         const_cast<DOMSVGPointList*>(this)->InternalList().Length(),
                       "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
+  nsIDOMSVGPoint* GetItemWithoutAddRef(PRUint32 aIndex);
+
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
    * Called by internal code to notify us when we need to sync the length of
    * this DOM list with its internal list. This is called immediately prior to
    * the length of the internal list being changed so that any DOM list items
--- a/content/svg/content/src/SVGPathData.cpp
+++ b/content/svg/content/src/SVGPathData.cpp
@@ -119,28 +119,27 @@ SVGPathData::AppendSeg(PRUint32 aType, .
   }
   va_end(args);
   return NS_OK;
 }
 
 float
 SVGPathData::GetPathLength() const
 {
-  float length = 0.0;
   SVGPathTraversalState state;
 
   PRUint32 i = 0;
   while (i < mData.Length()) {
-    length += SVGPathSegUtils::GetLength(&mData[i], state);
+    SVGPathSegUtils::TraversePathSegment(&mData[i], state);
     i += 1 + SVGPathSegUtils::ArgCountForType(mData[i]);
   }
 
   NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
 
-  return length;
+  return state.length;
 }
 
 #ifdef DEBUG
 PRUint32
 SVGPathData::CountItems() const
 {
   PRUint32 i = 0, count = 0;
 
@@ -158,54 +157,55 @@ SVGPathData::CountItems() const
 PRBool
 SVGPathData::GetSegmentLengths(nsTArray<double> *aLengths) const
 {
   aLengths->Clear();
   SVGPathTraversalState state;
 
   PRUint32 i = 0;
   while (i < mData.Length()) {
-    if (!aLengths->AppendElement(SVGPathSegUtils::GetLength(&mData[i], state))) {
+    state.length = 0.0;
+    SVGPathSegUtils::TraversePathSegment(&mData[i], state);
+    if (!aLengths->AppendElement(state.length)) {
       aLengths->Clear();
       return PR_FALSE;
     }
     i += 1 + SVGPathSegUtils::ArgCountForType(mData[i]);
   }
 
   NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
 
   return PR_TRUE;
 }
 
 PRBool
 SVGPathData::GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aOutput) const
 {
-  double distRunningTotal = 0.0;
   SVGPathTraversalState state;
 
   aOutput->Clear();
 
   PRUint32 i = 0;
   while (i < mData.Length()) {
     PRUint32 segType = SVGPathSegUtils::DecodeType(mData[i]);
+    SVGPathSegUtils::TraversePathSegment(&mData[i], state);
 
     // We skip all moveto commands except an initial moveto. See the text 'A
     // "move to" command does not count as an additional point when dividing up
     // the duration...':
     //
     // http://www.w3.org/TR/SVG11/animate.html#AnimateMotionElement
     //
     // This is important in the non-default case of calcMode="linear". In
     // this case an equal amount of time is spent on each path segment,
     // except on moveto segments which are jumped over immediately.
 
     if (i == 0 || (segType != nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS &&
                    segType != nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL)) {
-      distRunningTotal += SVGPathSegUtils::GetLength(&mData[i], state);
-      if (!aOutput->AppendElement(distRunningTotal)) {
+      if (!aOutput->AppendElement(state.length)) {
         return PR_FALSE;
       }
     }
     i += 1 + SVGPathSegUtils::ArgCountForType(segType);
   }
 
   NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt?");
 
@@ -215,23 +215,22 @@ SVGPathData::GetDistancesFromOriginToEnd
 PRUint32
 SVGPathData::GetPathSegAtLength(float aDistance) const
 {
   // TODO [SVGWG issue] get specified what happen if 'aDistance' < 0, or
   // 'aDistance' > the length of the path, or the seg list is empty.
   // Return -1? Throwing would better help authors avoid tricky bugs (DOM
   // could do that if we return -1).
 
-  double distRunningTotal = 0.0;
   PRUint32 i = 0, segIndex = 0;
   SVGPathTraversalState state;
 
   while (i < mData.Length()) {
-    distRunningTotal += SVGPathSegUtils::GetLength(&mData[i], state);
-    if (distRunningTotal >= aDistance) {
+    SVGPathSegUtils::TraversePathSegment(&mData[i], state);
+    if (state.length >= aDistance) {
       return segIndex;
     }
     i += 1 + SVGPathSegUtils::ArgCountForType(mData[i]);
     segIndex++;
   }
 
   NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
 
--- a/content/svg/content/src/SVGPathData.h
+++ b/content/svg/content/src/SVGPathData.h
@@ -100,33 +100,34 @@ class SVGPathData
   friend class SVGAnimatedPathSegList;
   friend class DOMSVGPathSegList;
   friend class DOMSVGPathSeg;
   friend class ::nsSVGPathDataParserToInternal;
   // nsSVGPathDataParserToInternal will not keep wrappers in sync, so consumers
   // are responsible for that!
 
 public:
+  typedef const float* const_iterator;
 
   SVGPathData(){}
   ~SVGPathData(){}
 
   // Only methods that don't make/permit modification to this list are public.
   // Only our friend classes can access methods that may change us.
 
   /// This may return an incomplete string on OOM, but that's acceptable.
   void GetValueAsString(nsAString& aValue) const;
 
   PRBool IsEmpty() const {
     return mData.IsEmpty();
   }
 
 #ifdef DEBUG
   /**
-   * This method iterates over the encoded segment data and countes the number
+   * This method iterates over the encoded segment data and counts the number
    * of segments we currently have.
    */
   PRUint32 CountItems() const;
 #endif
 
   /**
    * Returns the number of *floats* in the encoding array, and NOT the number
    * of segments encoded in this object. (For that, see CountItems() above.)
@@ -173,24 +174,28 @@ public:
    */
   PRBool GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aArray) const;
 
   already_AddRefed<gfxFlattenedPath>
   ToFlattenedPath(const gfxMatrix& aMatrix) const;
 
   void ConstructPath(gfxContext *aCtx) const;
 
+  const_iterator begin() const { return mData.Elements(); }
+  const_iterator end() const { return mData.Elements() + mData.Length(); }
+
   // Access to methods that can modify objects of this type is deliberately
   // limited. This is to reduce the chances of someone modifying objects of
   // this type without taking the necessary steps to keep DOM wrappers in sync.
   // If you need wider access to these methods, consider adding a method to
   // SVGAnimatedPathSegList and having that class act as an intermediary so it
   // can take care of keeping DOM wrappers in sync.
 
 protected:
+  typedef float* iterator;
 
   /**
    * This may fail on OOM if the internal capacity needs to be increased, in
    * which case the list will be left unmodified.
    */
   nsresult CopyFrom(const SVGPathData& rhs);
 
   float& operator[](PRUint32 aIndex) {
@@ -216,32 +221,34 @@ protected:
   //
   // * InsertItem(PRUint32 aDataIndex, PRUint32 aType, const float *aArgs);
   // * ReplaceItem(PRUint32 aDataIndex, PRUint32 aType, const float *aArgs);
   // * RemoveItem(PRUint32 aDataIndex);
   // * PRBool AppendItem(PRUint32 aType, const float *aArgs);
 
   nsresult AppendSeg(PRUint32 aType, ...); // variable number of float args
 
+  iterator begin() { return mData.Elements(); }
+  iterator end() { return mData.Elements() + mData.Length(); }
+
   nsTArray<float> mData;
 };
 
 
 /**
  * This SVGPathData subclass is for SVGPathSegListSMILType which needs to
  * have write access to the lists it works with.
  *
  * Instances of this class do not have DOM wrappers that need to be kept in
  * sync, so we can safely expose any protected base class methods required by
  * the SMIL code.
  */
 class SVGPathDataAndOwner : public SVGPathData
 {
 public:
-
   SVGPathDataAndOwner(nsSVGElement *aElement = nsnull)
     : mElement(aElement)
   {}
 
   void SetElement(nsSVGElement *aElement) {
     mElement = aElement;
   }
 
@@ -254,28 +261,24 @@ public:
     return SVGPathData::CopyFrom(rhs);
   }
 
   /**
    * Exposed so that SVGPathData baseVals can be copied to
    * SVGPathDataAndOwner objects. Note that callers should also call
    * SetElement() when using this method!
    */
-  nsresult CopyFrom(const SVGPathData& rhs) {
-    return SVGPathData::CopyFrom(rhs);
-  }
-  const float& operator[](PRUint32 aIndex) const {
-    return SVGPathData::operator[](aIndex);
-  }
-  float& operator[](PRUint32 aIndex) {
-    return SVGPathData::operator[](aIndex);
-  }
-  PRBool SetLength(PRUint32 aNumberOfItems) {
-    return SVGPathData::SetLength(aNumberOfItems);
-  }
+  using SVGPathData::CopyFrom;
+
+  // Exposed since SVGPathData objects can be modified.
+  using SVGPathData::iterator;
+  using SVGPathData::operator[];
+  using SVGPathData::SetLength;
+  using SVGPathData::begin;
+  using SVGPathData::end;
 
 private:
   // We must keep a strong reference to our element because we may belong to a
   // cached baseVal nsSMILValue. See the comments starting at:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
   nsRefPtr<nsSVGElement> mElement;
 };
 
--- a/content/svg/content/src/SVGPathSegListSMILType.cpp
+++ b/content/svg/content/src/SVGPathSegListSMILType.cpp
@@ -84,59 +84,290 @@ SVGPathSegListSMILType::IsEqual(const ns
 {
   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
 
   return *static_cast<const SVGPathDataAndOwner*>(aLeft.mU.mPtr) ==
          *static_cast<const SVGPathDataAndOwner*>(aRight.mU.mPtr);
 }
 
+static PRBool
+ArcFlagsDiffer(SVGPathDataAndOwner::const_iterator aPathData1,
+               SVGPathDataAndOwner::const_iterator aPathData2)
+{
+  NS_ABORT_IF_FALSE
+    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData1[0])),
+                                "ArcFlagsDiffer called with non-arc segment");
+  NS_ABORT_IF_FALSE
+    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData2[0])),
+                                "ArcFlagsDiffer called with non-arc segment");
+
+  return aPathData1[4] != aPathData2[4] ||  // large arc flag
+         aPathData1[5] != aPathData2[5];    // sweep flag
+}
+
+enum PathInterpolationResult {
+  eCannotInterpolate,
+  eRequiresConversion,
+  eCanInterpolate
+};
+
+static PathInterpolationResult
+CanInterpolate(const SVGPathDataAndOwner& aStart,
+               const SVGPathDataAndOwner& aEnd)
+{
+  if (aStart.IsEmpty()) {
+    return eCanInterpolate;
+  }
+
+  if (aStart.Length() != aEnd.Length()) {
+    return eCannotInterpolate;
+  }
+
+  PathInterpolationResult result = eCanInterpolate;
+
+  SVGPathDataAndOwner::const_iterator pStart = aStart.begin();
+  SVGPathDataAndOwner::const_iterator pEnd = aEnd.begin();
+  SVGPathDataAndOwner::const_iterator pStartDataEnd = aStart.end();
+  SVGPathDataAndOwner::const_iterator pEndDataEnd = aEnd.end();
+
+  while (pStart < pStartDataEnd && pEnd < pEndDataEnd) {
+    PRUint32 startType = SVGPathSegUtils::DecodeType(*pStart);
+    PRUint32 endType = SVGPathSegUtils::DecodeType(*pEnd);
+
+    if (SVGPathSegUtils::IsArcType(startType) &&
+        SVGPathSegUtils::IsArcType(endType) &&
+        ArcFlagsDiffer(pStart, pEnd)) {
+      return eCannotInterpolate;
+    }
+
+    if (startType != endType) {
+      if (!SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType)) {
+        return eCannotInterpolate;
+      }
+
+      result = eRequiresConversion;
+    }
+
+    pStart += 1 + SVGPathSegUtils::ArgCountForType(startType);
+    pEnd += 1 + SVGPathSegUtils::ArgCountForType(endType);
+  }
+
+  NS_ABORT_IF_FALSE(pStart <= pStartDataEnd && pEnd <= pEndDataEnd,
+                    "Iterated past end of buffer! (Corrupt path data?)");
+
+  if (pStart != pStartDataEnd || pEnd != pEndDataEnd) {
+    return eCannotInterpolate;
+  }
+
+  return result;
+}
+
+static void
+InterpolatePathSegmentData(SVGPathDataAndOwner::const_iterator& aStart,
+                           SVGPathDataAndOwner::const_iterator& aEnd,
+                           SVGPathDataAndOwner::iterator& aResult,
+                           float aUnitDistance)
+{
+  PRUint32 startType = SVGPathSegUtils::DecodeType(*aStart);
+  PRUint32 endType = SVGPathSegUtils::DecodeType(*aEnd);
+
+  NS_ABORT_IF_FALSE
+    (startType == endType,
+     "InterpolatePathSegmentData expects segment types to be the same!");
+
+  NS_ABORT_IF_FALSE
+    (!(SVGPathSegUtils::IsArcType(startType) && ArcFlagsDiffer(aStart, aEnd)),
+     "InterpolatePathSegmentData cannot interpolate arc segments with different flag values!");
+
+  PRUint32 argCount = SVGPathSegUtils::ArgCountForType(startType);
+
+  // Copy over segment type.
+  *aResult++ = *aStart++;
+  ++aEnd;
+
+  // Interpolate the arguments.
+  SVGPathDataAndOwner::const_iterator startSegEnd = aStart + argCount;
+  while (aStart != startSegEnd) {
+    *aResult = *aStart + (*aEnd - *aStart) * aUnitDistance;
+    ++aStart;
+    ++aEnd;
+    ++aResult;
+  }
+}
+
+enum RelativenessAdjustmentType {
+  eAbsoluteToRelative,
+  eRelativeToAbsolute
+};
+
+static inline void
+AdjustSegmentForRelativeness(RelativenessAdjustmentType aAdjustmentType,
+                             const SVGPathDataAndOwner::iterator& aSegmentToAdjust,
+                             const SVGPathTraversalState& aState)
+{
+  if (aAdjustmentType == eAbsoluteToRelative) {
+    aSegmentToAdjust[0] -= aState.pos.x;
+    aSegmentToAdjust[1] -= aState.pos.y;
+  } else {
+    aSegmentToAdjust[0] += aState.pos.x;
+    aSegmentToAdjust[1] += aState.pos.y;
+  }
+}
+
+static void
+ConvertPathSegmentData(SVGPathDataAndOwner::const_iterator& aStart,
+                       SVGPathDataAndOwner::const_iterator& aEnd,
+                       SVGPathDataAndOwner::iterator& aResult,
+                       SVGPathTraversalState& aState)
+{
+  PRUint32 startType = SVGPathSegUtils::DecodeType(*aStart);
+  PRUint32 endType = SVGPathSegUtils::DecodeType(*aEnd);
+
+  PRUint32 segmentLengthIncludingType =
+      1 + SVGPathSegUtils::ArgCountForType(startType);
+
+  SVGPathDataAndOwner::const_iterator pResultSegmentBegin = aResult;
+
+  if (startType == endType) {
+    // No conversion need, just directly copy aStart.
+    aEnd += segmentLengthIncludingType;
+    while (segmentLengthIncludingType) {
+      *aResult++ = *aStart++;
+      --segmentLengthIncludingType;
+    }
+    SVGPathSegUtils::TraversePathSegment(pResultSegmentBegin, aState);
+    return;
+  }
+
+  NS_ABORT_IF_FALSE
+      (SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType),
+       "Incompatible path segment types passed to ConvertPathSegmentData!");
+
+  RelativenessAdjustmentType adjustmentType =
+    SVGPathSegUtils::IsRelativeType(startType) ? eRelativeToAbsolute
+                                               : eAbsoluteToRelative;
+
+  NS_ABORT_IF_FALSE
+    (segmentLengthIncludingType ==
+       1 + SVGPathSegUtils::ArgCountForType(endType),
+     "Compatible path segment types for interpolation had different lengths!");
+
+  aResult[0] = aEnd[0];
+
+  switch (endType) {
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
+      aResult[1] = aStart[1] +
+        (adjustmentType == eRelativeToAbsolute ? 1 : -1) * aState.pos.x;
+      break;
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
+      aResult[1] = aStart[1] +
+        (adjustmentType == eRelativeToAbsolute  ? 1 : -1) * aState.pos.y;
+      break;
+    case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
+      aResult[1] = aStart[1];
+      aResult[2] = aStart[2];
+      aResult[3] = aStart[3];
+      aResult[4] = aStart[4];
+      aResult[5] = aStart[5];
+      aResult[6] = aStart[6];
+      aResult[7] = aStart[7];
+      AdjustSegmentForRelativeness(adjustmentType, aResult + 6, aState);
+      break;
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
+      aResult[5] = aStart[5];
+      aResult[6] = aStart[6];
+      AdjustSegmentForRelativeness(adjustmentType, aResult + 5, aState);
+      // fall through
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+      aResult[3] = aStart[3];
+      aResult[4] = aStart[4];
+      AdjustSegmentForRelativeness(adjustmentType, aResult + 3, aState);
+      // fall through
+    case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+    case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+      aResult[1] = aStart[1];
+      aResult[2] = aStart[2];
+      AdjustSegmentForRelativeness(adjustmentType, aResult + 1, aState);
+      break;
+  }
+
+  SVGPathSegUtils::TraversePathSegment(pResultSegmentBegin, aState);
+  aStart += segmentLengthIncludingType;
+  aEnd += segmentLengthIncludingType;
+  aResult += segmentLengthIncludingType;
+}
+
+static void
+ConvertAllPathSegmentData(SVGPathDataAndOwner::const_iterator aStart,
+                          SVGPathDataAndOwner::const_iterator aStartDataEnd,
+                          SVGPathDataAndOwner::const_iterator aEnd,
+                          SVGPathDataAndOwner::const_iterator aEndDataEnd,
+                          SVGPathDataAndOwner::iterator aResult)
+{
+  SVGPathTraversalState state;
+  state.mode = SVGPathTraversalState::eUpdateOnlyStartAndCurrentPos;
+  while (aStart < aStartDataEnd && aEnd < aEndDataEnd) {
+    ConvertPathSegmentData(aStart, aEnd, aResult, state);
+  }
+  NS_ABORT_IF_FALSE(aStart == aStartDataEnd && aEnd == aEndDataEnd,
+                    "Failed to convert all path segment data! (Corrupt?)");
+}
+
 nsresult
 SVGPathSegListSMILType::Add(nsSMILValue& aDest,
                             const nsSMILValue& aValueToAdd,
                             PRUint32 aCount) const
 {
   NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type");
   NS_PRECONDITION(aValueToAdd.mType == this, "Incompatible SMIL type");
 
   SVGPathDataAndOwner& dest =
     *static_cast<SVGPathDataAndOwner*>(aDest.mU.mPtr);
   const SVGPathDataAndOwner& valueToAdd =
     *static_cast<const SVGPathDataAndOwner*>(aValueToAdd.mU.mPtr);
 
-  if (dest.Length() != valueToAdd.Length()) {
-    // Allow addition to empty dest:
-    if (dest.Length() == 0) {
-      return dest.CopyFrom(valueToAdd);
-    }
-    // For now we only support animation to a list with the same number of
-    // items (and with the same segment types).
-    // nsSVGUtils::ReportToConsole
+  // Allow addition to empty dest.
+  if (dest.IsEmpty()) {
+    return dest.CopyFrom(valueToAdd);
+  }
+
+  PathInterpolationResult check = CanInterpolate(dest, valueToAdd);
+
+  if (check == eCannotInterpolate) {
+    // nsSVGUtils::ReportToConsole - can't add path segment lists with different
+    // numbers of segments, with arcs with different flag values, or with
+    // incompatible segment types.
     return NS_ERROR_FAILURE;
   }
 
+  if (check == eRequiresConversion) {
+    ConvertAllPathSegmentData(dest.begin(), dest.end(),
+                              valueToAdd.begin(), valueToAdd.end(),
+                              dest.begin());
+  }
+
   PRUint32 i = 0;
   while (i < dest.Length()) {
     PRUint32 type = SVGPathSegUtils::DecodeType(dest[i]);
-    if (type != SVGPathSegUtils::DecodeType(valueToAdd[i])) {
-      // nsSVGUtils::ReportToConsole - can't yet animate between different
-      // types, although it would make sense to allow animation between
-      // some.
-      return NS_ERROR_FAILURE;
-    }
     i++;
-    if ((type == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS ||
-         type == nsIDOMSVGPathSeg::PATHSEG_ARC_REL) &&
-        (dest[i+3] != valueToAdd[i+3] || dest[i+4] != valueToAdd[i+4])) {
-      // boolean args largeArcFlag and sweepFlag must be the same
-      return NS_ERROR_FAILURE;
-    }
     PRUint32 segEnd = i + SVGPathSegUtils::ArgCountForType(type);
     for (; i < segEnd; ++i) {
-      dest[i] += valueToAdd[i];
+      dest[i] += valueToAdd[i] * aCount;
     }
   }
 
   NS_ABORT_IF_FALSE(i == dest.Length(), "Very, very bad - path data corrupt");
 
   // For now we only support pure 'to' animation.
   // nsSVGUtils::ReportToConsole
   return NS_OK;
@@ -170,73 +401,71 @@ SVGPathSegListSMILType::Interpolate(cons
 
   const SVGPathDataAndOwner& start =
     *static_cast<const SVGPathDataAndOwner*>(aStartVal.mU.mPtr);
   const SVGPathDataAndOwner& end =
     *static_cast<const SVGPathDataAndOwner*>(aEndVal.mU.mPtr);
   SVGPathDataAndOwner& result =
     *static_cast<SVGPathDataAndOwner*>(aResult.mU.mPtr);
 
-  if (start.Length() != end.Length() && start.Length() != 0) {
-    // For now we only support animation to a list with the same number of
-    // items (and with the same segment types).
-    // nsSVGUtils::ReportToConsole
+  PathInterpolationResult check = CanInterpolate(start, end); 
+
+  if (check == eCannotInterpolate) {
+    // nsSVGUtils::ReportToConsole - can't interpolate path segment lists with
+    // different numbers of segments, with arcs with different flag values, or
+    // with incompatible segment types.
     return NS_ERROR_FAILURE;
   }
 
   if (!result.SetLength(end.Length())) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  PRUint32 i = 0;
-
-  if (start.Length() == 0) { // identity path
+  if (start.IsEmpty()) { // identity path
+    PRUint32 i = 0;
     while (i < end.Length()) {
       PRUint32 type = SVGPathSegUtils::DecodeType(end[i]);
       result[i] = end[i];
       i++;
       PRUint32 segEnd = i + SVGPathSegUtils::ArgCountForType(type);
-      if ((type == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS ||
-           type == nsIDOMSVGPathSeg::PATHSEG_ARC_REL)) {
+      if (SVGPathSegUtils::IsArcType(type)) {
         result[i] = end[i] * aUnitDistance;
         result[i+1] = end[i+1] * aUnitDistance;
         result[i+2] = end[i+2] * aUnitDistance;
         // boolean args largeArcFlag and sweepFlag must be the same
         result[i+3] = end[i+3];
         result[i+4] = end[i+4];
         result[i+5] = end[i+5] * aUnitDistance;
         result[i+6] = end[i+6] * aUnitDistance;
         i = segEnd;
       } else {
         for (; i < segEnd; ++i) {
           result[i] = end[i] * aUnitDistance;
         }
       }
     }
+    NS_ABORT_IF_FALSE(i == end.Length() && i == result.Length(),
+                      "Very, very bad - path data corrupt");
   } else {
-    while (i < end.Length()) {
-      PRUint32 type = SVGPathSegUtils::DecodeType(end[i]);
-      if (type != SVGPathSegUtils::DecodeType(start[i])) {
-        // nsSVGUtils::ReportToConsole - can't yet interpolate between different
-        // types, although it would make sense to allow interpolation between
-        // some.
-        return NS_ERROR_FAILURE;
-      }
-      result[i] = end[i];
-      i++;
-      if ((type == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS ||
-           type == nsIDOMSVGPathSeg::PATHSEG_ARC_REL) &&
-          (start[i+3] != end[i+3] || start[i+4] != end[i+4])) {
-        // boolean args largeArcFlag and sweepFlag must be the same
-        return NS_ERROR_FAILURE;
-      }
-      PRUint32 segEnd = i + SVGPathSegUtils::ArgCountForType(type);
-      for (; i < segEnd; ++i) {
-        result[i] = start[i] + (end[i] - start[i]) * aUnitDistance;
-      }
+    SVGPathDataAndOwner::const_iterator pStart = start.begin();
+    SVGPathDataAndOwner::const_iterator pStartDataEnd = start.end();
+    SVGPathDataAndOwner::const_iterator pEnd = end.begin();
+    SVGPathDataAndOwner::const_iterator pEndDataEnd = end.end();
+    SVGPathDataAndOwner::iterator pResult = result.begin();
+
+    if (check == eRequiresConversion) {
+      ConvertAllPathSegmentData(pStart, pStartDataEnd, pEnd, pEndDataEnd,
+                                pResult);
+      pStart = pResult;
+      pStartDataEnd = result.end();
     }
-  }
+
+    while (pStart != pStartDataEnd && pEnd != pEndDataEnd) {
+      InterpolatePathSegmentData(pStart, pEnd, pResult, aUnitDistance);
+    }
 
-  NS_ABORT_IF_FALSE(i == end.Length(), "Very, very bad - path data corrupt");
+    NS_ABORT_IF_FALSE(pStart == pStartDataEnd && pEnd == pEndDataEnd &&
+                      pResult == result.end(),
+                      "Very, very bad - path data corrupt");
+  }
 
   return NS_OK;
 }
-
--- a/content/svg/content/src/SVGPathSegUtils.cpp
+++ b/content/svg/content/src/SVGPathSegUtils.cpp
@@ -49,27 +49,28 @@
 
 using namespace mozilla;
 
 static const float PATH_SEG_LENGTH_TOLERANCE = 0.0000001f;
 static const PRUint32 MAX_RECURSION = 10;
 
 
 /* static */ void
-SVGPathSegUtils::GetValueAsString(const float *aSeg, nsAString& aValue)
+SVGPathSegUtils::GetValueAsString(const float* aSeg, nsAString& aValue)
 {
   // Adding new seg type? Is the formatting below acceptable for the new types?
+  PR_STATIC_ASSERT(NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
+                     nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
   PR_STATIC_ASSERT(NS_SVG_PATH_SEG_MAX_ARGS == 7);
 
   PRUint32 type = DecodeType(aSeg[0]);
   PRUnichar typeAsChar = GetPathSegTypeAsLetter(type);
 
   // Special case arcs:
-  if (type == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS ||
-      type == nsIDOMSVGPathSeg::PATHSEG_ARC_REL) {
+  if (IsArcType(type)) {
     PRBool largeArcFlag = aSeg[4] != 0.0f;
     PRBool sweepFlag = aSeg[5] != 0.0f;
     nsTextFormatter::ssprintf(aValue,
                               NS_LITERAL_STRING("%c%g,%g %g %d,%d %g,%g").get(),
                               typeAsChar, aSeg[1], aSeg[2], aSeg[3],
                               largeArcFlag, sweepFlag, aSeg[6], aSeg[7]);
   } else {
 
@@ -114,348 +115,371 @@ SVGPathSegUtils::GetValueAsString(const 
   //
   if (aValue[aValue.Length() - 1] == PRUnichar('\0')) {
     aValue.SetLength(aValue.Length() - 1);
   }
 }
 
 
 static float
-CalcDistanceBetweenPoints(const gfxPoint &p1, const gfxPoint &p2)
+CalcDistanceBetweenPoints(const gfxPoint& aP1, const gfxPoint& aP2)
 {
-  return NS_hypot(p2.x - p1.x, p2.y - p1.y);
+  return NS_hypot(aP2.x - aP1.x, aP2.y - aP1.y);
 }
 
 
-static void SplitQuadraticBezier(const gfxPoint *curve,
-                                 gfxPoint *left,
-                                 gfxPoint *right)
+static void
+SplitQuadraticBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
 {
-  left[0].x = curve[0].x;
-  left[0].y = curve[0].y;
-  right[2].x = curve[2].x;
-  right[2].y = curve[2].y;
-  left[1].x = (curve[0].x + curve[1].x) / 2;
-  left[1].y = (curve[0].y + curve[1].y) / 2;
-  right[1].x = (curve[1].x + curve[2].x) / 2;
-  right[1].y = (curve[1].y + curve[2].y) / 2;
-  left[2].x = right[0].x = (left[1].x + right[1].x) / 2;
-  left[2].y = right[0].y = (left[1].y + right[1].y) / 2;
+  aLeft[0].x = aCurve[0].x;
+  aLeft[0].y = aCurve[0].y;
+  aRight[2].x = aCurve[2].x;
+  aRight[2].y = aCurve[2].y;
+  aLeft[1].x = (aCurve[0].x + aCurve[1].x) / 2;
+  aLeft[1].y = (aCurve[0].y + aCurve[1].y) / 2;
+  aRight[1].x = (aCurve[1].x + aCurve[2].x) / 2;
+  aRight[1].y = (aCurve[1].y + aCurve[2].y) / 2;
+  aLeft[2].x = aRight[0].x = (aLeft[1].x + aRight[1].x) / 2;
+  aLeft[2].y = aRight[0].y = (aLeft[1].y + aRight[1].y) / 2;
 }
 
-static void SplitCubicBezier(const gfxPoint *curve,
-                             gfxPoint *left,
-                             gfxPoint *right)
+static void
+SplitCubicBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
 {
   gfxPoint tmp;
-  tmp.x = (curve[1].x + curve[2].x) / 4;
-  tmp.y = (curve[1].y + curve[2].y) / 4;
-  left[0].x = curve[0].x;
-  left[0].y = curve[0].y;
-  right[3].x = curve[3].x;
-  right[3].y = curve[3].y;
-  left[1].x = (curve[0].x + curve[1].x) / 2;
-  left[1].y = (curve[0].y + curve[1].y) / 2;
-  right[2].x = (curve[2].x + curve[3].x) / 2;
-  right[2].y = (curve[2].y + curve[3].y) / 2;
-  left[2].x = left[1].x / 2 + tmp.x;
-  left[2].y = left[1].y / 2 + tmp.y;
-  right[1].x = right[2].x / 2 + tmp.x;
-  right[1].y = right[2].y / 2 + tmp.y;
-  left[3].x = right[0].x = (left[2].x + right[1].x) / 2;
-  left[3].y = right[0].y = (left[2].y + right[1].y) / 2;
+  tmp.x = (aCurve[1].x + aCurve[2].x) / 4;
+  tmp.y = (aCurve[1].y + aCurve[2].y) / 4;
+  aLeft[0].x = aCurve[0].x;
+  aLeft[0].y = aCurve[0].y;
+  aRight[3].x = aCurve[3].x;
+  aRight[3].y = aCurve[3].y;
+  aLeft[1].x = (aCurve[0].x + aCurve[1].x) / 2;
+  aLeft[1].y = (aCurve[0].y + aCurve[1].y) / 2;
+  aRight[2].x = (aCurve[2].x + aCurve[3].x) / 2;
+  aRight[2].y = (aCurve[2].y + aCurve[3].y) / 2;
+  aLeft[2].x = aLeft[1].x / 2 + tmp.x;
+  aLeft[2].y = aLeft[1].y / 2 + tmp.y;
+  aRight[1].x = aRight[2].x / 2 + tmp.x;
+  aRight[1].y = aRight[2].y / 2 + tmp.y;
+  aLeft[3].x = aRight[0].x = (aLeft[2].x + aRight[1].x) / 2;
+  aLeft[3].y = aRight[0].y = (aLeft[2].y + aRight[1].y) / 2;
 }
 
-static gfxFloat CalcBezLengthHelper(gfxPoint *curve, PRUint32 numPts,
-                                    PRUint32 recursion_count,
-                                    void (*split)(const gfxPoint*, gfxPoint*, gfxPoint*))
+static gfxFloat
+CalcBezLengthHelper(gfxPoint* aCurve, PRUint32 aNumPts,
+                    PRUint32 aRecursionCount,
+                    void (*aSplit)(const gfxPoint*, gfxPoint*, gfxPoint*))
 {
   gfxPoint left[4];
   gfxPoint right[4];
   gfxFloat length = 0, dist;
-  for (PRUint32 i = 0; i < numPts - 1; i++) {
-    length += CalcDistanceBetweenPoints(curve[i], curve[i+1]);
+  for (PRUint32 i = 0; i < aNumPts - 1; i++) {
+    length += CalcDistanceBetweenPoints(aCurve[i], aCurve[i+1]);
   }
-  dist = CalcDistanceBetweenPoints(curve[0], curve[numPts - 1]);
-  if (length - dist > PATH_SEG_LENGTH_TOLERANCE && recursion_count < MAX_RECURSION) {
-    split(curve, left, right);
-    ++recursion_count;
-    return CalcBezLengthHelper(left, numPts, recursion_count, split) +
-           CalcBezLengthHelper(right, numPts, recursion_count, split);
+  dist = CalcDistanceBetweenPoints(aCurve[0], aCurve[aNumPts - 1]);
+  if (length - dist > PATH_SEG_LENGTH_TOLERANCE &&
+      aRecursionCount < MAX_RECURSION) {
+    aSplit(aCurve, left, right);
+    ++aRecursionCount;
+    return CalcBezLengthHelper(left, aNumPts, aRecursionCount, aSplit) +
+           CalcBezLengthHelper(right, aNumPts, aRecursionCount, aSplit);
   }
   return length;
 }
 
 static inline gfxFloat
-CalcLengthOfCubicBezier(const gfxPoint &pos, const gfxPoint &cp1,
-                        const gfxPoint &cp2, const gfxPoint &to)
+CalcLengthOfCubicBezier(const gfxPoint& aPos, const gfxPoint &aCP1,
+                        const gfxPoint& aCP2, const gfxPoint &aTo)
 {
-  gfxPoint curve[4] = { pos, cp1, cp2, to };
+  gfxPoint curve[4] = { aPos, aCP1, aCP2, aTo };
   return CalcBezLengthHelper(curve, 4, 0, SplitCubicBezier);
 }
 
 static inline gfxFloat
-CalcLengthOfQuadraticBezier(const gfxPoint &pos, const gfxPoint &cp,
-                            const gfxPoint &to)
+CalcLengthOfQuadraticBezier(const gfxPoint& aPos, const gfxPoint& aCP,
+                            const gfxPoint& aTo)
 {
-  gfxPoint curve[3] = { pos, cp, to };
+  gfxPoint curve[3] = { aPos, aCP, aTo };
   return CalcBezLengthHelper(curve, 3, 0, SplitQuadraticBezier);
 }
 
 
-static float GetLengthOfClosePath(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseClosePath(const float* aArgs, SVGPathTraversalState& aState)
 {
-  float dist = CalcDistanceBetweenPoints(aState.pos, aState.start);
-  aState.pos = aState.cp1 = aState.cp2 = aState.start;
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += CalcDistanceBetweenPoints(aState.pos, aState.start);
+    aState.cp1 = aState.cp2 = aState.start;
+  }
+  aState.pos = aState.start;
 }
 
-static float GetLengthOfMovetoAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseMovetoAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  aState.start = aState.pos = aState.cp1 = aState.cp2 = gfxPoint(aArgs[0], aArgs[1]);
-  return 0.0;
-}
-
-static float GetLengthOfMovetoRel(const float *aArgs, SVGPathTraversalState &aState)
-{
-  // aState.pos must be second from right due to +=
-  aState.start = aState.cp1 = aState.cp2 = aState.pos += gfxPoint(aArgs[0], aArgs[1]);
-  return 0.0;
+  aState.start = aState.pos = gfxPoint(aArgs[0], aArgs[1]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    // aState.length is unchanged, since move commands don't affect path length.
+    aState.cp1 = aState.cp2 = aState.start;
+  }
 }
 
-static float GetLengthOfLinetoAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseMovetoRel(const float* aArgs, SVGPathTraversalState& aState)
+{
+  aState.start = aState.pos += gfxPoint(aArgs[0], aArgs[1]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    // aState.length is unchanged, since move commands don't affect path length.
+    aState.cp1 = aState.cp2 = aState.start;
+  }
+}
+
+static void
+TraverseLinetoAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
   gfxPoint to(aArgs[0], aArgs[1]);
-  float dist = CalcDistanceBetweenPoints(aState.pos, to);
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += CalcDistanceBetweenPoints(aState.pos, to);
+    aState.cp1 = aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float GetLengthOfLinetoRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseLinetoRel(const float* aArgs, SVGPathTraversalState& aState)
 {
   gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
-  float dist = CalcDistanceBetweenPoints(aState.pos, to);
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
-}
-
-static float
-GetLengthOfLinetoHorizontalAbs(const float *aArgs, SVGPathTraversalState &aState)
-{
-  gfxPoint to(aArgs[0], aState.pos.y);
-  float dist = fabs(to.x - aState.pos.x);
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += CalcDistanceBetweenPoints(aState.pos, to);
+    aState.cp1 = aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfLinetoHorizontalRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseLinetoHorizontalAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  aState.cp1 = aState.cp2 = aState.pos += gfxPoint(aArgs[0], 0.0);
-  return fabs(aArgs[0]);
+  gfxPoint to(aArgs[0], aState.pos.y);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += fabs(to.x - aState.pos.x);
+    aState.cp1 = aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfLinetoVerticalAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseLinetoHorizontalRel(const float* aArgs, SVGPathTraversalState& aState)
+{
+  aState.pos.x += aArgs[0];
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += fabs(aArgs[0]);
+    aState.cp1 = aState.cp2 = aState.pos;
+  }
+}
+
+static void
+TraverseLinetoVerticalAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
   gfxPoint to(aState.pos.x, aArgs[0]);
-  float dist = fabs(to.y - aState.pos.y);
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
-}
-
-static float
-GetLengthOfLinetoVerticalRel(const float *aArgs, SVGPathTraversalState &aState)
-{
-  aState.cp1 = aState.cp2 = aState.pos += gfxPoint(0.0, aArgs[0]);
-  return fabs(aArgs[0]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += fabs(to.y - aState.pos.y);
+    aState.cp1 = aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float GetLengthOfCurvetoCubicAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseLinetoVerticalRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp1(aArgs[0], aArgs[1]);
-  gfxPoint cp2(aArgs[2], aArgs[3]);
-  gfxPoint to(aArgs[4], aArgs[5]);
-
-  float dist = (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
-
-  aState.cp2 = cp2;
-  aState.pos = aState.cp1 = to;
-
-  return dist;
+  aState.pos.y += aArgs[0];
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    aState.length += fabs(aArgs[0]);
+    aState.cp1 = aState.cp2 = aState.pos;
+  }
 }
 
-static float
-GetLengthOfCurvetoCubicSmoothAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoCubicAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
-  gfxPoint cp2(aArgs[0], aArgs[1]);
-  gfxPoint to(aArgs[2], aArgs[3]);
+  gfxPoint to(aArgs[4], aArgs[5]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp1(aArgs[0], aArgs[1]);
+    gfxPoint cp2(aArgs[2], aArgs[3]);
+    aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
+    aState.cp2 = cp2;
+    aState.cp1 = to;
+  }
+  aState.pos = to;
+}
 
-  float dist = (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
-
-  aState.cp2 = cp2;
-  aState.pos = aState.cp1 = to;
-
-  return dist;
+static void
+TraverseCurvetoCubicSmoothAbs(const float* aArgs, SVGPathTraversalState& aState)
+{
+  gfxPoint to(aArgs[2], aArgs[3]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
+    gfxPoint cp2(aArgs[0], aArgs[1]);
+    aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
+    aState.cp2 = cp2;
+    aState.cp1 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoCubicRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoCubicRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp1 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
-  gfxPoint cp2 = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
-  gfxPoint to  = aState.pos + gfxPoint(aArgs[4], aArgs[5]);
-
-  float dist = (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
-
-  aState.cp2 = cp2;
-  aState.pos = aState.cp1 = to;
-
-  return dist;
+  gfxPoint to = aState.pos + gfxPoint(aArgs[4], aArgs[5]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp1 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+    gfxPoint cp2 = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
+    aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
+    aState.cp2 = cp2;
+    aState.cp1 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoCubicSmoothRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoCubicSmoothRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
-  gfxPoint cp2 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
-  gfxPoint to  = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
-
-  float dist = (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
-
-  aState.cp2 = cp2;
-  aState.pos = aState.cp1 = to;
-
-  return dist;
+  gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
+    gfxPoint cp2 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+    aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
+    aState.cp2 = cp2;
+    aState.cp1 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoQuadraticAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoQuadraticAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp(aArgs[0], aArgs[1]);
   gfxPoint to(aArgs[2], aArgs[3]);
-
-  float dist = (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
-
-  aState.cp1 = cp;
-  aState.pos = aState.cp2 = to;
-
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp(aArgs[0], aArgs[1]);
+    aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
+    aState.cp1 = cp;
+    aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoQuadraticSmoothAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoQuadraticSmoothAbs(const float* aArgs,
+                                  SVGPathTraversalState& aState)
 {
-  gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
   gfxPoint to(aArgs[0], aArgs[1]);
-
-  float dist = (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
-
-  aState.cp1 = cp;
-  aState.pos = aState.cp2 = to;
-
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
+    aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
+    aState.cp1 = cp;
+    aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoQuadraticRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoQuadraticRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint cp = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
   gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
-
-  float dist = (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
-
-  aState.cp1 = cp;
-  aState.pos = aState.cp2 = to;
-
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
+    aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
+    aState.cp1 = cp;
+    aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfCurvetoQuadraticSmoothRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseCurvetoQuadraticSmoothRel(const float* aArgs,
+                                  SVGPathTraversalState& aState)
 {
-  gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
   gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
-
-  float dist = (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
-
-  aState.cp1 = cp;
-  aState.pos = aState.cp2 = to;
-
-  return dist;
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
+    aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
+    aState.cp1 = cp;
+    aState.cp2 = to;
+  }
+  aState.pos = to;
 }
 
-static float
-GetLengthOfArcAbs(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseArcAbs(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint radii(aArgs[0], aArgs[1]);
   gfxPoint to(aArgs[5], aArgs[6]);
-  gfxPoint bez[4] = { aState.pos, gfxPoint(0,0), gfxPoint(0,0), gfxPoint(0,0) };
-  nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
-                              aArgs[3] != 0, aArgs[4] != 0);
-  float dist = 0;
-  while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3]))
-  {
-    dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
-    bez[0] = bez[3];
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    float dist = 0;
+    gfxPoint radii(aArgs[0], aArgs[1]);
+    gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
+                        gfxPoint(0, 0), gfxPoint(0, 0) };
+    nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
+                                aArgs[3] != 0, aArgs[4] != 0);
+    while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
+      dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
+      bez[0] = bez[3];
+    }
+    aState.length += dist;
+    aState.cp1 = aState.cp2 = to;
   }
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
+  aState.pos = to;
 }
 
-static float
-GetLengthOfArcRel(const float *aArgs, SVGPathTraversalState &aState)
+static void
+TraverseArcRel(const float* aArgs, SVGPathTraversalState& aState)
 {
-  gfxPoint radii(aArgs[0], aArgs[1]);
   gfxPoint to = aState.pos + gfxPoint(aArgs[5], aArgs[6]);
-  gfxPoint bez[4] = { aState.pos, gfxPoint(0,0), gfxPoint(0,0), gfxPoint(0,0) };
-  nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
-                              aArgs[3] != 0, aArgs[4] != 0);
-  float dist = 0;
-  while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3]))
-  {
-    dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
-    bez[0] = bez[3];
+  if (aState.ShouldUpdateLengthAndControlPoints()) {
+    float dist = 0;
+    gfxPoint radii(aArgs[0], aArgs[1]);
+    gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
+                        gfxPoint(0, 0), gfxPoint(0, 0) };
+    nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
+                                aArgs[3] != 0, aArgs[4] != 0);
+    while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
+      dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
+      bez[0] = bez[3];
+    }
+    aState.length += dist;
+    aState.cp1 = aState.cp2 = to;
   }
-  aState.pos = aState.cp1 = aState.cp2 = to;
-  return dist;
+  aState.pos = to;
 }
 
 
-typedef float (*getLengthFunc)(const float*, SVGPathTraversalState&);
-
-/* static */ float
-SVGPathSegUtils::GetLength(const float *seg, SVGPathTraversalState &aState)
-{
-  PRUint32 type = DecodeType(seg[0]);
+typedef void (*TraverseFunc)(const float*, SVGPathTraversalState&);
 
-  static getLengthFunc lengthFuncTable[20] = {
-    nsnull, //  0 == PATHSEG_UNKNOWN
-    GetLengthOfClosePath,
-    GetLengthOfMovetoAbs,
-    GetLengthOfMovetoRel,
-    GetLengthOfLinetoAbs,
-    GetLengthOfLinetoRel,
-    GetLengthOfCurvetoCubicAbs,
-    GetLengthOfCurvetoCubicRel,
-    GetLengthOfCurvetoQuadraticAbs,
-    GetLengthOfCurvetoQuadraticRel,
-    GetLengthOfArcAbs,
-    GetLengthOfArcRel,
-    GetLengthOfLinetoHorizontalAbs,
-    GetLengthOfLinetoHorizontalRel,
-    GetLengthOfLinetoVerticalAbs,
-    GetLengthOfLinetoVerticalRel,
-    GetLengthOfCurvetoCubicSmoothAbs,
-    GetLengthOfCurvetoCubicSmoothRel,
-    GetLengthOfCurvetoQuadraticSmoothAbs,
-    GetLengthOfCurvetoQuadraticSmoothRel
-  };
+static TraverseFunc gTraverseFuncTable[NS_SVG_PATH_SEG_TYPE_COUNT] = {
+  nsnull, //  0 == PATHSEG_UNKNOWN
+  TraverseClosePath,
+  TraverseMovetoAbs,
+  TraverseMovetoRel,
+  TraverseLinetoAbs,
+  TraverseLinetoRel,
+  TraverseCurvetoCubicAbs,
+  TraverseCurvetoCubicRel,
+  TraverseCurvetoQuadraticAbs,
+  TraverseCurvetoQuadraticRel,
+  TraverseArcAbs,
+  TraverseArcRel,
+  TraverseLinetoHorizontalAbs,
+  TraverseLinetoHorizontalRel,
+  TraverseLinetoVerticalAbs,
+  TraverseLinetoVerticalRel,
+  TraverseCurvetoCubicSmoothAbs,
+  TraverseCurvetoCubicSmoothRel,
+  TraverseCurvetoQuadraticSmoothAbs,
+  TraverseCurvetoQuadraticSmoothRel
+};
 
-  NS_ABORT_IF_FALSE(IsValidType(type), "Seg type not recognized");
-
-  NS_ABORT_IF_FALSE(type > 0 && type < NS_ARRAY_LENGTH(lengthFuncTable),
-                    "Seg type not recognized");
-
-  return lengthFuncTable[type](seg + 1, aState);
+/* static */ void
+SVGPathSegUtils::TraversePathSegment(const float* aData,
+                                     SVGPathTraversalState& aState)
+{
+  PR_STATIC_ASSERT(NS_ARRAY_LENGTH(gTraverseFuncTable) ==
+                     NS_SVG_PATH_SEG_TYPE_COUNT);
+  PRUint32 type = DecodeType(aData[0]);
+  gTraverseFuncTable[type](aData + 1, aState);
 }
-
--- a/content/svg/content/src/SVGPathSegUtils.h
+++ b/content/svg/content/src/SVGPathSegUtils.h
@@ -38,45 +38,61 @@
 #define MOZILLA_SVGPATHSEGUTILS_H__
 
 #include "nsIDOMSVGPathSeg.h"
 #include "nsIContent.h"
 #include "nsAString.h"
 #include "nsContentUtils.h"
 #include "gfxPoint.h"
 
-#define NS_SVG_PATH_SEG_MAX_ARGS 7
+#define NS_SVG_PATH_SEG_MAX_ARGS         7
+#define NS_SVG_PATH_SEG_FIRST_VALID_TYPE nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH
+#define NS_SVG_PATH_SEG_LAST_VALID_TYPE  nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
+#define NS_SVG_PATH_SEG_TYPE_COUNT       (NS_SVG_PATH_SEG_LAST_VALID_TYPE + 1)
 
 namespace mozilla {
 
 /**
  * Code that works with path segments can use an instance of this class to
  * store/provide information about the start of the current subpath and the
  * last path segment (if any).
  */
 struct SVGPathTraversalState
 {
+  enum TraversalMode {
+    eUpdateAll,
+    eUpdateOnlyStartAndCurrentPos
+  };
+
   SVGPathTraversalState()
     : start(0.0, 0.0)
     , pos(0.0, 0.0)
     , cp1(0.0, 0.0)
     , cp2(0.0, 0.0)
+    , length(0.0)
+    , mode(eUpdateAll)
   {}
 
+  PRBool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; }
+
   gfxPoint start; // start point of current sub path (reset each moveto)
 
   gfxPoint pos;   // current position (end point of previous segment)
 
   gfxPoint cp1;   // quadratic control point - if the previous segment was a
                   // quadratic bezier curve then this is set to the absolute
                   // position of its control point, otherwise its set to pos
 
   gfxPoint cp2;   // cubic control point - if the previous segment was a cubic
                   // bezier curve then this is set to the absolute position of
                   // its second control point, otherwise it's set to pos
+
+  float length;   // accumulated path length
+
+  TraversalMode mode;  // indicates what to track while traversing a path
 };
 
 
 /**
  * This class is just a collection of static methods - it doesn't have any data
  * members, and it's not possible to create instances of this class. This class
  * exists purely as a convenient place to gather together a bunch of methods
  * related to manipulating and answering questions about path segments.
@@ -139,16 +155,17 @@ public:
       PRUnichar('h'),  // 13 == PATHSEG_LINETO_HORIZONTAL_REL
       PRUnichar('V'),  // 14 == PATHSEG_LINETO_VERTICAL_ABS
       PRUnichar('v'),  // 15 == PATHSEG_LINETO_VERTICAL_REL
       PRUnichar('S'),  // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
       PRUnichar('s'),  // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
       PRUnichar('T'),  // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
       PRUnichar('t')   // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
     };
+    PR_STATIC_ASSERT(NS_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT);
 
     return table[aType];
   }
 
   static PRUint32 ArgCountForType(PRUint32 aType) {
     NS_ABORT_IF_FALSE(IsValidType(aType), "Seg type not recognized");
 
     static const PRUint8 table[] = {
@@ -168,50 +185,101 @@ public:
       1,  // 13 == PATHSEG_LINETO_HORIZONTAL_REL
       1,  // 14 == PATHSEG_LINETO_VERTICAL_ABS
       1,  // 15 == PATHSEG_LINETO_VERTICAL_REL
       4,  // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
       4,  // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
       2,  // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
       2   // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
     };
+    PR_STATIC_ASSERT(NS_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT);
 
     return table[aType];
   }
 
   /**
    * Convenience so that callers can pass a float containing an encoded type
    * and have it decoded implicitly.
    */
   static PRUint32 ArgCountForType(float aType) {
     return ArgCountForType(DecodeType(aType));
   }
 
-  static inline PRBool IsValidType(PRUint32 aType) {
-    return aType >= nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH &&
-           aType <= nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+  static PRBool IsValidType(PRUint32 aType) {
+    return aType >= NS_SVG_PATH_SEG_FIRST_VALID_TYPE &&
+           aType <= NS_SVG_PATH_SEG_LAST_VALID_TYPE;
   }
 
-  static inline PRBool IsCubicType(PRUint32 aType) {
+  static PRBool IsCubicType(PRUint32 aType) {
     return aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
   }
 
-  static inline PRBool IsQuadraticType(PRUint32 aType) {
+  static PRBool IsQuadraticType(PRUint32 aType) {
     return aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
            aType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
   }
 
+  static PRBool IsArcType(PRUint32 aType) {
+    return aType == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS || 
+           aType == nsIDOMSVGPathSeg::PATHSEG_ARC_REL;
+  }
+
+  static PRBool IsRelativeOrAbsoluteType(PRUint32 aType) {
+    NS_ABORT_IF_FALSE(IsValidType(aType), "Seg type not recognized");
+
+    // When adding a new path segment type, ensure that the returned condition
+    // below is still correct.
+    PR_STATIC_ASSERT(NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
+                       nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
+
+    return aType >= nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS;
+  }
+
+  static PRBool IsRelativeType(PRUint32 aType) {
+    NS_ABORT_IF_FALSE
+      (IsRelativeOrAbsoluteType(aType),
+       "IsRelativeType called with segment type that does not come in relative and absolute forms");
+
+    // When adding a new path segment type, ensure that the returned condition
+    // below is still correct.
+    PR_STATIC_ASSERT(NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
+                       nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
+
+    return aType & 1;
+  }
+
+  static PRUint32 RelativeVersionOfType(PRUint32 aType) {
+    NS_ABORT_IF_FALSE
+      (IsRelativeOrAbsoluteType(aType),
+       "RelativeVersionOfType called with segment type that does not come in relative and absolute forms");
+
+    // When adding a new path segment type, ensure that the returned condition
+    // below is still correct.
+    PR_STATIC_ASSERT(NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
+                       nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
+
+    return aType | 1;
+  }
+
+  static PRUint32 SameTypeModuloRelativeness(PRUint32 aType1, PRUint32 aType2) {
+    if (!IsRelativeOrAbsoluteType(aType1)) {
+      return aType1 == aType2;
+    }
+
+    return RelativeVersionOfType(aType1) == RelativeVersionOfType(aType2);
+  }
+
   /**
-   * Returns the user unit length of tracing along the path segment.
+   * Traverse the given path segment and update the SVGPathTraversalState
+   * object.
    */
-  static float GetLength(const float *aSeg, SVGPathTraversalState &aState);
-
-  static void ToString(const float *aSeg, nsAString& aValue);
+  static void TraversePathSegment(const float* aData,
+                                  SVGPathTraversalState& aState);
 };
 
 } // namespace mozilla
 
 #endif // MOZILLA_SVGPATHSEGUTILS_H__
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -142,17 +142,18 @@ nsSVGAnimationElement::GetTargetElementC
   if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
     return mHrefTarget.get();
   }
   NS_ABORT_IF_FALSE(!mHrefTarget.get(),
                     "We shouldn't have an xlink:href target "
                     "if we don't have an xlink:href attribute");
 
   // No "xlink:href" attribute --> I should target my parent.
-  return nsSVGUtils::GetParentElement(this);
+  nsIContent* parent = GetFlattenedTreeParent();
+  return parent && parent->IsElement() ? parent->AsElement() : nsnull;
 }
 
 PRBool
 nsSVGAnimationElement::GetTargetAttributeName(PRInt32 *aNamespaceID,
                                               nsIAtom **aLocalName) const
 {
   const nsAttrValue* nameAttr
     = mAttrsAndChildren.GetAttr(nsGkAtoms::attributeName);
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -283,17 +283,17 @@ nsSVGElement::AfterSetAttr(PRInt32 aName
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (aNamespaceID == kNameSpaceID_None &&
       (aName == nsGkAtoms::requiredFeatures ||
        aName == nsGkAtoms::requiredExtensions ||
        aName == nsGkAtoms::systemLanguage)) {
 
-    nsIContent* parent = nsSVGUtils::GetParentElement(this);
+    nsIContent* parent = GetFlattenedTreeParent();
   
     if (parent &&
         parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) {
       static_cast<nsSVGSwitchElement*>(parent)->MaybeInvalidate();
     }
   }
 
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
@@ -1406,27 +1406,27 @@ nsIAtom* nsSVGElement::GetEventNameForAt
 #endif // MOZ_SMIL
 
   return aAttr;
 }
 
 nsSVGSVGElement *
 nsSVGElement::GetCtx()
 {
-  dom::Element* ancestor = nsSVGUtils::GetParentElement(this);
+  nsIContent* ancestor = GetFlattenedTreeParent();
 
   while (ancestor && ancestor->GetNameSpaceID() == kNameSpaceID_SVG) {
     nsIAtom* tag = ancestor->Tag();
     if (tag == nsGkAtoms::foreignObject) {
       return nsnull;
     }
     if (tag == nsGkAtoms::svg) {
       return static_cast<nsSVGSVGElement*>(ancestor);
     }
-    ancestor = nsSVGUtils::GetParentElement(ancestor);
+    ancestor = ancestor->GetFlattenedTreeParent();
   }
 
   // we don't have an ancestor <svg> element...
   return nsnull;
 }
 
 /* virtual */ gfxMatrix
 nsSVGElement::PrependLocalTransformTo(const gfxMatrix &aMatrix)
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -75,17 +75,17 @@ class SVGAnimatedNumberList;
 class SVGNumberList;
 class SVGAnimatedLengthList;
 class SVGUserUnitList;
 class SVGAnimatedPointList;
 class SVGAnimatedPathSegList;
 class SVGAnimatedPreserveAspectRatio;
 }
 
-typedef nsStyledElement nsSVGElementBase;
+typedef nsStyledElementNotElementCSSInlineStyle nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase,    // nsIContent
                      public nsISVGValueObserver  // :nsISupportsWeakReference
 {
 protected:
   nsSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   nsresult Init();
   virtual ~nsSVGElement();
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -314,19 +314,19 @@ inline static void DidAnimateAttr(Elemen
   if (frame) {
     nsSVGEffects::InvalidateRenderingObservers(frame);
   }
 }
 
 inline static void DidAnimateAttrViaParent(Element *aFilterPrimitive) {
   // No frame, use parent's
   NS_ASSERTION(!aFilterPrimitive->GetPrimaryFrame(), "Not expecting a frame");
-  Element *parent = nsSVGUtils::GetParentElement(aFilterPrimitive);
-  if (parent) {
-    DidAnimateAttr(parent);
+  nsIContent *parent = aFilterPrimitive->GetFlattenedTreeParent();
+  if (parent && parent->IsElement()) {
+    DidAnimateAttr(parent->AsElement());
   }
 }
 
 void
 nsSVGFE::DidAnimateLength(PRUint8 aAttrEnum)
 {
   DidAnimateAttr(this);
 }
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -267,17 +267,17 @@ protected:
     return IsInDoc() && !GetParent();
   }
 
   /**
    * Returns true if this is an SVG <svg> element that is the child of
    * another non-foreignObject SVG element.
    */
   PRBool IsInner() {
-    const mozilla::dom::Element *parent = nsSVGUtils::GetParentElement(this);
+    const nsIContent *parent = GetFlattenedTreeParent();
     return parent && parent->GetNameSpaceID() == kNameSpaceID_SVG &&
            parent->Tag() != nsGkAtoms::foreignObject;
   }
 
 #ifdef MOZ_SMIL
   /* 
    * While binding to the tree we need to determine if we will be the outermost
    * <svg> element _before_ the children are bound (as they want to know what
--- a/content/svg/content/src/nsSVGTransformList.h
+++ b/content/svg/content/src/nsSVGTransformList.h
@@ -73,16 +73,17 @@ public:
   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
                                      modificationType aModType);
   
   // nsISupportsWeakReference
   // implementation inherited from nsSupportsWeakReference
 
   
   // other methods:
+  nsIDOMSVGTransform* GetItemWithoutAddRef(PRInt32 index);
   nsIDOMSVGTransform* ElementAt(PRInt32 index);
   PRBool AppendElement(nsIDOMSVGTransform* aElement);
   static already_AddRefed<nsIDOMSVGMatrix>
   GetConsolidationMatrix(nsIDOMSVGTransformList *transforms);
   
 protected:
   PRInt32 ParseParameterList(char *paramstr, float *vars, PRInt32 nvars);
   void ReleaseTransforms();
--- a/content/svg/content/test/Makefile.in
+++ b/content/svg/content/test/Makefile.in
@@ -44,57 +44,59 @@ relativesrcdir  = content/svg/content/te
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # Disabled:
 #		bbox-helper.svg \
 #		test_length.xhtml \
 
 _TEST_FILES = \
+		test_a_href_01.xhtml \
+		test_a_href_02.xhtml \
+		a_href_destination.svg \
+		a_href_helper_01.svg \
+		a_href_helper_02_03.svg \
+		a_href_helper_04.svg \
 		test_animLengthObjectIdentity.xhtml \
 		test_animLengthReadonly.xhtml \
 		test_animLengthRelativeUnits.xhtml \
 		test_animLengthUnits.xhtml \
 		test_bbox.xhtml \
 		bbox-helper.svg \
 		bounds-helper.svg \
 		test_dataTypes.html \
 		dataTypes-helper.svg \
 		getCTM-helper.svg \
 		test_getCTM.html \
 		test_getSubStringLength.xhtml \
 		getSubStringLength-helper.svg \
 		test_isSupported.xhtml \
 		test_nonAnimStrings.xhtml \
+		test_pathAnimInterpolation.xhtml \
 		test_pathSeg.xhtml \
 		test_pointer-events.xhtml \
 		test_pointer-events-2.xhtml \
 		test_scientific.html \
 		scientific-helper.svg \
 		test_SVGAnimatedImageSMILDisabled.html \
 		animated-svg-image-helper.html \
 		animated-svg-image-helper.svg \
 		test_SVGLengthList.xhtml \
 		test_SVGLengthList-2.xhtml \
 		test_SVGPathSegList.xhtml \
 		test_SVGStyleElement.xhtml \
 		test_SVGxxxList.xhtml \
+		test_SVGxxxListIndexing.xhtml \
 		test_switch.xhtml \
 		switch-helper.svg \
 		test_text.html \
 		text-helper.svg \
 		test_transform.xhtml \
 		test_valueAsString.xhtml \
 		test_valueLeaks.xhtml \
 		viewport-helper.svg \
 		test_viewport.html \
 		zoom-helper.svg \
 		test_zoom.xhtml \
-		test_a_href_01.xhtml \
-		test_a_href_02.xhtml \
-		a_href_destination.svg \
-		a_href_helper_01.svg \
-		a_href_helper_02_03.svg \
-		a_href_helper_04.svg \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_SVGxxxListIndexing.xhtml
@@ -0,0 +1,83 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=631437
+-->
+<head>
+  <title>Tests the array indexing and .length on SVGXXXList objects</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=631437">Mozilla Bug 631437</a>
+<svg xmlns="http://www.w3.org/2000/svg" id="svg">
+  <text id="text" x="10 20 30" rotate="40 50 60">abcde</text>
+  <path id="path" d="M0,0 L100,100"/>
+  <polygon id="poly" points="50,50 70,70 90,50"/>
+</svg>
+<script type="text/javascript;version=1.8"><![CDATA[
+var text = document.getElementById("text"),
+    path = document.getElementById("path"),
+    poly = document.getElementById("poly");
+
+function CheckList(aListObject, aExpectedListLength, aListDescription)
+{
+  is(aListObject.numberOfItems, aExpectedListLength, aListDescription + ".numberOfItems");
+  is(aListObject.numberOfItems, aExpectedListLength, aListDescription + ".length");
+  for (let i = 0; i < aListObject.length; i++) {
+    let item = aListObject.getItem(i);
+    ok(aListObject[i] === item, aListDescription + "[" + i + "]");
+  }
+  ok(aListObject[aListObject.length] === void 0, aListDescription + "[outOfBounds]");
+}
+
+var tests = [
+  { element: text,
+    attribute: "x",
+    listProperty: "x.baseVal",
+    type: "SVGLengthList",
+    subtests: [ { values: null, length: 3 },
+                { values: "40", length: 1 },
+                { values: "1em 2em 3em 4em 5em", length: 5 } ] },
+  { element: text,
+    attribute: "rotate",
+    listProperty: "rotate.baseVal",
+    type: "SVGNumberList",
+    subtests: [ { values: null, length: 3 },
+                { values: "10", length: 1 },
+                { values: "1 2 3 4 5", length: 5 } ] },
+  { element: path,
+    attribute: "d",
+    listProperty: "pathSegList",
+    type: "SVGPathSegList",
+    subtests: [ { values: null, length: 2 },
+                { values: "M50,50", length: 1 },
+                { values: "M0,0 h10 v20 h30 v40", length: 5 } ] },
+  { element: poly,
+    attribute: "points",
+    listProperty: "animatedPoints",
+    type: "SVGPointList",
+    subtests: [ { values: null, length: 3 },
+                { values: "100,100", length: 1 },
+                { values: "0,0 10,10 20,0 30,10 40,0", length: 5 } ] }
+];
+
+for each (let test in tests) {
+  let list = test.element;
+  for each (let property in test.listProperty.split(".")) {
+    list = list[property];
+  }
+
+  for each (let subtest in test.subtests) {
+    if (subtest.values) {
+      test.element.setAttribute(test.attribute, subtest.values);
+    }
+
+    CheckList(list, subtest.length,
+              test.type + ": " + test.element.localName + "." +
+                test.listProperty);
+  }
+}
+]]></script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_pathAnimInterpolation.xhtml
@@ -0,0 +1,345 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=619498
+-->
+<head>
+  <title>Test interpolation between different path segment types</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=619498">Mozilla Bug 619498</a>
+<svg xmlns="http://www.w3.org/2000/svg" id="svg" visibility="hidden"
+     onload="this.pauseAnimations()"/>
+<script type="application/javascript;version=1.8"><![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+var gSVG = document.getElementById("svg");
+
+// Array of all subtests to run.  This is populated by addTest.
+var gTests = [];
+
+// Array of all path segment types.
+var gTypes = "zMmLlCcQqAaHhVvSsTt".split("");
+
+// Property names on the SVGPathSeg objects for the given segment type, in the
+// order that they would appear in a path data string.
+var gArgumentNames = {
+  Z: [],
+  M: ['x', 'y'],
+  L: ['x', 'y'],
+  C: ['x1', 'y1', 'x2', 'y2', 'x', 'y'],
+  Q: ['x1', 'y1', 'x', 'y'],
+  A: ['r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag', 'x', 'y'],
+  H: ['x'],
+  V: ['y'],
+  S: ['x2', 'y2', 'x', 'y'],
+  T: ['x', 'y']
+};
+
+// All of these prefixes leave the current point at 100,100.  Some of them
+// affect the implied control point if followed by a smooth quadratic or
+// cubic segment, but no valid interpolations depend on those control points.
+var gPrefixes = [
+  [1, "M100,100"],
+  [2, "M50,50 M100,100"],
+  [2, "M50,50 m50,50"],
+  [2, "M50,50 L100,100"],
+  [2, "M50,50 l50,50"],
+  [3, "M50,50 H100 V100"],
+  [3, "M50,50 h50 V100"],
+  [3, "M50,50 H100 v50"],
+  [2, "M50,50 A10,10,10,0,0,100,100"],
+  [2, "M50,50 a10,10,10,0,0,50,50"],
+  [4, "M50,50 l50,50 z m50,50"],
+
+  // These leave the quadratic implied control point at 125,125.
+  [2, "M50,50 Q75,75,100,100"],
+  [2, "M50,50 q25,25,50,50"],
+  [2, "M75,75 T100,100"],
+  [2, "M75,75 t25,25"],
+  [3, "M50,50 T62.5,62.5 t37.5,37.5"],
+  [3, "M50,50 T62.5,62.5 T100,100"],
+  [3, "M50,50 t12.5,12.5 t37.5,37.5"],
+  [3, "M50,50 t12.5,12.5 T100,100"],
+  [3, "M50,50 Q50,50,62.5,62.5 t37.5,37.5"],
+  [3, "M50,50 Q50,50,62.5,62.5 T100,100"],
+  [3, "M50,50 q0,0,12.5,12.5 t37.5,37.5"],
+  [3, "M50,50 q0,0,12.5,12.5 T100,100"],
+
+  // These leave the cubic implied control point at 125,125.
+  [2, "M50,50 C10,10,75,75,100,100"],
+  [2, "M50,50 c10,10,25,25,50,50"],
+  [2, "M50,50 S75,75,100,100"],
+  [2, "M50,50 s25,25,50,50"],
+  [3, "M50,50 S10,10,75,75 S75,75,100,100"],
+  [3, "M50,50 S10,10,75,75 s0,0,25,25"],
+  [3, "M50,50 s10,10,25,25 S75,75,100,100"],
+  [3, "M50,50 s10,10,25,25 s0,0,25,25"],
+  [3, "M50,50 C10,10,20,20,75,75 S75,75,100,100"],
+  [3, "M50,50 C10,10,20,20,75,75 s0,0,25,25"],
+  [3, "M50,50 c10,10,20,20,25,25 S75,75,100,100"],
+  [3, "M50,50 c10,10,20,20,25,25 s0,0,25,25"]
+];
+
+// These are all of the suffixes whose result is not dependent on whether the
+// preceding segment types are quadratic or cubic types.  Each entry is:
+//
+//   "<fromType><toType>": [fromArguments,
+//                          toArguments,
+//                          expectedArguments,
+//                          expectedArgumentsAdditive]
+//
+// As an example:
+//
+//   "Mm": [[10, 20], [30, 40], [-30, -20], [-120, -100]]
+//
+// This will testing interpolating between "M10,20" and "m30,40". All of the
+// these tests assume that the current point is left at 100,100.  So the above
+// entry represents two kinds of tests, one where additive and one not:
+//
+//   <path d="... M10,20">
+//     <animate attributeName="d" from="... M10,20" to="... m30,40"/>
+//   </path>
+//
+// and
+//
+//   <path d="... M10,20">
+//     <animate attributeName="d" from="... M10,20" to="... m30,40"
+//              additive="sum"/>
+//   </path>
+//
+// where the "..." is some prefix that leaves the current point at 100,100.
+// Each of the suffixes here in gSuffixes will be paired with each of the
+// prefixes in gPrefixes, all of which leave the current point at 100,100.
+// (Thus the above two tests for interpolating between "M" and "m" will be
+// performed many times, with different preceding commands.)
+//
+// The expected result of the non-additive test is "m-30,-20".  Since the
+// animation is from an absolute moveto to a relative moveto, we first
+// convert the "M10,20" into its relative form, which is "m-90,-80" due to the
+// current point being 100,100.  Half way through the animation between
+// "m-90,-80" and "m30,40" is thus "m-30,-20".
+// 
+// The expected result of the additive test is "m-120,-100".  We take the
+// halfway value of the animation, "m-30,-20" and add it on to the underlying
+// value.  Since the underlying value "M10,20" is an absolute moveto, we first
+// convert it to relative, "m-90,-80", and then add the "m-30,-20" to it,
+// giving us the result "m-120,-100".
+var gSuffixes = {
+  // Same path segment type, no conversion required.
+  MM: [[10, 20], [30, 40], [20, 30], [30, 50]],
+  mm: [[10, 20], [30, 40], [20, 30], [30, 50]],
+  LL: [[10, 20], [30, 40], [20, 30], [30, 50]],
+  ll: [[10, 20], [30, 40], [20, 30], [30, 50]],
+  CC: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
+       [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
+  cc: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
+       [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
+  QQ: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
+  qq: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
+  AA: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
+  aa: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
+  HH: [[10], [20], [15], [25]],
+  hh: [[10], [20], [15], [25]],
+  VV: [[10], [20], [15], [25]],
+  vv: [[10], [20], [15], [25]],
+  SS: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
+  ss: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
+  TT: [[10, 20], [30, 40], [20, 30], [30, 50]],
+  tt: [[10, 20], [30, 40], [20, 30], [30, 50]],
+
+  // Relative <-> absolute conversion.
+  Mm: [[10, 20], [30, 40], [-30, -20], [-120, -100]],
+  mM: [[10, 20], [30, 40], [70, 80], [180, 200]],
+  Ll: [[10, 20], [30, 40], [-30, -20], [-120, -100]],
+  lL: [[10, 20], [30, 40], [70, 80], [180, 200]],
+  Cc: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
+       [-10, 0, 10, 20, 30, 40], [-100, -80, -60, -40, -20, 0]],
+  cC: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
+       [90, 100, 110, 120, 130, 140], [200, 220, 240, 260, 280, 300]],
+  Qq: [[10, 20, 30, 40], [50, 60, 70, 80],
+       [-20, -10, 0, 10], [-110, -90, -70, -50]],
+  qQ: [[10, 20, 30, 40], [50, 60, 70, 80],
+       [80, 90, 100, 110], [190, 210, 230, 250]],
+  Aa: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 15, 25], [45, 65, 85, 0, 0, -45, -25]],
+  aA: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 0, 115, 125], [45, 65, 85, 0, 0, 255, 275]],
+  Hh: [[10], [20], [-35], [-125]],
+  hH: [[10], [20], [65], [175]],
+  Vv: [[10], [20], [-35], [-125]],
+  vV: [[10], [20], [65], [175]],
+  Tt: [[10, 20], [30, 40], [-30,-20], [-120, -100]],
+  tT: [[10, 20], [30, 40], [70, 80], [180, 200]],
+  Ss: [[10, 20, 30, 40], [50, 60, 70, 80],
+       [-20, -10, 0, 10], [-110, -90, -70, -50]],
+  sS: [[10, 20, 30, 40], [50, 60, 70, 80],
+       [80, 90, 100, 110], [190, 210, 230, 250]]
+};
+
+// Returns an array of property names that exist on an SVGPathSeg object
+// corresponding to the given segment type, in the order that they would
+// be present in a path data string.
+function argumentNames(aType)
+{
+  return gArgumentNames[aType.toUpperCase()];
+}
+
+// Creates and returns a new element and sets some attributes on it.
+function newElement(aNamespaceURI, aLocalName, aAttributes)
+{
+  var e = document.createElementNS(aNamespaceURI, aLocalName);
+  if (aAttributes) {
+    for (let [name, value] in Iterator(aAttributes)) {
+      e.setAttribute(name, value);
+    }
+  }
+  return e;
+}
+
+// Creates and returns a new SVG element and sets some attributes on it.
+function newSVGElement(aLocalName, aAttributes)
+{
+  return newElement("http://www.w3.org/2000/svg", aLocalName, aAttributes);
+}
+
+// Creates a subtest and adds it to the document.
+//
+// * aPrefixLength/aPrefix              the prefix to use
+// * aFromType/aFromArguments           the segment to interpolate from
+// * aToType/aToArguments               the segment to interpolate to
+// * aExpectedType/aExpectedArguments   the expected result of the interpolated
+//                                        segment half way through the animation
+//                                        duration
+// * aAdditive                          whether the subtest is for an additive
+//                                        animation
+function addTest(aPrefixLength, aPrefix, aFromType, aFromArguments,
+                 aToType, aToArguments, aExpectedType, aExpectedArguments,
+                 aAdditive)
+{
+  var fromPath = aPrefix + aFromType + aFromArguments,
+      toPath = aPrefix + aToType + aToArguments;
+
+  var path = newSVGElement("path", { d: fromPath });
+  var animate =
+    newSVGElement("animate", { attributeName: "d",
+                               from: fromPath,
+			       to: toPath,
+			       dur: "8s",
+			       additive: aAdditive ? "sum" : "replace" });
+  path.appendChild(animate);
+  gSVG.appendChild(path);
+
+  gTests.push({ element: path,
+                prefixLength: aPrefixLength,
+                from: fromPath,
+                to: toPath,
+                toType: aToType,
+                expectedType: aExpectedType,
+                expected: aExpectedArguments,
+                usesAddition: aAdditive });
+}
+
+// Generates an array of path segment arguments for the given type.  aOffset
+// is a number to add on to all non-Boolean segment arguments.
+function generatePathSegmentArguments(aType, aOffset)
+{
+  var args = new Array(argumentNames(aType).length);
+  for (let i = 0; i < args.length; i++) {
+    args[i] = i * 10 + aOffset;
+  }
+  if (aType == "A" || aType == "a") {
+    args[3] = 0;
+    args[4] = 0;
+  }
+  return args;
+}
+
+// Returns whether interpolating between the two given types is valid.
+function isValidInterpolation(aFromType, aToType)
+{
+  return aFromType.toUpperCase() == aToType.toUpperCase();
+}
+
+// Runs the test.
+function run()
+{
+  for each (let additive in [false, true]) {
+    let indexOfExpectedArguments = additive ? 3 : 2;
+
+    // Add subtests for each combination of prefix and suffix, and additive
+    // or not.
+    for (let [typePair, suffixEntry] in Iterator(gSuffixes)) {
+      let fromType = typePair[0],
+          toType = typePair[1],
+          fromArguments = suffixEntry[0],
+          toArguments = suffixEntry[1],
+          expectedArguments = suffixEntry[indexOfExpectedArguments];
+
+      for each (let prefixEntry in gPrefixes) {
+        let [prefixLength, prefix] = prefixEntry;
+        addTest(prefixLength, prefix, fromType, fromArguments,
+	        toType, toArguments, toType, expectedArguments, additive);
+      }
+    }
+
+    // Test that differences in arc flag parameters cause the
+    // interpolation/addition not to occur.
+    addTest(1, "M100,100",
+            "A", [10, 20, 30, 0, 0, 40, 50],
+            "a", [60, 70, 80, 0, 1, 90, 100],
+	    "a", [60, 70, 80, 0, 1, 90, 100], additive);
+    addTest(1, "M100,100",
+            "A", [10, 20, 30, 0, 0, 40, 50],
+            "a", [60, 70, 80, 1, 0, 90, 100],
+	    "a", [60, 70, 80, 1, 0, 90, 100], additive);
+
+    // Test all pairs of segment types that cannot be interpolated between.
+    for each (let fromType in gTypes) {
+      let fromArguments = generatePathSegmentArguments(fromType, 0);
+      for each (let toType in gTypes) {
+        if (!isValidInterpolation(fromType, toType)) {
+          let toArguments = generatePathSegmentArguments(toType, 1000);
+          addTest(1, "M100,100", fromType, fromArguments,
+	          toType, toArguments, toType, toArguments, additive);
+        }
+      }
+    }
+  }
+
+  // Move the document time to half way through the animations.
+  gSVG.setCurrentTime(4);
+
+  // Inspect the results of each subtest.
+  for each (let test in gTests) {
+    let list = test.element.animatedPathSegList;
+    is(list.numberOfItems, test.prefixLength + 1,
+       "Length of animatedPathSegList for interpolation " +
+         (test.usesAddition ? "with addition " : "") +
+	 " from " + test.from + " to " + test.to);
+
+    let seg = list.getItem(list.numberOfItems - 1);
+    let propertyNames = argumentNames(test.expectedType);
+
+    let actual = [];
+    for (let i = 0; i < test.expected.length; i++) {
+      actual.push(+seg[propertyNames[i]]);
+    }
+
+    is(seg.pathSegTypeAsLetter + actual, test.expectedType + test.expected,
+       "Path segment for interpolation " +
+         (test.usesAddition ? "with addition " : "") +
+         " from " + test.from + " to " + test.to);
+  }
+
+  SimpleTest.finish();
+}
+
+window.addEventListener("load", run, false);
+]]></script>
+</body>
+</html>
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -210,18 +210,18 @@ nsXBLDocGlobalObject::~nsXBLDocGlobalObj
 NS_IMPL_CYCLE_COLLECTION_1(nsXBLDocGlobalObject, mScriptContext)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXBLDocGlobalObject, nsIScriptGlobalObject)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXBLDocGlobalObject, nsIScriptGlobalObject)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocGlobalObject)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocGlobalObject)
 
 void
 XBL_ProtoErrorReporter(JSContext *cx,
                        const char *message,
                        JSErrorReport *report)
 {
   // Make an nsIScriptError and populate it with information from
   // this error.
@@ -461,22 +461,20 @@ TraceProtos(nsHashKey *aKey, void *aData
 {
   ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
   proto->Trace(closure->mCallback, closure->mClosure);
   return kHashEnumerateNext;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
-NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsXBLDocumentInfo)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
     tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nsnull);
   }
-NS_IMPL_CYCLE_COLLECTION_ROOT_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalObject)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
   if (tmp->mBindingTable) {
     tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
   }
@@ -491,19 +489,18 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsX
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObjectOwner)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXBLDocumentInfo, nsIScriptGlobalObjectOwner)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXBLDocumentInfo,
-                                           nsIScriptGlobalObjectOwner)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocumentInfo)
 
 nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
   : mDocument(aDocument),
     mScriptAccess(PR_TRUE),
     mIsChrome(PR_FALSE),
     mBindingTable(nsnull),
     mFirstBinding(nsnull)
 {
--- a/content/xml/content/src/Makefile.in
+++ b/content/xml/content/src/Makefile.in
@@ -59,17 +59,17 @@ FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
 		-I$(srcdir)/../../../base/src \
 		$(NULL)
 
 EXPORT_RESOURCE_CONTENT = \
-		$(srcdir)/xhtml11.dtd \
+		$(srcdir)/htmlmathml-f.ent \
 		$(NULL)
 libs::
 	$(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/res/dtd
 
 install::
 	$(SYSINSTALL) $(IFLAGS1) $(EXPORT_RESOURCE_CONTENT) $(DESTDIR)$(mozappdir)/res/dtd
 
 DEFINES += -D_IMPL_NS_LAYOUT
new file mode 100644
--- /dev/null
+++ b/content/xml/content/src/htmlmathml-f.ent
@@ -0,0 +1,2164 @@
+
+<!-- 
+     Copyright 1998 - 2011 W3C.
+
+     Use and distribution of this code are permitted under the terms of
+     either of the following two licences:
+
+     1) W3C Software Notice and License.
+        http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html
+
+
+     2) The license used for the WHATWG HTML specification,
+        which states, in full:
+            You are granted a license to use, reproduce and create derivative
+            works of this document.
+
+
+     Please report any errors to David Carlisle
+     via the public W3C list www-math@w3.org.
+
+ 
+       Public identifier: -//W3C//ENTITIES HTML MathML Set//EN//XML
+       System identifier: http://www.w3.org/2003/entities/2007/htmlmathml-f.ent
+
+     The public identifier should always be used verbatim.
+     The system identifier may be changed to suit local requirements.
+
+     Typical invocation:
+
+       <!ENTITY % htmlmathml-f PUBLIC
+         "-//W3C//ENTITIES HTML MathML Set//EN//XML"
+         "http://www.w3.org/2003/entities/2007/htmlmathml-f.ent"
+       >
+       %htmlmathml-f;
+
+
+
+-->
+
+<!ENTITY AElig            "&#x000C6;" ><!--LATIN CAPITAL LETTER AE -->
+<!ENTITY AMP              "&#38;#38;" ><!--AMPERSAND -->
+<!ENTITY Aacute           "&#x000C1;" ><!--LATIN CAPITAL LETTER A WITH ACUTE -->
+<!ENTITY Abreve           "&#x00102;" ><!--LATIN CAPITAL LETTER A WITH BREVE -->
+<!ENTITY Acirc            "&#x000C2;" ><!--LATIN CAPITAL LETTER A WITH CIRCUMFLEX -->
+<!ENTITY Acy              "&#x00410;" ><!--CYRILLIC CAPITAL LETTER A -->
+<!ENTITY Afr              "&#x1D504;" ><!--MATHEMATICAL FRAKTUR CAPITAL A -->
+<!ENTITY Agrave           "&#x000C0;" ><!--LATIN CAPITAL LETTER A WITH GRAVE -->
+<!ENTITY Alpha            "&#x00391;" ><!--GREEK CAPITAL LETTER ALPHA -->
+<!ENTITY Amacr            "&#x00100;" ><!--LATIN CAPITAL LETTER A WITH MACRON -->
+<!ENTITY And              "&#x02A53;" ><!--DOUBLE LOGICAL AND -->
+<!ENTITY Aogon            "&#x00104;" ><!--LATIN CAPITAL LETTER A WITH OGONEK -->
+<!ENTITY Aopf             "&#x1D538;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL A -->
+<!ENTITY ApplyFunction    "&#x02061;" ><!--FUNCTION APPLICATION -->
+<!ENTITY Aring            "&#x000C5;" ><!--LATIN CAPITAL LETTER A WITH RING ABOVE -->
+<!ENTITY Ascr             "&#x1D49C;" ><!--MATHEMATICAL SCRIPT CAPITAL A -->
+<!ENTITY Assign           "&#x02254;" ><!--COLON EQUALS -->
+<!ENTITY Atilde           "&#x000C3;" ><!--LATIN CAPITAL LETTER A WITH TILDE -->
+<!ENTITY Auml             "&#x000C4;" ><!--LATIN CAPITAL LETTER A WITH DIAERESIS -->
+<!ENTITY Backslash        "&#x02216;" ><!--SET MINUS -->
+<!ENTITY Barv             "&#x02AE7;" ><!--SHORT DOWN TACK WITH OVERBAR -->
+<!ENTITY Barwed           "&#x02306;" ><!--PERSPECTIVE -->
+<!ENTITY Bcy              "&#x00411;" ><!--CYRILLIC CAPITAL LETTER BE -->
+<!ENTITY Because          "&#x02235;" ><!--BECAUSE -->
+<!ENTITY Bernoullis       "&#x0212C;" ><!--SCRIPT CAPITAL B -->
+<!ENTITY Beta             "&#x00392;" ><!--GREEK CAPITAL LETTER BETA -->
+<!ENTITY Bfr              "&#x1D505;" ><!--MATHEMATICAL FRAKTUR CAPITAL B -->
+<!ENTITY Bopf             "&#x1D539;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL B -->
+<!ENTITY Breve            "&#x002D8;" ><!--BREVE -->
+<!ENTITY Bscr             "&#x0212C;" ><!--SCRIPT CAPITAL B -->
+<!ENTITY Bumpeq           "&#x0224E;" ><!--GEOMETRICALLY EQUIVALENT TO -->
+&